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