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