1 /*
2  * COPYRIGHT (C) 2006,2007
3  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4  * ALL RIGHTS RESERVED
5  *
6  * Permission is granted to use, copy, create derivative works
7  * and redistribute this software and such derivative works
8  * for any purpose, so long as the name of The University of
9  * Michigan is not used in any advertising or publicity
10  * pertaining to the use of distribution of this software
11  * without specific, written prior authorization.  If the
12  * above copyright notice or any other identification of the
13  * University of Michigan is included in any copy of any
14  * portion of this software, then the disclaimer below must
15  * also be included.
16  *
17  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18  * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19  * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20  * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21  * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23  * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24  * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25  * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26  * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGES.
29  */
30 
31 /*
32  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33  */
34 
35 #include <errno.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <dlfcn.h>
40 #include <unistd.h>
41 #include <dirent.h>
42 
43 
44 /* Solaris Kerberos */
45 #include <libintl.h>
46 #include "k5-int.h"
47 
48 /*
49  * Q: What is this SILLYDECRYPT stuff about?
50  * A: When using the ActivCard Linux pkcs11 library (v2.0.1),
51  *    the decrypt function fails.  By inserting an extra
52  *    function call, which serves nothing but to change the
53  *    stack, we were able to work around the issue.  If the
54  *    ActivCard library is fixed in the future, this
55  *    definition and related code can be removed.
56  */
57 #define SILLYDECRYPT
58 
59 #include "pkinit_crypto_openssl.h"
60 
61 /*
62  * Solaris Kerberos:
63  * Changed to a switch statement so gettext() can be used
64  * for internationization.
65  * Use defined constants rather than raw numbers for error codes.
66  */
67 static char *
68 pkcs11_error_table(short code) {
69 	switch (code) {
70 	    case CKR_OK:
71 		return (gettext("ok"));
72 	    case CKR_CANCEL:
73 		return (gettext("cancel"));
74 	    case CKR_HOST_MEMORY:
75 		return (gettext("host memory"));
76 	    case CKR_SLOT_ID_INVALID:
77 		return (gettext("slot id invalid"));
78 	    case CKR_GENERAL_ERROR:
79 		return (gettext("general error"));
80 	    case CKR_FUNCTION_FAILED:
81 		return (gettext("function failed"));
82 	    case CKR_ARGUMENTS_BAD:
83 		return (gettext("arguments bad"));
84 	    case CKR_NO_EVENT:
85 		return (gettext("no event"));
86 	    case CKR_NEED_TO_CREATE_THREADS:
87 		return (gettext("need to create threads"));
88 	    case CKR_CANT_LOCK:
89 		return (gettext("cant lock"));
90 	    case CKR_ATTRIBUTE_READ_ONLY:
91 		return (gettext("attribute read only"));
92 	    case CKR_ATTRIBUTE_SENSITIVE:
93 		return (gettext("attribute sensitive"));
94 	    case CKR_ATTRIBUTE_TYPE_INVALID:
95 		return (gettext("attribute type invalid"));
96 	    case CKR_ATTRIBUTE_VALUE_INVALID:
97 		return (gettext("attribute value invalid"));
98 	    case CKR_DATA_INVALID:
99 		return (gettext("data invalid"));
100 	    case CKR_DATA_LEN_RANGE:
101 		return (gettext("data len range"));
102 	    case CKR_DEVICE_ERROR:
103 		return (gettext("device error"));
104 	    case CKR_DEVICE_MEMORY:
105 		return (gettext("device memory"));
106 	    case CKR_DEVICE_REMOVED:
107 		return (gettext("device removed"));
108 	    case CKR_ENCRYPTED_DATA_INVALID:
109 		return (gettext("encrypted data invalid"));
110 	    case CKR_ENCRYPTED_DATA_LEN_RANGE:
111 		return (gettext("encrypted data len range"));
112 	    case CKR_FUNCTION_CANCELED:
113 		return (gettext("function canceled"));
114 	    case CKR_FUNCTION_NOT_PARALLEL:
115 		return (gettext("function not parallel"));
116 	    case CKR_FUNCTION_NOT_SUPPORTED:
117 		return (gettext("function not supported"));
118 	    case CKR_KEY_HANDLE_INVALID:
119 		return (gettext("key handle invalid"));
120 	    case CKR_KEY_SIZE_RANGE:
121 		return (gettext("key size range"));
122 	    case CKR_KEY_TYPE_INCONSISTENT:
123 		return (gettext("key type inconsistent"));
124 	    case CKR_KEY_NOT_NEEDED:
125 		return (gettext("key not needed"));
126 	    case CKR_KEY_CHANGED:
127 		return (gettext("key changed"));
128 	    case CKR_KEY_NEEDED:
129 		return (gettext("key needed"));
130 	    case CKR_KEY_INDIGESTIBLE:
131 		return (gettext("key indigestible"));
132 	    case CKR_KEY_FUNCTION_NOT_PERMITTED:
133 		return (gettext("key function not permitted"));
134 	    case CKR_KEY_NOT_WRAPPABLE:
135 		return (gettext("key not wrappable"));
136 	    case CKR_KEY_UNEXTRACTABLE:
137 		return (gettext("key unextractable"));
138 	    case CKR_MECHANISM_INVALID:
139 		return (gettext("mechanism invalid"));
140 	    case CKR_MECHANISM_PARAM_INVALID:
141 		return (gettext("mechanism param invalid"));
142 	    case CKR_OBJECT_HANDLE_INVALID:
143 		return (gettext("object handle invalid"));
144 	    case CKR_OPERATION_ACTIVE:
145 		return (gettext("operation active"));
146 	    case CKR_OPERATION_NOT_INITIALIZED:
147 		return (gettext("operation not initialized"));
148 	    case CKR_PIN_INCORRECT:
149 		return (gettext("pin incorrect"));
150 	    case CKR_PIN_INVALID:
151 		return (gettext("pin invalid"));
152 	    case CKR_PIN_LEN_RANGE:
153 		return (gettext("pin len range"));
154 	    case CKR_PIN_EXPIRED:
155 		return (gettext("pin expired"));
156 	    case CKR_PIN_LOCKED:
157 		return (gettext("pin locked"));
158 	    case CKR_SESSION_CLOSED:
159 		return (gettext("session closed"));
160 	    case CKR_SESSION_COUNT:
161 		return (gettext("session count"));
162 	    case CKR_SESSION_HANDLE_INVALID:
163 		return (gettext("session handle invalid"));
164 	    case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
165 		return (gettext("session parallel not supported"));
166 	    case CKR_SESSION_READ_ONLY:
167 		return (gettext("session read only"));
168 	    case CKR_SESSION_EXISTS:
169 		return (gettext("session exists"));
170 	    case CKR_SESSION_READ_ONLY_EXISTS:
171 		return (gettext("session read only exists"));
172 	    case CKR_SESSION_READ_WRITE_SO_EXISTS:
173 		return (gettext("session read write so exists"));
174 	    case CKR_SIGNATURE_INVALID:
175 		return (gettext("signature invalid"));
176 	    case CKR_SIGNATURE_LEN_RANGE:
177 		return (gettext("signature len range"));
178 	    case CKR_TEMPLATE_INCOMPLETE:
179 		return (gettext("template incomplete"));
180 	    case CKR_TEMPLATE_INCONSISTENT:
181 		return (gettext("template inconsistent"));
182 	    case CKR_TOKEN_NOT_PRESENT:
183 		return (gettext("token not present"));
184 	    case CKR_TOKEN_NOT_RECOGNIZED:
185 		return (gettext("token not recognized"));
186 	    case CKR_TOKEN_WRITE_PROTECTED:
187 		return (gettext("token write protected"));
188 	    case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
189 		return (gettext("unwrapping key handle invalid"));
190 	    case CKR_UNWRAPPING_KEY_SIZE_RANGE:
191 		return (gettext("unwrapping key size range"));
192 	    case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
193 		return (gettext("unwrapping key type inconsistent"));
194 	    case CKR_USER_ALREADY_LOGGED_IN:
195 		return (gettext("user already logged in"));
196 	    case CKR_USER_NOT_LOGGED_IN:
197 		return (gettext("user not logged in"));
198 	    case CKR_USER_PIN_NOT_INITIALIZED:
199 		return (gettext("user pin not initialized"));
200 	    case CKR_USER_TYPE_INVALID:
201 		return (gettext("user type invalid"));
202 	    case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
203 		return (gettext("user another already logged in"));
204 	    case CKR_USER_TOO_MANY_TYPES:
205 		return (gettext("user too many types"));
206 	    case CKR_WRAPPED_KEY_INVALID:
207 		return (gettext("wrapped key invalid"));
208 	    case CKR_WRAPPED_KEY_LEN_RANGE:
209 		return (gettext("wrapped key len range"));
210 	    case CKR_WRAPPING_KEY_HANDLE_INVALID:
211 		return (gettext("wrapping key handle invalid"));
212 	    case CKR_WRAPPING_KEY_SIZE_RANGE:
213 		return (gettext("wrapping key size range"));
214 	    case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
215 		return (gettext("wrapping key type inconsistent"));
216 	    case CKR_RANDOM_SEED_NOT_SUPPORTED:
217 		return (gettext("random seed not supported"));
218 	    case CKR_RANDOM_NO_RNG:
219 		return (gettext("random no rng"));
220 	    case CKR_DOMAIN_PARAMS_INVALID:
221 		return (gettext("domain params invalid"));
222 	    case CKR_BUFFER_TOO_SMALL:
223 		return (gettext("buffer too small"));
224 	    case CKR_SAVED_STATE_INVALID:
225 		return (gettext("saved state invalid"));
226 	    case CKR_INFORMATION_SENSITIVE:
227 		return (gettext("information sensitive"));
228 	    case CKR_STATE_UNSAVEABLE:
229 		return (gettext("state unsaveable"));
230 	    case CKR_CRYPTOKI_NOT_INITIALIZED:
231 		return (gettext("cryptoki not initialized"));
232 	    case CKR_CRYPTOKI_ALREADY_INITIALIZED:
233 		return (gettext("cryptoki already initialized"));
234 	    case CKR_MUTEX_BAD:
235 		return (gettext("mutex bad"));
236 	    case CKR_MUTEX_NOT_LOCKED:
237 		return (gettext("mutex not locked"));
238 	    case CKR_FUNCTION_REJECTED:
239 		return (gettext("function rejected"));
240 	    default:
241 		return (gettext("unknown error"));
242 	}
243 }
244 
245 /* DH parameters */
246 unsigned char pkinit_1024_dhprime[128] = {
247     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
248     0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
249     0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
250     0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
251     0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
252     0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
253     0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
254     0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
255     0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
256     0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
257     0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
258     0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
259     0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
260     0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
261     0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
262     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
263 };
264 
265 unsigned char pkinit_2048_dhprime[2048/8] = {
266     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
267     0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
268     0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
269     0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
270     0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
271     0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
272     0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
273     0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
274     0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
275     0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
276     0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
277     0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
278     0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
279     0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
280     0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
281     0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
282     0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
283     0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
284     0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
285     0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
286     0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
287     0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
288     0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
289     0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
290     0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
291     0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
292     0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
293     0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
294     0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
295     0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
296     0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
297     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
298 };
299 
300 unsigned char pkinit_4096_dhprime[4096/8] = {
301     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
302     0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
303     0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
304     0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
305     0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
306     0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
307     0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
308     0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
309     0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
310     0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
311     0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
312     0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
313     0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
314     0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
315     0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
316     0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
317     0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
318     0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
319     0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
320     0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
321     0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
322     0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
323     0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
324     0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
325     0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
326     0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
327     0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
328     0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
329     0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
330     0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
331     0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
332     0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
333     0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
334     0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
335     0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
336     0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
337     0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
338     0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
339     0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
340     0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
341     0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
342     0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
343     0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
344     0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
345     0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
346     0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
347     0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
348     0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
349     0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
350     0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
351     0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
352     0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
353     0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
354     0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
355     0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
356     0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
357     0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
358     0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
359     0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
360     0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
361     0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
362     0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
363     0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
364     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
365 };
366 
367 /* Solaris Kerberos */
368 static k5_mutex_t oids_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
369 static int pkinit_oids_refs = 0;
370 
371 krb5_error_code
372 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
373 
374     krb5_error_code retval = ENOMEM;
375     pkinit_plg_crypto_context ctx = NULL;
376 
377     /* initialize openssl routines */
378     /* Solaris Kerberos */
379     retval = openssl_init();
380     if (retval != 0)
381 	goto out;
382 
383     ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
384     if (ctx == NULL)
385 	goto out;
386     (void) memset(ctx, 0, sizeof(*ctx));
387 
388     pkiDebug("%s: initializing openssl crypto context at %p\n",
389 	     __FUNCTION__, ctx);
390     retval = pkinit_init_pkinit_oids(ctx);
391     if (retval)
392 	goto out;
393 
394     retval = pkinit_init_dh_params(ctx);
395     if (retval)
396 	goto out;
397 
398     *cryptoctx = ctx;
399 
400 out:
401     if (retval && ctx != NULL)
402 	    pkinit_fini_plg_crypto(ctx);
403 
404     return retval;
405 }
406 
407 void
408 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
409 {
410     pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
411 
412     if (cryptoctx == NULL)
413 	return;
414     pkinit_fini_pkinit_oids(cryptoctx);
415     pkinit_fini_dh_params(cryptoctx);
416     free(cryptoctx);
417 }
418 
419 krb5_error_code
420 pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
421 {
422     krb5_error_code retval = ENOMEM;
423     pkinit_identity_crypto_context ctx = NULL;
424 
425     ctx = (pkinit_identity_crypto_context)malloc(sizeof(*ctx));
426     if (ctx == NULL)
427 	goto out;
428     (void) memset(ctx, 0, sizeof(*ctx));
429 
430     retval = pkinit_init_certs(ctx);
431     if (retval)
432 	goto out;
433 
434     retval = pkinit_init_pkcs11(ctx);
435     if (retval)
436 	goto out;
437 
438     pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
439     *idctx = ctx;
440 
441 out:
442     if (retval) {
443 	if (ctx)
444 	    pkinit_fini_identity_crypto(ctx);
445     }
446 
447     return retval;
448 }
449 
450 void
451 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
452 {
453     if (idctx == NULL)
454 	return;
455 
456     pkiDebug("%s: freeing   ctx at %p\n", __FUNCTION__, idctx);
457     pkinit_fini_certs(idctx);
458     pkinit_fini_pkcs11(idctx);
459     free(idctx);
460 }
461 
462 krb5_error_code
463 pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
464 {
465 
466     pkinit_req_crypto_context ctx = NULL;
467 
468     /* Solaris Kerberos */
469     if (cryptoctx == NULL)
470 	return EINVAL;
471 
472     ctx = (pkinit_req_crypto_context)malloc(sizeof(*ctx));
473     if (ctx == NULL)
474 	return ENOMEM;
475     (void) memset(ctx, 0, sizeof(*ctx));
476 
477     ctx->dh = NULL;
478     ctx->received_cert = NULL;
479 
480     *cryptoctx = ctx;
481 
482     pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
483 
484     return 0;
485 }
486 
487 void
488 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
489 {
490     if (req_cryptoctx == NULL)
491 	return;
492 
493     pkiDebug("%s: freeing   ctx at %p\n", __FUNCTION__, req_cryptoctx);
494     if (req_cryptoctx->dh != NULL)
495       DH_free(req_cryptoctx->dh);
496     if (req_cryptoctx->received_cert != NULL)
497       X509_free(req_cryptoctx->received_cert);
498 
499     free(req_cryptoctx);
500 }
501 
502 static krb5_error_code
503 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
504 {
505     krb5_error_code retval = ENOMEM;
506     int nid = 0;
507 
508     /*
509      * If OpenSSL already knows about the OID, use the
510      * existing definition. Otherwise, create an OID object.
511      */
512     #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \
513 	nid = OBJ_txt2nid(oid); \
514 	if (nid == NID_undef) { \
515 	    nid = OBJ_create(oid, sn, ln); \
516 	    if (nid == NID_undef) { \
517 		pkiDebug("Error creating oid object for '%s'\n", oid); \
518 		goto out; \
519 	    } \
520 	} \
521 	ctx->vn = OBJ_nid2obj(nid);
522 
523     /* Solaris Kerberos */
524     retval = k5_mutex_lock(&oids_mutex);
525     if (retval != 0)
526 	goto out;
527 
528     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san,
529 			 "id-pkinit-san", "KRB5PrincipalName");
530 
531     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.1", id_pkinit_authData,
532 			 "id-pkinit-authdata", "PKINIT signedAuthPack");
533 
534     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.2", id_pkinit_DHKeyData,
535 			 "id-pkinit-DHKeyData", "PKINIT dhSignedData");
536 
537     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.3", id_pkinit_rkeyData,
538 			 "id-pkinit-rkeyData", "PKINIT encKeyPack");
539 
540     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.4", id_pkinit_KPClientAuth,
541 			 "id-pkinit-KPClientAuth", "PKINIT Client EKU");
542 
543     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.5", id_pkinit_KPKdc,
544 			 "id-pkinit-KPKdc", "KDC EKU");
545 
546 #if 0
547     CREATE_OBJ_IF_NEEDED("1.2.840.113549.1.7.1", id_pkinit_authData9,
548 			 "id-pkcs7-data", "PKCS7 data");
549 #else
550     /* See note in pkinit_pkcs7type2oid() */
551     ctx->id_pkinit_authData9 = NULL;
552 #endif
553 
554     CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.2", id_ms_kp_sc_logon,
555 			 "id-ms-kp-sc-logon EKU", "Microsoft SmartCard Login EKU");
556 
557     CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn,
558 			 "id-ms-san-upn", "Microsoft Universal Principal Name");
559 
560     CREATE_OBJ_IF_NEEDED("1.3.6.1.5.5.7.3.1", id_kp_serverAuth,
561 			 "id-kp-serverAuth EKU", "Server Authentication EKU");
562 
563     /* Success */
564     retval = 0;
565 
566     pkinit_oids_refs++;
567     /* Solaris Kerberos */
568     k5_mutex_unlock(&oids_mutex);
569 
570 out:
571     return retval;
572 }
573 
574 static krb5_error_code
575 get_cert(char *filename, X509 **retcert)
576 {
577     X509 *cert = NULL;
578     BIO *tmp = NULL;
579     int code;
580     krb5_error_code retval;
581 
582     if (filename == NULL || retcert == NULL)
583 	return EINVAL;
584 
585     *retcert = NULL;
586 
587     tmp = BIO_new(BIO_s_file());
588     if (tmp == NULL)
589 	return ENOMEM;
590 
591     code = BIO_read_filename(tmp, filename);
592     if (code == 0) {
593 	retval = errno;
594 	goto cleanup;
595     }
596 
597     cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
598     if (cert == NULL) {
599 	retval = EIO;
600 	pkiDebug("failed to read certificate from %s\n", filename);
601 	goto cleanup;
602     }
603     *retcert = cert;
604     retval = 0;
605 cleanup:
606     if (tmp != NULL)
607 	BIO_free(tmp);
608     return retval;
609 }
610 
611 static krb5_error_code
612 get_key(char *filename, EVP_PKEY **retkey)
613 {
614     EVP_PKEY *pkey = NULL;
615     BIO *tmp = NULL;
616     int code;
617     krb5_error_code retval;
618 
619     if (filename == NULL || retkey == NULL)
620 	return EINVAL;
621 
622     tmp = BIO_new(BIO_s_file());
623     if (tmp == NULL)
624 	return ENOMEM;
625 
626     code = BIO_read_filename(tmp, filename);
627     if (code == 0) {
628 	retval = errno;
629 	goto cleanup;
630     }
631     pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL);
632     if (pkey == NULL) {
633 	retval = EIO;
634 	pkiDebug("failed to read private key from %s\n", filename);
635 	goto cleanup;
636     }
637     *retkey = pkey;
638     retval = 0;
639 cleanup:
640     if (tmp != NULL)
641 	BIO_free(tmp);
642     return retval;
643 }
644 
645 static void
646 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
647 {
648     if (ctx == NULL)
649 	return;
650 
651     /* Only call OBJ_cleanup once! */
652     /* Solaris Kerberos: locking */
653     k5_mutex_lock(&oids_mutex);
654     if (--pkinit_oids_refs == 0)
655 	OBJ_cleanup();
656     k5_mutex_unlock(&oids_mutex);
657 }
658 
659 static krb5_error_code
660 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
661 {
662     krb5_error_code retval = ENOMEM;
663 
664     plgctx->dh_1024 = DH_new();
665     if (plgctx->dh_1024 == NULL)
666 	goto cleanup;
667     plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime,
668 	sizeof(pkinit_1024_dhprime), NULL);
669     if ((plgctx->dh_1024->g = BN_new()) == NULL ||
670 	(plgctx->dh_1024->q = BN_new()) == NULL)
671 	goto cleanup;
672     BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2);
673     BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p);
674 
675     plgctx->dh_2048 = DH_new();
676     if (plgctx->dh_2048 == NULL)
677 	goto cleanup;
678     plgctx->dh_2048->p = BN_bin2bn(pkinit_2048_dhprime,
679 	sizeof(pkinit_2048_dhprime), NULL);
680     if ((plgctx->dh_2048->g = BN_new()) == NULL ||
681 	(plgctx->dh_2048->q = BN_new()) == NULL)
682 	goto cleanup;
683     BN_set_word(plgctx->dh_2048->g, DH_GENERATOR_2);
684     BN_rshift1(plgctx->dh_2048->q, plgctx->dh_2048->p);
685 
686     plgctx->dh_4096 = DH_new();
687     if (plgctx->dh_4096 == NULL)
688 	goto cleanup;
689     plgctx->dh_4096->p = BN_bin2bn(pkinit_4096_dhprime,
690 	sizeof(pkinit_4096_dhprime), NULL);
691     if ((plgctx->dh_4096->g = BN_new()) == NULL ||
692 	(plgctx->dh_4096->q = BN_new()) == NULL)
693 	goto cleanup;
694     BN_set_word(plgctx->dh_4096->g, DH_GENERATOR_2);
695     BN_rshift1(plgctx->dh_4096->q, plgctx->dh_4096->p);
696 
697     retval = 0;
698 
699 cleanup:
700     if (retval)
701 	pkinit_fini_dh_params(plgctx);
702 
703     return retval;
704 }
705 
706 static void
707 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)
708 {
709     if (plgctx->dh_1024 != NULL)
710 	DH_free(plgctx->dh_1024);
711     if (plgctx->dh_2048 != NULL)
712 	DH_free(plgctx->dh_2048);
713     if (plgctx->dh_4096 != NULL)
714 	DH_free(plgctx->dh_4096);
715 
716     plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL;
717 }
718 
719 static krb5_error_code
720 pkinit_init_certs(pkinit_identity_crypto_context ctx)
721 {
722     /* Solaris Kerberos */
723     int i;
724 
725     for (i = 0; i < MAX_CREDS_ALLOWED; i++)
726 	ctx->creds[i] = NULL;
727     ctx->my_certs = NULL;
728     ctx->cert_index = 0;
729     ctx->my_key = NULL;
730     ctx->trustedCAs = NULL;
731     ctx->intermediateCAs = NULL;
732     ctx->revoked = NULL;
733 
734     return 0;
735 }
736 
737 static void
738 pkinit_fini_certs(pkinit_identity_crypto_context ctx)
739 {
740     if (ctx == NULL)
741 	return;
742 
743     if (ctx->my_certs != NULL)
744 	sk_X509_pop_free(ctx->my_certs, X509_free);
745 
746     if (ctx->my_key != NULL)
747 	EVP_PKEY_free(ctx->my_key);
748 
749     if (ctx->trustedCAs != NULL)
750 	sk_X509_pop_free(ctx->trustedCAs, X509_free);
751 
752     if (ctx->intermediateCAs != NULL)
753 	sk_X509_pop_free(ctx->intermediateCAs, X509_free);
754 
755     if (ctx->revoked != NULL)
756 	sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free);
757 }
758 
759 static krb5_error_code
760 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
761 {
762     /* Solaris Kerberos */
763 
764 #ifndef WITHOUT_PKCS11
765     ctx->p11_module_name = strdup(PKCS11_MODNAME);
766     if (ctx->p11_module_name == NULL)
767 	return ENOMEM;
768     ctx->p11_module = NULL;
769     ctx->slotid = PK_NOSLOT;
770     ctx->token_label = NULL;
771     ctx->cert_label = NULL;
772     ctx->PIN = NULL;
773     ctx->session = CK_INVALID_HANDLE;
774     ctx->p11 = NULL;
775     ctx->p11flags = 0; /* Solaris Kerberos */
776 #endif
777     ctx->pkcs11_method = 0;
778 
779     return 0;
780 }
781 
782 static void
783 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
784 {
785 #ifndef WITHOUT_PKCS11
786     if (ctx == NULL)
787 	return;
788 
789     if (ctx->p11 != NULL) {
790 	if (ctx->session) {
791 	    ctx->p11->C_CloseSession(ctx->session);
792 	    ctx->session = CK_INVALID_HANDLE;
793 	}
794 	/*
795 	 * Solaris Kerberos:
796 	 * Only call C_Finalize if the process was not already using pkcs11.
797 	 */
798 	if (ctx->finalize_pkcs11 == TRUE)
799 	    ctx->p11->C_Finalize(NULL_PTR);
800 
801 	ctx->p11 = NULL;
802     }
803     if (ctx->p11_module != NULL) {
804 	pkinit_C_UnloadModule(ctx->p11_module);
805 	ctx->p11_module = NULL;
806     }
807     if (ctx->p11_module_name != NULL)
808 	free(ctx->p11_module_name);
809     if (ctx->token_label != NULL)
810 	free(ctx->token_label);
811     if (ctx->cert_id != NULL)
812 	free(ctx->cert_id);
813     if (ctx->cert_label != NULL)
814 	free(ctx->cert_label);
815     if (ctx->PIN != NULL) {
816 	(void) memset(ctx->PIN, 0, strlen(ctx->PIN));
817 	free(ctx->PIN);
818     }
819 #endif
820 }
821 
822 krb5_error_code
823 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
824 			     krb5_prompter_fct prompter,
825 			     void *prompter_data)
826 {
827     id_cryptoctx->prompter = prompter;
828     id_cryptoctx->prompter_data = prompter_data;
829 
830     return 0;
831 }
832 
833 /* ARGSUSED */
834 krb5_error_code
835 cms_signeddata_create(krb5_context context,
836 		      pkinit_plg_crypto_context plg_cryptoctx,
837 		      pkinit_req_crypto_context req_cryptoctx,
838 		      pkinit_identity_crypto_context id_cryptoctx,
839 		      int cms_msg_type,
840 		      int include_certchain,
841 		      unsigned char *data,
842 		      unsigned int data_len,
843 		      unsigned char **signed_data,
844 		      unsigned int *signed_data_len)
845 {
846     /* Solaris Kerberos */
847     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
848     PKCS7  *p7 = NULL, *inner_p7 = NULL;
849     PKCS7_SIGNED *p7s = NULL;
850     PKCS7_SIGNER_INFO *p7si = NULL;
851     unsigned char *p;
852     ASN1_TYPE *pkinit_data = NULL;
853     STACK_OF(X509) * cert_stack = NULL;
854     ASN1_OCTET_STRING *digest_attr = NULL;
855     EVP_MD_CTX ctx, ctx2;
856     const EVP_MD *md_tmp = NULL;
857     unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
858     unsigned char *digestInfo_buf = NULL, *abuf = NULL;
859     unsigned int md_len, md_len2, alen, digestInfo_len;
860     STACK_OF(X509_ATTRIBUTE) * sk;
861     unsigned char *sig = NULL;
862     unsigned int sig_len = 0;
863     X509_ALGOR *alg = NULL;
864     ASN1_OCTET_STRING *digest = NULL;
865     unsigned int alg_len = 0, digest_len = 0;
866     unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
867     X509 *cert = NULL;
868     ASN1_OBJECT *oid = NULL;
869 
870     /* Solaris Kerberos */
871     if (signed_data == NULL)
872 	return EINVAL;
873 
874     if (signed_data_len == NULL)
875 	return EINVAL;
876 
877     /* start creating PKCS7 data */
878     if ((p7 = PKCS7_new()) == NULL)
879 	goto cleanup;
880     p7->type = OBJ_nid2obj(NID_pkcs7_signed);
881 
882     if ((p7s = PKCS7_SIGNED_new()) == NULL)
883 	goto cleanup;
884     p7->d.sign = p7s;
885     if (!ASN1_INTEGER_set(p7s->version, 3))
886 	goto cleanup;
887 
888     /* create a cert chain that has at least the signer's certificate */
889     if ((cert_stack = sk_X509_new_null()) == NULL)
890 	goto cleanup;
891 
892     cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
893     if (!include_certchain) {
894 	pkiDebug("only including signer's certificate\n");
895 	sk_X509_push(cert_stack, X509_dup(cert));
896     } else {
897 	/* create a cert chain */
898 	X509_STORE *certstore = NULL;
899 	X509_STORE_CTX certctx;
900 	STACK_OF(X509) *certstack = NULL;
901 	char buf[DN_BUF_LEN];
902 	int i = 0, size = 0;
903 
904 	if ((certstore = X509_STORE_new()) == NULL)
905 	    goto cleanup;
906 	pkiDebug("building certificate chain\n");
907 	X509_STORE_set_verify_cb_func(certstore, openssl_callback);
908 	X509_STORE_CTX_init(&certctx, certstore, cert,
909 			    id_cryptoctx->intermediateCAs);
910 	X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
911 	/* Solaris Kerberos */
912 	if (X509_verify_cert(&certctx) <= 0) {
913 	    pkiDebug("failed to create a certificate chain: %s\n",
914 	    X509_verify_cert_error_string(X509_STORE_CTX_get_error(&certctx)));
915 	    if (!sk_X509_num(id_cryptoctx->trustedCAs))
916 		pkiDebug("No trusted CAs found. Check your X509_anchors\n");
917 	    goto cleanup;
918 	}
919 	certstack = X509_STORE_CTX_get1_chain(&certctx);
920 	size = sk_X509_num(certstack);
921 	pkiDebug("size of certificate chain = %d\n", size);
922 	for(i = 0; i < size - 1; i++) {
923 	    X509 *x = sk_X509_value(certstack, i);
924 	    X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
925 	    pkiDebug("cert #%d: %s\n", i, buf);
926 	    sk_X509_push(cert_stack, X509_dup(x));
927 	}
928 	X509_STORE_CTX_cleanup(&certctx);
929 	X509_STORE_free(certstore);
930 	sk_X509_pop_free(certstack, X509_free);
931     }
932     p7s->cert = cert_stack;
933 
934     /* fill-in PKCS7_SIGNER_INFO */
935     if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
936 	goto cleanup;
937     if (!ASN1_INTEGER_set(p7si->version, 1))
938 	goto cleanup;
939     if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
940 		       X509_get_issuer_name(cert)))
941 	goto cleanup;
942     /* because ASN1_INTEGER_set is used to set a 'long' we will do
943      * things the ugly way. */
944     M_ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
945     if (!(p7si->issuer_and_serial->serial =
946 	  M_ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
947 	goto cleanup;
948 
949     /* will not fill-out EVP_PKEY because it's on the smartcard */
950 
951     /* Set digest algs */
952     p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
953 
954     if (p7si->digest_alg->parameter != NULL)
955 	ASN1_TYPE_free(p7si->digest_alg->parameter);
956     if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
957 	goto cleanup;
958     p7si->digest_alg->parameter->type = V_ASN1_NULL;
959 
960     /* Set sig algs */
961     if (p7si->digest_enc_alg->parameter != NULL)
962 	ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
963     p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
964     if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
965 	goto cleanup;
966     p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
967 
968     /* pick the correct oid for the eContentInfo */
969     oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
970     if (oid == NULL)
971 	goto cleanup;
972 
973     if (cms_msg_type == CMS_SIGN_DRAFT9) {
974 	/* don't include signed attributes for pa-type 15 request */
975 	abuf = data;
976 	alen = data_len;
977     } else {
978 	/* add signed attributes */
979 	/* compute sha1 digest over the EncapsulatedContentInfo */
980 	EVP_MD_CTX_init(&ctx);
981 	EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
982 	EVP_DigestUpdate(&ctx, data, data_len);
983 	md_tmp = EVP_MD_CTX_md(&ctx);
984 	EVP_DigestFinal_ex(&ctx, md_data, &md_len);
985 
986 	/* create a message digest attr */
987 	digest_attr = ASN1_OCTET_STRING_new();
988 	ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
989 	PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
990 				   V_ASN1_OCTET_STRING, (char *) digest_attr);
991 
992 	/* create a content-type attr */
993 	PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
994 				   V_ASN1_OBJECT, oid);
995 
996 	/* create the signature over signed attributes. get DER encoded value */
997 	/* This is the place where smartcard signature needs to be calculated */
998 	sk = p7si->auth_attr;
999 	alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
1000 			     ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
1001 	if (abuf == NULL)
1002 	    goto cleanup2;
1003     }
1004 
1005 #ifndef WITHOUT_PKCS11
1006     /* Some tokens can only do RSAEncryption without sha1 hash */
1007     /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
1008      * function and the hash value into an ASN.1 value of type DigestInfo
1009      * DigestInfo::=SEQUENCE {
1010      *	digestAlgorithm  AlgorithmIdentifier,
1011      *	digest OCTET STRING }
1012      */
1013     if (id_cryptoctx->pkcs11_method == 1 &&
1014 	    id_cryptoctx->mech == CKM_RSA_PKCS) {
1015 	pkiDebug("mech = CKM_RSA_PKCS\n");
1016 	EVP_MD_CTX_init(&ctx2);
1017 	/* if this is not draft9 request, include digest signed attribute */
1018 	if (cms_msg_type != CMS_SIGN_DRAFT9)
1019 	    EVP_DigestInit_ex(&ctx2, md_tmp, NULL);
1020 	else
1021 	    EVP_DigestInit_ex(&ctx2, EVP_sha1(), NULL);
1022 	EVP_DigestUpdate(&ctx2, abuf, alen);
1023 	EVP_DigestFinal_ex(&ctx2, md_data2, &md_len2);
1024 
1025 	alg = X509_ALGOR_new();
1026 	if (alg == NULL)
1027 	    goto cleanup2;
1028 	alg->algorithm = OBJ_nid2obj(NID_sha1);
1029 	alg->parameter = NULL;
1030 	alg_len = i2d_X509_ALGOR(alg, NULL);
1031 	alg_buf = (unsigned char *)malloc(alg_len);
1032 	if (alg_buf == NULL)
1033 	    goto cleanup2;
1034 
1035 	digest = ASN1_OCTET_STRING_new();
1036 	if (digest == NULL)
1037 	    goto cleanup2;
1038 	ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
1039 	digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
1040 	digest_buf = (unsigned char *)malloc(digest_len);
1041 	if (digest_buf == NULL)
1042 	    goto cleanup2;
1043 
1044 	digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
1045 					  V_ASN1_SEQUENCE);
1046 	y = digestInfo_buf = (unsigned char *)malloc(digestInfo_len);
1047 	if (digestInfo_buf == NULL)
1048 	    goto cleanup2;
1049 	ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
1050 			V_ASN1_UNIVERSAL);
1051 	i2d_X509_ALGOR(alg, &y);
1052 	i2d_ASN1_OCTET_STRING(digest, &y);
1053 #ifdef DEBUG_SIG
1054 	pkiDebug("signing buffer\n");
1055 	print_buffer(digestInfo_buf, digestInfo_len);
1056 	print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
1057 #endif
1058 	retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
1059 				  digestInfo_len, &sig, &sig_len);
1060     } else
1061 #endif
1062     {
1063 	pkiDebug("mech = %s\n",
1064 	    id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
1065 	retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
1066 				  &sig, &sig_len);
1067     }
1068 #ifdef DEBUG_SIG
1069     print_buffer(sig, sig_len);
1070 #endif
1071     if (cms_msg_type != CMS_SIGN_DRAFT9)
1072 	free(abuf);
1073     if (retval)
1074 	goto cleanup2;
1075 
1076     /* Add signature */
1077     if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
1078 			 (int)sig_len)) {
1079 	unsigned long err = ERR_peek_error();
1080 	retval = KRB5KDC_ERR_PREAUTH_FAILED;
1081 	krb5_set_error_message(context, retval, "%s\n",
1082 			       ERR_error_string(err, NULL));
1083 	pkiDebug("failed to add a signed digest attribute\n");
1084 	goto cleanup2;
1085     }
1086     /* adder signer_info to pkcs7 signed */
1087     if (!PKCS7_add_signer(p7, p7si))
1088 	goto cleanup2;
1089 
1090     /* start on adding data to the pkcs7 signed */
1091     if ((inner_p7 = PKCS7_new()) == NULL)
1092 	goto cleanup2;
1093     if ((pkinit_data = ASN1_TYPE_new()) == NULL)
1094 	goto cleanup2;
1095     pkinit_data->type = V_ASN1_OCTET_STRING;
1096     if ((pkinit_data->value.octet_string = ASN1_OCTET_STRING_new()) == NULL)
1097 	goto cleanup2;
1098     if (!ASN1_OCTET_STRING_set(pkinit_data->value.octet_string, data,
1099 			       (int)data_len)) {
1100 	unsigned long err = ERR_peek_error();
1101 	retval = KRB5KDC_ERR_PREAUTH_FAILED;
1102 	krb5_set_error_message(context, retval, "%s\n",
1103 			       ERR_error_string(err, NULL));
1104 	pkiDebug("failed to add pkcs7 data\n");
1105 	goto cleanup2;
1106     }
1107 
1108     if (!PKCS7_set0_type_other(inner_p7, OBJ_obj2nid(oid), pkinit_data))
1109 	goto cleanup2;
1110 
1111     if (p7s->contents != NULL)
1112 	PKCS7_free(p7s->contents);
1113     p7s->contents = inner_p7;
1114 
1115     *signed_data_len = i2d_PKCS7(p7, NULL);
1116     if (!(*signed_data_len)) {
1117 	unsigned long err = ERR_peek_error();
1118 	retval = KRB5KDC_ERR_PREAUTH_FAILED;
1119 	krb5_set_error_message(context, retval, "%s\n",
1120 			       ERR_error_string(err, NULL));
1121 	pkiDebug("failed to der encode pkcs7\n");
1122 	goto cleanup2;
1123     }
1124     if ((p = *signed_data =
1125 	 (unsigned char *) malloc((size_t)*signed_data_len)) == NULL)
1126 	goto cleanup2;
1127 
1128     /* DER encode PKCS7 data */
1129     retval = i2d_PKCS7(p7, &p);
1130     if (!retval) {
1131 	unsigned long err = ERR_peek_error();
1132 	retval = KRB5KDC_ERR_PREAUTH_FAILED;
1133 	krb5_set_error_message(context, retval, "%s\n",
1134 			       ERR_error_string(err, NULL));
1135 	pkiDebug("failed to der encode pkcs7\n");
1136 	goto cleanup2;
1137     }
1138     retval = 0;
1139 
1140 #ifdef DEBUG_ASN1
1141     if (cms_msg_type == CMS_SIGN_CLIENT) {
1142 	print_buffer_bin(*signed_data, *signed_data_len,
1143 			 "/tmp/client_pkcs7_signeddata");
1144     } else {
1145 	if (cms_msg_type == CMS_SIGN_SERVER) {
1146 	    print_buffer_bin(*signed_data, *signed_data_len,
1147 			     "/tmp/kdc_pkcs7_signeddata");
1148 	} else {
1149 	    print_buffer_bin(*signed_data, *signed_data_len,
1150 			     "/tmp/draft9_pkcs7_signeddata");
1151 	}
1152     }
1153 #endif
1154 
1155   cleanup2:
1156     if (cms_msg_type != CMS_SIGN_DRAFT9)
1157 	EVP_MD_CTX_cleanup(&ctx);
1158 #ifndef WITHOUT_PKCS11
1159     if (id_cryptoctx->pkcs11_method == 1 &&
1160 	    id_cryptoctx->mech == CKM_RSA_PKCS) {
1161 	EVP_MD_CTX_cleanup(&ctx2);
1162 	if (digest_buf != NULL)
1163 	    free(digest_buf);
1164 	if (digestInfo_buf != NULL)
1165 	    free(digestInfo_buf);
1166 	if (alg_buf != NULL)
1167 	    free(alg_buf);
1168 	if (digest != NULL)
1169 	    ASN1_OCTET_STRING_free(digest);
1170     }
1171 #endif
1172     if (alg != NULL)
1173 	X509_ALGOR_free(alg);
1174   cleanup:
1175     if (p7 != NULL)
1176 	PKCS7_free(p7);
1177     if (sig != NULL)
1178 	free(sig);
1179 
1180     return retval;
1181 }
1182 
1183 krb5_error_code
1184 cms_signeddata_verify(krb5_context context,
1185 		      pkinit_plg_crypto_context plgctx,
1186 		      pkinit_req_crypto_context reqctx,
1187 		      pkinit_identity_crypto_context idctx,
1188 		      int cms_msg_type,
1189 		      int require_crl_checking,
1190 		      unsigned char *signed_data,
1191 		      unsigned int signed_data_len,
1192 		      unsigned char **data,
1193 		      unsigned int *data_len,
1194 		      unsigned char **authz_data,
1195 		      unsigned int *authz_data_len)
1196 {
1197     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
1198     PKCS7 *p7 = NULL;
1199     BIO *out = NULL;
1200     int flags = PKCS7_NOVERIFY, i = 0;
1201     unsigned int vflags = 0, size = 0;
1202     const unsigned char *p = signed_data;
1203     STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
1204     PKCS7_SIGNER_INFO *si = NULL;
1205     X509 *x = NULL;
1206     X509_STORE *store = NULL;
1207     X509_STORE_CTX cert_ctx;
1208     STACK_OF(X509) *intermediateCAs = NULL;
1209     STACK_OF(X509_CRL) *revoked = NULL;
1210     STACK_OF(X509) *verified_chain = NULL;
1211     ASN1_OBJECT *oid = NULL;
1212     krb5_external_principal_identifier **krb5_verified_chain = NULL;
1213     krb5_data *authz = NULL;
1214     char buf[DN_BUF_LEN];
1215 
1216 #ifdef DEBUG_ASN1
1217     print_buffer_bin(signed_data, signed_data_len,
1218 		     "/tmp/client_received_pkcs7_signeddata");
1219 #endif
1220 
1221     /* Do this early enough to create the shadow OID for pkcs7-data if needed */
1222     oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
1223     if (oid == NULL)
1224 	goto cleanup;
1225 
1226     /* decode received PKCS7 message */
1227     if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) {
1228 	unsigned long err = ERR_peek_error();
1229 	krb5_set_error_message(context, retval, "%s\n",
1230 			       ERR_error_string(err, NULL));
1231 	pkiDebug("%s: failed to decode message: %s\n",
1232 		 __FUNCTION__, ERR_error_string(err, NULL));
1233 	goto cleanup;
1234     }
1235 
1236     /* verify that the received message is PKCS7 SignedData message */
1237     if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
1238 	pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
1239 		 OBJ_obj2nid(p7->type));
1240 	krb5_set_error_message(context, retval, "wrong oid\n");
1241 	goto cleanup;
1242     }
1243 
1244     /* setup to verify X509 certificate used to sign PKCS7 message */
1245     if (!(store = X509_STORE_new()))
1246 	goto cleanup;
1247 
1248     /* check if we are inforcing CRL checking */
1249     vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
1250     if (require_crl_checking)
1251 	X509_STORE_set_verify_cb_func(store, openssl_callback);
1252     else
1253 	X509_STORE_set_verify_cb_func(store, openssl_callback_ignore_crls);
1254     X509_STORE_set_flags(store, vflags);
1255 
1256     /* get the signer's information from the PKCS7 message */
1257     if ((si_sk = PKCS7_get_signer_info(p7)) == NULL)
1258 	goto cleanup;
1259     if ((si = sk_PKCS7_SIGNER_INFO_value(si_sk, 0)) == NULL)
1260 	goto cleanup;
1261     if ((x = PKCS7_cert_from_signer_info(p7, si)) == NULL)
1262 	goto cleanup;
1263 
1264     /* create available CRL information (get local CRLs and include CRLs
1265      * received in the PKCS7 message
1266      */
1267     if (idctx->revoked == NULL)
1268 	revoked = p7->d.sign->crl;
1269     else if (p7->d.sign->crl == NULL)
1270 	revoked = idctx->revoked;
1271     else {
1272 	size = sk_X509_CRL_num(idctx->revoked);
1273 	revoked = sk_X509_CRL_new_null();
1274 	for (i = 0; i < size; i++)
1275 	    sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i));
1276 	size = sk_X509_num(p7->d.sign->crl);
1277 	for (i = 0; i < size; i++)
1278 	    sk_X509_CRL_push(revoked, sk_X509_CRL_value(p7->d.sign->crl, i));
1279     }
1280 
1281     /* create available intermediate CAs chains (get local intermediateCAs and
1282      * include the CA chain received in the PKCS7 message
1283      */
1284     if (idctx->intermediateCAs == NULL)
1285 	intermediateCAs = p7->d.sign->cert;
1286     else if (p7->d.sign->cert == NULL)
1287 	intermediateCAs = idctx->intermediateCAs;
1288     else {
1289 	size = sk_X509_num(idctx->intermediateCAs);
1290 	intermediateCAs = sk_X509_new_null();
1291 	for (i = 0; i < size; i++) {
1292 	    sk_X509_push(intermediateCAs,
1293 		sk_X509_value(idctx->intermediateCAs, i));
1294 	}
1295 	size = sk_X509_num(p7->d.sign->cert);
1296 	for (i = 0; i < size; i++) {
1297 	    sk_X509_push(intermediateCAs, sk_X509_value(p7->d.sign->cert, i));
1298 	}
1299     }
1300 
1301     /* initialize x509 context with the received certificate and
1302      * trusted and intermediate CA chains and CRLs
1303      */
1304     if (!X509_STORE_CTX_init(&cert_ctx, store, x, intermediateCAs))
1305 	goto cleanup;
1306 
1307     X509_STORE_CTX_set0_crls(&cert_ctx, revoked);
1308 
1309     /* add trusted CAs certificates for cert verification */
1310     if (idctx->trustedCAs != NULL)
1311 	X509_STORE_CTX_trusted_stack(&cert_ctx, idctx->trustedCAs);
1312     else {
1313 	pkiDebug("unable to find any trusted CAs\n");
1314 	goto cleanup;
1315     }
1316 #ifdef DEBUG_CERTCHAIN
1317     if (intermediateCAs != NULL) {
1318 	size = sk_X509_num(intermediateCAs);
1319 	pkiDebug("untrusted cert chain of size %d\n", size);
1320 	for (i = 0; i < size; i++) {
1321 	    X509_NAME_oneline(X509_get_subject_name(
1322 		sk_X509_value(intermediateCAs, i)), buf, sizeof(buf));
1323 	    pkiDebug("cert #%d: %s\n", i, buf);
1324 	}
1325     }
1326     if (idctx->trustedCAs != NULL) {
1327 	size = sk_X509_num(idctx->trustedCAs);
1328 	pkiDebug("trusted cert chain of size %d\n", size);
1329 	for (i = 0; i < size; i++) {
1330 	    X509_NAME_oneline(X509_get_subject_name(
1331 		sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf));
1332 	    pkiDebug("cert #%d: %s\n", i, buf);
1333 	}
1334     }
1335     if (revoked != NULL) {
1336 	size = sk_X509_CRL_num(revoked);
1337 	pkiDebug("CRL chain of size %d\n", size);
1338 	for (i = 0; i < size; i++) {
1339 	    X509_CRL *crl = sk_X509_CRL_value(revoked, i);
1340 	    X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf));
1341 	    pkiDebug("crls by CA #%d: %s\n", i , buf);
1342 	}
1343     }
1344 #endif
1345 
1346     i = X509_verify_cert(&cert_ctx);
1347     if (i <= 0) {
1348 	int j = X509_STORE_CTX_get_error(&cert_ctx);
1349 
1350 	reqctx->received_cert = X509_dup(cert_ctx.current_cert);
1351 	switch(j) {
1352 	    case X509_V_ERR_CERT_REVOKED:
1353 		retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
1354 		break;
1355 	    case X509_V_ERR_UNABLE_TO_GET_CRL:
1356 		retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN;
1357 		break;
1358 	    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1359 	    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1360 		retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE;
1361 		break;
1362 	    default:
1363 		retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
1364 	}
1365 	X509_NAME_oneline(X509_get_subject_name(
1366 	    reqctx->received_cert), buf, sizeof(buf));
1367 	pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j,
1368 		 X509_verify_cert_error_string(j));
1369 	krb5_set_error_message(context, retval, "%s\n",
1370 	    X509_verify_cert_error_string(j));
1371 #ifdef DEBUG_CERTCHAIN
1372 	size = sk_X509_num(p7->d.sign->cert);
1373 	pkiDebug("received cert chain of size %d\n", size);
1374 	for (j = 0; j < size; j++) {
1375 	    X509 *tmp_cert = sk_X509_value(p7->d.sign->cert, j);
1376 	    X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf));
1377 	    pkiDebug("cert #%d: %s\n", j, buf);
1378 	}
1379 #endif
1380     } else {
1381 	/* retrieve verified certificate chain */
1382 	if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9)
1383 	    verified_chain = X509_STORE_CTX_get1_chain(&cert_ctx);
1384     }
1385     X509_STORE_CTX_cleanup(&cert_ctx);
1386     if (i <= 0)
1387 	goto cleanup;
1388 
1389     out = BIO_new(BIO_s_mem());
1390     if (cms_msg_type == CMS_SIGN_DRAFT9)
1391 	flags |= PKCS7_NOATTR;
1392     if (PKCS7_verify(p7, NULL, store, NULL, out, flags)) {
1393 	int valid_oid = 0;
1394 
1395 	if (!OBJ_cmp(p7->d.sign->contents->type, oid))
1396 	    valid_oid = 1;
1397 	else if (cms_msg_type == CMS_SIGN_DRAFT9) {
1398 	    /*
1399 	     * Various implementations of the pa-type 15 request use
1400 	     * different OIDS.  We check that the returned object
1401 	     * has any of the acceptable OIDs
1402 	     */
1403 	    ASN1_OBJECT *client_oid = NULL, *server_oid = NULL, *rsa_oid = NULL;
1404 	    client_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_CLIENT);
1405 	    server_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_SERVER);
1406 	    rsa_oid = pkinit_pkcs7type2oid(plgctx, CMS_ENVEL_SERVER);
1407 	    if (!OBJ_cmp(p7->d.sign->contents->type, client_oid) ||
1408 		!OBJ_cmp(p7->d.sign->contents->type, server_oid) ||
1409 		!OBJ_cmp(p7->d.sign->contents->type, rsa_oid))
1410 		valid_oid = 1;
1411 	}
1412 
1413 	if (valid_oid)
1414 	    pkiDebug("PKCS7 Verification successful\n");
1415 	else {
1416 	    pkiDebug("wrong oid in eContentType\n");
1417 	    print_buffer(p7->d.sign->contents->type->data,
1418 		(unsigned int)p7->d.sign->contents->type->length);
1419 	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
1420 	    krb5_set_error_message(context, retval, "wrong oid\n");
1421 	    goto cleanup;
1422 	}
1423     }
1424     else {
1425 	unsigned long err = ERR_peek_error();
1426 	switch(ERR_GET_REASON(err)) {
1427 	    case PKCS7_R_DIGEST_FAILURE:
1428 		retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED;
1429 		break;
1430 	    case PKCS7_R_SIGNATURE_FAILURE:
1431 	    default:
1432 		retval = KRB5KDC_ERR_INVALID_SIG;
1433 	}
1434 	pkiDebug("PKCS7 Verification failure\n");
1435 	krb5_set_error_message(context, retval, "%s\n",
1436 			       ERR_error_string(err, NULL));
1437 	goto cleanup;
1438     }
1439 
1440     /* transfer the data from PKCS7 message into return buffer */
1441     for (size = 0;;) {
1442 	if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
1443 	    goto cleanup;
1444 	i = BIO_read(out, &((*data)[size]), 1024 * 10);
1445 	if (i <= 0)
1446 	    break;
1447 	else
1448 	    size += i;
1449     }
1450     *data_len = size;
1451 
1452     reqctx->received_cert = X509_dup(x);
1453 
1454     /* generate authorization data */
1455     if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) {
1456 
1457 	if (authz_data == NULL || authz_data_len == NULL)
1458 	    goto out;
1459 
1460 	*authz_data = NULL;
1461 	retval = create_identifiers_from_stack(verified_chain,
1462 					       &krb5_verified_chain);
1463 	if (retval) {
1464 	    pkiDebug("create_identifiers_from_stack failed\n");
1465 	    goto cleanup;
1466 	}
1467 
1468 	retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_verified_chain, &authz);
1469 	if (retval) {
1470 	    pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
1471 	    goto cleanup;
1472 	}
1473 #ifdef DEBUG_ASN1
1474 	print_buffer_bin((unsigned char *)authz->data, authz->length,
1475 			 "/tmp/kdc_ad_initial_verified_cas");
1476 #endif
1477 	*authz_data = (unsigned char *)malloc(authz->length);
1478 	if (*authz_data == NULL) {
1479 	    retval = ENOMEM;
1480 	    goto cleanup;
1481 	}
1482 	(void) memcpy(*authz_data, authz->data, authz->length);
1483 	*authz_data_len = authz->length;
1484     }
1485   out:
1486     retval = 0;
1487 
1488   cleanup:
1489     if (out != NULL)
1490 	BIO_free(out);
1491     if (store != NULL)
1492 	X509_STORE_free(store);
1493     if (p7 != NULL) {
1494 	if (idctx->intermediateCAs != NULL && p7->d.sign->cert)
1495 	    sk_X509_free(intermediateCAs);
1496 	if (idctx->revoked != NULL && p7->d.sign->crl)
1497 	    sk_X509_CRL_free(revoked);
1498 	PKCS7_free(p7);
1499     }
1500     if (verified_chain != NULL)
1501 	sk_X509_pop_free(verified_chain, X509_free);
1502     if (krb5_verified_chain != NULL)
1503 	free_krb5_external_principal_identifier(&krb5_verified_chain);
1504     if (authz != NULL)
1505 	krb5_free_data(context, authz);
1506 
1507     return retval;
1508 }
1509 
1510 krb5_error_code
1511 cms_envelopeddata_create(krb5_context context,
1512 			 pkinit_plg_crypto_context plgctx,
1513 			 pkinit_req_crypto_context reqctx,
1514 			 pkinit_identity_crypto_context idctx,
1515 			 krb5_preauthtype pa_type,
1516 			 int include_certchain,
1517 			 unsigned char *key_pack,
1518 			 unsigned int key_pack_len,
1519 			 unsigned char **out,
1520 			 unsigned int *out_len)
1521 {
1522 
1523     /* Solaris Kerberos */
1524     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
1525     PKCS7 *p7 = NULL;
1526     BIO *in = NULL;
1527     unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL;
1528     int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY;
1529     STACK_OF(X509) *encerts = NULL;
1530     const EVP_CIPHER *cipher = NULL;
1531     int cms_msg_type;
1532 
1533     /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */
1534     switch ((int)pa_type) {
1535 	case KRB5_PADATA_PK_AS_REQ_OLD:
1536 	case KRB5_PADATA_PK_AS_REP_OLD:
1537 	    cms_msg_type = CMS_SIGN_DRAFT9;
1538 	    break;
1539 	case KRB5_PADATA_PK_AS_REQ:
1540 	    cms_msg_type = CMS_ENVEL_SERVER;
1541 	    break;
1542 	default:
1543 	    /* Solaris Kerberos */
1544 	    retval = EINVAL;
1545 	    goto cleanup;
1546     }
1547 
1548     retval = cms_signeddata_create(context, plgctx, reqctx, idctx,
1549 	cms_msg_type, include_certchain, key_pack, key_pack_len,
1550 	&signed_data, (unsigned int *)&signed_data_len);
1551     if (retval) {
1552 	pkiDebug("failed to create pkcs7 signed data\n");
1553 	goto cleanup;
1554     }
1555 
1556     /* check we have client's certificate */
1557     if (reqctx->received_cert == NULL) {
1558 	retval = KRB5KDC_ERR_PREAUTH_FAILED;
1559 	goto cleanup;
1560     }
1561     encerts = sk_X509_new_null();
1562     sk_X509_push(encerts, reqctx->received_cert);
1563 
1564     cipher = EVP_des_ede3_cbc();
1565     in = BIO_new(BIO_s_mem());
1566     switch (pa_type) {
1567 	case KRB5_PADATA_PK_AS_REQ:
1568 	    prepare_enc_data(signed_data, signed_data_len, &enc_data,
1569 			     &enc_data_len);
1570 	    retval = BIO_write(in, enc_data, enc_data_len);
1571 	    if (retval != enc_data_len) {
1572 		pkiDebug("BIO_write only wrote %d\n", retval);
1573 		goto cleanup;
1574 	    }
1575 	    break;
1576 	case KRB5_PADATA_PK_AS_REP_OLD:
1577 	case KRB5_PADATA_PK_AS_REQ_OLD:
1578 	    retval = BIO_write(in, signed_data, signed_data_len);
1579 		if (retval != signed_data_len) {
1580 		    pkiDebug("BIO_write only wrote %d\n", retval);
1581 		    /* Solaris Kerberos */
1582 		    retval = KRB5KRB_ERR_GENERIC;
1583 		    goto cleanup;
1584 	    }
1585 	    break;
1586 	default:
1587 	    retval = -1;
1588 	    goto cleanup;
1589     }
1590 
1591     p7 = PKCS7_encrypt(encerts, in, cipher, flags);
1592     if (p7 == NULL) {
1593 	pkiDebug("failed to encrypt PKCS7 object\n");
1594 	retval = -1;
1595 	goto cleanup;
1596     }
1597     switch (pa_type) {
1598 	case KRB5_PADATA_PK_AS_REQ:
1599 	    p7->d.enveloped->enc_data->content_type =
1600 		OBJ_nid2obj(NID_pkcs7_signed);
1601 	    break;
1602 	case KRB5_PADATA_PK_AS_REP_OLD:
1603 	case KRB5_PADATA_PK_AS_REQ_OLD:
1604 	    p7->d.enveloped->enc_data->content_type =
1605 		OBJ_nid2obj(NID_pkcs7_data);
1606 	    break;
1607     }
1608 
1609     *out_len = i2d_PKCS7(p7, NULL);
1610     if (!*out_len || (p = *out = (unsigned char *)malloc(*out_len)) == NULL) {
1611 	retval = ENOMEM;
1612 	goto cleanup;
1613     }
1614     retval = i2d_PKCS7(p7, &p);
1615     if (!retval) {
1616 	pkiDebug("unable to write pkcs7 object\n");
1617 	goto cleanup;
1618     }
1619     retval = 0;
1620 
1621 #ifdef DEBUG_ASN1
1622     print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data");
1623 #endif
1624 
1625 cleanup:
1626     if (p7 != NULL)
1627 	PKCS7_free(p7);
1628     if (in != NULL)
1629 	BIO_free(in);
1630     if (signed_data != NULL)
1631 	free(signed_data);
1632     if (enc_data != NULL)
1633 	free(enc_data);
1634     if (encerts != NULL)
1635 	sk_X509_free(encerts);
1636 
1637     return retval;
1638 }
1639 
1640 krb5_error_code
1641 cms_envelopeddata_verify(krb5_context context,
1642 			 pkinit_plg_crypto_context plg_cryptoctx,
1643 			 pkinit_req_crypto_context req_cryptoctx,
1644 			 pkinit_identity_crypto_context id_cryptoctx,
1645 			 krb5_preauthtype pa_type,
1646 			 int require_crl_checking,
1647 			 unsigned char *enveloped_data,
1648 			 unsigned int enveloped_data_len,
1649 			 unsigned char **data,
1650 			 unsigned int *data_len)
1651 {
1652     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
1653     PKCS7 *p7 = NULL;
1654     BIO *out = NULL;
1655     int i = 0;
1656     unsigned int size = 0;
1657     const unsigned char *p = enveloped_data;
1658     unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0;
1659     unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL;
1660     int msg_type = 0;
1661 
1662 #ifdef DEBUG_ASN1
1663     print_buffer_bin(enveloped_data, enveloped_data_len,
1664 		     "/tmp/client_envelopeddata");
1665 #endif
1666     /* decode received PKCS7 message */
1667     if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) {
1668 	unsigned long err = ERR_peek_error();
1669 	pkiDebug("failed to decode pkcs7\n");
1670 	krb5_set_error_message(context, retval, "%s\n",
1671 			       ERR_error_string(err, NULL));
1672 	goto cleanup;
1673     }
1674 
1675     /* verify that the received message is PKCS7 EnvelopedData message */
1676     if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped) {
1677 	pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
1678 		 OBJ_obj2nid(p7->type));
1679 	krb5_set_error_message(context, retval, "wrong oid\n");
1680 	goto cleanup;
1681     }
1682 
1683     /* decrypt received PKCS7 message */
1684     out = BIO_new(BIO_s_mem());
1685     if (pkcs7_decrypt(context, id_cryptoctx, p7, out)) {
1686 	pkiDebug("PKCS7 decryption successful\n");
1687     } else {
1688 	unsigned long err = ERR_peek_error();
1689 	if (err != 0)
1690 	    krb5_set_error_message(context, retval, "%s\n",
1691 				   ERR_error_string(err, NULL));
1692 	pkiDebug("PKCS7 decryption failed\n");
1693 	goto cleanup;
1694     }
1695 
1696     /* transfer the decoded PKCS7 SignedData message into a separate buffer */
1697     for (;;) {
1698 	if ((tmp_buf = realloc(tmp_buf, size + 1024 * 10)) == NULL)
1699 	    goto cleanup;
1700 	i = BIO_read(out, &(tmp_buf[size]), 1024 * 10);
1701 	if (i <= 0)
1702 	    break;
1703 	else
1704 	    size += i;
1705     }
1706     tmp_buf_len = size;
1707 
1708 #ifdef DEBUG_ASN1
1709     print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack");
1710 #endif
1711     /* verify PKCS7 SignedData message */
1712     switch (pa_type) {
1713 	case KRB5_PADATA_PK_AS_REP:
1714 	    msg_type = CMS_ENVEL_SERVER;
1715 
1716 	    break;
1717 	case KRB5_PADATA_PK_AS_REP_OLD:
1718 	    msg_type = CMS_SIGN_DRAFT9;
1719 	    break;
1720 	default:
1721 	    pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__, pa_type);
1722 	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
1723 	    goto cleanup;
1724     }
1725     /*
1726      * If this is the RFC style, wrap the signed data to make
1727      * decoding easier in the verify routine.
1728      * For draft9-compatible, we don't do anything because it
1729      * is already wrapped.
1730      */
1731 #ifdef LONGHORN_BETA_COMPAT
1732     /*
1733      * The Longhorn server returns the expected RFC-style data, but
1734      * it is missing the sequence tag and length, so it requires
1735      * special processing when wrapping.
1736      * This will hopefully be fixed before the final release and
1737      * this can all be removed.
1738      */
1739     if (msg_type == CMS_ENVEL_SERVER || longhorn == 1) {
1740 	retval = wrap_signeddata(tmp_buf, tmp_buf_len,
1741 				 &tmp_buf2, &tmp_buf2_len, longhorn);
1742 	if (retval) {
1743 	    pkiDebug("failed to encode signeddata\n");
1744 	    goto cleanup;
1745 	}
1746 	vfy_buf = tmp_buf2;
1747 	vfy_buf_len = tmp_buf2_len;
1748 
1749     } else {
1750 	vfy_buf = tmp_buf;
1751 	vfy_buf_len = tmp_buf_len;
1752     }
1753 #else
1754     if (msg_type == CMS_ENVEL_SERVER) {
1755 	retval = wrap_signeddata(tmp_buf, tmp_buf_len,
1756 				 &tmp_buf2, &tmp_buf2_len);
1757 	if (retval) {
1758 	    pkiDebug("failed to encode signeddata\n");
1759 	    goto cleanup;
1760 	}
1761 	vfy_buf = tmp_buf2;
1762 	vfy_buf_len = tmp_buf2_len;
1763 
1764     } else {
1765 	vfy_buf = tmp_buf;
1766 	vfy_buf_len = tmp_buf_len;
1767     }
1768 #endif
1769 
1770 #ifdef DEBUG_ASN1
1771     print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2");
1772 #endif
1773 
1774     retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx,
1775 				   id_cryptoctx, msg_type,
1776 				   require_crl_checking,
1777 				   vfy_buf, vfy_buf_len,
1778 				   data, data_len, NULL, NULL);
1779 
1780     if (!retval)
1781 	pkiDebug("PKCS7 Verification Success\n");
1782     else {
1783 	pkiDebug("PKCS7 Verification Failure\n");
1784 	goto cleanup;
1785     }
1786 
1787     retval = 0;
1788 
1789   cleanup:
1790 
1791     if (p7 != NULL)
1792 	PKCS7_free(p7);
1793     if (out != NULL)
1794 	BIO_free(out);
1795     if (tmp_buf != NULL)
1796 	free(tmp_buf);
1797     if (tmp_buf2 != NULL)
1798 	free(tmp_buf2);
1799 
1800     return retval;
1801 }
1802 
1803 /* ARGSUSED */
1804 static krb5_error_code
1805 crypto_retrieve_X509_sans(krb5_context context,
1806 			  pkinit_plg_crypto_context plgctx,
1807 			  pkinit_req_crypto_context reqctx,
1808 			  X509 *cert,
1809 			  krb5_principal **princs_ret,
1810 			  krb5_principal **upn_ret,
1811 			  unsigned char ***dns_ret)
1812 {
1813     krb5_error_code retval = EINVAL;
1814     char buf[DN_BUF_LEN];
1815     int p = 0, u = 0, d = 0;
1816     krb5_principal *princs = NULL;
1817     krb5_principal *upns = NULL;
1818     unsigned char **dnss = NULL;
1819     int i, num_found = 0;
1820 
1821     if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
1822 	pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
1823 	return retval;
1824     }
1825 
1826     if (cert == NULL) {
1827 	pkiDebug("%s: no certificate!\n", __FUNCTION__);
1828 	return retval;
1829     }
1830 
1831     X509_NAME_oneline(X509_get_subject_name(cert),
1832 		      buf, sizeof(buf));
1833     pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
1834 
1835     if ((i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
1836 	X509_EXTENSION *ext = NULL;
1837 	GENERAL_NAMES *ialt = NULL;
1838 	GENERAL_NAME *gen = NULL;
1839 	int ret = 0;
1840 	unsigned int num_sans = 0;
1841 
1842 	if (!(ext = X509_get_ext(cert, i)) || !(ialt = X509V3_EXT_d2i(ext))) {
1843 	    pkiDebug("%s: found no subject alt name extensions\n",
1844 		     __FUNCTION__);
1845 	    goto cleanup;
1846 	}
1847 	num_sans = sk_GENERAL_NAME_num(ialt);
1848 
1849 	pkiDebug("%s: found %d subject alt name extension(s)\n",
1850 		 __FUNCTION__, num_sans);
1851 
1852 	/* OK, we're likely returning something. Allocate return values */
1853 	if (princs_ret != NULL) {
1854 	    princs = calloc(num_sans + 1, sizeof(krb5_principal));
1855 	    if (princs == NULL) {
1856 		retval = ENOMEM;
1857 		goto cleanup;
1858 	    }
1859 	}
1860 	if (upn_ret != NULL) {
1861 	    upns = calloc(num_sans + 1, sizeof(krb5_principal));
1862 	    if (upns == NULL) {
1863 		retval = ENOMEM;
1864 		goto cleanup;
1865 	    }
1866 	}
1867 	if (dns_ret != NULL) {
1868 	    dnss = calloc(num_sans + 1, sizeof(*dnss));
1869 	    if (dnss == NULL) {
1870 		retval = ENOMEM;
1871 		goto cleanup;
1872 	    }
1873 	}
1874 
1875 	for (i = 0; i < num_sans; i++) {
1876 	    krb5_data name = { 0, 0, NULL };
1877 
1878 	    gen = sk_GENERAL_NAME_value(ialt, i);
1879 	    switch (gen->type) {
1880 	    case GEN_OTHERNAME:
1881 		name.length = gen->d.otherName->value->value.sequence->length;
1882 		name.data = (char *)gen->d.otherName->value->value.sequence->data;
1883 		if (princs != NULL
1884 		    && OBJ_cmp(plgctx->id_pkinit_san,
1885 			       gen->d.otherName->type_id) == 0) {
1886 #ifdef DEBUG_ASN1
1887 		    print_buffer_bin((unsigned char *)name.data, name.length,
1888 				     "/tmp/pkinit_san");
1889 #endif
1890 		    ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
1891 		    if (ret) {
1892 			pkiDebug("%s: failed decoding pkinit san value\n",
1893 				 __FUNCTION__);
1894 		    } else {
1895 			p++;
1896 			num_found++;
1897 		    }
1898 		} else if (upns != NULL
1899 			   && OBJ_cmp(plgctx->id_ms_san_upn,
1900 				      gen->d.otherName->type_id) == 0) {
1901 		    ret = krb5_parse_name(context, name.data, &upns[u]);
1902 		    if (ret) {
1903 			pkiDebug("%s: failed parsing ms-upn san value\n",
1904 				 __FUNCTION__);
1905 		    } else {
1906 			u++;
1907 			num_found++;
1908 		    }
1909 		} else {
1910 		    pkiDebug("%s: unrecognized othername oid in SAN\n",
1911 			     __FUNCTION__);
1912 		    continue;
1913 		}
1914 
1915 		break;
1916 	    case GEN_DNS:
1917 		if (dnss != NULL) {
1918 		    pkiDebug("%s: found dns name = %s\n",
1919 			     __FUNCTION__, gen->d.dNSName->data);
1920 		    dnss[d] = (unsigned char *)
1921 				    strdup((char *)gen->d.dNSName->data);
1922 		    if (dnss[d] == NULL) {
1923 			pkiDebug("%s: failed to duplicate dns name\n",
1924 				 __FUNCTION__);
1925 		    } else {
1926 			d++;
1927 			num_found++;
1928 		    }
1929 		}
1930 		break;
1931 	    default:
1932 		pkiDebug("%s: SAN type = %d expecting %d\n",
1933 			 __FUNCTION__, gen->type, GEN_OTHERNAME);
1934 	    }
1935 	}
1936 	sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
1937     }
1938 
1939     retval = 0;
1940     if (princs)
1941 	*princs_ret = princs;
1942     if (upns)
1943 	*upn_ret = upns;
1944     if (dnss)
1945 	*dns_ret = dnss;
1946 
1947   cleanup:
1948     if (retval) {
1949 	if (princs != NULL) {
1950 	    for (i = 0; princs[i] != NULL; i++)
1951 		krb5_free_principal(context, princs[i]);
1952 	    free(princs);
1953 	}
1954 	if (upns != NULL) {
1955 	    for (i = 0; upns[i] != NULL; i++)
1956 		krb5_free_principal(context, upns[i]);
1957 	    free(upns);
1958 	}
1959 	if (dnss != NULL) {
1960 	    for (i = 0; dnss[i] != NULL; i++)
1961 		free(dnss[i]);
1962 	    free(dnss);
1963 	}
1964     }
1965     return retval;
1966 }
1967 
1968 /* ARGSUSED */
1969 krb5_error_code
1970 crypto_retrieve_cert_sans(krb5_context context,
1971 			  pkinit_plg_crypto_context plgctx,
1972 			  pkinit_req_crypto_context reqctx,
1973 			  pkinit_identity_crypto_context idctx,
1974 			  krb5_principal **princs_ret,
1975 			  krb5_principal **upn_ret,
1976 			  unsigned char ***dns_ret)
1977 {
1978     krb5_error_code retval = EINVAL;
1979 
1980     if (reqctx->received_cert == NULL) {
1981 	pkiDebug("%s: No certificate!\n", __FUNCTION__);
1982 	return retval;
1983     }
1984 
1985     return crypto_retrieve_X509_sans(context, plgctx, reqctx,
1986 				     reqctx->received_cert, princs_ret,
1987 				     upn_ret, dns_ret);
1988 }
1989 
1990 /* ARGSUSED */
1991 krb5_error_code
1992 crypto_check_cert_eku(krb5_context context,
1993 		      pkinit_plg_crypto_context plgctx,
1994 		      pkinit_req_crypto_context reqctx,
1995 		      pkinit_identity_crypto_context idctx,
1996 		      int checking_kdc_cert,
1997 		      int allow_secondary_usage,
1998 		      int *valid_eku)
1999 {
2000     char buf[DN_BUF_LEN];
2001     int found_eku = 0;
2002     krb5_error_code retval = EINVAL;
2003     int i;
2004 
2005     /* Solaris Kerberos */
2006     if (valid_eku == NULL)
2007 	return retval;
2008 
2009     *valid_eku = 0;
2010     if (reqctx->received_cert == NULL)
2011 	goto cleanup;
2012 
2013     X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
2014 		      buf, sizeof(buf));
2015     pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
2016 
2017     if ((i = X509_get_ext_by_NID(reqctx->received_cert,
2018 				 NID_ext_key_usage, -1)) >= 0) {
2019 	EXTENDED_KEY_USAGE *extusage;
2020 
2021 	extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage,
2022 				    NULL, NULL);
2023 	if (extusage) {
2024 	    pkiDebug("%s: found eku info in the cert\n", __FUNCTION__);
2025 	    for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) {
2026 		ASN1_OBJECT *tmp_oid;
2027 
2028 		tmp_oid = sk_ASN1_OBJECT_value(extusage, i);
2029 		pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
2030 			 __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage),
2031 			 allow_secondary_usage);
2032 		if (checking_kdc_cert) {
2033 		    if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0)
2034 			 || (allow_secondary_usage
2035 			 && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0))
2036 			found_eku = 1;
2037 		} else {
2038 		    if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0)
2039 			 || (allow_secondary_usage
2040 			 && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0))
2041 			found_eku = 1;
2042 		}
2043 	    }
2044 	}
2045 	EXTENDED_KEY_USAGE_free(extusage);
2046 
2047 	if (found_eku) {
2048 	    ASN1_BIT_STRING *usage = NULL;
2049 	    pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
2050 
2051 	    /* check that digitalSignature KeyUsage is present */
2052 	    if ((usage = X509_get_ext_d2i(reqctx->received_cert,
2053 					  NID_key_usage, NULL, NULL))) {
2054 
2055 		if (!ku_reject(reqctx->received_cert,
2056 			       X509v3_KU_DIGITAL_SIGNATURE)) {
2057 		    pkiDebug("%s: found digitalSignature KU\n",
2058 			     __FUNCTION__);
2059 		    *valid_eku = 1;
2060 		} else
2061 		    pkiDebug("%s: didn't find digitalSignature KU\n",
2062 			     __FUNCTION__);
2063 	    }
2064 	    ASN1_BIT_STRING_free(usage);
2065 	}
2066     }
2067     retval = 0;
2068 cleanup:
2069     pkiDebug("%s: returning retval %d, valid_eku %d\n",
2070 	     __FUNCTION__, retval, *valid_eku);
2071     return retval;
2072 }
2073 
2074 krb5_error_code
2075 pkinit_octetstring2key(krb5_context context,
2076 		       krb5_enctype etype,
2077 		       unsigned char *key,
2078 		       unsigned int dh_key_len,
2079 		       krb5_keyblock * key_block)
2080 {
2081     krb5_error_code retval;
2082     unsigned char *buf = NULL;
2083     unsigned char md[SHA_DIGEST_LENGTH];
2084     unsigned char counter;
2085     size_t keybytes, keylength, offset;
2086     krb5_data random_data;
2087 
2088 
2089     if ((buf = (unsigned char *) malloc(dh_key_len)) == NULL) {
2090 	retval = ENOMEM;
2091 	goto cleanup;
2092     }
2093     (void) memset(buf, 0, dh_key_len);
2094 
2095     counter = 0;
2096     offset = 0;
2097     do {
2098 	SHA_CTX c;
2099 
2100 	SHA1_Init(&c);
2101 	SHA1_Update(&c, &counter, 1);
2102 	SHA1_Update(&c, key, dh_key_len);
2103 	SHA1_Final(md, &c);
2104 
2105 	if (dh_key_len - offset < sizeof(md))
2106 	    (void) memcpy(buf + offset, md, dh_key_len - offset);
2107 	else
2108 	    (void) memcpy(buf + offset, md, sizeof(md));
2109 
2110 	offset += sizeof(md);
2111 	counter++;
2112     } while (offset < dh_key_len);
2113 
2114     /* Solaris Kerberos */
2115     key_block->magic = KV5M_KEYBLOCK;
2116     key_block->enctype = etype;
2117 
2118     retval = krb5_c_keylengths(context, etype, &keybytes, &keylength);
2119     if (retval)
2120 	goto cleanup;
2121 
2122     key_block->length = keylength;
2123     key_block->contents = calloc(keylength, sizeof(unsigned char *));
2124     if (key_block->contents == NULL) {
2125 	retval = ENOMEM;
2126 	goto cleanup;
2127     }
2128 
2129     random_data.length = keybytes;
2130     random_data.data = (char *)buf;
2131 
2132     retval = krb5_c_random_to_key(context, etype, &random_data, key_block);
2133 
2134   cleanup:
2135     if (buf != NULL)
2136 	free(buf);
2137     if (retval && key_block->contents != NULL && key_block->length != 0) {
2138 	(void) memset(key_block->contents, 0, key_block->length);
2139 	key_block->length = 0;
2140     }
2141 
2142     return retval;
2143 }
2144 
2145 /* ARGSUSED */
2146 krb5_error_code
2147 client_create_dh(krb5_context context,
2148 		 pkinit_plg_crypto_context plg_cryptoctx,
2149 		 pkinit_req_crypto_context cryptoctx,
2150 		 pkinit_identity_crypto_context id_cryptoctx,
2151 		 int dh_size,
2152 		 unsigned char **dh_params,
2153 		 unsigned int *dh_params_len,
2154 		 unsigned char **dh_pubkey,
2155 		 unsigned int *dh_pubkey_len)
2156 {
2157     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2158     unsigned char *buf = NULL;
2159     int dh_err = 0;
2160     ASN1_INTEGER *pub_key = NULL;
2161 
2162     if (cryptoctx->dh == NULL) {
2163 	if ((cryptoctx->dh = DH_new()) == NULL)
2164 	    goto cleanup;
2165 	if ((cryptoctx->dh->g = BN_new()) == NULL ||
2166 	    (cryptoctx->dh->q = BN_new()) == NULL)
2167 	    goto cleanup;
2168 
2169 	switch(dh_size) {
2170 	    case 1024:
2171 		pkiDebug("client uses 1024 DH keys\n");
2172 		cryptoctx->dh->p = get_rfc2409_prime_1024(NULL);
2173 		break;
2174 	    case 2048:
2175 		pkiDebug("client uses 2048 DH keys\n");
2176 		cryptoctx->dh->p = BN_bin2bn(pkinit_2048_dhprime,
2177 		    sizeof(pkinit_2048_dhprime), NULL);
2178 		break;
2179 	    case 4096:
2180 		pkiDebug("client uses 4096 DH keys\n");
2181 		cryptoctx->dh->p = BN_bin2bn(pkinit_4096_dhprime,
2182 		    sizeof(pkinit_4096_dhprime), NULL);
2183 		break;
2184 	    default:
2185 		goto cleanup;
2186 	}
2187 
2188 	BN_set_word((cryptoctx->dh->g), DH_GENERATOR_2);
2189 	BN_rshift1(cryptoctx->dh->q, cryptoctx->dh->p);
2190     }
2191 
2192     DH_generate_key(cryptoctx->dh);
2193 /* Solaris Kerberos */
2194 #ifdef DEBUG
2195     DH_check(cryptoctx->dh, &dh_err);
2196     if (dh_err != 0) {
2197 	pkiDebug("Warning: dh_check failed with %d\n", dh_err);
2198 	if (dh_err & DH_CHECK_P_NOT_PRIME)
2199 	    pkiDebug("p value is not prime\n");
2200 	if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME)
2201 	    pkiDebug("p value is not a safe prime\n");
2202 	if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR)
2203 	    pkiDebug("unable to check the generator value\n");
2204 	if (dh_err & DH_NOT_SUITABLE_GENERATOR)
2205 	    pkiDebug("the g value is not a generator\n");
2206     }
2207 #endif
2208 #ifdef DEBUG_DH
2209     print_dh(cryptoctx->dh, "client's DH params\n");
2210     print_pubkey(cryptoctx->dh->pub_key, "client's pub_key=");
2211 #endif
2212 
2213     DH_check_pub_key(cryptoctx->dh, cryptoctx->dh->pub_key, &dh_err);
2214     if (dh_err != 0) {
2215 	pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
2216 	goto cleanup;
2217     }
2218 
2219     /* pack DHparams */
2220     /* aglo: usually we could just call i2d_DHparams to encode DH params
2221      * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
2222      */
2223     retval = pkinit_encode_dh_params(cryptoctx->dh->p, cryptoctx->dh->g,
2224 	cryptoctx->dh->q, dh_params, dh_params_len);
2225     if (retval)
2226 	goto cleanup;
2227 
2228     /* pack DH public key */
2229     /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2230      * encoding shall be used as the contents (the value) of the
2231      * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2232      * data element
2233      */
2234     if ((pub_key = BN_to_ASN1_INTEGER(cryptoctx->dh->pub_key, NULL)) == NULL)
2235 	goto cleanup;
2236     *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
2237     if ((buf = *dh_pubkey = (unsigned char *)
2238 	    malloc((size_t) *dh_pubkey_len)) == NULL) {
2239 	retval  = ENOMEM;
2240 	goto cleanup;
2241     }
2242     i2d_ASN1_INTEGER(pub_key, &buf);
2243 
2244     if (pub_key != NULL)
2245 	ASN1_INTEGER_free(pub_key);
2246 
2247     retval = 0;
2248     return retval;
2249 
2250   cleanup:
2251     if (cryptoctx->dh != NULL)
2252 	DH_free(cryptoctx->dh);
2253     cryptoctx->dh = NULL;
2254     if (*dh_params != NULL)
2255 	free(*dh_params);
2256     *dh_params = NULL;
2257     if (*dh_pubkey != NULL)
2258 	free(*dh_pubkey);
2259     *dh_pubkey = NULL;
2260     if (pub_key != NULL)
2261 	ASN1_INTEGER_free(pub_key);
2262 
2263     return retval;
2264 }
2265 
2266 /* ARGSUSED */
2267 krb5_error_code
2268 client_process_dh(krb5_context context,
2269 		  pkinit_plg_crypto_context plg_cryptoctx,
2270 		  pkinit_req_crypto_context cryptoctx,
2271 		  pkinit_identity_crypto_context id_cryptoctx,
2272 		  unsigned char *subjectPublicKey_data,
2273 		  unsigned int subjectPublicKey_length,
2274 		  unsigned char **client_key,
2275 		  unsigned int *client_key_len)
2276 {
2277     /* Solaris Kerberos */
2278     krb5_error_code retval = KRB5_PREAUTH_FAILED;
2279     BIGNUM *server_pub_key = NULL;
2280     ASN1_INTEGER *pub_key = NULL;
2281     const unsigned char *p = NULL;
2282     unsigned char *data = NULL;
2283     long data_len;
2284 
2285     /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */
2286 
2287     if (der_decode_data(subjectPublicKey_data, (long)subjectPublicKey_length,
2288 			&data, &data_len) != 0) {
2289 	pkiDebug("failed to decode subjectPublicKey\n");
2290 	/* Solaris Kerberos */
2291 	retval = KRB5_PREAUTH_FAILED;
2292 	goto cleanup;
2293     }
2294 
2295     *client_key_len = DH_size(cryptoctx->dh);
2296     if ((*client_key = (unsigned char *)
2297 	    malloc((size_t) *client_key_len)) == NULL) {
2298 	retval = ENOMEM;
2299 	goto cleanup;
2300     }
2301     p = data;
2302     if ((pub_key = d2i_ASN1_INTEGER(NULL, &p, data_len)) == NULL)
2303 	goto cleanup;
2304     if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL)
2305 	goto cleanup;
2306 
2307     DH_compute_key(*client_key, server_pub_key, cryptoctx->dh);
2308 #ifdef DEBUG_DH
2309     print_pubkey(server_pub_key, "server's pub_key=");
2310     pkiDebug("client secret key (%d)= ", *client_key_len);
2311     print_buffer(*client_key, *client_key_len);
2312 #endif
2313 
2314     retval = 0;
2315     if (server_pub_key != NULL)
2316 	BN_free(server_pub_key);
2317     if (pub_key != NULL)
2318 	ASN1_INTEGER_free(pub_key);
2319     if (data != NULL)
2320 	free (data);
2321 
2322     return retval;
2323 
2324   cleanup:
2325     if (*client_key != NULL)
2326 	free(*client_key);
2327     *client_key = NULL;
2328     if (pub_key != NULL)
2329 	ASN1_INTEGER_free(pub_key);
2330     if (data != NULL)
2331 	free (data);
2332 
2333     return retval;
2334 }
2335 
2336 /* ARGSUSED */
2337 krb5_error_code
2338 server_check_dh(krb5_context context,
2339 		pkinit_plg_crypto_context cryptoctx,
2340 		pkinit_req_crypto_context req_cryptoctx,
2341 		pkinit_identity_crypto_context id_cryptoctx,
2342 		krb5_octet_data *dh_params,
2343 		int minbits)
2344 {
2345     DH *dh = NULL;
2346     unsigned char *tmp = NULL;
2347     int dh_prime_bits;
2348     krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
2349 
2350     tmp = dh_params->data;
2351     dh = DH_new();
2352     dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length);
2353     if (dh == NULL) {
2354 	pkiDebug("failed to decode dhparams\n");
2355 	goto cleanup;
2356     }
2357 
2358     /* KDC SHOULD check to see if the key parameters satisfy its policy */
2359     dh_prime_bits = BN_num_bits(dh->p);
2360     if (minbits && dh_prime_bits < minbits) {
2361 	pkiDebug("client sent dh params with %d bits, we require %d\n",
2362 		 dh_prime_bits, minbits);
2363 	goto cleanup;
2364     }
2365 
2366     /* check dhparams is group 2 */
2367     if (pkinit_check_dh_params(cryptoctx->dh_1024->p,
2368 			       dh->p, dh->g, dh->q) == 0) {
2369 	retval = 0;
2370 	goto cleanup;
2371     }
2372 
2373     /* check dhparams is group 14 */
2374     if (pkinit_check_dh_params(cryptoctx->dh_2048->p,
2375 			       dh->p, dh->g, dh->q) == 0) {
2376 	retval = 0;
2377 	goto cleanup;
2378     }
2379 
2380     /* check dhparams is group 16 */
2381     if (pkinit_check_dh_params(cryptoctx->dh_4096->p,
2382 			       dh->p, dh->g, dh->q) == 0) {
2383 	retval = 0;
2384 	goto cleanup;
2385     }
2386 
2387   cleanup:
2388     if (retval == 0)
2389 	req_cryptoctx->dh = dh;
2390     else
2391 	DH_free(dh);
2392 
2393     return retval;
2394 }
2395 
2396 /* kdc's dh function */
2397 /* ARGSUSED */
2398 krb5_error_code
2399 server_process_dh(krb5_context context,
2400 		  pkinit_plg_crypto_context plg_cryptoctx,
2401 		  pkinit_req_crypto_context cryptoctx,
2402 		  pkinit_identity_crypto_context id_cryptoctx,
2403 		  unsigned char *data,
2404 		  unsigned int data_len,
2405 		  unsigned char **dh_pubkey,
2406 		  unsigned int *dh_pubkey_len,
2407 		  unsigned char **server_key,
2408 		  unsigned int *server_key_len)
2409 {
2410     /* Solaris Kerberos */
2411     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2412     DH *dh = NULL, *dh_server = NULL;
2413     unsigned char *p = NULL;
2414     ASN1_INTEGER *pub_key = NULL;
2415 
2416     /* get client's received DH parameters that we saved in server_check_dh */
2417     dh = cryptoctx->dh;
2418 
2419     dh_server = DH_new();
2420     if (dh_server == NULL)
2421 	goto cleanup;
2422     dh_server->p = BN_dup(dh->p);
2423     dh_server->g = BN_dup(dh->g);
2424     dh_server->q = BN_dup(dh->q);
2425 
2426     /* decode client's public key */
2427     p = data;
2428     pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len);
2429     if (pub_key == NULL)
2430 	goto cleanup;
2431     dh->pub_key = ASN1_INTEGER_to_BN(pub_key, NULL);
2432     if (dh->pub_key == NULL)
2433 	goto cleanup;
2434     ASN1_INTEGER_free(pub_key);
2435 
2436     if (!DH_generate_key(dh_server))
2437 	goto cleanup;
2438 
2439     /* generate DH session key */
2440     *server_key_len = DH_size(dh_server);
2441     if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len)) == NULL)
2442 	goto cleanup;
2443     DH_compute_key(*server_key, dh->pub_key, dh_server);
2444 
2445 #ifdef DEBUG_DH
2446     print_dh(dh_server, "client&server's DH params\n");
2447     print_pubkey(dh->pub_key, "client's pub_key=");
2448     print_pubkey(dh_server->pub_key, "server's pub_key=");
2449     pkiDebug("server secret key=");
2450     print_buffer(*server_key, *server_key_len);
2451 #endif
2452 
2453     /* KDC reply */
2454     /* pack DH public key */
2455     /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2456      * encoding shall be used as the contents (the value) of the
2457      * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2458      * data element
2459      */
2460     if ((pub_key = BN_to_ASN1_INTEGER(dh_server->pub_key, NULL)) == NULL)
2461 	goto cleanup;
2462     *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
2463     if ((p = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len)) == NULL)
2464 	goto cleanup;
2465     i2d_ASN1_INTEGER(pub_key, &p);
2466     if (pub_key != NULL)
2467 	ASN1_INTEGER_free(pub_key);
2468 
2469     retval = 0;
2470 
2471     if (dh_server != NULL)
2472 	DH_free(dh_server);
2473     return retval;
2474 
2475   cleanup:
2476     if (dh_server != NULL)
2477 	DH_free(dh_server);
2478     if (*dh_pubkey != NULL)
2479 	free(*dh_pubkey);
2480     if (*server_key != NULL)
2481 	free(*server_key);
2482 
2483     return retval;
2484 }
2485 
2486 /*
2487  * Solaris Kerberos:
2488  * Add locking around did_init to make it MT-safe.
2489  */
2490 static krb5_error_code
2491 openssl_init()
2492 {
2493     krb5_error_code ret = 0;
2494     static int did_init = 0;
2495     static k5_mutex_t init_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
2496 
2497     ret = k5_mutex_lock(&init_mutex);
2498     if (ret == 0) {
2499 	if (!did_init) {
2500 	    /* initialize openssl routines */
2501 	    CRYPTO_malloc_init();
2502 	    ERR_load_crypto_strings();
2503 	    OpenSSL_add_all_algorithms();
2504 	    did_init++;
2505 	}
2506 	k5_mutex_unlock(&init_mutex);
2507     }
2508     return (ret);
2509 }
2510 
2511 static krb5_error_code
2512 pkinit_encode_dh_params(BIGNUM *p, BIGNUM *g, BIGNUM *q,
2513 			unsigned char **buf, unsigned int *buf_len)
2514 {
2515     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2516     int bufsize = 0, r = 0;
2517     unsigned char *tmp = NULL;
2518     ASN1_INTEGER *ap = NULL, *ag = NULL, *aq = NULL;
2519 
2520     if ((ap = BN_to_ASN1_INTEGER(p, NULL)) == NULL)
2521 	goto cleanup;
2522     if ((ag = BN_to_ASN1_INTEGER(g, NULL)) == NULL)
2523 	goto cleanup;
2524     if ((aq = BN_to_ASN1_INTEGER(q, NULL)) == NULL)
2525 	goto cleanup;
2526     bufsize = i2d_ASN1_INTEGER(ap, NULL);
2527     bufsize += i2d_ASN1_INTEGER(ag, NULL);
2528     bufsize += i2d_ASN1_INTEGER(aq, NULL);
2529 
2530     r = ASN1_object_size(1, bufsize, V_ASN1_SEQUENCE);
2531 
2532     tmp = *buf = (unsigned char *)malloc((size_t) r);
2533     if (tmp == NULL)
2534 	goto cleanup;
2535 
2536     ASN1_put_object(&tmp, 1, bufsize, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
2537 
2538     i2d_ASN1_INTEGER(ap, &tmp);
2539     i2d_ASN1_INTEGER(ag, &tmp);
2540     i2d_ASN1_INTEGER(aq, &tmp);
2541 
2542     *buf_len = r;
2543 
2544     retval = 0;
2545 
2546 cleanup:
2547     if (ap != NULL)
2548 	ASN1_INTEGER_free(ap);
2549     if (ag != NULL)
2550 	ASN1_INTEGER_free(ag);
2551     if (aq != NULL)
2552 	ASN1_INTEGER_free(aq);
2553 
2554     return retval;
2555 }
2556 
2557 static DH *
2558 pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len)
2559 {
2560     ASN1_INTEGER ai, *aip = NULL;
2561     long length = (long) len;
2562 
2563     M_ASN1_D2I_vars(a, DH *, DH_new);
2564 
2565     M_ASN1_D2I_Init();
2566     M_ASN1_D2I_start_sequence();
2567     aip = &ai;
2568     ai.data = NULL;
2569     ai.length = 0;
2570     M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
2571     if (aip == NULL)
2572 	return NULL;
2573     else {
2574 	(*a)->p = ASN1_INTEGER_to_BN(aip, NULL);
2575 	if ((*a)->p == NULL)
2576 	    return NULL;
2577 	if (ai.data != NULL) {
2578 	    OPENSSL_free(ai.data);
2579 	    ai.data = NULL;
2580 	    ai.length = 0;
2581 	}
2582     }
2583     M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
2584     if (aip == NULL)
2585 	return NULL;
2586     else {
2587 	(*a)->g = ASN1_INTEGER_to_BN(aip, NULL);
2588 	if ((*a)->g == NULL)
2589 	    return NULL;
2590 	if (ai.data != NULL) {
2591 	    OPENSSL_free(ai.data);
2592 	    ai.data = NULL;
2593 	    ai.length = 0;
2594 	}
2595 
2596     }
2597     M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
2598     if (aip == NULL)
2599 	return NULL;
2600     else {
2601 	(*a)->q = ASN1_INTEGER_to_BN(aip, NULL);
2602 	if ((*a)->q == NULL)
2603 	    return NULL;
2604 	if (ai.data != NULL) {
2605 	    OPENSSL_free(ai.data);
2606 	    ai.data = NULL;
2607 	    ai.length = 0;
2608 	}
2609 
2610     }
2611     M_ASN1_D2I_end_sequence();
2612     M_ASN1_D2I_Finish(a, DH_free, 0);
2613 
2614 }
2615 
2616 static krb5_error_code
2617 pkinit_create_sequence_of_principal_identifiers(
2618     krb5_context context,
2619     pkinit_plg_crypto_context plg_cryptoctx,
2620     pkinit_req_crypto_context req_cryptoctx,
2621     pkinit_identity_crypto_context id_cryptoctx,
2622     int type,
2623     krb5_data **out_data)
2624 {
2625     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2626     krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
2627     krb5_data *td_certifiers = NULL, *data = NULL;
2628     krb5_typed_data **typed_data = NULL;
2629 
2630     switch(type) {
2631 	case TD_TRUSTED_CERTIFIERS:
2632 	    retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
2633 		req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
2634 	    if (retval) {
2635 		pkiDebug("create_krb5_trustedCertifiers failed\n");
2636 		goto cleanup;
2637     	    }
2638 	    break;
2639 	case TD_INVALID_CERTIFICATES:
2640 	    retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
2641 		req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
2642 	    if (retval) {
2643 		pkiDebug("create_krb5_invalidCertificates failed\n");
2644 		goto cleanup;
2645     	    }
2646 	    break;
2647 	default:
2648 	    retval = -1;
2649 	    goto cleanup;
2650     }
2651 
2652     retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_trusted_certifiers, &td_certifiers);
2653     if (retval) {
2654 	pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
2655 	goto cleanup;
2656     }
2657 #ifdef DEBUG_ASN1
2658     print_buffer_bin((unsigned char *)td_certifiers->data,
2659 		     td_certifiers->length, "/tmp/kdc_td_certifiers");
2660 #endif
2661     typed_data = malloc (2 * sizeof(krb5_typed_data *));
2662     if (typed_data == NULL) {
2663 	retval = ENOMEM;
2664 	goto cleanup;
2665     }
2666     typed_data[1] = NULL;
2667     init_krb5_typed_data(&typed_data[0]);
2668     if (typed_data[0] == NULL) {
2669 	retval = ENOMEM;
2670 	goto cleanup;
2671     }
2672     typed_data[0]->type = type;
2673     typed_data[0]->length = td_certifiers->length;
2674     typed_data[0]->data = (unsigned char *)td_certifiers->data;
2675     retval = k5int_encode_krb5_typed_data((const krb5_typed_data **)typed_data,
2676 					  &data);
2677     if (retval) {
2678 	pkiDebug("encode_krb5_typed_data failed\n");
2679 	goto cleanup;
2680     }
2681 #ifdef DEBUG_ASN1
2682     print_buffer_bin((unsigned char *)data->data, data->length,
2683 		     "/tmp/kdc_edata");
2684 #endif
2685     *out_data = (krb5_data *)malloc(sizeof(krb5_data));
2686     (*out_data)->length = data->length;
2687     (*out_data)->data = (char *)malloc(data->length);
2688     (void) memcpy((*out_data)->data, data->data, data->length);
2689 
2690     retval = 0;
2691 
2692 cleanup:
2693     if (krb5_trusted_certifiers != NULL)
2694 	free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
2695 
2696     if (data != NULL) {
2697 	if (data->data != NULL)
2698 	    free(data->data);
2699 	free(data);
2700     }
2701 
2702     if (td_certifiers != NULL)
2703 	free(td_certifiers);
2704 
2705     if (typed_data != NULL)
2706 	free_krb5_typed_data(&typed_data);
2707 
2708     return retval;
2709 }
2710 
2711 krb5_error_code
2712 pkinit_create_td_trusted_certifiers(krb5_context context,
2713 				    pkinit_plg_crypto_context plg_cryptoctx,
2714 				    pkinit_req_crypto_context req_cryptoctx,
2715 				    pkinit_identity_crypto_context id_cryptoctx,
2716 				    krb5_data **out_data)
2717 {
2718     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2719 
2720     retval = pkinit_create_sequence_of_principal_identifiers(context,
2721 	plg_cryptoctx, req_cryptoctx, id_cryptoctx,
2722 	TD_TRUSTED_CERTIFIERS, out_data);
2723 
2724     return retval;
2725 }
2726 
2727 krb5_error_code
2728 pkinit_create_td_invalid_certificate(
2729 	krb5_context context,
2730 	pkinit_plg_crypto_context plg_cryptoctx,
2731 	pkinit_req_crypto_context req_cryptoctx,
2732 	pkinit_identity_crypto_context id_cryptoctx,
2733 	krb5_data **out_data)
2734 {
2735     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2736 
2737     retval = pkinit_create_sequence_of_principal_identifiers(context,
2738 	plg_cryptoctx, req_cryptoctx, id_cryptoctx,
2739 	TD_INVALID_CERTIFICATES, out_data);
2740 
2741     return retval;
2742 }
2743 
2744 /* ARGSUSED */
2745 krb5_error_code
2746 pkinit_create_td_dh_parameters(krb5_context context,
2747 			       pkinit_plg_crypto_context plg_cryptoctx,
2748 			       pkinit_req_crypto_context req_cryptoctx,
2749 			       pkinit_identity_crypto_context id_cryptoctx,
2750 			       pkinit_plg_opts *opts,
2751 			       krb5_data **out_data)
2752 {
2753     /* Solaris Kerberos */
2754     krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2755     unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0;
2756     unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
2757     krb5_typed_data **typed_data = NULL;
2758     krb5_data *data = NULL, *encoded_algId = NULL;
2759     krb5_algorithm_identifier **algId = NULL;
2760 
2761     /* Solaris Kerberos */
2762     if (opts->dh_min_bits > 4096) {
2763 	retval = EINVAL;
2764 	goto cleanup;
2765     }
2766 
2767     if (opts->dh_min_bits <= 1024) {
2768 	retval = pkinit_encode_dh_params(plg_cryptoctx->dh_1024->p,
2769 	    plg_cryptoctx->dh_1024->g, plg_cryptoctx->dh_1024->q,
2770 	    &buf1, &buf1_len);
2771 	if (retval)
2772 	    goto cleanup;
2773     }
2774     if (opts->dh_min_bits <= 2048) {
2775 	retval = pkinit_encode_dh_params(plg_cryptoctx->dh_2048->p,
2776 	    plg_cryptoctx->dh_2048->g, plg_cryptoctx->dh_2048->q,
2777 	    &buf2, &buf2_len);
2778 	if (retval)
2779 	    goto cleanup;
2780     }
2781     retval = pkinit_encode_dh_params(plg_cryptoctx->dh_4096->p,
2782 	plg_cryptoctx->dh_4096->g, plg_cryptoctx->dh_4096->q,
2783 	&buf3, &buf3_len);
2784     if (retval)
2785 	goto cleanup;
2786 
2787     if (opts->dh_min_bits <= 1024) {
2788 	algId = malloc(4 * sizeof(krb5_algorithm_identifier *));
2789 	if (algId == NULL)
2790 	    goto cleanup;
2791 	algId[3] = NULL;
2792 	algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
2793 	if (algId[0] == NULL)
2794 	    goto cleanup;
2795 	algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
2796 	if (algId[0]->parameters.data == NULL)
2797 	    goto cleanup;
2798 	(void) memcpy(algId[0]->parameters.data, buf2, buf2_len);
2799 	algId[0]->parameters.length = buf2_len;
2800 	algId[0]->algorithm = dh_oid;
2801 
2802 	algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
2803 	if (algId[1] == NULL)
2804 	    goto cleanup;
2805 	algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
2806 	if (algId[1]->parameters.data == NULL)
2807 	    goto cleanup;
2808 	(void) memcpy(algId[1]->parameters.data, buf3, buf3_len);
2809 	algId[1]->parameters.length = buf3_len;
2810 	algId[1]->algorithm = dh_oid;
2811 
2812 	algId[2] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
2813 	if (algId[2] == NULL)
2814 	    goto cleanup;
2815 	algId[2]->parameters.data = (unsigned char *)malloc(buf1_len);
2816 	if (algId[2]->parameters.data == NULL)
2817 	    goto cleanup;
2818 	(void) memcpy(algId[2]->parameters.data, buf1, buf1_len);
2819 	algId[2]->parameters.length = buf1_len;
2820 	algId[2]->algorithm = dh_oid;
2821 
2822     } else if (opts->dh_min_bits <= 2048) {
2823 	algId = malloc(3 * sizeof(krb5_algorithm_identifier *));
2824 	if (algId == NULL)
2825 	    goto cleanup;
2826 	algId[2] = NULL;
2827 	algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
2828 	if (algId[0] == NULL)
2829 	    goto cleanup;
2830 	algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
2831 	if (algId[0]->parameters.data == NULL)
2832 	    goto cleanup;
2833 	(void) memcpy(algId[0]->parameters.data, buf2, buf2_len);
2834 	algId[0]->parameters.length = buf2_len;
2835 	algId[0]->algorithm = dh_oid;
2836 
2837 	algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
2838 	if (algId[1] == NULL)
2839 	    goto cleanup;
2840 	algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
2841 	if (algId[1]->parameters.data == NULL)
2842 	    goto cleanup;
2843 	(void) memcpy(algId[1]->parameters.data, buf3, buf3_len);
2844 	algId[1]->parameters.length = buf3_len;
2845 	algId[1]->algorithm = dh_oid;
2846 
2847     } else if (opts->dh_min_bits <= 4096) {
2848 	algId = malloc(2 * sizeof(krb5_algorithm_identifier *));
2849 	if (algId == NULL)
2850 	    goto cleanup;
2851 	algId[1] = NULL;
2852 	algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
2853 	if (algId[0] == NULL)
2854 	    goto cleanup;
2855 	algId[0]->parameters.data = (unsigned char *)malloc(buf3_len);
2856 	if (algId[0]->parameters.data == NULL)
2857 	    goto cleanup;
2858 	(void) memcpy(algId[0]->parameters.data, buf3, buf3_len);
2859 	algId[0]->parameters.length = buf3_len;
2860 	algId[0]->algorithm = dh_oid;
2861 
2862     }
2863     retval = k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier **)algId, &encoded_algId);
2864     if (retval)
2865 	goto cleanup;
2866 #ifdef DEBUG_ASN1
2867     print_buffer_bin((unsigned char *)encoded_algId->data,
2868 		     encoded_algId->length, "/tmp/kdc_td_dh_params");
2869 #endif
2870     typed_data = malloc (2 * sizeof(krb5_typed_data *));
2871     if (typed_data == NULL) {
2872 	retval = ENOMEM;
2873 	goto cleanup;
2874     }
2875     typed_data[1] = NULL;
2876     init_krb5_typed_data(&typed_data[0]);
2877     if (typed_data == NULL) {
2878 	retval = ENOMEM;
2879 	goto cleanup;
2880     }
2881     typed_data[0]->type = TD_DH_PARAMETERS;
2882     typed_data[0]->length = encoded_algId->length;
2883     typed_data[0]->data = (unsigned char *)encoded_algId->data;
2884     retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data,
2885 					  &data);
2886     if (retval) {
2887 	pkiDebug("encode_krb5_typed_data failed\n");
2888 	goto cleanup;
2889     }
2890 #ifdef DEBUG_ASN1
2891     print_buffer_bin((unsigned char *)data->data, data->length,
2892 		     "/tmp/kdc_edata");
2893 #endif
2894     *out_data = (krb5_data *)malloc(sizeof(krb5_data));
2895     if (*out_data == NULL)
2896 	goto cleanup;
2897     (*out_data)->length = data->length;
2898     (*out_data)->data = (char *)malloc(data->length);
2899     if ((*out_data)->data == NULL) {
2900 	free(*out_data);
2901 	*out_data = NULL;
2902 	goto cleanup;
2903     }
2904     (void) memcpy((*out_data)->data, data->data, data->length);
2905 
2906     retval = 0;
2907 cleanup:
2908 
2909     if (buf1 != NULL)
2910 	free(buf1);
2911     if (buf2 != NULL)
2912 	free(buf2);
2913     if (buf3 != NULL)
2914 	free(buf3);
2915     if (data != NULL) {
2916 	if (data->data != NULL)
2917 	    free(data->data);
2918 	free(data);
2919     }
2920     if (typed_data != NULL)
2921 	free_krb5_typed_data(&typed_data);
2922     if (encoded_algId != NULL)
2923 	free(encoded_algId);
2924 
2925     if (algId != NULL) {
2926 	while(algId[i] != NULL) {
2927 	    if (algId[i]->parameters.data != NULL)
2928 		free(algId[i]->parameters.data);
2929 	    free(algId[i]);
2930 	    i++;
2931 	}
2932 	free(algId);
2933     }
2934 
2935     return retval;
2936 }
2937 
2938 /* ARGSUSED */
2939 krb5_error_code
2940 pkinit_check_kdc_pkid(krb5_context context,
2941 		      pkinit_plg_crypto_context plg_cryptoctx,
2942 		      pkinit_req_crypto_context req_cryptoctx,
2943 		      pkinit_identity_crypto_context id_cryptoctx,
2944 		      unsigned char *pdid_buf,
2945 		      unsigned int pkid_len,
2946 		      int *valid_kdcPkId)
2947 {
2948     krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2949     PKCS7_ISSUER_AND_SERIAL *is = NULL;
2950     const unsigned char *p = pdid_buf;
2951     int status = 1;
2952     X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
2953 
2954     *valid_kdcPkId = 0;
2955     pkiDebug("found kdcPkId in AS REQ\n");
2956     is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
2957     if (is == NULL)
2958 	goto cleanup;
2959 
2960     status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
2961     if (!status) {
2962 	status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
2963 	if (!status)
2964 	    *valid_kdcPkId = 1;
2965     }
2966 
2967     retval = 0;
2968 cleanup:
2969     X509_NAME_free(is->issuer);
2970     ASN1_INTEGER_free(is->serial);
2971     free(is);
2972 
2973     return retval;
2974 }
2975 
2976 static int
2977 pkinit_check_dh_params(BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1)
2978 {
2979     BIGNUM *g2 = NULL, *q2 = NULL;
2980     /* Solaris Kerberos */
2981     int retval = EINVAL;
2982 
2983     if (!BN_cmp(p1, p2)) {
2984 	g2 = BN_new();
2985 	BN_set_word(g2, DH_GENERATOR_2);
2986 	if (!BN_cmp(g1, g2)) {
2987 	    q2 = BN_new();
2988 	    BN_rshift1(q2, p1);
2989 	    if (!BN_cmp(q1, q2)) {
2990 		pkiDebug("good %d dhparams\n", BN_num_bits(p1));
2991 		retval = 0;
2992 	    } else
2993 		pkiDebug("bad group 2 q dhparameter\n");
2994 	    BN_free(q2);
2995 	} else
2996 	    pkiDebug("bad g dhparameter\n");
2997 	BN_free(g2);
2998     } else
2999 	pkiDebug("p is not well-known group 2 dhparameter\n");
3000 
3001     return retval;
3002 }
3003 
3004 /* ARGSUSED */
3005 krb5_error_code
3006 pkinit_process_td_dh_params(krb5_context context,
3007 			    pkinit_plg_crypto_context cryptoctx,
3008 			    pkinit_req_crypto_context req_cryptoctx,
3009 			    pkinit_identity_crypto_context id_cryptoctx,
3010 			    krb5_algorithm_identifier **algId,
3011 			    int *new_dh_size)
3012 {
3013     krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3014     int i = 0, use_sent_dh = 0, ok = 0;
3015 
3016     pkiDebug("dh parameters\n");
3017 
3018     while (algId[i] != NULL) {
3019 	DH *dh = NULL;
3020 	unsigned char *tmp = NULL;
3021 	int dh_prime_bits = 0;
3022 
3023 	if (algId[i]->algorithm.length != dh_oid.length ||
3024 	    memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
3025 	    goto cleanup;
3026 
3027 	tmp = algId[i]->parameters.data;
3028 	dh = DH_new();
3029 	dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length);
3030 	dh_prime_bits = BN_num_bits(dh->p);
3031 	pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
3032 		 *new_dh_size, dh_prime_bits);
3033 	switch(dh_prime_bits) {
3034 	    case 1024:
3035 		if (pkinit_check_dh_params(cryptoctx->dh_1024->p, dh->p,
3036 			dh->g, dh->q) == 0) {
3037 		    *new_dh_size = 1024;
3038 		    ok = 1;
3039 		}
3040 		break;
3041 	    case 2048:
3042 		if (pkinit_check_dh_params(cryptoctx->dh_2048->p, dh->p,
3043 			dh->g, dh->q) == 0) {
3044 		    *new_dh_size = 2048;
3045 		    ok = 1;
3046 		}
3047 		break;
3048 	    case 4096:
3049 		if (pkinit_check_dh_params(cryptoctx->dh_4096->p, dh->p,
3050 			dh->g, dh->q) == 0) {
3051 		    *new_dh_size = 4096;
3052 		    ok = 1;
3053 		}
3054 		break;
3055 	    default:
3056 		break;
3057 	}
3058 	if (!ok) {
3059 	    DH_check(dh, &retval);
3060 	    if (retval != 0) {
3061 		pkiDebug("DH parameters provided by server are unacceptable\n");
3062 		retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3063 	    }
3064 	    else {
3065 		use_sent_dh = 1;
3066 		ok = 1;
3067 	    }
3068 	}
3069 	if (!use_sent_dh)
3070 	    DH_free(dh);
3071 	if (ok) {
3072 	    if (req_cryptoctx->dh != NULL) {
3073 		DH_free(