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