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 *
pkcs11_error_table(short code)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
__DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)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
__DH_get0_pqg(const DH * dh,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** g)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
__DH_set0_key(DH * dh,BIGNUM * pub_key,BIGNUM * priv_key)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
__DH_get0_key(const DH * dh,const BIGNUM ** pub,const BIGNUM ** priv)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
pkinit_init_plg_crypto(pkinit_plg_crypto_context * cryptoctx)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
pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)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
pkinit_init_identity_crypto(pkinit_identity_crypto_context * idctx)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
pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)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
pkinit_init_req_crypto(pkinit_req_crypto_context * cryptoctx)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
pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)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
pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)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
get_cert(char * filename,X509 ** retcert)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
get_key(char * filename,EVP_PKEY ** retkey)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
pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)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 *
make_dhprime(uint8_t * prime,size_t len)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
pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)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
pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)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
pkinit_init_certs(pkinit_identity_crypto_context ctx)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
pkinit_fini_certs(pkinit_identity_crypto_context ctx)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
pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)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
pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)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
pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,krb5_prompter_fct prompter,void * prompter_data)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
create_contentinfo(krb5_context context,ASN1_OBJECT * oid,unsigned char * data,size_t data_len,PKCS7 ** p7_out)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
cms_signeddata_create(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int cms_msg_type,int include_certchain,unsigned char * data,unsigned int data_len,unsigned char ** signed_data,unsigned int * signed_data_len)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
cms_signeddata_verify(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,int cms_msg_type,int require_crl_checking,unsigned char * signed_data,unsigned int signed_data_len,unsigned char ** data,unsigned int * data_len,unsigned char ** authz_data,unsigned int * authz_data_len)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
cms_envelopeddata_create(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,krb5_preauthtype pa_type,int include_certchain,unsigned char * key_pack,unsigned int key_pack_len,unsigned char ** out,unsigned int * out_len)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
cms_envelopeddata_verify(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_preauthtype pa_type,int require_crl_checking,unsigned char * enveloped_data,unsigned int enveloped_data_len,unsigned char ** data,unsigned int * data_len)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
crypto_retrieve_X509_sans(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,X509 * cert,krb5_principal ** princs_ret,krb5_principal ** upn_ret,unsigned char *** dns_ret)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
crypto_retrieve_cert_sans(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,krb5_principal ** princs_ret,krb5_principal ** upn_ret,unsigned char *** dns_ret)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
crypto_check_cert_eku(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,int checking_kdc_cert,int allow_secondary_usage,int * valid_eku)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
pkinit_octetstring2key(krb5_context context,krb5_enctype etype,unsigned char * key,unsigned int dh_key_len,krb5_keyblock * key_block)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
client_create_dh(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int dh_size,unsigned char ** dh_params,unsigned int * dh_params_len,unsigned char ** dh_pubkey,unsigned int * dh_pubkey_len)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
client_process_dh(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char * subjectPublicKey_data,unsigned int subjectPublicKey_length,unsigned char ** client_key,unsigned int * client_key_len)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
server_check_dh(krb5_context context,pkinit_plg_crypto_context cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_octet_data * dh_params,int minbits)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
server_process_dh(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char * data,unsigned int data_len,unsigned char ** dh_pubkey,unsigned int * dh_pubkey_len,unsigned char ** server_key,unsigned int * server_key_len)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
openssl_init()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
pkinit_encode_dh_params(const BIGNUM * p,const BIGNUM * g,const BIGNUM * q,unsigned char ** buf,unsigned int * buf_len)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 *
pkinit_decode_dh_params(DH ** a,unsigned char ** pp,unsigned int len)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
pkinit_create_sequence_of_principal_identifiers(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int type,krb5_data ** out_data)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
pkinit_create_td_trusted_certifiers(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_data ** out_data)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
pkinit_create_td_invalid_certificate(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_data ** out_data)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
pkinit_create_td_dh_parameters(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,pkinit_plg_opts * opts,krb5_data ** out_data)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, "/tmp/kdc_td_dh_params");
3075 #endif
3076 typed_data = malloc (2 * sizeof(krb5_typed_data *));
3077 if (typed_data == NULL) {
3078 retval = ENOMEM;
3079 goto cleanup;
3080 }
3081 typed_data[1] = NULL;
3082 init_krb5_typed_data(&typed_data[0]);
3083 if (typed_data == NULL) {
3084 retval = ENOMEM;
3085 goto cleanup;
3086 }
3087 typed_data[0]->type = TD_DH_PARAMETERS;
3088 typed_data[0]->length = encoded_algId->length;
3089 typed_data[0]->data = (unsigned char *)encoded_algId->data;
3090 retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data,
3091 &data);
3092 if (retval) {
3093 pkiDebug("encode_krb5_typed_data failed\n");
3094 goto cleanup;
3095 }
3096 #ifdef DEBUG_ASN1
3097 print_buffer_bin((unsigned char *)data->data, data->length,
3098 "/tmp/kdc_edata");
3099 #endif
3100 *out_data = (krb5_data *)malloc(sizeof(krb5_data));
3101 if (*out_data == NULL)
3102 goto cleanup;
3103 (*out_data)->length = data->length;
3104 (*out_data)->data = (char *)malloc(data->length);
3105 if ((*out_data)->data == NULL) {
3106 free(*out_data);
3107 *out_data = NULL;
3108 goto cleanup;
3109 }
3110 (void) memcpy((*out_data)->data, data->data, data->length);
3111
3112 retval = 0;
3113 cleanup:
3114
3115 if (buf1 != NULL)
3116 free(buf1);
3117 if (buf2 != NULL)
3118 free(buf2);
3119 if (buf3 != NULL)
3120 free(buf3);
3121 if (data != NULL) {
3122 if (data->data != NULL)
3123 free(data->data);
3124 free(data);
3125 }
3126 if (typed_data != NULL)
3127 free_krb5_typed_data(&typed_data);
3128 if (encoded_algId != NULL)
3129 free(encoded_algId);
3130
3131 if (algId != NULL) {
3132 while(algId[i] != NULL) {
3133 if (algId[i]->parameters.data != NULL)
3134 free(algId[i]->parameters.data);
3135 free(algId[i]);
3136 i++;
3137 }
3138 free(algId);
3139 }
3140
3141 return retval;
3142 }
3143
3144 /* ARGSUSED */
3145 krb5_error_code
pkinit_check_kdc_pkid(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char * pdid_buf,unsigned int pkid_len,int * valid_kdcPkId)3146 pkinit_check_kdc_pkid(krb5_context context,
3147 pkinit_plg_crypto_context plg_cryptoctx,
3148 pkinit_req_crypto_context req_cryptoctx,
3149 pkinit_identity_crypto_context id_cryptoctx,
3150 unsigned char *pdid_buf,
3151 unsigned int pkid_len,
3152 int *valid_kdcPkId)
3153 {
3154 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
3155 PKCS7_ISSUER_AND_SERIAL *is = NULL;
3156 const unsigned char *p = pdid_buf;
3157 int status = 1;
3158 X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
3159
3160 *valid_kdcPkId = 0;
3161 pkiDebug("found kdcPkId in AS REQ\n");
3162 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
3163 if (is == NULL)
3164 goto cleanup;
3165
3166 status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
3167 if (!status) {
3168 status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
3169 if (!status)
3170 *valid_kdcPkId = 1;
3171 }
3172
3173 retval = 0;
3174 cleanup:
3175 X509_NAME_free(is->issuer);
3176 ASN1_INTEGER_free(is->serial);
3177 free(is);
3178
3179 return retval;
3180 }
3181
3182 static int
pkinit_check_dh_params(const BIGNUM * p1,const BIGNUM * p2,const BIGNUM * g1,const BIGNUM * q1)3183 pkinit_check_dh_params(const BIGNUM *p1, const BIGNUM *p2, const BIGNUM *g1,
3184 const BIGNUM *q1)
3185 {
3186 BIGNUM *g2 = NULL, *q2 = NULL;
3187 /* Solaris Kerberos */
3188 int retval = EINVAL;
3189
3190 if (!BN_cmp(p1, p2)) {
3191 g2 = BN_new();
3192 BN_set_word(g2, DH_GENERATOR_2);
3193 if (!BN_cmp(g1, g2)) {
3194 q2 = BN_new();
3195 BN_rshift1(q2, p1);
3196 if (!BN_cmp(q1, q2)) {
3197 pkiDebug("good %d dhparams\n", BN_num_bits(p1));
3198 retval = 0;
3199 } else
3200 pkiDebug("bad group 2 q dhparameter\n");
3201 BN_free(q2);
3202 } else
3203 pkiDebug("bad g dhparameter\n");
3204 BN_free(g2);
3205 } else
3206 pkiDebug("p is not well-known group 2 dhparameter\n");
3207
3208 return retval;
3209 }
3210
3211 /* ARGSUSED */
3212 krb5_error_code
pkinit_process_td_dh_params(krb5_context context,pkinit_plg_crypto_context cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_algorithm_identifier ** algId,int * new_dh_size)3213 pkinit_process_td_dh_params(krb5_context context,
3214 pkinit_plg_crypto_context cryptoctx,
3215 pkinit_req_crypto_context req_cryptoctx,
3216 pkinit_identity_crypto_context id_cryptoctx,
3217 krb5_algorithm_identifier **algId,
3218 int *new_dh_size)
3219 {
3220 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3221 int i = 0, use_sent_dh = 0, ok = 0;
3222
3223 pkiDebug("dh parameters\n");
3224
3225 while (algId[i] != NULL) {
3226 DH *dh = NULL;
3227 unsigned char *tmp = NULL;
3228 const BIGNUM *p, *g, *q, *p2;
3229 int dh_prime_bits = 0;
3230
3231 if (algId[i]->algorithm.length != dh_oid.length ||
3232 memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
3233 goto cleanup;
3234
3235 tmp = algId[i]->parameters.data;
3236 dh = DH_new();
3237 dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length);
3238 dh_prime_bits = DH_bits(dh);
3239 pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
3240 *new_dh_size, dh_prime_bits);
3241 DH_get0_pqg(dh, &p, &q, &g);
3242 switch(dh_prime_bits) {
3243 case 1024:
3244 DH_get0_pqg(cryptoctx->dh_1024, &p2, NULL, NULL);
3245 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
3246 *new_dh_size = 1024;
3247 ok = 1;
3248 }
3249 break;
3250 case 2048:
3251 DH_get0_pqg(cryptoctx->dh_2048, &p2, NULL, NULL);
3252 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
3253 *new_dh_size = 2048;
3254 ok = 1;
3255 }
3256 break;
3257 case 4096:
3258 DH_get0_pqg(cryptoctx->dh_4096, &p2, NULL, NULL);
3259 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
3260 *new_dh_size = 4096;
3261 ok = 1;
3262 }
3263 break;
3264 default:
3265 break;
3266 }
3267 if (!ok) {
3268 DH_check(dh, &retval);
3269 if (retval != 0) {
3270 pkiDebug("DH parameters provided by server are unacceptable\n");
3271 retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3272 }
3273 else {
3274 use_sent_dh = 1;
3275 ok = 1;
3276 }
3277 }
3278 if (!use_sent_dh)
3279 DH_free(dh);
3280 if (ok) {
3281 if (req_cryptoctx->dh != NULL) {
3282 DH_free(req_cryptoctx->dh);
3283 req_cryptoctx->dh = NULL;
3284 }
3285 if (use_sent_dh)
3286 req_cryptoctx->dh = dh;
3287 break;
3288 }
3289 i++;
3290 }
3291
3292 if (ok)
3293 retval = 0;
3294
3295 cleanup:
3296 return retval;
3297 }
3298
3299 /* ARGSUSED */
3300 static int
openssl_callback(int ok,X509_STORE_CTX * ctx)3301 openssl_callback(int ok, X509_STORE_CTX * ctx)
3302 {
3303 #ifdef DEBUG
3304 if (!ok) {
3305 char buf[DN_BUF_LEN];
3306
3307 X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
3308 pkiDebug("cert = %s\n", buf);
3309 pkiDebug("callback function: %d (%s)\n", ctx->error,
3310 X509_verify_cert_error_string(ctx->error));
3311 }
3312 #endif
3313 return ok;
3314 }
3315
3316 static int
openssl_callback_ignore_crls(int ok,X509_STORE_CTX * ctx)3317 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
3318 {
3319 if (!ok)
3320 return (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL);
3321 return ok;
3322 }
3323
3324 static ASN1_OBJECT *
pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx,int pkcs7_type)3325 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
3326 {
3327 switch (pkcs7_type) {
3328 case CMS_SIGN_CLIENT:
3329 return cryptoctx->id_pkinit_authData;
3330 case CMS_SIGN_DRAFT9:
3331 return OBJ_nid2obj(NID_pkcs7_data);
3332 case CMS_SIGN_SERVER:
3333 return cryptoctx->id_pkinit_DHKeyData;
3334 case CMS_ENVEL_SERVER:
3335 return cryptoctx->id_pkinit_rkeyData;
3336 default:
3337 return NULL;
3338 }
3339
3340 }
3341
3342 #ifdef LONGHORN_BETA_COMPAT
3343 #if 0
3344 /*
3345 * This is a version that worked with Longhorn Beta 3.
3346 */
3347 static int
3348 wrap_signeddata(unsigned char *data, unsigned int data_len,
3349 unsigned char **out, unsigned int *out_len,
3350 int is_longhorn_server)
3351 {
3352
3353 unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
3354 ASN1_OBJECT *oid = NULL;
3355 unsigned char *p = NULL;
3356
3357 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3358 __FUNCTION__, is_longhorn_server);
3359
3360 /* Get length to wrap the original data with SEQUENCE tag */
3361 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
3362
3363 if (is_longhorn_server == 0) {
3364 /* Add the signedData OID and adjust lengths */
3365 oid = OBJ_nid2obj(NID_pkcs7_signed);
3366 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3367
3368 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
3369 }
3370
3371 p = *out = (unsigned char *)malloc(tot_len);
3372 if (p == NULL) return -1;
3373
3374 if (is_longhorn_server == 0) {
3375 ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
3376 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3377
3378 i2d_ASN1_OBJECT(oid, &p);
3379
3380 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3381 } else {
3382 ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3383 }
3384 memcpy(p, data, data_len);
3385
3386 *out_len = tot_len;
3387
3388 return 0;
3389 }
3390 #else
3391 /*
3392 * This is a version that works with a patched Longhorn KDC.
3393 * (Which should match SP1 ??).
3394 */
3395 static int
wrap_signeddata(unsigned char * data,unsigned int data_len,unsigned char ** out,unsigned int * out_len,int is_longhorn_server)3396 wrap_signeddata(unsigned char *data, unsigned int data_len,
3397 unsigned char **out, unsigned int *out_len,
3398 int is_longhorn_server)
3399 {
3400
3401 unsigned int oid_len = 0, tot_len = 0, wrap_len = 0, tag_len = 0;
3402 ASN1_OBJECT *oid = NULL;
3403 unsigned char *p = NULL;
3404
3405 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3406 __FUNCTION__, is_longhorn_server);
3407
3408 /* New longhorn is missing another sequence */
3409 if (is_longhorn_server == 1)
3410 wrap_len = ASN1_object_size(1, (int)(data_len), V_ASN1_SEQUENCE);
3411 else
3412 wrap_len = data_len;
3413
3414 /* Get length to wrap the original data with SEQUENCE tag */
3415 tag_len = ASN1_object_size(1, (int)wrap_len, V_ASN1_SEQUENCE);
3416
3417 /* Always add oid */
3418 oid = OBJ_nid2obj(NID_pkcs7_signed);
3419 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3420 oid_len += tag_len;
3421
3422 tot_len = ASN1_object_size(1, (int)(oid_len), V_ASN1_SEQUENCE);
3423
3424 p = *out = (unsigned char *)malloc(tot_len);
3425 if (p == NULL)
3426 return -1;
3427
3428 ASN1_put_object(&p, 1, (int)(oid_len),
3429 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3430
3431 i2d_ASN1_OBJECT(oid, &p);
3432
3433 ASN1_put_object(&p, 1, (int)wrap_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3434
3435 /* Wrap in extra seq tag */
3436 if (is_longhorn_server == 1) {
3437 ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3438 }
3439 (void) memcpy(p, data, data_len);
3440
3441 *out_len = tot_len;
3442
3443 return 0;
3444 }
3445
3446 #endif
3447 #else
3448 static int
wrap_signeddata(unsigned char * data,unsigned int data_len,unsigned char ** out,unsigned int * out_len)3449 wrap_signeddata(unsigned char *data, unsigned int data_len,
3450 unsigned char **out, unsigned int *out_len)
3451 {
3452
3453 unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
3454 ASN1_OBJECT *oid = NULL;
3455 unsigned char *p = NULL;
3456
3457 /* Get length to wrap the original data with SEQUENCE tag */
3458 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
3459
3460 /* Add the signedData OID and adjust lengths */
3461 oid = OBJ_nid2obj(NID_pkcs7_signed);
3462 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3463
3464 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
3465
3466 p = *out = (unsigned char *)malloc(tot_len);
3467 if (p == NULL) return -1;
3468
3469 ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
3470 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3471
3472 i2d_ASN1_OBJECT(oid, &p);
3473
3474 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3475 (void) memcpy(p, data, data_len);
3476
3477 *out_len = tot_len;
3478
3479 return 0;
3480 }
3481 #endif
3482
3483 static int
prepare_enc_data(unsigned char * indata,int indata_len,unsigned char ** outdata,int * outdata_len)3484 prepare_enc_data(unsigned char *indata,
3485 int indata_len,
3486 unsigned char **outdata,
3487 int *outdata_len)
3488 {
3489 int tag, class;
3490 long tlen, slen;
3491 const uint8_t *p = indata, *oldp;
3492
3493 /* Top-bit set means that the conversion failed. */
3494 if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80)
3495 return EINVAL;
3496 if (tag != V_ASN1_SEQUENCE)
3497 return EINVAL;
3498
3499 oldp = p;
3500 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3501 return EINVAL;
3502 p += tlen;
3503 slen -= (p - oldp);
3504
3505 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3506 return EINVAL;
3507
3508 *outdata = malloc(tlen);
3509 if (*outdata == NULL)
3510 return ENOMEM;
3511 memcpy(*outdata, p, tlen);
3512 *outdata_len = tlen;
3513
3514 return 0;
3515 }
3516
3517 #ifndef WITHOUT_PKCS11
3518 static void *
pkinit_C_LoadModule(const char * modname,CK_FUNCTION_LIST_PTR_PTR p11p)3519 pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p)
3520 {
3521 void *handle;
3522 CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
3523
3524 pkiDebug("loading module \"%s\"... ", modname);
3525 /* Solaris Kerberos */
3526 handle = dlopen(modname, RTLD_NOW | RTLD_GROUP);
3527 if (handle == NULL) {
3528 pkiDebug("not found\n");
3529 return NULL;
3530 }
3531 getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(handle, "C_GetFunctionList");
3532 if (getflist == NULL || (*getflist)(p11p) != CKR_OK) {
3533 (void) dlclose(handle);
3534 pkiDebug("failed\n");
3535 return NULL;
3536 }
3537 pkiDebug("ok\n");
3538 return handle;
3539 }
3540
3541 static CK_RV
pkinit_C_UnloadModule(void * handle)3542 pkinit_C_UnloadModule(void *handle)
3543 {
3544 /* Solaris Kerberos */
3545 if (dlclose(handle) != 0)
3546 return CKR_GENERAL_ERROR;
3547
3548 return CKR_OK;
3549 }
3550
3551 /*
3552 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3553 * code.
3554 *
3555 * labelstr will be C string containing token label with trailing white space
3556 * removed.
3557 */
3558 static void
trim_token_label(CK_TOKEN_INFO * tinfo,char * labelstr,unsigned int labelstr_len)3559 trim_token_label(CK_TOKEN_INFO *tinfo, char *labelstr, unsigned int labelstr_len)
3560 {
3561 int i;
3562
3563 assert(labelstr_len > sizeof (tinfo->label));
3564 /*
3565 * \0 terminate labelstr in case the last char in the token label is
3566 * non-whitespace
3567 */
3568 labelstr[sizeof (tinfo->label)] = '\0';
3569 (void) memcpy(labelstr, (char *) tinfo->label, sizeof (tinfo->label));
3570
3571 /* init i so terminating \0 is skipped */
3572 for (i = sizeof (tinfo->label) - 1; i >= 0; i--) {
3573 if (labelstr[i] == ' ')
3574 labelstr[i] = '\0';
3575 else
3576 break;
3577 }
3578 }
3579
3580 /*
3581 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3582 * code.
3583 */
3584 static krb5_error_code
pkinit_prompt_user(krb5_context context,pkinit_identity_crypto_context cctx,krb5_data * reply,char * prompt,int hidden)3585 pkinit_prompt_user(krb5_context context,
3586 pkinit_identity_crypto_context cctx,
3587 krb5_data *reply,
3588 char *prompt,
3589 int hidden)
3590 {
3591 krb5_error_code r;
3592 krb5_prompt kprompt;
3593 krb5_prompt_type prompt_type;
3594
3595 if (cctx->prompter == NULL)
3596 return (EINVAL);
3597
3598 kprompt.prompt = prompt;
3599 kprompt.hidden = hidden;
3600 kprompt.reply = reply;
3601 /*
3602 * Note, assuming this type for now, may need to be passed in in the future.
3603 */
3604 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
3605
3606 /* PROMPTER_INVOCATION */
3607 k5int_set_prompt_types(context, &prompt_type);
3608 r = (*cctx->prompter)(context, cctx->prompter_data,
3609 NULL, NULL, 1, &kprompt);
3610 k5int_set_prompt_types(context, NULL);
3611 return (r);
3612 }
3613
3614 /*
3615 * Solaris Kerberos: this function was changed to support a PIN being passed
3616 * in. If that is the case the user will not be prompted for their PIN.
3617 */
3618 static krb5_error_code
pkinit_login(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,CK_TOKEN_INFO * tip)3619 pkinit_login(krb5_context context,
3620 pkinit_identity_crypto_context id_cryptoctx,
3621 CK_TOKEN_INFO *tip)
3622 {
3623 krb5_data rdat;
3624 char *prompt;
3625 int prompt_len;
3626 int r = 0;
3627
3628 if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
3629 rdat.data = NULL;
3630 rdat.length = 0;
3631 } else if (id_cryptoctx->PIN != NULL) {
3632 if ((rdat.data = strdup(id_cryptoctx->PIN)) == NULL)
3633 return (ENOMEM);
3634 /*
3635 * Don't include NULL string terminator in length calculation as this
3636 * PIN is passed to the C_Login function and only the text chars should
3637 * be considered to be the PIN.
3638 */
3639 rdat.length = strlen(id_cryptoctx->PIN);
3640 } else {
3641 /* Solaris Kerberos - trim token label */
3642 char tmplabel[sizeof (tip->label) + 1];
3643
3644 if (!id_cryptoctx->prompter) {
3645 pkiDebug("pkinit_login: id_cryptoctx->prompter is NULL\n");
3646 /* Solaris Kerberos: Improved error messages */
3647 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
3648 gettext("Failed to log into token: prompter function is NULL"));
3649 return (KRB5KDC_ERR_PREAUTH_FAILED);
3650 }
3651 /* Solaris Kerberos - Changes for gettext() */
3652 prompt_len = sizeof (tip->label) + 256;
3653 if ((prompt = (char *) malloc(prompt_len)) == NULL)
3654 return ENOMEM;
3655
3656 /* Solaris Kerberos - trim token label which can be padded with space */
3657 trim_token_label(tip, tmplabel, sizeof (tmplabel));
3658 (void) snprintf(prompt, prompt_len, gettext("%s PIN"), tmplabel);
3659
3660 /* Solaris Kerberos */
3661 if (tip->flags & CKF_USER_PIN_LOCKED)
3662 (void) strlcat(prompt, gettext(" (Warning: PIN locked)"), prompt_len);
3663 else if (tip->flags & CKF_USER_PIN_FINAL_TRY)
3664 (void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len);
3665 else if (tip->flags & CKF_USER_PIN_COUNT_LOW)
3666 (void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len);
3667 rdat.data = malloc(tip->ulMaxPinLen + 2);
3668 rdat.length = tip->ulMaxPinLen + 1;
3669 /*
3670 * Note that the prompter function will set rdat.length such that the
3671 * NULL terminator is not included
3672 */
3673 /* PROMPTER_INVOCATION */
3674 r = pkinit_prompt_user(context, id_cryptoctx, &rdat, prompt, 1);
3675 free(prompt);
3676 }
3677
3678 if (r == 0) {
3679 r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
3680 (u_char *) rdat.data, rdat.length);
3681
3682 if (r != CKR_OK) {
3683 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r));
3684 /* Solaris Kerberos: Improved error messages */
3685 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
3686 gettext("Failed to log into token: %s"),
3687 pkinit_pkcs11_code_to_text(r));
3688 r = KRB5KDC_ERR_PREAUTH_FAILED;
3689 } else {
3690 /* Solaris Kerberos: only need to login once */
3691 id_cryptoctx->p11flags |= C_LOGIN_DONE;
3692 }
3693 }
3694 if (rdat.data) {
3695 (void) memset(rdat.data, 0, rdat.length);
3696 free(rdat.data);
3697 }
3698
3699 return (r);
3700 }
3701
3702 /*
3703 * Solaris Kerberos: added these structs in support of prompting user for
3704 * missing token.
3705 */
3706 struct _token_entry {
3707 CK_SLOT_ID slotID;
3708 CK_SESSION_HANDLE session;
3709 CK_TOKEN_INFO token_info;
3710 };
3711 struct _token_choices {
3712 unsigned int numtokens;
3713 struct _token_entry *token_array;
3714 };
3715
3716
3717 /*
3718 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3719 * code.
3720 */
3721 static krb5_error_code
pkinit_prompt_token(krb5_context context,pkinit_identity_crypto_context cctx)3722 pkinit_prompt_token(krb5_context context,
3723 pkinit_identity_crypto_context cctx)
3724 {
3725 char tmpbuf[4];
3726 krb5_data reply;
3727 char *token_prompt = gettext("If you have a smartcard insert it now. "
3728 "Press enter to continue");
3729
3730 reply.data = tmpbuf;
3731 reply.length = sizeof(tmpbuf);
3732
3733 /* note, don't care about the reply */
3734 return (pkinit_prompt_user(context, cctx, &reply, token_prompt, 0));
3735 }
3736
3737 /*
3738 * Solaris Kerberos: new defines for prompting support.
3739 */
3740 #define CHOOSE_THIS_TOKEN 0
3741 #define CHOOSE_RESCAN 1
3742 #define CHOOSE_SKIP 2
3743 #define CHOOSE_SEE_NEXT 3
3744
3745 #define RESCAN_TOKENS -1
3746 #define SKIP_TOKENS -2
3747
3748 /*
3749 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3750 * code.
3751 *
3752 * This prompts to user for various choices regarding a token to use. Note
3753 * that if there is no error, choice will be set to one of:
3754 * - the token_choices->token_array entry
3755 * - RESCAN_TOKENS
3756 * - SKIP_TOKENS
3757 */
3758 static int
pkinit_choose_tokens(krb5_context context,pkinit_identity_crypto_context cctx,struct _token_choices * token_choices,int * choice)3759 pkinit_choose_tokens(krb5_context context,
3760 pkinit_identity_crypto_context cctx,
3761 struct _token_choices *token_choices,
3762 int *choice)
3763 {
3764 krb5_error_code r;
3765 /*
3766 * Assuming that PAM_MAX_MSG_SIZE is a reasonable restriction. Note that -
3767 * 2 is to account for the fact that a krb prompter to PAM conv bridge will
3768 * add ": ".
3769 */
3770 char prompt[PAM_MAX_MSG_SIZE - 2];
3771 char tmpbuf[4];
3772 char tmplabel[sizeof (token_choices->token_array->token_info.label) + 1];
3773 krb5_data reply;
3774 int i, num_used, tmpchoice;
3775
3776 assert(token_choices != NULL);
3777 assert(choice != NULL);
3778
3779 /* Create the menu prompt */
3780
3781 /* only need to do this once before the for loop */
3782 reply.data = tmpbuf;
3783
3784 for (i = 0; i < token_choices->numtokens; i++) {
3785
3786 trim_token_label(&token_choices->token_array[i].token_info, tmplabel,
3787 sizeof (tmplabel));
3788
3789 if (i == (token_choices->numtokens - 1)) {
3790 /* no more smartcards/tokens */
3791 if ((num_used = snprintf(prompt, sizeof (prompt),
3792 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n",
3793 /*
3794 * TRANSLATION_NOTE: Translations of the
3795 * following 5 strings must not exceed 450
3796 * bytes total.
3797 */
3798 gettext("Select one of the following and press enter:"),
3799 CHOOSE_THIS_TOKEN, gettext("Use smartcard"), tmplabel,
3800 gettext("in slot"), token_choices->token_array[i].slotID,
3801 CHOOSE_RESCAN, gettext("Rescan for newly inserted smartcard"),
3802 CHOOSE_SKIP, gettext("Skip smartcard authentication")))
3803 >= sizeof (prompt)) {
3804 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3805 " sizeof prompt: %d\n", num_used, sizeof (prompt));
3806 krb5_set_error_message(context, EINVAL,
3807 gettext("In pkinit_choose_tokens: prompt size"
3808 " %d exceeds prompt buffer size %d"),
3809 num_used, sizeof(prompt));
3810 (void) snprintf(prompt, sizeof (prompt), "%s",
3811 gettext("Error: PKINIT prompt message is too large for buffer, "
3812 "please alert the system administrator. Press enter to "
3813 "continue"));
3814 reply.length = sizeof(tmpbuf);
3815 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 )
3816 return (r);
3817 return (EINVAL);
3818 }
3819 } else {
3820 if ((num_used = snprintf(prompt, sizeof (prompt),
3821 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n%d: %s\n",
3822 /*
3823 * TRANSLATION_NOTE: Translations of the
3824 * following 6 strings must not exceed 445
3825 * bytes total.
3826 */
3827 gettext("Select one of the following and press enter:"),
3828 CHOOSE_THIS_TOKEN, gettext("Use smartcard"), tmplabel,
3829 gettext("in slot"), token_choices->token_array[i].slotID,
3830 CHOOSE_RESCAN, gettext("Rescan for newly inserted smartcard"),
3831 CHOOSE_SKIP, gettext("Skip smartcard authentication"),
3832 CHOOSE_SEE_NEXT, gettext("See next smartcard")))
3833 >= sizeof (prompt)) {
3834
3835 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3836 " sizeof prompt: %d\n", num_used, sizeof (prompt));
3837 krb5_set_error_message(context, EINVAL,
3838 gettext("In pkinit_choose_tokens: prompt size"
3839 " %d exceeds prompt buffer size %d"),
3840 num_used, sizeof(prompt));
3841 (void) snprintf(prompt, sizeof (prompt), "%s",
3842 gettext("Error: PKINIT prompt message is too large for buffer, "
3843 "please alert the system administrator. Press enter to "
3844 "continue"));
3845 reply.length = sizeof(tmpbuf);
3846 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 )
3847 return (r);
3848 return (EINVAL);
3849 }
3850 }
3851
3852 /*
3853 * reply.length needs to be reset to length of tmpbuf before calling
3854 * prompter
3855 */
3856 reply.length = sizeof(tmpbuf);
3857 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 )
3858 return (r);
3859
3860 if (reply.length == 0) {
3861 return (EINVAL);
3862 } else {
3863 char *cp = reply.data;
3864 /* reply better be digits */
3865 while (*cp != '\0') {
3866 if (!isdigit(*cp++))
3867 return (EINVAL);
3868 }
3869 errno = 0;
3870 tmpchoice = (int) strtol(reply.data, (char **)NULL, 10);
3871 if (errno != 0)
3872 return (errno);
3873 }
3874
3875 switch (tmpchoice) {
3876 case CHOOSE_THIS_TOKEN:
3877 *choice = i; /* chosen entry of token_choices->token_array */
3878 return (0);
3879 case CHOOSE_RESCAN:
3880 *choice = RESCAN_TOKENS; /* rescan for new smartcard */
3881 return (0);
3882 case CHOOSE_SKIP:
3883 *choice = SKIP_TOKENS; /* skip smartcard auth */
3884 return (0);
3885 case CHOOSE_SEE_NEXT: /* see next smartcard */
3886 continue;
3887 default:
3888 return (EINVAL);
3889 }
3890 }
3891
3892 return (0);
3893 }
3894
3895 /*
3896 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3897 * code.
3898 *
3899 * Note, this isn't the best solution to providing a function to check the
3900 * certs in a token however I wanted to avoid rewriting a bunch of code so I
3901 * settled for some duplication of processing.
3902 */
3903 static krb5_error_code
check_load_certs(krb5_context context,CK_SESSION_HANDLE session,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ,int do_matching,int load_cert)3904 check_load_certs(krb5_context context,
3905 CK_SESSION_HANDLE session,
3906 pkinit_plg_crypto_context plg_cryptoctx,
3907 pkinit_req_crypto_context req_cryptoctx,
3908 pkinit_identity_crypto_context id_cryptoctx,
3909 krb5_principal princ,
3910 int do_matching,
3911 int load_cert)
3912 {
3913 CK_OBJECT_CLASS cls;
3914 CK_OBJECT_HANDLE obj;
3915 CK_ATTRIBUTE attrs[4];
3916 CK_ULONG count;
3917 CK_CERTIFICATE_TYPE certtype;
3918 CK_BYTE_PTR cert = NULL, cert_id = NULL;
3919 const unsigned char *cp;
3920 int i, r;
3921 unsigned int nattrs;
3922 X509 *x = NULL;
3923
3924 cls = CKO_CERTIFICATE;
3925 attrs[0].type = CKA_CLASS;
3926 attrs[0].pValue = &cls;
3927 attrs[0].ulValueLen = sizeof cls;
3928
3929 certtype = CKC_X_509;
3930 attrs[1].type = CKA_CERTIFICATE_TYPE;
3931 attrs[1].pValue = &certtype;
3932 attrs[1].ulValueLen = sizeof certtype;
3933
3934 nattrs = 2;
3935
3936 /* If a cert id and/or label were given, use them too */
3937 if (id_cryptoctx->cert_id_len > 0) {
3938 attrs[nattrs].type = CKA_ID;
3939 attrs[nattrs].pValue = id_cryptoctx->cert_id;
3940 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
3941 nattrs++;
3942 }
3943 if (id_cryptoctx->cert_label != NULL) {
3944 attrs[nattrs].type = CKA_LABEL;
3945 attrs[nattrs].pValue = id_cryptoctx->cert_label;
3946 attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label);
3947 nattrs++;
3948 }
3949
3950 r = id_cryptoctx->p11->C_FindObjectsInit(session, attrs, nattrs);
3951 if (r != CKR_OK) {
3952 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r));
3953 krb5_set_error_message(context, EINVAL,
3954 gettext("PKCS11 error from C_FindObjectsInit: %s"),
3955 pkinit_pkcs11_code_to_text(r));
3956 r = EINVAL;
3957 goto out;
3958 }
3959
3960 for (i = 0; ; i++) {
3961 if (i >= MAX_CREDS_ALLOWED) {
3962 r = EINVAL;
3963 goto out;
3964 }
3965
3966 /* Look for x.509 cert */
3967 /* Solaris Kerberos */
3968 if ((r = id_cryptoctx->p11->C_FindObjects(session, &obj, 1, &count))
3969 != CKR_OK || count == 0) {
3970 id_cryptoctx->creds[i] = NULL;
3971 break;
3972 }
3973
3974 /* Get cert and id len */
3975 attrs[0].type = CKA_VALUE;
3976 attrs[0].pValue = NULL;
3977 attrs[0].ulValueLen = 0;
3978
3979 attrs[1].type = CKA_ID;
3980 attrs[1].pValue = NULL;
3981 attrs[1].ulValueLen = 0;
3982
3983 if ((r = id_cryptoctx->p11->C_GetAttributeValue(session,
3984 obj,
3985 attrs,
3986 2)) != CKR_OK &&
3987 r != CKR_BUFFER_TOO_SMALL) {
3988 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
3989 krb5_set_error_message(context, EINVAL,
3990 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
3991 pkinit_pkcs11_code_to_text(r));
3992 r = EINVAL;
3993 goto out;
3994 }
3995 cert = malloc((size_t) attrs[0].ulValueLen + 1);
3996 if (cert == NULL) {
3997 r = ENOMEM;
3998 goto out;
3999 }
4000 cert_id = malloc((size_t) attrs[1].ulValueLen + 1);
4001 if (cert_id == NULL) {
4002 r = ENOMEM;
4003 goto out;
4004 }
4005
4006 /* Read the cert and id off the card */
4007
4008 attrs[0].type = CKA_VALUE;
4009 attrs[0].pValue = cert;
4010
4011 attrs[1].type = CKA_ID;
4012 attrs[1].pValue = cert_id;
4013
4014 if ((r = id_cryptoctx->p11->C_GetAttributeValue(session,
4015 obj, attrs, 2)) != CKR_OK) {
4016 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
4017 krb5_set_error_message(context, EINVAL,
4018 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
4019 pkinit_pkcs11_code_to_text(r));
4020 r = EINVAL;
4021 goto out;
4022 }
4023
4024 pkiDebug("cert %d size %d id %d idlen %d\n", i,
4025 (int) attrs[0].ulValueLen, (int) cert_id[0],
4026 (int) attrs[1].ulValueLen);
4027
4028 cp = (unsigned char *) cert;
4029 x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen);
4030 if (x == NULL) {
4031 r = EINVAL;
4032 goto out;
4033 }
4034
4035 id_cryptoctx->creds[i] = malloc(sizeof(struct _pkinit_cred_info));
4036 if (id_cryptoctx->creds[i] == NULL) {
4037 r = ENOMEM;
4038 goto out;
4039 }
4040 id_cryptoctx->creds[i]->cert = x;
4041 id_cryptoctx->creds[i]->key = NULL;
4042 id_cryptoctx->creds[i]->cert_id = cert_id;
4043 cert_id = NULL;
4044 id_cryptoctx->creds[i]->cert_id_len = attrs[1].ulValueLen;
4045 free(cert);
4046 cert = NULL;
4047 }
4048 id_cryptoctx->p11->C_FindObjectsFinal(session);
4049
4050 if (id_cryptoctx->creds[0] == NULL || id_cryptoctx->creds[0]->cert == NULL) {
4051 r = ENOENT;
4052 } else if (do_matching){
4053 /*
4054 * Do not let pkinit_cert_matching set the primary cert in id_cryptoctx
4055 * as this will be done later.
4056 */
4057 r = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx,
4058 id_cryptoctx, princ, FALSE);
4059 }
4060
4061 out:
4062 if ((r != 0 || !load_cert) &&
4063 id_cryptoctx->creds[0] != NULL &&
4064 id_cryptoctx->creds[0]->cert != NULL) {
4065 /*
4066 * If there's an error or load_cert isn't 1 free all the certs loaded
4067 * onto id_cryptoctx.
4068 */
4069 (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
4070 id_cryptoctx);
4071 }
4072
4073 if (cert)
4074 free(cert);
4075
4076 if (cert_id)
4077 free(cert_id);
4078
4079 return (r);
4080 }
4081
4082 /*
4083 * Solaris Kerberos: this function has been significantly modified to prompt
4084 * the user in certain cases so defer to this version when resyncing MIT code.
4085 *
4086 * pkinit_open_session now does several things including prompting the user if
4087 * do_matching is set which indicates the code is executing in a client
4088 * context. This function fills out a pkinit_identity_crypto_context with a
4089 * set of certs and a open session if a token can be found that matches all
4090 * supplied criteria. If no token is found then the user is prompted one time
4091 * to insert their token. If there is more than one token that matches all
4092 * client criteria the user is prompted to make a choice if in client context.
4093 * If do_matching is false (KDC context) then the first token matching all
4094 * server criteria is chosen.
4095 */
4096 static krb5_error_code
pkinit_open_session(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context cctx,krb5_principal princ,int do_matching)4097 pkinit_open_session(krb5_context context,
4098 pkinit_plg_crypto_context plg_cryptoctx,
4099 pkinit_req_crypto_context req_cryptoctx,
4100 pkinit_identity_crypto_context cctx,
4101 krb5_principal princ,
4102 int do_matching)
4103 {
4104 int i, r;
4105 CK_ULONG count = 0;
4106 CK_SLOT_ID_PTR slotlist = NULL, tmpslotlist = NULL;
4107 CK_TOKEN_INFO tinfo;
4108 krb5_boolean tokenmatch = FALSE;
4109 CK_SESSION_HANDLE tmpsession = CK_INVALID_HANDLE;
4110 struct _token_choices token_choices;
4111 int choice = 0;
4112
4113 if (cctx->session != CK_INVALID_HANDLE)
4114 return 0; /* session already open */
4115
4116 /* Load module */
4117 if (cctx->p11_module == NULL) {
4118 cctx->p11_module =
4119 pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11);
4120 if (cctx->p11_module == NULL)
4121 return KRB5KDC_ERR_PREAUTH_FAILED;
4122 }
4123
4124 /* Init */
4125 /* Solaris Kerberos: Don't fail if cryptoki is already initialized */
4126 r = cctx->p11->C_Initialize(NULL);
4127 if (r != CKR_OK && r != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
4128 pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r));
4129 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4130 gettext("Error from PKCS11 C_Initialize: %s"),
4131 pkinit_pkcs11_code_to_text(r));
4132 return KRB5KDC_ERR_PREAUTH_FAILED;
4133 }
4134
4135 (void) memset(&token_choices, 0, sizeof(token_choices));
4136
4137 /*
4138 * Solaris Kerberos:
4139 * If C_Initialize was already called by the process before the pkinit
4140 * module was loaded then record that fact.
4141 * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether
4142 * or not C_Finalize() should be called.
4143 */
4144 cctx->finalize_pkcs11 =
4145 (r == CKR_CRYPTOKI_ALREADY_INITIALIZED ? FALSE : TRUE);
4146 /*
4147 * First make sure that is an applicable slot otherwise fail.
4148 *
4149 * Start by getting a count of all slots with or without tokens.
4150 */
4151
4152 if ((r = cctx->p11->C_GetSlotList(FALSE, NULL, &count)) != CKR_OK) {
4153 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4154 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4155 gettext("Error trying to get PKCS11 slot list: %s"),
4156 pkinit_pkcs11_code_to_text(r));
4157 r = KRB5KDC_ERR_PREAUTH_FAILED;
4158 goto out;
4159 }
4160
4161 if (count == 0) {
4162 /* There are no slots so bail */
4163 r = KRB5KDC_ERR_PREAUTH_FAILED;
4164 krb5_set_error_message(context, r,
4165 gettext("No PKCS11 slots found"));
4166 pkiDebug("pkinit_open_session: no slots, count: %d\n", count);
4167 goto out;
4168 } else if (cctx->slotid != PK_NOSLOT) {
4169 /* See if any of the slots match the specified slotID */
4170 tmpslotlist = malloc(count * sizeof (CK_SLOT_ID));
4171 if (tmpslotlist == NULL) {
4172 krb5_set_error_message(context, ENOMEM,
4173 gettext("Memory allocation error:"));
4174 r = KRB5KDC_ERR_PREAUTH_FAILED;
4175 goto out;
4176 }
4177 if ((r = cctx->p11->C_GetSlotList(FALSE, tmpslotlist, &count)) != CKR_OK) {
4178 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4179 gettext("Error trying to get PKCS11 slot list: %s"),
4180 pkinit_pkcs11_code_to_text(r));
4181 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4182 r = KRB5KDC_ERR_PREAUTH_FAILED;
4183 goto out;
4184 }
4185
4186 for (i = 0; i < count && cctx->slotid != tmpslotlist[i]; i++)
4187 continue;
4188
4189 if (i >= count) {
4190 /* no slots match */
4191 r = KRB5KDC_ERR_PREAUTH_FAILED;
4192 krb5_set_error_message(context, r,
4193 gettext("Requested PKCS11 slot ID %d not found"),
4194 cctx->slotid);
4195 pkiDebug("open_session: no matching slot found for slotID %d\n",
4196 cctx->slotid);
4197 goto out;
4198 }
4199 }
4200
4201 tryagain:
4202 /* get count of slots that have tokens */
4203 if ((r = cctx->p11->C_GetSlotList(TRUE, NULL, &count)) != CKR_OK) {
4204 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4205 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4206 gettext("Error trying to get PKCS11 slot list: %s"),
4207 pkinit_pkcs11_code_to_text(r));
4208 r = KRB5KDC_ERR_PREAUTH_FAILED;
4209 goto out;
4210 }
4211
4212 if (count == 0) {
4213 /*
4214 * Note, never prompt if !do_matching as this implies KDC side
4215 * processing
4216 */
4217 if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) {
4218 /* found slot(s) but no token so prompt and try again */
4219 if ((r = pkinit_prompt_token(context, cctx)) == 0) {
4220 cctx->p11flags |= C_PROMPTED_USER;
4221 goto tryagain;
4222 } else {
4223 pkiDebug("open_session: prompt for token/smart card failed\n");
4224 krb5_set_error_message(context, r,
4225 gettext("Prompt for token/smart card failed"));
4226 r = KRB5KDC_ERR_PREAUTH_FAILED;
4227 goto out;
4228 }
4229
4230 } else {
4231 /* already prompted once so bailing */
4232 r = KRB5KDC_ERR_PREAUTH_FAILED;
4233 krb5_set_error_message(context, r,
4234 gettext("No smart card tokens found"));
4235 pkiDebug("pkinit_open_session: no token, already prompted\n");
4236 goto out;
4237 }
4238 }
4239
4240 if (slotlist != NULL)
4241 free(slotlist);
4242
4243 slotlist = malloc(count * sizeof (CK_SLOT_ID));
4244 if (slotlist == NULL) {
4245 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4246 gettext("Memory allocation error"));
4247 r = KRB5KDC_ERR_PREAUTH_FAILED;
4248 goto out;
4249 }
4250 /*
4251 * Solaris Kerberos: get list of PKCS11 slotid's that have tokens.
4252 */
4253 if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) {
4254 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4255 gettext("Error trying to get PKCS11 slot list: %s"),
4256 pkinit_pkcs11_code_to_text(r));
4257 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4258 r = KRB5KDC_ERR_PREAUTH_FAILED;
4259 goto out;
4260 }
4261
4262 token_choices.numtokens = 0;
4263 token_choices.token_array = malloc(count * sizeof (*token_choices.token_array));
4264 if (token_choices.token_array == NULL) {
4265 r = KRB5KDC_ERR_PREAUTH_FAILED;
4266 krb5_set_error_message(context, r,
4267 gettext("Memory allocation error"));
4268 goto out;
4269 }
4270
4271 /* examine all the tokens */
4272 for (i = 0; i < count; i++) {
4273 /*
4274 * Solaris Kerberos: if a slotid was specified skip slots that don't
4275 * match.
4276 */
4277 if (cctx->slotid != PK_NOSLOT && cctx->slotid != slotlist[i])
4278 continue;
4279
4280 /* Open session */
4281 if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
4282 NULL, NULL, &tmpsession)) != CKR_OK) {
4283 pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r));
4284 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4285 gettext("Error trying to open PKCS11 session: %s"),
4286 pkinit_pkcs11_code_to_text(r));
4287 r = KRB5KDC_ERR_PREAUTH_FAILED;
4288 goto out;
4289 }
4290
4291 /* Get token info */
4292 if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) {
4293 pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r));
4294 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4295 gettext("Error trying to read PKCS11 token: %s"),
4296 pkinit_pkcs11_code_to_text(r));
4297 r = KRB5KDC_ERR_PREAUTH_FAILED;
4298 cctx->p11->C_CloseSession(tmpsession);
4299 goto out;
4300 }
4301
4302 if (cctx->token_label == NULL) {
4303 /*
4304 * If the token doesn't require login to examine the certs then
4305 * let's check the certs out to see if any match the criteria if
4306 * any.
4307 */
4308 if (!(tinfo.flags & CKF_LOGIN_REQUIRED)) {
4309 /*
4310 * It's okay to check the certs if we don't have to login but
4311 * don't load the certs onto cctx at this point, this will be
4312 * done later in this function for the chosen token.
4313 */
4314 if ((r = check_load_certs(context, tmpsession, plg_cryptoctx,
4315 req_cryptoctx, cctx, princ,
4316 do_matching, 0)) == 0) {
4317 tokenmatch = TRUE;
4318 } else if (r != ENOENT){
4319 r = KRB5KDC_ERR_PREAUTH_FAILED;
4320 cctx->p11->C_CloseSession(tmpsession);
4321 goto out;
4322 } else {
4323 /* ignore ENOENT here */
4324 r = 0;
4325 }
4326 } else {
4327 tokenmatch = TRUE;
4328 }
4329 } else {
4330 /* + 1 so tokenlabelstr can be \0 terminated */
4331 char tokenlabelstr[sizeof (tinfo.label) + 1];
4332
4333 /*
4334 * Convert token label into C string with trailing white space
4335 * trimmed.
4336 */
4337 trim_token_label(&tinfo, tokenlabelstr, sizeof (tokenlabelstr));
4338
4339 pkiDebug("open_session: slotid %d token found: \"%s\", "
4340 "cctx->token_label: \"%s\"\n",
4341 slotlist[i], tokenlabelstr, (char *) cctx->token_label);
4342
4343 if (!strcmp(cctx->token_label, tokenlabelstr)) {
4344 if (!(tinfo.flags & CKF_LOGIN_REQUIRED)) {
4345 /*
4346 * It's okay to check the certs if we don't have to login but
4347 * don't load the certs onto cctx at this point, this will be
4348 * done later in this function for the chosen token.
4349 */
4350 if ((r = check_load_certs(context, tmpsession, plg_cryptoctx,
4351 req_cryptoctx, cctx, princ,
4352 do_matching, 0)) == 0) {
4353 tokenmatch = TRUE;
4354 } else if (r != ENOENT){
4355 r = KRB5KDC_ERR_PREAUTH_FAILED;
4356 cctx->p11->C_CloseSession(tmpsession);
4357 goto out;
4358 } else {
4359 /* ignore ENOENT here */
4360 r = 0;
4361 }
4362 } else {
4363 tokenmatch = TRUE;
4364 }
4365 }
4366 }
4367
4368 if (tokenmatch == TRUE) {
4369 /* add the token to token_choices.token_array */
4370 token_choices.token_array[token_choices.numtokens].slotID = slotlist[i];
4371 token_choices.token_array[token_choices.numtokens].session = tmpsession;
4372 token_choices.token_array[token_choices.numtokens].token_info = tinfo;
4373 token_choices.numtokens++;
4374 /* !do_matching implies we take the first matching token */
4375 if (!do_matching)
4376 break;
4377 else
4378 tokenmatch = FALSE;
4379 } else {
4380 cctx->p11->C_CloseSession(tmpsession);
4381 }
4382 }
4383
4384 if (token_choices.numtokens == 0) {
4385 /*
4386 * Solaris Kerberos: prompt for token one time if there was no token
4387 * and do_matching is 1 (see earlier comment about do_matching).
4388 */
4389 if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) {
4390 if ((r = pkinit_prompt_token(context, cctx)) == 0) {
4391 cctx->p11flags |= C_PROMPTED_USER;
4392 goto tryagain;
4393 } else {
4394 pkiDebug("open_session: prompt for token/smart card failed\n");
4395 krb5_set_error_message(context, r,
4396 gettext("Prompt for token/smart card failed"));
4397 r = KRB5KDC_ERR_PREAUTH_FAILED;
4398 goto out;
4399 }
4400 } else {
4401 r = KRB5KDC_ERR_PREAUTH_FAILED;
4402 krb5_set_error_message(context, r,
4403 gettext("No smart card tokens found"));
4404 pkiDebug("open_session: no matching token found\n");
4405 goto out;
4406 }
4407 } else if (token_choices.numtokens == 1) {
4408 if ((token_choices.token_array[0].token_info.flags & CKF_LOGIN_REQUIRED) &&
4409 !(cctx->p11flags & C_PROMPTED_USER) &&
4410 do_matching) {
4411 if ((r = pkinit_choose_tokens(context, cctx, &token_choices, &choice)) != 0) {
4412 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r);
4413 r = KRB5KDC_ERR_PREAUTH_FAILED;
4414 krb5_set_error_message(context, r,
4415 gettext("Prompt for token/smart card failed"));
4416 goto out;
4417 }
4418 if (choice == RESCAN_TOKENS) {
4419 /* rescan for new smartcard/token */
4420 for (i = 0; i < token_choices.numtokens; i++) {
4421 /* close all sessions */
4422 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4423 }
4424 free(token_choices.token_array);
4425 token_choices.token_array = NULL;
4426 token_choices.numtokens = 0;
4427 goto tryagain;
4428 } else if (choice == SKIP_TOKENS) {
4429 /* do not use smartcard/token for auth */
4430 cctx->p11flags |= (C_PROMPTED_USER|C_SKIP_PKCS11_AUTH);
4431 r = KRB5KDC_ERR_PREAUTH_FAILED;
4432 goto out;
4433 } else {
4434 cctx->p11flags |= C_PROMPTED_USER;
4435 }
4436 } else {
4437 choice = 0; /* really the only choice is the first token_array entry */
4438 }
4439 } else if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) {
4440 /* > 1 token so present menu of token choices, let the user decide. */
4441 if ((r = pkinit_choose_tokens(context, cctx, &token_choices, &choice)) != 0) {
4442 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r);
4443 r = KRB5KDC_ERR_PREAUTH_FAILED;
4444 krb5_set_error_message(context, r,
4445 gettext("Prompt for token/smart card failed"));
4446 goto out;
4447 }
4448 if (choice == RESCAN_TOKENS) {
4449 /* rescan for new smartcard/token */
4450 for (i = 0; i < token_choices.numtokens; i++) {
4451 /* close all sessions */
4452 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4453 }
4454 free(token_choices.token_array);
4455 token_choices.token_array = NULL;
4456 token_choices.numtokens = 0;
4457 goto tryagain;
4458 } else if (choice == SKIP_TOKENS) {
4459 /* do not use smartcard/token for auth */
4460 cctx->p11flags |= (C_PROMPTED_USER|C_SKIP_PKCS11_AUTH);
4461 r = KRB5KDC_ERR_PREAUTH_FAILED;
4462 goto out;
4463 } else {
4464 cctx->p11flags |= C_PROMPTED_USER;
4465 }
4466 } else {
4467 r = KRB5KDC_ERR_PREAUTH_FAILED;
4468 goto out;
4469 }
4470
4471 cctx->slotid = token_choices.token_array[choice].slotID;
4472 cctx->session = token_choices.token_array[choice].session;
4473
4474 pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx->slotid,
4475 i + 1, (int) count);
4476
4477 /* Login if needed */
4478 /* Solaris Kerberos: added cctx->p11flags check */
4479 if ((token_choices.token_array[choice].token_info.flags & CKF_LOGIN_REQUIRED) &&
4480 !(cctx->p11flags & C_LOGIN_DONE)) {
4481 r = pkinit_login(context, cctx, &token_choices.token_array[choice].token_info);
4482 }
4483
4484 if (r == 0) {
4485 /* Doing this again to load the certs into cctx. */
4486 r = check_load_certs(context, cctx->session, plg_cryptoctx,
4487 req_cryptoctx, cctx, princ, do_matching, 1);
4488 }
4489
4490 out:
4491 if (slotlist != NULL)
4492 free(slotlist);
4493
4494 if (tmpslotlist != NULL)
4495 free(tmpslotlist);
4496
4497 if (token_choices.token_array != NULL) {
4498 if (r != 0) {
4499 /* close all sessions if there's an error */
4500 for (i = 0; i < token_choices.numtokens; i++) {
4501 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4502 }
4503 cctx->session = CK_INVALID_HANDLE;
4504 } else {
4505 /* close sessions not chosen */
4506 for (i = 0; i < token_choices.numtokens; i++) {
4507 if (i != choice) {
4508 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4509 }
4510 }
4511 }
4512 free(token_choices.token_array);
4513 }
4514
4515 return (r);
4516 }
4517
4518 /*
4519 * Look for a key that's:
4520 * 1. private
4521 * 2. capable of the specified operation (usually signing or decrypting)
4522 * 3. RSA (this may be wrong but it's all we can do for now)
4523 * 4. matches the id of the cert we chose
4524 *
4525 * You must call pkinit_get_certs before calling pkinit_find_private_key
4526 * (that's because we need the ID of the private key)
4527 *
4528 * pkcs11 says the id of the key doesn't have to match that of the cert, but
4529 * I can't figure out any other way to decide which key to use.
4530 *
4531 * We should only find one key that fits all the requirements.
4532 * If there are more than one, we just take the first one.
4533 */
4534
4535 /* ARGSUSED */
4536 krb5_error_code
pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,CK_ATTRIBUTE_TYPE usage,CK_OBJECT_HANDLE * objp)4537 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
4538 CK_ATTRIBUTE_TYPE usage,
4539 CK_OBJECT_HANDLE *objp)
4540 {
4541 CK_OBJECT_CLASS cls;
4542 CK_ATTRIBUTE attrs[4];
4543 CK_ULONG count;
4544 CK_KEY_TYPE keytype;
4545 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
4546 const RSA *rsa;
4547 #else
4548 RSA *rsa;
4549 #endif
4550 unsigned int nattrs = 0;
4551 int r;
4552 #ifdef PKINIT_USE_KEY_USAGE
4553 CK_BBOOL true_false;
4554 #endif
4555
4556 cls = CKO_PRIVATE_KEY;
4557 attrs[nattrs].type = CKA_CLASS;
4558 attrs[nattrs].pValue = &cls;
4559 attrs[nattrs].ulValueLen = sizeof cls;
4560 nattrs++;
4561
4562 #ifdef PKINIT_USE_KEY_USAGE
4563 /*
4564 * Some cards get confused if you try to specify a key usage,
4565 * so don't, and hope for the best. This will fail if you have
4566 * several keys with the same id and different usages but I have
4567 * not seen this on real cards.
4568 */
4569 true_false = TRUE;
4570 attrs[nattrs].type = usage;
4571 attrs[nattrs].pValue = &true_false;
4572 attrs[nattrs].ulValueLen = sizeof true_false;
4573 nattrs++;
4574 #endif
4575
4576 keytype = CKK_RSA;
4577 attrs[nattrs].type = CKA_KEY_TYPE;
4578 attrs[nattrs].pValue = &keytype;
4579 attrs[nattrs].ulValueLen = sizeof keytype;
4580 nattrs++;
4581
4582 attrs[nattrs].type = CKA_ID;
4583 attrs[nattrs].pValue = id_cryptoctx->cert_id;
4584 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
4585 nattrs++;
4586
4587 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
4588 if (r != CKR_OK) {
4589 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4590 pkinit_pkcs11_code_to_text(r));
4591 return KRB5KDC_ERR_PREAUTH_FAILED;
4592 }
4593
4594 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
4595 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
4596 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
4597
4598 /*
4599 * Solaris Kerberos:
4600 * The CKA_ID may not be correctly set for the private key. For e.g. when
4601 * storing a private key in softtoken pktool(1) doesn't generate or store
4602 * a CKA_ID for the private key. Another way to identify the private key is
4603 * to look for a private key with the same RSA modulus as the public key
4604 * in the certificate.
4605 */
4606 if (r == CKR_OK && count != 1) {
4607
4608 EVP_PKEY *priv;
4609 X509 *cert;
4610 const BIGNUM *rsan;
4611 unsigned int n_len;
4612 unsigned char *n_bytes;
4613
4614 cert = sk_X509_value(id_cryptoctx->my_certs, 0);
4615 priv = X509_get_pubkey(cert);
4616 if (priv == NULL) {
4617 pkiDebug("Failed to extract pub key from cert\n");
4618 return KRB5KDC_ERR_PREAUTH_FAILED;
4619 }
4620
4621 nattrs = 0;
4622 cls = CKO_PRIVATE_KEY;
4623 attrs[nattrs].type = CKA_CLASS;
4624 attrs[nattrs].pValue = &cls;
4625 attrs[nattrs].ulValueLen = sizeof cls;
4626 nattrs++;
4627
4628 #ifdef PKINIT_USE_KEY_USAGE
4629 true_false = TRUE;
4630 attrs[nattrs].type = usage;
4631 attrs[nattrs].pValue = &true_false;
4632 attrs[nattrs].ulValueLen = sizeof true_false;
4633 nattrs++;
4634 #endif
4635
4636 keytype = CKK_RSA;
4637 attrs[nattrs].type = CKA_KEY_TYPE;
4638 attrs[nattrs].pValue = &keytype;
4639 attrs[nattrs].ulValueLen = sizeof keytype;
4640 nattrs++;
4641
4642 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
4643 rsa = priv->pkey.rsa;
4644 rsan = rsa->n;
4645 n_len = BN_num_bytes(rsan);
4646 #else
4647 rsa = EVP_PKEY_get0_RSA(priv);
4648 RSA_get0_key(rsa, &rsan, NULL, NULL);
4649 n_len = RSA_size(rsa);
4650 #endif
4651 n_bytes = (unsigned char *) malloc((size_t) n_len);
4652 if (n_bytes == NULL) {
4653 return (ENOMEM);
4654 }
4655
4656 if (BN_bn2bin(rsan, n_bytes) == 0) {
4657 free (n_bytes);
4658 pkiDebug("zero-byte key modulus\n");
4659 return KRB5KDC_ERR_PREAUTH_FAILED;
4660 }
4661
4662 attrs[nattrs].type = CKA_MODULUS;
4663 attrs[nattrs].ulValueLen = n_len;
4664 attrs[nattrs].pValue = n_bytes;
4665
4666 nattrs++;
4667
4668 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
4669 free (n_bytes);
4670 if (r != CKR_OK) {
4671 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4672 pkinit_pkcs11_code_to_text(r));
4673 return KRB5KDC_ERR_PREAUTH_FAILED;
4674 }
4675
4676 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
4677 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
4678 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
4679
4680 }
4681
4682 if (r != CKR_OK || count < 1)
4683 return KRB5KDC_ERR_PREAUTH_FAILED;
4684 return 0;
4685 }
4686 #endif
4687
4688 /* ARGSUSED */
4689 static krb5_error_code
pkinit_decode_data_fs(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,unsigned char * data,unsigned int data_len,unsigned char ** decoded_data,unsigned int * decoded_data_len)4690 pkinit_decode_data_fs(krb5_context context,
4691 pkinit_identity_crypto_context id_cryptoctx,
4692 unsigned char *data,
4693 unsigned int data_len,
4694 unsigned char **decoded_data,
4695 unsigned int *decoded_data_len)
4696 {
4697 if (decode_data(decoded_data, decoded_data_len, data, data_len,
4698 id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs,
4699 id_cryptoctx->cert_index)) <= 0) {
4700 pkiDebug("failed to decode data\n");
4701 return KRB5KDC_ERR_PREAUTH_FAILED;
4702 }
4703 return 0;
4704 }
4705
4706 #ifndef WITHOUT_PKCS11
4707 #ifdef SILLYDECRYPT
4708 CK_RV
pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)4709 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,
4710 CK_BYTE_PTR pEncryptedData,
4711 CK_ULONG ulEncryptedDataLen,
4712 CK_BYTE_PTR pData,
4713 CK_ULONG_PTR pulDataLen)
4714 {
4715 CK_RV rv = CKR_OK;
4716
4717 rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData,
4718 ulEncryptedDataLen, pData, pulDataLen);
4719 if (rv == CKR_OK) {
4720 pkiDebug("pData %x *pulDataLen %d\n", (int) pData, (int) *pulDataLen);
4721 }
4722 return rv;
4723 }
4724 #endif
4725
4726 static krb5_error_code
pkinit_decode_data_pkcs11(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,unsigned char * data,unsigned int data_len,unsigned char ** decoded_data,unsigned int * decoded_data_len)4727 pkinit_decode_data_pkcs11(krb5_context context,
4728 pkinit_identity_crypto_context id_cryptoctx,
4729 unsigned char *data,
4730 unsigned int data_len,
4731 unsigned char **decoded_data,
4732 unsigned int *decoded_data_len)
4733 {
4734 CK_OBJECT_HANDLE obj;
4735 CK_ULONG len;
4736 CK_MECHANISM mech;
4737 unsigned char *cp;
4738 int r;
4739
4740 /*
4741 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4742 * loaded.
4743 */
4744 assert(id_cryptoctx->p11 != NULL);
4745
4746 /* Solaris Kerberos: Login, if needed, to access private object */
4747 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) {
4748 CK_TOKEN_INFO tinfo;
4749
4750 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo);
4751 if (r != 0)
4752 return r;
4753
4754 r = pkinit_login(context, id_cryptoctx, &tinfo);
4755 if (r != 0)
4756 return r;
4757 }
4758
4759 r = pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj);
4760 if (r != 0)
4761 return r;
4762
4763 mech.mechanism = CKM_RSA_PKCS;
4764 mech.pParameter = NULL;
4765 mech.ulParameterLen = 0;
4766
4767 if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech,
4768 obj)) != CKR_OK) {
4769 pkiDebug("C_DecryptInit: 0x%x\n", (int) r);
4770 return KRB5KDC_ERR_PREAUTH_FAILED;
4771 }
4772 pkiDebug("data_len = %d\n", data_len);
4773 cp = (unsigned char *)malloc((size_t) data_len);
4774 if (cp == NULL)
4775 return ENOMEM;
4776 len = data_len;
4777 #ifdef SILLYDECRYPT
4778 pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n",
4779 (int) id_cryptoctx->session, (int) data, (int) data_len, (int) cp,
4780 (int) &len, (int) len);
4781 if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len,
4782 cp, &len)) != CKR_OK) {
4783 #else
4784 if ((r = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, data,
4785 (CK_ULONG) data_len, cp, &len)) != CKR_OK) {
4786 #endif
4787 pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r));
4788 if (r == CKR_BUFFER_TOO_SMALL)
4789 pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len);
4790 return KRB5KDC_ERR_PREAUTH_FAILED;
4791 }
4792 pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len);
4793 *decoded_data_len = len;
4794 *decoded_data = cp;
4795
4796 return 0;
4797 }
4798 #endif
4799
4800 krb5_error_code
4801 pkinit_decode_data(krb5_context context,
4802 pkinit_identity_crypto_context id_cryptoctx,
4803 unsigned char *data,
4804 unsigned int data_len,
4805 unsigned char **decoded_data,
4806 unsigned int *decoded_data_len)
4807 {
4808 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4809
4810 if (id_cryptoctx->pkcs11_method != 1)
4811 retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len,
4812 decoded_data, decoded_data_len);
4813 #ifndef WITHOUT_PKCS11
4814 else
4815 retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data,
4816 data_len, decoded_data, decoded_data_len);
4817 #endif
4818
4819 return retval;
4820 }
4821
4822 /* ARGSUSED */
4823 static krb5_error_code
4824 pkinit_sign_data_fs(krb5_context context,
4825 pkinit_identity_crypto_context id_cryptoctx,
4826 unsigned char *data,
4827 unsigned int data_len,
4828 unsigned char **sig,
4829 unsigned int *sig_len)
4830 {
4831 if (create_signature(sig, sig_len, data, data_len,
4832 id_cryptoctx->my_key) != 0) {
4833 pkiDebug("failed to create the signature\n");
4834 return KRB5KDC_ERR_PREAUTH_FAILED;
4835 }
4836 return 0;
4837 }
4838
4839 #ifndef WITHOUT_PKCS11
4840 static krb5_error_code
4841 pkinit_sign_data_pkcs11(krb5_context context,
4842 pkinit_identity_crypto_context id_cryptoctx,
4843 unsigned char *data,
4844 unsigned int data_len,
4845 unsigned char **sig,
4846 unsigned int *sig_len)
4847 {
4848 CK_OBJECT_HANDLE obj;
4849 CK_ULONG len;
4850 CK_MECHANISM mech;
4851 unsigned char *cp;
4852 int r;
4853
4854 /*
4855 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4856 * loaded.
4857 */
4858 assert(id_cryptoctx->p11 != NULL);
4859
4860 /* Solaris Kerberos: Login, if needed, to access private object */
4861 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) {
4862 CK_TOKEN_INFO tinfo;
4863
4864 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo);
4865 if (r != 0)
4866 return r;
4867
4868 r = pkinit_login(context, id_cryptoctx, &tinfo);
4869 if (r != 0)
4870 return r;
4871 }
4872
4873 r = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
4874 if (r != 0 )
4875 return r;
4876
4877 mech.mechanism = id_cryptoctx->mech;
4878 mech.pParameter = NULL;
4879 mech.ulParameterLen = 0;
4880
4881 if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
4882 obj)) != CKR_OK) {
4883 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r));
4884 return KRB5KDC_ERR_PREAUTH_FAILED;
4885 }
4886
4887 /*
4888 * Key len would give an upper bound on sig size, but there's no way to
4889 * get that. So guess, and if it's too small, re-malloc.
4890 */
4891 len = PK_SIGLEN_GUESS;
4892 cp = (unsigned char *)malloc((size_t) len);
4893 if (cp == NULL)
4894 return ENOMEM;
4895
4896 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
4897 (CK_ULONG) data_len, cp, &len);
4898 if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
4899 free(cp);
4900 pkiDebug("C_Sign realloc %d\n", (int) len);
4901 cp = (unsigned char *)malloc((size_t) len);
4902 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
4903 (CK_ULONG) data_len, cp, &len);
4904 }
4905 if (r != CKR_OK) {
4906 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r));
4907 return KRB5KDC_ERR_PREAUTH_FAILED;
4908 }
4909 pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
4910 *sig_len = len;
4911 *sig = cp;
4912
4913 return 0;
4914 }
4915 #endif
4916
4917 krb5_error_code
4918 pkinit_sign_data(krb5_context context,
4919 pkinit_identity_crypto_context id_cryptoctx,
4920 unsigned char *data,
4921 unsigned int data_len,
4922 unsigned char **sig,
4923 unsigned int *sig_len)
4924 {
4925 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4926
4927 if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1)
4928 retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len,
4929 sig, sig_len);
4930 #ifndef WITHOUT_PKCS11
4931 else
4932 retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len,
4933 sig, sig_len);
4934 #endif
4935
4936 return retval;
4937 }
4938
4939
4940 static krb5_error_code
4941 decode_data(unsigned char **out_data, unsigned int *out_data_len,
4942 unsigned char *data, unsigned int data_len,
4943 EVP_PKEY *pkey, X509 *cert)
4944 {
4945 /* Solaris Kerberos */
4946 int len;
4947 unsigned char *buf = NULL;
4948 int buf_len = 0;
4949
4950 /* Solaris Kerberos */
4951 if (out_data == NULL || out_data_len == NULL)
4952 return EINVAL;
4953
4954 if (cert && !X509_check_private_key(cert, pkey)) {
4955 pkiDebug("private key does not match certificate\n");
4956 /* Solaris Kerberos */
4957 return EINVAL;
4958 }
4959
4960 buf_len = EVP_PKEY_size(pkey);
4961 buf = (unsigned char *)malloc((size_t) buf_len + 10);
4962 if (buf == NULL)
4963 return ENOMEM;
4964
4965 len = EVP_PKEY_decrypt_old(buf, data, (int)data_len, pkey);
4966 if (len <= 0) {
4967 pkiDebug("unable to decrypt received data (len=%d)\n", data_len);
4968 /* Solaris Kerberos */
4969 free(buf);
4970 return KRB5KRB_ERR_GENERIC;
4971 }
4972 *out_data = buf;
4973 *out_data_len = len;
4974
4975 return 0;
4976 }
4977
4978 static krb5_error_code
4979 create_signature(unsigned char **sig, unsigned int *sig_len,
4980 unsigned char *data, unsigned int data_len, EVP_PKEY *pkey)
4981 {
4982 krb5_error_code retval = ENOMEM;
4983 EVP_MD_CTX *md_ctx;
4984
4985 if (pkey == NULL)
4986 /* Solaris Kerberos */
4987 return EINVAL;
4988
4989 if ((md_ctx = EVP_MD_CTX_new()) == NULL)
4990 return EINVAL;
4991
4992 EVP_VerifyInit(md_ctx, EVP_sha1());
4993 EVP_SignUpdate(md_ctx, data, data_len);
4994 *sig_len = EVP_PKEY_size(pkey);
4995 if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL)
4996 goto cleanup;
4997 EVP_SignFinal(md_ctx, *sig, sig_len, pkey);
4998
4999 retval = 0;
5000
5001 cleanup:
5002 EVP_MD_CTX_free(md_ctx);
5003
5004 return retval;
5005 }
5006
5007 /*
5008 * Note:
5009 * This is not the routine the KDC uses to get its certificate.
5010 * This routine is intended to be called by the client
5011 * to obtain the KDC's certificate from some local storage
5012 * to be sent as a hint in its request to the KDC.
5013 */
5014 /* ARGSUSED */
5015 krb5_error_code
5016 pkinit_get_kdc_cert(krb5_context context,
5017 pkinit_plg_crypto_context plg_cryptoctx,
5018 pkinit_req_crypto_context req_cryptoctx,
5019 pkinit_identity_crypto_context id_cryptoctx,
5020 krb5_principal princ)
5021 {
5022 /* Solaris Kerberos */
5023 if (req_cryptoctx == NULL)
5024 return EINVAL;
5025
5026 req_cryptoctx->received_cert = NULL;
5027 return 0;
5028 }
5029
5030 /* ARGSUSED */
5031 static krb5_error_code
5032 pkinit_get_certs_pkcs12(krb5_context context,
5033 pkinit_plg_crypto_context plg_cryptoctx,
5034 pkinit_req_crypto_context req_cryptoctx,
5035 pkinit_identity_opts *idopts,
5036 pkinit_identity_crypto_context id_cryptoctx,
5037 krb5_principal princ)
5038 {
5039 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
5040 X509 *x = NULL;
5041 PKCS12 *p12 = NULL;
5042 int ret;
5043 FILE *fp;
5044 EVP_PKEY *y = NULL;
5045
5046 if (idopts->cert_filename == NULL) {
5047 /* Solaris Kerberos: Improved error messages */
5048 krb5_set_error_message(context, retval,
5049 gettext("Failed to get certificate location"));
5050 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
5051 goto cleanup;
5052 }
5053
5054 if (idopts->key_filename == NULL) {
5055 /* Solaris Kerberos: Improved error messages */
5056 krb5_set_error_message(context, retval,
5057 gettext("Failed to get private key location"));
5058 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
5059 goto cleanup;
5060 }
5061
5062 fp = fopen(idopts->cert_filename, "rb");
5063 if (fp == NULL) {
5064 /* Solaris Kerberos: Improved error messages */
5065 krb5_set_error_message(context, retval,
5066 gettext("Failed to open PKCS12 file '%s': %s"),
5067 idopts->cert_filename, error_message(errno));
5068 pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
5069 idopts->cert_filename, errno);
5070 goto cleanup;
5071 }
5072
5073 p12 = d2i_PKCS12_fp(fp, NULL);
5074 (void) fclose(fp);
5075 if (p12 == NULL) {
5076 krb5_set_error_message(context, retval,
5077 gettext("Failed to decode PKCS12 file '%s' contents"),
5078 idopts->cert_filename);
5079 pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
5080 idopts->cert_filename);
5081 goto cleanup;
5082 }
5083 /*
5084 * Try parsing with no pass phrase first. If that fails,
5085 * prompt for the pass phrase and try again.
5086 */
5087 ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
5088 if (ret == 0) {
5089 krb5_data rdat;
5090 krb5_prompt kprompt;
5091 krb5_prompt_type prompt_type;
5092 int r = 0;
5093 char prompt_string[128];
5094 char prompt_reply[128];
5095 /* Solaris Kerberos */
5096 char *prompt_prefix = gettext("Pass phrase for");
5097
5098 pkiDebug("Initial PKCS12_parse with no password failed\n");
5099
5100 if (id_cryptoctx->PIN != NULL) {
5101 /* Solaris Kerberos: use PIN if set */
5102 rdat.data = id_cryptoctx->PIN;
5103 /* note rdat.length isn't needed in this case */
5104 } else {
5105 (void) memset(prompt_reply, '\0', sizeof(prompt_reply));
5106 rdat.data = prompt_reply;
5107 rdat.length = sizeof(prompt_reply);
5108
5109 r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
5110 prompt_prefix, idopts->cert_filename);
5111 if (r >= sizeof(prompt_string)) {
5112 pkiDebug("Prompt string, '%s %s', is too long!\n",
5113 prompt_prefix, idopts->cert_filename);
5114 goto cleanup;
5115 }
5116 kprompt.prompt = prompt_string;
5117 kprompt.hidden = 1;
5118 kprompt.reply = &rdat;
5119 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
5120
5121 /* PROMPTER_INVOCATION */
5122 k5int_set_prompt_types(context, &prompt_type);
5123 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
5124 NULL, NULL, 1, &kprompt);
5125 k5int_set_prompt_types(context, NULL);
5126 }
5127
5128 ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
5129 if (ret == 0) {
5130 /* Solaris Kerberos: Improved error messages */
5131 krb5_set_error_message(context, retval,
5132 gettext("Failed to parse PKCS12 file '%s' with password"),
5133 idopts->cert_filename);
5134 pkiDebug("Seconde PKCS12_parse with password failed\n");
5135 goto cleanup;
5136 }
5137 }
5138 id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
5139 if (id_cryptoctx->creds[0] == NULL)
5140 goto cleanup;
5141 id_cryptoctx->creds[0]->cert = x;
5142 #ifndef WITHOUT_PKCS11
5143 id_cryptoctx->creds[0]->cert_id = NULL;
5144 id_cryptoctx->creds[0]->cert_id_len = 0;
5145 #endif
5146 id_cryptoctx->creds[0]->key = y;
5147 id_cryptoctx->creds[1] = NULL;
5148
5149 retval = 0;
5150
5151 cleanup:
5152 if (p12)
5153 PKCS12_free(p12);
5154 if (retval) {
5155 if (x != NULL)
5156 X509_free(x);
5157 if (y != NULL)
5158 EVP_PKEY_free(y);
5159 }
5160 return retval;
5161 }
5162
5163 static krb5_error_code
5164 pkinit_load_fs_cert_and_key(krb5_context context,
5165 pkinit_identity_crypto_context id_cryptoctx,
5166 char *certname,
5167 char *keyname,
5168 int cindex)
5169 {
5170 krb5_error_code retval;
5171 X509 *x = NULL;
5172 EVP_PKEY *y = NULL;
5173
5174 /* load the certificate */
5175 retval = get_cert(certname, &x);
5176 if (retval != 0 || x == NULL) {
5177 /* Solaris Kerberos: Improved error messages */
5178 krb5_set_error_message(context, retval,
5179 gettext("Failed to load user's certificate from %s: %s"),
5180 certname, error_message(retval));
5181 pkiDebug("failed to load user's certificate from '%s'\n", certname);
5182 goto cleanup;
5183 }
5184 retval = get_key(keyname, &y);
5185 if (retval != 0 || y == NULL) {
5186 /* Solaris Kerberos: Improved error messages */
5187 krb5_set_error_message(context, retval,
5188 gettext("Failed to load user's private key from %s: %s"),
5189 keyname, error_message(retval));
5190 pkiDebug("failed to load user's private key from '%s'\n", keyname);
5191 goto cleanup;
5192 }
5193
5194 id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
5195 if (id_cryptoctx->creds[cindex] == NULL) {
5196 retval = ENOMEM;
5197 goto cleanup;
5198 }
5199 id_cryptoctx->creds[cindex]->cert = x;
5200 #ifndef WITHOUT_PKCS11
5201 id_cryptoctx->creds[cindex]->cert_id = NULL;
5202 id_cryptoctx->creds[cindex]->cert_id_len = 0;
5203 #endif
5204 id_cryptoctx->creds[cindex]->key = y;
5205 id_cryptoctx->creds[cindex+1] = NULL;
5206
5207 retval = 0;
5208
5209 cleanup:
5210 if (retval) {
5211 if (x != NULL)
5212 X509_free(x);
5213 if (y != NULL)
5214 EVP_PKEY_free(y);
5215 }
5216 return retval;
5217 }
5218
5219 /* ARGSUSED */
5220 static krb5_error_code
5221 pkinit_get_certs_fs(krb5_context context,
5222 pkinit_plg_crypto_context plg_cryptoctx,
5223 pkinit_req_crypto_context req_cryptoctx,
5224 pkinit_identity_opts *idopts,
5225 pkinit_identity_crypto_context id_cryptoctx,
5226 krb5_principal princ)
5227 {
5228 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
5229
5230 if (idopts->cert_filename == NULL) {
5231 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
5232 goto cleanup;
5233 }
5234
5235 if (idopts->key_filename == NULL) {
5236 pkiDebug("%s: failed to get user's private key location\n",
5237 __FUNCTION__);
5238 goto cleanup;
5239 }
5240
5241 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
5242 idopts->cert_filename,
5243 idopts->key_filename, 0);
5244 cleanup:
5245 return retval;
5246 }
5247
5248 /* ARGSUSED */
5249 static krb5_error_code
5250 pkinit_get_certs_dir(krb5_context context,
5251 pkinit_plg_crypto_context plg_cryptoctx,
5252 pkinit_req_crypto_context req_cryptoctx,
5253 pkinit_identity_opts *idopts,
5254 pkinit_identity_crypto_context id_cryptoctx,
5255 krb5_principal princ)
5256 {
5257 /* Solaris Kerberos */
5258 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
5259 DIR *d = NULL;
5260 struct dirent *dentry = NULL;
5261 char certname[1024];
5262 char keyname[1024];
5263 int i = 0, len;
5264 char *dirname, *suf;
5265
5266 /* Solaris Kerberos */
5267 if (idopts == NULL)
5268 return EINVAL;
5269
5270 if (idopts->cert_filename == NULL) {
5271 pkiDebug("%s: failed to get user's certificate directory location\n",
5272 __FUNCTION__);
5273 return ENOENT;
5274 }
5275
5276 dirname = idopts->cert_filename;
5277 d = opendir(dirname);
5278 if (d == NULL) {
5279 /* Solaris Kerberos: Improved error messages */
5280 krb5_set_error_message(context, errno,
5281 gettext("Failed to open directory \"%s\": %s"),
5282 dirname, error_message(errno));
5283 return errno;
5284 }
5285
5286 /*
5287 * We'll assume that certs are named XXX.crt and the corresponding
5288 * key is named XXX.key
5289 */
5290 while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) {
5291 /* Ignore subdirectories and anything starting with a dot */
5292 #ifdef DT_DIR
5293 if (dentry->d_type == DT_DIR)
5294 continue;
5295 #endif
5296 if (dentry->d_name[0] == '.')
5297 continue;
5298 len = strlen(dentry->d_name);
5299 if (len < 5)
5300 continue;
5301 suf = dentry->d_name + (len - 4);
5302 if (strncmp(suf, ".crt", 4) != 0)
5303 continue;
5304
5305 /* Checked length */
5306 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) {
5307 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
5308 __FUNCTION__, dirname, dentry->d_name);
5309 continue;
5310 }
5311 (void) snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name);
5312 (void) snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name);
5313 len = strlen(keyname);
5314 keyname[len - 3] = 'k';
5315 keyname[len - 2] = 'e';
5316 keyname[len - 1] = 'y';
5317
5318 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
5319 certname, keyname, i);
5320 if (retval == 0) {
5321 pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
5322 __FUNCTION__, dentry->d_name);
5323 i++;
5324 }
5325 else
5326 continue;
5327 }
5328
5329 if (i == 0) {
5330 /* Solaris Kerberos: Improved error messages */
5331 krb5_set_error_message(context, ENOENT,
5332 gettext("No suitable cert/key pairs found in directory '%s'"),
5333 idopts->cert_filename);
5334 pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
5335 __FUNCTION__, idopts->cert_filename);
5336 retval = ENOENT;
5337 goto cleanup;
5338 }
5339
5340 retval = 0;
5341
5342 cleanup:
5343 if (d)
5344 (void) closedir(d);
5345
5346 return retval;
5347 }
5348
5349 #ifndef WITHOUT_PKCS11
5350 /* ARGSUSED */
5351 static krb5_error_code
5352 pkinit_get_certs_pkcs11(krb5_context context,
5353 pkinit_plg_crypto_context plg_cryptoctx,
5354 pkinit_req_crypto_context req_cryptoctx,
5355 pkinit_identity_opts *idopts,
5356 pkinit_identity_crypto_context id_cryptoctx,
5357 krb5_principal princ,
5358 int do_matching)
5359 {
5360 #ifdef PKINIT_USE_MECH_LIST
5361 CK_MECHANISM_TYPE_PTR mechp = NULL;
5362 CK_MECHANISM_INFO info;
5363 #endif
5364
5365 if (id_cryptoctx->p11flags & C_SKIP_PKCS11_AUTH)
5366 return KRB5KDC_ERR_PREAUTH_FAILED;
5367
5368 /* Copy stuff from idopts -> id_cryptoctx */
5369 if (idopts->p11_module_name != NULL) {
5370 id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name);
5371 if (id_cryptoctx->p11_module_name == NULL)
5372 return ENOMEM;
5373 }
5374 if (idopts->token_label != NULL) {
5375 id_cryptoctx->token_label = strdup(idopts->token_label);
5376 if (id_cryptoctx->token_label == NULL)
5377 return ENOMEM;
5378 }
5379 if (idopts->cert_label != NULL) {
5380 id_cryptoctx->cert_label = strdup(idopts->cert_label);
5381 if (id_cryptoctx->cert_label == NULL)
5382 return ENOMEM;
5383 }
5384 if (idopts->PIN != NULL) {
5385 id_cryptoctx->PIN = strdup(idopts->PIN);
5386 if (id_cryptoctx->PIN == NULL)
5387 return ENOMEM;
5388 }
5389 /* Convert the ascii cert_id string into a binary blob */
5390 /*
5391 * Solaris Kerberos:
5392 * If the cert_id_string is empty then behave in a similar way to how
5393 * an empty certlabel is treated - i.e. don't fail now but rather continue
5394 * as though the certid wasn't specified.
5395 */
5396 if (idopts->cert_id_string != NULL && strlen(idopts->cert_id_string) != 0) {
5397 BIGNUM *bn = NULL;
5398 BN_hex2bn(&bn, idopts->cert_id_string);
5399 if (bn == NULL)
5400 return ENOMEM;
5401 id_cryptoctx->cert_id_len = BN_num_bytes(bn);
5402 id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
5403 if (id_cryptoctx->cert_id == NULL) {
5404 BN_free(bn);
5405 return ENOMEM;
5406 }
5407 BN_bn2bin(bn, id_cryptoctx->cert_id);
5408 BN_free(bn);
5409 }
5410 id_cryptoctx->slotid = idopts->slotid;
5411 id_cryptoctx->pkcs11_method = 1;
5412
5413 #ifndef PKINIT_USE_MECH_LIST
5414 /*
5415 * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
5416 * many cards seems to be confused about whether they are capable of
5417 * this or not. The safe thing seems to be to ignore the mechanism list,
5418 * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
5419 */
5420
5421 id_cryptoctx->mech = CKM_RSA_PKCS;
5422 #else
5423 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, NULL,
5424 &count)) != CKR_OK || count <= 0) {
5425 pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r));
5426 return KRB5KDC_ERR_PREAUTH_FAILED;
5427 }
5428 mechp = (CK_MECHANISM_TYPE_PTR) malloc(count * sizeof (CK_MECHANISM_TYPE));
5429 if (mechp == NULL)
5430 return ENOMEM;
5431 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid,
5432 mechp, &count)) != CKR_OK) {
5433 free(mechp);
5434 return KRB5KDC_ERR_PREAUTH_FAILED;
5435 }
5436 for (i = 0; i < count; i++) {
5437 if ((r = id_cryptoctx->p11->C_GetMechanismInfo(id_cryptoctx->slotid,
5438 mechp[i], &info)) != CKR_OK) {
5439 free(mechp);
5440 return KRB5KDC_ERR_PREAUTH_FAILED;
5441 }
5442 #ifdef DEBUG_MECHINFO
5443 pkiDebug("mech %x flags %x\n", (int) mechp[i], (int) info.flags);
5444 if ((info.flags & (CKF_SIGN|CKF_DECRYPT)) == (CKF_SIGN|CKF_DECRYPT))
5445 pkiDebug(" this mech is good for sign & decrypt\n");
5446 #endif
5447 if (mechp[i] == CKM_RSA_PKCS) {
5448 /* This seems backwards... */
5449 id_cryptoctx->mech =
5450 (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
5451 }
5452 }
5453 free(mechp);
5454
5455 pkiDebug("got %d mechs from card\n", (int) count);
5456 #endif
5457
5458 return (pkinit_open_session(context, plg_cryptoctx, req_cryptoctx,
5459 id_cryptoctx, princ, do_matching));
5460 }
5461 #endif
5462
5463 /* ARGSUSED */
5464 static void
5465 free_cred_info(krb5_context context,
5466 pkinit_identity_crypto_context id_cryptoctx,
5467 struct _pkinit_cred_info *cred)
5468 {
5469 if (cred != NULL) {
5470 if (cred->cert != NULL)
5471 X509_free(cred->cert);
5472 if (cred->key != NULL)
5473 EVP_PKEY_free(cred->key);
5474 #ifndef WITHOUT_PKCS11
5475 if (cred->cert_id != NULL)
5476 free(cred->cert_id);
5477 #endif
5478 free(cred);
5479 }
5480 }
5481
5482 /* ARGSUSED */
5483 krb5_error_code
5484 crypto_free_cert_info(krb5_context context,
5485 pkinit_plg_crypto_context plg_cryptoctx,
5486 pkinit_req_crypto_context req_cryptoctx,
5487 pkinit_identity_crypto_context id_cryptoctx)
5488 {
5489 int i;
5490
5491 if (id_cryptoctx == NULL)
5492 return EINVAL;
5493
5494 for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
5495 if (id_cryptoctx->creds[i] != NULL) {
5496 free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]);
5497 id_cryptoctx->creds[i] = NULL;
5498 }
5499 }
5500 return 0;
5501 }
5502
5503 krb5_error_code
5504 crypto_load_certs(krb5_context context,
5505 pkinit_plg_crypto_context plg_cryptoctx,
5506 pkinit_req_crypto_context req_cryptoctx,
5507 pkinit_identity_opts *idopts,
5508 pkinit_identity_crypto_context id_cryptoctx,
5509 krb5_principal princ,
5510 int do_matching)
5511 {
5512 krb5_error_code retval;
5513
5514 switch(idopts->idtype) {
5515 case IDTYPE_FILE:
5516 retval = pkinit_get_certs_fs(context, plg_cryptoctx,
5517 req_cryptoctx, idopts,
5518 id_cryptoctx, princ);
5519 break;
5520 case IDTYPE_DIR:
5521 retval = pkinit_get_certs_dir(context, plg_cryptoctx,
5522 req_cryptoctx, idopts,
5523 id_cryptoctx, princ);
5524 break;
5525 #ifndef WITHOUT_PKCS11
5526 case IDTYPE_PKCS11:
5527 retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx,
5528 req_cryptoctx, idopts,
5529 id_cryptoctx, princ, do_matching);
5530 break;
5531 #endif
5532 case IDTYPE_PKCS12:
5533 retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx,
5534 req_cryptoctx, idopts,
5535 id_cryptoctx, princ);
5536 break;
5537 default:
5538 retval = EINVAL;
5539 }
5540 /* Solaris Kerberos */
5541
5542 return retval;
5543 }
5544
5545 /*
5546 * Get number of certificates available after crypto_load_certs()
5547 */
5548 /* ARGSUSED */
5549 krb5_error_code
5550 crypto_cert_get_count(krb5_context context,
5551 pkinit_plg_crypto_context plg_cryptoctx,
5552 pkinit_req_crypto_context req_cryptoctx,
5553 pkinit_identity_crypto_context id_cryptoctx,
5554 int *cert_count)
5555 {
5556 int count;
5557
5558 if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
5559 return EINVAL;
5560
5561 for (count = 0;
5562 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
5563 count++);
5564 *cert_count = count;
5565 return 0;
5566 }
5567
5568
5569 /*
5570 * Begin iteration over the certs loaded in crypto_load_certs()
5571 */
5572 /* ARGSUSED */
5573 krb5_error_code
5574 crypto_cert_iteration_begin(krb5_context context,
5575 pkinit_plg_crypto_context plg_cryptoctx,
5576 pkinit_req_crypto_context req_cryptoctx,
5577 pkinit_identity_crypto_context id_cryptoctx,
5578 pkinit_cert_iter_handle *ih_ret)
5579 {
5580 struct _pkinit_cert_iter_data *id;
5581
5582 if (id_cryptoctx == NULL || ih_ret == NULL)
5583 return EINVAL;
5584 if (id_cryptoctx->creds[0] == NULL) /* No cred info available */
5585 return ENOENT;
5586
5587 id = calloc(1, sizeof(*id));
5588 if (id == NULL)
5589 return ENOMEM;
5590 id->magic = ITER_MAGIC;
5591 id->plgctx = plg_cryptoctx,
5592 id->reqctx = req_cryptoctx,
5593 id->idctx = id_cryptoctx;
5594 id->index = 0;
5595 *ih_ret = (pkinit_cert_iter_handle) id;
5596 return 0;
5597 }
5598
5599 /*
5600 * End iteration over the certs loaded in crypto_load_certs()
5601 */
5602 /* ARGSUSED */
5603 krb5_error_code
5604 crypto_cert_iteration_end(krb5_context context,
5605 pkinit_cert_iter_handle ih)
5606 {
5607 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
5608
5609 if (id == NULL || id->magic != ITER_MAGIC)
5610 return EINVAL;
5611 free(ih);
5612 return 0;
5613 }
5614
5615 /*
5616 * Get next certificate handle
5617 */
5618 /* ARGSUSED */
5619 krb5_error_code
5620 crypto_cert_iteration_next(krb5_context context,
5621 pkinit_cert_iter_handle ih,
5622 pkinit_cert_handle *ch_ret)
5623 {
5624 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
5625 struct _pkinit_cert_data *cd;
5626 pkinit_identity_crypto_context id_cryptoctx;
5627
5628 if (id == NULL || id->magic != ITER_MAGIC)
5629 return EINVAL;
5630
5631 if (ch_ret == NULL)
5632 return EINVAL;
5633
5634 id_cryptoctx = id->idctx;
5635 if (id_cryptoctx == NULL)
5636 return EINVAL;
5637
5638 if (id_cryptoctx->creds[id->index] == NULL)
5639 return PKINIT_ITER_NO_MORE;
5640
5641 cd = calloc(1, sizeof(*cd));
5642 if (cd == NULL)
5643 return ENOMEM;
5644
5645 cd->magic = CERT_MAGIC;
5646 cd->plgctx = id->plgctx;
5647 cd->reqctx = id->reqctx;
5648 cd->idctx = id->idctx;
5649 cd->index = id->index;
5650 cd->cred = id_cryptoctx->creds[id->index++];
5651 *ch_ret = (pkinit_cert_handle)cd;
5652 return 0;
5653 }
5654
5655 /*
5656 * Release cert handle
5657 */
5658 /* ARGSUSED */
5659 krb5_error_code
5660 crypto_cert_release(krb5_context context,
5661 pkinit_cert_handle ch)
5662 {
5663 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
5664 if (cd == NULL || cd->magic != CERT_MAGIC)
5665 return EINVAL;
5666 free(cd);
5667 return 0;
5668 }
5669
5670 /*
5671 * Get certificate Key Usage and Extended Key Usage
5672 */
5673 /* ARGSUSED */
5674 static krb5_error_code
5675 crypto_retieve_X509_key_usage(krb5_context context,
5676 pkinit_plg_crypto_context plgcctx,
5677 pkinit_req_crypto_context reqcctx,
5678 X509 *x,
5679 unsigned int *ret_ku_bits,
5680 unsigned int *ret_eku_bits)
5681 {
5682 /* Solaris Kerberos */
5683 int i;
5684 unsigned int eku_bits = 0, ku_bits = 0;
5685 ASN1_BIT_STRING *usage = NULL;
5686
5687 if (ret_ku_bits == NULL && ret_eku_bits == NULL)
5688 return EINVAL;
5689
5690 if (ret_eku_bits)
5691 *ret_eku_bits = 0;
5692 else {
5693 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__);
5694 goto check_kus;
5695 }
5696
5697 /* Start with Extended Key usage */
5698 i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
5699 if (i >= 0) {
5700 EXTENDED_KEY_USAGE *eku;
5701
5702 eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
5703 if (eku) {
5704 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
5705 ASN1_OBJECT *certoid;
5706 certoid = sk_ASN1_OBJECT_value(eku, i);
5707 if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0)
5708 eku_bits |= PKINIT_EKU_PKINIT;
5709 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0)
5710 eku_bits |= PKINIT_EKU_MSSCLOGIN;
5711 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0)
5712 eku_bits |= PKINIT_EKU_CLIENTAUTH;
5713 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0)
5714 eku_bits |= PKINIT_EKU_EMAILPROTECTION;
5715 }
5716 EXTENDED_KEY_USAGE_free(eku);
5717 }
5718 }
5719 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits);
5720 *ret_eku_bits = eku_bits;
5721
5722 check_kus:
5723 /* Now the Key Usage bits */
5724 if (ret_ku_bits)
5725 *ret_ku_bits = 0;
5726 else {
5727 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__);
5728 goto out;
5729 }
5730
5731 /* Make sure usage exists before checking bits */
5732 usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL);
5733 if (usage) {
5734 if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
5735 ku_bits |= PKINIT_KU_DIGITALSIGNATURE;
5736 if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT))
5737 ku_bits |= PKINIT_KU_KEYENCIPHERMENT;
5738 ASN1_BIT_STRING_free(usage);
5739 }
5740
5741 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits);
5742 *ret_ku_bits = ku_bits;
5743
5744 out:
5745 return 0;
5746 }
5747
5748 /*
5749 * Return a string format of an X509_NAME in buf where
5750 * size is an in/out parameter. On input it is the size
5751 * of the buffer, and on output it is the actual length
5752 * of the name.
5753 * If buf is NULL, returns the length req'd to hold name
5754 */
5755 static char *
5756 X509_NAME_oneline_ex(X509_NAME * a,
5757 char *buf,
5758 unsigned int *size,
5759 unsigned long flag)
5760 {
5761 BIO *out = NULL;
5762
5763 out = BIO_new(BIO_s_mem ());
5764 if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
5765 if (buf != NULL && *size > (int) BIO_number_written(out)) {
5766 (void) memset(buf, 0, *size);
5767 BIO_read(out, buf, (int) BIO_number_written(out));
5768 }
5769 else {
5770 *size = BIO_number_written(out);
5771 }
5772 }
5773 BIO_free(out);
5774 return (buf);
5775 }
5776
5777 /*
5778 * Get certificate information
5779 */
5780 krb5_error_code
5781 crypto_cert_get_matching_data(krb5_context context,
5782 pkinit_cert_handle ch,
5783 pkinit_cert_matching_data **ret_md)
5784 {
5785 krb5_error_code retval;
5786 pkinit_cert_matching_data *md;
5787 krb5_principal *pkinit_sans =NULL, *upn_sans = NULL;
5788 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
5789 int i, j;
5790 char buf[DN_BUF_LEN];
5791 unsigned int bufsize = sizeof(buf);
5792
5793 if (cd == NULL || cd->magic != CERT_MAGIC)
5794 return EINVAL;
5795 if (ret_md == NULL)
5796 return EINVAL;
5797
5798 md = calloc(1, sizeof(*md));
5799 if (md == NULL)
5800 return ENOMEM;
5801
5802 md->ch = ch;
5803
5804 /* get the subject name (in rfc2253 format) */
5805 X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert),
5806 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
5807 md->subject_dn = strdup(buf);
5808 if (md->subject_dn == NULL) {
5809 retval = ENOMEM;
5810 goto cleanup;
5811 }
5812
5813 /* get the issuer name (in rfc2253 format) */
5814 X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert),
5815 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
5816 md->issuer_dn = strdup(buf);
5817 if (md->issuer_dn == NULL) {
5818 retval = ENOMEM;
5819 goto cleanup;
5820 }
5821
5822 /* get the san data */
5823 retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,
5824 cd->cred->cert, &pkinit_sans,
5825 &upn_sans, NULL);
5826 if (retval)
5827 goto cleanup;
5828
5829 j = 0;
5830 if (pkinit_sans != NULL) {
5831 for (i = 0; pkinit_sans[i] != NULL; i++)
5832 j++;
5833 }
5834 if (upn_sans != NULL) {
5835 for (i = 0; upn_sans[i] != NULL; i++)
5836 j++;
5837 }
5838 if (j != 0) {
5839 md->sans = calloc((size_t)j+1, sizeof(*md->sans));
5840 if (md->sans == NULL) {
5841 retval = ENOMEM;
5842 goto cleanup;
5843 }
5844 j = 0;
5845 if (pkinit_sans != NULL) {
5846 for (i = 0; pkinit_sans[i] != NULL; i++)
5847 md->sans[j++] = pkinit_sans[i];
5848 free(pkinit_sans);
5849 }
5850 if (upn_sans != NULL) {
5851 for (i = 0; upn_sans[i] != NULL; i++)
5852 md->sans[j++] = upn_sans[i];
5853 free(upn_sans);
5854 }
5855 md->sans[j] = NULL;
5856 } else
5857 md->sans = NULL;
5858
5859 /* get the KU and EKU data */
5860
5861 retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx,
5862 cd->cred->cert,
5863 &md->ku_bits, &md->eku_bits);
5864 if (retval)
5865 goto cleanup;
5866
5867 *ret_md = md;
5868 retval = 0;
5869 cleanup:
5870 if (retval) {
5871 if (md)
5872 crypto_cert_free_matching_data(context, md);
5873 }
5874 return retval;
5875 }
5876
5877 /*
5878 * Free certificate information
5879 */
5880 krb5_error_code
5881 crypto_cert_free_matching_data(krb5_context context,
5882 pkinit_cert_matching_data *md)
5883 {
5884 krb5_principal p;
5885 int i;
5886
5887 if (md == NULL)
5888 return EINVAL;
5889 if (md->subject_dn)
5890 free(md->subject_dn);
5891 if (md->issuer_dn)
5892 free(md->issuer_dn);
5893 if (md->sans) {
5894 for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i])
5895 krb5_free_principal(context, p);
5896 free(md->sans);
5897 }
5898 free(md);
5899 return 0;
5900 }
5901
5902 /*
5903 * Make this matching certificate "the chosen one"
5904 */
5905 /* ARGSUSED */
5906 krb5_error_code
5907 crypto_cert_select(krb5_context context,
5908 pkinit_cert_matching_data *md)
5909 {
5910 struct _pkinit_cert_data *cd;
5911 if (md == NULL)
5912 return EINVAL;
5913
5914 cd = (struct _pkinit_cert_data *)md->ch;
5915 if (cd == NULL || cd->magic != CERT_MAGIC)
5916 return EINVAL;
5917
5918 /* copy the selected cert into our id_cryptoctx */
5919 if (cd->idctx->my_certs != NULL) {
5920 sk_X509_pop_free(cd->idctx->my_certs, X509_free);
5921 }
5922 cd->idctx->my_certs = sk_X509_new_null();
5923 sk_X509_push(cd->idctx->my_certs, cd->cred->cert);
5924 cd->idctx->creds[cd->index]->cert = NULL; /* Don't free it twice */
5925 cd->idctx->cert_index = 0;
5926
5927 if (cd->idctx->pkcs11_method != 1) {
5928 cd->idctx->my_key = cd->cred->key;
5929 cd->idctx->creds[cd->index]->key = NULL; /* Don't free it twice */
5930 }
5931 #ifndef WITHOUT_PKCS11
5932 else {
5933 cd->idctx->cert_id = cd->cred->cert_id;
5934 cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */
5935 cd->idctx->cert_id_len = cd->cred->cert_id_len;
5936 }
5937 #endif
5938 return 0;
5939 }
5940
5941 /*
5942 * Choose the default certificate as "the chosen one"
5943 */
5944 krb5_error_code
5945 crypto_cert_select_default(krb5_context context,
5946 pkinit_plg_crypto_context plg_cryptoctx,
5947 pkinit_req_crypto_context req_cryptoctx,
5948 pkinit_identity_crypto_context id_cryptoctx)
5949 {
5950 krb5_error_code retval;
5951 int cert_count = 0;
5952
5953 retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
5954 id_cryptoctx, &cert_count);
5955 if (retval) {
5956 pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
5957 __FUNCTION__, retval, error_message(retval));
5958 goto errout;
5959 }
5960 if (cert_count != 1) {
5961 /* Solaris Kerberos: Improved error messages */
5962 retval = EINVAL;
5963 krb5_set_error_message(context, retval,
5964 gettext("Failed to select default certificate: "
5965 "found %d certs to choose from but there must be exactly one"),
5966 cert_count);
5967 pkiDebug("%s: ERROR: There are %d certs to choose from, "
5968 "but there must be exactly one.\n",
5969 __FUNCTION__, cert_count);
5970 goto errout;
5971 }
5972 /* copy the selected cert into our id_cryptoctx */
5973 if (id_cryptoctx->my_certs != NULL) {
5974 sk_X509_pop_free(id_cryptoctx->my_certs, X509_free);
5975 }
5976 id_cryptoctx->my_certs = sk_X509_new_null();
5977 sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert);
5978 id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */
5979 id_cryptoctx->cert_index = 0;
5980
5981 if (id_cryptoctx->pkcs11_method != 1) {
5982 id_cryptoctx->my_key = id_cryptoctx->creds[0]->key;
5983 id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */
5984 }
5985 #ifndef WITHOUT_PKCS11
5986 else {
5987 id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id;
5988 id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */
5989 id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len;
5990 }
5991 #endif
5992 retval = 0;
5993 errout:
5994 return retval;
5995 }
5996
5997
5998 /* ARGSUSED */
5999 static krb5_error_code
6000 load_cas_and_crls(krb5_context context,
6001 pkinit_plg_crypto_context plg_cryptoctx,
6002 pkinit_req_crypto_context req_cryptoctx,
6003 pkinit_identity_crypto_context id_cryptoctx,
6004 int catype,
6005 char *filename)
6006 {
6007 STACK_OF(X509_INFO) *sk = NULL;
6008 STACK_OF(X509) *ca_certs = NULL;
6009 STACK_OF(X509_CRL) *ca_crls = NULL;
6010 BIO *in = NULL;
6011 /* Solaris Kerberos */
6012 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
6013 int i = 0;
6014
6015 /* If there isn't already a stack in the context,
6016 * create a temporary one now */
6017 switch(catype) {
6018 case CATYPE_ANCHORS:
6019 if (id_cryptoctx->trustedCAs != NULL)
6020 ca_certs = id_cryptoctx->trustedCAs;
6021 else {
6022 ca_certs = sk_X509_new_null();
6023 if (ca_certs == NULL)
6024 return ENOMEM;
6025 }
6026 break;
6027 case CATYPE_INTERMEDIATES:
6028 if (id_cryptoctx->intermediateCAs != NULL)
6029 ca_certs = id_cryptoctx->intermediateCAs;
6030 else {
6031 ca_certs = sk_X509_new_null();
6032 if (ca_certs == NULL)
6033 return ENOMEM;
6034 }
6035 break;
6036 case CATYPE_CRLS:
6037 if (id_cryptoctx->revoked != NULL)
6038 ca_crls = id_cryptoctx->revoked;
6039 else {
6040 ca_crls = sk_X509_CRL_new_null();
6041 if (ca_crls == NULL)
6042 return ENOMEM;
6043 }
6044 break;
6045 default:
6046 return ENOTSUP;
6047 }
6048
6049 if (!(in = BIO_new_file(filename, "r"))) {
6050 retval = errno;
6051 pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__,
6052 filename, error_message(errno));
6053 goto cleanup;
6054 }
6055
6056 /* This loads from a file, a stack of x509/crl/pkey sets */
6057 if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) {
6058 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename);
6059 retval = EIO;
6060 goto cleanup;
6061 }
6062
6063 /* scan over the stack created from loading the file contents,
6064 * weed out duplicates, and push new ones onto the return stack
6065 */
6066 for (i = 0; i < sk_X509_INFO_num(sk); i++) {
6067 X509_INFO *xi = sk_X509_INFO_value(sk, i);
6068 if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) {
6069 int j = 0, size = sk_X509_num(ca_certs), flag = 0;
6070
6071 if (!size) {
6072 sk_X509_push(ca_certs, xi->x509);
6073 xi->x509 = NULL;
6074 continue;
6075 }
6076 for (j = 0; j < size; j++) {
6077 X509 *x = sk_X509_value(ca_certs, j);
6078 flag = X509_cmp(x, xi->x509);
6079 if (flag == 0)
6080 break;
6081 else
6082 continue;
6083 }
6084 if (flag != 0) {
6085 sk_X509_push(ca_certs, X509_dup(xi->x509));
6086 }
6087 } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) {
6088 int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0;
6089 if (!size) {
6090 sk_X509_CRL_push(ca_crls, xi->crl);
6091 xi->crl = NULL;
6092 continue;
6093 }
6094 for (j = 0; j < size; j++) {
6095 X509_CRL *x = sk_X509_CRL_value(ca_crls, j);
6096 flag = X509_CRL_cmp(x, xi->crl);
6097 if (flag == 0)
6098 break;
6099 else
6100 continue;
6101 }
6102 if (flag != 0) {
6103 sk_X509_CRL_push(ca_crls, X509_CRL_dup(xi->crl));
6104 }
6105 }
6106 }
6107
6108 /* If we added something and there wasn't a stack in the
6109 * context before, add the temporary stack to the context.
6110 */
6111 switch(catype) {
6112 case CATYPE_ANCHORS:
6113 if (sk_X509_num(ca_certs) == 0) {
6114 pkiDebug("no anchors in file, %s\n", filename);
6115 if (id_cryptoctx->trustedCAs == NULL)
6116 sk_X509_free(ca_certs);
6117 } else {
6118 if (id_cryptoctx->trustedCAs == NULL)
6119 id_cryptoctx->trustedCAs = ca_certs;
6120 }
6121 break;
6122 case CATYPE_INTERMEDIATES:
6123 if (sk_X509_num(ca_certs) == 0) {
6124 pkiDebug("no intermediates in file, %s\n", filename);
6125 if (id_cryptoctx->intermediateCAs == NULL)
6126 sk_X509_free(ca_certs);
6127 } else {
6128 if (id_cryptoctx->intermediateCAs == NULL)
6129 id_cryptoctx->intermediateCAs = ca_certs;
6130 }
6131 break;
6132 case CATYPE_CRLS:
6133 if (sk_X509_CRL_num(ca_crls) == 0) {
6134 pkiDebug("no crls in file, %s\n", filename);
6135 if (id_cryptoctx->revoked == NULL)
6136 sk_X509_CRL_free(ca_crls);
6137 } else {
6138 if (id_cryptoctx->revoked == NULL)
6139 id_cryptoctx->revoked = ca_crls;
6140 }
6141 break;
6142 default:
6143 /* Should have been caught above! */
6144 retval = EINVAL;
6145 goto cleanup;
6146 /* Solaris Kerberos: removed "break" as it's never reached */
6147 }
6148
6149 retval = 0;
6150
6151 cleanup:
6152 if (in != NULL)
6153 BIO_free(in);
6154 if (sk != NULL)
6155 sk_X509_INFO_pop_free(sk, X509_INFO_free);
6156
6157 return retval;
6158 }
6159
6160 static krb5_error_code
6161 load_cas_and_crls_dir(krb5_context context,
6162 pkinit_plg_crypto_context plg_cryptoctx,
6163 pkinit_req_crypto_context req_cryptoctx,
6164 pkinit_identity_crypto_context id_cryptoctx,
6165 int catype,
6166 char *dirname)
6167 {
6168 krb5_error_code retval = EINVAL;
6169 DIR *d = NULL;
6170 struct dirent *dentry = NULL;
6171 char filename[1024];
6172
6173 if (dirname == NULL)
6174 return EINVAL;
6175
6176 d = opendir(dirname);
6177 if (d == NULL)
6178 return ENOENT;
6179
6180 while ((dentry = readdir(d))) {
6181 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) {
6182 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
6183 __FUNCTION__, dirname, dentry->d_name);
6184 goto cleanup;
6185 }
6186 /* Ignore subdirectories and anything starting with a dot */
6187 #ifdef DT_DIR
6188 if (dentry->d_type == DT_DIR)
6189 continue;
6190 #endif
6191 if (dentry->d_name[0] == '.')
6192 continue;
6193 (void) snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
6194
6195 retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
6196 id_cryptoctx, catype, filename);
6197 if (retval)
6198 goto cleanup;
6199 }
6200
6201 retval = 0;
6202
6203 cleanup:
6204 if (d != NULL)
6205 (void) closedir(d);
6206
6207 return retval;
6208 }
6209
6210 /* ARGSUSED */
6211 krb5_error_code
6212 crypto_load_cas_and_crls(krb5_context context,
6213 pkinit_plg_crypto_context plg_cryptoctx,
6214 pkinit_req_crypto_context req_cryptoctx,
6215 pkinit_identity_opts *idopts,
6216 pkinit_identity_crypto_context id_cryptoctx,
6217 int idtype,
6218 int catype,
6219 char *id)
6220 {
6221 pkiDebug("%s: called with idtype %s and catype %s\n",
6222 __FUNCTION__, idtype2string(idtype), catype2string(catype));
6223 /* Solaris Kerberos: Removed "break"'s as they are never reached */
6224 switch (idtype) {
6225 case IDTYPE_FILE:
6226 return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
6227 id_cryptoctx, catype, id);
6228 case IDTYPE_DIR:
6229 return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
6230 id_cryptoctx, catype, id);
6231 default:
6232 return ENOTSUP;
6233 }
6234 }
6235
6236 static krb5_error_code
6237 create_identifiers_from_stack(STACK_OF(X509) *sk,
6238 krb5_external_principal_identifier *** ids)
6239 {
6240 krb5_error_code retval = ENOMEM;
6241 int i = 0, sk_size = sk_X509_num(sk);
6242 krb5_external_principal_identifier **krb5_cas = NULL;
6243 X509 *x = NULL;
6244 X509_NAME *xn = NULL;
6245 unsigned char *p = NULL;
6246 int len = 0;
6247 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6248 char buf[DN_BUF_LEN];
6249
6250 *ids = NULL;
6251
6252 krb5_cas =
6253 malloc((sk_size + 1) * sizeof(krb5_external_principal_identifier *));
6254 if (krb5_cas == NULL)
6255 return ENOMEM;
6256 krb5_cas[sk_size] = NULL;
6257
6258 for (i = 0; i < sk_size; i++) {
6259 krb5_cas[i] = (krb5_external_principal_identifier *)malloc(sizeof(krb5_external_principal_identifier));
6260
6261 x = sk_X509_value(sk, i);
6262
6263 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
6264 pkiDebug("#%d cert= %s\n", i, buf);
6265
6266 /* fill-in subjectName */
6267 krb5_cas[i]->subjectName.magic = 0;
6268 krb5_cas[i]->subjectName.length = 0;
6269 krb5_cas[i]->subjectName.data = NULL;
6270
6271 xn = X509_get_subject_name(x);
6272 len = i2d_X509_NAME(xn, NULL);
6273 if ((p = krb5_cas[i]->subjectName.data = (unsigned char *)malloc((size_t) len)) == NULL)
6274 goto cleanup;
6275 i2d_X509_NAME(xn, &p);
6276 krb5_cas[i]->subjectName.length = len;
6277
6278 /* fill-in issuerAndSerialNumber */
6279 krb5_cas[i]->issuerAndSerialNumber.length = 0;
6280 krb5_cas[i]->issuerAndSerialNumber.magic = 0;
6281 krb5_cas[i]->issuerAndSerialNumber.data = NULL;
6282
6283 #ifdef LONGHORN_BETA_COMPAT
6284 if (longhorn == 0) { /* XXX Longhorn doesn't like this */
6285 #endif
6286 is = PKCS7_ISSUER_AND_SERIAL_new();
6287 X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
6288 ASN1_INTEGER_free(is->serial);
6289 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
6290 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
6291 if ((p = krb5_cas[i]->issuerAndSerialNumber.data =
6292 (unsigned char *)malloc((size_t) len)) == NULL)
6293 goto cleanup;
6294 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
6295 krb5_cas[i]->issuerAndSerialNumber.length = len;
6296 #ifdef LONGHORN_BETA_COMPAT
6297 }
6298 #endif
6299
6300 /* fill-in subjectKeyIdentifier */
6301 krb5_cas[i]->subjectKeyIdentifier.length = 0;
6302 krb5_cas[i]->subjectKeyIdentifier.magic = 0;
6303 krb5_cas[i]->subjectKeyIdentifier.data = NULL;
6304
6305
6306 #ifdef LONGHORN_BETA_COMPAT
6307 if (longhorn == 0) { /* XXX Longhorn doesn't like this */
6308 #endif
6309 if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
6310 ASN1_OCTET_STRING *ikeyid = NULL;
6311
6312 if ((ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
6313 NULL))) {
6314 len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
6315 if ((p = krb5_cas[i]->subjectKeyIdentifier.data =
6316 (unsigned char *)malloc((size_t) len)) == NULL)
6317 goto cleanup;
6318 i2d_ASN1_OCTET_STRING(ikeyid, &p);
6319 krb5_cas[i]->subjectKeyIdentifier.length = len;
6320 }
6321 if (ikeyid != NULL)
6322 ASN1_OCTET_STRING_free(ikeyid);
6323 }
6324 #ifdef LONGHORN_BETA_COMPAT
6325 }
6326 #endif
6327 if (is != NULL) {
6328 if (is->issuer != NULL)
6329 X509_NAME_free(is->issuer);
6330 if (is->serial != NULL)
6331 ASN1_INTEGER_free(is->serial);
6332 free(is);
6333 }
6334 }
6335
6336 *ids = krb5_cas;
6337
6338 retval = 0;
6339 cleanup:
6340 if (retval)
6341 free_krb5_external_principal_identifier(&krb5_cas);
6342
6343 return retval;
6344 }
6345
6346 /* ARGSUSED */
6347 static krb5_error_code
6348 create_krb5_invalidCertificates(krb5_context context,
6349 pkinit_plg_crypto_context plg_cryptoctx,
6350 pkinit_req_crypto_context req_cryptoctx,
6351 pkinit_identity_crypto_context id_cryptoctx,
6352 krb5_external_principal_identifier *** ids)
6353 {
6354
6355 krb5_error_code retval = ENOMEM;
6356 STACK_OF(X509) *sk = NULL;
6357
6358 *ids = NULL;
6359 if (req_cryptoctx->received_cert == NULL)
6360 return KRB5KDC_ERR_PREAUTH_FAILED;
6361
6362 sk = sk_X509_new_null();
6363 if (sk == NULL)
6364 goto cleanup;
6365 sk_X509_push(sk, req_cryptoctx->received_cert);
6366
6367 retval = create_identifiers_from_stack(sk, ids);
6368
6369 sk_X509_free(sk);
6370 cleanup:
6371
6372 return retval;
6373 }
6374
6375 /* ARGSUSED */
6376 krb5_error_code
6377 create_krb5_supportedCMSTypes(krb5_context context,
6378 pkinit_plg_crypto_context plg_cryptoctx,
6379 pkinit_req_crypto_context req_cryptoctx,
6380 pkinit_identity_crypto_context id_cryptoctx,
6381 krb5_algorithm_identifier ***oids)
6382 {
6383
6384 krb5_error_code retval = ENOMEM;
6385 krb5_algorithm_identifier **loids = NULL;
6386 krb5_octet_data des3oid = {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
6387
6388 *oids = NULL;
6389 loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
6390 if (loids == NULL)
6391 goto cleanup;
6392 loids[1] = NULL;
6393 loids[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
6394 if (loids[0] == NULL) {
6395 free(loids);
6396 goto cleanup;
6397 }
6398 retval = pkinit_copy_krb5_octet_data(&loids[0]->algorithm, &des3oid);
6399 if (retval) {
6400 free(loids[0]);
6401 free(loids);
6402 goto cleanup;
6403 }
6404 loids[0]->parameters.length = 0;
6405 loids[0]->parameters.data = NULL;
6406
6407 *oids = loids;
6408 retval = 0;
6409 cleanup:
6410
6411 return retval;
6412 }
6413
6414 /* ARGSUSED */
6415 krb5_error_code
6416 create_krb5_trustedCertifiers(krb5_context context,
6417 pkinit_plg_crypto_context plg_cryptoctx,
6418 pkinit_req_crypto_context req_cryptoctx,
6419 pkinit_identity_crypto_context id_cryptoctx,
6420 krb5_external_principal_identifier *** ids)
6421 {
6422
6423 /* Solaris Kerberos */
6424 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
6425
6426 *ids = NULL;
6427 if (id_cryptoctx->trustedCAs == NULL)
6428 return KRB5KDC_ERR_PREAUTH_FAILED;
6429
6430 return create_identifiers_from_stack(sk, ids);
6431
6432 }
6433
6434 /* ARGSUSED */
6435 krb5_error_code
6436 create_krb5_trustedCas(krb5_context context,
6437 pkinit_plg_crypto_context plg_cryptoctx,
6438 pkinit_req_crypto_context req_cryptoctx,
6439 pkinit_identity_crypto_context id_cryptoctx,
6440 int flag,
6441 krb5_trusted_ca *** ids)
6442 {
6443 krb5_error_code retval = ENOMEM;
6444 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
6445 int i = 0, len = 0, sk_size = sk_X509_num(sk);
6446 krb5_trusted_ca **krb5_cas = NULL;
6447 X509 *x = NULL;
6448 char buf[DN_BUF_LEN];
6449 X509_NAME *xn = NULL;
6450 unsigned char *p = NULL;
6451 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6452
6453 *ids = NULL;
6454 if (id_cryptoctx->trustedCAs == NULL)
6455 return KRB5KDC_ERR_PREAUTH_FAILED;
6456
6457 krb5_cas = malloc((sk_size + 1) * sizeof(krb5_trusted_ca *));
6458 if (krb5_cas == NULL)
6459 return ENOMEM;
6460 krb5_cas[sk_size] = NULL;
6461
6462 for (i = 0; i < sk_size; i++) {
6463 krb5_cas[i] = (krb5_trusted_ca *)malloc(sizeof(krb5_trusted_ca));
6464 if (krb5_cas[i] == NULL)
6465 goto cleanup;
6466 x = sk_X509_value(sk, i);
6467
6468 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
6469 pkiDebug("#%d cert= %s\n", i, buf);
6470
6471 switch (flag) {
6472 case choice_trusted_cas_principalName:
6473 krb5_cas[i]->choice = choice_trusted_cas_principalName;
6474 break;
6475 case choice_trusted_cas_caName:
6476 krb5_cas[i]->choice = choice_trusted_cas_caName;
6477 krb5_cas[i]->u.caName.data = NULL;
6478 krb5_cas[i]->u.caName.length = 0;
6479 xn = X509_get_subject_name(x);
6480 len = i2d_X509_NAME(xn, NULL);
6481 if ((p = krb5_cas[i]->u.caName.data =
6482 (unsigned char *)malloc((size_t) len)) == NULL)
6483 goto cleanup;
6484 i2d_X509_NAME(xn, &p);
6485 krb5_cas[i]->u.caName.length = len;
6486 break;
6487 case choice_trusted_cas_issuerAndSerial:
6488 krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial;
6489 krb5_cas[i]->u.issuerAndSerial.data = NULL;
6490 krb5_cas[i]->u.issuerAndSerial.length = 0;
6491 is = PKCS7_ISSUER_AND_SERIAL_new();
6492 X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
6493 ASN1_INTEGER_free(is->serial);
6494 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
6495 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
6496 if ((p = krb5_cas[i]->u.issuerAndSerial.data =
6497 (unsigned char *)malloc((size_t) len)) == NULL)
6498 goto cleanup;
6499 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
6500 krb5_cas[i]->u.issuerAndSerial.length = len;
6501 if (is != NULL) {
6502 if (is->issuer != NULL)
6503 X509_NAME_free(is->issuer);
6504 if (is->serial != NULL)
6505 ASN1_INTEGER_free(is->serial);
6506 free(is);
6507 }
6508 break;
6509 default: break;
6510 }
6511 }
6512 retval = 0;
6513 *ids = krb5_cas;
6514 cleanup:
6515 if (retval)
6516 free_krb5_trusted_ca(&krb5_cas);
6517
6518 return retval;
6519 }
6520
6521 /* ARGSUSED */
6522 krb5_error_code
6523 create_issuerAndSerial(krb5_context context,
6524 pkinit_plg_crypto_context plg_cryptoctx,
6525 pkinit_req_crypto_context req_cryptoctx,
6526 pkinit_identity_crypto_context id_cryptoctx,
6527 unsigned char **out,
6528 unsigned int *out_len)
6529 {
6530 unsigned char *p = NULL;
6531 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6532 int len = 0;
6533 krb5_error_code retval = ENOMEM;
6534 X509 *cert = req_cryptoctx->received_cert;
6535
6536 *out = NULL;
6537 *out_len = 0;
6538 if (req_cryptoctx->received_cert == NULL)
6539 return 0;
6540
6541 is = PKCS7_ISSUER_AND_SERIAL_new();
6542 X509_NAME_set(&is->issuer, X509_get_issuer_name(cert));
6543 ASN1_INTEGER_free(is->serial);
6544 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert));
6545 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
6546 if ((p = *out = (unsigned char *)malloc((size_t) len)) == NULL)
6547 goto cleanup;
6548 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
6549 *out_len = len;
6550 retval = 0;
6551
6552 cleanup:
6553 X509_NAME_free(is->issuer);
6554 ASN1_INTEGER_free(is->serial);
6555 free(is);
6556
6557 return retval;
6558 }
6559
6560 static int
6561 pkcs7_decrypt(krb5_context context,
6562 pkinit_identity_crypto_context id_cryptoctx,
6563 PKCS7 *p7,
6564 BIO *data)
6565 {
6566 BIO *tmpmem = NULL;
6567 /* Solaris Kerberos */
6568 int i = 0;
6569 char buf[4096];
6570
6571 if(p7 == NULL)
6572 return 0;
6573
6574 if(!PKCS7_type_is_enveloped(p7)) {
6575 pkiDebug("wrong pkcs7 content type\n");
6576 return 0;
6577 }
6578
6579 if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) {
6580 pkiDebug("unable to decrypt pkcs7 object\n");
6581 return 0;
6582 }
6583 /* Solaris Kerberos: Suppress sun studio compiler warning */
6584 #pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED)
6585 for(;;) {
6586 i = BIO_read(tmpmem, buf, sizeof(buf));
6587 if (i <= 0) break;
6588 BIO_write(data, buf, i);
6589 BIO_free_all(tmpmem);
6590 return 1;
6591 }
6592 #pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED)
6593
6594 return 0;
6595 }
6596
6597 krb5_error_code
6598 pkinit_process_td_trusted_certifiers(
6599 krb5_context context,
6600 pkinit_plg_crypto_context plg_cryptoctx,
6601 pkinit_req_crypto_context req_cryptoctx,
6602 pkinit_identity_crypto_context id_cryptoctx,
6603 krb5_external_principal_identifier **krb5_trusted_certifiers,
6604 int td_type)
6605 {
6606 krb5_error_code retval = ENOMEM;
6607 STACK_OF(X509_NAME) *sk_xn = NULL;
6608 X509_NAME *xn = NULL;
6609 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6610 ASN1_OCTET_STRING *id = NULL;
6611 const unsigned char *p = NULL;
6612 char buf[DN_BUF_LEN];
6613 int i = 0;
6614
6615 if (td_type == TD_TRUSTED_CERTIFIERS)
6616 pkiDebug("received trusted certifiers\n");
6617 else
6618 pkiDebug("received invalid certificate\n");
6619
6620 sk_xn = sk_X509_NAME_new_null();
6621 while(krb5_trusted_certifiers[i] != NULL) {
6622 if (krb5_trusted_certifiers[i]->subjectName.data != NULL) {
6623 p = krb5_trusted_certifiers[i]->subjectName.data;
6624 xn = d2i_X509_NAME(NULL, &p,
6625 (int)krb5_trusted_certifiers[i]->subjectName.length);
6626 if (xn == NULL)
6627 goto cleanup;
6628 X509_NAME_oneline(xn, buf, sizeof(buf));
6629 if (td_type == TD_TRUSTED_CERTIFIERS)
6630 pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf);
6631 else
6632 pkiDebug("#%d cert = %s is invalid\n", i, buf);
6633 sk_X509_NAME_push(sk_xn, xn);
6634 }
6635
6636 if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) {
6637 p = krb5_trusted_certifiers[i]->issuerAndSerialNumber.data;
6638 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p,
6639 (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length);
6640 if (is == NULL)
6641 goto cleanup;
6642 X509_NAME_oneline(is->issuer, buf, sizeof(buf));
6643 if (td_type == TD_TRUSTED_CERTIFIERS)
6644 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i,
6645 buf, ASN1_INTEGER_get(is->serial));
6646 else
6647 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf,
6648 ASN1_INTEGER_get(is->serial));
6649 PKCS7_ISSUER_AND_SERIAL_free(is);
6650 }
6651
6652 if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) {
6653 p = krb5_trusted_certifiers[i]->subjectKeyIdentifier.data;
6654 id = d2i_ASN1_OCTET_STRING(NULL, &p,
6655 (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length);
6656 if (id == NULL)
6657 goto cleanup;
6658 /* XXX */
6659 ASN1_OCTET_STRING_free(id);
6660 }
6661 i++;
6662 }
6663 /* XXX Since we not doing anything with received trusted certifiers
6664 * return an error. this is the place where we can pick a different
6665 * client certificate based on the information in td_trusted_certifiers
6666 */
6667 retval = KRB5KDC_ERR_PREAUTH_FAILED;
6668 cleanup:
6669 if (sk_xn != NULL)
6670 sk_X509_NAME_pop_free(sk_xn, X509_NAME_free);
6671
6672 return retval;
6673 }
6674
6675 static BIO *
6676 pkcs7_dataDecode(krb5_context context,
6677 pkinit_identity_crypto_context id_cryptoctx,
6678 PKCS7 *p7)
6679 {
6680 int i = 0;
6681 unsigned int jj = 0, tmp_len = 0;
6682 BIO *out=NULL,*etmp=NULL,*bio=NULL;
6683 unsigned char *tmp=NULL;
6684 ASN1_OCTET_STRING *data_body=NULL;
6685 const EVP_CIPHER *evp_cipher=NULL;
6686 EVP_CIPHER_CTX *evp_ctx=NULL;
6687 X509_ALGOR *enc_alg=NULL;
6688 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
6689 /* Solaris Kerberos: Not used */
6690 #if 0
6691 X509_ALGOR *xalg=NULL;
6692 #endif
6693 PKCS7_RECIP_INFO *ri=NULL;
6694 X509 *cert = sk_X509_value(id_cryptoctx->my_certs,
6695 id_cryptoctx->cert_index);
6696
6697 p7->state=PKCS7_S_HEADER;
6698
6699 rsk=p7->d.enveloped->recipientinfo;
6700 enc_alg=p7->d.enveloped->enc_data->algorithm;
6701 data_body=p7->d.enveloped->enc_data->enc_data;
6702 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
6703 if (evp_cipher == NULL) {
6704 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
6705 goto cleanup;
6706 }
6707 /* Solaris Kerberos: Not used */
6708 #if 0
6709 xalg=p7->d.enveloped->enc_data->algorithm;
6710 #endif
6711
6712 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) {
6713 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
6714 goto cleanup;
6715 }
6716
6717 /* It was encrypted, we need to decrypt the secret key
6718 * with the private key */
6719
6720 /* Find the recipientInfo which matches the passed certificate
6721 * (if any)
6722 */
6723
6724 if (cert) {
6725 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
6726 int tmp_ret = 0;
6727 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
6728 tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
6729 X509_get_issuer_name(cert));
6730 if (!tmp_ret) {
6731 tmp_ret = ASN1_INTEGER_cmp(X509_get_serialNumber(cert),
6732 ri->issuer_and_serial->serial);
6733 if (!tmp_ret)
6734 break;
6735 }
6736 ri=NULL;
6737 }
6738 if (ri == NULL) {
6739 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
6740 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
6741 goto cleanup;
6742 }
6743 }
6744
6745 /* If we haven't got a certificate try each ri in turn */
6746
6747 if (cert == NULL) {
6748 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
6749 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
6750 jj = pkinit_decode_data(context, id_cryptoctx,
6751 (unsigned char *)ASN1_STRING_get0_data(ri->enc_key),
6752 ASN1_STRING_length(ri->enc_key),
6753 &tmp, &tmp_len);
6754 if (jj) {
6755 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
6756 goto cleanup;
6757 }
6758
6759 if (!jj && tmp_len > 0) {
6760 jj = tmp_len;
6761 break;
6762 }
6763
6764 ERR_clear_error();
6765 ri = NULL;
6766 }
6767
6768 if (ri == NULL) {
6769 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
6770 goto cleanup;
6771 }
6772 }
6773 else {
6774 jj = pkinit_decode_data(context, id_cryptoctx,
6775 (unsigned char *)ASN1_STRING_get0_data(ri->enc_key),
6776 ASN1_STRING_length(ri->enc_key),
6777 &tmp, &tmp_len);
6778 /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */
6779 if (jj || tmp_len == 0) {
6780 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
6781 goto cleanup;
6782 }
6783 jj = tmp_len;
6784 }
6785
6786 evp_ctx=NULL;
6787 BIO_get_cipher_ctx(etmp,&evp_ctx);
6788 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
6789 goto cleanup;
6790 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
6791 goto cleanup;
6792
6793 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
6794 /* Some S/MIME clients don't use the same key
6795 * and effective key length. The key length is
6796 * determined by the size of the decrypted RSA key.
6797 */
6798 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) {
6799 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
6800 PKCS7_R_DECRYPT_ERROR);
6801 goto cleanup;
6802 }
6803 }
6804 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
6805 goto cleanup;
6806
6807 OPENSSL_cleanse(tmp,jj);
6808
6809 if (out == NULL)
6810 out=etmp;
6811 else
6812 BIO_push(out,etmp);
6813 etmp=NULL;
6814
6815 if (data_body->length > 0)
6816 bio = BIO_new_mem_buf(data_body->data, data_body->length);
6817 else {
6818 bio=BIO_new(BIO_s_mem());
6819 BIO_set_mem_eof_return(bio,0);
6820 }
6821 BIO_push(out,bio);
6822 bio=NULL;
6823
6824 /* Solaris Kerberos */
6825 goto out;
6826
6827 cleanup:
6828 if (out != NULL) BIO_free_all(out);
6829 if (etmp != NULL) BIO_free_all(etmp);
6830 if (bio != NULL) BIO_free_all(bio);
6831 out=NULL;
6832
6833 out:
6834 if (tmp != NULL)
6835 free(tmp);
6836
6837 return(out);
6838 }
6839
6840 static krb5_error_code
6841 der_decode_data(unsigned char *data, long data_len,
6842 unsigned char **out, long *out_len)
6843 {
6844 /* Solaris Kerberos */
6845 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
6846 ASN1_OCTET_STRING *s = NULL;
6847 const unsigned char *p = data;
6848
6849 if ((s = d2i_ASN1_BIT_STRING(NULL, &p, data_len)) == NULL)
6850 goto cleanup;
6851 *out_len = s->length;
6852 if ((*out = (unsigned char *) malloc((size_t) *out_len + 1)) == NULL) {
6853 retval = ENOMEM;
6854 goto cleanup;
6855 }
6856 (void) memcpy(*out, s->data, (size_t) s->length);
6857 (*out)[s->length] = '\0';
6858
6859 retval = 0;
6860 cleanup:
6861 if (s != NULL)
6862 ASN1_OCTET_STRING_free(s);
6863
6864 return retval;
6865 }
6866
6867
6868 #ifdef DEBUG_DH
6869 static void
6870 print_dh(DH * dh, char *msg)
6871 {
6872 BIO *bio_err = NULL;
6873
6874 bio_err = BIO_new(BIO_s_file());
6875 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
6876
6877 if (msg)
6878 BIO_puts(bio_err, (const char *)msg);
6879 if (dh)
6880 DHparams_print(bio_err, dh);
6881
6882 BN_print(bio_err, dh->q);
6883 BIO_puts(bio_err, (const char *)"\n");
6884 BIO_free(bio_err);
6885
6886 }
6887
6888 static void
6889 print_pubkey(BIGNUM * key, char *msg)
6890 {
6891 BIO *bio_err = NULL;
6892
6893 bio_err = BIO_new(BIO_s_file());
6894 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
6895
6896 if (msg)
6897 BIO_puts(bio_err, (const char *)msg);
6898 if (key)
6899 BN_print(bio_err, key);
6900 BIO_puts(bio_err, "\n");
6901
6902 BIO_free(bio_err);
6903
6904 }
6905 #endif
6906
6907 /*
6908 * Solaris Kerberos:
6909 * Error message generation has changed so gettext() can be used
6910 */
6911 #if 0
6912 static char *
6913 pkinit_pkcs11_code_to_text(int err)
6914 {
6915 int i;
6916 static char uc[64];
6917
6918 for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
6919 if (pkcs11_errstrings[i].code == err)
6920 break;
6921 if (pkcs11_errstrings[i].text != NULL)
6922 return (pkcs11_errstrings[i].text);
6923 snprintf(uc, 64, gettext("unknown code 0x%x"), err);
6924 return (uc);
6925 }
6926 #endif
6927
6928 static char *
6929 pkinit_pkcs11_code_to_text(int err) {
6930 return pkcs11_error_table(err);
6931 }
6932