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