1 /*
2 * COPYRIGHT (C) 2006,2007
3 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4 * ALL RIGHTS RESERVED
5 *
6 * Permission is granted to use, copy, create derivative works
7 * and redistribute this software and such derivative works
8 * for any purpose, so long as the name of The University of
9 * Michigan is not used in any advertising or publicity
10 * pertaining to the use of distribution of this software
11 * without specific, written prior authorization. If the
12 * above copyright notice or any other identification of the
13 * University of Michigan is included in any copy of any
14 * portion of this software, then the disclaimer below must
15 * also be included.
16 *
17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGES.
29 */
30
31 /*
32 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
34 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
35 */
36
37 #include <errno.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <dlfcn.h>
42 #include <unistd.h>
43 #include <dirent.h>
44
45
46 /* Solaris Kerberos */
47 #include <libintl.h>
48 #include <assert.h>
49 #include <security/pam_appl.h>
50 #include <ctype.h>
51 #include "k5-int.h"
52 #include <ctype.h>
53
54 /*
55 * Q: What is this SILLYDECRYPT stuff about?
56 * A: When using the ActivCard Linux pkcs11 library (v2.0.1),
57 * the decrypt function fails. By inserting an extra
58 * function call, which serves nothing but to change the
59 * stack, we were able to work around the issue. If the
60 * ActivCard library is fixed in the future, this
61 * definition and related code can be removed.
62 */
63 #define SILLYDECRYPT
64
65 #include "pkinit_crypto_openssl.h"
66
67 /*
68 * Solaris Kerberos:
69 * Changed to a switch statement so gettext() can be used
70 * for internationization.
71 * Use defined constants rather than raw numbers for error codes.
72 */
73 static char *
74 pkcs11_error_table(short code) {
75 switch (code) {
76 case CKR_OK:
77 return (gettext("ok"));
78 case CKR_CANCEL:
79 return (gettext("cancel"));
80 case CKR_HOST_MEMORY:
81 return (gettext("host memory"));
82 case CKR_SLOT_ID_INVALID:
83 return (gettext("slot id invalid"));
84 case CKR_GENERAL_ERROR:
85 return (gettext("general error"));
86 case CKR_FUNCTION_FAILED:
87 return (gettext("function failed"));
88 case CKR_ARGUMENTS_BAD:
89 return (gettext("arguments bad"));
90 case CKR_NO_EVENT:
91 return (gettext("no event"));
92 case CKR_NEED_TO_CREATE_THREADS:
93 return (gettext("need to create threads"));
94 case CKR_CANT_LOCK:
95 return (gettext("cant lock"));
96 case CKR_ATTRIBUTE_READ_ONLY:
97 return (gettext("attribute read only"));
98 case CKR_ATTRIBUTE_SENSITIVE:
99 return (gettext("attribute sensitive"));
100 case CKR_ATTRIBUTE_TYPE_INVALID:
101 return (gettext("attribute type invalid"));
102 case CKR_ATTRIBUTE_VALUE_INVALID:
103 return (gettext("attribute value invalid"));
104 case CKR_DATA_INVALID:
105 return (gettext("data invalid"));
106 case CKR_DATA_LEN_RANGE:
107 return (gettext("data len range"));
108 case CKR_DEVICE_ERROR:
109 return (gettext("device error"));
110 case CKR_DEVICE_MEMORY:
111 return (gettext("device memory"));
112 case CKR_DEVICE_REMOVED:
113 return (gettext("device removed"));
114 case CKR_ENCRYPTED_DATA_INVALID:
115 return (gettext("encrypted data invalid"));
116 case CKR_ENCRYPTED_DATA_LEN_RANGE:
117 return (gettext("encrypted data len range"));
118 case CKR_FUNCTION_CANCELED:
119 return (gettext("function canceled"));
120 case CKR_FUNCTION_NOT_PARALLEL:
121 return (gettext("function not parallel"));
122 case CKR_FUNCTION_NOT_SUPPORTED:
123 return (gettext("function not supported"));
124 case CKR_KEY_HANDLE_INVALID:
125 return (gettext("key handle invalid"));
126 case CKR_KEY_SIZE_RANGE:
127 return (gettext("key size range"));
128 case CKR_KEY_TYPE_INCONSISTENT:
129 return (gettext("key type inconsistent"));
130 case CKR_KEY_NOT_NEEDED:
131 return (gettext("key not needed"));
132 case CKR_KEY_CHANGED:
133 return (gettext("key changed"));
134 case CKR_KEY_NEEDED:
135 return (gettext("key needed"));
136 case CKR_KEY_INDIGESTIBLE:
137 return (gettext("key indigestible"));
138 case CKR_KEY_FUNCTION_NOT_PERMITTED:
139 return (gettext("key function not permitted"));
140 case CKR_KEY_NOT_WRAPPABLE:
141 return (gettext("key not wrappable"));
142 case CKR_KEY_UNEXTRACTABLE:
143 return (gettext("key unextractable"));
144 case CKR_MECHANISM_INVALID:
145 return (gettext("mechanism invalid"));
146 case CKR_MECHANISM_PARAM_INVALID:
147 return (gettext("mechanism param invalid"));
148 case CKR_OBJECT_HANDLE_INVALID:
149 return (gettext("object handle invalid"));
150 case CKR_OPERATION_ACTIVE:
151 return (gettext("operation active"));
152 case CKR_OPERATION_NOT_INITIALIZED:
153 return (gettext("operation not initialized"));
154 case CKR_PIN_INCORRECT:
155 return (gettext("pin incorrect"));
156 case CKR_PIN_INVALID:
157 return (gettext("pin invalid"));
158 case CKR_PIN_LEN_RANGE:
159 return (gettext("pin len range"));
160 case CKR_PIN_EXPIRED:
161 return (gettext("pin expired"));
162 case CKR_PIN_LOCKED:
163 return (gettext("pin locked"));
164 case CKR_SESSION_CLOSED:
165 return (gettext("session closed"));
166 case CKR_SESSION_COUNT:
167 return (gettext("session count"));
168 case CKR_SESSION_HANDLE_INVALID:
169 return (gettext("session handle invalid"));
170 case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
171 return (gettext("session parallel not supported"));
172 case CKR_SESSION_READ_ONLY:
173 return (gettext("session read only"));
174 case CKR_SESSION_EXISTS:
175 return (gettext("session exists"));
176 case CKR_SESSION_READ_ONLY_EXISTS:
177 return (gettext("session read only exists"));
178 case CKR_SESSION_READ_WRITE_SO_EXISTS:
179 return (gettext("session read write so exists"));
180 case CKR_SIGNATURE_INVALID:
181 return (gettext("signature invalid"));
182 case CKR_SIGNATURE_LEN_RANGE:
183 return (gettext("signature len range"));
184 case CKR_TEMPLATE_INCOMPLETE:
185 return (gettext("template incomplete"));
186 case CKR_TEMPLATE_INCONSISTENT:
187 return (gettext("template inconsistent"));
188 case CKR_TOKEN_NOT_PRESENT:
189 return (gettext("token not present"));
190 case CKR_TOKEN_NOT_RECOGNIZED:
191 return (gettext("token not recognized"));
192 case CKR_TOKEN_WRITE_PROTECTED:
193 return (gettext("token write protected"));
194 case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
195 return (gettext("unwrapping key handle invalid"));
196 case CKR_UNWRAPPING_KEY_SIZE_RANGE:
197 return (gettext("unwrapping key size range"));
198 case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
199 return (gettext("unwrapping key type inconsistent"));
200 case CKR_USER_ALREADY_LOGGED_IN:
201 return (gettext("user already logged in"));
202 case CKR_USER_NOT_LOGGED_IN:
203 return (gettext("user not logged in"));
204 case CKR_USER_PIN_NOT_INITIALIZED:
205 return (gettext("user pin not initialized"));
206 case CKR_USER_TYPE_INVALID:
207 return (gettext("user type invalid"));
208 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
209 return (gettext("user another already logged in"));
210 case CKR_USER_TOO_MANY_TYPES:
211 return (gettext("user too many types"));
212 case CKR_WRAPPED_KEY_INVALID:
213 return (gettext("wrapped key invalid"));
214 case CKR_WRAPPED_KEY_LEN_RANGE:
215 return (gettext("wrapped key len range"));
216 case CKR_WRAPPING_KEY_HANDLE_INVALID:
217 return (gettext("wrapping key handle invalid"));
218 case CKR_WRAPPING_KEY_SIZE_RANGE:
219 return (gettext("wrapping key size range"));
220 case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
221 return (gettext("wrapping key type inconsistent"));
222 case CKR_RANDOM_SEED_NOT_SUPPORTED:
223 return (gettext("random seed not supported"));
224 case CKR_RANDOM_NO_RNG:
225 return (gettext("random no rng"));
226 case CKR_DOMAIN_PARAMS_INVALID:
227 return (gettext("domain params invalid"));
228 case CKR_BUFFER_TOO_SMALL:
229 return (gettext("buffer too small"));
230 case CKR_SAVED_STATE_INVALID:
231 return (gettext("saved state invalid"));
232 case CKR_INFORMATION_SENSITIVE:
233 return (gettext("information sensitive"));
234 case CKR_STATE_UNSAVEABLE:
235 return (gettext("state unsaveable"));
236 case CKR_CRYPTOKI_NOT_INITIALIZED:
237 return (gettext("cryptoki not initialized"));
238 case CKR_CRYPTOKI_ALREADY_INITIALIZED:
239 return (gettext("cryptoki already initialized"));
240 case CKR_MUTEX_BAD:
241 return (gettext("mutex bad"));
242 case CKR_MUTEX_NOT_LOCKED:
243 return (gettext("mutex not locked"));
244 case CKR_FUNCTION_REJECTED:
245 return (gettext("function rejected"));
246 default:
247 return (gettext("unknown error"));
248 }
249 }
250
251 /* DH parameters */
252 unsigned char pkinit_1024_dhprime[128] = {
253 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
254 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
255 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
256 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
257 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
258 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
259 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
260 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
261 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
262 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
263 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
264 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
265 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
266 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
267 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
268 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
269 };
270
271 unsigned char pkinit_2048_dhprime[2048/8] = {
272 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
273 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
274 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
275 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
276 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
277 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
278 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
279 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
280 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
281 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
282 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
283 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
284 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
285 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
286 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
287 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
288 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
289 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
290 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
291 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
292 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
293 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
294 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
295 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
296 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
297 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
298 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
299 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
300 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
301 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
302 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
303 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
304 };
305
306 unsigned char pkinit_4096_dhprime[4096/8] = {
307 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
308 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
309 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
310 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
311 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
312 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
313 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
314 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
315 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
316 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
317 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
318 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
319 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
320 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
321 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
322 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
323 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
324 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
325 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
326 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
327 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
328 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
329 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
330 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
331 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
332 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
333 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
334 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
335 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
336 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
337 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
338 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
339 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
340 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
341 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
342 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
343 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
344 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
345 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
346 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
347 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
348 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
349 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
350 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
351 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
352 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
353 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
354 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
355 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
356 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
357 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
358 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
359 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
360 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
361 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
362 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
363 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
364 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
365 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
366 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
367 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
368 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
369 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
370 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
371 };
372
373 #if OPENSSL_VERSION_NUMBER < 0x10100000L
374 /*
375 * Many things have changed in OpenSSL 1.1. The code in this file has been
376 * updated to use the v1.1 APIs but some are new and require emulation
377 * for older OpenSSL versions.
378 */
379
380 /* EVP_MD_CTX construct and destructor names have changed */
381
382 #define EVP_MD_CTX_new EVP_MD_CTX_create
383 #define EVP_MD_CTX_free EVP_MD_CTX_destroy
384
385 /* ASN1_STRING_data is deprecated */
386 #define ASN1_STRING_get0_data ASN1_STRING_data
387
388 /* X509_STORE_CTX_trusted_stack is deprecated */
389 #define X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_trusted_stack
390
391 /* get_rfc2409_prime_1024() has been renamed. */
392 #define BN_get_rfc2409_prime_1024 get_rfc2409_prime_1024
393
394 #define OBJ_get0_data(o) ((o)->data)
395 #define OBJ_length(o) ((o)->length)
396
397 /* Some new DH functions that aren't in OpenSSL 1.0.x */
398 #define DH_bits(dh) BN_num_bits((dh)->p);
399
400 #define DH_set0_pqg(dh, p, q, g) __DH_set0_pqg(dh, p, q, g)
401 static int
402 __DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
403 {
404 if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL))
405 return 0;
406
407 if (p != NULL) {
408 BN_free(dh->p);
409 dh->p = p;
410 }
411 if (q != NULL) {
412 BN_free(dh->q);
413 dh->q = q;
414 }
415 if (g != NULL) {
416 BN_free(dh->g);
417 dh->g = g;
418 }
419
420 if (q != NULL) {
421 dh->length = BN_num_bits(q);
422 }
423
424 return 1;
425 }
426
427 #define DH_get0_pqg(dh, p, q, g) __DH_get0_pqg(dh, p, q, g)
428 static void
429 __DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q,
430 const BIGNUM **g)
431 {
432 if (p != NULL)
433 *p = dh->p;
434 if (q != NULL)
435 *q = dh->q;
436 if (g != NULL)
437 *g = dh->g;
438 }
439
440 #define DH_set0_key(dh, pub, priv) __DH_set0_key(dh, pub, priv)
441 static int
442 __DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
443 {
444 if (pub_key != NULL) {
445 BN_free(dh->pub_key);
446 dh->pub_key = pub_key;
447 }
448 if (priv_key != NULL) {
449 BN_free(dh->priv_key);
450 dh->priv_key = priv_key;
451 }
452
453 return 1;
454 }
455
456 #define DH_get0_key(dh, pub, priv) __DH_get0_key(dh, pub, priv)
457 static void
458 __DH_get0_key(const DH *dh, const BIGNUM **pub, const BIGNUM **priv)
459 {
460 if (pub != NULL)
461 *pub = dh->pub_key;
462 if (priv != NULL)
463 *priv = dh->priv_key;
464 }
465
466 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
467
468 /* Solaris Kerberos */
469 static k5_mutex_t oids_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
470 static int pkinit_oids_refs = 0;
471
472 krb5_error_code
473 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
474
475 krb5_error_code retval = ENOMEM;
476 pkinit_plg_crypto_context ctx = NULL;
477
478 /* initialize openssl routines */
479 /* Solaris Kerberos */
480 retval = openssl_init();
481 if (retval != 0)
482 goto out;
483
484 ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
485 if (ctx == NULL)
486 goto out;
487 (void) memset(ctx, 0, sizeof(*ctx));
488
489 pkiDebug("%s: initializing openssl crypto context at %p\n",
490 __FUNCTION__, ctx);
491 retval = pkinit_init_pkinit_oids(ctx);
492 if (retval)
493 goto out;
494
495 retval = pkinit_init_dh_params(ctx);
496 if (retval)
497 goto out;
498
499 *cryptoctx = ctx;
500
501 out:
502 if (retval && ctx != NULL)
503 pkinit_fini_plg_crypto(ctx);
504
505 return retval;
506 }
507
508 void
509 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
510 {
511 pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
512
513 if (cryptoctx == NULL)
514 return;
515 pkinit_fini_pkinit_oids(cryptoctx);
516 pkinit_fini_dh_params(cryptoctx);
517 free(cryptoctx);
518 }
519
520 krb5_error_code
521 pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
522 {
523 krb5_error_code retval = ENOMEM;
524 pkinit_identity_crypto_context ctx = NULL;
525
526 ctx = (pkinit_identity_crypto_context)malloc(sizeof(*ctx));
527 if (ctx == NULL)
528 goto out;
529 (void) memset(ctx, 0, sizeof(*ctx));
530
531 retval = pkinit_init_certs(ctx);
532 if (retval)
533 goto out;
534
535 retval = pkinit_init_pkcs11(ctx);
536 if (retval)
537 goto out;
538
539 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
540 *idctx = ctx;
541
542 out:
543 if (retval) {
544 if (ctx)
545 pkinit_fini_identity_crypto(ctx);
546 }
547
548 return retval;
549 }
550
551 void
552 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
553 {
554 if (idctx == NULL)
555 return;
556
557 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx);
558 pkinit_fini_certs(idctx);
559 pkinit_fini_pkcs11(idctx);
560 free(idctx);
561 }
562
563 krb5_error_code
564 pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
565 {
566
567 pkinit_req_crypto_context ctx = NULL;
568
569 /* Solaris Kerberos */
570 if (cryptoctx == NULL)
571 return EINVAL;
572
573 ctx = (pkinit_req_crypto_context)malloc(sizeof(*ctx));
574 if (ctx == NULL)
575 return ENOMEM;
576 (void) memset(ctx, 0, sizeof(*ctx));
577
578 ctx->dh = NULL;
579 ctx->received_cert = NULL;
580
581 *cryptoctx = ctx;
582
583 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
584
585 return 0;
586 }
587
588 void
589 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
590 {
591 if (req_cryptoctx == NULL)
592 return;
593
594 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx);
595 if (req_cryptoctx->dh != NULL)
596 DH_free(req_cryptoctx->dh);
597 if (req_cryptoctx->received_cert != NULL)
598 X509_free(req_cryptoctx->received_cert);
599
600 free(req_cryptoctx);
601 }
602
603 static krb5_error_code
604 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
605 {
606 krb5_error_code retval = ENOMEM;
607 int nid = 0;
608
609 /*
610 * If OpenSSL already knows about the OID, use the
611 * existing definition. Otherwise, create an OID object.
612 */
613 #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \
614 nid = OBJ_txt2nid(oid); \
615 if (nid == NID_undef) { \
616 nid = OBJ_create(oid, sn, ln); \
617 if (nid == NID_undef) { \
618 pkiDebug("Error creating oid object for '%s'\n", oid); \
619 goto out; \
620 } \
621 } \
622 ctx->vn = OBJ_nid2obj(nid);
623
624 /* Solaris Kerberos */
625 retval = k5_mutex_lock(&oids_mutex);
626 if (retval != 0)
627 goto out;
628
629 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san,
630 "id-pkinit-san", "KRB5PrincipalName");
631
632 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.1", id_pkinit_authData,
633 "id-pkinit-authdata", "PKINIT signedAuthPack");
634
635 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.2", id_pkinit_DHKeyData,
636 "id-pkinit-DHKeyData", "PKINIT dhSignedData");
637
638 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.3", id_pkinit_rkeyData,
639 "id-pkinit-rkeyData", "PKINIT encKeyPack");
640
641 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.4", id_pkinit_KPClientAuth,
642 "id-pkinit-KPClientAuth", "PKINIT Client EKU");
643
644 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.5", id_pkinit_KPKdc,
645 "id-pkinit-KPKdc", "KDC EKU");
646
647 #if 0
648 CREATE_OBJ_IF_NEEDED("1.2.840.113549.1.7.1", id_pkinit_authData9,
649 "id-pkcs7-data", "PKCS7 data");
650 #else
651 /* See note in pkinit_pkcs7type2oid() */
652 ctx->id_pkinit_authData9 = NULL;
653 #endif
654
655 CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.2", id_ms_kp_sc_logon,
656 "id-ms-kp-sc-logon EKU", "Microsoft SmartCard Login EKU");
657
658 CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn,
659 "id-ms-san-upn", "Microsoft Universal Principal Name");
660
661 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.5.7.3.1", id_kp_serverAuth,
662 "id-kp-serverAuth EKU", "Server Authentication EKU");
663
664 /* Success */
665 retval = 0;
666
667 pkinit_oids_refs++;
668 /* Solaris Kerberos */
669 k5_mutex_unlock(&oids_mutex);
670
671 out:
672 return retval;
673 }
674
675 static krb5_error_code
676 get_cert(char *filename, X509 **retcert)
677 {
678 X509 *cert = NULL;
679 BIO *tmp = NULL;
680 int code;
681 krb5_error_code retval;
682
683 if (filename == NULL || retcert == NULL)
684 return EINVAL;
685
686 *retcert = NULL;
687
688 tmp = BIO_new(BIO_s_file());
689 if (tmp == NULL)
690 return ENOMEM;
691
692 code = BIO_read_filename(tmp, filename);
693 if (code == 0) {
694 retval = errno;
695 goto cleanup;
696 }
697
698 cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
699 if (cert == NULL) {
700 retval = EIO;
701 pkiDebug("failed to read certificate from %s\n", filename);
702 goto cleanup;
703 }
704 *retcert = cert;
705 retval = 0;
706 cleanup:
707 if (tmp != NULL)
708 BIO_free(tmp);
709 return retval;
710 }
711
712 static krb5_error_code
713 get_key(char *filename, EVP_PKEY **retkey)
714 {
715 EVP_PKEY *pkey = NULL;
716 BIO *tmp = NULL;
717 int code;
718 krb5_error_code retval;
719
720 if (filename == NULL || retkey == NULL)
721 return EINVAL;
722
723 tmp = BIO_new(BIO_s_file());
724 if (tmp == NULL)
725 return ENOMEM;
726
727 code = BIO_read_filename(tmp, filename);
728 if (code == 0) {
729 retval = errno;
730 goto cleanup;
731 }
732 pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL);
733 if (pkey == NULL) {
734 retval = EIO;
735 pkiDebug("failed to read private key from %s\n", filename);
736 goto cleanup;
737 }
738 *retkey = pkey;
739 retval = 0;
740 cleanup:
741 if (tmp != NULL)
742 BIO_free(tmp);
743 return retval;
744 }
745
746 static void
747 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
748 {
749 if (ctx == NULL)
750 return;
751
752 /* Only call OBJ_cleanup once! */
753 /* Solaris Kerberos: locking */
754 k5_mutex_lock(&oids_mutex);
755 #if OPENSSL_VERSION_NUMBER < 0x10100000L
756 /*
757 * In OpenSSL versions prior to 1.1.0, OBJ_cleanup() cleaned up OpenSSL's
758 * internal object table. This function is deprecated in version 1.1.0.
759 * No explicit de-initialisation is now required.
760 */
761 if (--pkinit_oids_refs == 0)
762 OBJ_cleanup();
763 #else
764 pkinit_oids_refs--;
765 #endif
766 k5_mutex_unlock(&oids_mutex);
767 }
768
769 /* Construct an OpenSSL DH object for an Oakley group. */
770 static DH *
771 make_dhprime(uint8_t *prime, size_t len)
772 {
773 DH *dh = NULL;
774 BIGNUM *p = NULL, *q = NULL, *g = NULL;
775
776 if ((p = BN_bin2bn(prime, len, NULL)) == NULL)
777 goto cleanup;
778 if ((q = BN_new()) == NULL)
779 goto cleanup;
780 if (!BN_rshift1(q, p))
781 goto cleanup;
782 if ((g = BN_new()) == NULL)
783 goto cleanup;
784 if (!BN_set_word(g, DH_GENERATOR_2))
785 goto cleanup;
786
787 dh = DH_new();
788 if (dh == NULL)
789 goto cleanup;
790 DH_set0_pqg(dh, p, q, g);
791 p = g = q = NULL;
792
793 cleanup:
794 BN_free(p);
795 BN_free(q);
796 BN_free(g);
797 return dh;
798 }
799
800 static krb5_error_code
801 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
802 {
803 krb5_error_code retval = ENOMEM;
804
805 plgctx->dh_1024 = make_dhprime(pkinit_1024_dhprime,
806 sizeof(pkinit_1024_dhprime));
807 if (plgctx->dh_1024 == NULL)
808 goto cleanup;
809
810 plgctx->dh_2048 = make_dhprime(pkinit_2048_dhprime,
811 sizeof(pkinit_2048_dhprime));
812 if (plgctx->dh_2048 == NULL)
813 goto cleanup;
814
815 plgctx->dh_4096 = make_dhprime(pkinit_4096_dhprime,
816 sizeof(pkinit_4096_dhprime));
817 if (plgctx->dh_4096 == NULL)
818 goto cleanup;
819
820 retval = 0;
821
822 cleanup:
823 if (retval)
824 pkinit_fini_dh_params(plgctx);
825
826 return retval;
827 }
828
829 static void
830 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)
831 {
832 if (plgctx->dh_1024 != NULL)
833 DH_free(plgctx->dh_1024);
834 if (plgctx->dh_2048 != NULL)
835 DH_free(plgctx->dh_2048);
836 if (plgctx->dh_4096 != NULL)
837 DH_free(plgctx->dh_4096);
838
839 plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL;
840 }
841
842 static krb5_error_code
843 pkinit_init_certs(pkinit_identity_crypto_context ctx)
844 {
845 /* Solaris Kerberos */
846 int i;
847
848 for (i = 0; i < MAX_CREDS_ALLOWED; i++)
849 ctx->creds[i] = NULL;
850 ctx->my_certs = NULL;
851 ctx->cert_index = 0;
852 ctx->my_key = NULL;
853 ctx->trustedCAs = NULL;
854 ctx->intermediateCAs = NULL;
855 ctx->revoked = NULL;
856
857 return 0;
858 }
859
860 static void
861 pkinit_fini_certs(pkinit_identity_crypto_context ctx)
862 {
863 if (ctx == NULL)
864 return;
865
866 if (ctx->my_certs != NULL)
867 sk_X509_pop_free(ctx->my_certs, X509_free);
868
869 if (ctx->my_key != NULL)
870 EVP_PKEY_free(ctx->my_key);
871
872 if (ctx->trustedCAs != NULL)
873 sk_X509_pop_free(ctx->trustedCAs, X509_free);
874
875 if (ctx->intermediateCAs != NULL)
876 sk_X509_pop_free(ctx->intermediateCAs, X509_free);
877
878 if (ctx->revoked != NULL)
879 sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free);
880 }
881
882 static krb5_error_code
883 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
884 {
885 /* Solaris Kerberos */
886
887 #ifndef WITHOUT_PKCS11
888 ctx->p11_module_name = strdup(PKCS11_MODNAME);
889 if (ctx->p11_module_name == NULL)
890 return ENOMEM;
891 ctx->p11_module = NULL;
892 ctx->slotid = PK_NOSLOT;
893 ctx->token_label = NULL;
894 ctx->cert_label = NULL;
895 ctx->PIN = NULL;
896 ctx->session = CK_INVALID_HANDLE;
897 ctx->p11 = NULL;
898 ctx->p11flags = 0; /* Solaris Kerberos */
899 #endif
900 ctx->pkcs11_method = 0;
901 (void) memset(ctx->creds, 0, sizeof(ctx->creds));
902
903 return 0;
904 }
905
906 static void
907 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
908 {
909 #ifndef WITHOUT_PKCS11
910 if (ctx == NULL)
911 return;
912
913 if (ctx->p11 != NULL) {
914 if (ctx->session != CK_INVALID_HANDLE) {
915 ctx->p11->C_CloseSession(ctx->session);
916 ctx->session = CK_INVALID_HANDLE;
917 }
918 /*
919 * Solaris Kerberos:
920 * Only call C_Finalize if the process was not already using pkcs11.
921 */
922 if (ctx->finalize_pkcs11 == TRUE)
923 ctx->p11->C_Finalize(NULL_PTR);
924
925 ctx->p11 = NULL;
926 }
927 if (ctx->p11_module != NULL) {
928 pkinit_C_UnloadModule(ctx->p11_module);
929 ctx->p11_module = NULL;
930 }
931 if (ctx->p11_module_name != NULL)
932 free(ctx->p11_module_name);
933 if (ctx->token_label != NULL)
934 free(ctx->token_label);
935 if (ctx->cert_id != NULL)
936 free(ctx->cert_id);
937 if (ctx->cert_label != NULL)
938 free(ctx->cert_label);
939 if (ctx->PIN != NULL) {
940 (void) memset(ctx->PIN, 0, strlen(ctx->PIN));
941 free(ctx->PIN);
942 }
943 #endif
944 }
945
946 krb5_error_code
947 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
948 krb5_prompter_fct prompter,
949 void *prompter_data)
950 {
951 id_cryptoctx->prompter = prompter;
952 id_cryptoctx->prompter_data = prompter_data;
953
954 return 0;
955 }
956
957 /* ARGSUSED */
958 krb5_error_code
959 cms_signeddata_create(krb5_context context,
960 pkinit_plg_crypto_context plg_cryptoctx,
961 pkinit_req_crypto_context req_cryptoctx,
962 pkinit_identity_crypto_context id_cryptoctx,
963 int cms_msg_type,
964 int include_certchain,
965 unsigned char *data,
966 unsigned int data_len,
967 unsigned char **signed_data,
968 unsigned int *signed_data_len)
969 {
970 /* Solaris Kerberos */
971 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
972 PKCS7 *p7 = NULL, *inner_p7 = NULL;
973 PKCS7_SIGNED *p7s = NULL;
974 PKCS7_SIGNER_INFO *p7si = NULL;
975 unsigned char *p;
976 ASN1_TYPE *pkinit_data = NULL;
977 STACK_OF(X509) * cert_stack = NULL;
978 ASN1_OCTET_STRING *digest_attr = NULL;
979 EVP_MD_CTX *ctx = NULL, *ctx2 = NULL;
980 const EVP_MD *md_tmp = NULL;
981 unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
982 unsigned char *digestInfo_buf = NULL, *abuf = NULL;
983 unsigned int md_len, md_len2, alen, digestInfo_len;
984 STACK_OF(X509_ATTRIBUTE) * sk;
985 unsigned char *sig = NULL;
986 unsigned int sig_len = 0;
987 X509_ALGOR *alg = NULL;
988 ASN1_OCTET_STRING *digest = NULL;
989 unsigned int alg_len = 0, digest_len = 0;
990 unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
991 X509 *cert = NULL;
992 ASN1_OBJECT *oid = NULL;
993
994 /* Solaris Kerberos */
995 if (signed_data == NULL)
996 return EINVAL;
997
998 if (signed_data_len == NULL)
999 return EINVAL;
1000
1001 /* start creating PKCS7 data */
1002 if ((p7 = PKCS7_new()) == NULL)
1003 goto cleanup;
1004 p7->type = OBJ_nid2obj(NID_pkcs7_signed);
1005
1006 if ((p7s = PKCS7_SIGNED_new()) == NULL)
1007 goto cleanup;
1008 p7->d.sign = p7s;
1009 if (!ASN1_INTEGER_set(p7s->version, 3))
1010 goto cleanup;
1011
1012 /* create a cert chain that has at least the signer's certificate */
1013 if ((cert_stack = sk_X509_new_null()) == NULL)
1014 goto cleanup;
1015
1016 cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
1017 if (!include_certchain) {
1018 pkiDebug("only including signer's certificate\n");
1019 sk_X509_push(cert_stack, X509_dup(cert));
1020 } else {
1021 /* create a cert chain */
1022 X509_STORE *certstore = NULL;
1023 X509_STORE_CTX *certctx;
1024 STACK_OF(X509) *certstack = NULL;
1025 char buf[DN_BUF_LEN];
1026 int i = 0, size = 0;
1027
1028 if ((certstore = X509_STORE_new()) == NULL)
1029 goto cleanup;
1030 if ((certctx = X509_STORE_CTX_new()) == NULL)
1031 goto cleanup;
1032 pkiDebug("building certificate chain\n");
1033 X509_STORE_set_verify_cb(certstore, openssl_callback);
1034 X509_STORE_CTX_init(certctx, certstore, cert,
1035 id_cryptoctx->intermediateCAs);
1036 X509_STORE_CTX_set0_trusted_stack(certctx, id_cryptoctx->trustedCAs);
1037 /* Solaris Kerberos */
1038 if (X509_verify_cert(certctx) <= 0) {
1039 pkiDebug("failed to create a certificate chain: %s\n",
1040 X509_verify_cert_error_string(X509_STORE_CTX_get_error(certctx)));
1041 if (!sk_X509_num(id_cryptoctx->trustedCAs))
1042 pkiDebug("No trusted CAs found. Check your X509_anchors\n");
1043 goto cleanup;
1044 }
1045 certstack = X509_STORE_CTX_get1_chain(certctx);
1046 size = sk_X509_num(certstack);
1047 pkiDebug("size of certificate chain = %d\n", size);
1048 for(i = 0; i < size - 1; i++) {
1049 X509 *x = sk_X509_value(certstack, i);
1050 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
1051 pkiDebug("cert #%d: %s\n", i, buf);
1052 sk_X509_push(cert_stack, X509_dup(x));
1053 }
1054 X509_STORE_CTX_free(certctx);
1055 X509_STORE_free(certstore);
1056 sk_X509_pop_free(certstack, X509_free);
1057 }
1058 p7s->cert = cert_stack;
1059
1060 /* fill-in PKCS7_SIGNER_INFO */
1061 if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
1062 goto cleanup;
1063 if (!ASN1_INTEGER_set(p7si->version, 1))
1064 goto cleanup;
1065 if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
1066 X509_get_issuer_name(cert)))
1067 goto cleanup;
1068 /* because ASN1_INTEGER_set is used to set a 'long' we will do
1069 * things the ugly way. */
1070 ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
1071 if (!(p7si->issuer_and_serial->serial =
1072 ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
1073 goto cleanup;
1074
1075 /* will not fill-out EVP_PKEY because it's on the smartcard */
1076
1077 /* Set digest algs */
1078 p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
1079
1080 if (p7si->digest_alg->parameter != NULL)
1081 ASN1_TYPE_free(p7si->digest_alg->parameter);
1082 if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
1083 goto cleanup;
1084 p7si->digest_alg->parameter->type = V_ASN1_NULL;
1085
1086 /* Set sig algs */
1087 if (p7si->digest_enc_alg->parameter != NULL)
1088 ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
1089 p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
1090 if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
1091 goto cleanup;
1092 p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
1093
1094 /* pick the correct oid for the eContentInfo */
1095 oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
1096 if (oid == NULL)
1097 goto cleanup;
1098
1099 if (cms_msg_type == CMS_SIGN_DRAFT9) {
1100 /* don't include signed attributes for pa-type 15 request */
1101 abuf = data;
1102 alen = data_len;
1103 } else {
1104 /* add signed attributes */
1105 /* compute sha1 digest over the EncapsulatedContentInfo */
1106 ctx = EVP_MD_CTX_new();
1107 if (ctx == NULL)
1108 goto cleanup2;
1109 EVP_MD_CTX_init(ctx);
1110 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1111 EVP_DigestUpdate(ctx, data, data_len);
1112 md_tmp = EVP_MD_CTX_md(ctx);
1113 EVP_DigestFinal_ex(ctx, md_data, &md_len);
1114 EVP_MD_CTX_free(ctx);
1115 ctx = NULL;
1116
1117 /* create a message digest attr */
1118 digest_attr = ASN1_OCTET_STRING_new();
1119 ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
1120 PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
1121 V_ASN1_OCTET_STRING, (char *) digest_attr);
1122
1123 /* create a content-type attr */
1124 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
1125 V_ASN1_OBJECT, oid);
1126
1127 /* create the signature over signed attributes. get DER encoded value */
1128 /* This is the place where smartcard signature needs to be calculated */
1129 sk = p7si->auth_attr;
1130 alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
1131 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
1132 if (abuf == NULL)
1133 goto cleanup2;
1134 }
1135
1136 #ifndef WITHOUT_PKCS11
1137 /* Some tokens can only do RSAEncryption without sha1 hash */
1138 /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
1139 * function and the hash value into an ASN.1 value of type DigestInfo
1140 * DigestInfo::=SEQUENCE {
1141 * digestAlgorithm AlgorithmIdentifier,
1142 * digest OCTET STRING }
1143 */
1144 if (id_cryptoctx->pkcs11_method == 1 &&
1145 id_cryptoctx->mech == CKM_RSA_PKCS) {
1146 pkiDebug("mech = CKM_RSA_PKCS\n");
1147 ctx2 = EVP_MD_CTX_new();
1148 if (ctx2 == NULL)
1149 goto cleanup2;
1150 EVP_MD_CTX_init(ctx2);
1151 /* if this is not draft9 request, include digest signed attribute */
1152 if (cms_msg_type != CMS_SIGN_DRAFT9)
1153 EVP_DigestInit_ex(ctx2, md_tmp, NULL);
1154 else
1155 EVP_DigestInit_ex(ctx2, EVP_sha1(), NULL);
1156 EVP_DigestUpdate(ctx2, abuf, alen);
1157 EVP_DigestFinal_ex(ctx2, md_data2, &md_len2);
1158 EVP_MD_CTX_free(ctx2);
1159 ctx2 = NULL;
1160
1161 alg = X509_ALGOR_new();
1162 if (alg == NULL)
1163 goto cleanup2;
1164 alg->algorithm = OBJ_nid2obj(NID_sha1);
1165 alg->parameter = NULL;
1166 alg_len = i2d_X509_ALGOR(alg, NULL);
1167 alg_buf = (unsigned char *)malloc(alg_len);
1168 if (alg_buf == NULL)
1169 goto cleanup2;
1170
1171 digest = ASN1_OCTET_STRING_new();
1172 if (digest == NULL)
1173 goto cleanup2;
1174 ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
1175 digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
1176 digest_buf = (unsigned char *)malloc(digest_len);
1177 if (digest_buf == NULL)
1178 goto cleanup2;
1179
1180 digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
1181 V_ASN1_SEQUENCE);
1182 y = digestInfo_buf = (unsigned char *)malloc(digestInfo_len);
1183 if (digestInfo_buf == NULL)
1184 goto cleanup2;
1185 ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
1186 V_ASN1_UNIVERSAL);
1187 i2d_X509_ALGOR(alg, &y);
1188 i2d_ASN1_OCTET_STRING(digest, &y);
1189 #ifdef DEBUG_SIG
1190 pkiDebug("signing buffer\n");
1191 print_buffer(digestInfo_buf, digestInfo_len);
1192 print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
1193 #endif
1194 retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
1195 digestInfo_len, &sig, &sig_len);
1196 } else
1197 #endif
1198 {
1199 pkiDebug("mech = %s\n",
1200 id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
1201 retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
1202 &sig, &sig_len);
1203 }
1204 #ifdef DEBUG_SIG
1205 print_buffer(sig, sig_len);
1206 #endif
1207 if (cms_msg_type != CMS_SIGN_DRAFT9)
1208 free(abuf);
1209 if (retval)
1210 goto cleanup2;
1211
1212 /* Add signature */
1213 if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
1214 (int)sig_len)) {
1215 unsigned long err = ERR_peek_error();
1216 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1217 krb5_set_error_message(context, retval, "%s\n",
1218 ERR_error_string(err, NULL));
1219 pkiDebug("failed to add a signed digest attribute\n");
1220 goto cleanup2;
1221 }
1222 /* adder signer_info to pkcs7 signed */
1223 if (!PKCS7_add_signer(p7, p7si))
1224 goto cleanup2;
1225
1226 /* start on adding data to the pkcs7 signed */
1227 if ((inner_p7 = PKCS7_new()) == NULL)
1228 goto cleanup2;
1229 if ((pkinit_data = ASN1_TYPE_new()) == NULL)
1230 goto cleanup2;
1231 pkinit_data->type = V_ASN1_OCTET_STRING;
1232 if ((pkinit_data->value.octet_string = ASN1_OCTET_STRING_new()) == NULL)
1233 goto cleanup2;
1234 if (!ASN1_OCTET_STRING_set(pkinit_data->value.octet_string, data,
1235 (int)data_len)) {
1236 unsigned long err = ERR_peek_error();
1237 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1238 krb5_set_error_message(context, retval, "%s\n",
1239 ERR_error_string(err, NULL));
1240 pkiDebug("failed to add pkcs7 data\n");
1241 goto cleanup2;
1242 }
1243
1244 if (!PKCS7_set0_type_other(inner_p7, OBJ_obj2nid(oid), pkinit_data))
1245 goto cleanup2;
1246
1247 if (p7s->contents != NULL)
1248 PKCS7_free(p7s->contents);
1249 p7s->contents = inner_p7;
1250
1251 *signed_data_len = i2d_PKCS7(p7, NULL);
1252 if (!(*signed_data_len)) {
1253 unsigned long err = ERR_peek_error();
1254 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1255 krb5_set_error_message(context, retval, "%s\n",
1256 ERR_error_string(err, NULL));
1257 pkiDebug("failed to der encode pkcs7\n");
1258 goto cleanup2;
1259 }
1260 if ((p = *signed_data =
1261 (unsigned char *) malloc((size_t)*signed_data_len)) == NULL)
1262 goto cleanup2;
1263
1264 /* DER encode PKCS7 data */
1265 retval = i2d_PKCS7(p7, &p);
1266 if (!retval) {
1267 unsigned long err = ERR_peek_error();
1268 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1269 krb5_set_error_message(context, retval, "%s\n",
1270 ERR_error_string(err, NULL));
1271 pkiDebug("failed to der encode pkcs7\n");
1272 goto cleanup2;
1273 }
1274 retval = 0;
1275
1276 #ifdef DEBUG_ASN1
1277 if (cms_msg_type == CMS_SIGN_CLIENT) {
1278 print_buffer_bin(*signed_data, *signed_data_len,
1279 "/tmp/client_pkcs7_signeddata");
1280 } else {
1281 if (cms_msg_type == CMS_SIGN_SERVER) {
1282 print_buffer_bin(*signed_data, *signed_data_len,
1283 "/tmp/kdc_pkcs7_signeddata");
1284 } else {
1285 print_buffer_bin(*signed_data, *signed_data_len,
1286 "/tmp/draft9_pkcs7_signeddata");
1287 }
1288 }
1289 #endif
1290
1291 cleanup2:
1292 if (cms_msg_type != CMS_SIGN_DRAFT9)
1293 if (ctx != NULL)
1294 EVP_MD_CTX_free(ctx);
1295 #ifndef WITHOUT_PKCS11
1296 if (id_cryptoctx->pkcs11_method == 1 &&
1297 id_cryptoctx->mech == CKM_RSA_PKCS) {
1298 if (ctx2 != NULL)
1299 EVP_MD_CTX_free(ctx2);
1300 if (digest_buf != NULL)
1301 free(digest_buf);
1302 if (digestInfo_buf != NULL)
1303 free(digestInfo_buf);
1304 if (alg_buf != NULL)
1305 free(alg_buf);
1306 if (digest != NULL)
1307 ASN1_OCTET_STRING_free(digest);
1308 }
1309 #endif
1310 if (alg != NULL)
1311 X509_ALGOR_free(alg);
1312 cleanup:
1313 if (p7 != NULL)
1314 PKCS7_free(p7);
1315 if (sig != NULL)
1316 free(sig);
1317
1318 return retval;
1319 }
1320
1321 krb5_error_code
1322 cms_signeddata_verify(krb5_context context,
1323 pkinit_plg_crypto_context plgctx,
1324 pkinit_req_crypto_context reqctx,
1325 pkinit_identity_crypto_context idctx,
1326 int cms_msg_type,
1327 int require_crl_checking,
1328 unsigned char *signed_data,
1329 unsigned int signed_data_len,
1330 unsigned char **data,
1331 unsigned int *data_len,
1332 unsigned char **authz_data,
1333 unsigned int *authz_data_len)
1334 {
1335 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
1336 PKCS7 *p7 = NULL;
1337 BIO *out = NULL;
1338 int flags = PKCS7_NOVERIFY, i = 0;
1339 unsigned int vflags = 0, size = 0;
1340 const unsigned char *p = signed_data;
1341 STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
1342 PKCS7_SIGNER_INFO *si = NULL;
1343 X509 *x = NULL;
1344 X509_STORE *store = NULL;
1345 X509_STORE_CTX *cert_ctx;
1346 STACK_OF(X509) *intermediateCAs = NULL;
1347 STACK_OF(X509_CRL) *revoked = NULL;
1348 STACK_OF(X509) *verified_chain = NULL;
1349 ASN1_OBJECT *oid = NULL;
1350 krb5_external_principal_identifier **krb5_verified_chain = NULL;
1351 krb5_data *authz = NULL;
1352 char buf[DN_BUF_LEN];
1353
1354 #ifdef DEBUG_ASN1
1355 print_buffer_bin(signed_data, signed_data_len,
1356 "/tmp/client_received_pkcs7_signeddata");
1357 #endif
1358
1359 /* Do this early enough to create the shadow OID for pkcs7-data if needed */
1360 oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
1361 if (oid == NULL)
1362 goto cleanup;
1363
1364 /* decode received PKCS7 message */
1365 if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) {
1366 unsigned long err = ERR_peek_error();
1367 krb5_set_error_message(context, retval, "%s\n",
1368 ERR_error_string(err, NULL));
1369 pkiDebug("%s: failed to decode message: %s\n",
1370 __FUNCTION__, ERR_error_string(err, NULL));
1371 goto cleanup;
1372 }
1373
1374 /* verify that the received message is PKCS7 SignedData message */
1375 if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
1376 pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
1377 OBJ_obj2nid(p7->type));
1378 krb5_set_error_message(context, retval, "wrong oid\n");
1379 goto cleanup;
1380 }
1381
1382 /* setup to verify X509 certificate used to sign PKCS7 message */
1383 if (!(store = X509_STORE_new()))
1384 goto cleanup;
1385
1386 /* check if we are inforcing CRL checking */
1387 vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
1388 if (require_crl_checking)
1389 X509_STORE_set_verify_cb(store, openssl_callback);
1390 else
1391 X509_STORE_set_verify_cb(store, openssl_callback_ignore_crls);
1392 X509_STORE_set_flags(store, vflags);
1393
1394 /* get the signer's information from the PKCS7 message */
1395 if ((si_sk = PKCS7_get_signer_info(p7)) == NULL)
1396 goto cleanup;
1397 if ((si = sk_PKCS7_SIGNER_INFO_value(si_sk, 0)) == NULL)
1398 goto cleanup;
1399 if ((x = PKCS7_cert_from_signer_info(p7, si)) == NULL)
1400 goto cleanup;
1401
1402 /* create available CRL information (get local CRLs and include CRLs
1403 * received in the PKCS7 message
1404 */
1405 if (idctx->revoked == NULL)
1406 revoked = p7->d.sign->crl;
1407 else if (p7->d.sign->crl == NULL)
1408 revoked = idctx->revoked;
1409 else {
1410 size = sk_X509_CRL_num(idctx->revoked);
1411 revoked = sk_X509_CRL_new_null();
1412 for (i = 0; i < size; i++)
1413 sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i));
1414 size = sk_X509_CRL_num(p7->d.sign->crl);
1415 for (i = 0; i < size; i++)
1416 sk_X509_CRL_push(revoked, sk_X509_CRL_value(p7->d.sign->crl, i));
1417 }
1418
1419 /* create available intermediate CAs chains (get local intermediateCAs and
1420 * include the CA chain received in the PKCS7 message
1421 */
1422 if (idctx->intermediateCAs == NULL)
1423 intermediateCAs = p7->d.sign->cert;
1424 else if (p7->d.sign->cert == NULL)
1425 intermediateCAs = idctx->intermediateCAs;
1426 else {
1427 size = sk_X509_num(idctx->intermediateCAs);
1428 intermediateCAs = sk_X509_new_null();
1429 for (i = 0; i < size; i++) {
1430 sk_X509_push(intermediateCAs,
1431 sk_X509_value(idctx->intermediateCAs, i));
1432 }
1433 size = sk_X509_num(p7->d.sign->cert);
1434 for (i = 0; i < size; i++) {
1435 sk_X509_push(intermediateCAs, sk_X509_value(p7->d.sign->cert, i));
1436 }
1437 }
1438
1439 /* initialize x509 context with the received certificate and
1440 * trusted and intermediate CA chains and CRLs
1441 */
1442 if ((cert_ctx = X509_STORE_CTX_new()) == NULL)
1443 goto cleanup;
1444 if (!X509_STORE_CTX_init(cert_ctx, store, x, intermediateCAs))
1445 goto cleanup;
1446
1447 X509_STORE_CTX_set0_crls(cert_ctx, revoked);
1448
1449 /* add trusted CAs certificates for cert verification */
1450 if (idctx->trustedCAs != NULL)
1451 X509_STORE_CTX_set0_trusted_stack(cert_ctx, idctx->trustedCAs);
1452 else {
1453 pkiDebug("unable to find any trusted CAs\n");
1454 goto cleanup;
1455 }
1456 #ifdef DEBUG_CERTCHAIN
1457 if (intermediateCAs != NULL) {
1458 size = sk_X509_num(intermediateCAs);
1459 pkiDebug("untrusted cert chain of size %d\n", size);
1460 for (i = 0; i < size; i++) {
1461 X509_NAME_oneline(X509_get_subject_name(
1462 sk_X509_value(intermediateCAs, i)), buf, sizeof(buf));
1463 pkiDebug("cert #%d: %s\n", i, buf);
1464 }
1465 }
1466 if (idctx->trustedCAs != NULL) {
1467 size = sk_X509_num(idctx->trustedCAs);
1468 pkiDebug("trusted cert chain of size %d\n", size);
1469 for (i = 0; i < size; i++) {
1470 X509_NAME_oneline(X509_get_subject_name(
1471 sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf));
1472 pkiDebug("cert #%d: %s\n", i, buf);
1473 }
1474 }
1475 if (revoked != NULL) {
1476 size = sk_X509_CRL_num(revoked);
1477 pkiDebug("CRL chain of size %d\n", size);
1478 for (i = 0; i < size; i++) {
1479 X509_CRL *crl = sk_X509_CRL_value(revoked, i);
1480 X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf));
1481 pkiDebug("crls by CA #%d: %s\n", i , buf);
1482 }
1483 }
1484 #endif
1485
1486 i = X509_verify_cert(cert_ctx);
1487 if (i <= 0) {
1488 int j = X509_STORE_CTX_get_error(cert_ctx);
1489
1490 reqctx->received_cert = X509_dup(
1491 X509_STORE_CTX_get_current_cert(cert_ctx));
1492 switch(j) {
1493 case X509_V_ERR_CERT_REVOKED:
1494 retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
1495 break;
1496 case X509_V_ERR_UNABLE_TO_GET_CRL:
1497 retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN;
1498 break;
1499 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1500 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1501 retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE;
1502 break;
1503 default:
1504 retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
1505 }
1506 X509_NAME_oneline(X509_get_subject_name(
1507 reqctx->received_cert), buf, sizeof(buf));
1508 pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j,
1509 X509_verify_cert_error_string(j));
1510 krb5_set_error_message(context, retval, "%s\n",
1511 X509_verify_cert_error_string(j));
1512 #ifdef DEBUG_CERTCHAIN
1513 size = sk_X509_num(p7->d.sign->cert);
1514 pkiDebug("received cert chain of size %d\n", size);
1515 for (j = 0; j < size; j++) {
1516 X509 *tmp_cert = sk_X509_value(p7->d.sign->cert, j);
1517 X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf));
1518 pkiDebug("cert #%d: %s\n", j, buf);
1519 }
1520 #endif
1521 } else {
1522 /* retrieve verified certificate chain */
1523 if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9)
1524 verified_chain = X509_STORE_CTX_get1_chain(cert_ctx);
1525 }
1526 X509_STORE_CTX_free(cert_ctx);
1527 if (i <= 0)
1528 goto cleanup;
1529
1530 out = BIO_new(BIO_s_mem());
1531 if (cms_msg_type == CMS_SIGN_DRAFT9)
1532 flags |= PKCS7_NOATTR;
1533 if (PKCS7_verify(p7, NULL, store, NULL, out, flags)) {
1534 int valid_oid = 0;
1535
1536 if (!OBJ_cmp(p7->d.sign->contents->type, oid))
1537 valid_oid = 1;
1538 else if (cms_msg_type == CMS_SIGN_DRAFT9) {
1539 /*
1540 * Various implementations of the pa-type 15 request use
1541 * different OIDS. We check that the returned object
1542 * has any of the acceptable OIDs
1543 */
1544 ASN1_OBJECT *client_oid = NULL, *server_oid = NULL, *rsa_oid = NULL;
1545 client_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_CLIENT);
1546 server_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_SERVER);
1547 rsa_oid = pkinit_pkcs7type2oid(plgctx, CMS_ENVEL_SERVER);
1548 if (!OBJ_cmp(p7->d.sign->contents->type, client_oid) ||
1549 !OBJ_cmp(p7->d.sign->contents->type, server_oid) ||
1550 !OBJ_cmp(p7->d.sign->contents->type, rsa_oid))
1551 valid_oid = 1;
1552 }
1553
1554 if (valid_oid)
1555 pkiDebug("PKCS7 Verification successful\n");
1556 else {
1557 const ASN1_OBJECT *etype = p7->d.sign->contents->type;
1558 pkiDebug("wrong oid in eContentType\n");
1559 print_buffer((unsigned char *)OBJ_get0_data(etype),
1560 OBJ_length(etype));
1561 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1562 krb5_set_error_message(context, retval, "wrong oid\n");
1563 goto cleanup;
1564 }
1565 }
1566 else {
1567 unsigned long err = ERR_peek_error();
1568 switch(ERR_GET_REASON(err)) {
1569 case PKCS7_R_DIGEST_FAILURE:
1570 retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED;
1571 break;
1572 case PKCS7_R_SIGNATURE_FAILURE:
1573 default:
1574 retval = KRB5KDC_ERR_INVALID_SIG;
1575 }
1576 pkiDebug("PKCS7 Verification failure\n");
1577 krb5_set_error_message(context, retval, "%s\n",
1578 ERR_error_string(err, NULL));
1579 goto cleanup;
1580 }
1581
1582 /* transfer the data from PKCS7 message into return buffer */
1583 for (size = 0;;) {
1584 if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
1585 goto cleanup;
1586 i = BIO_read(out, &((*data)[size]), 1024 * 10);
1587 if (i <= 0)
1588 break;
1589 else
1590 size += i;
1591 }
1592 *data_len = size;
1593
1594 reqctx->received_cert = X509_dup(x);
1595
1596 /* generate authorization data */
1597 if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) {
1598
1599 if (authz_data == NULL || authz_data_len == NULL)
1600 goto out;
1601
1602 *authz_data = NULL;
1603 retval = create_identifiers_from_stack(verified_chain,
1604 &krb5_verified_chain);
1605 if (retval) {
1606 pkiDebug("create_identifiers_from_stack failed\n");
1607 goto cleanup;
1608 }
1609
1610 retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_verified_chain, &authz);
1611 if (retval) {
1612 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
1613 goto cleanup;
1614 }
1615 #ifdef DEBUG_ASN1
1616 print_buffer_bin((unsigned char *)authz->data, authz->length,
1617 "/tmp/kdc_ad_initial_verified_cas");
1618 #endif
1619 *authz_data = (unsigned char *)malloc(authz->length);
1620 if (*authz_data == NULL) {
1621 retval = ENOMEM;
1622 goto cleanup;
1623 }
1624 (void) memcpy(*authz_data, authz->data, authz->length);
1625 *authz_data_len = authz->length;
1626 }
1627 out:
1628 retval = 0;
1629
1630 cleanup:
1631 if (out != NULL)
1632 BIO_free(out);
1633 if (store != NULL)
1634 X509_STORE_free(store);
1635 if (p7 != NULL) {
1636 if (idctx->intermediateCAs != NULL && p7->d.sign->cert)
1637 sk_X509_free(intermediateCAs);
1638 if (idctx->revoked != NULL && p7->d.sign->crl)
1639 sk_X509_CRL_free(revoked);
1640 PKCS7_free(p7);
1641 }
1642 if (verified_chain != NULL)
1643 sk_X509_pop_free(verified_chain, X509_free);
1644 if (krb5_verified_chain != NULL)
1645 free_krb5_external_principal_identifier(&krb5_verified_chain);
1646 if (authz != NULL)
1647 krb5_free_data(context, authz);
1648
1649 return retval;
1650 }
1651
1652 krb5_error_code
1653 cms_envelopeddata_create(krb5_context context,
1654 pkinit_plg_crypto_context plgctx,
1655 pkinit_req_crypto_context reqctx,
1656 pkinit_identity_crypto_context idctx,
1657 krb5_preauthtype pa_type,
1658 int include_certchain,
1659 unsigned char *key_pack,
1660 unsigned int key_pack_len,
1661 unsigned char **out,
1662 unsigned int *out_len)
1663 {
1664
1665 /* Solaris Kerberos */
1666 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
1667 PKCS7 *p7 = NULL;
1668 BIO *in = NULL;
1669 unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL;
1670 int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY;
1671 STACK_OF(X509) *encerts = NULL;
1672 const EVP_CIPHER *cipher = NULL;
1673 int cms_msg_type;
1674
1675 /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */
1676 switch ((int)pa_type) {
1677 case KRB5_PADATA_PK_AS_REQ_OLD:
1678 case KRB5_PADATA_PK_AS_REP_OLD:
1679 cms_msg_type = CMS_SIGN_DRAFT9;
1680 break;
1681 case KRB5_PADATA_PK_AS_REQ:
1682 cms_msg_type = CMS_ENVEL_SERVER;
1683 break;
1684 default:
1685 /* Solaris Kerberos */
1686 retval = EINVAL;
1687 goto cleanup;
1688 }
1689
1690 retval = cms_signeddata_create(context, plgctx, reqctx, idctx,
1691 cms_msg_type, include_certchain, key_pack, key_pack_len,
1692 &signed_data, (unsigned int *)&signed_data_len);
1693 if (retval) {
1694 pkiDebug("failed to create pkcs7 signed data\n");
1695 goto cleanup;
1696 }
1697
1698 /* check we have client's certificate */
1699 if (reqctx->received_cert == NULL) {
1700 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1701 goto cleanup;
1702 }
1703 encerts = sk_X509_new_null();
1704 sk_X509_push(encerts, reqctx->received_cert);
1705
1706 cipher = EVP_des_ede3_cbc();
1707 in = BIO_new(BIO_s_mem());
1708 switch (pa_type) {
1709 case KRB5_PADATA_PK_AS_REQ:
1710 prepare_enc_data(signed_data, signed_data_len, &enc_data,
1711 &enc_data_len);
1712 retval = BIO_write(in, enc_data, enc_data_len);
1713 if (retval != enc_data_len) {
1714 pkiDebug("BIO_write only wrote %d\n", retval);
1715 goto cleanup;
1716 }
1717 break;
1718 case KRB5_PADATA_PK_AS_REP_OLD:
1719 case KRB5_PADATA_PK_AS_REQ_OLD:
1720 retval = BIO_write(in, signed_data, signed_data_len);
1721 if (retval != signed_data_len) {
1722 pkiDebug("BIO_write only wrote %d\n", retval);
1723 /* Solaris Kerberos */
1724 retval = KRB5KRB_ERR_GENERIC;
1725 goto cleanup;
1726 }
1727 break;
1728 default:
1729 retval = -1;
1730 goto cleanup;
1731 }
1732
1733 p7 = PKCS7_encrypt(encerts, in, cipher, flags);
1734 if (p7 == NULL) {
1735 pkiDebug("failed to encrypt PKCS7 object\n");
1736 retval = -1;
1737 goto cleanup;
1738 }
1739 switch (pa_type) {
1740 case KRB5_PADATA_PK_AS_REQ:
1741 p7->d.enveloped->enc_data->content_type =
1742 OBJ_nid2obj(NID_pkcs7_signed);
1743 break;
1744 case KRB5_PADATA_PK_AS_REP_OLD:
1745 case KRB5_PADATA_PK_AS_REQ_OLD:
1746 p7->d.enveloped->enc_data->content_type =
1747 OBJ_nid2obj(NID_pkcs7_data);
1748 break;
1749 }
1750
1751 *out_len = i2d_PKCS7(p7, NULL);
1752 if (!*out_len || (p = *out = (unsigned char *)malloc(*out_len)) == NULL) {
1753 retval = ENOMEM;
1754 goto cleanup;
1755 }
1756 retval = i2d_PKCS7(p7, &p);
1757 if (!retval) {
1758 pkiDebug("unable to write pkcs7 object\n");
1759 goto cleanup;
1760 }
1761 retval = 0;
1762
1763 #ifdef DEBUG_ASN1
1764 print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data");
1765 #endif
1766
1767 cleanup:
1768 if (p7 != NULL)
1769 PKCS7_free(p7);
1770 if (in != NULL)
1771 BIO_free(in);
1772 if (signed_data != NULL)
1773 free(signed_data);
1774 if (enc_data != NULL)
1775 free(enc_data);
1776 if (encerts != NULL)
1777 sk_X509_free(encerts);
1778
1779 return retval;
1780 }
1781
1782 krb5_error_code
1783 cms_envelopeddata_verify(krb5_context context,
1784 pkinit_plg_crypto_context plg_cryptoctx,
1785 pkinit_req_crypto_context req_cryptoctx,
1786 pkinit_identity_crypto_context id_cryptoctx,
1787 krb5_preauthtype pa_type,
1788 int require_crl_checking,
1789 unsigned char *enveloped_data,
1790 unsigned int enveloped_data_len,
1791 unsigned char **data,
1792 unsigned int *data_len)
1793 {
1794 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
1795 PKCS7 *p7 = NULL;
1796 BIO *out = NULL;
1797 int i = 0;
1798 unsigned int size = 0;
1799 const unsigned char *p = enveloped_data;
1800 unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0;
1801 unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL;
1802 int msg_type = 0;
1803
1804 #ifdef DEBUG_ASN1
1805 print_buffer_bin(enveloped_data, enveloped_data_len,
1806 "/tmp/client_envelopeddata");
1807 #endif
1808 /* decode received PKCS7 message */
1809 if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) {
1810 unsigned long err = ERR_peek_error();
1811 pkiDebug("failed to decode pkcs7\n");
1812 krb5_set_error_message(context, retval, "%s\n",
1813 ERR_error_string(err, NULL));
1814 goto cleanup;
1815 }
1816
1817 /* verify that the received message is PKCS7 EnvelopedData message */
1818 if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped) {
1819 pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
1820 OBJ_obj2nid(p7->type));
1821 krb5_set_error_message(context, retval, "wrong oid\n");
1822 goto cleanup;
1823 }
1824
1825 /* decrypt received PKCS7 message */
1826 out = BIO_new(BIO_s_mem());
1827 if (pkcs7_decrypt(context, id_cryptoctx, p7, out)) {
1828 pkiDebug("PKCS7 decryption successful\n");
1829 } else {
1830 unsigned long err = ERR_peek_error();
1831 if (err != 0)
1832 krb5_set_error_message(context, retval, "%s\n",
1833 ERR_error_string(err, NULL));
1834 pkiDebug("PKCS7 decryption failed\n");
1835 goto cleanup;
1836 }
1837
1838 /* transfer the decoded PKCS7 SignedData message into a separate buffer */
1839 for (;;) {
1840 if ((tmp_buf = realloc(tmp_buf, size + 1024 * 10)) == NULL)
1841 goto cleanup;
1842 i = BIO_read(out, &(tmp_buf[size]), 1024 * 10);
1843 if (i <= 0)
1844 break;
1845 else
1846 size += i;
1847 }
1848 tmp_buf_len = size;
1849
1850 #ifdef DEBUG_ASN1
1851 print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack");
1852 #endif
1853 /* verify PKCS7 SignedData message */
1854 switch (pa_type) {
1855 case KRB5_PADATA_PK_AS_REP:
1856 msg_type = CMS_ENVEL_SERVER;
1857
1858 break;
1859 case KRB5_PADATA_PK_AS_REP_OLD:
1860 msg_type = CMS_SIGN_DRAFT9;
1861 break;
1862 default:
1863 pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__, pa_type);
1864 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1865 goto cleanup;
1866 }
1867 /*
1868 * If this is the RFC style, wrap the signed data to make
1869 * decoding easier in the verify routine.
1870 * For draft9-compatible, we don't do anything because it
1871 * is already wrapped.
1872 */
1873 #ifdef LONGHORN_BETA_COMPAT
1874 /*
1875 * The Longhorn server returns the expected RFC-style data, but
1876 * it is missing the sequence tag and length, so it requires
1877 * special processing when wrapping.
1878 * This will hopefully be fixed before the final release and
1879 * this can all be removed.
1880 */
1881 if (msg_type == CMS_ENVEL_SERVER || longhorn == 1) {
1882 retval = wrap_signeddata(tmp_buf, tmp_buf_len,
1883 &tmp_buf2, &tmp_buf2_len, longhorn);
1884 if (retval) {
1885 pkiDebug("failed to encode signeddata\n");
1886 goto cleanup;
1887 }
1888 vfy_buf = tmp_buf2;
1889 vfy_buf_len = tmp_buf2_len;
1890
1891 } else {
1892 vfy_buf = tmp_buf;
1893 vfy_buf_len = tmp_buf_len;
1894 }
1895 #else
1896 if (msg_type == CMS_ENVEL_SERVER) {
1897 retval = wrap_signeddata(tmp_buf, tmp_buf_len,
1898 &tmp_buf2, &tmp_buf2_len);
1899 if (retval) {
1900 pkiDebug("failed to encode signeddata\n");
1901 goto cleanup;
1902 }
1903 vfy_buf = tmp_buf2;
1904 vfy_buf_len = tmp_buf2_len;
1905
1906 } else {
1907 vfy_buf = tmp_buf;
1908 vfy_buf_len = tmp_buf_len;
1909 }
1910 #endif
1911
1912 #ifdef DEBUG_ASN1
1913 print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2");
1914 #endif
1915
1916 retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx,
1917 id_cryptoctx, msg_type,
1918 require_crl_checking,
1919 vfy_buf, vfy_buf_len,
1920 data, data_len, NULL, NULL);
1921
1922 if (!retval)
1923 pkiDebug("PKCS7 Verification Success\n");
1924 else {
1925 pkiDebug("PKCS7 Verification Failure\n");
1926 goto cleanup;
1927 }
1928
1929 retval = 0;
1930
1931 cleanup:
1932
1933 if (p7 != NULL)
1934 PKCS7_free(p7);
1935 if (out != NULL)
1936 BIO_free(out);
1937 if (tmp_buf != NULL)
1938 free(tmp_buf);
1939 if (tmp_buf2 != NULL)
1940 free(tmp_buf2);
1941
1942 return retval;
1943 }
1944
1945 /* ARGSUSED */
1946 static krb5_error_code
1947 crypto_retrieve_X509_sans(krb5_context context,
1948 pkinit_plg_crypto_context plgctx,
1949 pkinit_req_crypto_context reqctx,
1950 X509 *cert,
1951 krb5_principal **princs_ret,
1952 krb5_principal **upn_ret,
1953 unsigned char ***dns_ret)
1954 {
1955 krb5_error_code retval = EINVAL;
1956 char buf[DN_BUF_LEN];
1957 int p = 0, u = 0, d = 0;
1958 krb5_principal *princs = NULL;
1959 krb5_principal *upns = NULL;
1960 unsigned char **dnss = NULL;
1961 int i, num_found = 0;
1962
1963 if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
1964 pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
1965 return retval;
1966 }
1967
1968 if (cert == NULL) {
1969 pkiDebug("%s: no certificate!\n", __FUNCTION__);
1970 return retval;
1971 }
1972
1973 X509_NAME_oneline(X509_get_subject_name(cert),
1974 buf, sizeof(buf));
1975 pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
1976
1977 if ((i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
1978 X509_EXTENSION *ext = NULL;
1979 GENERAL_NAMES *ialt = NULL;
1980 GENERAL_NAME *gen = NULL;
1981 int ret = 0;
1982 unsigned int num_sans = 0;
1983
1984 if (!(ext = X509_get_ext(cert, i)) || !(ialt = X509V3_EXT_d2i(ext))) {
1985 pkiDebug("%s: found no subject alt name extensions\n",
1986 __FUNCTION__);
1987 goto cleanup;
1988 }
1989 num_sans = sk_GENERAL_NAME_num(ialt);
1990
1991 pkiDebug("%s: found %d subject alt name extension(s)\n",
1992 __FUNCTION__, num_sans);
1993
1994 /* OK, we're likely returning something. Allocate return values */
1995 if (princs_ret != NULL) {
1996 princs = calloc(num_sans + 1, sizeof(krb5_principal));
1997 if (princs == NULL) {
1998 retval = ENOMEM;
1999 goto cleanup;
2000 }
2001 }
2002 if (upn_ret != NULL) {
2003 upns = calloc(num_sans + 1, sizeof(krb5_principal));
2004 if (upns == NULL) {
2005 retval = ENOMEM;
2006 goto cleanup;
2007 }
2008 }
2009 if (dns_ret != NULL) {
2010 dnss = calloc(num_sans + 1, sizeof(*dnss));
2011 if (dnss == NULL) {
2012 retval = ENOMEM;
2013 goto cleanup;
2014 }
2015 }
2016
2017 for (i = 0; i < num_sans; i++) {
2018 krb5_data name = { 0, 0, NULL };
2019
2020 gen = sk_GENERAL_NAME_value(ialt, i);
2021 switch (gen->type) {
2022 case GEN_OTHERNAME:
2023 name.length = gen->d.otherName->value->value.sequence->length;
2024 name.data = (char *)gen->d.otherName->value->value.sequence->data;
2025 if (princs != NULL
2026 && OBJ_cmp(plgctx->id_pkinit_san,
2027 gen->d.otherName->type_id) == 0) {
2028 #ifdef DEBUG_ASN1
2029 print_buffer_bin((unsigned char *)name.data, name.length,
2030 "/tmp/pkinit_san");
2031 #endif
2032 ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
2033 if (ret) {
2034 pkiDebug("%s: failed decoding pkinit san value\n",
2035 __FUNCTION__);
2036 } else {
2037 p++;
2038 num_found++;
2039 }
2040 } else if (upns != NULL
2041 && OBJ_cmp(plgctx->id_ms_san_upn,
2042 gen->d.otherName->type_id) == 0) {
2043 ret = krb5_parse_name(context, name.data, &upns[u]);
2044 if (ret) {
2045 pkiDebug("%s: failed parsing ms-upn san value\n",
2046 __FUNCTION__);
2047 } else {
2048 u++;
2049 num_found++;
2050 }
2051 } else {
2052 pkiDebug("%s: unrecognized othername oid in SAN\n",
2053 __FUNCTION__);
2054 continue;
2055 }
2056
2057 break;
2058 case GEN_DNS:
2059 if (dnss != NULL) {
2060 pkiDebug("%s: found dns name = %s\n",
2061 __FUNCTION__, gen->d.dNSName->data);
2062 dnss[d] = (unsigned char *)
2063 strdup((char *)gen->d.dNSName->data);
2064 if (dnss[d] == NULL) {
2065 pkiDebug("%s: failed to duplicate dns name\n",
2066 __FUNCTION__);
2067 } else {
2068 d++;
2069 num_found++;
2070 }
2071 }
2072 break;
2073 default:
2074 pkiDebug("%s: SAN type = %d expecting %d\n",
2075 __FUNCTION__, gen->type, GEN_OTHERNAME);
2076 }
2077 }
2078 sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
2079 }
2080
2081 retval = 0;
2082 if (princs)
2083 *princs_ret = princs;
2084 if (upns)
2085 *upn_ret = upns;
2086 if (dnss)
2087 *dns_ret = dnss;
2088
2089 cleanup:
2090 if (retval) {
2091 if (princs != NULL) {
2092 for (i = 0; princs[i] != NULL; i++)
2093 krb5_free_principal(context, princs[i]);
2094 free(princs);
2095 }
2096 if (upns != NULL) {
2097 for (i = 0; upns[i] != NULL; i++)
2098 krb5_free_principal(context, upns[i]);
2099 free(upns);
2100 }
2101 if (dnss != NULL) {
2102 for (i = 0; dnss[i] != NULL; i++)
2103 free(dnss[i]);
2104 free(dnss);
2105 }
2106 }
2107 return retval;
2108 }
2109
2110 /* ARGSUSED */
2111 krb5_error_code
2112 crypto_retrieve_cert_sans(krb5_context context,
2113 pkinit_plg_crypto_context plgctx,
2114 pkinit_req_crypto_context reqctx,
2115 pkinit_identity_crypto_context idctx,
2116 krb5_principal **princs_ret,
2117 krb5_principal **upn_ret,
2118 unsigned char ***dns_ret)
2119 {
2120 krb5_error_code retval = EINVAL;
2121
2122 if (reqctx->received_cert == NULL) {
2123 pkiDebug("%s: No certificate!\n", __FUNCTION__);
2124 return retval;
2125 }
2126
2127 return crypto_retrieve_X509_sans(context, plgctx, reqctx,
2128 reqctx->received_cert, princs_ret,
2129 upn_ret, dns_ret);
2130 }
2131
2132 /* ARGSUSED */
2133 krb5_error_code
2134 crypto_check_cert_eku(krb5_context context,
2135 pkinit_plg_crypto_context plgctx,
2136 pkinit_req_crypto_context reqctx,
2137 pkinit_identity_crypto_context idctx,
2138 int checking_kdc_cert,
2139 int allow_secondary_usage,
2140 int *valid_eku)
2141 {
2142 char buf[DN_BUF_LEN];
2143 int found_eku = 0;
2144 krb5_error_code retval = EINVAL;
2145 int i;
2146
2147 /* Solaris Kerberos */
2148 if (valid_eku == NULL)
2149 return retval;
2150
2151 *valid_eku = 0;
2152 if (reqctx->received_cert == NULL)
2153 goto cleanup;
2154
2155 X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
2156 buf, sizeof(buf));
2157 pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
2158
2159 if ((i = X509_get_ext_by_NID(reqctx->received_cert,
2160 NID_ext_key_usage, -1)) >= 0) {
2161 EXTENDED_KEY_USAGE *extusage;
2162
2163 extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage,
2164 NULL, NULL);
2165 if (extusage) {
2166 pkiDebug("%s: found eku info in the cert\n", __FUNCTION__);
2167 for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) {
2168 ASN1_OBJECT *tmp_oid;
2169
2170 tmp_oid = sk_ASN1_OBJECT_value(extusage, i);
2171 pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
2172 __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage),
2173 allow_secondary_usage);
2174 if (checking_kdc_cert) {
2175 if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0)
2176 || (allow_secondary_usage
2177 && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0))
2178 found_eku = 1;
2179 } else {
2180 if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0)
2181 || (allow_secondary_usage
2182 && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0))
2183 found_eku = 1;
2184 }
2185 }
2186 }
2187 EXTENDED_KEY_USAGE_free(extusage);
2188
2189 if (found_eku) {
2190 ASN1_BIT_STRING *usage = NULL;
2191 pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
2192
2193 /* check that digitalSignature KeyUsage is present */
2194 if ((usage = X509_get_ext_d2i(reqctx->received_cert,
2195 NID_key_usage, NULL, NULL))) {
2196
2197 if (!ku_reject(reqctx->received_cert,
2198 X509v3_KU_DIGITAL_SIGNATURE)) {
2199 pkiDebug("%s: found digitalSignature KU\n",
2200 __FUNCTION__);
2201 *valid_eku = 1;
2202 } else
2203 pkiDebug("%s: didn't find digitalSignature KU\n",
2204 __FUNCTION__);
2205 }
2206 ASN1_BIT_STRING_free(usage);
2207 }
2208 }
2209 retval = 0;
2210 cleanup:
2211 pkiDebug("%s: returning retval %d, valid_eku %d\n",
2212 __FUNCTION__, retval, *valid_eku);
2213 return retval;
2214 }
2215
2216 krb5_error_code
2217 pkinit_octetstring2key(krb5_context context,
2218 krb5_enctype etype,
2219 unsigned char *key,
2220 unsigned int dh_key_len,
2221 krb5_keyblock * key_block)
2222 {
2223 krb5_error_code retval;
2224 unsigned char *buf = NULL;
2225 unsigned char md[SHA_DIGEST_LENGTH];
2226 unsigned char counter;
2227 size_t keybytes, keylength, offset;
2228 krb5_data random_data;
2229
2230
2231 if ((buf = (unsigned char *) malloc(dh_key_len)) == NULL) {
2232 retval = ENOMEM;
2233 goto cleanup;
2234 }
2235 (void) memset(buf, 0, dh_key_len);
2236
2237 counter = 0;
2238 offset = 0;
2239 do {
2240 SHA_CTX c;
2241
2242 SHA1_Init(&c);
2243 SHA1_Update(&c, &counter, 1);
2244 SHA1_Update(&c, key, dh_key_len);
2245 SHA1_Final(md, &c);
2246
2247 if (dh_key_len - offset < sizeof(md))
2248 (void) memcpy(buf + offset, md, dh_key_len - offset);
2249 else
2250 (void) memcpy(buf + offset, md, sizeof(md));
2251
2252 offset += sizeof(md);
2253 counter++;
2254 } while (offset < dh_key_len);
2255
2256 /* Solaris Kerberos */
2257 key_block->magic = KV5M_KEYBLOCK;
2258 key_block->enctype = etype;
2259
2260 retval = krb5_c_keylengths(context, etype, &keybytes, &keylength);
2261 if (retval)
2262 goto cleanup;
2263
2264 key_block->length = keylength;
2265 key_block->contents = calloc(keylength, sizeof(unsigned char *));
2266 if (key_block->contents == NULL) {
2267 retval = ENOMEM;
2268 goto cleanup;
2269 }
2270
2271 random_data.length = keybytes;
2272 random_data.data = (char *)buf;
2273
2274 retval = krb5_c_random_to_key(context, etype, &random_data, key_block);
2275
2276 cleanup:
2277 if (buf != NULL)
2278 free(buf);
2279 if (retval && key_block->contents != NULL && key_block->length != 0) {
2280 (void) memset(key_block->contents, 0, key_block->length);
2281 key_block->length = 0;
2282 }
2283
2284 return retval;
2285 }
2286
2287 /* ARGSUSED */
2288 krb5_error_code
2289 client_create_dh(krb5_context context,
2290 pkinit_plg_crypto_context plg_cryptoctx,
2291 pkinit_req_crypto_context cryptoctx,
2292 pkinit_identity_crypto_context id_cryptoctx,
2293 int dh_size,
2294 unsigned char **dh_params,
2295 unsigned int *dh_params_len,
2296 unsigned char **dh_pubkey,
2297 unsigned int *dh_pubkey_len)
2298 {
2299 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2300 unsigned char *buf = NULL;
2301 int dh_err = 0;
2302 ASN1_INTEGER *asn_pub_key = NULL;
2303 BIGNUM *p, *g, *q;
2304 const BIGNUM *pub_key;
2305
2306 if (cryptoctx->dh == NULL) {
2307 if ((cryptoctx->dh = DH_new()) == NULL)
2308 goto cleanup;
2309 if ((g = BN_new()) == NULL || (q = BN_new()) == NULL)
2310 goto cleanup;
2311
2312 switch(dh_size) {
2313 case 1024:
2314 pkiDebug("client uses 1024 DH keys\n");
2315 cryptoctx->dh = make_dhprime(pkinit_1024_dhprime,
2316 sizeof(pkinit_1024_dhprime));
2317 break;
2318 case 2048:
2319 pkiDebug("client uses 2048 DH keys\n");
2320 cryptoctx->dh = make_dhprime(pkinit_2048_dhprime,
2321 sizeof(pkinit_2048_dhprime));
2322 break;
2323 case 4096:
2324 pkiDebug("client uses 4096 DH keys\n");
2325 cryptoctx->dh = make_dhprime(pkinit_4096_dhprime,
2326 sizeof(pkinit_4096_dhprime));
2327 break;
2328 }
2329 if (cryptoctx->dh == NULL)
2330 goto cleanup;
2331 }
2332
2333 DH_generate_key(cryptoctx->dh);
2334 DH_get0_key(cryptoctx->dh, &pub_key, NULL);
2335
2336 /* Solaris Kerberos */
2337 #ifdef DEBUG
2338 DH_check(cryptoctx->dh, &dh_err);
2339 if (dh_err != 0) {
2340 pkiDebug("Warning: dh_check failed with %d\n", dh_err);
2341 if (dh_err & DH_CHECK_P_NOT_PRIME)
2342 pkiDebug("p value is not prime\n");
2343 if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME)
2344 pkiDebug("p value is not a safe prime\n");
2345 if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR)
2346 pkiDebug("unable to check the generator value\n");
2347 if (dh_err & DH_NOT_SUITABLE_GENERATOR)
2348 pkiDebug("the g value is not a generator\n");
2349 }
2350 #endif
2351 #ifdef DEBUG_DH
2352 print_dh(cryptoctx->dh, "client's DH params\n");
2353 print_pubkey(pub_key, "client's pub_key=");
2354 #endif
2355
2356 DH_check_pub_key(cryptoctx->dh, pub_key, &dh_err);
2357 if (dh_err != 0) {
2358 pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
2359 goto cleanup;
2360 }
2361
2362 /* pack DHparams */
2363 /* aglo: usually we could just call i2d_DHparams to encode DH params
2364 * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
2365 */
2366 DH_get0_pqg(cryptoctx->dh, (const BIGNUM **)&p, (const BIGNUM **)&q,
2367 (const BIGNUM **)&g);
2368 retval = pkinit_encode_dh_params(p, g, q, dh_params, dh_params_len);
2369 if (retval)
2370 goto cleanup;
2371
2372 /* pack DH public key */
2373 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2374 * encoding shall be used as the contents (the value) of the
2375 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2376 * data element
2377 */
2378 if ((asn_pub_key = BN_to_ASN1_INTEGER(pub_key, NULL)) == NULL)
2379 goto cleanup;
2380 *dh_pubkey_len = i2d_ASN1_INTEGER(asn_pub_key, NULL);
2381 if ((buf = *dh_pubkey = (unsigned char *)
2382 malloc((size_t) *dh_pubkey_len)) == NULL) {
2383 retval = ENOMEM;
2384 goto cleanup;
2385 }
2386 i2d_ASN1_INTEGER(asn_pub_key, &buf);
2387
2388 if (asn_pub_key != NULL)
2389 ASN1_INTEGER_free(asn_pub_key);
2390
2391 retval = 0;
2392 return retval;
2393
2394 cleanup:
2395 if (cryptoctx->dh != NULL)
2396 DH_free(cryptoctx->dh);
2397 cryptoctx->dh = NULL;
2398 if (*dh_params != NULL)
2399 free(*dh_params);
2400 *dh_params = NULL;
2401 if (*dh_pubkey != NULL)
2402 free(*dh_pubkey);
2403 *dh_pubkey = NULL;
2404 if (asn_pub_key != NULL)
2405 ASN1_INTEGER_free(asn_pub_key);
2406
2407 return retval;
2408 }
2409
2410 /* ARGSUSED */
2411 krb5_error_code
2412 client_process_dh(krb5_context context,
2413 pkinit_plg_crypto_context plg_cryptoctx,
2414 pkinit_req_crypto_context cryptoctx,
2415 pkinit_identity_crypto_context id_cryptoctx,
2416 unsigned char *subjectPublicKey_data,
2417 unsigned int subjectPublicKey_length,
2418 unsigned char **client_key,
2419 unsigned int *client_key_len)
2420 {
2421 /* Solaris Kerberos */
2422 krb5_error_code retval = KRB5_PREAUTH_FAILED;
2423 BIGNUM *server_pub_key = NULL;
2424 ASN1_INTEGER *pub_key = NULL;
2425 const unsigned char *p = NULL;
2426 unsigned char *data = NULL;
2427 long data_len;
2428
2429 /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */
2430
2431 if (der_decode_data(subjectPublicKey_data, (long)subjectPublicKey_length,
2432 &data, &data_len) != 0) {
2433 pkiDebug("failed to decode subjectPublicKey\n");
2434 /* Solaris Kerberos */
2435 retval = KRB5_PREAUTH_FAILED;
2436 goto cleanup;
2437 }
2438
2439 *client_key_len = DH_size(cryptoctx->dh);
2440 if ((*client_key = (unsigned char *)
2441 malloc((size_t) *client_key_len)) == NULL) {
2442 retval = ENOMEM;
2443 goto cleanup;
2444 }
2445 p = data;
2446 if ((pub_key = d2i_ASN1_INTEGER(NULL, &p, data_len)) == NULL)
2447 goto cleanup;
2448 if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL)
2449 goto cleanup;
2450
2451 DH_compute_key(*client_key, server_pub_key, cryptoctx->dh);
2452 #ifdef DEBUG_DH
2453 print_pubkey(server_pub_key, "server's pub_key=");
2454 pkiDebug("client secret key (%d)= ", *client_key_len);
2455 print_buffer(*client_key, *client_key_len);
2456 #endif
2457
2458 retval = 0;
2459 if (server_pub_key != NULL)
2460 BN_free(server_pub_key);
2461 if (pub_key != NULL)
2462 ASN1_INTEGER_free(pub_key);
2463 if (data != NULL)
2464 free (data);
2465
2466 return retval;
2467
2468 cleanup:
2469 if (*client_key != NULL)
2470 free(*client_key);
2471 *client_key = NULL;
2472 if (pub_key != NULL)
2473 ASN1_INTEGER_free(pub_key);
2474 if (data != NULL)
2475 free (data);
2476
2477 return retval;
2478 }
2479
2480 /* ARGSUSED */
2481 krb5_error_code
2482 server_check_dh(krb5_context context,
2483 pkinit_plg_crypto_context cryptoctx,
2484 pkinit_req_crypto_context req_cryptoctx,
2485 pkinit_identity_crypto_context id_cryptoctx,
2486 krb5_octet_data *dh_params,
2487 int minbits)
2488 {
2489 DH *dh = NULL;
2490 unsigned char *tmp = NULL;
2491 int dh_prime_bits;
2492 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
2493 const BIGNUM *p, *g, *q, *p2;
2494
2495 tmp = dh_params->data;
2496 dh = DH_new();
2497 dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length);
2498 if (dh == NULL) {
2499 pkiDebug("failed to decode dhparams\n");
2500 goto cleanup;
2501 }
2502
2503 DH_get0_pqg(dh, &p, &q, &g);
2504
2505 /* KDC SHOULD check to see if the key parameters satisfy its policy */
2506 dh_prime_bits = BN_num_bits(p);
2507 if (minbits && dh_prime_bits < minbits) {
2508 pkiDebug("client sent dh params with %d bits, we require %d\n",
2509 dh_prime_bits, minbits);
2510 goto cleanup;
2511 }
2512
2513 /* check dhparams is group 2 */
2514 DH_get0_pqg(cryptoctx->dh_1024, &p2, NULL, NULL);
2515 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
2516 retval = 0;
2517 goto cleanup;
2518 }
2519
2520 /* check dhparams is group 14 */
2521 DH_get0_pqg(cryptoctx->dh_2048, &p2, NULL, NULL);
2522 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
2523 retval = 0;
2524 goto cleanup;
2525 }
2526
2527 /* check dhparams is group 16 */
2528 DH_get0_pqg(cryptoctx->dh_4096, &p2, NULL, NULL);
2529 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
2530 retval = 0;
2531 goto cleanup;
2532 }
2533
2534 cleanup:
2535 if (retval == 0)
2536 req_cryptoctx->dh = dh;
2537 else
2538 DH_free(dh);
2539
2540 return retval;
2541 }
2542
2543 /* kdc's dh function */
2544 /* ARGSUSED */
2545 krb5_error_code
2546 server_process_dh(krb5_context context,
2547 pkinit_plg_crypto_context plg_cryptoctx,
2548 pkinit_req_crypto_context cryptoctx,
2549 pkinit_identity_crypto_context id_cryptoctx,
2550 unsigned char *data,
2551 unsigned int data_len,
2552 unsigned char **dh_pubkey,
2553 unsigned int *dh_pubkey_len,
2554 unsigned char **server_key,
2555 unsigned int *server_key_len)
2556 {
2557 /* Solaris Kerberos */
2558 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2559 DH *dh = NULL, *dh_server = NULL;
2560 const BIGNUM *p, *g, *q, *s_pub_key;
2561 BIGNUM *pub_key;
2562 unsigned char *s = NULL;
2563 ASN1_INTEGER *asn_pub_key = NULL;
2564
2565 /* get client's received DH parameters that we saved in server_check_dh */
2566 dh = cryptoctx->dh;
2567
2568 dh_server = DH_new();
2569 if (dh_server == NULL)
2570 goto cleanup;
2571 DH_get0_pqg(dh, &p, &g, &q);
2572 DH_set0_pqg(dh_server, BN_dup(p), BN_dup(g), BN_dup(q));
2573
2574 /* decode client's public key */
2575 s = data;
2576 asn_pub_key = d2i_ASN1_INTEGER(NULL,
2577 (const unsigned char **)&s, (int)data_len);
2578 if (asn_pub_key == NULL)
2579 goto cleanup;
2580 pub_key = ASN1_INTEGER_to_BN(asn_pub_key, NULL);
2581 if (pub_key == NULL)
2582 goto cleanup;
2583 DH_set0_key(dh, pub_key, NULL);
2584 ASN1_INTEGER_free(asn_pub_key);
2585
2586 if (!DH_generate_key(dh_server))
2587 goto cleanup;
2588
2589 /* generate DH session key */
2590 *server_key_len = DH_size(dh_server);
2591 if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len))
2592 == NULL)
2593 goto cleanup;
2594 DH_compute_key(*server_key, pub_key, dh_server);
2595 DH_get0_key(dh_server, &s_pub_key, NULL);
2596
2597 #ifdef DEBUG_DH
2598 print_dh(dh_server, "client&server's DH params\n");
2599 print_pubkey(pub_key, "client's pub_key=");
2600 print_pubkey(s_pub_key, "server's pub_key=");
2601 pkiDebug("server secret key=");
2602 print_buffer(*server_key, *server_key_len);
2603 #endif
2604
2605 /* KDC reply */
2606 /* pack DH public key */
2607 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2608 * encoding shall be used as the contents (the value) of the
2609 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2610 * data element
2611 */
2612 if ((asn_pub_key = BN_to_ASN1_INTEGER(s_pub_key, NULL)) == NULL)
2613 goto cleanup;
2614 *dh_pubkey_len = i2d_ASN1_INTEGER(asn_pub_key, NULL);
2615 if ((s = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len))
2616 == NULL)
2617 goto cleanup;
2618 i2d_ASN1_INTEGER(asn_pub_key, &s);
2619 if (asn_pub_key != NULL)
2620 ASN1_INTEGER_free(asn_pub_key);
2621
2622 retval = 0;
2623
2624 if (dh_server != NULL)
2625 DH_free(dh_server);
2626 return retval;
2627
2628 cleanup:
2629 if (dh_server != NULL)
2630 DH_free(dh_server);
2631 if (*dh_pubkey != NULL)
2632 free(*dh_pubkey);
2633 if (*server_key != NULL)
2634 free(*server_key);
2635
2636 return retval;
2637 }
2638
2639 /*
2640 * Solaris Kerberos:
2641 * Add locking around did_init to make it MT-safe.
2642 */
2643 static krb5_error_code
2644 openssl_init()
2645 {
2646 krb5_error_code ret = 0;
2647 static int did_init = 0;
2648 static k5_mutex_t init_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
2649
2650 ret = k5_mutex_lock(&init_mutex);
2651 if (ret == 0) {
2652 if (!did_init) {
2653 /* initialize openssl routines */
2654 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2655 /*
2656 * As of version 1.1.0, OpenSSL will automatically allocate
2657 * resources as-needed.
2658 */
2659 CRYPTO_malloc_init();
2660 ERR_load_crypto_strings();
2661 OpenSSL_add_all_algorithms();
2662 #endif
2663 did_init++;
2664 }
2665 k5_mutex_unlock(&init_mutex);
2666 }
2667 return (ret);
2668 }
2669
2670 static krb5_error_code
2671 pkinit_encode_dh_params(const BIGNUM *p, const BIGNUM *g, const BIGNUM *q,
2672 unsigned char **buf, unsigned int *buf_len)
2673 {
2674 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2675 int bufsize = 0, r = 0;
2676 unsigned char *tmp = NULL;
2677 ASN1_INTEGER *ap = NULL, *ag = NULL, *aq = NULL;
2678
2679 if ((ap = BN_to_ASN1_INTEGER(p, NULL)) == NULL)
2680 goto cleanup;
2681 if ((ag = BN_to_ASN1_INTEGER(g, NULL)) == NULL)
2682 goto cleanup;
2683 if ((aq = BN_to_ASN1_INTEGER(q, NULL)) == NULL)
2684 goto cleanup;
2685 bufsize = i2d_ASN1_INTEGER(ap, NULL);
2686 bufsize += i2d_ASN1_INTEGER(ag, NULL);
2687 bufsize += i2d_ASN1_INTEGER(aq, NULL);
2688
2689 r = ASN1_object_size(1, bufsize, V_ASN1_SEQUENCE);
2690
2691 tmp = *buf = (unsigned char *)malloc((size_t) r);
2692 if (tmp == NULL)
2693 goto cleanup;
2694
2695 ASN1_put_object(&tmp, 1, bufsize, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
2696
2697 i2d_ASN1_INTEGER(ap, &tmp);
2698 i2d_ASN1_INTEGER(ag, &tmp);
2699 i2d_ASN1_INTEGER(aq, &tmp);
2700
2701 *buf_len = r;
2702
2703 retval = 0;
2704
2705 cleanup:
2706 if (ap != NULL)
2707 ASN1_INTEGER_free(ap);
2708 if (ag != NULL)
2709 ASN1_INTEGER_free(ag);
2710 if (aq != NULL)
2711 ASN1_INTEGER_free(aq);
2712
2713 return retval;
2714 }
2715
2716 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2717
2718 static DH *
2719 pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len)
2720 {
2721 ASN1_INTEGER ai, *aip = NULL;
2722 long length = (long) len;
2723
2724 M_ASN1_D2I_vars(a, DH *, DH_new);
2725
2726 M_ASN1_D2I_Init();
2727 M_ASN1_D2I_start_sequence();
2728 aip = &ai;
2729 ai.data = NULL;
2730 ai.length = 0;
2731 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
2732 if (aip == NULL)
2733 return NULL;
2734 else {
2735 (*a)->p = ASN1_INTEGER_to_BN(aip, NULL);
2736 if ((*a)->p == NULL)
2737 return NULL;
2738 if (ai.data != NULL) {
2739 OPENSSL_free(ai.data);
2740 ai.data = NULL;
2741 ai.length = 0;
2742 }
2743 }
2744 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
2745 if (aip == NULL)
2746 return NULL;
2747 else {
2748 (*a)->g = ASN1_INTEGER_to_BN(aip, NULL);
2749 if ((*a)->g == NULL)
2750 return NULL;
2751 if (ai.data != NULL) {
2752 OPENSSL_free(ai.data);
2753 ai.data = NULL;
2754 ai.length = 0;
2755 }
2756
2757 }
2758 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
2759 if (aip == NULL)
2760 return NULL;
2761 else {
2762 (*a)->q = ASN1_INTEGER_to_BN(aip, NULL);
2763 if ((*a)->q == NULL)
2764 return NULL;
2765 if (ai.data != NULL) {
2766 OPENSSL_free(ai.data);
2767 ai.data = NULL;
2768 ai.length = 0;
2769 }
2770
2771 }
2772 M_ASN1_D2I_end_sequence();
2773 M_ASN1_D2I_Finish(a, DH_free, 0);
2774
2775 }
2776
2777 #else
2778
2779 /*
2780 * This is taken from the internal dh_asn1.c file in OpenSSL 1.1, modified to
2781 * make q an optional field.
2782 */
2783
2784 typedef struct {
2785 ASN1_BIT_STRING *seed;
2786 BIGNUM *counter;
2787 } int_dhvparams;
2788
2789 typedef struct {
2790 BIGNUM *p;
2791 BIGNUM *q;
2792 BIGNUM *g;
2793 BIGNUM *j;
2794 int_dhvparams *vparams;
2795 } int_dhx942_dh;
2796
2797 ASN1_SEQUENCE(DHvparams) = {
2798 ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING),
2799 ASN1_SIMPLE(int_dhvparams, counter, BIGNUM)
2800 } static_ASN1_SEQUENCE_END_name(int_dhvparams, DHvparams)
2801
2802 ASN1_SEQUENCE(DHxparams) = {
2803 ASN1_SIMPLE(int_dhx942_dh, p, BIGNUM),
2804 ASN1_SIMPLE(int_dhx942_dh, g, BIGNUM),
2805 ASN1_OPT(int_dhx942_dh, q, BIGNUM),
2806 ASN1_OPT(int_dhx942_dh, j, BIGNUM),
2807 ASN1_OPT(int_dhx942_dh, vparams, DHvparams),
2808 } static_ASN1_SEQUENCE_END_name(int_dhx942_dh, DHxparams)
2809
2810 static DH *
2811 pkinit_decode_dh_params(DH **a, unsigned char **pp, unsigned int len)
2812 {
2813 int_dhx942_dh *params;
2814 DH *dh = *a;
2815
2816 if (dh == NULL)
2817 return NULL;
2818
2819 params = (int_dhx942_dh *)ASN1_item_d2i(NULL,
2820 (const unsigned char **)pp, len, ASN1_ITEM_rptr(DHxparams));
2821 if (params == NULL) {
2822 DH_free(dh);
2823 return NULL;
2824 }
2825
2826 DH_set0_pqg(dh, params->p, params->q, params->g);
2827 params->p = params->q = params->g = NULL;
2828 ASN1_item_free((ASN1_VALUE *)params, ASN1_ITEM_rptr(DHxparams));
2829 return dh;
2830 }
2831
2832 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
2833
2834 static krb5_error_code
2835 pkinit_create_sequence_of_principal_identifiers(
2836 krb5_context context,
2837 pkinit_plg_crypto_context plg_cryptoctx,
2838 pkinit_req_crypto_context req_cryptoctx,
2839 pkinit_identity_crypto_context id_cryptoctx,
2840 int type,
2841 krb5_data **out_data)
2842 {
2843 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2844 krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
2845 krb5_data *td_certifiers = NULL, *data = NULL;
2846 krb5_typed_data **typed_data = NULL;
2847
2848 switch(type) {
2849 case TD_TRUSTED_CERTIFIERS:
2850 retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
2851 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
2852 if (retval) {
2853 pkiDebug("create_krb5_trustedCertifiers failed\n");
2854 goto cleanup;
2855 }
2856 break;
2857 case TD_INVALID_CERTIFICATES:
2858 retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
2859 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
2860 if (retval) {
2861 pkiDebug("create_krb5_invalidCertificates failed\n");
2862 goto cleanup;
2863 }
2864 break;
2865 default:
2866 retval = -1;
2867 goto cleanup;
2868 }
2869
2870 retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_trusted_certifiers, &td_certifiers);
2871 if (retval) {
2872 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
2873 goto cleanup;
2874 }
2875 #ifdef DEBUG_ASN1
2876 print_buffer_bin((unsigned char *)td_certifiers->data,
2877 td_certifiers->length, "/tmp/kdc_td_certifiers");
2878 #endif
2879 typed_data = malloc (2 * sizeof(krb5_typed_data *));
2880 if (typed_data == NULL) {
2881 retval = ENOMEM;
2882 goto cleanup;
2883 }
2884 typed_data[1] = NULL;
2885 init_krb5_typed_data(&typed_data[0]);
2886 if (typed_data[0] == NULL) {
2887 retval = ENOMEM;
2888 goto cleanup;
2889 }
2890 typed_data[0]->type = type;
2891 typed_data[0]->length = td_certifiers->length;
2892 typed_data[0]->data = (unsigned char *)td_certifiers->data;
2893 retval = k5int_encode_krb5_typed_data((const krb5_typed_data **)typed_data,
2894 &data);
2895 if (retval) {
2896 pkiDebug("encode_krb5_typed_data failed\n");
2897 goto cleanup;
2898 }
2899 #ifdef DEBUG_ASN1
2900 print_buffer_bin((unsigned char *)data->data, data->length,
2901 "/tmp/kdc_edata");
2902 #endif
2903 *out_data = (krb5_data *)malloc(sizeof(krb5_data));
2904 (*out_data)->length = data->length;
2905 (*out_data)->data = (char *)malloc(data->length);
2906 (void) memcpy((*out_data)->data, data->data, data->length);
2907
2908 retval = 0;
2909
2910 cleanup:
2911 if (krb5_trusted_certifiers != NULL)
2912 free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
2913
2914 if (data != NULL) {
2915 if (data->data != NULL)
2916 free(data->data);
2917 free(data);
2918 }
2919
2920 if (td_certifiers != NULL)
2921 free(td_certifiers);
2922
2923 if (typed_data != NULL)
2924 free_krb5_typed_data(&typed_data);
2925
2926 return retval;
2927 }
2928
2929 krb5_error_code
2930 pkinit_create_td_trusted_certifiers(krb5_context context,
2931 pkinit_plg_crypto_context plg_cryptoctx,
2932 pkinit_req_crypto_context req_cryptoctx,
2933 pkinit_identity_crypto_context id_cryptoctx,
2934 krb5_data **out_data)
2935 {
2936 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2937
2938 retval = pkinit_create_sequence_of_principal_identifiers(context,
2939 plg_cryptoctx, req_cryptoctx, id_cryptoctx,
2940 TD_TRUSTED_CERTIFIERS, out_data);
2941
2942 return retval;
2943 }
2944
2945 krb5_error_code
2946 pkinit_create_td_invalid_certificate(
2947 krb5_context context,
2948 pkinit_plg_crypto_context plg_cryptoctx,
2949 pkinit_req_crypto_context req_cryptoctx,
2950 pkinit_identity_crypto_context id_cryptoctx,
2951 krb5_data **out_data)
2952 {
2953 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2954
2955 retval = pkinit_create_sequence_of_principal_identifiers(context,
2956 plg_cryptoctx, req_cryptoctx, id_cryptoctx,
2957 TD_INVALID_CERTIFICATES, out_data);
2958
2959 return retval;
2960 }
2961
2962 /* ARGSUSED */
2963 krb5_error_code
2964 pkinit_create_td_dh_parameters(krb5_context context,
2965 pkinit_plg_crypto_context plg_cryptoctx,
2966 pkinit_req_crypto_context req_cryptoctx,
2967 pkinit_identity_crypto_context id_cryptoctx,
2968 pkinit_plg_opts *opts,
2969 krb5_data **out_data)
2970 {
2971 /* Solaris Kerberos */
2972 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
2973 unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0;
2974 unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
2975 krb5_typed_data **typed_data = NULL;
2976 krb5_data *data = NULL, *encoded_algId = NULL;
2977 krb5_algorithm_identifier **algId = NULL;
2978 const BIGNUM *p, *q, *g;
2979
2980 /* Solaris Kerberos */
2981 if (opts->dh_min_bits > 4096) {
2982 retval = EINVAL;
2983 goto cleanup;
2984 }
2985
2986 if (opts->dh_min_bits <= 1024) {
2987 DH_get0_pqg(plg_cryptoctx->dh_1024, &p, &q, &g);
2988 retval = pkinit_encode_dh_params(p, g, q, &buf1, &buf1_len);
2989 if (retval)
2990 goto cleanup;
2991 }
2992 if (opts->dh_min_bits <= 2048) {
2993 DH_get0_pqg(plg_cryptoctx->dh_2048, &p, &q, &g);
2994 retval = pkinit_encode_dh_params(p, g, q, &buf2, &buf2_len);
2995 if (retval)
2996 goto cleanup;
2997 }
2998 DH_get0_pqg(plg_cryptoctx->dh_4096, &p, &q, &g);
2999 retval = pkinit_encode_dh_params(p, g, q, &buf3, &buf3_len);
3000 if (retval)
3001 goto cleanup;
3002
3003 if (opts->dh_min_bits <= 1024) {
3004 algId = malloc(4 * sizeof(krb5_algorithm_identifier *));
3005 if (algId == NULL)
3006 goto cleanup;
3007 algId[3] = NULL;
3008 algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
3009 if (algId[0] == NULL)
3010 goto cleanup;
3011 algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
3012 if (algId[0]->parameters.data == NULL)
3013 goto cleanup;
3014 (void) memcpy(algId[0]->parameters.data, buf2, buf2_len);
3015 algId[0]->parameters.length = buf2_len;
3016 algId[0]->algorithm = dh_oid;
3017
3018 algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
3019 if (algId[1] == NULL)
3020 goto cleanup;
3021 algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
3022 if (algId[1]->parameters.data == NULL)
3023 goto cleanup;
3024 (void) memcpy(algId[1]->parameters.data, buf3, buf3_len);
3025 algId[1]->parameters.length = buf3_len;
3026 algId[1]->algorithm = dh_oid;
3027
3028 algId[2] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
3029 if (algId[2] == NULL)
3030 goto cleanup;
3031 algId[2]->parameters.data = (unsigned char *)malloc(buf1_len);
3032 if (algId[2]->parameters.data == NULL)
3033 goto cleanup;
3034 (void) memcpy(algId[2]->parameters.data, buf1, buf1_len);
3035 algId[2]->parameters.length = buf1_len;
3036 algId[2]->algorithm = dh_oid;
3037
3038 } else if (opts->dh_min_bits <= 2048) {
3039 algId = malloc(3 * sizeof(krb5_algorithm_identifier *));
3040 if (algId == NULL)
3041 goto cleanup;
3042 algId[2] = NULL;
3043 algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
3044 if (algId[0] == NULL)
3045 goto cleanup;
3046 algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
3047 if (algId[0]->parameters.data == NULL)
3048 goto cleanup;
3049 (void) memcpy(algId[0]->parameters.data, buf2, buf2_len);
3050 algId[0]->parameters.length = buf2_len;
3051 algId[0]->algorithm = dh_oid;
3052
3053 algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
3054 if (algId[1] == NULL)
3055 goto cleanup;
3056 algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
3057 if (algId[1]->parameters.data == NULL)
3058 goto cleanup;
3059 (void) memcpy(algId[1]->parameters.data, buf3, buf3_len);
3060 algId[1]->parameters.length = buf3_len;
3061 algId[1]->algorithm = dh_oid;
3062
3063 } else if (opts->dh_min_bits <= 4096) {
3064 algId = malloc(2 * sizeof(krb5_algorithm_identifier *));
3065 if (algId == NULL)
3066 goto cleanup;
3067 algId[1] = NULL;
3068 algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
3069 if (algId[0] == NULL)
3070 goto cleanup;
3071 algId[0]->parameters.data = (unsigned char *)malloc(buf3_len);
3072 if (algId[0]->parameters.data == NULL)
3073 goto cleanup;
3074 (void) memcpy(algId[0]->parameters.data, buf3, buf3_len);
3075 algId[0]->parameters.length = buf3_len;
3076 algId[0]->algorithm = dh_oid;
3077
3078 }
3079 retval = k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier **)algId, &encoded_algId);
3080 if (retval)
3081 goto cleanup;
3082 #ifdef DEBUG_ASN1
3083 print_buffer_bin((unsigned char *)encoded_algId->data,
3084 encoded_algId->length, "/tmp/kdc_td_dh_params");
3085 #endif
3086 typed_data = malloc (2 * sizeof(krb5_typed_data *));
3087 if (typed_data == NULL) {
3088 retval = ENOMEM;
3089 goto cleanup;
3090 }
3091 typed_data[1] = NULL;
3092 init_krb5_typed_data(&typed_data[0]);
3093 if (typed_data == NULL) {
3094 retval = ENOMEM;
3095 goto cleanup;
3096 }
3097 typed_data[0]->type = TD_DH_PARAMETERS;
3098 typed_data[0]->length = encoded_algId->length;
3099 typed_data[0]->data = (unsigned char *)encoded_algId->data;
3100 retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data,
3101 &data);
3102 if (retval) {
3103 pkiDebug("encode_krb5_typed_data failed\n");
3104 goto cleanup;
3105 }
3106 #ifdef DEBUG_ASN1
3107 print_buffer_bin((unsigned char *)data->data, data->length,
3108 "/tmp/kdc_edata");
3109 #endif
3110 *out_data = (krb5_data *)malloc(sizeof(krb5_data));
3111 if (*out_data == NULL)
3112 goto cleanup;
3113 (*out_data)->length = data->length;
3114 (*out_data)->data = (char *)malloc(data->length);
3115 if ((*out_data)->data == NULL) {
3116 free(*out_data);
3117 *out_data = NULL;
3118 goto cleanup;
3119 }
3120 (void) memcpy((*out_data)->data, data->data, data->length);
3121
3122 retval = 0;
3123 cleanup:
3124
3125 if (buf1 != NULL)
3126 free(buf1);
3127 if (buf2 != NULL)
3128 free(buf2);
3129 if (buf3 != NULL)
3130 free(buf3);
3131 if (data != NULL) {
3132 if (data->data != NULL)
3133 free(data->data);
3134 free(data);
3135 }
3136 if (typed_data != NULL)
3137 free_krb5_typed_data(&typed_data);
3138 if (encoded_algId != NULL)
3139 free(encoded_algId);
3140
3141 if (algId != NULL) {
3142 while(algId[i] != NULL) {
3143 if (algId[i]->parameters.data != NULL)
3144 free(algId[i]->parameters.data);
3145 free(algId[i]);
3146 i++;
3147 }
3148 free(algId);
3149 }
3150
3151 return retval;
3152 }
3153
3154 /* ARGSUSED */
3155 krb5_error_code
3156 pkinit_check_kdc_pkid(krb5_context context,
3157 pkinit_plg_crypto_context plg_cryptoctx,
3158 pkinit_req_crypto_context req_cryptoctx,
3159 pkinit_identity_crypto_context id_cryptoctx,
3160 unsigned char *pdid_buf,
3161 unsigned int pkid_len,
3162 int *valid_kdcPkId)
3163 {
3164 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
3165 PKCS7_ISSUER_AND_SERIAL *is = NULL;
3166 const unsigned char *p = pdid_buf;
3167 int status = 1;
3168 X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
3169
3170 *valid_kdcPkId = 0;
3171 pkiDebug("found kdcPkId in AS REQ\n");
3172 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
3173 if (is == NULL)
3174 goto cleanup;
3175
3176 status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
3177 if (!status) {
3178 status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
3179 if (!status)
3180 *valid_kdcPkId = 1;
3181 }
3182
3183 retval = 0;
3184 cleanup:
3185 X509_NAME_free(is->issuer);
3186 ASN1_INTEGER_free(is->serial);
3187 free(is);
3188
3189 return retval;
3190 }
3191
3192 static int
3193 pkinit_check_dh_params(const BIGNUM *p1, const BIGNUM *p2, const BIGNUM *g1,
3194 const BIGNUM *q1)
3195 {
3196 BIGNUM *g2 = NULL, *q2 = NULL;
3197 /* Solaris Kerberos */
3198 int retval = EINVAL;
3199
3200 if (!BN_cmp(p1, p2)) {
3201 g2 = BN_new();
3202 BN_set_word(g2, DH_GENERATOR_2);
3203 if (!BN_cmp(g1, g2)) {
3204 q2 = BN_new();
3205 BN_rshift1(q2, p1);
3206 if (!BN_cmp(q1, q2)) {
3207 pkiDebug("good %d dhparams\n", BN_num_bits(p1));
3208 retval = 0;
3209 } else
3210 pkiDebug("bad group 2 q dhparameter\n");
3211 BN_free(q2);
3212 } else
3213 pkiDebug("bad g dhparameter\n");
3214 BN_free(g2);
3215 } else
3216 pkiDebug("p is not well-known group 2 dhparameter\n");
3217
3218 return retval;
3219 }
3220
3221 /* ARGSUSED */
3222 krb5_error_code
3223 pkinit_process_td_dh_params(krb5_context context,
3224 pkinit_plg_crypto_context cryptoctx,
3225 pkinit_req_crypto_context req_cryptoctx,
3226 pkinit_identity_crypto_context id_cryptoctx,
3227 krb5_algorithm_identifier **algId,
3228 int *new_dh_size)
3229 {
3230 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3231 int i = 0, use_sent_dh = 0, ok = 0;
3232
3233 pkiDebug("dh parameters\n");
3234
3235 while (algId[i] != NULL) {
3236 DH *dh = NULL;
3237 unsigned char *tmp = NULL;
3238 const BIGNUM *p, *g, *q, *p2;
3239 int dh_prime_bits = 0;
3240
3241 if (algId[i]->algorithm.length != dh_oid.length ||
3242 memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
3243 goto cleanup;
3244
3245 tmp = algId[i]->parameters.data;
3246 dh = DH_new();
3247 dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length);
3248 dh_prime_bits = DH_bits(dh);
3249 pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
3250 *new_dh_size, dh_prime_bits);
3251 DH_get0_pqg(dh, &p, &q, &g);
3252 switch(dh_prime_bits) {
3253 case 1024:
3254 DH_get0_pqg(cryptoctx->dh_1024, &p2, NULL, NULL);
3255 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
3256 *new_dh_size = 1024;
3257 ok = 1;
3258 }
3259 break;
3260 case 2048:
3261 DH_get0_pqg(cryptoctx->dh_2048, &p2, NULL, NULL);
3262 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
3263 *new_dh_size = 2048;
3264 ok = 1;
3265 }
3266 break;
3267 case 4096:
3268 DH_get0_pqg(cryptoctx->dh_4096, &p2, NULL, NULL);
3269 if (pkinit_check_dh_params(p2, p, g, q) == 0) {
3270 *new_dh_size = 4096;
3271 ok = 1;
3272 }
3273 break;
3274 default:
3275 break;
3276 }
3277 if (!ok) {
3278 DH_check(dh, &retval);
3279 if (retval != 0) {
3280 pkiDebug("DH parameters provided by server are unacceptable\n");
3281 retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3282 }
3283 else {
3284 use_sent_dh = 1;
3285 ok = 1;
3286 }
3287 }
3288 if (!use_sent_dh)
3289 DH_free(dh);
3290 if (ok) {
3291 if (req_cryptoctx->dh != NULL) {
3292 DH_free(req_cryptoctx->dh);
3293 req_cryptoctx->dh = NULL;
3294 }
3295 if (use_sent_dh)
3296 req_cryptoctx->dh = dh;
3297 break;
3298 }
3299 i++;
3300 }
3301
3302 if (ok)
3303 retval = 0;
3304
3305 cleanup:
3306 return retval;
3307 }
3308
3309 /* ARGSUSED */
3310 static int
3311 openssl_callback(int ok, X509_STORE_CTX * ctx)
3312 {
3313 #ifdef DEBUG
3314 if (!ok) {
3315 char buf[DN_BUF_LEN];
3316
3317 X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
3318 pkiDebug("cert = %s\n", buf);
3319 pkiDebug("callback function: %d (%s)\n", ctx->error,
3320 X509_verify_cert_error_string(ctx->error));
3321 }
3322 #endif
3323 return ok;
3324 }
3325
3326 static int
3327 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
3328 {
3329 if (!ok)
3330 return (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL);
3331 return ok;
3332 }
3333
3334 static ASN1_OBJECT *
3335 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
3336 {
3337 int nid;
3338
3339 switch (pkcs7_type) {
3340 case CMS_SIGN_CLIENT:
3341 return cryptoctx->id_pkinit_authData;
3342 case CMS_SIGN_DRAFT9:
3343 /*
3344 * Delay creating this OID until we know we need it.
3345 * It shadows an existing OpenSSL oid. If it
3346 * is created too early, it breaks things like
3347 * the use of pkcs12 (which uses pkcs7 structures).
3348 * We need this shadow version because our code
3349 * depends on the "other" type to be unknown to the
3350 * OpenSSL code.
3351 */
3352 if (cryptoctx->id_pkinit_authData9 == NULL) {
3353 pkiDebug("%s: Creating shadow instance of pkcs7-data oid\n",
3354 __FUNCTION__);
3355 nid = OBJ_create("1.2.840.113549.1.7.1", "id-pkcs7-data",
3356 "PKCS7 data");
3357 if (nid == NID_undef)
3358 return NULL;
3359 cryptoctx->id_pkinit_authData9 = OBJ_nid2obj(nid);
3360 }
3361 return cryptoctx->id_pkinit_authData9;
3362 case CMS_SIGN_SERVER:
3363 return cryptoctx->id_pkinit_DHKeyData;
3364 case CMS_ENVEL_SERVER:
3365 return cryptoctx->id_pkinit_rkeyData;
3366 default:
3367 return NULL;
3368 }
3369
3370 }
3371
3372 #ifdef LONGHORN_BETA_COMPAT
3373 #if 0
3374 /*
3375 * This is a version that worked with Longhorn Beta 3.
3376 */
3377 static int
3378 wrap_signeddata(unsigned char *data, unsigned int data_len,
3379 unsigned char **out, unsigned int *out_len,
3380 int is_longhorn_server)
3381 {
3382
3383 unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
3384 ASN1_OBJECT *oid = NULL;
3385 unsigned char *p = NULL;
3386
3387 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3388 __FUNCTION__, is_longhorn_server);
3389
3390 /* Get length to wrap the original data with SEQUENCE tag */
3391 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
3392
3393 if (is_longhorn_server == 0) {
3394 /* Add the signedData OID and adjust lengths */
3395 oid = OBJ_nid2obj(NID_pkcs7_signed);
3396 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3397
3398 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
3399 }
3400
3401 p = *out = (unsigned char *)malloc(tot_len);
3402 if (p == NULL) return -1;
3403
3404 if (is_longhorn_server == 0) {
3405 ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
3406 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3407
3408 i2d_ASN1_OBJECT(oid, &p);
3409
3410 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3411 } else {
3412 ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3413 }
3414 memcpy(p, data, data_len);
3415
3416 *out_len = tot_len;
3417
3418 return 0;
3419 }
3420 #else
3421 /*
3422 * This is a version that works with a patched Longhorn KDC.
3423 * (Which should match SP1 ??).
3424 */
3425 static int
3426 wrap_signeddata(unsigned char *data, unsigned int data_len,
3427 unsigned char **out, unsigned int *out_len,
3428 int is_longhorn_server)
3429 {
3430
3431 unsigned int oid_len = 0, tot_len = 0, wrap_len = 0, tag_len = 0;
3432 ASN1_OBJECT *oid = NULL;
3433 unsigned char *p = NULL;
3434
3435 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3436 __FUNCTION__, is_longhorn_server);
3437
3438 /* New longhorn is missing another sequence */
3439 if (is_longhorn_server == 1)
3440 wrap_len = ASN1_object_size(1, (int)(data_len), V_ASN1_SEQUENCE);
3441 else
3442 wrap_len = data_len;
3443
3444 /* Get length to wrap the original data with SEQUENCE tag */
3445 tag_len = ASN1_object_size(1, (int)wrap_len, V_ASN1_SEQUENCE);
3446
3447 /* Always add oid */
3448 oid = OBJ_nid2obj(NID_pkcs7_signed);
3449 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3450 oid_len += tag_len;
3451
3452 tot_len = ASN1_object_size(1, (int)(oid_len), V_ASN1_SEQUENCE);
3453
3454 p = *out = (unsigned char *)malloc(tot_len);
3455 if (p == NULL)
3456 return -1;
3457
3458 ASN1_put_object(&p, 1, (int)(oid_len),
3459 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3460
3461 i2d_ASN1_OBJECT(oid, &p);
3462
3463 ASN1_put_object(&p, 1, (int)wrap_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3464
3465 /* Wrap in extra seq tag */
3466 if (is_longhorn_server == 1) {
3467 ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3468 }
3469 (void) memcpy(p, data, data_len);
3470
3471 *out_len = tot_len;
3472
3473 return 0;
3474 }
3475
3476 #endif
3477 #else
3478 static int
3479 wrap_signeddata(unsigned char *data, unsigned int data_len,
3480 unsigned char **out, unsigned int *out_len)
3481 {
3482
3483 unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
3484 ASN1_OBJECT *oid = NULL;
3485 unsigned char *p = NULL;
3486
3487 /* Get length to wrap the original data with SEQUENCE tag */
3488 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
3489
3490 /* Add the signedData OID and adjust lengths */
3491 oid = OBJ_nid2obj(NID_pkcs7_signed);
3492 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3493
3494 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
3495
3496 p = *out = (unsigned char *)malloc(tot_len);
3497 if (p == NULL) return -1;
3498
3499 ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
3500 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3501
3502 i2d_ASN1_OBJECT(oid, &p);
3503
3504 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3505 (void) memcpy(p, data, data_len);
3506
3507 *out_len = tot_len;
3508
3509 return 0;
3510 }
3511 #endif
3512
3513 static int
3514 prepare_enc_data(unsigned char *indata,
3515 int indata_len,
3516 unsigned char **outdata,
3517 int *outdata_len)
3518 {
3519 int tag, class;
3520 long tlen, slen;
3521 const uint8_t *p = indata, *oldp;
3522
3523 /* Top-bit set means that the conversion failed. */
3524 if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80)
3525 return EINVAL;
3526 if (tag != V_ASN1_SEQUENCE)
3527 return EINVAL;
3528
3529 oldp = p;
3530 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3531 return EINVAL;
3532 p += tlen;
3533 slen -= (p - oldp);
3534
3535 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3536 return EINVAL;
3537
3538 *outdata = malloc(tlen);
3539 if (*outdata == NULL)
3540 return ENOMEM;
3541 memcpy(*outdata, p, tlen);
3542 *outdata_len = tlen;
3543
3544 return 0;
3545 }
3546
3547 #ifndef WITHOUT_PKCS11
3548 static void *
3549 pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p)
3550 {
3551 void *handle;
3552 CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
3553
3554 pkiDebug("loading module \"%s\"... ", modname);
3555 /* Solaris Kerberos */
3556 handle = dlopen(modname, RTLD_NOW | RTLD_GROUP);
3557 if (handle == NULL) {
3558 pkiDebug("not found\n");
3559 return NULL;
3560 }
3561 getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(handle, "C_GetFunctionList");
3562 if (getflist == NULL || (*getflist)(p11p) != CKR_OK) {
3563 (void) dlclose(handle);
3564 pkiDebug("failed\n");
3565 return NULL;
3566 }
3567 pkiDebug("ok\n");
3568 return handle;
3569 }
3570
3571 static CK_RV
3572 pkinit_C_UnloadModule(void *handle)
3573 {
3574 /* Solaris Kerberos */
3575 if (dlclose(handle) != 0)
3576 return CKR_GENERAL_ERROR;
3577
3578 return CKR_OK;
3579 }
3580
3581 /*
3582 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3583 * code.
3584 *
3585 * labelstr will be C string containing token label with trailing white space
3586 * removed.
3587 */
3588 static void
3589 trim_token_label(CK_TOKEN_INFO *tinfo, char *labelstr, unsigned int labelstr_len)
3590 {
3591 int i;
3592
3593 assert(labelstr_len > sizeof (tinfo->label));
3594 /*
3595 * \0 terminate labelstr in case the last char in the token label is
3596 * non-whitespace
3597 */
3598 labelstr[sizeof (tinfo->label)] = '\0';
3599 (void) memcpy(labelstr, (char *) tinfo->label, sizeof (tinfo->label));
3600
3601 /* init i so terminating \0 is skipped */
3602 for (i = sizeof (tinfo->label) - 1; i >= 0; i--) {
3603 if (labelstr[i] == ' ')
3604 labelstr[i] = '\0';
3605 else
3606 break;
3607 }
3608 }
3609
3610 /*
3611 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3612 * code.
3613 */
3614 static krb5_error_code
3615 pkinit_prompt_user(krb5_context context,
3616 pkinit_identity_crypto_context cctx,
3617 krb5_data *reply,
3618 char *prompt,
3619 int hidden)
3620 {
3621 krb5_error_code r;
3622 krb5_prompt kprompt;
3623 krb5_prompt_type prompt_type;
3624
3625 if (cctx->prompter == NULL)
3626 return (EINVAL);
3627
3628 kprompt.prompt = prompt;
3629 kprompt.hidden = hidden;
3630 kprompt.reply = reply;
3631 /*
3632 * Note, assuming this type for now, may need to be passed in in the future.
3633 */
3634 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
3635
3636 /* PROMPTER_INVOCATION */
3637 k5int_set_prompt_types(context, &prompt_type);
3638 r = (*cctx->prompter)(context, cctx->prompter_data,
3639 NULL, NULL, 1, &kprompt);
3640 k5int_set_prompt_types(context, NULL);
3641 return (r);
3642 }
3643
3644 /*
3645 * Solaris Kerberos: this function was changed to support a PIN being passed
3646 * in. If that is the case the user will not be prompted for their PIN.
3647 */
3648 static krb5_error_code
3649 pkinit_login(krb5_context context,
3650 pkinit_identity_crypto_context id_cryptoctx,
3651 CK_TOKEN_INFO *tip)
3652 {
3653 krb5_data rdat;
3654 char *prompt;
3655 int prompt_len;
3656 int r = 0;
3657
3658 if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
3659 rdat.data = NULL;
3660 rdat.length = 0;
3661 } else if (id_cryptoctx->PIN != NULL) {
3662 if ((rdat.data = strdup(id_cryptoctx->PIN)) == NULL)
3663 return (ENOMEM);
3664 /*
3665 * Don't include NULL string terminator in length calculation as this
3666 * PIN is passed to the C_Login function and only the text chars should
3667 * be considered to be the PIN.
3668 */
3669 rdat.length = strlen(id_cryptoctx->PIN);
3670 } else {
3671 /* Solaris Kerberos - trim token label */
3672 char tmplabel[sizeof (tip->label) + 1];
3673
3674 if (!id_cryptoctx->prompter) {
3675 pkiDebug("pkinit_login: id_cryptoctx->prompter is NULL\n");
3676 /* Solaris Kerberos: Improved error messages */
3677 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
3678 gettext("Failed to log into token: prompter function is NULL"));
3679 return (KRB5KDC_ERR_PREAUTH_FAILED);
3680 }
3681 /* Solaris Kerberos - Changes for gettext() */
3682 prompt_len = sizeof (tip->label) + 256;
3683 if ((prompt = (char *) malloc(prompt_len)) == NULL)
3684 return ENOMEM;
3685
3686 /* Solaris Kerberos - trim token label which can be padded with space */
3687 trim_token_label(tip, tmplabel, sizeof (tmplabel));
3688 (void) snprintf(prompt, prompt_len, gettext("%s PIN"), tmplabel);
3689
3690 /* Solaris Kerberos */
3691 if (tip->flags & CKF_USER_PIN_LOCKED)
3692 (void) strlcat(prompt, gettext(" (Warning: PIN locked)"), prompt_len);
3693 else if (tip->flags & CKF_USER_PIN_FINAL_TRY)
3694 (void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len);
3695 else if (tip->flags & CKF_USER_PIN_COUNT_LOW)
3696 (void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len);
3697 rdat.data = malloc(tip->ulMaxPinLen + 2);
3698 rdat.length = tip->ulMaxPinLen + 1;
3699 /*
3700 * Note that the prompter function will set rdat.length such that the
3701 * NULL terminator is not included
3702 */
3703 /* PROMPTER_INVOCATION */
3704 r = pkinit_prompt_user(context, id_cryptoctx, &rdat, prompt, 1);
3705 free(prompt);
3706 }
3707
3708 if (r == 0) {
3709 r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
3710 (u_char *) rdat.data, rdat.length);
3711
3712 if (r != CKR_OK) {
3713 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r));
3714 /* Solaris Kerberos: Improved error messages */
3715 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
3716 gettext("Failed to log into token: %s"),
3717 pkinit_pkcs11_code_to_text(r));
3718 r = KRB5KDC_ERR_PREAUTH_FAILED;
3719 } else {
3720 /* Solaris Kerberos: only need to login once */
3721 id_cryptoctx->p11flags |= C_LOGIN_DONE;
3722 }
3723 }
3724 if (rdat.data) {
3725 (void) memset(rdat.data, 0, rdat.length);
3726 free(rdat.data);
3727 }
3728
3729 return (r);
3730 }
3731
3732 /*
3733 * Solaris Kerberos: added these structs in support of prompting user for
3734 * missing token.
3735 */
3736 struct _token_entry {
3737 CK_SLOT_ID slotID;
3738 CK_SESSION_HANDLE session;
3739 CK_TOKEN_INFO token_info;
3740 };
3741 struct _token_choices {
3742 unsigned int numtokens;
3743 struct _token_entry *token_array;
3744 };
3745
3746
3747 /*
3748 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3749 * code.
3750 */
3751 static krb5_error_code
3752 pkinit_prompt_token(krb5_context context,
3753 pkinit_identity_crypto_context cctx)
3754 {
3755 char tmpbuf[4];
3756 krb5_data reply;
3757 char *token_prompt = gettext("If you have a smartcard insert it now. "
3758 "Press enter to continue");
3759
3760 reply.data = tmpbuf;
3761 reply.length = sizeof(tmpbuf);
3762
3763 /* note, don't care about the reply */
3764 return (pkinit_prompt_user(context, cctx, &reply, token_prompt, 0));
3765 }
3766
3767 /*
3768 * Solaris Kerberos: new defines for prompting support.
3769 */
3770 #define CHOOSE_THIS_TOKEN 0
3771 #define CHOOSE_RESCAN 1
3772 #define CHOOSE_SKIP 2
3773 #define CHOOSE_SEE_NEXT 3
3774
3775 #define RESCAN_TOKENS -1
3776 #define SKIP_TOKENS -2
3777
3778 /*
3779 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3780 * code.
3781 *
3782 * This prompts to user for various choices regarding a token to use. Note
3783 * that if there is no error, choice will be set to one of:
3784 * - the token_choices->token_array entry
3785 * - RESCAN_TOKENS
3786 * - SKIP_TOKENS
3787 */
3788 static int
3789 pkinit_choose_tokens(krb5_context context,
3790 pkinit_identity_crypto_context cctx,
3791 struct _token_choices *token_choices,
3792 int *choice)
3793 {
3794 krb5_error_code r;
3795 /*
3796 * Assuming that PAM_MAX_MSG_SIZE is a reasonable restriction. Note that -
3797 * 2 is to account for the fact that a krb prompter to PAM conv bridge will
3798 * add ": ".
3799 */
3800 char prompt[PAM_MAX_MSG_SIZE - 2];
3801 char tmpbuf[4];
3802 char tmplabel[sizeof (token_choices->token_array->token_info.label) + 1];
3803 krb5_data reply;
3804 int i, num_used, tmpchoice;
3805
3806 assert(token_choices != NULL);
3807 assert(choice != NULL);
3808
3809 /* Create the menu prompt */
3810
3811 /* only need to do this once before the for loop */
3812 reply.data = tmpbuf;
3813
3814 for (i = 0; i < token_choices->numtokens; i++) {
3815
3816 trim_token_label(&token_choices->token_array[i].token_info, tmplabel,
3817 sizeof (tmplabel));
3818
3819 if (i == (token_choices->numtokens - 1)) {
3820 /* no more smartcards/tokens */
3821 if ((num_used = snprintf(prompt, sizeof (prompt),
3822 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n",
3823 /*
3824 * TRANSLATION_NOTE: Translations of the
3825 * following 5 strings must not exceed 450
3826 * bytes total.
3827 */
3828 gettext("Select one of the following and press enter:"),
3829 CHOOSE_THIS_TOKEN, gettext("Use smartcard"), tmplabel,
3830 gettext("in slot"), token_choices->token_array[i].slotID,
3831 CHOOSE_RESCAN, gettext("Rescan for newly inserted smartcard"),
3832 CHOOSE_SKIP, gettext("Skip smartcard authentication")))
3833 >= sizeof (prompt)) {
3834 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3835 " sizeof prompt: %d\n", num_used, sizeof (prompt));
3836 krb5_set_error_message(context, EINVAL,
3837 gettext("In pkinit_choose_tokens: prompt size"
3838 " %d exceeds prompt buffer size %d"),
3839 num_used, sizeof(prompt));
3840 (void) snprintf(prompt, sizeof (prompt), "%s",
3841 gettext("Error: PKINIT prompt message is too large for buffer, "
3842 "please alert the system administrator. Press enter to "
3843 "continue"));
3844 reply.length = sizeof(tmpbuf);
3845 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 )
3846 return (r);
3847 return (EINVAL);
3848 }
3849 } else {
3850 if ((num_used = snprintf(prompt, sizeof (prompt),
3851 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n%d: %s\n",
3852 /*
3853 * TRANSLATION_NOTE: Translations of the
3854 * following 6 strings must not exceed 445
3855 * bytes total.
3856 */
3857 gettext("Select one of the following and press enter:"),
3858 CHOOSE_THIS_TOKEN, gettext("Use smartcard"), tmplabel,
3859 gettext("in slot"), token_choices->token_array[i].slotID,
3860 CHOOSE_RESCAN, gettext("Rescan for newly inserted smartcard"),
3861 CHOOSE_SKIP, gettext("Skip smartcard authentication"),
3862 CHOOSE_SEE_NEXT, gettext("See next smartcard")))
3863 >= sizeof (prompt)) {
3864
3865 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3866 " sizeof prompt: %d\n", num_used, sizeof (prompt));
3867 krb5_set_error_message(context, EINVAL,
3868 gettext("In pkinit_choose_tokens: prompt size"
3869 " %d exceeds prompt buffer size %d"),
3870 num_used, sizeof(prompt));
3871 (void) snprintf(prompt, sizeof (prompt), "%s",
3872 gettext("Error: PKINIT prompt message is too large for buffer, "
3873 "please alert the system administrator. Press enter to "
3874 "continue"));
3875 reply.length = sizeof(tmpbuf);
3876 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 )
3877 return (r);
3878 return (EINVAL);
3879 }
3880 }
3881
3882 /*
3883 * reply.length needs to be reset to length of tmpbuf before calling
3884 * prompter
3885 */
3886 reply.length = sizeof(tmpbuf);
3887 if ((r = pkinit_prompt_user(context, cctx, &reply, prompt, 0)) != 0 )
3888 return (r);
3889
3890 if (reply.length == 0) {
3891 return (EINVAL);
3892 } else {
3893 char *cp = reply.data;
3894 /* reply better be digits */
3895 while (*cp != NULL) {
3896 if (!isdigit(*cp++))
3897 return (EINVAL);
3898 }
3899 errno = 0;
3900 tmpchoice = (int) strtol(reply.data, (char **)NULL, 10);
3901 if (errno != 0)
3902 return (errno);
3903 }
3904
3905 switch (tmpchoice) {
3906 case CHOOSE_THIS_TOKEN:
3907 *choice = i; /* chosen entry of token_choices->token_array */
3908 return (0);
3909 case CHOOSE_RESCAN:
3910 *choice = RESCAN_TOKENS; /* rescan for new smartcard */
3911 return (0);
3912 case CHOOSE_SKIP:
3913 *choice = SKIP_TOKENS; /* skip smartcard auth */
3914 return (0);
3915 case CHOOSE_SEE_NEXT: /* see next smartcard */
3916 continue;
3917 default:
3918 return (EINVAL);
3919 }
3920 }
3921
3922 return (0);
3923 }
3924
3925 /*
3926 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3927 * code.
3928 *
3929 * Note, this isn't the best solution to providing a function to check the
3930 * certs in a token however I wanted to avoid rewriting a bunch of code so I
3931 * settled for some duplication of processing.
3932 */
3933 static krb5_error_code
3934 check_load_certs(krb5_context context,
3935 CK_SESSION_HANDLE session,
3936 pkinit_plg_crypto_context plg_cryptoctx,
3937 pkinit_req_crypto_context req_cryptoctx,
3938 pkinit_identity_crypto_context id_cryptoctx,
3939 krb5_principal princ,
3940 int do_matching,
3941 int load_cert)
3942 {
3943 CK_OBJECT_CLASS cls;
3944 CK_OBJECT_HANDLE obj;
3945 CK_ATTRIBUTE attrs[4];
3946 CK_ULONG count;
3947 CK_CERTIFICATE_TYPE certtype;
3948 CK_BYTE_PTR cert = NULL, cert_id = NULL;
3949 const unsigned char *cp;
3950 int i, r;
3951 unsigned int nattrs;
3952 X509 *x = NULL;
3953
3954 cls = CKO_CERTIFICATE;
3955 attrs[0].type = CKA_CLASS;
3956 attrs[0].pValue = &cls;
3957 attrs[0].ulValueLen = sizeof cls;
3958
3959 certtype = CKC_X_509;
3960 attrs[1].type = CKA_CERTIFICATE_TYPE;
3961 attrs[1].pValue = &certtype;
3962 attrs[1].ulValueLen = sizeof certtype;
3963
3964 nattrs = 2;
3965
3966 /* If a cert id and/or label were given, use them too */
3967 if (id_cryptoctx->cert_id_len > 0) {
3968 attrs[nattrs].type = CKA_ID;
3969 attrs[nattrs].pValue = id_cryptoctx->cert_id;
3970 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
3971 nattrs++;
3972 }
3973 if (id_cryptoctx->cert_label != NULL) {
3974 attrs[nattrs].type = CKA_LABEL;
3975 attrs[nattrs].pValue = id_cryptoctx->cert_label;
3976 attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label);
3977 nattrs++;
3978 }
3979
3980 r = id_cryptoctx->p11->C_FindObjectsInit(session, attrs, nattrs);
3981 if (r != CKR_OK) {
3982 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r));
3983 krb5_set_error_message(context, EINVAL,
3984 gettext("PKCS11 error from C_FindObjectsInit: %s"),
3985 pkinit_pkcs11_code_to_text(r));
3986 r = EINVAL;
3987 goto out;
3988 }
3989
3990 for (i = 0; ; i++) {
3991 if (i >= MAX_CREDS_ALLOWED) {
3992 r = EINVAL;
3993 goto out;
3994 }
3995
3996 /* Look for x.509 cert */
3997 /* Solaris Kerberos */
3998 if ((r = id_cryptoctx->p11->C_FindObjects(session, &obj, 1, &count))
3999 != CKR_OK || count == 0) {
4000 id_cryptoctx->creds[i] = NULL;
4001 break;
4002 }
4003
4004 /* Get cert and id len */
4005 attrs[0].type = CKA_VALUE;
4006 attrs[0].pValue = NULL;
4007 attrs[0].ulValueLen = 0;
4008
4009 attrs[1].type = CKA_ID;
4010 attrs[1].pValue = NULL;
4011 attrs[1].ulValueLen = 0;
4012
4013 if ((r = id_cryptoctx->p11->C_GetAttributeValue(session,
4014 obj,
4015 attrs,
4016 2)) != CKR_OK &&
4017 r != CKR_BUFFER_TOO_SMALL) {
4018 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
4019 krb5_set_error_message(context, EINVAL,
4020 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
4021 pkinit_pkcs11_code_to_text(r));
4022 r = EINVAL;
4023 goto out;
4024 }
4025 cert = malloc((size_t) attrs[0].ulValueLen + 1);
4026 if (cert == NULL) {
4027 r = ENOMEM;
4028 goto out;
4029 }
4030 cert_id = malloc((size_t) attrs[1].ulValueLen + 1);
4031 if (cert_id == NULL) {
4032 r = ENOMEM;
4033 goto out;
4034 }
4035
4036 /* Read the cert and id off the card */
4037
4038 attrs[0].type = CKA_VALUE;
4039 attrs[0].pValue = cert;
4040
4041 attrs[1].type = CKA_ID;
4042 attrs[1].pValue = cert_id;
4043
4044 if ((r = id_cryptoctx->p11->C_GetAttributeValue(session,
4045 obj, attrs, 2)) != CKR_OK) {
4046 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
4047 krb5_set_error_message(context, EINVAL,
4048 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
4049 pkinit_pkcs11_code_to_text(r));
4050 r = EINVAL;
4051 goto out;
4052 }
4053
4054 pkiDebug("cert %d size %d id %d idlen %d\n", i,
4055 (int) attrs[0].ulValueLen, (int) cert_id[0],
4056 (int) attrs[1].ulValueLen);
4057
4058 cp = (unsigned char *) cert;
4059 x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen);
4060 if (x == NULL) {
4061 r = EINVAL;
4062 goto out;
4063 }
4064
4065 id_cryptoctx->creds[i] = malloc(sizeof(struct _pkinit_cred_info));
4066 if (id_cryptoctx->creds[i] == NULL) {
4067 r = ENOMEM;
4068 goto out;
4069 }
4070 id_cryptoctx->creds[i]->cert = x;
4071 id_cryptoctx->creds[i]->key = NULL;
4072 id_cryptoctx->creds[i]->cert_id = cert_id;
4073 cert_id = NULL;
4074 id_cryptoctx->creds[i]->cert_id_len = attrs[1].ulValueLen;
4075 free(cert);
4076 cert = NULL;
4077 }
4078 id_cryptoctx->p11->C_FindObjectsFinal(session);
4079
4080 if (id_cryptoctx->creds[0] == NULL || id_cryptoctx->creds[0]->cert == NULL) {
4081 r = ENOENT;
4082 } else if (do_matching){
4083 /*
4084 * Do not let pkinit_cert_matching set the primary cert in id_cryptoctx
4085 * as this will be done later.
4086 */
4087 r = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx,
4088 id_cryptoctx, princ, FALSE);
4089 }
4090
4091 out:
4092 if ((r != 0 || !load_cert) &&
4093 id_cryptoctx->creds[0] != NULL &&
4094 id_cryptoctx->creds[0]->cert != NULL) {
4095 /*
4096 * If there's an error or load_cert isn't 1 free all the certs loaded
4097 * onto id_cryptoctx.
4098 */
4099 (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
4100 id_cryptoctx);
4101 }
4102
4103 if (cert)
4104 free(cert);
4105
4106 if (cert_id)
4107 free(cert_id);
4108
4109 return (r);
4110 }
4111
4112 /*
4113 * Solaris Kerberos: this function has been significantly modified to prompt
4114 * the user in certain cases so defer to this version when resyncing MIT code.
4115 *
4116 * pkinit_open_session now does several things including prompting the user if
4117 * do_matching is set which indicates the code is executing in a client
4118 * context. This function fills out a pkinit_identity_crypto_context with a
4119 * set of certs and a open session if a token can be found that matches all
4120 * supplied criteria. If no token is found then the user is prompted one time
4121 * to insert their token. If there is more than one token that matches all
4122 * client criteria the user is prompted to make a choice if in client context.
4123 * If do_matching is false (KDC context) then the first token matching all
4124 * server criteria is chosen.
4125 */
4126 static krb5_error_code
4127 pkinit_open_session(krb5_context context,
4128 pkinit_plg_crypto_context plg_cryptoctx,
4129 pkinit_req_crypto_context req_cryptoctx,
4130 pkinit_identity_crypto_context cctx,
4131 krb5_principal princ,
4132 int do_matching)
4133 {
4134 int i, r;
4135 CK_ULONG count = 0;
4136 CK_SLOT_ID_PTR slotlist = NULL, tmpslotlist = NULL;
4137 CK_TOKEN_INFO tinfo;
4138 krb5_boolean tokenmatch = FALSE;
4139 CK_SESSION_HANDLE tmpsession = NULL;
4140 struct _token_choices token_choices;
4141 int choice = 0;
4142
4143 if (cctx->session != CK_INVALID_HANDLE)
4144 return 0; /* session already open */
4145
4146 /* Load module */
4147 if (cctx->p11_module == NULL) {
4148 cctx->p11_module =
4149 pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11);
4150 if (cctx->p11_module == NULL)
4151 return KRB5KDC_ERR_PREAUTH_FAILED;
4152 }
4153
4154 /* Init */
4155 /* Solaris Kerberos: Don't fail if cryptoki is already initialized */
4156 r = cctx->p11->C_Initialize(NULL);
4157 if (r != CKR_OK && r != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
4158 pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r));
4159 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4160 gettext("Error from PKCS11 C_Initialize: %s"),
4161 pkinit_pkcs11_code_to_text(r));
4162 return KRB5KDC_ERR_PREAUTH_FAILED;
4163 }
4164
4165 (void) memset(&token_choices, 0, sizeof(token_choices));
4166
4167 /*
4168 * Solaris Kerberos:
4169 * If C_Initialize was already called by the process before the pkinit
4170 * module was loaded then record that fact.
4171 * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether
4172 * or not C_Finalize() should be called.
4173 */
4174 cctx->finalize_pkcs11 =
4175 (r == CKR_CRYPTOKI_ALREADY_INITIALIZED ? FALSE : TRUE);
4176 /*
4177 * First make sure that is an applicable slot otherwise fail.
4178 *
4179 * Start by getting a count of all slots with or without tokens.
4180 */
4181
4182 if ((r = cctx->p11->C_GetSlotList(FALSE, NULL, &count)) != CKR_OK) {
4183 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4184 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4185 gettext("Error trying to get PKCS11 slot list: %s"),
4186 pkinit_pkcs11_code_to_text(r));
4187 r = KRB5KDC_ERR_PREAUTH_FAILED;
4188 goto out;
4189 }
4190
4191 if (count == 0) {
4192 /* There are no slots so bail */
4193 r = KRB5KDC_ERR_PREAUTH_FAILED;
4194 krb5_set_error_message(context, r,
4195 gettext("No PKCS11 slots found"));
4196 pkiDebug("pkinit_open_session: no slots, count: %d\n", count);
4197 goto out;
4198 } else if (cctx->slotid != PK_NOSLOT) {
4199 /* See if any of the slots match the specified slotID */
4200 tmpslotlist = malloc(count * sizeof (CK_SLOT_ID));
4201 if (tmpslotlist == NULL) {
4202 krb5_set_error_message(context, ENOMEM,
4203 gettext("Memory allocation error:"));
4204 r = KRB5KDC_ERR_PREAUTH_FAILED;
4205 goto out;
4206 }
4207 if ((r = cctx->p11->C_GetSlotList(FALSE, tmpslotlist, &count)) != CKR_OK) {
4208 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4209 gettext("Error trying to get PKCS11 slot list: %s"),
4210 pkinit_pkcs11_code_to_text(r));
4211 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4212 r = KRB5KDC_ERR_PREAUTH_FAILED;
4213 goto out;
4214 }
4215
4216 for (i = 0; i < count && cctx->slotid != tmpslotlist[i]; i++)
4217 continue;
4218
4219 if (i >= count) {
4220 /* no slots match */
4221 r = KRB5KDC_ERR_PREAUTH_FAILED;
4222 krb5_set_error_message(context, r,
4223 gettext("Requested PKCS11 slot ID %d not found"),
4224 cctx->slotid);
4225 pkiDebug("open_session: no matching slot found for slotID %d\n",
4226 cctx->slotid);
4227 goto out;
4228 }
4229 }
4230
4231 tryagain:
4232 /* get count of slots that have tokens */
4233 if ((r = cctx->p11->C_GetSlotList(TRUE, NULL, &count)) != CKR_OK) {
4234 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4235 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4236 gettext("Error trying to get PKCS11 slot list: %s"),
4237 pkinit_pkcs11_code_to_text(r));
4238 r = KRB5KDC_ERR_PREAUTH_FAILED;
4239 goto out;
4240 }
4241
4242 if (count == 0) {
4243 /*
4244 * Note, never prompt if !do_matching as this implies KDC side
4245 * processing
4246 */
4247 if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) {
4248 /* found slot(s) but no token so prompt and try again */
4249 if ((r = pkinit_prompt_token(context, cctx)) == 0) {
4250 cctx->p11flags |= C_PROMPTED_USER;
4251 goto tryagain;
4252 } else {
4253 pkiDebug("open_session: prompt for token/smart card failed\n");
4254 krb5_set_error_message(context, r,
4255 gettext("Prompt for token/smart card failed"));
4256 r = KRB5KDC_ERR_PREAUTH_FAILED;
4257 goto out;
4258 }
4259
4260 } else {
4261 /* already prompted once so bailing */
4262 r = KRB5KDC_ERR_PREAUTH_FAILED;
4263 krb5_set_error_message(context, r,
4264 gettext("No smart card tokens found"));
4265 pkiDebug("pkinit_open_session: no token, already prompted\n");
4266 goto out;
4267 }
4268 }
4269
4270 if (slotlist != NULL)
4271 free(slotlist);
4272
4273 slotlist = malloc(count * sizeof (CK_SLOT_ID));
4274 if (slotlist == NULL) {
4275 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4276 gettext("Memory allocation error"));
4277 r = KRB5KDC_ERR_PREAUTH_FAILED;
4278 goto out;
4279 }
4280 /*
4281 * Solaris Kerberos: get list of PKCS11 slotid's that have tokens.
4282 */
4283 if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) {
4284 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4285 gettext("Error trying to get PKCS11 slot list: %s"),
4286 pkinit_pkcs11_code_to_text(r));
4287 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r));
4288 r = KRB5KDC_ERR_PREAUTH_FAILED;
4289 goto out;
4290 }
4291
4292 token_choices.numtokens = 0;
4293 token_choices.token_array = malloc(count * sizeof (*token_choices.token_array));
4294 if (token_choices.token_array == NULL) {
4295 r = KRB5KDC_ERR_PREAUTH_FAILED;
4296 krb5_set_error_message(context, r,
4297 gettext("Memory allocation error"));
4298 goto out;
4299 }
4300
4301 /* examine all the tokens */
4302 for (i = 0; i < count; i++) {
4303 /*
4304 * Solaris Kerberos: if a slotid was specified skip slots that don't
4305 * match.
4306 */
4307 if (cctx->slotid != PK_NOSLOT && cctx->slotid != slotlist[i])
4308 continue;
4309
4310 /* Open session */
4311 if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
4312 NULL, NULL, &tmpsession)) != CKR_OK) {
4313 pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r));
4314 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4315 gettext("Error trying to open PKCS11 session: %s"),
4316 pkinit_pkcs11_code_to_text(r));
4317 r = KRB5KDC_ERR_PREAUTH_FAILED;
4318 goto out;
4319 }
4320
4321 /* Get token info */
4322 if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) {
4323 pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r));
4324 krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
4325 gettext("Error trying to read PKCS11 token: %s"),
4326 pkinit_pkcs11_code_to_text(r));
4327 r = KRB5KDC_ERR_PREAUTH_FAILED;
4328 cctx->p11->C_CloseSession(tmpsession);
4329 goto out;
4330 }
4331
4332 if (cctx->token_label == NULL) {
4333 /*
4334 * If the token doesn't require login to examine the certs then
4335 * let's check the certs out to see if any match the criteria if
4336 * any.
4337 */
4338 if (!(tinfo.flags & CKF_LOGIN_REQUIRED)) {
4339 /*
4340 * It's okay to check the certs if we don't have to login but
4341 * don't load the certs onto cctx at this point, this will be
4342 * done later in this function for the chosen token.
4343 */
4344 if ((r = check_load_certs(context, tmpsession, plg_cryptoctx,
4345 req_cryptoctx, cctx, princ,
4346 do_matching, 0)) == 0) {
4347 tokenmatch = TRUE;
4348 } else if (r != ENOENT){
4349 r = KRB5KDC_ERR_PREAUTH_FAILED;
4350 cctx->p11->C_CloseSession(tmpsession);
4351 goto out;
4352 } else {
4353 /* ignore ENOENT here */
4354 r = 0;
4355 }
4356 } else {
4357 tokenmatch = TRUE;
4358 }
4359 } else {
4360 /* + 1 so tokenlabelstr can be \0 terminated */
4361 char tokenlabelstr[sizeof (tinfo.label) + 1];
4362
4363 /*
4364 * Convert token label into C string with trailing white space
4365 * trimmed.
4366 */
4367 trim_token_label(&tinfo, tokenlabelstr, sizeof (tokenlabelstr));
4368
4369 pkiDebug("open_session: slotid %d token found: \"%s\", "
4370 "cctx->token_label: \"%s\"\n",
4371 slotlist[i], tokenlabelstr, (char *) cctx->token_label);
4372
4373 if (!strcmp(cctx->token_label, tokenlabelstr)) {
4374 if (!(tinfo.flags & CKF_LOGIN_REQUIRED)) {
4375 /*
4376 * It's okay to check the certs if we don't have to login but
4377 * don't load the certs onto cctx at this point, this will be
4378 * done later in this function for the chosen token.
4379 */
4380 if ((r = check_load_certs(context, tmpsession, plg_cryptoctx,
4381 req_cryptoctx, cctx, princ,
4382 do_matching, 0)) == 0) {
4383 tokenmatch = TRUE;
4384 } else if (r != ENOENT){
4385 r = KRB5KDC_ERR_PREAUTH_FAILED;
4386 cctx->p11->C_CloseSession(tmpsession);
4387 goto out;
4388 } else {
4389 /* ignore ENOENT here */
4390 r = 0;
4391 }
4392 } else {
4393 tokenmatch = TRUE;
4394 }
4395 }
4396 }
4397
4398 if (tokenmatch == TRUE) {
4399 /* add the token to token_choices.token_array */
4400 token_choices.token_array[token_choices.numtokens].slotID = slotlist[i];
4401 token_choices.token_array[token_choices.numtokens].session = tmpsession;
4402 token_choices.token_array[token_choices.numtokens].token_info = tinfo;
4403 token_choices.numtokens++;
4404 /* !do_matching implies we take the first matching token */
4405 if (!do_matching)
4406 break;
4407 else
4408 tokenmatch = FALSE;
4409 } else {
4410 cctx->p11->C_CloseSession(tmpsession);
4411 }
4412 }
4413
4414 if (token_choices.numtokens == 0) {
4415 /*
4416 * Solaris Kerberos: prompt for token one time if there was no token
4417 * and do_matching is 1 (see earlier comment about do_matching).
4418 */
4419 if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) {
4420 if ((r = pkinit_prompt_token(context, cctx)) == 0) {
4421 cctx->p11flags |= C_PROMPTED_USER;
4422 goto tryagain;
4423 } else {
4424 pkiDebug("open_session: prompt for token/smart card failed\n");
4425 krb5_set_error_message(context, r,
4426 gettext("Prompt for token/smart card failed"));
4427 r = KRB5KDC_ERR_PREAUTH_FAILED;
4428 goto out;
4429 }
4430 } else {
4431 r = KRB5KDC_ERR_PREAUTH_FAILED;
4432 krb5_set_error_message(context, r,
4433 gettext("No smart card tokens found"));
4434 pkiDebug("open_session: no matching token found\n");
4435 goto out;
4436 }
4437 } else if (token_choices.numtokens == 1) {
4438 if ((token_choices.token_array[0].token_info.flags & CKF_LOGIN_REQUIRED) &&
4439 !(cctx->p11flags & C_PROMPTED_USER) &&
4440 do_matching) {
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 choice = 0; /* really the only choice is the first token_array entry */
4468 }
4469 } else if (!(cctx->p11flags & C_PROMPTED_USER) && do_matching) {
4470 /* > 1 token so present menu of token choices, let the user decide. */
4471 if ((r = pkinit_choose_tokens(context, cctx, &token_choices, &choice)) != 0) {
4472 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r);
4473 r = KRB5KDC_ERR_PREAUTH_FAILED;
4474 krb5_set_error_message(context, r,
4475 gettext("Prompt for token/smart card failed"));
4476 goto out;
4477 }
4478 if (choice == RESCAN_TOKENS) {
4479 /* rescan for new smartcard/token */
4480 for (i = 0; i < token_choices.numtokens; i++) {
4481 /* close all sessions */
4482 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4483 }
4484 free(token_choices.token_array);
4485 token_choices.token_array = NULL;
4486 token_choices.numtokens = 0;
4487 goto tryagain;
4488 } else if (choice == SKIP_TOKENS) {
4489 /* do not use smartcard/token for auth */
4490 cctx->p11flags |= (C_PROMPTED_USER|C_SKIP_PKCS11_AUTH);
4491 r = KRB5KDC_ERR_PREAUTH_FAILED;
4492 goto out;
4493 } else {
4494 cctx->p11flags |= C_PROMPTED_USER;
4495 }
4496 } else {
4497 r = KRB5KDC_ERR_PREAUTH_FAILED;
4498 goto out;
4499 }
4500
4501 cctx->slotid = token_choices.token_array[choice].slotID;
4502 cctx->session = token_choices.token_array[choice].session;
4503
4504 pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx->slotid,
4505 i + 1, (int) count);
4506
4507 /* Login if needed */
4508 /* Solaris Kerberos: added cctx->p11flags check */
4509 if ((token_choices.token_array[choice].token_info.flags & CKF_LOGIN_REQUIRED) &&
4510 !(cctx->p11flags & C_LOGIN_DONE)) {
4511 r = pkinit_login(context, cctx, &token_choices.token_array[choice].token_info);
4512 }
4513
4514 if (r == 0) {
4515 /* Doing this again to load the certs into cctx. */
4516 r = check_load_certs(context, cctx->session, plg_cryptoctx,
4517 req_cryptoctx, cctx, princ, do_matching, 1);
4518 }
4519
4520 out:
4521 if (slotlist != NULL)
4522 free(slotlist);
4523
4524 if (tmpslotlist != NULL)
4525 free(tmpslotlist);
4526
4527 if (token_choices.token_array != NULL) {
4528 if (r != 0) {
4529 /* close all sessions if there's an error */
4530 for (i = 0; i < token_choices.numtokens; i++) {
4531 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4532 }
4533 cctx->session = CK_INVALID_HANDLE;
4534 } else {
4535 /* close sessions not chosen */
4536 for (i = 0; i < token_choices.numtokens; i++) {
4537 if (i != choice) {
4538 cctx->p11->C_CloseSession(token_choices.token_array[i].session);
4539 }
4540 }
4541 }
4542 free(token_choices.token_array);
4543 }
4544
4545 return (r);
4546 }
4547
4548 /*
4549 * Look for a key that's:
4550 * 1. private
4551 * 2. capable of the specified operation (usually signing or decrypting)
4552 * 3. RSA (this may be wrong but it's all we can do for now)
4553 * 4. matches the id of the cert we chose
4554 *
4555 * You must call pkinit_get_certs before calling pkinit_find_private_key
4556 * (that's because we need the ID of the private key)
4557 *
4558 * pkcs11 says the id of the key doesn't have to match that of the cert, but
4559 * I can't figure out any other way to decide which key to use.
4560 *
4561 * We should only find one key that fits all the requirements.
4562 * If there are more than one, we just take the first one.
4563 */
4564
4565 /* ARGSUSED */
4566 krb5_error_code
4567 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
4568 CK_ATTRIBUTE_TYPE usage,
4569 CK_OBJECT_HANDLE *objp)
4570 {
4571 CK_OBJECT_CLASS cls;
4572 CK_ATTRIBUTE attrs[4];
4573 CK_ULONG count;
4574 CK_KEY_TYPE keytype;
4575 RSA *rsa;
4576 unsigned int nattrs = 0;
4577 int r;
4578 #ifdef PKINIT_USE_KEY_USAGE
4579 CK_BBOOL true_false;
4580 #endif
4581
4582 cls = CKO_PRIVATE_KEY;
4583 attrs[nattrs].type = CKA_CLASS;
4584 attrs[nattrs].pValue = &cls;
4585 attrs[nattrs].ulValueLen = sizeof cls;
4586 nattrs++;
4587
4588 #ifdef PKINIT_USE_KEY_USAGE
4589 /*
4590 * Some cards get confused if you try to specify a key usage,
4591 * so don't, and hope for the best. This will fail if you have
4592 * several keys with the same id and different usages but I have
4593 * not seen this on real cards.
4594 */
4595 true_false = TRUE;
4596 attrs[nattrs].type = usage;
4597 attrs[nattrs].pValue = &true_false;
4598 attrs[nattrs].ulValueLen = sizeof true_false;
4599 nattrs++;
4600 #endif
4601
4602 keytype = CKK_RSA;
4603 attrs[nattrs].type = CKA_KEY_TYPE;
4604 attrs[nattrs].pValue = &keytype;
4605 attrs[nattrs].ulValueLen = sizeof keytype;
4606 nattrs++;
4607
4608 attrs[nattrs].type = CKA_ID;
4609 attrs[nattrs].pValue = id_cryptoctx->cert_id;
4610 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
4611 nattrs++;
4612
4613 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
4614 if (r != CKR_OK) {
4615 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4616 pkinit_pkcs11_code_to_text(r));
4617 return KRB5KDC_ERR_PREAUTH_FAILED;
4618 }
4619
4620 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
4621 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
4622 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
4623
4624 /*
4625 * Solaris Kerberos:
4626 * The CKA_ID may not be correctly set for the private key. For e.g. when
4627 * storing a private key in softtoken pktool(1) doesn't generate or store
4628 * a CKA_ID for the private key. Another way to identify the private key is
4629 * to look for a private key with the same RSA modulus as the public key
4630 * in the certificate.
4631 */
4632 if (r == CKR_OK && count != 1) {
4633
4634 EVP_PKEY *priv;
4635 X509 *cert;
4636 const BIGNUM *rsan;
4637 unsigned int n_len;
4638 unsigned char *n_bytes;
4639
4640 cert = sk_X509_value(id_cryptoctx->my_certs, 0);
4641 priv = X509_get_pubkey(cert);
4642 if (priv == NULL) {
4643 pkiDebug("Failed to extract pub key from cert\n");
4644 return KRB5KDC_ERR_PREAUTH_FAILED;
4645 }
4646
4647 nattrs = 0;
4648 cls = CKO_PRIVATE_KEY;
4649 attrs[nattrs].type = CKA_CLASS;
4650 attrs[nattrs].pValue = &cls;
4651 attrs[nattrs].ulValueLen = sizeof cls;
4652 nattrs++;
4653
4654 #ifdef PKINIT_USE_KEY_USAGE
4655 true_false = TRUE;
4656 attrs[nattrs].type = usage;
4657 attrs[nattrs].pValue = &true_false;
4658 attrs[nattrs].ulValueLen = sizeof true_false;
4659 nattrs++;
4660 #endif
4661
4662 keytype = CKK_RSA;
4663 attrs[nattrs].type = CKA_KEY_TYPE;
4664 attrs[nattrs].pValue = &keytype;
4665 attrs[nattrs].ulValueLen = sizeof keytype;
4666 nattrs++;
4667
4668 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4669 rsa = priv->pkey.rsa;
4670 rsan = rsa->n;
4671 n_len = BN_num_bytes(rsan);
4672 #else
4673 rsa = EVP_PKEY_get0_RSA(priv);
4674 RSA_get0_key(rsa, &rsan, NULL, NULL);
4675 n_len = RSA_size(rsa);
4676 #endif
4677 n_bytes = (unsigned char *) malloc((size_t) n_len);
4678 if (n_bytes == NULL) {
4679 return (ENOMEM);
4680 }
4681
4682 if (BN_bn2bin(rsan, n_bytes) == 0) {
4683 free (n_bytes);
4684 pkiDebug("zero-byte key modulus\n");
4685 return KRB5KDC_ERR_PREAUTH_FAILED;
4686 }
4687
4688 attrs[nattrs].type = CKA_MODULUS;
4689 attrs[nattrs].ulValueLen = n_len;
4690 attrs[nattrs].pValue = n_bytes;
4691
4692 nattrs++;
4693
4694 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
4695 free (n_bytes);
4696 if (r != CKR_OK) {
4697 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4698 pkinit_pkcs11_code_to_text(r));
4699 return KRB5KDC_ERR_PREAUTH_FAILED;
4700 }
4701
4702 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
4703 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
4704 pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
4705
4706 }
4707
4708 if (r != CKR_OK || count < 1)
4709 return KRB5KDC_ERR_PREAUTH_FAILED;
4710 return 0;
4711 }
4712 #endif
4713
4714 /* ARGSUSED */
4715 static krb5_error_code
4716 pkinit_decode_data_fs(krb5_context context,
4717 pkinit_identity_crypto_context id_cryptoctx,
4718 unsigned char *data,
4719 unsigned int data_len,
4720 unsigned char **decoded_data,
4721 unsigned int *decoded_data_len)
4722 {
4723 if (decode_data(decoded_data, decoded_data_len, data, data_len,
4724 id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs,
4725 id_cryptoctx->cert_index)) <= 0) {
4726 pkiDebug("failed to decode data\n");
4727 return KRB5KDC_ERR_PREAUTH_FAILED;
4728 }
4729 return 0;
4730 }
4731
4732 #ifndef WITHOUT_PKCS11
4733 #ifdef SILLYDECRYPT
4734 CK_RV
4735 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,
4736 CK_BYTE_PTR pEncryptedData,
4737 CK_ULONG ulEncryptedDataLen,
4738 CK_BYTE_PTR pData,
4739 CK_ULONG_PTR pulDataLen)
4740 {
4741 CK_RV rv = CKR_OK;
4742
4743 rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData,
4744 ulEncryptedDataLen, pData, pulDataLen);
4745 if (rv == CKR_OK) {
4746 pkiDebug("pData %x *pulDataLen %d\n", (int) pData, (int) *pulDataLen);
4747 }
4748 return rv;
4749 }
4750 #endif
4751
4752 static krb5_error_code
4753 pkinit_decode_data_pkcs11(krb5_context context,
4754 pkinit_identity_crypto_context id_cryptoctx,
4755 unsigned char *data,
4756 unsigned int data_len,
4757 unsigned char **decoded_data,
4758 unsigned int *decoded_data_len)
4759 {
4760 CK_OBJECT_HANDLE obj;
4761 CK_ULONG len;
4762 CK_MECHANISM mech;
4763 unsigned char *cp;
4764 int r;
4765
4766 /*
4767 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4768 * loaded.
4769 */
4770 assert(id_cryptoctx->p11 != NULL);
4771
4772 /* Solaris Kerberos: Login, if needed, to access private object */
4773 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) {
4774 CK_TOKEN_INFO tinfo;
4775
4776 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo);
4777 if (r != 0)
4778 return r;
4779
4780 r = pkinit_login(context, id_cryptoctx, &tinfo);
4781 if (r != 0)
4782 return r;
4783 }
4784
4785 r = pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj);
4786 if (r != 0)
4787 return r;
4788
4789 mech.mechanism = CKM_RSA_PKCS;
4790 mech.pParameter = NULL;
4791 mech.ulParameterLen = 0;
4792
4793 if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech,
4794 obj)) != CKR_OK) {
4795 pkiDebug("C_DecryptInit: 0x%x\n", (int) r);
4796 return KRB5KDC_ERR_PREAUTH_FAILED;
4797 }
4798 pkiDebug("data_len = %d\n", data_len);
4799 cp = (unsigned char *)malloc((size_t) data_len);
4800 if (cp == NULL)
4801 return ENOMEM;
4802 len = data_len;
4803 #ifdef SILLYDECRYPT
4804 pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n",
4805 (int) id_cryptoctx->session, (int) data, (int) data_len, (int) cp,
4806 (int) &len, (int) len);
4807 if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len,
4808 cp, &len)) != CKR_OK) {
4809 #else
4810 if ((r = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, data,
4811 (CK_ULONG) data_len, cp, &len)) != CKR_OK) {
4812 #endif
4813 pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r));
4814 if (r == CKR_BUFFER_TOO_SMALL)
4815 pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len);
4816 return KRB5KDC_ERR_PREAUTH_FAILED;
4817 }
4818 pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len);
4819 *decoded_data_len = len;
4820 *decoded_data = cp;
4821
4822 return 0;
4823 }
4824 #endif
4825
4826 krb5_error_code
4827 pkinit_decode_data(krb5_context context,
4828 pkinit_identity_crypto_context id_cryptoctx,
4829 unsigned char *data,
4830 unsigned int data_len,
4831 unsigned char **decoded_data,
4832 unsigned int *decoded_data_len)
4833 {
4834 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4835
4836 if (id_cryptoctx->pkcs11_method != 1)
4837 retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len,
4838 decoded_data, decoded_data_len);
4839 #ifndef WITHOUT_PKCS11
4840 else
4841 retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data,
4842 data_len, decoded_data, decoded_data_len);
4843 #endif
4844
4845 return retval;
4846 }
4847
4848 /* ARGSUSED */
4849 static krb5_error_code
4850 pkinit_sign_data_fs(krb5_context context,
4851 pkinit_identity_crypto_context id_cryptoctx,
4852 unsigned char *data,
4853 unsigned int data_len,
4854 unsigned char **sig,
4855 unsigned int *sig_len)
4856 {
4857 if (create_signature(sig, sig_len, data, data_len,
4858 id_cryptoctx->my_key) != 0) {
4859 pkiDebug("failed to create the signature\n");
4860 return KRB5KDC_ERR_PREAUTH_FAILED;
4861 }
4862 return 0;
4863 }
4864
4865 #ifndef WITHOUT_PKCS11
4866 static krb5_error_code
4867 pkinit_sign_data_pkcs11(krb5_context context,
4868 pkinit_identity_crypto_context id_cryptoctx,
4869 unsigned char *data,
4870 unsigned int data_len,
4871 unsigned char **sig,
4872 unsigned int *sig_len)
4873 {
4874 CK_OBJECT_HANDLE obj;
4875 CK_ULONG len;
4876 CK_MECHANISM mech;
4877 unsigned char *cp;
4878 int r;
4879
4880 /*
4881 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4882 * loaded.
4883 */
4884 assert(id_cryptoctx->p11 != NULL);
4885
4886 /* Solaris Kerberos: Login, if needed, to access private object */
4887 if (!(id_cryptoctx->p11flags & C_LOGIN_DONE)) {
4888 CK_TOKEN_INFO tinfo;
4889
4890 r = id_cryptoctx->p11->C_GetTokenInfo(id_cryptoctx->slotid, &tinfo);
4891 if (r != 0)
4892 return r;
4893
4894 r = pkinit_login(context, id_cryptoctx, &tinfo);
4895 if (r != 0)
4896 return r;
4897 }
4898
4899 r = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
4900 if (r != 0 )
4901 return r;
4902
4903 mech.mechanism = id_cryptoctx->mech;
4904 mech.pParameter = NULL;
4905 mech.ulParameterLen = 0;
4906
4907 if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
4908 obj)) != CKR_OK) {
4909 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r));
4910 return KRB5KDC_ERR_PREAUTH_FAILED;
4911 }
4912
4913 /*
4914 * Key len would give an upper bound on sig size, but there's no way to
4915 * get that. So guess, and if it's too small, re-malloc.
4916 */
4917 len = PK_SIGLEN_GUESS;
4918 cp = (unsigned char *)malloc((size_t) len);
4919 if (cp == NULL)
4920 return ENOMEM;
4921
4922 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
4923 (CK_ULONG) data_len, cp, &len);
4924 if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
4925 free(cp);
4926 pkiDebug("C_Sign realloc %d\n", (int) len);
4927 cp = (unsigned char *)malloc((size_t) len);
4928 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
4929 (CK_ULONG) data_len, cp, &len);
4930 }
4931 if (r != CKR_OK) {
4932 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r));
4933 return KRB5KDC_ERR_PREAUTH_FAILED;
4934 }
4935 pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
4936 *sig_len = len;
4937 *sig = cp;
4938
4939 return 0;
4940 }
4941 #endif
4942
4943 krb5_error_code
4944 pkinit_sign_data(krb5_context context,
4945 pkinit_identity_crypto_context id_cryptoctx,
4946 unsigned char *data,
4947 unsigned int data_len,
4948 unsigned char **sig,
4949 unsigned int *sig_len)
4950 {
4951 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4952
4953 if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1)
4954 retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len,
4955 sig, sig_len);
4956 #ifndef WITHOUT_PKCS11
4957 else
4958 retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len,
4959 sig, sig_len);
4960 #endif
4961
4962 return retval;
4963 }
4964
4965
4966 static krb5_error_code
4967 decode_data(unsigned char **out_data, unsigned int *out_data_len,
4968 unsigned char *data, unsigned int data_len,
4969 EVP_PKEY *pkey, X509 *cert)
4970 {
4971 /* Solaris Kerberos */
4972 int len;
4973 unsigned char *buf = NULL;
4974 int buf_len = 0;
4975
4976 /* Solaris Kerberos */
4977 if (out_data == NULL || out_data_len == NULL)
4978 return EINVAL;
4979
4980 if (cert && !X509_check_private_key(cert, pkey)) {
4981 pkiDebug("private key does not match certificate\n");
4982 /* Solaris Kerberos */
4983 return EINVAL;
4984 }
4985
4986 buf_len = EVP_PKEY_size(pkey);
4987 buf = (unsigned char *)malloc((size_t) buf_len + 10);
4988 if (buf == NULL)
4989 return ENOMEM;
4990
4991 len = EVP_PKEY_decrypt_old(buf, data, (int)data_len, pkey);
4992 if (len <= 0) {
4993 pkiDebug("unable to decrypt received data (len=%d)\n", data_len);
4994 /* Solaris Kerberos */
4995 free(buf);
4996 return KRB5KRB_ERR_GENERIC;
4997 }
4998 *out_data = buf;
4999 *out_data_len = len;
5000
5001 return 0;
5002 }
5003
5004 static krb5_error_code
5005 create_signature(unsigned char **sig, unsigned int *sig_len,
5006 unsigned char *data, unsigned int data_len, EVP_PKEY *pkey)
5007 {
5008 krb5_error_code retval = ENOMEM;
5009 EVP_MD_CTX *md_ctx;
5010
5011 if (pkey == NULL)
5012 /* Solaris Kerberos */
5013 return EINVAL;
5014
5015 if ((md_ctx = EVP_MD_CTX_new()) == NULL)
5016 return EINVAL;
5017
5018 EVP_VerifyInit(md_ctx, EVP_sha1());
5019 EVP_SignUpdate(md_ctx, data, data_len);
5020 *sig_len = EVP_PKEY_size(pkey);
5021 if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL)
5022 goto cleanup;
5023 EVP_SignFinal(md_ctx, *sig, sig_len, pkey);
5024
5025 retval = 0;
5026
5027 cleanup:
5028 EVP_MD_CTX_free(md_ctx);
5029
5030 return retval;
5031 }
5032
5033 /*
5034 * Note:
5035 * This is not the routine the KDC uses to get its certificate.
5036 * This routine is intended to be called by the client
5037 * to obtain the KDC's certificate from some local storage
5038 * to be sent as a hint in its request to the KDC.
5039 */
5040 /* ARGSUSED */
5041 krb5_error_code
5042 pkinit_get_kdc_cert(krb5_context context,
5043 pkinit_plg_crypto_context plg_cryptoctx,
5044 pkinit_req_crypto_context req_cryptoctx,
5045 pkinit_identity_crypto_context id_cryptoctx,
5046 krb5_principal princ)
5047 {
5048 /* Solaris Kerberos */
5049 if (req_cryptoctx == NULL)
5050 return EINVAL;
5051
5052 req_cryptoctx->received_cert = NULL;
5053 return 0;
5054 }
5055
5056 /* ARGSUSED */
5057 static krb5_error_code
5058 pkinit_get_certs_pkcs12(krb5_context context,
5059 pkinit_plg_crypto_context plg_cryptoctx,
5060 pkinit_req_crypto_context req_cryptoctx,
5061 pkinit_identity_opts *idopts,
5062 pkinit_identity_crypto_context id_cryptoctx,
5063 krb5_principal princ)
5064 {
5065 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
5066 X509 *x = NULL;
5067 PKCS12 *p12 = NULL;
5068 int ret;
5069 FILE *fp;
5070 EVP_PKEY *y = NULL;
5071
5072 if (idopts->cert_filename == NULL) {
5073 /* Solaris Kerberos: Improved error messages */
5074 krb5_set_error_message(context, retval,
5075 gettext("Failed to get certificate location"));
5076 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
5077 goto cleanup;
5078 }
5079
5080 if (idopts->key_filename == NULL) {
5081 /* Solaris Kerberos: Improved error messages */
5082 krb5_set_error_message(context, retval,
5083 gettext("Failed to get private key location"));
5084 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
5085 goto cleanup;
5086 }
5087
5088 fp = fopen(idopts->cert_filename, "rb");
5089 if (fp == NULL) {
5090 /* Solaris Kerberos: Improved error messages */
5091 krb5_set_error_message(context, retval,
5092 gettext("Failed to open PKCS12 file '%s': %s"),
5093 idopts->cert_filename, error_message(errno));
5094 pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
5095 idopts->cert_filename, errno);
5096 goto cleanup;
5097 }
5098
5099 p12 = d2i_PKCS12_fp(fp, NULL);
5100 (void) fclose(fp);
5101 if (p12 == NULL) {
5102 krb5_set_error_message(context, retval,
5103 gettext("Failed to decode PKCS12 file '%s' contents"),
5104 idopts->cert_filename);
5105 pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
5106 idopts->cert_filename);
5107 goto cleanup;
5108 }
5109 /*
5110 * Try parsing with no pass phrase first. If that fails,
5111 * prompt for the pass phrase and try again.
5112 */
5113 ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
5114 if (ret == 0) {
5115 krb5_data rdat;
5116 krb5_prompt kprompt;
5117 krb5_prompt_type prompt_type;
5118 int r = 0;
5119 char prompt_string[128];
5120 char prompt_reply[128];
5121 /* Solaris Kerberos */
5122 char *prompt_prefix = gettext("Pass phrase for");
5123
5124 pkiDebug("Initial PKCS12_parse with no password failed\n");
5125
5126 if (id_cryptoctx->PIN != NULL) {
5127 /* Solaris Kerberos: use PIN if set */
5128 rdat.data = id_cryptoctx->PIN;
5129 /* note rdat.length isn't needed in this case */
5130 } else {
5131 (void) memset(prompt_reply, '\0', sizeof(prompt_reply));
5132 rdat.data = prompt_reply;
5133 rdat.length = sizeof(prompt_reply);
5134
5135 r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
5136 prompt_prefix, idopts->cert_filename);
5137 if (r >= sizeof(prompt_string)) {
5138 pkiDebug("Prompt string, '%s %s', is too long!\n",
5139 prompt_prefix, idopts->cert_filename);
5140 goto cleanup;
5141 }
5142 kprompt.prompt = prompt_string;
5143 kprompt.hidden = 1;
5144 kprompt.reply = &rdat;
5145 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
5146
5147 /* PROMPTER_INVOCATION */
5148 k5int_set_prompt_types(context, &prompt_type);
5149 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
5150 NULL, NULL, 1, &kprompt);
5151 k5int_set_prompt_types(context, NULL);
5152 }
5153
5154 ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
5155 if (ret == 0) {
5156 /* Solaris Kerberos: Improved error messages */
5157 krb5_set_error_message(context, retval,
5158 gettext("Failed to parse PKCS12 file '%s' with password"),
5159 idopts->cert_filename);
5160 pkiDebug("Seconde PKCS12_parse with password failed\n");
5161 goto cleanup;
5162 }
5163 }
5164 id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
5165 if (id_cryptoctx->creds[0] == NULL)
5166 goto cleanup;
5167 id_cryptoctx->creds[0]->cert = x;
5168 #ifndef WITHOUT_PKCS11
5169 id_cryptoctx->creds[0]->cert_id = NULL;
5170 id_cryptoctx->creds[0]->cert_id_len = 0;
5171 #endif
5172 id_cryptoctx->creds[0]->key = y;
5173 id_cryptoctx->creds[1] = NULL;
5174
5175 retval = 0;
5176
5177 cleanup:
5178 if (p12)
5179 PKCS12_free(p12);
5180 if (retval) {
5181 if (x != NULL)
5182 X509_free(x);
5183 if (y != NULL)
5184 EVP_PKEY_free(y);
5185 }
5186 return retval;
5187 }
5188
5189 static krb5_error_code
5190 pkinit_load_fs_cert_and_key(krb5_context context,
5191 pkinit_identity_crypto_context id_cryptoctx,
5192 char *certname,
5193 char *keyname,
5194 int cindex)
5195 {
5196 krb5_error_code retval;
5197 X509 *x = NULL;
5198 EVP_PKEY *y = NULL;
5199
5200 /* load the certificate */
5201 retval = get_cert(certname, &x);
5202 if (retval != 0 || x == NULL) {
5203 /* Solaris Kerberos: Improved error messages */
5204 krb5_set_error_message(context, retval,
5205 gettext("Failed to load user's certificate from %s: %s"),
5206 certname, error_message(retval));
5207 pkiDebug("failed to load user's certificate from '%s'\n", certname);
5208 goto cleanup;
5209 }
5210 retval = get_key(keyname, &y);
5211 if (retval != 0 || y == NULL) {
5212 /* Solaris Kerberos: Improved error messages */
5213 krb5_set_error_message(context, retval,
5214 gettext("Failed to load user's private key from %s: %s"),
5215 keyname, error_message(retval));
5216 pkiDebug("failed to load user's private key from '%s'\n", keyname);
5217 goto cleanup;
5218 }
5219
5220 id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
5221 if (id_cryptoctx->creds[cindex] == NULL) {
5222 retval = ENOMEM;
5223 goto cleanup;
5224 }
5225 id_cryptoctx->creds[cindex]->cert = x;
5226 #ifndef WITHOUT_PKCS11
5227 id_cryptoctx->creds[cindex]->cert_id = NULL;
5228 id_cryptoctx->creds[cindex]->cert_id_len = 0;
5229 #endif
5230 id_cryptoctx->creds[cindex]->key = y;
5231 id_cryptoctx->creds[cindex+1] = NULL;
5232
5233 retval = 0;
5234
5235 cleanup:
5236 if (retval) {
5237 if (x != NULL)
5238 X509_free(x);
5239 if (y != NULL)
5240 EVP_PKEY_free(y);
5241 }
5242 return retval;
5243 }
5244
5245 /* ARGSUSED */
5246 static krb5_error_code
5247 pkinit_get_certs_fs(krb5_context context,
5248 pkinit_plg_crypto_context plg_cryptoctx,
5249 pkinit_req_crypto_context req_cryptoctx,
5250 pkinit_identity_opts *idopts,
5251 pkinit_identity_crypto_context id_cryptoctx,
5252 krb5_principal princ)
5253 {
5254 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
5255
5256 if (idopts->cert_filename == NULL) {
5257 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
5258 goto cleanup;
5259 }
5260
5261 if (idopts->key_filename == NULL) {
5262 pkiDebug("%s: failed to get user's private key location\n",
5263 __FUNCTION__);
5264 goto cleanup;
5265 }
5266
5267 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
5268 idopts->cert_filename,
5269 idopts->key_filename, 0);
5270 cleanup:
5271 return retval;
5272 }
5273
5274 /* ARGSUSED */
5275 static krb5_error_code
5276 pkinit_get_certs_dir(krb5_context context,
5277 pkinit_plg_crypto_context plg_cryptoctx,
5278 pkinit_req_crypto_context req_cryptoctx,
5279 pkinit_identity_opts *idopts,
5280 pkinit_identity_crypto_context id_cryptoctx,
5281 krb5_principal princ)
5282 {
5283 /* Solaris Kerberos */
5284 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
5285 DIR *d = NULL;
5286 struct dirent *dentry = NULL;
5287 char certname[1024];
5288 char keyname[1024];
5289 int i = 0, len;
5290 char *dirname, *suf;
5291
5292 /* Solaris Kerberos */
5293 if (idopts == NULL)
5294 return EINVAL;
5295
5296 if (idopts->cert_filename == NULL) {
5297 pkiDebug("%s: failed to get user's certificate directory location\n",
5298 __FUNCTION__);
5299 return ENOENT;
5300 }
5301
5302 dirname = idopts->cert_filename;
5303 d = opendir(dirname);
5304 if (d == NULL) {
5305 /* Solaris Kerberos: Improved error messages */
5306 krb5_set_error_message(context, errno,
5307 gettext("Failed to open directory \"%s\": %s"),
5308 dirname, error_message(errno));
5309 return errno;
5310 }
5311
5312 /*
5313 * We'll assume that certs are named XXX.crt and the corresponding
5314 * key is named XXX.key
5315 */
5316 while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) {
5317 /* Ignore subdirectories and anything starting with a dot */
5318 #ifdef DT_DIR
5319 if (dentry->d_type == DT_DIR)
5320 continue;
5321 #endif
5322 if (dentry->d_name[0] == '.')
5323 continue;
5324 len = strlen(dentry->d_name);
5325 if (len < 5)
5326 continue;
5327 suf = dentry->d_name + (len - 4);
5328 if (strncmp(suf, ".crt", 4) != 0)
5329 continue;
5330
5331 /* Checked length */
5332 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) {
5333 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
5334 __FUNCTION__, dirname, dentry->d_name);
5335 continue;
5336 }
5337 (void) snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name);
5338 (void) snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name);
5339 len = strlen(keyname);
5340 keyname[len - 3] = 'k';
5341 keyname[len - 2] = 'e';
5342 keyname[len - 1] = 'y';
5343
5344 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
5345 certname, keyname, i);
5346 if (retval == 0) {
5347 pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
5348 __FUNCTION__, dentry->d_name);
5349 i++;
5350 }
5351 else
5352 continue;
5353 }
5354
5355 if (i == 0) {
5356 /* Solaris Kerberos: Improved error messages */
5357 krb5_set_error_message(context, ENOENT,
5358 gettext("No suitable cert/key pairs found in directory '%s'"),
5359 idopts->cert_filename);
5360 pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
5361 __FUNCTION__, idopts->cert_filename);
5362 retval = ENOENT;
5363 goto cleanup;
5364 }
5365
5366 retval = 0;
5367
5368 cleanup:
5369 if (d)
5370 (void) closedir(d);
5371
5372 return retval;
5373 }
5374
5375 #ifndef WITHOUT_PKCS11
5376 /* ARGSUSED */
5377 static krb5_error_code
5378 pkinit_get_certs_pkcs11(krb5_context context,
5379 pkinit_plg_crypto_context plg_cryptoctx,
5380 pkinit_req_crypto_context req_cryptoctx,
5381 pkinit_identity_opts *idopts,
5382 pkinit_identity_crypto_context id_cryptoctx,
5383 krb5_principal princ,
5384 int do_matching)
5385 {
5386 #ifdef PKINIT_USE_MECH_LIST
5387 CK_MECHANISM_TYPE_PTR mechp = NULL;
5388 CK_MECHANISM_INFO info;
5389 #endif
5390
5391 if (id_cryptoctx->p11flags & C_SKIP_PKCS11_AUTH)
5392 return KRB5KDC_ERR_PREAUTH_FAILED;
5393
5394 /* Copy stuff from idopts -> id_cryptoctx */
5395 if (idopts->p11_module_name != NULL) {
5396 id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name);
5397 if (id_cryptoctx->p11_module_name == NULL)
5398 return ENOMEM;
5399 }
5400 if (idopts->token_label != NULL) {
5401 id_cryptoctx->token_label = strdup(idopts->token_label);
5402 if (id_cryptoctx->token_label == NULL)
5403 return ENOMEM;
5404 }
5405 if (idopts->cert_label != NULL) {
5406 id_cryptoctx->cert_label = strdup(idopts->cert_label);
5407 if (id_cryptoctx->cert_label == NULL)
5408 return ENOMEM;
5409 }
5410 if (idopts->PIN != NULL) {
5411 id_cryptoctx->PIN = strdup(idopts->PIN);
5412 if (id_cryptoctx->PIN == NULL)
5413 return ENOMEM;
5414 }
5415 /* Convert the ascii cert_id string into a binary blob */
5416 /*
5417 * Solaris Kerberos:
5418 * If the cert_id_string is empty then behave in a similar way to how
5419 * an empty certlabel is treated - i.e. don't fail now but rather continue
5420 * as though the certid wasn't specified.
5421 */
5422 if (idopts->cert_id_string != NULL && strlen(idopts->cert_id_string) != 0) {
5423 BIGNUM *bn = NULL;
5424 BN_hex2bn(&bn, idopts->cert_id_string);
5425 if (bn == NULL)
5426 return ENOMEM;
5427 id_cryptoctx->cert_id_len = BN_num_bytes(bn);
5428 id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
5429 if (id_cryptoctx->cert_id == NULL) {
5430 BN_free(bn);
5431 return ENOMEM;
5432 }
5433 BN_bn2bin(bn, id_cryptoctx->cert_id);
5434 BN_free(bn);
5435 }
5436 id_cryptoctx->slotid = idopts->slotid;
5437 id_cryptoctx->pkcs11_method = 1;
5438
5439 #ifndef PKINIT_USE_MECH_LIST
5440 /*
5441 * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
5442 * many cards seems to be confused about whether they are capable of
5443 * this or not. The safe thing seems to be to ignore the mechanism list,
5444 * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
5445 */
5446
5447 id_cryptoctx->mech = CKM_RSA_PKCS;
5448 #else
5449 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, NULL,
5450 &count)) != CKR_OK || count <= 0) {
5451 pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r));
5452 return KRB5KDC_ERR_PREAUTH_FAILED;
5453 }
5454 mechp = (CK_MECHANISM_TYPE_PTR) malloc(count * sizeof (CK_MECHANISM_TYPE));
5455 if (mechp == NULL)
5456 return ENOMEM;
5457 if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid,
5458 mechp, &count)) != CKR_OK) {
5459 free(mechp);
5460 return KRB5KDC_ERR_PREAUTH_FAILED;
5461 }
5462 for (i = 0; i < count; i++) {
5463 if ((r = id_cryptoctx->p11->C_GetMechanismInfo(id_cryptoctx->slotid,
5464 mechp[i], &info)) != CKR_OK) {
5465 free(mechp);
5466 return KRB5KDC_ERR_PREAUTH_FAILED;
5467 }
5468 #ifdef DEBUG_MECHINFO
5469 pkiDebug("mech %x flags %x\n", (int) mechp[i], (int) info.flags);
5470 if ((info.flags & (CKF_SIGN|CKF_DECRYPT)) == (CKF_SIGN|CKF_DECRYPT))
5471 pkiDebug(" this mech is good for sign & decrypt\n");
5472 #endif
5473 if (mechp[i] == CKM_RSA_PKCS) {
5474 /* This seems backwards... */
5475 id_cryptoctx->mech =
5476 (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
5477 }
5478 }
5479 free(mechp);
5480
5481 pkiDebug("got %d mechs from card\n", (int) count);
5482 #endif
5483
5484 return (pkinit_open_session(context, plg_cryptoctx, req_cryptoctx,
5485 id_cryptoctx, princ, do_matching));
5486 }
5487 #endif
5488
5489 /* ARGSUSED */
5490 static void
5491 free_cred_info(krb5_context context,
5492 pkinit_identity_crypto_context id_cryptoctx,
5493 struct _pkinit_cred_info *cred)
5494 {
5495 if (cred != NULL) {
5496 if (cred->cert != NULL)
5497 X509_free(cred->cert);
5498 if (cred->key != NULL)
5499 EVP_PKEY_free(cred->key);
5500 #ifndef WITHOUT_PKCS11
5501 if (cred->cert_id != NULL)
5502 free(cred->cert_id);
5503 #endif
5504 free(cred);
5505 }
5506 }
5507
5508 /* ARGSUSED */
5509 krb5_error_code
5510 crypto_free_cert_info(krb5_context context,
5511 pkinit_plg_crypto_context plg_cryptoctx,
5512 pkinit_req_crypto_context req_cryptoctx,
5513 pkinit_identity_crypto_context id_cryptoctx)
5514 {
5515 int i;
5516
5517 if (id_cryptoctx == NULL)
5518 return EINVAL;
5519
5520 for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
5521 if (id_cryptoctx->creds[i] != NULL) {
5522 free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]);
5523 id_cryptoctx->creds[i] = NULL;
5524 }
5525 }
5526 return 0;
5527 }
5528
5529 krb5_error_code
5530 crypto_load_certs(krb5_context context,
5531 pkinit_plg_crypto_context plg_cryptoctx,
5532 pkinit_req_crypto_context req_cryptoctx,
5533 pkinit_identity_opts *idopts,
5534 pkinit_identity_crypto_context id_cryptoctx,
5535 krb5_principal princ,
5536 int do_matching)
5537 {
5538 krb5_error_code retval;
5539
5540 switch(idopts->idtype) {
5541 case IDTYPE_FILE:
5542 retval = pkinit_get_certs_fs(context, plg_cryptoctx,
5543 req_cryptoctx, idopts,
5544 id_cryptoctx, princ);
5545 break;
5546 case IDTYPE_DIR:
5547 retval = pkinit_get_certs_dir(context, plg_cryptoctx,
5548 req_cryptoctx, idopts,
5549 id_cryptoctx, princ);
5550 break;
5551 #ifndef WITHOUT_PKCS11
5552 case IDTYPE_PKCS11:
5553 retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx,
5554 req_cryptoctx, idopts,
5555 id_cryptoctx, princ, do_matching);
5556 break;
5557 #endif
5558 case IDTYPE_PKCS12:
5559 retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx,
5560 req_cryptoctx, idopts,
5561 id_cryptoctx, princ);
5562 break;
5563 default:
5564 retval = EINVAL;
5565 }
5566 /* Solaris Kerberos */
5567
5568 return retval;
5569 }
5570
5571 /*
5572 * Get number of certificates available after crypto_load_certs()
5573 */
5574 /* ARGSUSED */
5575 krb5_error_code
5576 crypto_cert_get_count(krb5_context context,
5577 pkinit_plg_crypto_context plg_cryptoctx,
5578 pkinit_req_crypto_context req_cryptoctx,
5579 pkinit_identity_crypto_context id_cryptoctx,
5580 int *cert_count)
5581 {
5582 int count;
5583
5584 if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
5585 return EINVAL;
5586
5587 for (count = 0;
5588 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
5589 count++);
5590 *cert_count = count;
5591 return 0;
5592 }
5593
5594
5595 /*
5596 * Begin iteration over the certs loaded in crypto_load_certs()
5597 */
5598 /* ARGSUSED */
5599 krb5_error_code
5600 crypto_cert_iteration_begin(krb5_context context,
5601 pkinit_plg_crypto_context plg_cryptoctx,
5602 pkinit_req_crypto_context req_cryptoctx,
5603 pkinit_identity_crypto_context id_cryptoctx,
5604 pkinit_cert_iter_handle *ih_ret)
5605 {
5606 struct _pkinit_cert_iter_data *id;
5607
5608 if (id_cryptoctx == NULL || ih_ret == NULL)
5609 return EINVAL;
5610 if (id_cryptoctx->creds[0] == NULL) /* No cred info available */
5611 return ENOENT;
5612
5613 id = calloc(1, sizeof(*id));
5614 if (id == NULL)
5615 return ENOMEM;
5616 id->magic = ITER_MAGIC;
5617 id->plgctx = plg_cryptoctx,
5618 id->reqctx = req_cryptoctx,
5619 id->idctx = id_cryptoctx;
5620 id->index = 0;
5621 *ih_ret = (pkinit_cert_iter_handle) id;
5622 return 0;
5623 }
5624
5625 /*
5626 * End iteration over the certs loaded in crypto_load_certs()
5627 */
5628 /* ARGSUSED */
5629 krb5_error_code
5630 crypto_cert_iteration_end(krb5_context context,
5631 pkinit_cert_iter_handle ih)
5632 {
5633 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
5634
5635 if (id == NULL || id->magic != ITER_MAGIC)
5636 return EINVAL;
5637 free(ih);
5638 return 0;
5639 }
5640
5641 /*
5642 * Get next certificate handle
5643 */
5644 /* ARGSUSED */
5645 krb5_error_code
5646 crypto_cert_iteration_next(krb5_context context,
5647 pkinit_cert_iter_handle ih,
5648 pkinit_cert_handle *ch_ret)
5649 {
5650 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
5651 struct _pkinit_cert_data *cd;
5652 pkinit_identity_crypto_context id_cryptoctx;
5653
5654 if (id == NULL || id->magic != ITER_MAGIC)
5655 return EINVAL;
5656
5657 if (ch_ret == NULL)
5658 return EINVAL;
5659
5660 id_cryptoctx = id->idctx;
5661 if (id_cryptoctx == NULL)
5662 return EINVAL;
5663
5664 if (id_cryptoctx->creds[id->index] == NULL)
5665 return PKINIT_ITER_NO_MORE;
5666
5667 cd = calloc(1, sizeof(*cd));
5668 if (cd == NULL)
5669 return ENOMEM;
5670
5671 cd->magic = CERT_MAGIC;
5672 cd->plgctx = id->plgctx;
5673 cd->reqctx = id->reqctx;
5674 cd->idctx = id->idctx;
5675 cd->index = id->index;
5676 cd->cred = id_cryptoctx->creds[id->index++];
5677 *ch_ret = (pkinit_cert_handle)cd;
5678 return 0;
5679 }
5680
5681 /*
5682 * Release cert handle
5683 */
5684 /* ARGSUSED */
5685 krb5_error_code
5686 crypto_cert_release(krb5_context context,
5687 pkinit_cert_handle ch)
5688 {
5689 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
5690 if (cd == NULL || cd->magic != CERT_MAGIC)
5691 return EINVAL;
5692 free(cd);
5693 return 0;
5694 }
5695
5696 /*
5697 * Get certificate Key Usage and Extended Key Usage
5698 */
5699 /* ARGSUSED */
5700 static krb5_error_code
5701 crypto_retieve_X509_key_usage(krb5_context context,
5702 pkinit_plg_crypto_context plgcctx,
5703 pkinit_req_crypto_context reqcctx,
5704 X509 *x,
5705 unsigned int *ret_ku_bits,
5706 unsigned int *ret_eku_bits)
5707 {
5708 /* Solaris Kerberos */
5709 int i;
5710 unsigned int eku_bits = 0, ku_bits = 0;
5711 ASN1_BIT_STRING *usage = NULL;
5712
5713 if (ret_ku_bits == NULL && ret_eku_bits == NULL)
5714 return EINVAL;
5715
5716 if (ret_eku_bits)
5717 *ret_eku_bits = 0;
5718 else {
5719 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__);
5720 goto check_kus;
5721 }
5722
5723 /* Start with Extended Key usage */
5724 i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
5725 if (i >= 0) {
5726 EXTENDED_KEY_USAGE *eku;
5727
5728 eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
5729 if (eku) {
5730 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
5731 ASN1_OBJECT *certoid;
5732 certoid = sk_ASN1_OBJECT_value(eku, i);
5733 if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0)
5734 eku_bits |= PKINIT_EKU_PKINIT;
5735 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0)
5736 eku_bits |= PKINIT_EKU_MSSCLOGIN;
5737 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0)
5738 eku_bits |= PKINIT_EKU_CLIENTAUTH;
5739 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0)
5740 eku_bits |= PKINIT_EKU_EMAILPROTECTION;
5741 }
5742 EXTENDED_KEY_USAGE_free(eku);
5743 }
5744 }
5745 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits);
5746 *ret_eku_bits = eku_bits;
5747
5748 check_kus:
5749 /* Now the Key Usage bits */
5750 if (ret_ku_bits)
5751 *ret_ku_bits = 0;
5752 else {
5753 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__);
5754 goto out;
5755 }
5756
5757 /* Make sure usage exists before checking bits */
5758 usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL);
5759 if (usage) {
5760 if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
5761 ku_bits |= PKINIT_KU_DIGITALSIGNATURE;
5762 if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT))
5763 ku_bits |= PKINIT_KU_KEYENCIPHERMENT;
5764 ASN1_BIT_STRING_free(usage);
5765 }
5766
5767 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits);
5768 *ret_ku_bits = ku_bits;
5769
5770 out:
5771 return 0;
5772 }
5773
5774 /*
5775 * Return a string format of an X509_NAME in buf where
5776 * size is an in/out parameter. On input it is the size
5777 * of the buffer, and on output it is the actual length
5778 * of the name.
5779 * If buf is NULL, returns the length req'd to hold name
5780 */
5781 static char *
5782 X509_NAME_oneline_ex(X509_NAME * a,
5783 char *buf,
5784 unsigned int *size,
5785 unsigned long flag)
5786 {
5787 BIO *out = NULL;
5788
5789 out = BIO_new(BIO_s_mem ());
5790 if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
5791 if (buf != NULL && *size > (int) BIO_number_written(out)) {
5792 (void) memset(buf, 0, *size);
5793 BIO_read(out, buf, (int) BIO_number_written(out));
5794 }
5795 else {
5796 *size = BIO_number_written(out);
5797 }
5798 }
5799 BIO_free(out);
5800 return (buf);
5801 }
5802
5803 /*
5804 * Get certificate information
5805 */
5806 krb5_error_code
5807 crypto_cert_get_matching_data(krb5_context context,
5808 pkinit_cert_handle ch,
5809 pkinit_cert_matching_data **ret_md)
5810 {
5811 krb5_error_code retval;
5812 pkinit_cert_matching_data *md;
5813 krb5_principal *pkinit_sans =NULL, *upn_sans = NULL;
5814 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
5815 int i, j;
5816 char buf[DN_BUF_LEN];
5817 unsigned int bufsize = sizeof(buf);
5818
5819 if (cd == NULL || cd->magic != CERT_MAGIC)
5820 return EINVAL;
5821 if (ret_md == NULL)
5822 return EINVAL;
5823
5824 md = calloc(1, sizeof(*md));
5825 if (md == NULL)
5826 return ENOMEM;
5827
5828 md->ch = ch;
5829
5830 /* get the subject name (in rfc2253 format) */
5831 X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert),
5832 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
5833 md->subject_dn = strdup(buf);
5834 if (md->subject_dn == NULL) {
5835 retval = ENOMEM;
5836 goto cleanup;
5837 }
5838
5839 /* get the issuer name (in rfc2253 format) */
5840 X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert),
5841 buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
5842 md->issuer_dn = strdup(buf);
5843 if (md->issuer_dn == NULL) {
5844 retval = ENOMEM;
5845 goto cleanup;
5846 }
5847
5848 /* get the san data */
5849 retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,
5850 cd->cred->cert, &pkinit_sans,
5851 &upn_sans, NULL);
5852 if (retval)
5853 goto cleanup;
5854
5855 j = 0;
5856 if (pkinit_sans != NULL) {
5857 for (i = 0; pkinit_sans[i] != NULL; i++)
5858 j++;
5859 }
5860 if (upn_sans != NULL) {
5861 for (i = 0; upn_sans[i] != NULL; i++)
5862 j++;
5863 }
5864 if (j != 0) {
5865 md->sans = calloc((size_t)j+1, sizeof(*md->sans));
5866 if (md->sans == NULL) {
5867 retval = ENOMEM;
5868 goto cleanup;
5869 }
5870 j = 0;
5871 if (pkinit_sans != NULL) {
5872 for (i = 0; pkinit_sans[i] != NULL; i++)
5873 md->sans[j++] = pkinit_sans[i];
5874 free(pkinit_sans);
5875 }
5876 if (upn_sans != NULL) {
5877 for (i = 0; upn_sans[i] != NULL; i++)
5878 md->sans[j++] = upn_sans[i];
5879 free(upn_sans);
5880 }
5881 md->sans[j] = NULL;
5882 } else
5883 md->sans = NULL;
5884
5885 /* get the KU and EKU data */
5886
5887 retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx,
5888 cd->cred->cert,
5889 &md->ku_bits, &md->eku_bits);
5890 if (retval)
5891 goto cleanup;
5892
5893 *ret_md = md;
5894 retval = 0;
5895 cleanup:
5896 if (retval) {
5897 if (md)
5898 crypto_cert_free_matching_data(context, md);
5899 }
5900 return retval;
5901 }
5902
5903 /*
5904 * Free certificate information
5905 */
5906 krb5_error_code
5907 crypto_cert_free_matching_data(krb5_context context,
5908 pkinit_cert_matching_data *md)
5909 {
5910 krb5_principal p;
5911 int i;
5912
5913 if (md == NULL)
5914 return EINVAL;
5915 if (md->subject_dn)
5916 free(md->subject_dn);
5917 if (md->issuer_dn)
5918 free(md->issuer_dn);
5919 if (md->sans) {
5920 for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i])
5921 krb5_free_principal(context, p);
5922 free(md->sans);
5923 }
5924 free(md);
5925 return 0;
5926 }
5927
5928 /*
5929 * Make this matching certificate "the chosen one"
5930 */
5931 /* ARGSUSED */
5932 krb5_error_code
5933 crypto_cert_select(krb5_context context,
5934 pkinit_cert_matching_data *md)
5935 {
5936 struct _pkinit_cert_data *cd;
5937 if (md == NULL)
5938 return EINVAL;
5939
5940 cd = (struct _pkinit_cert_data *)md->ch;
5941 if (cd == NULL || cd->magic != CERT_MAGIC)
5942 return EINVAL;
5943
5944 /* copy the selected cert into our id_cryptoctx */
5945 if (cd->idctx->my_certs != NULL) {
5946 sk_X509_pop_free(cd->idctx->my_certs, X509_free);
5947 }
5948 cd->idctx->my_certs = sk_X509_new_null();
5949 sk_X509_push(cd->idctx->my_certs, cd->cred->cert);
5950 cd->idctx->creds[cd->index]->cert = NULL; /* Don't free it twice */
5951 cd->idctx->cert_index = 0;
5952
5953 if (cd->idctx->pkcs11_method != 1) {
5954 cd->idctx->my_key = cd->cred->key;
5955 cd->idctx->creds[cd->index]->key = NULL; /* Don't free it twice */
5956 }
5957 #ifndef WITHOUT_PKCS11
5958 else {
5959 cd->idctx->cert_id = cd->cred->cert_id;
5960 cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */
5961 cd->idctx->cert_id_len = cd->cred->cert_id_len;
5962 }
5963 #endif
5964 return 0;
5965 }
5966
5967 /*
5968 * Choose the default certificate as "the chosen one"
5969 */
5970 krb5_error_code
5971 crypto_cert_select_default(krb5_context context,
5972 pkinit_plg_crypto_context plg_cryptoctx,
5973 pkinit_req_crypto_context req_cryptoctx,
5974 pkinit_identity_crypto_context id_cryptoctx)
5975 {
5976 krb5_error_code retval;
5977 int cert_count = 0;
5978
5979 retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
5980 id_cryptoctx, &cert_count);
5981 if (retval) {
5982 pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
5983 __FUNCTION__, retval, error_message(retval));
5984 goto errout;
5985 }
5986 if (cert_count != 1) {
5987 /* Solaris Kerberos: Improved error messages */
5988 retval = EINVAL;
5989 krb5_set_error_message(context, retval,
5990 gettext("Failed to select default certificate: "
5991 "found %d certs to choose from but there must be exactly one"),
5992 cert_count);
5993 pkiDebug("%s: ERROR: There are %d certs to choose from, "
5994 "but there must be exactly one.\n",
5995 __FUNCTION__, cert_count);
5996 goto errout;
5997 }
5998 /* copy the selected cert into our id_cryptoctx */
5999 if (id_cryptoctx->my_certs != NULL) {
6000 sk_X509_pop_free(id_cryptoctx->my_certs, X509_free);
6001 }
6002 id_cryptoctx->my_certs = sk_X509_new_null();
6003 sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert);
6004 id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */
6005 id_cryptoctx->cert_index = 0;
6006
6007 if (id_cryptoctx->pkcs11_method != 1) {
6008 id_cryptoctx->my_key = id_cryptoctx->creds[0]->key;
6009 id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */
6010 }
6011 #ifndef WITHOUT_PKCS11
6012 else {
6013 id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id;
6014 id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */
6015 id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len;
6016 }
6017 #endif
6018 retval = 0;
6019 errout:
6020 return retval;
6021 }
6022
6023
6024 /* ARGSUSED */
6025 static krb5_error_code
6026 load_cas_and_crls(krb5_context context,
6027 pkinit_plg_crypto_context plg_cryptoctx,
6028 pkinit_req_crypto_context req_cryptoctx,
6029 pkinit_identity_crypto_context id_cryptoctx,
6030 int catype,
6031 char *filename)
6032 {
6033 STACK_OF(X509_INFO) *sk = NULL;
6034 STACK_OF(X509) *ca_certs = NULL;
6035 STACK_OF(X509_CRL) *ca_crls = NULL;
6036 BIO *in = NULL;
6037 /* Solaris Kerberos */
6038 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
6039 int i = 0;
6040
6041 /* If there isn't already a stack in the context,
6042 * create a temporary one now */
6043 switch(catype) {
6044 case CATYPE_ANCHORS:
6045 if (id_cryptoctx->trustedCAs != NULL)
6046 ca_certs = id_cryptoctx->trustedCAs;
6047 else {
6048 ca_certs = sk_X509_new_null();
6049 if (ca_certs == NULL)
6050 return ENOMEM;
6051 }
6052 break;
6053 case CATYPE_INTERMEDIATES:
6054 if (id_cryptoctx->intermediateCAs != NULL)
6055 ca_certs = id_cryptoctx->intermediateCAs;
6056 else {
6057 ca_certs = sk_X509_new_null();
6058 if (ca_certs == NULL)
6059 return ENOMEM;
6060 }
6061 break;
6062 case CATYPE_CRLS:
6063 if (id_cryptoctx->revoked != NULL)
6064 ca_crls = id_cryptoctx->revoked;
6065 else {
6066 ca_crls = sk_X509_CRL_new_null();
6067 if (ca_crls == NULL)
6068 return ENOMEM;
6069 }
6070 break;
6071 default:
6072 return ENOTSUP;
6073 }
6074
6075 if (!(in = BIO_new_file(filename, "r"))) {
6076 retval = errno;
6077 pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__,
6078 filename, error_message(errno));
6079 goto cleanup;
6080 }
6081
6082 /* This loads from a file, a stack of x509/crl/pkey sets */
6083 if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) {
6084 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename);
6085 retval = EIO;
6086 goto cleanup;
6087 }
6088
6089 /* scan over the stack created from loading the file contents,
6090 * weed out duplicates, and push new ones onto the return stack
6091 */
6092 for (i = 0; i < sk_X509_INFO_num(sk); i++) {
6093 X509_INFO *xi = sk_X509_INFO_value(sk, i);
6094 if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) {
6095 int j = 0, size = sk_X509_num(ca_certs), flag = 0;
6096
6097 if (!size) {
6098 sk_X509_push(ca_certs, xi->x509);
6099 xi->x509 = NULL;
6100 continue;
6101 }
6102 for (j = 0; j < size; j++) {
6103 X509 *x = sk_X509_value(ca_certs, j);
6104 flag = X509_cmp(x, xi->x509);
6105 if (flag == 0)
6106 break;
6107 else
6108 continue;
6109 }
6110 if (flag != 0) {
6111 sk_X509_push(ca_certs, X509_dup(xi->x509));
6112 }
6113 } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) {
6114 int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0;
6115 if (!size) {
6116 sk_X509_CRL_push(ca_crls, xi->crl);
6117 xi->crl = NULL;
6118 continue;
6119 }
6120 for (j = 0; j < size; j++) {
6121 X509_CRL *x = sk_X509_CRL_value(ca_crls, j);
6122 flag = X509_CRL_cmp(x, xi->crl);
6123 if (flag == 0)
6124 break;
6125 else
6126 continue;
6127 }
6128 if (flag != 0) {
6129 sk_X509_CRL_push(ca_crls, X509_CRL_dup(xi->crl));
6130 }
6131 }
6132 }
6133
6134 /* If we added something and there wasn't a stack in the
6135 * context before, add the temporary stack to the context.
6136 */
6137 switch(catype) {
6138 case CATYPE_ANCHORS:
6139 if (sk_X509_num(ca_certs) == 0) {
6140 pkiDebug("no anchors in file, %s\n", filename);
6141 if (id_cryptoctx->trustedCAs == NULL)
6142 sk_X509_free(ca_certs);
6143 } else {
6144 if (id_cryptoctx->trustedCAs == NULL)
6145 id_cryptoctx->trustedCAs = ca_certs;
6146 }
6147 break;
6148 case CATYPE_INTERMEDIATES:
6149 if (sk_X509_num(ca_certs) == 0) {
6150 pkiDebug("no intermediates in file, %s\n", filename);
6151 if (id_cryptoctx->intermediateCAs == NULL)
6152 sk_X509_free(ca_certs);
6153 } else {
6154 if (id_cryptoctx->intermediateCAs == NULL)
6155 id_cryptoctx->intermediateCAs = ca_certs;
6156 }
6157 break;
6158 case CATYPE_CRLS:
6159 if (sk_X509_CRL_num(ca_crls) == 0) {
6160 pkiDebug("no crls in file, %s\n", filename);
6161 if (id_cryptoctx->revoked == NULL)
6162 sk_X509_CRL_free(ca_crls);
6163 } else {
6164 if (id_cryptoctx->revoked == NULL)
6165 id_cryptoctx->revoked = ca_crls;
6166 }
6167 break;
6168 default:
6169 /* Should have been caught above! */
6170 retval = EINVAL;
6171 goto cleanup;
6172 /* Solaris Kerberos: removed "break" as it's never reached */
6173 }
6174
6175 retval = 0;
6176
6177 cleanup:
6178 if (in != NULL)
6179 BIO_free(in);
6180 if (sk != NULL)
6181 sk_X509_INFO_pop_free(sk, X509_INFO_free);
6182
6183 return retval;
6184 }
6185
6186 static krb5_error_code
6187 load_cas_and_crls_dir(krb5_context context,
6188 pkinit_plg_crypto_context plg_cryptoctx,
6189 pkinit_req_crypto_context req_cryptoctx,
6190 pkinit_identity_crypto_context id_cryptoctx,
6191 int catype,
6192 char *dirname)
6193 {
6194 krb5_error_code retval = EINVAL;
6195 DIR *d = NULL;
6196 struct dirent *dentry = NULL;
6197 char filename[1024];
6198
6199 if (dirname == NULL)
6200 return EINVAL;
6201
6202 d = opendir(dirname);
6203 if (d == NULL)
6204 return ENOENT;
6205
6206 while ((dentry = readdir(d))) {
6207 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) {
6208 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
6209 __FUNCTION__, dirname, dentry->d_name);
6210 goto cleanup;
6211 }
6212 /* Ignore subdirectories and anything starting with a dot */
6213 #ifdef DT_DIR
6214 if (dentry->d_type == DT_DIR)
6215 continue;
6216 #endif
6217 if (dentry->d_name[0] == '.')
6218 continue;
6219 (void) snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
6220
6221 retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
6222 id_cryptoctx, catype, filename);
6223 if (retval)
6224 goto cleanup;
6225 }
6226
6227 retval = 0;
6228
6229 cleanup:
6230 if (d != NULL)
6231 (void) closedir(d);
6232
6233 return retval;
6234 }
6235
6236 /* ARGSUSED */
6237 krb5_error_code
6238 crypto_load_cas_and_crls(krb5_context context,
6239 pkinit_plg_crypto_context plg_cryptoctx,
6240 pkinit_req_crypto_context req_cryptoctx,
6241 pkinit_identity_opts *idopts,
6242 pkinit_identity_crypto_context id_cryptoctx,
6243 int idtype,
6244 int catype,
6245 char *id)
6246 {
6247 pkiDebug("%s: called with idtype %s and catype %s\n",
6248 __FUNCTION__, idtype2string(idtype), catype2string(catype));
6249 /* Solaris Kerberos: Removed "break"'s as they are never reached */
6250 switch (idtype) {
6251 case IDTYPE_FILE:
6252 return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
6253 id_cryptoctx, catype, id);
6254 case IDTYPE_DIR:
6255 return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
6256 id_cryptoctx, catype, id);
6257 default:
6258 return ENOTSUP;
6259 }
6260 }
6261
6262 static krb5_error_code
6263 create_identifiers_from_stack(STACK_OF(X509) *sk,
6264 krb5_external_principal_identifier *** ids)
6265 {
6266 krb5_error_code retval = ENOMEM;
6267 int i = 0, sk_size = sk_X509_num(sk);
6268 krb5_external_principal_identifier **krb5_cas = NULL;
6269 X509 *x = NULL;
6270 X509_NAME *xn = NULL;
6271 unsigned char *p = NULL;
6272 int len = 0;
6273 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6274 char buf[DN_BUF_LEN];
6275
6276 *ids = NULL;
6277
6278 krb5_cas =
6279 malloc((sk_size + 1) * sizeof(krb5_external_principal_identifier *));
6280 if (krb5_cas == NULL)
6281 return ENOMEM;
6282 krb5_cas[sk_size] = NULL;
6283
6284 for (i = 0; i < sk_size; i++) {
6285 krb5_cas[i] = (krb5_external_principal_identifier *)malloc(sizeof(krb5_external_principal_identifier));
6286
6287 x = sk_X509_value(sk, i);
6288
6289 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
6290 pkiDebug("#%d cert= %s\n", i, buf);
6291
6292 /* fill-in subjectName */
6293 krb5_cas[i]->subjectName.magic = 0;
6294 krb5_cas[i]->subjectName.length = 0;
6295 krb5_cas[i]->subjectName.data = NULL;
6296
6297 xn = X509_get_subject_name(x);
6298 len = i2d_X509_NAME(xn, NULL);
6299 if ((p = krb5_cas[i]->subjectName.data = (unsigned char *)malloc((size_t) len)) == NULL)
6300 goto cleanup;
6301 i2d_X509_NAME(xn, &p);
6302 krb5_cas[i]->subjectName.length = len;
6303
6304 /* fill-in issuerAndSerialNumber */
6305 krb5_cas[i]->issuerAndSerialNumber.length = 0;
6306 krb5_cas[i]->issuerAndSerialNumber.magic = 0;
6307 krb5_cas[i]->issuerAndSerialNumber.data = NULL;
6308
6309 #ifdef LONGHORN_BETA_COMPAT
6310 if (longhorn == 0) { /* XXX Longhorn doesn't like this */
6311 #endif
6312 is = PKCS7_ISSUER_AND_SERIAL_new();
6313 X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
6314 ASN1_INTEGER_free(is->serial);
6315 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
6316 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
6317 if ((p = krb5_cas[i]->issuerAndSerialNumber.data =
6318 (unsigned char *)malloc((size_t) len)) == NULL)
6319 goto cleanup;
6320 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
6321 krb5_cas[i]->issuerAndSerialNumber.length = len;
6322 #ifdef LONGHORN_BETA_COMPAT
6323 }
6324 #endif
6325
6326 /* fill-in subjectKeyIdentifier */
6327 krb5_cas[i]->subjectKeyIdentifier.length = 0;
6328 krb5_cas[i]->subjectKeyIdentifier.magic = 0;
6329 krb5_cas[i]->subjectKeyIdentifier.data = NULL;
6330
6331
6332 #ifdef LONGHORN_BETA_COMPAT
6333 if (longhorn == 0) { /* XXX Longhorn doesn't like this */
6334 #endif
6335 if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
6336 ASN1_OCTET_STRING *ikeyid = NULL;
6337
6338 if ((ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
6339 NULL))) {
6340 len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
6341 if ((p = krb5_cas[i]->subjectKeyIdentifier.data =
6342 (unsigned char *)malloc((size_t) len)) == NULL)
6343 goto cleanup;
6344 i2d_ASN1_OCTET_STRING(ikeyid, &p);
6345 krb5_cas[i]->subjectKeyIdentifier.length = len;
6346 }
6347 if (ikeyid != NULL)
6348 ASN1_OCTET_STRING_free(ikeyid);
6349 }
6350 #ifdef LONGHORN_BETA_COMPAT
6351 }
6352 #endif
6353 if (is != NULL) {
6354 if (is->issuer != NULL)
6355 X509_NAME_free(is->issuer);
6356 if (is->serial != NULL)
6357 ASN1_INTEGER_free(is->serial);
6358 free(is);
6359 }
6360 }
6361
6362 *ids = krb5_cas;
6363
6364 retval = 0;
6365 cleanup:
6366 if (retval)
6367 free_krb5_external_principal_identifier(&krb5_cas);
6368
6369 return retval;
6370 }
6371
6372 /* ARGSUSED */
6373 static krb5_error_code
6374 create_krb5_invalidCertificates(krb5_context context,
6375 pkinit_plg_crypto_context plg_cryptoctx,
6376 pkinit_req_crypto_context req_cryptoctx,
6377 pkinit_identity_crypto_context id_cryptoctx,
6378 krb5_external_principal_identifier *** ids)
6379 {
6380
6381 krb5_error_code retval = ENOMEM;
6382 STACK_OF(X509) *sk = NULL;
6383
6384 *ids = NULL;
6385 if (req_cryptoctx->received_cert == NULL)
6386 return KRB5KDC_ERR_PREAUTH_FAILED;
6387
6388 sk = sk_X509_new_null();
6389 if (sk == NULL)
6390 goto cleanup;
6391 sk_X509_push(sk, req_cryptoctx->received_cert);
6392
6393 retval = create_identifiers_from_stack(sk, ids);
6394
6395 sk_X509_free(sk);
6396 cleanup:
6397
6398 return retval;
6399 }
6400
6401 /* ARGSUSED */
6402 krb5_error_code
6403 create_krb5_supportedCMSTypes(krb5_context context,
6404 pkinit_plg_crypto_context plg_cryptoctx,
6405 pkinit_req_crypto_context req_cryptoctx,
6406 pkinit_identity_crypto_context id_cryptoctx,
6407 krb5_algorithm_identifier ***oids)
6408 {
6409
6410 krb5_error_code retval = ENOMEM;
6411 krb5_algorithm_identifier **loids = NULL;
6412 krb5_octet_data des3oid = {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
6413
6414 *oids = NULL;
6415 loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
6416 if (loids == NULL)
6417 goto cleanup;
6418 loids[1] = NULL;
6419 loids[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
6420 if (loids[0] == NULL) {
6421 free(loids);
6422 goto cleanup;
6423 }
6424 retval = pkinit_copy_krb5_octet_data(&loids[0]->algorithm, &des3oid);
6425 if (retval) {
6426 free(loids[0]);
6427 free(loids);
6428 goto cleanup;
6429 }
6430 loids[0]->parameters.length = 0;
6431 loids[0]->parameters.data = NULL;
6432
6433 *oids = loids;
6434 retval = 0;
6435 cleanup:
6436
6437 return retval;
6438 }
6439
6440 /* ARGSUSED */
6441 krb5_error_code
6442 create_krb5_trustedCertifiers(krb5_context context,
6443 pkinit_plg_crypto_context plg_cryptoctx,
6444 pkinit_req_crypto_context req_cryptoctx,
6445 pkinit_identity_crypto_context id_cryptoctx,
6446 krb5_external_principal_identifier *** ids)
6447 {
6448
6449 /* Solaris Kerberos */
6450 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
6451
6452 *ids = NULL;
6453 if (id_cryptoctx->trustedCAs == NULL)
6454 return KRB5KDC_ERR_PREAUTH_FAILED;
6455
6456 return create_identifiers_from_stack(sk, ids);
6457
6458 }
6459
6460 /* ARGSUSED */
6461 krb5_error_code
6462 create_krb5_trustedCas(krb5_context context,
6463 pkinit_plg_crypto_context plg_cryptoctx,
6464 pkinit_req_crypto_context req_cryptoctx,
6465 pkinit_identity_crypto_context id_cryptoctx,
6466 int flag,
6467 krb5_trusted_ca *** ids)
6468 {
6469 krb5_error_code retval = ENOMEM;
6470 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
6471 int i = 0, len = 0, sk_size = sk_X509_num(sk);
6472 krb5_trusted_ca **krb5_cas = NULL;
6473 X509 *x = NULL;
6474 char buf[DN_BUF_LEN];
6475 X509_NAME *xn = NULL;
6476 unsigned char *p = NULL;
6477 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6478
6479 *ids = NULL;
6480 if (id_cryptoctx->trustedCAs == NULL)
6481 return KRB5KDC_ERR_PREAUTH_FAILED;
6482
6483 krb5_cas = malloc((sk_size + 1) * sizeof(krb5_trusted_ca *));
6484 if (krb5_cas == NULL)
6485 return ENOMEM;
6486 krb5_cas[sk_size] = NULL;
6487
6488 for (i = 0; i < sk_size; i++) {
6489 krb5_cas[i] = (krb5_trusted_ca *)malloc(sizeof(krb5_trusted_ca));
6490 if (krb5_cas[i] == NULL)
6491 goto cleanup;
6492 x = sk_X509_value(sk, i);
6493
6494 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
6495 pkiDebug("#%d cert= %s\n", i, buf);
6496
6497 switch (flag) {
6498 case choice_trusted_cas_principalName:
6499 krb5_cas[i]->choice = choice_trusted_cas_principalName;
6500 break;
6501 case choice_trusted_cas_caName:
6502 krb5_cas[i]->choice = choice_trusted_cas_caName;
6503 krb5_cas[i]->u.caName.data = NULL;
6504 krb5_cas[i]->u.caName.length = 0;
6505 xn = X509_get_subject_name(x);
6506 len = i2d_X509_NAME(xn, NULL);
6507 if ((p = krb5_cas[i]->u.caName.data =
6508 (unsigned char *)malloc((size_t) len)) == NULL)
6509 goto cleanup;
6510 i2d_X509_NAME(xn, &p);
6511 krb5_cas[i]->u.caName.length = len;
6512 break;
6513 case choice_trusted_cas_issuerAndSerial:
6514 krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial;
6515 krb5_cas[i]->u.issuerAndSerial.data = NULL;
6516 krb5_cas[i]->u.issuerAndSerial.length = 0;
6517 is = PKCS7_ISSUER_AND_SERIAL_new();
6518 X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
6519 ASN1_INTEGER_free(is->serial);
6520 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
6521 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
6522 if ((p = krb5_cas[i]->u.issuerAndSerial.data =
6523 (unsigned char *)malloc((size_t) len)) == NULL)
6524 goto cleanup;
6525 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
6526 krb5_cas[i]->u.issuerAndSerial.length = len;
6527 if (is != NULL) {
6528 if (is->issuer != NULL)
6529 X509_NAME_free(is->issuer);
6530 if (is->serial != NULL)
6531 ASN1_INTEGER_free(is->serial);
6532 free(is);
6533 }
6534 break;
6535 default: break;
6536 }
6537 }
6538 retval = 0;
6539 *ids = krb5_cas;
6540 cleanup:
6541 if (retval)
6542 free_krb5_trusted_ca(&krb5_cas);
6543
6544 return retval;
6545 }
6546
6547 /* ARGSUSED */
6548 krb5_error_code
6549 create_issuerAndSerial(krb5_context context,
6550 pkinit_plg_crypto_context plg_cryptoctx,
6551 pkinit_req_crypto_context req_cryptoctx,
6552 pkinit_identity_crypto_context id_cryptoctx,
6553 unsigned char **out,
6554 unsigned int *out_len)
6555 {
6556 unsigned char *p = NULL;
6557 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6558 int len = 0;
6559 krb5_error_code retval = ENOMEM;
6560 X509 *cert = req_cryptoctx->received_cert;
6561
6562 *out = NULL;
6563 *out_len = 0;
6564 if (req_cryptoctx->received_cert == NULL)
6565 return 0;
6566
6567 is = PKCS7_ISSUER_AND_SERIAL_new();
6568 X509_NAME_set(&is->issuer, X509_get_issuer_name(cert));
6569 ASN1_INTEGER_free(is->serial);
6570 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert));
6571 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
6572 if ((p = *out = (unsigned char *)malloc((size_t) len)) == NULL)
6573 goto cleanup;
6574 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
6575 *out_len = len;
6576 retval = 0;
6577
6578 cleanup:
6579 X509_NAME_free(is->issuer);
6580 ASN1_INTEGER_free(is->serial);
6581 free(is);
6582
6583 return retval;
6584 }
6585
6586 static int
6587 pkcs7_decrypt(krb5_context context,
6588 pkinit_identity_crypto_context id_cryptoctx,
6589 PKCS7 *p7,
6590 BIO *data)
6591 {
6592 BIO *tmpmem = NULL;
6593 /* Solaris Kerberos */
6594 int i = 0;
6595 char buf[4096];
6596
6597 if(p7 == NULL)
6598 return 0;
6599
6600 if(!PKCS7_type_is_enveloped(p7)) {
6601 pkiDebug("wrong pkcs7 content type\n");
6602 return 0;
6603 }
6604
6605 if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) {
6606 pkiDebug("unable to decrypt pkcs7 object\n");
6607 return 0;
6608 }
6609 /* Solaris Kerberos: Suppress sun studio compiler warning */
6610 #pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED)
6611 for(;;) {
6612 i = BIO_read(tmpmem, buf, sizeof(buf));
6613 if (i <= 0) break;
6614 BIO_write(data, buf, i);
6615 BIO_free_all(tmpmem);
6616 return 1;
6617 }
6618 #pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED)
6619
6620 return 0;
6621 }
6622
6623 krb5_error_code
6624 pkinit_process_td_trusted_certifiers(
6625 krb5_context context,
6626 pkinit_plg_crypto_context plg_cryptoctx,
6627 pkinit_req_crypto_context req_cryptoctx,
6628 pkinit_identity_crypto_context id_cryptoctx,
6629 krb5_external_principal_identifier **krb5_trusted_certifiers,
6630 int td_type)
6631 {
6632 krb5_error_code retval = ENOMEM;
6633 STACK_OF(X509_NAME) *sk_xn = NULL;
6634 X509_NAME *xn = NULL;
6635 PKCS7_ISSUER_AND_SERIAL *is = NULL;
6636 ASN1_OCTET_STRING *id = NULL;
6637 const unsigned char *p = NULL;
6638 char buf[DN_BUF_LEN];
6639 int i = 0;
6640
6641 if (td_type == TD_TRUSTED_CERTIFIERS)
6642 pkiDebug("received trusted certifiers\n");
6643 else
6644 pkiDebug("received invalid certificate\n");
6645
6646 sk_xn = sk_X509_NAME_new_null();
6647 while(krb5_trusted_certifiers[i] != NULL) {
6648 if (krb5_trusted_certifiers[i]->subjectName.data != NULL) {
6649 p = krb5_trusted_certifiers[i]->subjectName.data;
6650 xn = d2i_X509_NAME(NULL, &p,
6651 (int)krb5_trusted_certifiers[i]->subjectName.length);
6652 if (xn == NULL)
6653 goto cleanup;
6654 X509_NAME_oneline(xn, buf, sizeof(buf));
6655 if (td_type == TD_TRUSTED_CERTIFIERS)
6656 pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf);
6657 else
6658 pkiDebug("#%d cert = %s is invalid\n", i, buf);
6659 sk_X509_NAME_push(sk_xn, xn);
6660 }
6661
6662 if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) {
6663 p = krb5_trusted_certifiers[i]->issuerAndSerialNumber.data;
6664 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p,
6665 (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length);
6666 if (is == NULL)
6667 goto cleanup;
6668 X509_NAME_oneline(is->issuer, buf, sizeof(buf));
6669 if (td_type == TD_TRUSTED_CERTIFIERS)
6670 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i,
6671 buf, ASN1_INTEGER_get(is->serial));
6672 else
6673 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf,
6674 ASN1_INTEGER_get(is->serial));
6675 PKCS7_ISSUER_AND_SERIAL_free(is);
6676 }
6677
6678 if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) {
6679 p = krb5_trusted_certifiers[i]->subjectKeyIdentifier.data;
6680 id = d2i_ASN1_OCTET_STRING(NULL, &p,
6681 (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length);
6682 if (id == NULL)
6683 goto cleanup;
6684 /* XXX */
6685 ASN1_OCTET_STRING_free(id);
6686 }
6687 i++;
6688 }
6689 /* XXX Since we not doing anything with received trusted certifiers
6690 * return an error. this is the place where we can pick a different
6691 * client certificate based on the information in td_trusted_certifiers
6692 */
6693 retval = KRB5KDC_ERR_PREAUTH_FAILED;
6694 cleanup:
6695 if (sk_xn != NULL)
6696 sk_X509_NAME_pop_free(sk_xn, X509_NAME_free);
6697
6698 return retval;
6699 }
6700
6701 static BIO *
6702 pkcs7_dataDecode(krb5_context context,
6703 pkinit_identity_crypto_context id_cryptoctx,
6704 PKCS7 *p7)
6705 {
6706 int i = 0;
6707 unsigned int jj = 0, tmp_len = 0;
6708 BIO *out=NULL,*etmp=NULL,*bio=NULL;
6709 unsigned char *tmp=NULL;
6710 ASN1_OCTET_STRING *data_body=NULL;
6711 const EVP_CIPHER *evp_cipher=NULL;
6712 EVP_CIPHER_CTX *evp_ctx=NULL;
6713 X509_ALGOR *enc_alg=NULL;
6714 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
6715 /* Solaris Kerberos: Not used */
6716 #if 0
6717 X509_ALGOR *xalg=NULL;
6718 #endif
6719 PKCS7_RECIP_INFO *ri=NULL;
6720 X509 *cert = sk_X509_value(id_cryptoctx->my_certs,
6721 id_cryptoctx->cert_index);
6722
6723 p7->state=PKCS7_S_HEADER;
6724
6725 rsk=p7->d.enveloped->recipientinfo;
6726 enc_alg=p7->d.enveloped->enc_data->algorithm;
6727 data_body=p7->d.enveloped->enc_data->enc_data;
6728 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
6729 if (evp_cipher == NULL) {
6730 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
6731 goto cleanup;
6732 }
6733 /* Solaris Kerberos: Not used */
6734 #if 0
6735 xalg=p7->d.enveloped->enc_data->algorithm;
6736 #endif
6737
6738 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) {
6739 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
6740 goto cleanup;
6741 }
6742
6743 /* It was encrypted, we need to decrypt the secret key
6744 * with the private key */
6745
6746 /* Find the recipientInfo which matches the passed certificate
6747 * (if any)
6748 */
6749
6750 if (cert) {
6751 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
6752 int tmp_ret = 0;
6753 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
6754 tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
6755 X509_get_issuer_name(cert));
6756 if (!tmp_ret) {
6757 tmp_ret = ASN1_INTEGER_cmp(X509_get_serialNumber(cert),
6758 ri->issuer_and_serial->serial);
6759 if (!tmp_ret)
6760 break;
6761 }
6762 ri=NULL;
6763 }
6764 if (ri == NULL) {
6765 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
6766 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
6767 goto cleanup;
6768 }
6769
6770 }
6771
6772 /* If we haven't got a certificate try each ri in turn */
6773
6774 if (cert == NULL) {
6775 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
6776 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
6777 jj = pkinit_decode_data(context, id_cryptoctx,
6778 (unsigned char *)ASN1_STRING_get0_data(ri->enc_key),
6779 ASN1_STRING_length(ri->enc_key),
6780 &tmp, &tmp_len);
6781 if (jj) {
6782 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
6783 goto cleanup;
6784 }
6785
6786 if (!jj && tmp_len > 0) {
6787 jj = tmp_len;
6788 break;
6789 }
6790
6791 ERR_clear_error();
6792 ri = NULL;
6793 }
6794
6795 if (ri == NULL) {
6796 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
6797 goto cleanup;
6798 }
6799 }
6800 else {
6801 jj = pkinit_decode_data(context, id_cryptoctx,
6802 (unsigned char *)ASN1_STRING_get0_data(ri->enc_key),
6803 ASN1_STRING_length(ri->enc_key),
6804 &tmp, &tmp_len);
6805 /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */
6806 if (jj || tmp_len == 0) {
6807 PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
6808 goto cleanup;
6809 }
6810 jj = tmp_len;
6811 }
6812
6813 evp_ctx=NULL;
6814 BIO_get_cipher_ctx(etmp,&evp_ctx);
6815 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
6816 goto cleanup;
6817 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
6818 goto cleanup;
6819
6820 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
6821 /* Some S/MIME clients don't use the same key
6822 * and effective key length. The key length is
6823 * determined by the size of the decrypted RSA key.
6824 */
6825 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) {
6826 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
6827 PKCS7_R_DECRYPT_ERROR);
6828 goto cleanup;
6829 }
6830 }
6831 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
6832 goto cleanup;
6833
6834 OPENSSL_cleanse(tmp,jj);
6835
6836 if (out == NULL)
6837 out=etmp;
6838 else
6839 BIO_push(out,etmp);
6840 etmp=NULL;
6841
6842 if (data_body->length > 0)
6843 bio = BIO_new_mem_buf(data_body->data, data_body->length);
6844 else {
6845 bio=BIO_new(BIO_s_mem());
6846 BIO_set_mem_eof_return(bio,0);
6847 }
6848 BIO_push(out,bio);
6849 bio=NULL;
6850
6851 /* Solaris Kerberos */
6852 goto out;
6853
6854 cleanup:
6855 if (out != NULL) BIO_free_all(out);
6856 if (etmp != NULL) BIO_free_all(etmp);
6857 if (bio != NULL) BIO_free_all(bio);
6858 out=NULL;
6859
6860 out:
6861 if (tmp != NULL)
6862 free(tmp);
6863
6864 return(out);
6865 }
6866
6867 static krb5_error_code
6868 der_decode_data(unsigned char *data, long data_len,
6869 unsigned char **out, long *out_len)
6870 {
6871 /* Solaris Kerberos */
6872 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
6873 ASN1_OCTET_STRING *s = NULL;
6874 const unsigned char *p = data;
6875
6876 if ((s = d2i_ASN1_BIT_STRING(NULL, &p, data_len)) == NULL)
6877 goto cleanup;
6878 *out_len = s->length;
6879 if ((*out = (unsigned char *) malloc((size_t) *out_len + 1)) == NULL) {
6880 retval = ENOMEM;
6881 goto cleanup;
6882 }
6883 (void) memcpy(*out, s->data, (size_t) s->length);
6884 (*out)[s->length] = '\0';
6885
6886 retval = 0;
6887 cleanup:
6888 if (s != NULL)
6889 ASN1_OCTET_STRING_free(s);
6890
6891 return retval;
6892 }
6893
6894
6895 #ifdef DEBUG_DH
6896 static void
6897 print_dh(DH * dh, char *msg)
6898 {
6899 BIO *bio_err = NULL;
6900
6901 bio_err = BIO_new(BIO_s_file());
6902 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
6903
6904 if (msg)
6905 BIO_puts(bio_err, (const char *)msg);
6906 if (dh)
6907 DHparams_print(bio_err, dh);
6908
6909 BN_print(bio_err, dh->q);
6910 BIO_puts(bio_err, (const char *)"\n");
6911 BIO_free(bio_err);
6912
6913 }
6914
6915 static void
6916 print_pubkey(BIGNUM * key, char *msg)
6917 {
6918 BIO *bio_err = NULL;
6919
6920 bio_err = BIO_new(BIO_s_file());
6921 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
6922
6923 if (msg)
6924 BIO_puts(bio_err, (const char *)msg);
6925 if (key)
6926 BN_print(bio_err, key);
6927 BIO_puts(bio_err, "\n");
6928
6929 BIO_free(bio_err);
6930
6931 }
6932 #endif
6933
6934 /*
6935 * Solaris Kerberos:
6936 * Error message generation has changed so gettext() can be used
6937 */
6938 #if 0
6939 static char *
6940 pkinit_pkcs11_code_to_text(int err)
6941 {
6942 int i;
6943 static char uc[64];
6944
6945 for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
6946 if (pkcs11_errstrings[i].code == err)
6947 break;
6948 if (pkcs11_errstrings[i].text != NULL)
6949 return (pkcs11_errstrings[i].text);
6950 snprintf(uc, 64, gettext("unknown code 0x%x"), err);
6951 return (uc);
6952 }
6953 #endif
6954
6955 static char *
6956 pkinit_pkcs11_code_to_text(int err) {
6957 return pkcs11_error_table(err);
6958 }