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