2 * COPYRIGHT (C) 2006,2007
3 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
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
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
32 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
33 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
34 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
35 * Copyright 2018 RackTop Systems.
47 /* Solaris Kerberos */
50 #include <security/pam_appl.h>
56 * Q: What is this SILLYDECRYPT stuff about?
57 * A: When using the ActivCard Linux pkcs11 library (v2.0.1),
58 * the decrypt function fails. By inserting an extra
59 * function call, which serves nothing but to change the
60 * stack, we were able to work around the issue. If the
61 * ActivCard library is fixed in the future, this
62 * definition and related code can be removed.
66 #include "pkinit_crypto_openssl.h"
70 * Changed to a switch statement so gettext() can be used
71 * for internationization.
72 * Use defined constants rather than raw numbers for error codes.
75 pkcs11_error_table(short code
) {
78 return (gettext("ok"));
80 return (gettext("cancel"));
82 return (gettext("host memory"));
83 case CKR_SLOT_ID_INVALID
:
84 return (gettext("slot id invalid"));
85 case CKR_GENERAL_ERROR
:
86 return (gettext("general error"));
87 case CKR_FUNCTION_FAILED
:
88 return (gettext("function failed"));
89 case CKR_ARGUMENTS_BAD
:
90 return (gettext("arguments bad"));
92 return (gettext("no event"));
93 case CKR_NEED_TO_CREATE_THREADS
:
94 return (gettext("need to create threads"));
96 return (gettext("cant lock"));
97 case CKR_ATTRIBUTE_READ_ONLY
:
98 return (gettext("attribute read only"));
99 case CKR_ATTRIBUTE_SENSITIVE
:
100 return (gettext("attribute sensitive"));
101 case CKR_ATTRIBUTE_TYPE_INVALID
:
102 return (gettext("attribute type invalid"));
103 case CKR_ATTRIBUTE_VALUE_INVALID
:
104 return (gettext("attribute value invalid"));
105 case CKR_DATA_INVALID
:
106 return (gettext("data invalid"));
107 case CKR_DATA_LEN_RANGE
:
108 return (gettext("data len range"));
109 case CKR_DEVICE_ERROR
:
110 return (gettext("device error"));
111 case CKR_DEVICE_MEMORY
:
112 return (gettext("device memory"));
113 case CKR_DEVICE_REMOVED
:
114 return (gettext("device removed"));
115 case CKR_ENCRYPTED_DATA_INVALID
:
116 return (gettext("encrypted data invalid"));
117 case CKR_ENCRYPTED_DATA_LEN_RANGE
:
118 return (gettext("encrypted data len range"));
119 case CKR_FUNCTION_CANCELED
:
120 return (gettext("function canceled"));
121 case CKR_FUNCTION_NOT_PARALLEL
:
122 return (gettext("function not parallel"));
123 case CKR_FUNCTION_NOT_SUPPORTED
:
124 return (gettext("function not supported"));
125 case CKR_KEY_HANDLE_INVALID
:
126 return (gettext("key handle invalid"));
127 case CKR_KEY_SIZE_RANGE
:
128 return (gettext("key size range"));
129 case CKR_KEY_TYPE_INCONSISTENT
:
130 return (gettext("key type inconsistent"));
131 case CKR_KEY_NOT_NEEDED
:
132 return (gettext("key not needed"));
133 case CKR_KEY_CHANGED
:
134 return (gettext("key changed"));
136 return (gettext("key needed"));
137 case CKR_KEY_INDIGESTIBLE
:
138 return (gettext("key indigestible"));
139 case CKR_KEY_FUNCTION_NOT_PERMITTED
:
140 return (gettext("key function not permitted"));
141 case CKR_KEY_NOT_WRAPPABLE
:
142 return (gettext("key not wrappable"));
143 case CKR_KEY_UNEXTRACTABLE
:
144 return (gettext("key unextractable"));
145 case CKR_MECHANISM_INVALID
:
146 return (gettext("mechanism invalid"));
147 case CKR_MECHANISM_PARAM_INVALID
:
148 return (gettext("mechanism param invalid"));
149 case CKR_OBJECT_HANDLE_INVALID
:
150 return (gettext("object handle invalid"));
151 case CKR_OPERATION_ACTIVE
:
152 return (gettext("operation active"));
153 case CKR_OPERATION_NOT_INITIALIZED
:
154 return (gettext("operation not initialized"));
155 case CKR_PIN_INCORRECT
:
156 return (gettext("pin incorrect"));
157 case CKR_PIN_INVALID
:
158 return (gettext("pin invalid"));
159 case CKR_PIN_LEN_RANGE
:
160 return (gettext("pin len range"));
161 case CKR_PIN_EXPIRED
:
162 return (gettext("pin expired"));
164 return (gettext("pin locked"));
165 case CKR_SESSION_CLOSED
:
166 return (gettext("session closed"));
167 case CKR_SESSION_COUNT
:
168 return (gettext("session count"));
169 case CKR_SESSION_HANDLE_INVALID
:
170 return (gettext("session handle invalid"));
171 case CKR_SESSION_PARALLEL_NOT_SUPPORTED
:
172 return (gettext("session parallel not supported"));
173 case CKR_SESSION_READ_ONLY
:
174 return (gettext("session read only"));
175 case CKR_SESSION_EXISTS
:
176 return (gettext("session exists"));
177 case CKR_SESSION_READ_ONLY_EXISTS
:
178 return (gettext("session read only exists"));
179 case CKR_SESSION_READ_WRITE_SO_EXISTS
:
180 return (gettext("session read write so exists"));
181 case CKR_SIGNATURE_INVALID
:
182 return (gettext("signature invalid"));
183 case CKR_SIGNATURE_LEN_RANGE
:
184 return (gettext("signature len range"));
185 case CKR_TEMPLATE_INCOMPLETE
:
186 return (gettext("template incomplete"));
187 case CKR_TEMPLATE_INCONSISTENT
:
188 return (gettext("template inconsistent"));
189 case CKR_TOKEN_NOT_PRESENT
:
190 return (gettext("token not present"));
191 case CKR_TOKEN_NOT_RECOGNIZED
:
192 return (gettext("token not recognized"));
193 case CKR_TOKEN_WRITE_PROTECTED
:
194 return (gettext("token write protected"));
195 case CKR_UNWRAPPING_KEY_HANDLE_INVALID
:
196 return (gettext("unwrapping key handle invalid"));
197 case CKR_UNWRAPPING_KEY_SIZE_RANGE
:
198 return (gettext("unwrapping key size range"));
199 case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
:
200 return (gettext("unwrapping key type inconsistent"));
201 case CKR_USER_ALREADY_LOGGED_IN
:
202 return (gettext("user already logged in"));
203 case CKR_USER_NOT_LOGGED_IN
:
204 return (gettext("user not logged in"));
205 case CKR_USER_PIN_NOT_INITIALIZED
:
206 return (gettext("user pin not initialized"));
207 case CKR_USER_TYPE_INVALID
:
208 return (gettext("user type invalid"));
209 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN
:
210 return (gettext("user another already logged in"));
211 case CKR_USER_TOO_MANY_TYPES
:
212 return (gettext("user too many types"));
213 case CKR_WRAPPED_KEY_INVALID
:
214 return (gettext("wrapped key invalid"));
215 case CKR_WRAPPED_KEY_LEN_RANGE
:
216 return (gettext("wrapped key len range"));
217 case CKR_WRAPPING_KEY_HANDLE_INVALID
:
218 return (gettext("wrapping key handle invalid"));
219 case CKR_WRAPPING_KEY_SIZE_RANGE
:
220 return (gettext("wrapping key size range"));
221 case CKR_WRAPPING_KEY_TYPE_INCONSISTENT
:
222 return (gettext("wrapping key type inconsistent"));
223 case CKR_RANDOM_SEED_NOT_SUPPORTED
:
224 return (gettext("random seed not supported"));
225 case CKR_RANDOM_NO_RNG
:
226 return (gettext("random no rng"));
227 case CKR_DOMAIN_PARAMS_INVALID
:
228 return (gettext("domain params invalid"));
229 case CKR_BUFFER_TOO_SMALL
:
230 return (gettext("buffer too small"));
231 case CKR_SAVED_STATE_INVALID
:
232 return (gettext("saved state invalid"));
233 case CKR_INFORMATION_SENSITIVE
:
234 return (gettext("information sensitive"));
235 case CKR_STATE_UNSAVEABLE
:
236 return (gettext("state unsaveable"));
237 case CKR_CRYPTOKI_NOT_INITIALIZED
:
238 return (gettext("cryptoki not initialized"));
239 case CKR_CRYPTOKI_ALREADY_INITIALIZED
:
240 return (gettext("cryptoki already initialized"));
242 return (gettext("mutex bad"));
243 case CKR_MUTEX_NOT_LOCKED
:
244 return (gettext("mutex not locked"));
245 case CKR_FUNCTION_REJECTED
:
246 return (gettext("function rejected"));
248 return (gettext("unknown error"));
253 unsigned char pkinit_1024_dhprime
[128] = {
254 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
255 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
256 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
257 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
258 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
259 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
260 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
261 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
262 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
263 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
264 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
265 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
266 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
267 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
268 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
269 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
272 unsigned char pkinit_2048_dhprime
[2048/8] = {
273 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
274 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
275 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
276 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
277 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
278 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
279 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
280 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
281 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
282 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
283 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
284 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
285 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
286 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
287 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
288 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
289 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
290 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
291 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
292 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
293 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
294 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
295 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
296 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
297 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
298 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
299 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
300 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
301 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
302 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
303 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
304 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
307 unsigned char pkinit_4096_dhprime
[4096/8] = {
308 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
309 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
310 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
311 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
312 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
313 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
314 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
315 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
316 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
317 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
318 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
319 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
320 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
321 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
322 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
323 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
324 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
325 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
326 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
327 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
328 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
329 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
330 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
331 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
332 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
333 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
334 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
335 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
336 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
337 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
338 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
339 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
340 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
341 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
342 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
343 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
344 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
345 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
346 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
347 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
348 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
349 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
350 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
351 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
352 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
353 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
354 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
355 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
356 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
357 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
358 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
359 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
360 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
361 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
362 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
363 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
364 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
365 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
366 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
367 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
368 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
369 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
370 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
371 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
374 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
376 * Many things have changed in OpenSSL 1.1. The code in this file has been
377 * updated to use the v1.1 APIs but some are new and require emulation
378 * for older OpenSSL versions.
381 /* EVP_MD_CTX construct and destructor names have changed */
383 #define EVP_MD_CTX_new EVP_MD_CTX_create
384 #define EVP_MD_CTX_free EVP_MD_CTX_destroy
386 /* ASN1_STRING_data is deprecated */
387 #define ASN1_STRING_get0_data ASN1_STRING_data
389 /* X509_STORE_CTX_trusted_stack is deprecated */
390 #define X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_trusted_stack
392 /* get_rfc2409_prime_1024() has been renamed. */
393 #define BN_get_rfc2409_prime_1024 get_rfc2409_prime_1024
395 #define OBJ_get0_data(o) ((o)->data)
396 #define OBJ_length(o) ((o)->length)
398 /* Some new DH functions that aren't in OpenSSL 1.0.x */
399 #define DH_bits(dh) BN_num_bits((dh)->p);
401 #define DH_set0_pqg(dh, p, q, g) __DH_set0_pqg(dh, p, q, g)
403 __DH_set0_pqg(DH
*dh
, BIGNUM
*p
, BIGNUM
*q
, BIGNUM
*g
)
405 if ((dh
->p
== NULL
&& p
== NULL
) || (dh
->g
== NULL
&& g
== NULL
))
422 dh
->length
= BN_num_bits(q
);
428 #define DH_get0_pqg(dh, p, q, g) __DH_get0_pqg(dh, p, q, g)
430 __DH_get0_pqg(const DH
*dh
, const BIGNUM
**p
, const BIGNUM
**q
,
441 #define DH_set0_key(dh, pub, priv) __DH_set0_key(dh, pub, priv)
443 __DH_set0_key(DH
*dh
, BIGNUM
*pub_key
, BIGNUM
*priv_key
)
445 if (pub_key
!= NULL
) {
446 BN_free(dh
->pub_key
);
447 dh
->pub_key
= pub_key
;
449 if (priv_key
!= NULL
) {
450 BN_free(dh
->priv_key
);
451 dh
->priv_key
= priv_key
;
457 #define DH_get0_key(dh, pub, priv) __DH_get0_key(dh, pub, priv)
459 __DH_get0_key(const DH
*dh
, const BIGNUM
**pub
, const BIGNUM
**priv
)
464 *priv
= dh
->priv_key
;
467 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
470 pkinit_init_plg_crypto(pkinit_plg_crypto_context
*cryptoctx
) {
472 krb5_error_code retval
= ENOMEM
;
473 pkinit_plg_crypto_context ctx
= NULL
;
475 /* initialize openssl routines */
476 /* Solaris Kerberos */
477 retval
= openssl_init();
481 ctx
= (pkinit_plg_crypto_context
)malloc(sizeof(*ctx
));
484 (void) memset(ctx
, 0, sizeof(*ctx
));
486 pkiDebug("%s: initializing openssl crypto context at %p\n",
488 retval
= pkinit_init_pkinit_oids(ctx
);
492 retval
= pkinit_init_dh_params(ctx
);
499 if (retval
&& ctx
!= NULL
)
500 pkinit_fini_plg_crypto(ctx
);
506 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx
)
508 pkiDebug("%s: freeing context at %p\n", __FUNCTION__
, cryptoctx
);
510 if (cryptoctx
== NULL
)
512 pkinit_fini_pkinit_oids(cryptoctx
);
513 pkinit_fini_dh_params(cryptoctx
);
518 pkinit_init_identity_crypto(pkinit_identity_crypto_context
*idctx
)
520 krb5_error_code retval
= ENOMEM
;
521 pkinit_identity_crypto_context ctx
= NULL
;
523 ctx
= (pkinit_identity_crypto_context
)malloc(sizeof(*ctx
));
526 (void) memset(ctx
, 0, sizeof(*ctx
));
528 retval
= pkinit_init_certs(ctx
);
532 retval
= pkinit_init_pkcs11(ctx
);
536 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__
, ctx
);
542 pkinit_fini_identity_crypto(ctx
);
549 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx
)
554 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__
, idctx
);
555 pkinit_fini_certs(idctx
);
556 pkinit_fini_pkcs11(idctx
);
561 pkinit_init_req_crypto(pkinit_req_crypto_context
*cryptoctx
)
564 pkinit_req_crypto_context ctx
= NULL
;
566 /* Solaris Kerberos */
567 if (cryptoctx
== NULL
)
570 ctx
= (pkinit_req_crypto_context
)malloc(sizeof(*ctx
));
573 (void) memset(ctx
, 0, sizeof(*ctx
));
576 ctx
->received_cert
= NULL
;
580 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__
, ctx
);
586 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx
)
588 if (req_cryptoctx
== NULL
)
591 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__
, req_cryptoctx
);
592 if (req_cryptoctx
->dh
!= NULL
)
593 DH_free(req_cryptoctx
->dh
);
594 if (req_cryptoctx
->received_cert
!= NULL
)
595 X509_free(req_cryptoctx
->received_cert
);
600 static krb5_error_code
601 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx
)
603 ctx
->id_pkinit_san
= OBJ_txt2obj("1.3.6.1.5.2.2", 1);
604 if (ctx
->id_pkinit_san
== NULL
)
607 ctx
->id_pkinit_authData
= OBJ_txt2obj("1.3.6.1.5.2.3.1", 1);
608 if (ctx
->id_pkinit_authData
== NULL
)
611 ctx
->id_pkinit_DHKeyData
= OBJ_txt2obj("1.3.6.1.5.2.3.2", 1);
612 if (ctx
->id_pkinit_DHKeyData
== NULL
)
615 ctx
->id_pkinit_rkeyData
= OBJ_txt2obj("1.3.6.1.5.2.3.3", 1);
616 if (ctx
->id_pkinit_rkeyData
== NULL
)
619 ctx
->id_pkinit_KPClientAuth
= OBJ_txt2obj("1.3.6.1.5.2.3.4", 1);
620 if (ctx
->id_pkinit_KPClientAuth
== NULL
)
623 ctx
->id_pkinit_KPKdc
= OBJ_txt2obj("1.3.6.1.5.2.3.5", 1);
624 if (ctx
->id_pkinit_KPKdc
== NULL
)
627 ctx
->id_ms_kp_sc_logon
= OBJ_txt2obj("1.3.6.1.4.1.311.20.2.2", 1);
628 if (ctx
->id_ms_kp_sc_logon
== NULL
)
631 ctx
->id_ms_san_upn
= OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1);
632 if (ctx
->id_ms_san_upn
== NULL
)
635 ctx
->id_kp_serverAuth
= OBJ_txt2obj("1.3.6.1.5.5.7.3.1", 1);
636 if (ctx
->id_kp_serverAuth
== NULL
)
642 static krb5_error_code
643 get_cert(char *filename
, X509
**retcert
)
648 krb5_error_code retval
;
650 if (filename
== NULL
|| retcert
== NULL
)
655 tmp
= BIO_new(BIO_s_file());
659 code
= BIO_read_filename(tmp
, filename
);
665 cert
= (X509
*) PEM_read_bio_X509(tmp
, NULL
, NULL
, NULL
);
668 pkiDebug("failed to read certificate from %s\n", filename
);
679 static krb5_error_code
680 get_key(char *filename
, EVP_PKEY
**retkey
)
682 EVP_PKEY
*pkey
= NULL
;
685 krb5_error_code retval
;
687 if (filename
== NULL
|| retkey
== NULL
)
690 tmp
= BIO_new(BIO_s_file());
694 code
= BIO_read_filename(tmp
, filename
);
699 pkey
= (EVP_PKEY
*) PEM_read_bio_PrivateKey(tmp
, NULL
, NULL
, NULL
);
702 pkiDebug("failed to read private key from %s\n", filename
);
714 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx
)
718 ASN1_OBJECT_free(ctx
->id_pkinit_san
);
719 ASN1_OBJECT_free(ctx
->id_pkinit_authData
);
720 ASN1_OBJECT_free(ctx
->id_pkinit_DHKeyData
);
721 ASN1_OBJECT_free(ctx
->id_pkinit_rkeyData
);
722 ASN1_OBJECT_free(ctx
->id_pkinit_KPClientAuth
);
723 ASN1_OBJECT_free(ctx
->id_pkinit_KPKdc
);
724 ASN1_OBJECT_free(ctx
->id_ms_kp_sc_logon
);
725 ASN1_OBJECT_free(ctx
->id_ms_san_upn
);
726 ASN1_OBJECT_free(ctx
->id_kp_serverAuth
);
730 make_dhprime(uint8_t *prime
, size_t len
)
733 BIGNUM
*p
= NULL
, *q
= NULL
, *g
= NULL
;
735 if ((p
= BN_bin2bn(prime
, len
, NULL
)) == NULL
)
737 if ((q
= BN_new()) == NULL
)
739 if (!BN_rshift1(q
, p
))
741 if ((g
= BN_new()) == NULL
)
743 if (!BN_set_word(g
, DH_GENERATOR_2
))
749 DH_set0_pqg(dh
, p
, q
, g
);
759 static krb5_error_code
760 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx
)
762 krb5_error_code retval
= ENOMEM
;
764 plgctx
->dh_1024
= make_dhprime(pkinit_1024_dhprime
,
765 sizeof(pkinit_1024_dhprime
));
766 if (plgctx
->dh_1024
== NULL
)
769 plgctx
->dh_2048
= make_dhprime(pkinit_2048_dhprime
,
770 sizeof(pkinit_2048_dhprime
));
771 if (plgctx
->dh_2048
== NULL
)
774 plgctx
->dh_4096
= make_dhprime(pkinit_4096_dhprime
,
775 sizeof(pkinit_4096_dhprime
));
776 if (plgctx
->dh_4096
== NULL
)
783 pkinit_fini_dh_params(plgctx
);
789 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx
)
791 if (plgctx
->dh_1024
!= NULL
)
792 DH_free(plgctx
->dh_1024
);
793 if (plgctx
->dh_2048
!= NULL
)
794 DH_free(plgctx
->dh_2048
);
795 if (plgctx
->dh_4096
!= NULL
)
796 DH_free(plgctx
->dh_4096
);
798 plgctx
->dh_1024
= plgctx
->dh_2048
= plgctx
->dh_4096
= NULL
;
801 static krb5_error_code
802 pkinit_init_certs(pkinit_identity_crypto_context ctx
)
804 /* Solaris Kerberos */
807 for (i
= 0; i
< MAX_CREDS_ALLOWED
; i
++)
808 ctx
->creds
[i
] = NULL
;
809 ctx
->my_certs
= NULL
;
812 ctx
->trustedCAs
= NULL
;
813 ctx
->intermediateCAs
= NULL
;
820 pkinit_fini_certs(pkinit_identity_crypto_context ctx
)
825 if (ctx
->my_certs
!= NULL
)
826 sk_X509_pop_free(ctx
->my_certs
, X509_free
);
828 if (ctx
->my_key
!= NULL
)
829 EVP_PKEY_free(ctx
->my_key
);
831 if (ctx
->trustedCAs
!= NULL
)
832 sk_X509_pop_free(ctx
->trustedCAs
, X509_free
);
834 if (ctx
->intermediateCAs
!= NULL
)
835 sk_X509_pop_free(ctx
->intermediateCAs
, X509_free
);
837 if (ctx
->revoked
!= NULL
)
838 sk_X509_CRL_pop_free(ctx
->revoked
, X509_CRL_free
);
841 static krb5_error_code
842 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx
)
844 /* Solaris Kerberos */
846 #ifndef WITHOUT_PKCS11
847 ctx
->p11_module_name
= strdup(PKCS11_MODNAME
);
848 if (ctx
->p11_module_name
== NULL
)
850 ctx
->p11_module
= NULL
;
851 ctx
->slotid
= PK_NOSLOT
;
852 ctx
->token_label
= NULL
;
853 ctx
->cert_label
= NULL
;
855 ctx
->session
= CK_INVALID_HANDLE
;
857 ctx
->p11flags
= 0; /* Solaris Kerberos */
859 ctx
->pkcs11_method
= 0;
860 (void) memset(ctx
->creds
, 0, sizeof(ctx
->creds
));
866 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx
)
868 #ifndef WITHOUT_PKCS11
872 if (ctx
->p11
!= NULL
) {
873 if (ctx
->session
!= CK_INVALID_HANDLE
) {
874 ctx
->p11
->C_CloseSession(ctx
->session
);
875 ctx
->session
= CK_INVALID_HANDLE
;
879 * Only call C_Finalize if the process was not already using pkcs11.
881 if (ctx
->finalize_pkcs11
== TRUE
)
882 ctx
->p11
->C_Finalize(NULL_PTR
);
886 if (ctx
->p11_module
!= NULL
) {
887 pkinit_C_UnloadModule(ctx
->p11_module
);
888 ctx
->p11_module
= NULL
;
890 if (ctx
->p11_module_name
!= NULL
)
891 free(ctx
->p11_module_name
);
892 if (ctx
->token_label
!= NULL
)
893 free(ctx
->token_label
);
894 if (ctx
->cert_id
!= NULL
)
896 if (ctx
->cert_label
!= NULL
)
897 free(ctx
->cert_label
);
898 if (ctx
->PIN
!= NULL
) {
899 (void) memset(ctx
->PIN
, 0, strlen(ctx
->PIN
));
906 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx
,
907 krb5_prompter_fct prompter
,
910 id_cryptoctx
->prompter
= prompter
;
911 id_cryptoctx
->prompter_data
= prompter_data
;
916 /* Create a CMS ContentInfo of type oid containing the octet string in data. */
917 static krb5_error_code
918 create_contentinfo(krb5_context context
,
925 ASN1_OCTET_STRING
*ostr
= NULL
;
929 ostr
= ASN1_OCTET_STRING_new();
932 if (!ASN1_OCTET_STRING_set(ostr
, (unsigned char *)data
, data_len
))
938 p7
->type
= OBJ_dup(oid
);
939 if (p7
->type
== NULL
)
942 if (OBJ_obj2nid(oid
) == NID_pkcs7_data
) {
943 /* Draft 9 uses id-pkcs7-data for signed data. For this type OpenSSL
944 * expects an octet string in d.data. */
947 p7
->d
.other
= ASN1_TYPE_new();
948 if (p7
->d
.other
== NULL
)
950 p7
->d
.other
->type
= V_ASN1_OCTET_STRING
;
951 p7
->d
.other
->value
.octet_string
= ostr
;
959 ASN1_OCTET_STRING_free(ostr
);
967 cms_signeddata_create(krb5_context context
,
968 pkinit_plg_crypto_context plg_cryptoctx
,
969 pkinit_req_crypto_context req_cryptoctx
,
970 pkinit_identity_crypto_context id_cryptoctx
,
972 int include_certchain
,
974 unsigned int data_len
,
975 unsigned char **signed_data
,
976 unsigned int *signed_data_len
)
978 /* Solaris Kerberos */
979 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
980 PKCS7
*p7
= NULL
, *inner_p7
= NULL
;
981 PKCS7_SIGNED
*p7s
= NULL
;
982 PKCS7_SIGNER_INFO
*p7si
= NULL
;
984 STACK_OF(X509
) * cert_stack
= NULL
;
985 ASN1_OCTET_STRING
*digest_attr
= NULL
;
986 EVP_MD_CTX
*ctx
= NULL
, *ctx2
= NULL
;
987 const EVP_MD
*md_tmp
= NULL
;
988 unsigned char md_data
[EVP_MAX_MD_SIZE
], md_data2
[EVP_MAX_MD_SIZE
];
989 unsigned char *digestInfo_buf
= NULL
, *abuf
= NULL
;
990 unsigned int md_len
, md_len2
, alen
, digestInfo_len
;
991 STACK_OF(X509_ATTRIBUTE
) * sk
;
992 unsigned char *sig
= NULL
;
993 unsigned int sig_len
= 0;
994 X509_ALGOR
*alg
= NULL
;
995 ASN1_OCTET_STRING
*digest
= NULL
;
996 unsigned int alg_len
= 0, digest_len
= 0;
997 unsigned char *y
= NULL
, *alg_buf
= NULL
, *digest_buf
= NULL
;
999 ASN1_OBJECT
*oid
= NULL
, *oid_copy
;
1001 /* Solaris Kerberos */
1002 if (signed_data
== NULL
)
1005 if (signed_data_len
== NULL
)
1008 /* start creating PKCS7 data */
1009 if ((p7
= PKCS7_new()) == NULL
)
1011 p7
->type
= OBJ_nid2obj(NID_pkcs7_signed
);
1013 if ((p7s
= PKCS7_SIGNED_new()) == NULL
)
1016 if (!ASN1_INTEGER_set(p7s
->version
, 3))
1019 /* create a cert chain that has at least the signer's certificate */
1020 if ((cert_stack
= sk_X509_new_null()) == NULL
)
1023 cert
= sk_X509_value(id_cryptoctx
->my_certs
, id_cryptoctx
->cert_index
);
1024 if (!include_certchain
) {
1025 pkiDebug("only including signer's certificate\n");
1026 sk_X509_push(cert_stack
, X509_dup(cert
));
1028 /* create a cert chain */
1029 X509_STORE
*certstore
= NULL
;
1030 X509_STORE_CTX
*certctx
;
1031 STACK_OF(X509
) *certstack
= NULL
;
1032 char buf
[DN_BUF_LEN
];
1033 int i
= 0, size
= 0;
1035 if ((certstore
= X509_STORE_new()) == NULL
)
1037 if ((certctx
= X509_STORE_CTX_new()) == NULL
)
1039 pkiDebug("building certificate chain\n");
1040 X509_STORE_set_verify_cb(certstore
, openssl_callback
);
1041 X509_STORE_CTX_init(certctx
, certstore
, cert
,
1042 id_cryptoctx
->intermediateCAs
);
1043 X509_STORE_CTX_set0_trusted_stack(certctx
, id_cryptoctx
->trustedCAs
);
1044 /* Solaris Kerberos */
1045 if (X509_verify_cert(certctx
) <= 0) {
1046 pkiDebug("failed to create a certificate chain: %s\n",
1047 X509_verify_cert_error_string(X509_STORE_CTX_get_error(certctx
)));
1048 if (!sk_X509_num(id_cryptoctx
->trustedCAs
))
1049 pkiDebug("No trusted CAs found. Check your X509_anchors\n");
1052 certstack
= X509_STORE_CTX_get1_chain(certctx
);
1053 size
= sk_X509_num(certstack
);
1054 pkiDebug("size of certificate chain = %d\n", size
);
1055 for(i
= 0; i
< size
- 1; i
++) {
1056 X509
*x
= sk_X509_value(certstack
, i
);
1057 X509_NAME_oneline(X509_get_subject_name(x
), buf
, sizeof(buf
));
1058 pkiDebug("cert #%d: %s\n", i
, buf
);
1059 sk_X509_push(cert_stack
, X509_dup(x
));
1061 X509_STORE_CTX_free(certctx
);
1062 X509_STORE_free(certstore
);
1063 sk_X509_pop_free(certstack
, X509_free
);
1065 p7s
->cert
= cert_stack
;
1067 /* fill-in PKCS7_SIGNER_INFO */
1068 if ((p7si
= PKCS7_SIGNER_INFO_new()) == NULL
)
1070 if (!ASN1_INTEGER_set(p7si
->version
, 1))
1072 if (!X509_NAME_set(&p7si
->issuer_and_serial
->issuer
,
1073 X509_get_issuer_name(cert
)))
1075 /* because ASN1_INTEGER_set is used to set a 'long' we will do
1076 * things the ugly way. */
1077 ASN1_INTEGER_free(p7si
->issuer_and_serial
->serial
);
1078 if (!(p7si
->issuer_and_serial
->serial
=
1079 ASN1_INTEGER_dup(X509_get_serialNumber(cert
))))
1082 /* will not fill-out EVP_PKEY because it's on the smartcard */
1084 /* Set digest algs */
1085 p7si
->digest_alg
->algorithm
= OBJ_nid2obj(NID_sha1
);
1087 if (p7si
->digest_alg
->parameter
!= NULL
)
1088 ASN1_TYPE_free(p7si
->digest_alg
->parameter
);
1089 if ((p7si
->digest_alg
->parameter
= ASN1_TYPE_new()) == NULL
)
1091 p7si
->digest_alg
->parameter
->type
= V_ASN1_NULL
;
1094 if (p7si
->digest_enc_alg
->parameter
!= NULL
)
1095 ASN1_TYPE_free(p7si
->digest_enc_alg
->parameter
);
1096 p7si
->digest_enc_alg
->algorithm
= OBJ_nid2obj(NID_sha1WithRSAEncryption
);
1097 if (!(p7si
->digest_enc_alg
->parameter
= ASN1_TYPE_new()))
1099 p7si
->digest_enc_alg
->parameter
->type
= V_ASN1_NULL
;
1101 /* pick the correct oid for the eContentInfo */
1102 oid
= pkinit_pkcs7type2oid(plg_cryptoctx
, cms_msg_type
);
1106 if (cms_msg_type
== CMS_SIGN_DRAFT9
) {
1107 /* don't include signed attributes for pa-type 15 request */
1111 /* add signed attributes */
1112 /* compute sha1 digest over the EncapsulatedContentInfo */
1113 ctx
= EVP_MD_CTX_new();
1116 EVP_MD_CTX_init(ctx
);
1117 EVP_DigestInit_ex(ctx
, EVP_sha1(), NULL
);
1118 EVP_DigestUpdate(ctx
, data
, data_len
);
1119 md_tmp
= EVP_MD_CTX_md(ctx
);
1120 EVP_DigestFinal_ex(ctx
, md_data
, &md_len
);
1121 EVP_MD_CTX_free(ctx
);
1124 /* create a message digest attr */
1125 digest_attr
= ASN1_OCTET_STRING_new();
1126 ASN1_OCTET_STRING_set(digest_attr
, md_data
, (int)md_len
);
1127 PKCS7_add_signed_attribute(p7si
, NID_pkcs9_messageDigest
,
1128 V_ASN1_OCTET_STRING
, (char *) digest_attr
);
1130 /* create a content-type attr */
1131 oid_copy
= OBJ_dup(oid
);
1132 if (oid_copy
== NULL
)
1134 PKCS7_add_signed_attribute(p7si
, NID_pkcs9_contentType
,
1135 V_ASN1_OBJECT
, oid_copy
);
1137 /* create the signature over signed attributes. get DER encoded value */
1138 /* This is the place where smartcard signature needs to be calculated */
1139 sk
= p7si
->auth_attr
;
1140 alen
= ASN1_item_i2d((ASN1_VALUE
*) sk
, &abuf
,
1141 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN
));
1146 #ifndef WITHOUT_PKCS11
1147 /* Some tokens can only do RSAEncryption without sha1 hash */
1148 /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
1149 * function and the hash value into an ASN.1 value of type DigestInfo
1150 * DigestInfo::=SEQUENCE {
1151 * digestAlgorithm AlgorithmIdentifier,
1152 * digest OCTET STRING }
1154 if (id_cryptoctx
->pkcs11_method
== 1 &&
1155 id_cryptoctx
->mech
== CKM_RSA_PKCS
) {
1156 pkiDebug("mech = CKM_RSA_PKCS\n");
1157 ctx2
= EVP_MD_CTX_new();
1160 EVP_MD_CTX_init(ctx2
);
1161 /* if this is not draft9 request, include digest signed attribute */
1162 if (cms_msg_type
!= CMS_SIGN_DRAFT9
)
1163 EVP_DigestInit_ex(ctx2
, md_tmp
, NULL
);
1165 EVP_DigestInit_ex(ctx2
, EVP_sha1(), NULL
);
1166 EVP_DigestUpdate(ctx2
, abuf
, alen
);
1167 EVP_DigestFinal_ex(ctx2
, md_data2
, &md_len2
);
1168 EVP_MD_CTX_free(ctx2
);
1171 alg
= X509_ALGOR_new();
1174 alg
->algorithm
= OBJ_nid2obj(NID_sha1
);
1175 alg
->parameter
= NULL
;
1176 alg_len
= i2d_X509_ALGOR(alg
, NULL
);
1177 alg_buf
= (unsigned char *)malloc(alg_len
);
1178 if (alg_buf
== NULL
)
1181 digest
= ASN1_OCTET_STRING_new();
1184 ASN1_OCTET_STRING_set(digest
, md_data2
, (int)md_len2
);
1185 digest_len
= i2d_ASN1_OCTET_STRING(digest
, NULL
);
1186 digest_buf
= (unsigned char *)malloc(digest_len
);
1187 if (digest_buf
== NULL
)
1190 digestInfo_len
= ASN1_object_size(1, (int)(alg_len
+ digest_len
),
1192 y
= digestInfo_buf
= (unsigned char *)malloc(digestInfo_len
);
1193 if (digestInfo_buf
== NULL
)
1195 ASN1_put_object(&y
, 1, (int)(alg_len
+ digest_len
), V_ASN1_SEQUENCE
,
1197 i2d_X509_ALGOR(alg
, &y
);
1198 i2d_ASN1_OCTET_STRING(digest
, &y
);
1200 pkiDebug("signing buffer\n");
1201 print_buffer(digestInfo_buf
, digestInfo_len
);
1202 print_buffer_bin(digestInfo_buf
, digestInfo_len
, "/tmp/pkcs7_tosign");
1204 retval
= pkinit_sign_data(context
, id_cryptoctx
, digestInfo_buf
,
1205 digestInfo_len
, &sig
, &sig_len
);
1209 pkiDebug("mech = %s\n",
1210 id_cryptoctx
->pkcs11_method
== 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
1211 retval
= pkinit_sign_data(context
, id_cryptoctx
, abuf
, alen
,
1215 print_buffer(sig
, sig_len
);
1217 if (cms_msg_type
!= CMS_SIGN_DRAFT9
)
1223 if (!ASN1_STRING_set(p7si
->enc_digest
, (unsigned char *) sig
,
1225 unsigned long err
= ERR_peek_error();
1226 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1227 krb5_set_error_message(context
, retval
, "%s\n",
1228 ERR_error_string(err
, NULL
));
1229 pkiDebug("failed to add a signed digest attribute\n");
1232 /* adder signer_info to pkcs7 signed */
1233 if (!PKCS7_add_signer(p7
, p7si
))
1236 /* start on adding data to the pkcs7 signed */
1237 retval
= create_contentinfo(context
, oid
, data
, data_len
, &inner_p7
);
1238 if (p7s
->contents
!= NULL
)
1239 PKCS7_free(p7s
->contents
);
1240 p7s
->contents
= inner_p7
;
1242 *signed_data_len
= i2d_PKCS7(p7
, NULL
);
1243 if (!(*signed_data_len
)) {
1244 unsigned long err
= ERR_peek_error();
1245 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1246 krb5_set_error_message(context
, retval
, "%s\n",
1247 ERR_error_string(err
, NULL
));
1248 pkiDebug("failed to der encode pkcs7\n");
1251 if ((p
= *signed_data
=
1252 (unsigned char *) malloc((size_t)*signed_data_len
)) == NULL
)
1255 /* DER encode PKCS7 data */
1256 retval
= i2d_PKCS7(p7
, &p
);
1258 unsigned long err
= ERR_peek_error();
1259 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1260 krb5_set_error_message(context
, retval
, "%s\n",
1261 ERR_error_string(err
, NULL
));
1262 pkiDebug("failed to der encode pkcs7\n");
1268 if (cms_msg_type
== CMS_SIGN_CLIENT
) {
1269 print_buffer_bin(*signed_data
, *signed_data_len
,
1270 "/tmp/client_pkcs7_signeddata");
1272 if (cms_msg_type
== CMS_SIGN_SERVER
) {
1273 print_buffer_bin(*signed_data
, *signed_data_len
,
1274 "/tmp/kdc_pkcs7_signeddata");
1276 print_buffer_bin(*signed_data
, *signed_data_len
,
1277 "/tmp/draft9_pkcs7_signeddata");
1283 if (cms_msg_type
!= CMS_SIGN_DRAFT9
)
1285 EVP_MD_CTX_free(ctx
);
1286 #ifndef WITHOUT_PKCS11
1287 if (id_cryptoctx
->pkcs11_method
== 1 &&
1288 id_cryptoctx
->mech
== CKM_RSA_PKCS
) {
1290 EVP_MD_CTX_free(ctx2
);
1291 if (digest_buf
!= NULL
)
1293 if (digestInfo_buf
!= NULL
)
1294 free(digestInfo_buf
);
1295 if (alg_buf
!= NULL
)
1298 ASN1_OCTET_STRING_free(digest
);
1302 X509_ALGOR_free(alg
);
1313 cms_signeddata_verify(krb5_context context
,
1314 pkinit_plg_crypto_context plgctx
,
1315 pkinit_req_crypto_context reqctx
,
1316 pkinit_identity_crypto_context idctx
,
1318 int require_crl_checking
,
1319 unsigned char *signed_data
,
1320 unsigned int signed_data_len
,
1321 unsigned char **data
,
1322 unsigned int *data_len
,
1323 unsigned char **authz_data
,
1324 unsigned int *authz_data_len
)
1326 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1329 int flags
= PKCS7_NOVERIFY
, i
= 0;
1330 unsigned int vflags
= 0, size
= 0;
1331 const unsigned char *p
= signed_data
;
1332 STACK_OF(PKCS7_SIGNER_INFO
) *si_sk
= NULL
;
1333 PKCS7_SIGNER_INFO
*si
= NULL
;
1335 X509_STORE
*store
= NULL
;
1336 X509_STORE_CTX
*cert_ctx
;
1337 STACK_OF(X509
) *intermediateCAs
= NULL
;
1338 STACK_OF(X509_CRL
) *revoked
= NULL
;
1339 STACK_OF(X509
) *verified_chain
= NULL
;
1340 ASN1_OBJECT
*oid
= NULL
;
1341 krb5_external_principal_identifier
**krb5_verified_chain
= NULL
;
1342 krb5_data
*authz
= NULL
;
1343 char buf
[DN_BUF_LEN
];
1346 print_buffer_bin(signed_data
, signed_data_len
,
1347 "/tmp/client_received_pkcs7_signeddata");
1350 oid
= pkinit_pkcs7type2oid(plgctx
, cms_msg_type
);
1354 /* decode received PKCS7 message */
1355 if ((p7
= d2i_PKCS7(NULL
, &p
, (int)signed_data_len
)) == NULL
) {
1356 unsigned long err
= ERR_peek_error();
1357 krb5_set_error_message(context
, retval
, "%s\n",
1358 ERR_error_string(err
, NULL
));
1359 pkiDebug("%s: failed to decode message: %s\n",
1360 __FUNCTION__
, ERR_error_string(err
, NULL
));
1364 /* verify that the received message is PKCS7 SignedData message */
1365 if (OBJ_obj2nid(p7
->type
) != NID_pkcs7_signed
) {
1366 pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
1367 OBJ_obj2nid(p7
->type
));
1368 krb5_set_error_message(context
, retval
, "wrong oid\n");
1372 /* setup to verify X509 certificate used to sign PKCS7 message */
1373 if (!(store
= X509_STORE_new()))
1376 /* check if we are inforcing CRL checking */
1377 vflags
= X509_V_FLAG_CRL_CHECK
|X509_V_FLAG_CRL_CHECK_ALL
;
1378 if (require_crl_checking
)
1379 X509_STORE_set_verify_cb(store
, openssl_callback
);
1381 X509_STORE_set_verify_cb(store
, openssl_callback_ignore_crls
);
1382 X509_STORE_set_flags(store
, vflags
);
1384 /* get the signer's information from the PKCS7 message */
1385 if ((si_sk
= PKCS7_get_signer_info(p7
)) == NULL
)
1387 if ((si
= sk_PKCS7_SIGNER_INFO_value(si_sk
, 0)) == NULL
)
1389 if ((x
= PKCS7_cert_from_signer_info(p7
, si
)) == NULL
)
1392 /* create available CRL information (get local CRLs and include CRLs
1393 * received in the PKCS7 message
1395 if (idctx
->revoked
== NULL
)
1396 revoked
= p7
->d
.sign
->crl
;
1397 else if (p7
->d
.sign
->crl
== NULL
)
1398 revoked
= idctx
->revoked
;
1400 size
= sk_X509_CRL_num(idctx
->revoked
);
1401 revoked
= sk_X509_CRL_new_null();
1402 for (i
= 0; i
< size
; i
++)
1403 sk_X509_CRL_push(revoked
, sk_X509_CRL_value(idctx
->revoked
, i
));
1404 size
= sk_X509_CRL_num(p7
->d
.sign
->crl
);
1405 for (i
= 0; i
< size
; i
++)
1406 sk_X509_CRL_push(revoked
, sk_X509_CRL_value(p7
->d
.sign
->crl
, i
));
1409 /* create available intermediate CAs chains (get local intermediateCAs and
1410 * include the CA chain received in the PKCS7 message
1412 if (idctx
->intermediateCAs
== NULL
)
1413 intermediateCAs
= p7
->d
.sign
->cert
;
1414 else if (p7
->d
.sign
->cert
== NULL
)
1415 intermediateCAs
= idctx
->intermediateCAs
;
1417 size
= sk_X509_num(idctx
->intermediateCAs
);
1418 intermediateCAs
= sk_X509_new_null();
1419 for (i
= 0; i
< size
; i
++) {
1420 sk_X509_push(intermediateCAs
,
1421 sk_X509_value(idctx
->intermediateCAs
, i
));
1423 size
= sk_X509_num(p7
->d
.sign
->cert
);
1424 for (i
= 0; i
< size
; i
++) {
1425 sk_X509_push(intermediateCAs
, sk_X509_value(p7
->d
.sign
->cert
, i
));
1429 /* initialize x509 context with the received certificate and
1430 * trusted and intermediate CA chains and CRLs
1432 if ((cert_ctx
= X509_STORE_CTX_new()) == NULL
)
1434 if (!X509_STORE_CTX_init(cert_ctx
, store
, x
, intermediateCAs
))
1437 X509_STORE_CTX_set0_crls(cert_ctx
, revoked
);
1439 /* add trusted CAs certificates for cert verification */
1440 if (idctx
->trustedCAs
!= NULL
)
1441 X509_STORE_CTX_set0_trusted_stack(cert_ctx
, idctx
->trustedCAs
);
1443 pkiDebug("unable to find any trusted CAs\n");
1446 #ifdef DEBUG_CERTCHAIN
1447 if (intermediateCAs
!= NULL
) {
1448 size
= sk_X509_num(intermediateCAs
);
1449 pkiDebug("untrusted cert chain of size %d\n", size
);
1450 for (i
= 0; i
< size
; i
++) {
1451 X509_NAME_oneline(X509_get_subject_name(
1452 sk_X509_value(intermediateCAs
, i
)), buf
, sizeof(buf
));
1453 pkiDebug("cert #%d: %s\n", i
, buf
);
1456 if (idctx
->trustedCAs
!= NULL
) {
1457 size
= sk_X509_num(idctx
->trustedCAs
);
1458 pkiDebug("trusted cert chain of size %d\n", size
);
1459 for (i
= 0; i
< size
; i
++) {
1460 X509_NAME_oneline(X509_get_subject_name(
1461 sk_X509_value(idctx
->trustedCAs
, i
)), buf
, sizeof(buf
));
1462 pkiDebug("cert #%d: %s\n", i
, buf
);
1465 if (revoked
!= NULL
) {
1466 size
= sk_X509_CRL_num(revoked
);
1467 pkiDebug("CRL chain of size %d\n", size
);
1468 for (i
= 0; i
< size
; i
++) {
1469 X509_CRL
*crl
= sk_X509_CRL_value(revoked
, i
);
1470 X509_NAME_oneline(X509_CRL_get_issuer(crl
), buf
, sizeof(buf
));
1471 pkiDebug("crls by CA #%d: %s\n", i
, buf
);
1476 i
= X509_verify_cert(cert_ctx
);
1478 int j
= X509_STORE_CTX_get_error(cert_ctx
);
1480 reqctx
->received_cert
= X509_dup(
1481 X509_STORE_CTX_get_current_cert(cert_ctx
));
1483 case X509_V_ERR_CERT_REVOKED
:
1484 retval
= KRB5KDC_ERR_REVOKED_CERTIFICATE
;
1486 case X509_V_ERR_UNABLE_TO_GET_CRL
:
1487 retval
= KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN
;
1489 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
:
1490 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
1491 retval
= KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE
;
1494 retval
= KRB5KDC_ERR_INVALID_CERTIFICATE
;
1496 X509_NAME_oneline(X509_get_subject_name(
1497 reqctx
->received_cert
), buf
, sizeof(buf
));
1498 pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf
, j
,
1499 X509_verify_cert_error_string(j
));
1500 krb5_set_error_message(context
, retval
, "%s\n",
1501 X509_verify_cert_error_string(j
));
1502 #ifdef DEBUG_CERTCHAIN
1503 size
= sk_X509_num(p7
->d
.sign
->cert
);
1504 pkiDebug("received cert chain of size %d\n", size
);
1505 for (j
= 0; j
< size
; j
++) {
1506 X509
*tmp_cert
= sk_X509_value(p7
->d
.sign
->cert
, j
);
1507 X509_NAME_oneline(X509_get_subject_name(tmp_cert
), buf
, sizeof(buf
));
1508 pkiDebug("cert #%d: %s\n", j
, buf
);
1512 /* retrieve verified certificate chain */
1513 if (cms_msg_type
== CMS_SIGN_CLIENT
|| cms_msg_type
== CMS_SIGN_DRAFT9
)
1514 verified_chain
= X509_STORE_CTX_get1_chain(cert_ctx
);
1516 X509_STORE_CTX_free(cert_ctx
);
1520 out
= BIO_new(BIO_s_mem());
1521 if (cms_msg_type
== CMS_SIGN_DRAFT9
)
1522 flags
|= PKCS7_NOATTR
;
1523 if (PKCS7_verify(p7
, NULL
, store
, NULL
, out
, flags
)) {
1526 if (!OBJ_cmp(p7
->d
.sign
->contents
->type
, oid
))
1528 else if (cms_msg_type
== CMS_SIGN_DRAFT9
) {
1530 * Various implementations of the pa-type 15 request use
1531 * different OIDS. We check that the returned object
1532 * has any of the acceptable OIDs
1534 ASN1_OBJECT
*client_oid
= NULL
, *server_oid
= NULL
, *rsa_oid
= NULL
;
1535 client_oid
= pkinit_pkcs7type2oid(plgctx
, CMS_SIGN_CLIENT
);
1536 server_oid
= pkinit_pkcs7type2oid(plgctx
, CMS_SIGN_SERVER
);
1537 rsa_oid
= pkinit_pkcs7type2oid(plgctx
, CMS_ENVEL_SERVER
);
1538 if (!OBJ_cmp(p7
->d
.sign
->contents
->type
, client_oid
) ||
1539 !OBJ_cmp(p7
->d
.sign
->contents
->type
, server_oid
) ||
1540 !OBJ_cmp(p7
->d
.sign
->contents
->type
, rsa_oid
))
1545 pkiDebug("PKCS7 Verification successful\n");
1547 const ASN1_OBJECT
*etype
= p7
->d
.sign
->contents
->type
;
1548 pkiDebug("wrong oid in eContentType\n");
1549 print_buffer((unsigned char *)OBJ_get0_data(etype
),
1551 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1552 krb5_set_error_message(context
, retval
, "wrong oid\n");
1557 unsigned long err
= ERR_peek_error();
1558 switch(ERR_GET_REASON(err
)) {
1559 case PKCS7_R_DIGEST_FAILURE
:
1560 retval
= KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED
;
1562 case PKCS7_R_SIGNATURE_FAILURE
:
1564 retval
= KRB5KDC_ERR_INVALID_SIG
;
1566 pkiDebug("PKCS7 Verification failure\n");
1567 krb5_set_error_message(context
, retval
, "%s\n",
1568 ERR_error_string(err
, NULL
));
1572 /* transfer the data from PKCS7 message into return buffer */
1574 if ((*data
= realloc(*data
, size
+ 1024 * 10)) == NULL
)
1576 i
= BIO_read(out
, &((*data
)[size
]), 1024 * 10);
1584 reqctx
->received_cert
= X509_dup(x
);
1586 /* generate authorization data */
1587 if (cms_msg_type
== CMS_SIGN_CLIENT
|| cms_msg_type
== CMS_SIGN_DRAFT9
) {
1589 if (authz_data
== NULL
|| authz_data_len
== NULL
)
1593 retval
= create_identifiers_from_stack(verified_chain
,
1594 &krb5_verified_chain
);
1596 pkiDebug("create_identifiers_from_stack failed\n");
1600 retval
= k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier
**)krb5_verified_chain
, &authz
);
1602 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
1606 print_buffer_bin((unsigned char *)authz
->data
, authz
->length
,
1607 "/tmp/kdc_ad_initial_verified_cas");
1609 *authz_data
= (unsigned char *)malloc(authz
->length
);
1610 if (*authz_data
== NULL
) {
1614 (void) memcpy(*authz_data
, authz
->data
, authz
->length
);
1615 *authz_data_len
= authz
->length
;
1624 X509_STORE_free(store
);
1626 if (idctx
->intermediateCAs
!= NULL
&& p7
->d
.sign
->cert
)
1627 sk_X509_free(intermediateCAs
);
1628 if (idctx
->revoked
!= NULL
&& p7
->d
.sign
->crl
)
1629 sk_X509_CRL_free(revoked
);
1632 if (verified_chain
!= NULL
)
1633 sk_X509_pop_free(verified_chain
, X509_free
);
1634 if (krb5_verified_chain
!= NULL
)
1635 free_krb5_external_principal_identifier(&krb5_verified_chain
);
1637 krb5_free_data(context
, authz
);
1643 cms_envelopeddata_create(krb5_context context
,
1644 pkinit_plg_crypto_context plgctx
,
1645 pkinit_req_crypto_context reqctx
,
1646 pkinit_identity_crypto_context idctx
,
1647 krb5_preauthtype pa_type
,
1648 int include_certchain
,
1649 unsigned char *key_pack
,
1650 unsigned int key_pack_len
,
1651 unsigned char **out
,
1652 unsigned int *out_len
)
1655 /* Solaris Kerberos */
1656 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
1659 unsigned char *p
= NULL
, *signed_data
= NULL
, *enc_data
= NULL
;
1660 int signed_data_len
= 0, enc_data_len
= 0, flags
= PKCS7_BINARY
;
1661 STACK_OF(X509
) *encerts
= NULL
;
1662 const EVP_CIPHER
*cipher
= NULL
;
1665 /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */
1666 switch ((int)pa_type
) {
1667 case KRB5_PADATA_PK_AS_REQ_OLD
:
1668 case KRB5_PADATA_PK_AS_REP_OLD
:
1669 cms_msg_type
= CMS_SIGN_DRAFT9
;
1671 case KRB5_PADATA_PK_AS_REQ
:
1672 cms_msg_type
= CMS_ENVEL_SERVER
;
1675 /* Solaris Kerberos */
1680 retval
= cms_signeddata_create(context
, plgctx
, reqctx
, idctx
,
1681 cms_msg_type
, include_certchain
, key_pack
, key_pack_len
,
1682 &signed_data
, (unsigned int *)&signed_data_len
);
1684 pkiDebug("failed to create pkcs7 signed data\n");
1688 /* check we have client's certificate */
1689 if (reqctx
->received_cert
== NULL
) {
1690 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1693 encerts
= sk_X509_new_null();
1694 sk_X509_push(encerts
, reqctx
->received_cert
);
1696 cipher
= EVP_des_ede3_cbc();
1697 in
= BIO_new(BIO_s_mem());
1699 case KRB5_PADATA_PK_AS_REQ
:
1700 prepare_enc_data(signed_data
, signed_data_len
, &enc_data
,
1702 retval
= BIO_write(in
, enc_data
, enc_data_len
);
1703 if (retval
!= enc_data_len
) {
1704 pkiDebug("BIO_write only wrote %d\n", retval
);
1708 case KRB5_PADATA_PK_AS_REP_OLD
:
1709 case KRB5_PADATA_PK_AS_REQ_OLD
:
1710 retval
= BIO_write(in
, signed_data
, signed_data_len
);
1711 if (retval
!= signed_data_len
) {
1712 pkiDebug("BIO_write only wrote %d\n", retval
);
1713 /* Solaris Kerberos */
1714 retval
= KRB5KRB_ERR_GENERIC
;
1723 p7
= PKCS7_encrypt(encerts
, in
, cipher
, flags
);
1725 pkiDebug("failed to encrypt PKCS7 object\n");
1730 case KRB5_PADATA_PK_AS_REQ
:
1731 p7
->d
.enveloped
->enc_data
->content_type
=
1732 OBJ_nid2obj(NID_pkcs7_signed
);
1734 case KRB5_PADATA_PK_AS_REP_OLD
:
1735 case KRB5_PADATA_PK_AS_REQ_OLD
:
1736 p7
->d
.enveloped
->enc_data
->content_type
=
1737 OBJ_nid2obj(NID_pkcs7_data
);
1741 *out_len
= i2d_PKCS7(p7
, NULL
);
1742 if (!*out_len
|| (p
= *out
= (unsigned char *)malloc(*out_len
)) == NULL
) {
1746 retval
= i2d_PKCS7(p7
, &p
);
1748 pkiDebug("unable to write pkcs7 object\n");
1754 print_buffer_bin(*out
, *out_len
, "/tmp/kdc_enveloped_data");
1762 if (signed_data
!= NULL
)
1764 if (enc_data
!= NULL
)
1766 if (encerts
!= NULL
)
1767 sk_X509_free(encerts
);
1773 cms_envelopeddata_verify(krb5_context context
,
1774 pkinit_plg_crypto_context plg_cryptoctx
,
1775 pkinit_req_crypto_context req_cryptoctx
,
1776 pkinit_identity_crypto_context id_cryptoctx
,
1777 krb5_preauthtype pa_type
,
1778 int require_crl_checking
,
1779 unsigned char *enveloped_data
,
1780 unsigned int enveloped_data_len
,
1781 unsigned char **data
,
1782 unsigned int *data_len
)
1784 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1788 unsigned int size
= 0;
1789 const unsigned char *p
= enveloped_data
;
1790 unsigned int tmp_buf_len
= 0, tmp_buf2_len
= 0, vfy_buf_len
= 0;
1791 unsigned char *tmp_buf
= NULL
, *tmp_buf2
= NULL
, *vfy_buf
= NULL
;
1795 print_buffer_bin(enveloped_data
, enveloped_data_len
,
1796 "/tmp/client_envelopeddata");
1798 /* decode received PKCS7 message */
1799 if ((p7
= d2i_PKCS7(NULL
, &p
, (int)enveloped_data_len
)) == NULL
) {
1800 unsigned long err
= ERR_peek_error();
1801 pkiDebug("failed to decode pkcs7\n");
1802 krb5_set_error_message(context
, retval
, "%s\n",
1803 ERR_error_string(err
, NULL
));
1807 /* verify that the received message is PKCS7 EnvelopedData message */
1808 if (OBJ_obj2nid(p7
->type
) != NID_pkcs7_enveloped
) {
1809 pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
1810 OBJ_obj2nid(p7
->type
));
1811 krb5_set_error_message(context
, retval
, "wrong oid\n");
1815 /* decrypt received PKCS7 message */
1816 out
= BIO_new(BIO_s_mem());
1817 if (pkcs7_decrypt(context
, id_cryptoctx
, p7
, out
)) {
1818 pkiDebug("PKCS7 decryption successful\n");
1820 unsigned long err
= ERR_peek_error();
1822 krb5_set_error_message(context
, retval
, "%s\n",
1823 ERR_error_string(err
, NULL
));
1824 pkiDebug("PKCS7 decryption failed\n");
1828 /* transfer the decoded PKCS7 SignedData message into a separate buffer */
1830 if ((tmp_buf
= realloc(tmp_buf
, size
+ 1024 * 10)) == NULL
)
1832 i
= BIO_read(out
, &(tmp_buf
[size
]), 1024 * 10);
1841 print_buffer_bin(tmp_buf
, tmp_buf_len
, "/tmp/client_enc_keypack");
1843 /* verify PKCS7 SignedData message */
1845 case KRB5_PADATA_PK_AS_REP
:
1846 msg_type
= CMS_ENVEL_SERVER
;
1849 case KRB5_PADATA_PK_AS_REP_OLD
:
1850 msg_type
= CMS_SIGN_DRAFT9
;
1853 pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__
, pa_type
);
1854 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1858 * If this is the RFC style, wrap the signed data to make
1859 * decoding easier in the verify routine.
1860 * For draft9-compatible, we don't do anything because it
1861 * is already wrapped.
1863 #ifdef LONGHORN_BETA_COMPAT
1865 * The Longhorn server returns the expected RFC-style data, but
1866 * it is missing the sequence tag and length, so it requires
1867 * special processing when wrapping.
1868 * This will hopefully be fixed before the final release and
1869 * this can all be removed.
1871 if (msg_type
== CMS_ENVEL_SERVER
|| longhorn
== 1) {
1872 retval
= wrap_signeddata(tmp_buf
, tmp_buf_len
,
1873 &tmp_buf2
, &tmp_buf2_len
, longhorn
);
1875 pkiDebug("failed to encode signeddata\n");
1879 vfy_buf_len
= tmp_buf2_len
;
1883 vfy_buf_len
= tmp_buf_len
;
1886 if (msg_type
== CMS_ENVEL_SERVER
) {
1887 retval
= wrap_signeddata(tmp_buf
, tmp_buf_len
,
1888 &tmp_buf2
, &tmp_buf2_len
);
1890 pkiDebug("failed to encode signeddata\n");
1894 vfy_buf_len
= tmp_buf2_len
;
1898 vfy_buf_len
= tmp_buf_len
;
1903 print_buffer_bin(vfy_buf
, vfy_buf_len
, "/tmp/client_enc_keypack2");
1906 retval
= cms_signeddata_verify(context
, plg_cryptoctx
, req_cryptoctx
,
1907 id_cryptoctx
, msg_type
,
1908 require_crl_checking
,
1909 vfy_buf
, vfy_buf_len
,
1910 data
, data_len
, NULL
, NULL
);
1913 pkiDebug("PKCS7 Verification Success\n");
1915 pkiDebug("PKCS7 Verification Failure\n");
1927 if (tmp_buf
!= NULL
)
1929 if (tmp_buf2
!= NULL
)
1936 static krb5_error_code
1937 crypto_retrieve_X509_sans(krb5_context context
,
1938 pkinit_plg_crypto_context plgctx
,
1939 pkinit_req_crypto_context reqctx
,
1941 krb5_principal
**princs_ret
,
1942 krb5_principal
**upn_ret
,
1943 unsigned char ***dns_ret
)
1945 krb5_error_code retval
= EINVAL
;
1946 char buf
[DN_BUF_LEN
];
1947 int p
= 0, u
= 0, d
= 0;
1948 krb5_principal
*princs
= NULL
;
1949 krb5_principal
*upns
= NULL
;
1950 unsigned char **dnss
= NULL
;
1951 int i
, num_found
= 0;
1953 if (princs_ret
== NULL
&& upn_ret
== NULL
&& dns_ret
== NULL
) {
1954 pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__
);
1959 pkiDebug("%s: no certificate!\n", __FUNCTION__
);
1963 X509_NAME_oneline(X509_get_subject_name(cert
),
1965 pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__
, buf
);
1967 if ((i
= X509_get_ext_by_NID(cert
, NID_subject_alt_name
, -1)) >= 0) {
1968 X509_EXTENSION
*ext
= NULL
;
1969 GENERAL_NAMES
*ialt
= NULL
;
1970 GENERAL_NAME
*gen
= NULL
;
1972 unsigned int num_sans
= 0;
1974 if (!(ext
= X509_get_ext(cert
, i
)) || !(ialt
= X509V3_EXT_d2i(ext
))) {
1975 pkiDebug("%s: found no subject alt name extensions\n",
1979 num_sans
= sk_GENERAL_NAME_num(ialt
);
1981 pkiDebug("%s: found %d subject alt name extension(s)\n",
1982 __FUNCTION__
, num_sans
);
1984 /* OK, we're likely returning something. Allocate return values */
1985 if (princs_ret
!= NULL
) {
1986 princs
= calloc(num_sans
+ 1, sizeof(krb5_principal
));
1987 if (princs
== NULL
) {
1992 if (upn_ret
!= NULL
) {
1993 upns
= calloc(num_sans
+ 1, sizeof(krb5_principal
));
1999 if (dns_ret
!= NULL
) {
2000 dnss
= calloc(num_sans
+ 1, sizeof(*dnss
));
2007 for (i
= 0; i
< num_sans
; i
++) {
2008 krb5_data name
= { 0, 0, NULL
};
2010 gen
= sk_GENERAL_NAME_value(ialt
, i
);
2011 switch (gen
->type
) {
2013 name
.length
= gen
->d
.otherName
->value
->value
.sequence
->length
;
2014 name
.data
= (char *)gen
->d
.otherName
->value
->value
.sequence
->data
;
2016 && OBJ_cmp(plgctx
->id_pkinit_san
,
2017 gen
->d
.otherName
->type_id
) == 0) {
2019 print_buffer_bin((unsigned char *)name
.data
, name
.length
,
2022 ret
= k5int_decode_krb5_principal_name(&name
, &princs
[p
]);
2024 pkiDebug("%s: failed decoding pkinit san value\n",
2030 } else if (upns
!= NULL
2031 && OBJ_cmp(plgctx
->id_ms_san_upn
,
2032 gen
->d
.otherName
->type_id
) == 0) {
2033 ret
= krb5_parse_name(context
, name
.data
, &upns
[u
]);
2035 pkiDebug("%s: failed parsing ms-upn san value\n",
2042 pkiDebug("%s: unrecognized othername oid in SAN\n",
2050 pkiDebug("%s: found dns name = %s\n",
2051 __FUNCTION__
, gen
->d
.dNSName
->data
);
2052 dnss
[d
] = (unsigned char *)
2053 strdup((char *)gen
->d
.dNSName
->data
);
2054 if (dnss
[d
] == NULL
) {
2055 pkiDebug("%s: failed to duplicate dns name\n",
2064 pkiDebug("%s: SAN type = %d expecting %d\n",
2065 __FUNCTION__
, gen
->type
, GEN_OTHERNAME
);
2068 sk_GENERAL_NAME_pop_free(ialt
, GENERAL_NAME_free
);
2073 *princs_ret
= princs
;
2081 if (princs
!= NULL
) {
2082 for (i
= 0; princs
[i
] != NULL
; i
++)
2083 krb5_free_principal(context
, princs
[i
]);
2087 for (i
= 0; upns
[i
] != NULL
; i
++)
2088 krb5_free_principal(context
, upns
[i
]);
2092 for (i
= 0; dnss
[i
] != NULL
; i
++)
2102 crypto_retrieve_cert_sans(krb5_context context
,
2103 pkinit_plg_crypto_context plgctx
,
2104 pkinit_req_crypto_context reqctx
,
2105 pkinit_identity_crypto_context idctx
,
2106 krb5_principal
**princs_ret
,
2107 krb5_principal
**upn_ret
,
2108 unsigned char ***dns_ret
)
2110 krb5_error_code retval
= EINVAL
;
2112 if (reqctx
->received_cert
== NULL
) {
2113 pkiDebug("%s: No certificate!\n", __FUNCTION__
);
2117 return crypto_retrieve_X509_sans(context
, plgctx
, reqctx
,
2118 reqctx
->received_cert
, princs_ret
,
2124 crypto_check_cert_eku(krb5_context context
,
2125 pkinit_plg_crypto_context plgctx
,
2126 pkinit_req_crypto_context reqctx
,
2127 pkinit_identity_crypto_context idctx
,
2128 int checking_kdc_cert
,
2129 int allow_secondary_usage
,
2132 char buf
[DN_BUF_LEN
];
2134 krb5_error_code retval
= EINVAL
;
2137 /* Solaris Kerberos */
2138 if (valid_eku
== NULL
)
2142 if (reqctx
->received_cert
== NULL
)
2145 X509_NAME_oneline(X509_get_subject_name(reqctx
->received_cert
),
2147 pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__
, buf
);
2149 if ((i
= X509_get_ext_by_NID(reqctx
->received_cert
,
2150 NID_ext_key_usage
, -1)) >= 0) {
2151 EXTENDED_KEY_USAGE
*extusage
;
2153 extusage
= X509_get_ext_d2i(reqctx
->received_cert
, NID_ext_key_usage
,
2156 pkiDebug("%s: found eku info in the cert\n", __FUNCTION__
);
2157 for (i
= 0; found_eku
== 0 && i
< sk_ASN1_OBJECT_num(extusage
); i
++) {
2158 ASN1_OBJECT
*tmp_oid
;
2160 tmp_oid
= sk_ASN1_OBJECT_value(extusage
, i
);
2161 pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
2162 __FUNCTION__
, i
+1, sk_ASN1_OBJECT_num(extusage
),
2163 allow_secondary_usage
);
2164 if (checking_kdc_cert
) {
2165 if ((OBJ_cmp(tmp_oid
, plgctx
->id_pkinit_KPKdc
) == 0)
2166 || (allow_secondary_usage
2167 && OBJ_cmp(tmp_oid
, plgctx
->id_kp_serverAuth
) == 0))
2170 if ((OBJ_cmp(tmp_oid
, plgctx
->id_pkinit_KPClientAuth
) == 0)
2171 || (allow_secondary_usage
2172 && OBJ_cmp(tmp_oid
, plgctx
->id_ms_kp_sc_logon
) == 0))
2177 EXTENDED_KEY_USAGE_free(extusage
);
2180 ASN1_BIT_STRING
*usage
= NULL
;
2181 pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__
);
2183 /* check that digitalSignature KeyUsage is present */
2184 if ((usage
= X509_get_ext_d2i(reqctx
->received_cert
,
2185 NID_key_usage
, NULL
, NULL
))) {
2187 if (!ku_reject(reqctx
->received_cert
,
2188 X509v3_KU_DIGITAL_SIGNATURE
)) {
2189 pkiDebug("%s: found digitalSignature KU\n",
2193 pkiDebug("%s: didn't find digitalSignature KU\n",
2196 ASN1_BIT_STRING_free(usage
);
2201 pkiDebug("%s: returning retval %d, valid_eku %d\n",
2202 __FUNCTION__
, retval
, *valid_eku
);
2207 pkinit_octetstring2key(krb5_context context
,
2210 unsigned int dh_key_len
,
2211 krb5_keyblock
* key_block
)
2213 krb5_error_code retval
;
2214 unsigned char *buf
= NULL
;
2215 unsigned char md
[SHA_DIGEST_LENGTH
];
2216 unsigned char counter
;
2217 size_t keybytes
, keylength
, offset
;
2218 krb5_data random_data
;
2221 if ((buf
= (unsigned char *) malloc(dh_key_len
)) == NULL
) {
2225 (void) memset(buf
, 0, dh_key_len
);
2233 SHA1_Update(&c
, &counter
, 1);
2234 SHA1_Update(&c
, key
, dh_key_len
);
2237 if (dh_key_len
- offset
< sizeof(md
))
2238 (void) memcpy(buf
+ offset
, md
, dh_key_len
- offset
);
2240 (void) memcpy(buf
+ offset
, md
, sizeof(md
));
2242 offset
+= sizeof(md
);
2244 } while (offset
< dh_key_len
);
2246 /* Solaris Kerberos */
2247 key_block
->magic
= KV5M_KEYBLOCK
;
2248 key_block
->enctype
= etype
;
2250 retval
= krb5_c_keylengths(context
, etype
, &keybytes
, &keylength
);
2254 key_block
->length
= keylength
;
2255 key_block
->contents
= calloc(keylength
, sizeof(unsigned char *));
2256 if (key_block
->contents
== NULL
) {
2261 random_data
.length
= keybytes
;
2262 random_data
.data
= (char *)buf
;
2264 retval
= krb5_c_random_to_key(context
, etype
, &random_data
, key_block
);
2269 if (retval
&& key_block
->contents
!= NULL
&& key_block
->length
!= 0) {
2270 (void) memset(key_block
->contents
, 0, key_block
->length
);
2271 key_block
->length
= 0;
2279 client_create_dh(krb5_context context
,
2280 pkinit_plg_crypto_context plg_cryptoctx
,
2281 pkinit_req_crypto_context cryptoctx
,
2282 pkinit_identity_crypto_context id_cryptoctx
,
2284 unsigned char **dh_params
,
2285 unsigned int *dh_params_len
,
2286 unsigned char **dh_pubkey
,
2287 unsigned int *dh_pubkey_len
)
2289 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
2290 unsigned char *buf
= NULL
;
2292 ASN1_INTEGER
*asn_pub_key
= NULL
;
2294 const BIGNUM
*pub_key
;
2296 if (cryptoctx
->dh
== NULL
) {
2297 if ((cryptoctx
->dh
= DH_new()) == NULL
)
2299 if ((g
= BN_new()) == NULL
|| (q
= BN_new()) == NULL
)
2304 pkiDebug("client uses 1024 DH keys\n");
2305 cryptoctx
->dh
= make_dhprime(pkinit_1024_dhprime
,
2306 sizeof(pkinit_1024_dhprime
));
2309 pkiDebug("client uses 2048 DH keys\n");
2310 cryptoctx
->dh
= make_dhprime(pkinit_2048_dhprime
,
2311 sizeof(pkinit_2048_dhprime
));
2314 pkiDebug("client uses 4096 DH keys\n");
2315 cryptoctx
->dh
= make_dhprime(pkinit_4096_dhprime
,
2316 sizeof(pkinit_4096_dhprime
));
2319 if (cryptoctx
->dh
== NULL
)
2323 DH_generate_key(cryptoctx
->dh
);
2324 DH_get0_key(cryptoctx
->dh
, &pub_key
, NULL
);
2326 /* Solaris Kerberos */
2328 DH_check(cryptoctx
->dh
, &dh_err
);
2330 pkiDebug("Warning: dh_check failed with %d\n", dh_err
);
2331 if (dh_err
& DH_CHECK_P_NOT_PRIME
)
2332 pkiDebug("p value is not prime\n");
2333 if (dh_err
& DH_CHECK_P_NOT_SAFE_PRIME
)
2334 pkiDebug("p value is not a safe prime\n");
2335 if (dh_err
& DH_UNABLE_TO_CHECK_GENERATOR
)
2336 pkiDebug("unable to check the generator value\n");
2337 if (dh_err
& DH_NOT_SUITABLE_GENERATOR
)
2338 pkiDebug("the g value is not a generator\n");
2342 print_dh(cryptoctx
->dh
, "client's DH params\n");
2343 print_pubkey(pub_key
, "client's pub_key=");
2346 DH_check_pub_key(cryptoctx
->dh
, pub_key
, &dh_err
);
2348 pkiDebug("dh_check_pub_key failed with %d\n", dh_err
);
2353 /* aglo: usually we could just call i2d_DHparams to encode DH params
2354 * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
2356 DH_get0_pqg(cryptoctx
->dh
, (const BIGNUM
**)&p
, (const BIGNUM
**)&q
,
2357 (const BIGNUM
**)&g
);
2358 retval
= pkinit_encode_dh_params(p
, g
, q
, dh_params
, dh_params_len
);
2362 /* pack DH public key */
2363 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2364 * encoding shall be used as the contents (the value) of the
2365 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2368 if ((asn_pub_key
= BN_to_ASN1_INTEGER(pub_key
, NULL
)) == NULL
)
2370 *dh_pubkey_len
= i2d_ASN1_INTEGER(asn_pub_key
, NULL
);
2371 if ((buf
= *dh_pubkey
= (unsigned char *)
2372 malloc((size_t) *dh_pubkey_len
)) == NULL
) {
2376 i2d_ASN1_INTEGER(asn_pub_key
, &buf
);
2378 if (asn_pub_key
!= NULL
)
2379 ASN1_INTEGER_free(asn_pub_key
);
2385 if (cryptoctx
->dh
!= NULL
)
2386 DH_free(cryptoctx
->dh
);
2387 cryptoctx
->dh
= NULL
;
2388 if (*dh_params
!= NULL
)
2391 if (*dh_pubkey
!= NULL
)
2394 if (asn_pub_key
!= NULL
)
2395 ASN1_INTEGER_free(asn_pub_key
);
2402 client_process_dh(krb5_context context
,
2403 pkinit_plg_crypto_context plg_cryptoctx
,
2404 pkinit_req_crypto_context cryptoctx
,
2405 pkinit_identity_crypto_context id_cryptoctx
,
2406 unsigned char *subjectPublicKey_data
,
2407 unsigned int subjectPublicKey_length
,
2408 unsigned char **client_key
,
2409 unsigned int *client_key_len
)
2411 /* Solaris Kerberos */
2412 krb5_error_code retval
= KRB5_PREAUTH_FAILED
;
2413 BIGNUM
*server_pub_key
= NULL
;
2414 ASN1_INTEGER
*pub_key
= NULL
;
2415 const unsigned char *p
= NULL
;
2416 unsigned char *data
= NULL
;
2419 /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */
2421 if (der_decode_data(subjectPublicKey_data
, (long)subjectPublicKey_length
,
2422 &data
, &data_len
) != 0) {
2423 pkiDebug("failed to decode subjectPublicKey\n");
2424 /* Solaris Kerberos */
2425 retval
= KRB5_PREAUTH_FAILED
;
2429 *client_key_len
= DH_size(cryptoctx
->dh
);
2430 if ((*client_key
= (unsigned char *)
2431 malloc((size_t) *client_key_len
)) == NULL
) {
2436 if ((pub_key
= d2i_ASN1_INTEGER(NULL
, &p
, data_len
)) == NULL
)
2438 if ((server_pub_key
= ASN1_INTEGER_to_BN(pub_key
, NULL
)) == NULL
)
2441 DH_compute_key(*client_key
, server_pub_key
, cryptoctx
->dh
);
2443 print_pubkey(server_pub_key
, "server's pub_key=");
2444 pkiDebug("client secret key (%d)= ", *client_key_len
);
2445 print_buffer(*client_key
, *client_key_len
);
2449 if (server_pub_key
!= NULL
)
2450 BN_free(server_pub_key
);
2451 if (pub_key
!= NULL
)
2452 ASN1_INTEGER_free(pub_key
);
2459 if (*client_key
!= NULL
)
2462 if (pub_key
!= NULL
)
2463 ASN1_INTEGER_free(pub_key
);
2472 server_check_dh(krb5_context context
,
2473 pkinit_plg_crypto_context cryptoctx
,
2474 pkinit_req_crypto_context req_cryptoctx
,
2475 pkinit_identity_crypto_context id_cryptoctx
,
2476 krb5_octet_data
*dh_params
,
2480 unsigned char *tmp
= NULL
;
2482 krb5_error_code retval
= KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
;
2483 const BIGNUM
*p
, *g
, *q
, *p2
;
2485 tmp
= dh_params
->data
;
2487 dh
= pkinit_decode_dh_params(&dh
, &tmp
, dh_params
->length
);
2489 pkiDebug("failed to decode dhparams\n");
2493 DH_get0_pqg(dh
, &p
, &q
, &g
);
2495 /* KDC SHOULD check to see if the key parameters satisfy its policy */
2496 dh_prime_bits
= BN_num_bits(p
);
2497 if (minbits
&& dh_prime_bits
< minbits
) {
2498 pkiDebug("client sent dh params with %d bits, we require %d\n",
2499 dh_prime_bits
, minbits
);
2503 /* check dhparams is group 2 */
2504 DH_get0_pqg(cryptoctx
->dh_1024
, &p2
, NULL
, NULL
);
2505 if (pkinit_check_dh_params(p2
, p
, g
, q
) == 0) {
2510 /* check dhparams is group 14 */
2511 DH_get0_pqg(cryptoctx
->dh_2048
, &p2
, NULL
, NULL
);
2512 if (pkinit_check_dh_params(p2
, p
, g
, q
) == 0) {
2517 /* check dhparams is group 16 */
2518 DH_get0_pqg(cryptoctx
->dh_4096
, &p2
, NULL
, NULL
);
2519 if (pkinit_check_dh_params(p2
, p
, g
, q
) == 0) {
2526 req_cryptoctx
->dh
= dh
;
2533 /* kdc's dh function */
2536 server_process_dh(krb5_context context
,
2537 pkinit_plg_crypto_context plg_cryptoctx
,
2538 pkinit_req_crypto_context cryptoctx
,
2539 pkinit_identity_crypto_context id_cryptoctx
,
2540 unsigned char *data
,
2541 unsigned int data_len
,
2542 unsigned char **dh_pubkey
,
2543 unsigned int *dh_pubkey_len
,
2544 unsigned char **server_key
,
2545 unsigned int *server_key_len
)
2547 /* Solaris Kerberos */
2548 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2549 DH
*dh
= NULL
, *dh_server
= NULL
;
2550 const BIGNUM
*p
, *g
, *q
, *s_pub_key
;
2552 unsigned char *s
= NULL
;
2553 ASN1_INTEGER
*asn_pub_key
= NULL
;
2555 /* get client's received DH parameters that we saved in server_check_dh */
2558 dh_server
= DH_new();
2559 if (dh_server
== NULL
)
2561 DH_get0_pqg(dh
, &p
, &g
, &q
);
2562 DH_set0_pqg(dh_server
, BN_dup(p
), BN_dup(g
), BN_dup(q
));
2564 /* decode client's public key */
2566 asn_pub_key
= d2i_ASN1_INTEGER(NULL
,
2567 (const unsigned char **)&s
, (int)data_len
);
2568 if (asn_pub_key
== NULL
)
2570 pub_key
= ASN1_INTEGER_to_BN(asn_pub_key
, NULL
);
2571 if (pub_key
== NULL
)
2573 DH_set0_key(dh
, pub_key
, NULL
);
2574 ASN1_INTEGER_free(asn_pub_key
);
2576 if (!DH_generate_key(dh_server
))
2579 /* generate DH session key */
2580 *server_key_len
= DH_size(dh_server
);
2581 if ((*server_key
= (unsigned char *) malloc((size_t)*server_key_len
))
2584 DH_compute_key(*server_key
, pub_key
, dh_server
);
2585 DH_get0_key(dh_server
, &s_pub_key
, NULL
);
2588 print_dh(dh_server
, "client&server's DH params\n");
2589 print_pubkey(pub_key
, "client's pub_key=");
2590 print_pubkey(s_pub_key
, "server's pub_key=");
2591 pkiDebug("server secret key=");
2592 print_buffer(*server_key
, *server_key_len
);
2596 /* pack DH public key */
2597 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2598 * encoding shall be used as the contents (the value) of the
2599 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2602 if ((asn_pub_key
= BN_to_ASN1_INTEGER(s_pub_key
, NULL
)) == NULL
)
2604 *dh_pubkey_len
= i2d_ASN1_INTEGER(asn_pub_key
, NULL
);
2605 if ((s
= *dh_pubkey
= (unsigned char *) malloc((size_t)*dh_pubkey_len
))
2608 i2d_ASN1_INTEGER(asn_pub_key
, &s
);
2609 if (asn_pub_key
!= NULL
)
2610 ASN1_INTEGER_free(asn_pub_key
);
2614 if (dh_server
!= NULL
)
2619 if (dh_server
!= NULL
)
2621 if (*dh_pubkey
!= NULL
)
2623 if (*server_key
!= NULL
)
2631 * Add locking around did_init to make it MT-safe.
2633 static krb5_error_code
2636 krb5_error_code ret
= 0;
2637 static int did_init
= 0;
2638 static k5_mutex_t init_mutex
= K5_MUTEX_PARTIAL_INITIALIZER
;
2640 ret
= k5_mutex_lock(&init_mutex
);
2643 /* initialize openssl routines */
2644 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2646 * As of version 1.1.0, OpenSSL will automatically allocate
2647 * resources as-needed.
2649 CRYPTO_malloc_init();
2650 ERR_load_crypto_strings();
2651 OpenSSL_add_all_algorithms();
2655 k5_mutex_unlock(&init_mutex
);
2660 static krb5_error_code
2661 pkinit_encode_dh_params(const BIGNUM
*p
, const BIGNUM
*g
, const BIGNUM
*q
,
2662 unsigned char **buf
, unsigned int *buf_len
)
2664 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
2665 int bufsize
= 0, r
= 0;
2666 unsigned char *tmp
= NULL
;
2667 ASN1_INTEGER
*ap
= NULL
, *ag
= NULL
, *aq
= NULL
;
2669 if ((ap
= BN_to_ASN1_INTEGER(p
, NULL
)) == NULL
)
2671 if ((ag
= BN_to_ASN1_INTEGER(g
, NULL
)) == NULL
)
2673 if ((aq
= BN_to_ASN1_INTEGER(q
, NULL
)) == NULL
)
2675 bufsize
= i2d_ASN1_INTEGER(ap
, NULL
);
2676 bufsize
+= i2d_ASN1_INTEGER(ag
, NULL
);
2677 bufsize
+= i2d_ASN1_INTEGER(aq
, NULL
);
2679 r
= ASN1_object_size(1, bufsize
, V_ASN1_SEQUENCE
);
2681 tmp
= *buf
= (unsigned char *)malloc((size_t) r
);
2685 ASN1_put_object(&tmp
, 1, bufsize
, V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
2687 i2d_ASN1_INTEGER(ap
, &tmp
);
2688 i2d_ASN1_INTEGER(ag
, &tmp
);
2689 i2d_ASN1_INTEGER(aq
, &tmp
);
2697 ASN1_INTEGER_free(ap
);
2699 ASN1_INTEGER_free(ag
);
2701 ASN1_INTEGER_free(aq
);
2706 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2709 pkinit_decode_dh_params(DH
** a
, unsigned char **pp
, unsigned int len
)
2711 ASN1_INTEGER ai
, *aip
= NULL
;
2712 long length
= (long) len
;
2714 M_ASN1_D2I_vars(a
, DH
*, DH_new
);
2717 M_ASN1_D2I_start_sequence();
2721 M_ASN1_D2I_get_x(ASN1_INTEGER
, aip
, d2i_ASN1_INTEGER
);
2725 (*a
)->p
= ASN1_INTEGER_to_BN(aip
, NULL
);
2726 if ((*a
)->p
== NULL
)
2728 if (ai
.data
!= NULL
) {
2729 OPENSSL_free(ai
.data
);
2734 M_ASN1_D2I_get_x(ASN1_INTEGER
, aip
, d2i_ASN1_INTEGER
);
2738 (*a
)->g
= ASN1_INTEGER_to_BN(aip
, NULL
);
2739 if ((*a
)->g
== NULL
)
2741 if (ai
.data
!= NULL
) {
2742 OPENSSL_free(ai
.data
);
2748 M_ASN1_D2I_get_x(ASN1_INTEGER
, aip
, d2i_ASN1_INTEGER
);
2752 (*a
)->q
= ASN1_INTEGER_to_BN(aip
, NULL
);
2753 if ((*a
)->q
== NULL
)
2755 if (ai
.data
!= NULL
) {
2756 OPENSSL_free(ai
.data
);
2762 M_ASN1_D2I_end_sequence();
2763 M_ASN1_D2I_Finish(a
, DH_free
, 0);
2770 * This is taken from the internal dh_asn1.c file in OpenSSL 1.1, modified to
2771 * make q an optional field.
2775 ASN1_BIT_STRING
*seed
;
2784 int_dhvparams
*vparams
;
2787 ASN1_SEQUENCE(DHvparams
) = {
2788 ASN1_SIMPLE(int_dhvparams
, seed
, ASN1_BIT_STRING
),
2789 ASN1_SIMPLE(int_dhvparams
, counter
, BIGNUM
)
2790 } static_ASN1_SEQUENCE_END_name(int_dhvparams
, DHvparams
)
2792 ASN1_SEQUENCE(DHxparams
) = {
2793 ASN1_SIMPLE(int_dhx942_dh
, p
, BIGNUM
),
2794 ASN1_SIMPLE(int_dhx942_dh
, g
, BIGNUM
),
2795 ASN1_OPT(int_dhx942_dh
, q
, BIGNUM
),
2796 ASN1_OPT(int_dhx942_dh
, j
, BIGNUM
),
2797 ASN1_OPT(int_dhx942_dh
, vparams
, DHvparams
),
2798 } static_ASN1_SEQUENCE_END_name(int_dhx942_dh
, DHxparams
)
2801 pkinit_decode_dh_params(DH
**a
, unsigned char **pp
, unsigned int len
)
2803 int_dhx942_dh
*params
;
2809 params
= (int_dhx942_dh
*)ASN1_item_d2i(NULL
,
2810 (const unsigned char **)pp
, len
, ASN1_ITEM_rptr(DHxparams
));
2811 if (params
== NULL
) {
2816 DH_set0_pqg(dh
, params
->p
, params
->q
, params
->g
);
2817 params
->p
= params
->q
= params
->g
= NULL
;
2818 ASN1_item_free((ASN1_VALUE
*)params
, ASN1_ITEM_rptr(DHxparams
));
2822 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
2824 static krb5_error_code
2825 pkinit_create_sequence_of_principal_identifiers(
2826 krb5_context context
,
2827 pkinit_plg_crypto_context plg_cryptoctx
,
2828 pkinit_req_crypto_context req_cryptoctx
,
2829 pkinit_identity_crypto_context id_cryptoctx
,
2831 krb5_data
**out_data
)
2833 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2834 krb5_external_principal_identifier
**krb5_trusted_certifiers
= NULL
;
2835 krb5_data
*td_certifiers
= NULL
, *data
= NULL
;
2836 krb5_typed_data
**typed_data
= NULL
;
2839 case TD_TRUSTED_CERTIFIERS
:
2840 retval
= create_krb5_trustedCertifiers(context
, plg_cryptoctx
,
2841 req_cryptoctx
, id_cryptoctx
, &krb5_trusted_certifiers
);
2843 pkiDebug("create_krb5_trustedCertifiers failed\n");
2847 case TD_INVALID_CERTIFICATES
:
2848 retval
= create_krb5_invalidCertificates(context
, plg_cryptoctx
,
2849 req_cryptoctx
, id_cryptoctx
, &krb5_trusted_certifiers
);
2851 pkiDebug("create_krb5_invalidCertificates failed\n");
2860 retval
= k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier
**)krb5_trusted_certifiers
, &td_certifiers
);
2862 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
2866 print_buffer_bin((unsigned char *)td_certifiers
->data
,
2867 td_certifiers
->length
, "/tmp/kdc_td_certifiers");
2869 typed_data
= malloc (2 * sizeof(krb5_typed_data
*));
2870 if (typed_data
== NULL
) {
2874 typed_data
[1] = NULL
;
2875 init_krb5_typed_data(&typed_data
[0]);
2876 if (typed_data
[0] == NULL
) {
2880 typed_data
[0]->type
= type
;
2881 typed_data
[0]->length
= td_certifiers
->length
;
2882 typed_data
[0]->data
= (unsigned char *)td_certifiers
->data
;
2883 retval
= k5int_encode_krb5_typed_data((const krb5_typed_data
**)typed_data
,
2886 pkiDebug("encode_krb5_typed_data failed\n");
2890 print_buffer_bin((unsigned char *)data
->data
, data
->length
,
2893 *out_data
= (krb5_data
*)malloc(sizeof(krb5_data
));
2894 (*out_data
)->length
= data
->length
;
2895 (*out_data
)->data
= (char *)malloc(data
->length
);
2896 (void) memcpy((*out_data
)->data
, data
->data
, data
->length
);
2901 if (krb5_trusted_certifiers
!= NULL
)
2902 free_krb5_external_principal_identifier(&krb5_trusted_certifiers
);
2905 if (data
->data
!= NULL
)
2910 if (td_certifiers
!= NULL
)
2911 free(td_certifiers
);
2913 if (typed_data
!= NULL
)
2914 free_krb5_typed_data(&typed_data
);
2920 pkinit_create_td_trusted_certifiers(krb5_context context
,
2921 pkinit_plg_crypto_context plg_cryptoctx
,
2922 pkinit_req_crypto_context req_cryptoctx
,
2923 pkinit_identity_crypto_context id_cryptoctx
,
2924 krb5_data
**out_data
)
2926 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2928 retval
= pkinit_create_sequence_of_principal_identifiers(context
,
2929 plg_cryptoctx
, req_cryptoctx
, id_cryptoctx
,
2930 TD_TRUSTED_CERTIFIERS
, out_data
);
2936 pkinit_create_td_invalid_certificate(
2937 krb5_context context
,
2938 pkinit_plg_crypto_context plg_cryptoctx
,
2939 pkinit_req_crypto_context req_cryptoctx
,
2940 pkinit_identity_crypto_context id_cryptoctx
,
2941 krb5_data
**out_data
)
2943 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2945 retval
= pkinit_create_sequence_of_principal_identifiers(context
,
2946 plg_cryptoctx
, req_cryptoctx
, id_cryptoctx
,
2947 TD_INVALID_CERTIFICATES
, out_data
);
2954 pkinit_create_td_dh_parameters(krb5_context context
,
2955 pkinit_plg_crypto_context plg_cryptoctx
,
2956 pkinit_req_crypto_context req_cryptoctx
,
2957 pkinit_identity_crypto_context id_cryptoctx
,
2958 pkinit_plg_opts
*opts
,
2959 krb5_data
**out_data
)
2961 /* Solaris Kerberos */
2962 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2963 unsigned int buf1_len
= 0, buf2_len
= 0, buf3_len
= 0, i
= 0;
2964 unsigned char *buf1
= NULL
, *buf2
= NULL
, *buf3
= NULL
;
2965 krb5_typed_data
**typed_data
= NULL
;
2966 krb5_data
*data
= NULL
, *encoded_algId
= NULL
;
2967 krb5_algorithm_identifier
**algId
= NULL
;
2968 const BIGNUM
*p
, *q
, *g
;
2970 /* Solaris Kerberos */
2971 if (opts
->dh_min_bits
> 4096) {
2976 if (opts
->dh_min_bits
<= 1024) {
2977 DH_get0_pqg(plg_cryptoctx
->dh_1024
, &p
, &q
, &g
);
2978 retval
= pkinit_encode_dh_params(p
, g
, q
, &buf1
, &buf1_len
);
2982 if (opts
->dh_min_bits
<= 2048) {
2983 DH_get0_pqg(plg_cryptoctx
->dh_2048
, &p
, &q
, &g
);
2984 retval
= pkinit_encode_dh_params(p
, g
, q
, &buf2
, &buf2_len
);
2988 DH_get0_pqg(plg_cryptoctx
->dh_4096
, &p
, &q
, &g
);
2989 retval
= pkinit_encode_dh_params(p
, g
, q
, &buf3
, &buf3_len
);
2993 if (opts
->dh_min_bits
<= 1024) {
2994 algId
= malloc(4 * sizeof(krb5_algorithm_identifier
*));
2998 algId
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2999 if (algId
[0] == NULL
)
3001 algId
[0]->parameters
.data
= (unsigned char *)malloc(buf2_len
);
3002 if (algId
[0]->parameters
.data
== NULL
)
3004 (void) memcpy(algId
[0]->parameters
.data
, buf2
, buf2_len
);
3005 algId
[0]->parameters
.length
= buf2_len
;
3006 algId
[0]->algorithm
= dh_oid
;
3008 algId
[1] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
3009 if (algId
[1] == NULL
)
3011 algId
[1]->parameters
.data
= (unsigned char *)malloc(buf3_len
);
3012 if (algId
[1]->parameters
.data
== NULL
)
3014 (void) memcpy(algId
[1]->parameters
.data
, buf3
, buf3_len
);
3015 algId
[1]->parameters
.length
= buf3_len
;
3016 algId
[1]->algorithm
= dh_oid
;
3018 algId
[2] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
3019 if (algId
[2] == NULL
)
3021 algId
[2]->parameters
.data
= (unsigned char *)malloc(buf1_len
);
3022 if (algId
[2]->parameters
.data
== NULL
)
3024 (void) memcpy(algId
[2]->parameters
.data
, buf1
, buf1_len
);
3025 algId
[2]->parameters
.length
= buf1_len
;
3026 algId
[2]->algorithm
= dh_oid
;
3028 } else if (opts
->dh_min_bits
<= 2048) {
3029 algId
= malloc(3 * sizeof(krb5_algorithm_identifier
*));
3033 algId
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
3034 if (algId
[0] == NULL
)
3036 algId
[0]->parameters
.data
= (unsigned char *)malloc(buf2_len
);
3037 if (algId
[0]->parameters
.data
== NULL
)
3039 (void) memcpy(algId
[0]->parameters
.data
, buf2
, buf2_len
);
3040 algId
[0]->parameters
.length
= buf2_len
;
3041 algId
[0]->algorithm
= dh_oid
;
3043 algId
[1] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
3044 if (algId
[1] == NULL
)
3046 algId
[1]->parameters
.data
= (unsigned char *)malloc(buf3_len
);
3047 if (algId
[1]->parameters
.data
== NULL
)
3049 (void) memcpy(algId
[1]->parameters
.data
, buf3
, buf3_len
);
3050 algId
[1]->parameters
.length
= buf3_len
;
3051 algId
[1]->algorithm
= dh_oid
;
3053 } else if (opts
->dh_min_bits
<= 4096) {
3054 algId
= malloc(2 * sizeof(krb5_algorithm_identifier
*));
3058 algId
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
3059 if (algId
[0] == NULL
)
3061 algId
[0]->parameters
.data
= (unsigned char *)malloc(buf3_len
);
3062 if (algId
[0]->parameters
.data
== NULL
)
3064 (void) memcpy(algId
[0]->parameters
.data
, buf3
, buf3_len
);
3065 algId
[0]->parameters
.length
= buf3_len
;
3066 algId
[0]->algorithm
= dh_oid
;
3069 retval
= k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier
**)algId
, &encoded_algId
);
3073 print_buffer_bin((unsigned char *)encoded_algId
->data
,
3074 encoded_algId
->length
, "/tmp/kdc_td_dh_params");
3076 typed_data
= malloc (2 * sizeof(krb5_typed_data
*));
3077 if (typed_data
== NULL
) {
3081 typed_data
[1] = NULL
;
3082 init_krb5_typed_data(&typed_data
[0]);
3083 if (typed_data
== NULL
) {
3087 typed_data
[0]->type
= TD_DH_PARAMETERS
;
3088 typed_data
[0]->length
= encoded_algId
->length
;
3089 typed_data
[0]->data
= (unsigned char *)encoded_algId
->data
;
3090 retval
= k5int_encode_krb5_typed_data((const krb5_typed_data
**)typed_data
,
3093 pkiDebug("encode_krb5_typed_data failed\n");
3097 print_buffer_bin((unsigned char *)data
->data
, data
->length
,
3100 *out_data
= (krb5_data
*)malloc(sizeof(krb5_data
));
3101 if (*out_data
== NULL
)
3103 (*out_data
)->length
= data
->length
;
3104 (*out_data
)->data
= (char *)malloc(data
->length
);
3105 if ((*out_data
)->data
== NULL
) {
3110 (void) memcpy((*out_data
)->data
, data
->data
, data
->length
);
3122 if (data
->data
!= NULL
)
3126 if (typed_data
!= NULL
)
3127 free_krb5_typed_data(&typed_data
);
3128 if (encoded_algId
!= NULL
)
3129 free(encoded_algId
);
3131 if (algId
!= NULL
) {
3132 while(algId
[i
] != NULL
) {
3133 if (algId
[i
]->parameters
.data
!= NULL
)
3134 free(algId
[i
]->parameters
.data
);
3146 pkinit_check_kdc_pkid(krb5_context context
,
3147 pkinit_plg_crypto_context plg_cryptoctx
,
3148 pkinit_req_crypto_context req_cryptoctx
,
3149 pkinit_identity_crypto_context id_cryptoctx
,
3150 unsigned char *pdid_buf
,
3151 unsigned int pkid_len
,
3154 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
3155 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
3156 const unsigned char *p
= pdid_buf
;
3158 X509
*kdc_cert
= sk_X509_value(id_cryptoctx
->my_certs
, id_cryptoctx
->cert_index
);
3161 pkiDebug("found kdcPkId in AS REQ\n");
3162 is
= d2i_PKCS7_ISSUER_AND_SERIAL(NULL
, &p
, (int)pkid_len
);
3166 status
= X509_NAME_cmp(X509_get_issuer_name(kdc_cert
), is
->issuer
);
3168 status
= ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert
), is
->serial
);
3175 X509_NAME_free(is
->issuer
);
3176 ASN1_INTEGER_free(is
->serial
);
3183 pkinit_check_dh_params(const BIGNUM
*p1
, const BIGNUM
*p2
, const BIGNUM
*g1
,
3186 BIGNUM
*g2
= NULL
, *q2
= NULL
;
3187 /* Solaris Kerberos */
3188 int retval
= EINVAL
;
3190 if (!BN_cmp(p1
, p2
)) {
3192 BN_set_word(g2
, DH_GENERATOR_2
);
3193 if (!BN_cmp(g1
, g2
)) {
3196 if (!BN_cmp(q1
, q2
)) {
3197 pkiDebug("good %d dhparams\n", BN_num_bits(p1
));
3200 pkiDebug("bad group 2 q dhparameter\n");
3203 pkiDebug("bad g dhparameter\n");
3206 pkiDebug("p is not well-known group 2 dhparameter\n");
3213 pkinit_process_td_dh_params(krb5_context context
,
3214 pkinit_plg_crypto_context cryptoctx
,
3215 pkinit_req_crypto_context req_cryptoctx
,
3216 pkinit_identity_crypto_context id_cryptoctx
,
3217 krb5_algorithm_identifier
**algId
,
3220 krb5_error_code retval
= KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
;
3221 int i
= 0, use_sent_dh
= 0, ok
= 0;
3223 pkiDebug("dh parameters\n");
3225 while (algId
[i
] != NULL
) {
3227 unsigned char *tmp
= NULL
;
3228 const BIGNUM
*p
, *g
, *q
, *p2
;
3229 int dh_prime_bits
= 0;
3231 if (algId
[i
]->algorithm
.length
!= dh_oid
.length
||
3232 memcmp(algId
[i
]->algorithm
.data
, dh_oid
.data
, dh_oid
.length
))
3235 tmp
= algId
[i
]->parameters
.data
;
3237 dh
= pkinit_decode_dh_params(&dh
, &tmp
, algId
[i
]->parameters
.length
);
3238 dh_prime_bits
= DH_bits(dh
);
3239 pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
3240 *new_dh_size
, dh_prime_bits
);
3241 DH_get0_pqg(dh
, &p
, &q
, &g
);
3242 switch(dh_prime_bits
) {
3244 DH_get0_pqg(cryptoctx
->dh_1024
, &p2
, NULL
, NULL
);
3245 if (pkinit_check_dh_params(p2
, p
, g
, q
) == 0) {
3246 *new_dh_size
= 1024;
3251 DH_get0_pqg(cryptoctx
->dh_2048
, &p2
, NULL
, NULL
);
3252 if (pkinit_check_dh_params(p2
, p
, g
, q
) == 0) {
3253 *new_dh_size
= 2048;
3258 DH_get0_pqg(cryptoctx
->dh_4096
, &p2
, NULL
, NULL
);
3259 if (pkinit_check_dh_params(p2
, p
, g
, q
) == 0) {
3260 *new_dh_size
= 4096;
3268 DH_check(dh
, &retval
);
3270 pkiDebug("DH parameters provided by server are unacceptable\n");
3271 retval
= KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
;
3281 if (req_cryptoctx
->dh
!= NULL
) {
3282 DH_free(req_cryptoctx
->dh
);
3283 req_cryptoctx
->dh
= NULL
;
3286 req_cryptoctx
->dh
= dh
;
3301 openssl_callback(int ok
, X509_STORE_CTX
* ctx
)
3305 char buf
[DN_BUF_LEN
];
3307 X509_NAME_oneline(X509_get_subject_name(ctx
->current_cert
), buf
, sizeof(buf
));
3308 pkiDebug("cert = %s\n", buf
);
3309 pkiDebug("callback function: %d (%s)\n", ctx
->error
,
3310 X509_verify_cert_error_string(ctx
->error
));
3317 openssl_callback_ignore_crls(int ok
, X509_STORE_CTX
* ctx
)
3320 return (X509_STORE_CTX_get_error(ctx
) == X509_V_ERR_UNABLE_TO_GET_CRL
);
3324 static ASN1_OBJECT
*
3325 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx
, int pkcs7_type
)
3327 switch (pkcs7_type
) {
3328 case CMS_SIGN_CLIENT
:
3329 return cryptoctx
->id_pkinit_authData
;
3330 case CMS_SIGN_DRAFT9
:
3331 return OBJ_nid2obj(NID_pkcs7_data
);
3332 case CMS_SIGN_SERVER
:
3333 return cryptoctx
->id_pkinit_DHKeyData
;
3334 case CMS_ENVEL_SERVER
:
3335 return cryptoctx
->id_pkinit_rkeyData
;
3342 #ifdef LONGHORN_BETA_COMPAT
3345 * This is a version that worked with Longhorn Beta 3.
3348 wrap_signeddata(unsigned char *data
, unsigned int data_len
,
3349 unsigned char **out
, unsigned int *out_len
,
3350 int is_longhorn_server
)
3353 unsigned int orig_len
= 0, oid_len
= 0, tot_len
= 0;
3354 ASN1_OBJECT
*oid
= NULL
;
3355 unsigned char *p
= NULL
;
3357 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3358 __FUNCTION__
, is_longhorn_server
);
3360 /* Get length to wrap the original data with SEQUENCE tag */
3361 tot_len
= orig_len
= ASN1_object_size(1, (int)data_len
, V_ASN1_SEQUENCE
);
3363 if (is_longhorn_server
== 0) {
3364 /* Add the signedData OID and adjust lengths */
3365 oid
= OBJ_nid2obj(NID_pkcs7_signed
);
3366 oid_len
= i2d_ASN1_OBJECT(oid
, NULL
);
3368 tot_len
= ASN1_object_size(1, (int)(orig_len
+oid_len
), V_ASN1_SEQUENCE
);
3371 p
= *out
= (unsigned char *)malloc(tot_len
);
3372 if (p
== NULL
) return -1;
3374 if (is_longhorn_server
== 0) {
3375 ASN1_put_object(&p
, 1, (int)(orig_len
+oid_len
),
3376 V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3378 i2d_ASN1_OBJECT(oid
, &p
);
3380 ASN1_put_object(&p
, 1, (int)data_len
, 0, V_ASN1_CONTEXT_SPECIFIC
);
3382 ASN1_put_object(&p
, 1, (int)data_len
, V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3384 memcpy(p
, data
, data_len
);
3392 * This is a version that works with a patched Longhorn KDC.
3393 * (Which should match SP1 ??).
3396 wrap_signeddata(unsigned char *data
, unsigned int data_len
,
3397 unsigned char **out
, unsigned int *out_len
,
3398 int is_longhorn_server
)
3401 unsigned int oid_len
= 0, tot_len
= 0, wrap_len
= 0, tag_len
= 0;
3402 ASN1_OBJECT
*oid
= NULL
;
3403 unsigned char *p
= NULL
;
3405 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3406 __FUNCTION__
, is_longhorn_server
);
3408 /* New longhorn is missing another sequence */
3409 if (is_longhorn_server
== 1)
3410 wrap_len
= ASN1_object_size(1, (int)(data_len
), V_ASN1_SEQUENCE
);
3412 wrap_len
= data_len
;
3414 /* Get length to wrap the original data with SEQUENCE tag */
3415 tag_len
= ASN1_object_size(1, (int)wrap_len
, V_ASN1_SEQUENCE
);
3417 /* Always add oid */
3418 oid
= OBJ_nid2obj(NID_pkcs7_signed
);
3419 oid_len
= i2d_ASN1_OBJECT(oid
, NULL
);
3422 tot_len
= ASN1_object_size(1, (int)(oid_len
), V_ASN1_SEQUENCE
);
3424 p
= *out
= (unsigned char *)malloc(tot_len
);
3428 ASN1_put_object(&p
, 1, (int)(oid_len
),
3429 V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3431 i2d_ASN1_OBJECT(oid
, &p
);
3433 ASN1_put_object(&p
, 1, (int)wrap_len
, 0, V_ASN1_CONTEXT_SPECIFIC
);
3435 /* Wrap in extra seq tag */
3436 if (is_longhorn_server
== 1) {
3437 ASN1_put_object(&p
, 1, (int)data_len
, V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3439 (void) memcpy(p
, data
, data_len
);
3449 wrap_signeddata(unsigned char *data
, unsigned int data_len
,
3450 unsigned char **out
, unsigned int *out_len
)
3453 unsigned int orig_len
= 0, oid_len
= 0, tot_len
= 0;
3454 ASN1_OBJECT
*oid
= NULL
;
3455 unsigned char *p
= NULL
;
3457 /* Get length to wrap the original data with SEQUENCE tag */
3458 tot_len
= orig_len
= ASN1_object_size(1, (int)data_len
, V_ASN1_SEQUENCE
);
3460 /* Add the signedData OID and adjust lengths */
3461 oid
= OBJ_nid2obj(NID_pkcs7_signed
);
3462 oid_len
= i2d_ASN1_OBJECT(oid
, NULL
);
3464 tot_len
= ASN1_object_size(1, (int)(orig_len
+oid_len
), V_ASN1_SEQUENCE
);
3466 p
= *out
= (unsigned char *)malloc(tot_len
);
3467 if (p
== NULL
) return -1;
3469 ASN1_put_object(&p
, 1, (int)(orig_len
+oid_len
),
3470 V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3472 i2d_ASN1_OBJECT(oid
, &p
);
3474 ASN1_put_object(&p
, 1, (int)data_len
, 0, V_ASN1_CONTEXT_SPECIFIC
);
3475 (void) memcpy(p
, data
, data_len
);
3484 prepare_enc_data(unsigned char *indata
,
3486 unsigned char **outdata
,
3491 const uint8_t *p
= indata
, *oldp
;
3493 /* Top-bit set means that the conversion failed. */
3494 if (ASN1_get_object(&p
, &slen
, &tag
, &class, indata_len
) & 0x80)
3496 if (tag
!= V_ASN1_SEQUENCE
)
3500 if (ASN1_get_object(&p
, &tlen
, &tag
, &class, slen
) & 0x80)
3505 if (ASN1_get_object(&p
, &tlen
, &tag
, &class, slen
) & 0x80)
3508 *outdata
= malloc(tlen
);
3509 if (*outdata
== NULL
)
3511 memcpy(*outdata
, p
, tlen
);
3512 *outdata_len
= tlen
;
3517 #ifndef WITHOUT_PKCS11
3519 pkinit_C_LoadModule(const char *modname
, CK_FUNCTION_LIST_PTR_PTR p11p
)
3522 CK_RV (*getflist
)(CK_FUNCTION_LIST_PTR_PTR
);
3524 pkiDebug("loading module \"%s\"... ", modname
);
3525 /* Solaris Kerberos */
3526 handle
= dlopen(modname
, RTLD_NOW
| RTLD_GROUP
);
3527 if (handle
== NULL
) {
3528 pkiDebug("not found\n");
3531 getflist
= (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR
)) dlsym(handle
, "C_GetFunctionList");
3532 if (getflist
== NULL
|| (*getflist
)(p11p
) != CKR_OK
) {
3533 (void) dlclose(handle
);
3534 pkiDebug("failed\n");
3542 pkinit_C_UnloadModule(void *handle
)
3544 /* Solaris Kerberos */
3545 if (dlclose(handle
) != 0)
3546 return CKR_GENERAL_ERROR
;
3552 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3555 * labelstr will be C string containing token label with trailing white space
3559 trim_token_label(CK_TOKEN_INFO
*tinfo
, char *labelstr
, unsigned int labelstr_len
)
3563 assert(labelstr_len
> sizeof (tinfo
->label
));
3565 * \0 terminate labelstr in case the last char in the token label is
3568 labelstr
[sizeof (tinfo
->label
)] = '\0';
3569 (void) memcpy(labelstr
, (char *) tinfo
->label
, sizeof (tinfo
->label
));
3571 /* init i so terminating \0 is skipped */
3572 for (i
= sizeof (tinfo
->label
) - 1; i
>= 0; i
--) {
3573 if (labelstr
[i
] == ' ')
3581 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3584 static krb5_error_code
3585 pkinit_prompt_user(krb5_context context
,
3586 pkinit_identity_crypto_context cctx
,
3592 krb5_prompt kprompt
;
3593 krb5_prompt_type prompt_type
;
3595 if (cctx
->prompter
== NULL
)
3598 kprompt
.prompt
= prompt
;
3599 kprompt
.hidden
= hidden
;
3600 kprompt
.reply
= reply
;
3602 * Note, assuming this type for now, may need to be passed in in the future.
3604 prompt_type
= KRB5_PROMPT_TYPE_PREAUTH
;
3606 /* PROMPTER_INVOCATION */
3607 k5int_set_prompt_types(context
, &prompt_type
);
3608 r
= (*cctx
->prompter
)(context
, cctx
->prompter_data
,
3609 NULL
, NULL
, 1, &kprompt
);
3610 k5int_set_prompt_types(context
, NULL
);
3615 * Solaris Kerberos: this function was changed to support a PIN being passed
3616 * in. If that is the case the user will not be prompted for their PIN.
3618 static krb5_error_code
3619 pkinit_login(krb5_context context
,
3620 pkinit_identity_crypto_context id_cryptoctx
,
3628 if (tip
->flags
& CKF_PROTECTED_AUTHENTICATION_PATH
) {
3631 } else if (id_cryptoctx
->PIN
!= NULL
) {
3632 if ((rdat
.data
= strdup(id_cryptoctx
->PIN
)) == NULL
)
3635 * Don't include NULL string terminator in length calculation as this
3636 * PIN is passed to the C_Login function and only the text chars should
3637 * be considered to be the PIN.
3639 rdat
.length
= strlen(id_cryptoctx
->PIN
);
3641 /* Solaris Kerberos - trim token label */
3642 char tmplabel
[sizeof (tip
->label
) + 1];
3644 if (!id_cryptoctx
->prompter
) {
3645 pkiDebug("pkinit_login: id_cryptoctx->prompter is NULL\n");
3646 /* Solaris Kerberos: Improved error messages */
3647 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3648 gettext("Failed to log into token: prompter function is NULL"));
3649 return (KRB5KDC_ERR_PREAUTH_FAILED
);
3651 /* Solaris Kerberos - Changes for gettext() */
3652 prompt_len
= sizeof (tip
->label
) + 256;
3653 if ((prompt
= (char *) malloc(prompt_len
)) == NULL
)
3656 /* Solaris Kerberos - trim token label which can be padded with space */
3657 trim_token_label(tip
, tmplabel
, sizeof (tmplabel
));
3658 (void) snprintf(prompt
, prompt_len
, gettext("%s PIN"), tmplabel
);
3660 /* Solaris Kerberos */
3661 if (tip
->flags
& CKF_USER_PIN_LOCKED
)
3662 (void) strlcat(prompt
, gettext(" (Warning: PIN locked)"), prompt_len
);
3663 else if (tip
->flags
& CKF_USER_PIN_FINAL_TRY
)
3664 (void) strlcat(prompt
, gettext(" (Warning: PIN final try)"), prompt_len
);
3665 else if (tip
->flags
& CKF_USER_PIN_COUNT_LOW
)
3666 (void) strlcat(prompt
, gettext(" (Warning: PIN count low)"), prompt_len
);
3667 rdat
.data
= malloc(tip
->ulMaxPinLen
+ 2);
3668 rdat
.length
= tip
->ulMaxPinLen
+ 1;
3670 * Note that the prompter function will set rdat.length such that the
3671 * NULL terminator is not included
3673 /* PROMPTER_INVOCATION */
3674 r
= pkinit_prompt_user(context
, id_cryptoctx
, &rdat
, prompt
, 1);
3679 r
= id_cryptoctx
->p11
->C_Login(id_cryptoctx
->session
, CKU_USER
,
3680 (u_char
*) rdat
.data
, rdat
.length
);
3683 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r
));
3684 /* Solaris Kerberos: Improved error messages */
3685 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3686 gettext("Failed to log into token: %s"),
3687 pkinit_pkcs11_code_to_text(r
));
3688 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3690 /* Solaris Kerberos: only need to login once */
3691 id_cryptoctx
->p11flags
|= C_LOGIN_DONE
;
3695 (void) memset(rdat
.data
, 0, rdat
.length
);
3703 * Solaris Kerberos: added these structs in support of prompting user for
3706 struct _token_entry
{
3708 CK_SESSION_HANDLE session
;
3709 CK_TOKEN_INFO token_info
;
3711 struct _token_choices
{
3712 unsigned int numtokens
;
3713 struct _token_entry
*token_array
;
3718 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3721 static krb5_error_code
3722 pkinit_prompt_token(krb5_context context
,
3723 pkinit_identity_crypto_context cctx
)
3727 char *token_prompt
= gettext("If you have a smartcard insert it now. "
3728 "Press enter to continue");
3730 reply
.data
= tmpbuf
;
3731 reply
.length
= sizeof(tmpbuf
);
3733 /* note, don't care about the reply */
3734 return (pkinit_prompt_user(context
, cctx
, &reply
, token_prompt
, 0));
3738 * Solaris Kerberos: new defines for prompting support.
3740 #define CHOOSE_THIS_TOKEN 0
3741 #define CHOOSE_RESCAN 1
3742 #define CHOOSE_SKIP 2
3743 #define CHOOSE_SEE_NEXT 3
3745 #define RESCAN_TOKENS -1
3746 #define SKIP_TOKENS -2
3749 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3752 * This prompts to user for various choices regarding a token to use. Note
3753 * that if there is no error, choice will be set to one of:
3754 * - the token_choices->token_array entry
3759 pkinit_choose_tokens(krb5_context context
,
3760 pkinit_identity_crypto_context cctx
,
3761 struct _token_choices
*token_choices
,
3766 * Assuming that PAM_MAX_MSG_SIZE is a reasonable restriction. Note that -
3767 * 2 is to account for the fact that a krb prompter to PAM conv bridge will
3770 char prompt
[PAM_MAX_MSG_SIZE
- 2];
3772 char tmplabel
[sizeof (token_choices
->token_array
->token_info
.label
) + 1];
3774 int i
, num_used
, tmpchoice
;
3776 assert(token_choices
!= NULL
);
3777 assert(choice
!= NULL
);
3779 /* Create the menu prompt */
3781 /* only need to do this once before the for loop */
3782 reply
.data
= tmpbuf
;
3784 for (i
= 0; i
< token_choices
->numtokens
; i
++) {
3786 trim_token_label(&token_choices
->token_array
[i
].token_info
, tmplabel
,
3789 if (i
== (token_choices
->numtokens
- 1)) {
3790 /* no more smartcards/tokens */
3791 if ((num_used
= snprintf(prompt
, sizeof (prompt
),
3792 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n",
3794 * TRANSLATION_NOTE: Translations of the
3795 * following 5 strings must not exceed 450
3798 gettext("Select one of the following and press enter:"),
3799 CHOOSE_THIS_TOKEN
, gettext("Use smartcard"), tmplabel
,
3800 gettext("in slot"), token_choices
->token_array
[i
].slotID
,
3801 CHOOSE_RESCAN
, gettext("Rescan for newly inserted smartcard"),
3802 CHOOSE_SKIP
, gettext("Skip smartcard authentication")))
3803 >= sizeof (prompt
)) {
3804 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3805 " sizeof prompt: %d\n", num_used
, sizeof (prompt
));
3806 krb5_set_error_message(context
, EINVAL
,
3807 gettext("In pkinit_choose_tokens: prompt size"
3808 " %d exceeds prompt buffer size %d"),
3809 num_used
, sizeof(prompt
));
3810 (void) snprintf(prompt
, sizeof (prompt
), "%s",
3811 gettext("Error: PKINIT prompt message is too large for buffer, "
3812 "please alert the system administrator. Press enter to "
3814 reply
.length
= sizeof(tmpbuf
);
3815 if ((r
= pkinit_prompt_user(context
, cctx
, &reply
, prompt
, 0)) != 0 )
3820 if ((num_used
= snprintf(prompt
, sizeof (prompt
),
3821 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n%d: %s\n",
3823 * TRANSLATION_NOTE: Translations of the
3824 * following 6 strings must not exceed 445
3827 gettext("Select one of the following and press enter:"),
3828 CHOOSE_THIS_TOKEN
, gettext("Use smartcard"), tmplabel
,
3829 gettext("in slot"), token_choices
->token_array
[i
].slotID
,
3830 CHOOSE_RESCAN
, gettext("Rescan for newly inserted smartcard"),
3831 CHOOSE_SKIP
, gettext("Skip smartcard authentication"),
3832 CHOOSE_SEE_NEXT
, gettext("See next smartcard")))
3833 >= sizeof (prompt
)) {
3835 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3836 " sizeof prompt: %d\n", num_used
, sizeof (prompt
));
3837 krb5_set_error_message(context
, EINVAL
,
3838 gettext("In pkinit_choose_tokens: prompt size"
3839 " %d exceeds prompt buffer size %d"),
3840 num_used
, sizeof(prompt
));
3841 (void) snprintf(prompt
, sizeof (prompt
), "%s",
3842 gettext("Error: PKINIT prompt message is too large for buffer, "
3843 "please alert the system administrator. Press enter to "
3845 reply
.length
= sizeof(tmpbuf
);
3846 if ((r
= pkinit_prompt_user(context
, cctx
, &reply
, prompt
, 0)) != 0 )
3853 * reply.length needs to be reset to length of tmpbuf before calling
3856 reply
.length
= sizeof(tmpbuf
);
3857 if ((r
= pkinit_prompt_user(context
, cctx
, &reply
, prompt
, 0)) != 0 )
3860 if (reply
.length
== 0) {
3863 char *cp
= reply
.data
;
3864 /* reply better be digits */
3865 while (*cp
!= '\0') {
3866 if (!isdigit(*cp
++))
3870 tmpchoice
= (int) strtol(reply
.data
, (char **)NULL
, 10);
3875 switch (tmpchoice
) {
3876 case CHOOSE_THIS_TOKEN
:
3877 *choice
= i
; /* chosen entry of token_choices->token_array */
3880 *choice
= RESCAN_TOKENS
; /* rescan for new smartcard */
3883 *choice
= SKIP_TOKENS
; /* skip smartcard auth */
3885 case CHOOSE_SEE_NEXT
: /* see next smartcard */
3896 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3899 * Note, this isn't the best solution to providing a function to check the
3900 * certs in a token however I wanted to avoid rewriting a bunch of code so I
3901 * settled for some duplication of processing.
3903 static krb5_error_code
3904 check_load_certs(krb5_context context
,
3905 CK_SESSION_HANDLE session
,
3906 pkinit_plg_crypto_context plg_cryptoctx
,
3907 pkinit_req_crypto_context req_cryptoctx
,
3908 pkinit_identity_crypto_context id_cryptoctx
,
3909 krb5_principal princ
,
3913 CK_OBJECT_CLASS cls
;
3914 CK_OBJECT_HANDLE obj
;
3915 CK_ATTRIBUTE attrs
[4];
3917 CK_CERTIFICATE_TYPE certtype
;
3918 CK_BYTE_PTR cert
= NULL
, cert_id
= NULL
;
3919 const unsigned char *cp
;
3921 unsigned int nattrs
;
3924 cls
= CKO_CERTIFICATE
;
3925 attrs
[0].type
= CKA_CLASS
;
3926 attrs
[0].pValue
= &cls
;
3927 attrs
[0].ulValueLen
= sizeof cls
;
3929 certtype
= CKC_X_509
;
3930 attrs
[1].type
= CKA_CERTIFICATE_TYPE
;
3931 attrs
[1].pValue
= &certtype
;
3932 attrs
[1].ulValueLen
= sizeof certtype
;
3936 /* If a cert id and/or label were given, use them too */
3937 if (id_cryptoctx
->cert_id_len
> 0) {
3938 attrs
[nattrs
].type
= CKA_ID
;
3939 attrs
[nattrs
].pValue
= id_cryptoctx
->cert_id
;
3940 attrs
[nattrs
].ulValueLen
= id_cryptoctx
->cert_id_len
;
3943 if (id_cryptoctx
->cert_label
!= NULL
) {
3944 attrs
[nattrs
].type
= CKA_LABEL
;
3945 attrs
[nattrs
].pValue
= id_cryptoctx
->cert_label
;
3946 attrs
[nattrs
].ulValueLen
= strlen(id_cryptoctx
->cert_label
);
3950 r
= id_cryptoctx
->p11
->C_FindObjectsInit(session
, attrs
, nattrs
);
3952 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r
));
3953 krb5_set_error_message(context
, EINVAL
,
3954 gettext("PKCS11 error from C_FindObjectsInit: %s"),
3955 pkinit_pkcs11_code_to_text(r
));
3960 for (i
= 0; ; i
++) {
3961 if (i
>= MAX_CREDS_ALLOWED
) {
3966 /* Look for x.509 cert */
3967 /* Solaris Kerberos */
3968 if ((r
= id_cryptoctx
->p11
->C_FindObjects(session
, &obj
, 1, &count
))
3969 != CKR_OK
|| count
== 0) {
3970 id_cryptoctx
->creds
[i
] = NULL
;
3974 /* Get cert and id len */
3975 attrs
[0].type
= CKA_VALUE
;
3976 attrs
[0].pValue
= NULL
;
3977 attrs
[0].ulValueLen
= 0;
3979 attrs
[1].type
= CKA_ID
;
3980 attrs
[1].pValue
= NULL
;
3981 attrs
[1].ulValueLen
= 0;
3983 if ((r
= id_cryptoctx
->p11
->C_GetAttributeValue(session
,
3987 r
!= CKR_BUFFER_TOO_SMALL
) {
3988 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r
));
3989 krb5_set_error_message(context
, EINVAL
,
3990 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
3991 pkinit_pkcs11_code_to_text(r
));
3995 cert
= malloc((size_t) attrs
[0].ulValueLen
+ 1);
4000 cert_id
= malloc((size_t) attrs
[1].ulValueLen
+ 1);
4001 if (cert_id
== NULL
) {
4006 /* Read the cert and id off the card */
4008 attrs
[0].type
= CKA_VALUE
;
4009 attrs
[0].pValue
= cert
;
4011 attrs
[1].type
= CKA_ID
;
4012 attrs
[1].pValue
= cert_id
;
4014 if ((r
= id_cryptoctx
->p11
->C_GetAttributeValue(session
,
4015 obj
, attrs
, 2)) != CKR_OK
) {
4016 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r
));
4017 krb5_set_error_message(context
, EINVAL
,
4018 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
4019 pkinit_pkcs11_code_to_text(r
));
4024 pkiDebug("cert %d size %d id %d idlen %d\n", i
,
4025 (int) attrs
[0].ulValueLen
, (int) cert_id
[0],
4026 (int) attrs
[1].ulValueLen
);
4028 cp
= (unsigned char *) cert
;
4029 x
= d2i_X509(NULL
, &cp
, (int) attrs
[0].ulValueLen
);
4035 id_cryptoctx
->creds
[i
] = malloc(sizeof(struct _pkinit_cred_info
));
4036 if (id_cryptoctx
->creds
[i
] == NULL
) {
4040 id_cryptoctx
->creds
[i
]->cert
= x
;
4041 id_cryptoctx
->creds
[i
]->key
= NULL
;
4042 id_cryptoctx
->creds
[i
]->cert_id
= cert_id
;
4044 id_cryptoctx
->creds
[i
]->cert_id_len
= attrs
[1].ulValueLen
;
4048 id_cryptoctx
->p11
->C_FindObjectsFinal(session
);
4050 if (id_cryptoctx
->creds
[0] == NULL
|| id_cryptoctx
->creds
[0]->cert
== NULL
) {
4052 } else if (do_matching
){
4054 * Do not let pkinit_cert_matching set the primary cert in id_cryptoctx
4055 * as this will be done later.
4057 r
= pkinit_cert_matching(context
, plg_cryptoctx
, req_cryptoctx
,
4058 id_cryptoctx
, princ
, FALSE
);
4062 if ((r
!= 0 || !load_cert
) &&
4063 id_cryptoctx
->creds
[0] != NULL
&&
4064 id_cryptoctx
->creds
[0]->cert
!= NULL
) {
4066 * If there's an error or load_cert isn't 1 free all the certs loaded
4067 * onto id_cryptoctx.
4069 (void) crypto_free_cert_info(context
, plg_cryptoctx
, req_cryptoctx
,
4083 * Solaris Kerberos: this function has been significantly modified to prompt
4084 * the user in certain cases so defer to this version when resyncing MIT code.
4086 * pkinit_open_session now does several things including prompting the user if
4087 * do_matching is set which indicates the code is executing in a client
4088 * context. This function fills out a pkinit_identity_crypto_context with a
4089 * set of certs and a open session if a token can be found that matches all
4090 * supplied criteria. If no token is found then the user is prompted one time
4091 * to insert their token. If there is more than one token that matches all
4092 * client criteria the user is prompted to make a choice if in client context.
4093 * If do_matching is false (KDC context) then the first token matching all
4094 * server criteria is chosen.
4096 static krb5_error_code
4097 pkinit_open_session(krb5_context context
,
4098 pkinit_plg_crypto_context plg_cryptoctx
,
4099 pkinit_req_crypto_context req_cryptoctx
,
4100 pkinit_identity_crypto_context cctx
,
4101 krb5_principal princ
,
4106 CK_SLOT_ID_PTR slotlist
= NULL
, tmpslotlist
= NULL
;
4107 CK_TOKEN_INFO tinfo
;
4108 krb5_boolean tokenmatch
= FALSE
;
4109 CK_SESSION_HANDLE tmpsession
= CK_INVALID_HANDLE
;
4110 struct _token_choices token_choices
;
4113 if (cctx
->session
!= CK_INVALID_HANDLE
)
4114 return 0; /* session already open */
4117 if (cctx
->p11_module
== NULL
) {
4119 pkinit_C_LoadModule(cctx
->p11_module_name
, &cctx
->p11
);
4120 if (cctx
->p11_module
== NULL
)
4121 return KRB5KDC_ERR_PREAUTH_FAILED
;
4125 /* Solaris Kerberos: Don't fail if cryptoki is already initialized */
4126 r
= cctx
->p11
->C_Initialize(NULL
);
4127 if (r
!= CKR_OK
&& r
!= CKR_CRYPTOKI_ALREADY_INITIALIZED
) {
4128 pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r
));
4129 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4130 gettext("Error from PKCS11 C_Initialize: %s"),
4131 pkinit_pkcs11_code_to_text(r
));
4132 return KRB5KDC_ERR_PREAUTH_FAILED
;
4135 (void) memset(&token_choices
, 0, sizeof(token_choices
));
4139 * If C_Initialize was already called by the process before the pkinit
4140 * module was loaded then record that fact.
4141 * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether
4142 * or not C_Finalize() should be called.
4144 cctx
->finalize_pkcs11
=
4145 (r
== CKR_CRYPTOKI_ALREADY_INITIALIZED
? FALSE
: TRUE
);
4147 * First make sure that is an applicable slot otherwise fail.
4149 * Start by getting a count of all slots with or without tokens.
4152 if ((r
= cctx
->p11
->C_GetSlotList(FALSE
, NULL
, &count
)) != CKR_OK
) {
4153 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
4154 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4155 gettext("Error trying to get PKCS11 slot list: %s"),
4156 pkinit_pkcs11_code_to_text(r
));
4157 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4162 /* There are no slots so bail */
4163 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4164 krb5_set_error_message(context
, r
,
4165 gettext("No PKCS11 slots found"));
4166 pkiDebug("pkinit_open_session: no slots, count: %d\n", count
);
4168 } else if (cctx
->slotid
!= PK_NOSLOT
) {
4169 /* See if any of the slots match the specified slotID */
4170 tmpslotlist
= malloc(count
* sizeof (CK_SLOT_ID
));
4171 if (tmpslotlist
== NULL
) {
4172 krb5_set_error_message(context
, ENOMEM
,
4173 gettext("Memory allocation error:"));
4174 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4177 if ((r
= cctx
->p11
->C_GetSlotList(FALSE
, tmpslotlist
, &count
)) != CKR_OK
) {
4178 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4179 gettext("Error trying to get PKCS11 slot list: %s"),
4180 pkinit_pkcs11_code_to_text(r
));
4181 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
4182 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4186 for (i
= 0; i
< count
&& cctx
->slotid
!= tmpslotlist
[i
]; i
++)
4190 /* no slots match */
4191 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4192 krb5_set_error_message(context
, r
,
4193 gettext("Requested PKCS11 slot ID %d not found"),
4195 pkiDebug("open_session: no matching slot found for slotID %d\n",
4202 /* get count of slots that have tokens */
4203 if ((r
= cctx
->p11
->C_GetSlotList(TRUE
, NULL
, &count
)) != CKR_OK
) {
4204 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
4205 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4206 gettext("Error trying to get PKCS11 slot list: %s"),
4207 pkinit_pkcs11_code_to_text(r
));
4208 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4214 * Note, never prompt if !do_matching as this implies KDC side
4217 if (!(cctx
->p11flags
& C_PROMPTED_USER
) && do_matching
) {
4218 /* found slot(s) but no token so prompt and try again */
4219 if ((r
= pkinit_prompt_token(context
, cctx
)) == 0) {
4220 cctx
->p11flags
|= C_PROMPTED_USER
;
4223 pkiDebug("open_session: prompt for token/smart card failed\n");
4224 krb5_set_error_message(context
, r
,
4225 gettext("Prompt for token/smart card failed"));
4226 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4231 /* already prompted once so bailing */
4232 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4233 krb5_set_error_message(context
, r
,
4234 gettext("No smart card tokens found"));
4235 pkiDebug("pkinit_open_session: no token, already prompted\n");
4240 if (slotlist
!= NULL
)
4243 slotlist
= malloc(count
* sizeof (CK_SLOT_ID
));
4244 if (slotlist
== NULL
) {
4245 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4246 gettext("Memory allocation error"));
4247 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4251 * Solaris Kerberos: get list of PKCS11 slotid's that have tokens.
4253 if (cctx
->p11
->C_GetSlotList(TRUE
, slotlist
, &count
) != CKR_OK
) {
4254 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4255 gettext("Error trying to get PKCS11 slot list: %s"),
4256 pkinit_pkcs11_code_to_text(r
));
4257 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
4258 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4262 token_choices
.numtokens
= 0;
4263 token_choices
.token_array
= malloc(count
* sizeof (*token_choices
.token_array
));
4264 if (token_choices
.token_array
== NULL
) {
4265 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4266 krb5_set_error_message(context
, r
,
4267 gettext("Memory allocation error"));
4271 /* examine all the tokens */
4272 for (i
= 0; i
< count
; i
++) {
4274 * Solaris Kerberos: if a slotid was specified skip slots that don't
4277 if (cctx
->slotid
!= PK_NOSLOT
&& cctx
->slotid
!= slotlist
[i
])
4281 if ((r
= cctx
->p11
->C_OpenSession(slotlist
[i
], CKF_SERIAL_SESSION
,
4282 NULL
, NULL
, &tmpsession
)) != CKR_OK
) {
4283 pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r
));
4284 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4285 gettext("Error trying to open PKCS11 session: %s"),
4286 pkinit_pkcs11_code_to_text(r
));
4287 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4291 /* Get token info */
4292 if ((r
= cctx
->p11
->C_GetTokenInfo(slotlist
[i
], &tinfo
)) != CKR_OK
) {
4293 pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r
));
4294 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4295 gettext("Error trying to read PKCS11 token: %s"),
4296 pkinit_pkcs11_code_to_text(r
));
4297 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4298 cctx
->p11
->C_CloseSession(tmpsession
);
4302 if (cctx
->token_label
== NULL
) {
4304 * If the token doesn't require login to examine the certs then
4305 * let's check the certs out to see if any match the criteria if
4308 if (!(tinfo
.flags
& CKF_LOGIN_REQUIRED
)) {
4310 * It's okay to check the certs if we don't have to login but
4311 * don't load the certs onto cctx at this point, this will be
4312 * done later in this function for the chosen token.
4314 if ((r
= check_load_certs(context
, tmpsession
, plg_cryptoctx
,
4315 req_cryptoctx
, cctx
, princ
,
4316 do_matching
, 0)) == 0) {
4318 } else if (r
!= ENOENT
){
4319 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4320 cctx
->p11
->C_CloseSession(tmpsession
);
4323 /* ignore ENOENT here */
4330 /* + 1 so tokenlabelstr can be \0 terminated */
4331 char tokenlabelstr
[sizeof (tinfo
.label
) + 1];
4334 * Convert token label into C string with trailing white space
4337 trim_token_label(&tinfo
, tokenlabelstr
, sizeof (tokenlabelstr
));
4339 pkiDebug("open_session: slotid %d token found: \"%s\", "
4340 "cctx->token_label: \"%s\"\n",
4341 slotlist
[i
], tokenlabelstr
, (char *) cctx
->token_label
);
4343 if (!strcmp(cctx
->token_label
, tokenlabelstr
)) {
4344 if (!(tinfo
.flags
& CKF_LOGIN_REQUIRED
)) {
4346 * It's okay to check the certs if we don't have to login but
4347 * don't load the certs onto cctx at this point, this will be
4348 * done later in this function for the chosen token.
4350 if ((r
= check_load_certs(context
, tmpsession
, plg_cryptoctx
,
4351 req_cryptoctx
, cctx
, princ
,
4352 do_matching
, 0)) == 0) {
4354 } else if (r
!= ENOENT
){
4355 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4356 cctx
->p11
->C_CloseSession(tmpsession
);
4359 /* ignore ENOENT here */
4368 if (tokenmatch
== TRUE
) {
4369 /* add the token to token_choices.token_array */
4370 token_choices
.token_array
[token_choices
.numtokens
].slotID
= slotlist
[i
];
4371 token_choices
.token_array
[token_choices
.numtokens
].session
= tmpsession
;
4372 token_choices
.token_array
[token_choices
.numtokens
].token_info
= tinfo
;
4373 token_choices
.numtokens
++;
4374 /* !do_matching implies we take the first matching token */
4380 cctx
->p11
->C_CloseSession(tmpsession
);
4384 if (token_choices
.numtokens
== 0) {
4386 * Solaris Kerberos: prompt for token one time if there was no token
4387 * and do_matching is 1 (see earlier comment about do_matching).
4389 if (!(cctx
->p11flags
& C_PROMPTED_USER
) && do_matching
) {
4390 if ((r
= pkinit_prompt_token(context
, cctx
)) == 0) {
4391 cctx
->p11flags
|= C_PROMPTED_USER
;
4394 pkiDebug("open_session: prompt for token/smart card failed\n");
4395 krb5_set_error_message(context
, r
,
4396 gettext("Prompt for token/smart card failed"));
4397 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4401 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4402 krb5_set_error_message(context
, r
,
4403 gettext("No smart card tokens found"));
4404 pkiDebug("open_session: no matching token found\n");
4407 } else if (token_choices
.numtokens
== 1) {
4408 if ((token_choices
.token_array
[0].token_info
.flags
& CKF_LOGIN_REQUIRED
) &&
4409 !(cctx
->p11flags
& C_PROMPTED_USER
) &&
4411 if ((r
= pkinit_choose_tokens(context
, cctx
, &token_choices
, &choice
)) != 0) {
4412 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r
);
4413 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4414 krb5_set_error_message(context
, r
,
4415 gettext("Prompt for token/smart card failed"));
4418 if (choice
== RESCAN_TOKENS
) {
4419 /* rescan for new smartcard/token */
4420 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4421 /* close all sessions */
4422 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4424 free(token_choices
.token_array
);
4425 token_choices
.token_array
= NULL
;
4426 token_choices
.numtokens
= 0;
4428 } else if (choice
== SKIP_TOKENS
) {
4429 /* do not use smartcard/token for auth */
4430 cctx
->p11flags
|= (C_PROMPTED_USER
|C_SKIP_PKCS11_AUTH
);
4431 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4434 cctx
->p11flags
|= C_PROMPTED_USER
;
4437 choice
= 0; /* really the only choice is the first token_array entry */
4439 } else if (!(cctx
->p11flags
& C_PROMPTED_USER
) && do_matching
) {
4440 /* > 1 token so present menu of token choices, let the user decide. */
4441 if ((r
= pkinit_choose_tokens(context
, cctx
, &token_choices
, &choice
)) != 0) {
4442 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r
);
4443 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4444 krb5_set_error_message(context
, r
,
4445 gettext("Prompt for token/smart card failed"));
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
);
4454 free(token_choices
.token_array
);
4455 token_choices
.token_array
= NULL
;
4456 token_choices
.numtokens
= 0;
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
;
4464 cctx
->p11flags
|= C_PROMPTED_USER
;
4467 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4471 cctx
->slotid
= token_choices
.token_array
[choice
].slotID
;
4472 cctx
->session
= token_choices
.token_array
[choice
].session
;
4474 pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx
->slotid
,
4475 i
+ 1, (int) count
);
4477 /* Login if needed */
4478 /* Solaris Kerberos: added cctx->p11flags check */
4479 if ((token_choices
.token_array
[choice
].token_info
.flags
& CKF_LOGIN_REQUIRED
) &&
4480 !(cctx
->p11flags
& C_LOGIN_DONE
)) {
4481 r
= pkinit_login(context
, cctx
, &token_choices
.token_array
[choice
].token_info
);
4485 /* Doing this again to load the certs into cctx. */
4486 r
= check_load_certs(context
, cctx
->session
, plg_cryptoctx
,
4487 req_cryptoctx
, cctx
, princ
, do_matching
, 1);
4491 if (slotlist
!= NULL
)
4494 if (tmpslotlist
!= NULL
)
4497 if (token_choices
.token_array
!= NULL
) {
4499 /* close all sessions if there's an error */
4500 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4501 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4503 cctx
->session
= CK_INVALID_HANDLE
;
4505 /* close sessions not chosen */
4506 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4508 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4512 free(token_choices
.token_array
);
4519 * Look for a key that's:
4521 * 2. capable of the specified operation (usually signing or decrypting)
4522 * 3. RSA (this may be wrong but it's all we can do for now)
4523 * 4. matches the id of the cert we chose
4525 * You must call pkinit_get_certs before calling pkinit_find_private_key
4526 * (that's because we need the ID of the private key)
4528 * pkcs11 says the id of the key doesn't have to match that of the cert, but
4529 * I can't figure out any other way to decide which key to use.
4531 * We should only find one key that fits all the requirements.
4532 * If there are more than one, we just take the first one.
4537 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx
,
4538 CK_ATTRIBUTE_TYPE usage
,
4539 CK_OBJECT_HANDLE
*objp
)
4541 CK_OBJECT_CLASS cls
;
4542 CK_ATTRIBUTE attrs
[4];
4544 CK_KEY_TYPE keytype
;
4546 unsigned int nattrs
= 0;
4548 #ifdef PKINIT_USE_KEY_USAGE
4549 CK_BBOOL true_false
;
4552 cls
= CKO_PRIVATE_KEY
;
4553 attrs
[nattrs
].type
= CKA_CLASS
;
4554 attrs
[nattrs
].pValue
= &cls
;
4555 attrs
[nattrs
].ulValueLen
= sizeof cls
;
4558 #ifdef PKINIT_USE_KEY_USAGE
4560 * Some cards get confused if you try to specify a key usage,
4561 * so don't, and hope for the best. This will fail if you have
4562 * several keys with the same id and different usages but I have
4563 * not seen this on real cards.
4566 attrs
[nattrs
].type
= usage
;
4567 attrs
[nattrs
].pValue
= &true_false
;
4568 attrs
[nattrs
].ulValueLen
= sizeof true_false
;
4573 attrs
[nattrs
].type
= CKA_KEY_TYPE
;
4574 attrs
[nattrs
].pValue
= &keytype
;
4575 attrs
[nattrs
].ulValueLen
= sizeof keytype
;
4578 attrs
[nattrs
].type
= CKA_ID
;
4579 attrs
[nattrs
].pValue
= id_cryptoctx
->cert_id
;
4580 attrs
[nattrs
].ulValueLen
= id_cryptoctx
->cert_id_len
;
4583 r
= id_cryptoctx
->p11
->C_FindObjectsInit(id_cryptoctx
->session
, attrs
, nattrs
);
4585 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4586 pkinit_pkcs11_code_to_text(r
));
4587 return KRB5KDC_ERR_PREAUTH_FAILED
;
4590 r
= id_cryptoctx
->p11
->C_FindObjects(id_cryptoctx
->session
, objp
, 1, &count
);
4591 id_cryptoctx
->p11
->C_FindObjectsFinal(id_cryptoctx
->session
);
4592 pkiDebug("found %d private keys (%s)\n", (int) count
, pkinit_pkcs11_code_to_text(r
));
4596 * The CKA_ID may not be correctly set for the private key. For e.g. when
4597 * storing a private key in softtoken pktool(1) doesn't generate or store
4598 * a CKA_ID for the private key. Another way to identify the private key is
4599 * to look for a private key with the same RSA modulus as the public key
4600 * in the certificate.
4602 if (r
== CKR_OK
&& count
!= 1) {
4608 unsigned char *n_bytes
;
4610 cert
= sk_X509_value(id_cryptoctx
->my_certs
, 0);
4611 priv
= X509_get_pubkey(cert
);
4613 pkiDebug("Failed to extract pub key from cert\n");
4614 return KRB5KDC_ERR_PREAUTH_FAILED
;
4618 cls
= CKO_PRIVATE_KEY
;
4619 attrs
[nattrs
].type
= CKA_CLASS
;
4620 attrs
[nattrs
].pValue
= &cls
;
4621 attrs
[nattrs
].ulValueLen
= sizeof cls
;
4624 #ifdef PKINIT_USE_KEY_USAGE
4626 attrs
[nattrs
].type
= usage
;
4627 attrs
[nattrs
].pValue
= &true_false
;
4628 attrs
[nattrs
].ulValueLen
= sizeof true_false
;
4633 attrs
[nattrs
].type
= CKA_KEY_TYPE
;
4634 attrs
[nattrs
].pValue
= &keytype
;
4635 attrs
[nattrs
].ulValueLen
= sizeof keytype
;
4638 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
4639 rsa
= priv
->pkey
.rsa
;
4641 n_len
= BN_num_bytes(rsan
);
4643 rsa
= EVP_PKEY_get0_RSA(priv
);
4644 RSA_get0_key(rsa
, &rsan
, NULL
, NULL
);
4645 n_len
= RSA_size(rsa
);
4647 n_bytes
= (unsigned char *) malloc((size_t) n_len
);
4648 if (n_bytes
== NULL
) {
4652 if (BN_bn2bin(rsan
, n_bytes
) == 0) {
4654 pkiDebug("zero-byte key modulus\n");
4655 return KRB5KDC_ERR_PREAUTH_FAILED
;
4658 attrs
[nattrs
].type
= CKA_MODULUS
;
4659 attrs
[nattrs
].ulValueLen
= n_len
;
4660 attrs
[nattrs
].pValue
= n_bytes
;
4664 r
= id_cryptoctx
->p11
->C_FindObjectsInit(id_cryptoctx
->session
, attrs
, nattrs
);
4667 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4668 pkinit_pkcs11_code_to_text(r
));
4669 return KRB5KDC_ERR_PREAUTH_FAILED
;
4672 r
= id_cryptoctx
->p11
->C_FindObjects(id_cryptoctx
->session
, objp
, 1, &count
);
4673 id_cryptoctx
->p11
->C_FindObjectsFinal(id_cryptoctx
->session
);
4674 pkiDebug("found %d private keys (%s)\n", (int) count
, pkinit_pkcs11_code_to_text(r
));
4678 if (r
!= CKR_OK
|| count
< 1)
4679 return KRB5KDC_ERR_PREAUTH_FAILED
;
4685 static krb5_error_code
4686 pkinit_decode_data_fs(krb5_context context
,
4687 pkinit_identity_crypto_context id_cryptoctx
,
4688 unsigned char *data
,
4689 unsigned int data_len
,
4690 unsigned char **decoded_data
,
4691 unsigned int *decoded_data_len
)
4693 if (decode_data(decoded_data
, decoded_data_len
, data
, data_len
,
4694 id_cryptoctx
->my_key
, sk_X509_value(id_cryptoctx
->my_certs
,
4695 id_cryptoctx
->cert_index
)) <= 0) {
4696 pkiDebug("failed to decode data\n");
4697 return KRB5KDC_ERR_PREAUTH_FAILED
;
4702 #ifndef WITHOUT_PKCS11
4705 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx
,
4706 CK_BYTE_PTR pEncryptedData
,
4707 CK_ULONG ulEncryptedDataLen
,
4709 CK_ULONG_PTR pulDataLen
)
4713 rv
= id_cryptoctx
->p11
->C_Decrypt(id_cryptoctx
->session
, pEncryptedData
,
4714 ulEncryptedDataLen
, pData
, pulDataLen
);
4716 pkiDebug("pData %x *pulDataLen %d\n", (int) pData
, (int) *pulDataLen
);
4722 static krb5_error_code
4723 pkinit_decode_data_pkcs11(krb5_context context
,
4724 pkinit_identity_crypto_context id_cryptoctx
,
4725 unsigned char *data
,
4726 unsigned int data_len
,
4727 unsigned char **decoded_data
,
4728 unsigned int *decoded_data_len
)
4730 CK_OBJECT_HANDLE obj
;
4737 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4740 assert(id_cryptoctx
->p11
!= NULL
);
4742 /* Solaris Kerberos: Login, if needed, to access private object */
4743 if (!(id_cryptoctx
->p11flags
& C_LOGIN_DONE
)) {
4744 CK_TOKEN_INFO tinfo
;
4746 r
= id_cryptoctx
->p11
->C_GetTokenInfo(id_cryptoctx
->slotid
, &tinfo
);
4750 r
= pkinit_login(context
, id_cryptoctx
, &tinfo
);
4755 r
= pkinit_find_private_key(id_cryptoctx
, CKA_DECRYPT
, &obj
);
4759 mech
.mechanism
= CKM_RSA_PKCS
;
4760 mech
.pParameter
= NULL
;
4761 mech
.ulParameterLen
= 0;
4763 if ((r
= id_cryptoctx
->p11
->C_DecryptInit(id_cryptoctx
->session
, &mech
,
4765 pkiDebug("C_DecryptInit: 0x%x\n", (int) r
);
4766 return KRB5KDC_ERR_PREAUTH_FAILED
;
4768 pkiDebug("data_len = %d\n", data_len
);
4769 cp
= (unsigned char *)malloc((size_t) data_len
);
4774 pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n",
4775 (int) id_cryptoctx
->session
, (int) data
, (int) data_len
, (int) cp
,
4776 (int) &len
, (int) len
);
4777 if ((r
= pkinit_C_Decrypt(id_cryptoctx
, data
, (CK_ULONG
) data_len
,
4778 cp
, &len
)) != CKR_OK
) {
4780 if ((r
= id_cryptoctx
->p11
->C_Decrypt(id_cryptoctx
->session
, data
,
4781 (CK_ULONG
) data_len
, cp
, &len
)) != CKR_OK
) {
4783 pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r
));
4784 if (r
== CKR_BUFFER_TOO_SMALL
)
4785 pkiDebug("decrypt %d needs %d\n", (int) data_len
, (int) len
);
4786 return KRB5KDC_ERR_PREAUTH_FAILED
;
4788 pkiDebug("decrypt %d -> %d\n", (int) data_len
, (int) len
);
4789 *decoded_data_len
= len
;
4797 pkinit_decode_data(krb5_context context
,
4798 pkinit_identity_crypto_context id_cryptoctx
,
4799 unsigned char *data
,
4800 unsigned int data_len
,
4801 unsigned char **decoded_data
,
4802 unsigned int *decoded_data_len
)
4804 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
4806 if (id_cryptoctx
->pkcs11_method
!= 1)
4807 retval
= pkinit_decode_data_fs(context
, id_cryptoctx
, data
, data_len
,
4808 decoded_data
, decoded_data_len
);
4809 #ifndef WITHOUT_PKCS11
4811 retval
= pkinit_decode_data_pkcs11(context
, id_cryptoctx
, data
,
4812 data_len
, decoded_data
, decoded_data_len
);
4819 static krb5_error_code
4820 pkinit_sign_data_fs(krb5_context context
,
4821 pkinit_identity_crypto_context id_cryptoctx
,
4822 unsigned char *data
,
4823 unsigned int data_len
,
4824 unsigned char **sig
,
4825 unsigned int *sig_len
)
4827 if (create_signature(sig
, sig_len
, data
, data_len
,
4828 id_cryptoctx
->my_key
) != 0) {
4829 pkiDebug("failed to create the signature\n");
4830 return KRB5KDC_ERR_PREAUTH_FAILED
;
4835 #ifndef WITHOUT_PKCS11
4836 static krb5_error_code
4837 pkinit_sign_data_pkcs11(krb5_context context
,
4838 pkinit_identity_crypto_context id_cryptoctx
,
4839 unsigned char *data
,
4840 unsigned int data_len
,
4841 unsigned char **sig
,
4842 unsigned int *sig_len
)
4844 CK_OBJECT_HANDLE obj
;
4851 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4854 assert(id_cryptoctx
->p11
!= NULL
);
4856 /* Solaris Kerberos: Login, if needed, to access private object */
4857 if (!(id_cryptoctx
->p11flags
& C_LOGIN_DONE
)) {
4858 CK_TOKEN_INFO tinfo
;
4860 r
= id_cryptoctx
->p11
->C_GetTokenInfo(id_cryptoctx
->slotid
, &tinfo
);
4864 r
= pkinit_login(context
, id_cryptoctx
, &tinfo
);
4869 r
= pkinit_find_private_key(id_cryptoctx
, CKA_SIGN
, &obj
);
4873 mech
.mechanism
= id_cryptoctx
->mech
;
4874 mech
.pParameter
= NULL
;
4875 mech
.ulParameterLen
= 0;
4877 if ((r
= id_cryptoctx
->p11
->C_SignInit(id_cryptoctx
->session
, &mech
,
4879 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r
));
4880 return KRB5KDC_ERR_PREAUTH_FAILED
;
4884 * Key len would give an upper bound on sig size, but there's no way to
4885 * get that. So guess, and if it's too small, re-malloc.
4887 len
= PK_SIGLEN_GUESS
;
4888 cp
= (unsigned char *)malloc((size_t) len
);
4892 r
= id_cryptoctx
->p11
->C_Sign(id_cryptoctx
->session
, data
,
4893 (CK_ULONG
) data_len
, cp
, &len
);
4894 if (r
== CKR_BUFFER_TOO_SMALL
|| (r
== CKR_OK
&& len
>= PK_SIGLEN_GUESS
)) {
4896 pkiDebug("C_Sign realloc %d\n", (int) len
);
4897 cp
= (unsigned char *)malloc((size_t) len
);
4898 r
= id_cryptoctx
->p11
->C_Sign(id_cryptoctx
->session
, data
,
4899 (CK_ULONG
) data_len
, cp
, &len
);
4902 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r
));
4903 return KRB5KDC_ERR_PREAUTH_FAILED
;
4905 pkiDebug("sign %d -> %d\n", (int) data_len
, (int) len
);
4914 pkinit_sign_data(krb5_context context
,
4915 pkinit_identity_crypto_context id_cryptoctx
,
4916 unsigned char *data
,
4917 unsigned int data_len
,
4918 unsigned char **sig
,
4919 unsigned int *sig_len
)
4921 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
4923 if (id_cryptoctx
== NULL
|| id_cryptoctx
->pkcs11_method
!= 1)
4924 retval
= pkinit_sign_data_fs(context
, id_cryptoctx
, data
, data_len
,
4926 #ifndef WITHOUT_PKCS11
4928 retval
= pkinit_sign_data_pkcs11(context
, id_cryptoctx
, data
, data_len
,
4936 static krb5_error_code
4937 decode_data(unsigned char **out_data
, unsigned int *out_data_len
,
4938 unsigned char *data
, unsigned int data_len
,
4939 EVP_PKEY
*pkey
, X509
*cert
)
4941 /* Solaris Kerberos */
4943 unsigned char *buf
= NULL
;
4946 /* Solaris Kerberos */
4947 if (out_data
== NULL
|| out_data_len
== NULL
)
4950 if (cert
&& !X509_check_private_key(cert
, pkey
)) {
4951 pkiDebug("private key does not match certificate\n");
4952 /* Solaris Kerberos */
4956 buf_len
= EVP_PKEY_size(pkey
);
4957 buf
= (unsigned char *)malloc((size_t) buf_len
+ 10);
4961 len
= EVP_PKEY_decrypt_old(buf
, data
, (int)data_len
, pkey
);
4963 pkiDebug("unable to decrypt received data (len=%d)\n", data_len
);
4964 /* Solaris Kerberos */
4966 return KRB5KRB_ERR_GENERIC
;
4969 *out_data_len
= len
;
4974 static krb5_error_code
4975 create_signature(unsigned char **sig
, unsigned int *sig_len
,
4976 unsigned char *data
, unsigned int data_len
, EVP_PKEY
*pkey
)
4978 krb5_error_code retval
= ENOMEM
;
4982 /* Solaris Kerberos */
4985 if ((md_ctx
= EVP_MD_CTX_new()) == NULL
)
4988 EVP_VerifyInit(md_ctx
, EVP_sha1());
4989 EVP_SignUpdate(md_ctx
, data
, data_len
);
4990 *sig_len
= EVP_PKEY_size(pkey
);
4991 if ((*sig
= (unsigned char *) malloc((size_t) *sig_len
)) == NULL
)
4993 EVP_SignFinal(md_ctx
, *sig
, sig_len
, pkey
);
4998 EVP_MD_CTX_free(md_ctx
);
5005 * This is not the routine the KDC uses to get its certificate.
5006 * This routine is intended to be called by the client
5007 * to obtain the KDC's certificate from some local storage
5008 * to be sent as a hint in its request to the KDC.
5012 pkinit_get_kdc_cert(krb5_context context
,
5013 pkinit_plg_crypto_context plg_cryptoctx
,
5014 pkinit_req_crypto_context req_cryptoctx
,
5015 pkinit_identity_crypto_context id_cryptoctx
,
5016 krb5_principal princ
)
5018 /* Solaris Kerberos */
5019 if (req_cryptoctx
== NULL
)
5022 req_cryptoctx
->received_cert
= NULL
;
5027 static krb5_error_code
5028 pkinit_get_certs_pkcs12(krb5_context context
,
5029 pkinit_plg_crypto_context plg_cryptoctx
,
5030 pkinit_req_crypto_context req_cryptoctx
,
5031 pkinit_identity_opts
*idopts
,
5032 pkinit_identity_crypto_context id_cryptoctx
,
5033 krb5_principal princ
)
5035 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
5042 if (idopts
->cert_filename
== NULL
) {
5043 /* Solaris Kerberos: Improved error messages */
5044 krb5_set_error_message(context
, retval
,
5045 gettext("Failed to get certificate location"));
5046 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__
);
5050 if (idopts
->key_filename
== NULL
) {
5051 /* Solaris Kerberos: Improved error messages */
5052 krb5_set_error_message(context
, retval
,
5053 gettext("Failed to get private key location"));
5054 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__
);
5058 fp
= fopen(idopts
->cert_filename
, "rb");
5060 /* Solaris Kerberos: Improved error messages */
5061 krb5_set_error_message(context
, retval
,
5062 gettext("Failed to open PKCS12 file '%s': %s"),
5063 idopts
->cert_filename
, error_message(errno
));
5064 pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
5065 idopts
->cert_filename
, errno
);
5069 p12
= d2i_PKCS12_fp(fp
, NULL
);
5072 krb5_set_error_message(context
, retval
,
5073 gettext("Failed to decode PKCS12 file '%s' contents"),
5074 idopts
->cert_filename
);
5075 pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
5076 idopts
->cert_filename
);
5080 * Try parsing with no pass phrase first. If that fails,
5081 * prompt for the pass phrase and try again.
5083 ret
= PKCS12_parse(p12
, NULL
, &y
, &x
, NULL
);
5086 krb5_prompt kprompt
;
5087 krb5_prompt_type prompt_type
;
5089 char prompt_string
[128];
5090 char prompt_reply
[128];
5091 /* Solaris Kerberos */
5092 char *prompt_prefix
= gettext("Pass phrase for");
5094 pkiDebug("Initial PKCS12_parse with no password failed\n");
5096 if (id_cryptoctx
->PIN
!= NULL
) {
5097 /* Solaris Kerberos: use PIN if set */
5098 rdat
.data
= id_cryptoctx
->PIN
;
5099 /* note rdat.length isn't needed in this case */
5101 (void) memset(prompt_reply
, '\0', sizeof(prompt_reply
));
5102 rdat
.data
= prompt_reply
;
5103 rdat
.length
= sizeof(prompt_reply
);
5105 r
= snprintf(prompt_string
, sizeof(prompt_string
), "%s %s",
5106 prompt_prefix
, idopts
->cert_filename
);
5107 if (r
>= sizeof(prompt_string
)) {
5108 pkiDebug("Prompt string, '%s %s', is too long!\n",
5109 prompt_prefix
, idopts
->cert_filename
);
5112 kprompt
.prompt
= prompt_string
;
5114 kprompt
.reply
= &rdat
;
5115 prompt_type
= KRB5_PROMPT_TYPE_PREAUTH
;
5117 /* PROMPTER_INVOCATION */
5118 k5int_set_prompt_types(context
, &prompt_type
);
5119 r
= (*id_cryptoctx
->prompter
)(context
, id_cryptoctx
->prompter_data
,
5120 NULL
, NULL
, 1, &kprompt
);
5121 k5int_set_prompt_types(context
, NULL
);
5124 ret
= PKCS12_parse(p12
, rdat
.data
, &y
, &x
, NULL
);
5126 /* Solaris Kerberos: Improved error messages */
5127 krb5_set_error_message(context
, retval
,
5128 gettext("Failed to parse PKCS12 file '%s' with password"),
5129 idopts
->cert_filename
);
5130 pkiDebug("Seconde PKCS12_parse with password failed\n");
5134 id_cryptoctx
->creds
[0] = malloc(sizeof(struct _pkinit_cred_info
));
5135 if (id_cryptoctx
->creds
[0] == NULL
)
5137 id_cryptoctx
->creds
[0]->cert
= x
;
5138 #ifndef WITHOUT_PKCS11
5139 id_cryptoctx
->creds
[0]->cert_id
= NULL
;
5140 id_cryptoctx
->creds
[0]->cert_id_len
= 0;
5142 id_cryptoctx
->creds
[0]->key
= y
;
5143 id_cryptoctx
->creds
[1] = NULL
;
5159 static krb5_error_code
5160 pkinit_load_fs_cert_and_key(krb5_context context
,
5161 pkinit_identity_crypto_context id_cryptoctx
,
5166 krb5_error_code retval
;
5170 /* load the certificate */
5171 retval
= get_cert(certname
, &x
);
5172 if (retval
!= 0 || x
== NULL
) {
5173 /* Solaris Kerberos: Improved error messages */
5174 krb5_set_error_message(context
, retval
,
5175 gettext("Failed to load user's certificate from %s: %s"),
5176 certname
, error_message(retval
));
5177 pkiDebug("failed to load user's certificate from '%s'\n", certname
);
5180 retval
= get_key(keyname
, &y
);
5181 if (retval
!= 0 || y
== NULL
) {
5182 /* Solaris Kerberos: Improved error messages */
5183 krb5_set_error_message(context
, retval
,
5184 gettext("Failed to load user's private key from %s: %s"),
5185 keyname
, error_message(retval
));
5186 pkiDebug("failed to load user's private key from '%s'\n", keyname
);
5190 id_cryptoctx
->creds
[cindex
] = malloc(sizeof(struct _pkinit_cred_info
));
5191 if (id_cryptoctx
->creds
[cindex
] == NULL
) {
5195 id_cryptoctx
->creds
[cindex
]->cert
= x
;
5196 #ifndef WITHOUT_PKCS11
5197 id_cryptoctx
->creds
[cindex
]->cert_id
= NULL
;
5198 id_cryptoctx
->creds
[cindex
]->cert_id_len
= 0;
5200 id_cryptoctx
->creds
[cindex
]->key
= y
;
5201 id_cryptoctx
->creds
[cindex
+1] = NULL
;
5216 static krb5_error_code
5217 pkinit_get_certs_fs(krb5_context context
,
5218 pkinit_plg_crypto_context plg_cryptoctx
,
5219 pkinit_req_crypto_context req_cryptoctx
,
5220 pkinit_identity_opts
*idopts
,
5221 pkinit_identity_crypto_context id_cryptoctx
,
5222 krb5_principal princ
)
5224 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
5226 if (idopts
->cert_filename
== NULL
) {
5227 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__
);
5231 if (idopts
->key_filename
== NULL
) {
5232 pkiDebug("%s: failed to get user's private key location\n",
5237 retval
= pkinit_load_fs_cert_and_key(context
, id_cryptoctx
,
5238 idopts
->cert_filename
,
5239 idopts
->key_filename
, 0);
5245 static krb5_error_code
5246 pkinit_get_certs_dir(krb5_context context
,
5247 pkinit_plg_crypto_context plg_cryptoctx
,
5248 pkinit_req_crypto_context req_cryptoctx
,
5249 pkinit_identity_opts
*idopts
,
5250 pkinit_identity_crypto_context id_cryptoctx
,
5251 krb5_principal princ
)
5253 /* Solaris Kerberos */
5254 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
5256 struct dirent
*dentry
= NULL
;
5257 char certname
[1024];
5260 char *dirname
, *suf
;
5262 /* Solaris Kerberos */
5266 if (idopts
->cert_filename
== NULL
) {
5267 pkiDebug("%s: failed to get user's certificate directory location\n",
5272 dirname
= idopts
->cert_filename
;
5273 d
= opendir(dirname
);
5275 /* Solaris Kerberos: Improved error messages */
5276 krb5_set_error_message(context
, errno
,
5277 gettext("Failed to open directory \"%s\": %s"),
5278 dirname
, error_message(errno
));
5283 * We'll assume that certs are named XXX.crt and the corresponding
5284 * key is named XXX.key
5286 while ((i
< MAX_CREDS_ALLOWED
) && (dentry
= readdir(d
)) != NULL
) {
5287 /* Ignore subdirectories and anything starting with a dot */
5289 if (dentry
->d_type
== DT_DIR
)
5292 if (dentry
->d_name
[0] == '.')
5294 len
= strlen(dentry
->d_name
);
5297 suf
= dentry
->d_name
+ (len
- 4);
5298 if (strncmp(suf
, ".crt", 4) != 0)
5301 /* Checked length */
5302 if (strlen(dirname
) + strlen(dentry
->d_name
) + 2 > sizeof(certname
)) {
5303 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
5304 __FUNCTION__
, dirname
, dentry
->d_name
);
5307 (void) snprintf(certname
, sizeof(certname
), "%s/%s", dirname
, dentry
->d_name
);
5308 (void) snprintf(keyname
, sizeof(keyname
), "%s/%s", dirname
, dentry
->d_name
);
5309 len
= strlen(keyname
);
5310 keyname
[len
- 3] = 'k';
5311 keyname
[len
- 2] = 'e';
5312 keyname
[len
- 1] = 'y';
5314 retval
= pkinit_load_fs_cert_and_key(context
, id_cryptoctx
,
5315 certname
, keyname
, i
);
5317 pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
5318 __FUNCTION__
, dentry
->d_name
);
5326 /* Solaris Kerberos: Improved error messages */
5327 krb5_set_error_message(context
, ENOENT
,
5328 gettext("No suitable cert/key pairs found in directory '%s'"),
5329 idopts
->cert_filename
);
5330 pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
5331 __FUNCTION__
, idopts
->cert_filename
);
5345 #ifndef WITHOUT_PKCS11
5347 static krb5_error_code
5348 pkinit_get_certs_pkcs11(krb5_context context
,
5349 pkinit_plg_crypto_context plg_cryptoctx
,
5350 pkinit_req_crypto_context req_cryptoctx
,
5351 pkinit_identity_opts
*idopts
,
5352 pkinit_identity_crypto_context id_cryptoctx
,
5353 krb5_principal princ
,
5356 #ifdef PKINIT_USE_MECH_LIST
5357 CK_MECHANISM_TYPE_PTR mechp
= NULL
;
5358 CK_MECHANISM_INFO info
;
5361 if (id_cryptoctx
->p11flags
& C_SKIP_PKCS11_AUTH
)
5362 return KRB5KDC_ERR_PREAUTH_FAILED
;
5364 /* Copy stuff from idopts -> id_cryptoctx */
5365 if (idopts
->p11_module_name
!= NULL
) {
5366 id_cryptoctx
->p11_module_name
= strdup(idopts
->p11_module_name
);
5367 if (id_cryptoctx
->p11_module_name
== NULL
)
5370 if (idopts
->token_label
!= NULL
) {
5371 id_cryptoctx
->token_label
= strdup(idopts
->token_label
);
5372 if (id_cryptoctx
->token_label
== NULL
)
5375 if (idopts
->cert_label
!= NULL
) {
5376 id_cryptoctx
->cert_label
= strdup(idopts
->cert_label
);
5377 if (id_cryptoctx
->cert_label
== NULL
)
5380 if (idopts
->PIN
!= NULL
) {
5381 id_cryptoctx
->PIN
= strdup(idopts
->PIN
);
5382 if (id_cryptoctx
->PIN
== NULL
)
5385 /* Convert the ascii cert_id string into a binary blob */
5388 * If the cert_id_string is empty then behave in a similar way to how
5389 * an empty certlabel is treated - i.e. don't fail now but rather continue
5390 * as though the certid wasn't specified.
5392 if (idopts
->cert_id_string
!= NULL
&& strlen(idopts
->cert_id_string
) != 0) {
5394 BN_hex2bn(&bn
, idopts
->cert_id_string
);
5397 id_cryptoctx
->cert_id_len
= BN_num_bytes(bn
);
5398 id_cryptoctx
->cert_id
= malloc((size_t) id_cryptoctx
->cert_id_len
);
5399 if (id_cryptoctx
->cert_id
== NULL
) {
5403 BN_bn2bin(bn
, id_cryptoctx
->cert_id
);
5406 id_cryptoctx
->slotid
= idopts
->slotid
;
5407 id_cryptoctx
->pkcs11_method
= 1;
5409 #ifndef PKINIT_USE_MECH_LIST
5411 * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
5412 * many cards seems to be confused about whether they are capable of
5413 * this or not. The safe thing seems to be to ignore the mechanism list,
5414 * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
5417 id_cryptoctx
->mech
= CKM_RSA_PKCS
;
5419 if ((r
= id_cryptoctx
->p11
->C_GetMechanismList(id_cryptoctx
->slotid
, NULL
,
5420 &count
)) != CKR_OK
|| count
<= 0) {
5421 pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r
));
5422 return KRB5KDC_ERR_PREAUTH_FAILED
;
5424 mechp
= (CK_MECHANISM_TYPE_PTR
) malloc(count
* sizeof (CK_MECHANISM_TYPE
));
5427 if ((r
= id_cryptoctx
->p11
->C_GetMechanismList(id_cryptoctx
->slotid
,
5428 mechp
, &count
)) != CKR_OK
) {
5430 return KRB5KDC_ERR_PREAUTH_FAILED
;
5432 for (i
= 0; i
< count
; i
++) {
5433 if ((r
= id_cryptoctx
->p11
->C_GetMechanismInfo(id_cryptoctx
->slotid
,
5434 mechp
[i
], &info
)) != CKR_OK
) {
5436 return KRB5KDC_ERR_PREAUTH_FAILED
;
5438 #ifdef DEBUG_MECHINFO
5439 pkiDebug("mech %x flags %x\n", (int) mechp
[i
], (int) info
.flags
);
5440 if ((info
.flags
& (CKF_SIGN
|CKF_DECRYPT
)) == (CKF_SIGN
|CKF_DECRYPT
))
5441 pkiDebug(" this mech is good for sign & decrypt\n");
5443 if (mechp
[i
] == CKM_RSA_PKCS
) {
5444 /* This seems backwards... */
5445 id_cryptoctx
->mech
=
5446 (info
.flags
& CKF_SIGN
) ? CKM_SHA1_RSA_PKCS
: CKM_RSA_PKCS
;
5451 pkiDebug("got %d mechs from card\n", (int) count
);
5454 return (pkinit_open_session(context
, plg_cryptoctx
, req_cryptoctx
,
5455 id_cryptoctx
, princ
, do_matching
));
5461 free_cred_info(krb5_context context
,
5462 pkinit_identity_crypto_context id_cryptoctx
,
5463 struct _pkinit_cred_info
*cred
)
5466 if (cred
->cert
!= NULL
)
5467 X509_free(cred
->cert
);
5468 if (cred
->key
!= NULL
)
5469 EVP_PKEY_free(cred
->key
);
5470 #ifndef WITHOUT_PKCS11
5471 if (cred
->cert_id
!= NULL
)
5472 free(cred
->cert_id
);
5480 crypto_free_cert_info(krb5_context context
,
5481 pkinit_plg_crypto_context plg_cryptoctx
,
5482 pkinit_req_crypto_context req_cryptoctx
,
5483 pkinit_identity_crypto_context id_cryptoctx
)
5487 if (id_cryptoctx
== NULL
)
5490 for (i
= 0; i
< MAX_CREDS_ALLOWED
; i
++) {
5491 if (id_cryptoctx
->creds
[i
] != NULL
) {
5492 free_cred_info(context
, id_cryptoctx
, id_cryptoctx
->creds
[i
]);
5493 id_cryptoctx
->creds
[i
] = NULL
;
5500 crypto_load_certs(krb5_context context
,
5501 pkinit_plg_crypto_context plg_cryptoctx
,
5502 pkinit_req_crypto_context req_cryptoctx
,
5503 pkinit_identity_opts
*idopts
,
5504 pkinit_identity_crypto_context id_cryptoctx
,
5505 krb5_principal princ
,
5508 krb5_error_code retval
;
5510 switch(idopts
->idtype
) {
5512 retval
= pkinit_get_certs_fs(context
, plg_cryptoctx
,
5513 req_cryptoctx
, idopts
,
5514 id_cryptoctx
, princ
);
5517 retval
= pkinit_get_certs_dir(context
, plg_cryptoctx
,
5518 req_cryptoctx
, idopts
,
5519 id_cryptoctx
, princ
);
5521 #ifndef WITHOUT_PKCS11
5523 retval
= pkinit_get_certs_pkcs11(context
, plg_cryptoctx
,
5524 req_cryptoctx
, idopts
,
5525 id_cryptoctx
, princ
, do_matching
);
5529 retval
= pkinit_get_certs_pkcs12(context
, plg_cryptoctx
,
5530 req_cryptoctx
, idopts
,
5531 id_cryptoctx
, princ
);
5536 /* Solaris Kerberos */
5542 * Get number of certificates available after crypto_load_certs()
5546 crypto_cert_get_count(krb5_context context
,
5547 pkinit_plg_crypto_context plg_cryptoctx
,
5548 pkinit_req_crypto_context req_cryptoctx
,
5549 pkinit_identity_crypto_context id_cryptoctx
,
5554 if (id_cryptoctx
== NULL
|| id_cryptoctx
->creds
[0] == NULL
)
5558 count
<= MAX_CREDS_ALLOWED
&& id_cryptoctx
->creds
[count
] != NULL
;
5560 *cert_count
= count
;
5566 * Begin iteration over the certs loaded in crypto_load_certs()
5570 crypto_cert_iteration_begin(krb5_context context
,
5571 pkinit_plg_crypto_context plg_cryptoctx
,
5572 pkinit_req_crypto_context req_cryptoctx
,
5573 pkinit_identity_crypto_context id_cryptoctx
,
5574 pkinit_cert_iter_handle
*ih_ret
)
5576 struct _pkinit_cert_iter_data
*id
;
5578 if (id_cryptoctx
== NULL
|| ih_ret
== NULL
)
5580 if (id_cryptoctx
->creds
[0] == NULL
) /* No cred info available */
5583 id
= calloc(1, sizeof(*id
));
5586 id
->magic
= ITER_MAGIC
;
5587 id
->plgctx
= plg_cryptoctx
,
5588 id
->reqctx
= req_cryptoctx
,
5589 id
->idctx
= id_cryptoctx
;
5591 *ih_ret
= (pkinit_cert_iter_handle
) id
;
5596 * End iteration over the certs loaded in crypto_load_certs()
5600 crypto_cert_iteration_end(krb5_context context
,
5601 pkinit_cert_iter_handle ih
)
5603 struct _pkinit_cert_iter_data
*id
= (struct _pkinit_cert_iter_data
*)ih
;
5605 if (id
== NULL
|| id
->magic
!= ITER_MAGIC
)
5612 * Get next certificate handle
5616 crypto_cert_iteration_next(krb5_context context
,
5617 pkinit_cert_iter_handle ih
,
5618 pkinit_cert_handle
*ch_ret
)
5620 struct _pkinit_cert_iter_data
*id
= (struct _pkinit_cert_iter_data
*)ih
;
5621 struct _pkinit_cert_data
*cd
;
5622 pkinit_identity_crypto_context id_cryptoctx
;
5624 if (id
== NULL
|| id
->magic
!= ITER_MAGIC
)
5630 id_cryptoctx
= id
->idctx
;
5631 if (id_cryptoctx
== NULL
)
5634 if (id_cryptoctx
->creds
[id
->index
] == NULL
)
5635 return PKINIT_ITER_NO_MORE
;
5637 cd
= calloc(1, sizeof(*cd
));
5641 cd
->magic
= CERT_MAGIC
;
5642 cd
->plgctx
= id
->plgctx
;
5643 cd
->reqctx
= id
->reqctx
;
5644 cd
->idctx
= id
->idctx
;
5645 cd
->index
= id
->index
;
5646 cd
->cred
= id_cryptoctx
->creds
[id
->index
++];
5647 *ch_ret
= (pkinit_cert_handle
)cd
;
5652 * Release cert handle
5656 crypto_cert_release(krb5_context context
,
5657 pkinit_cert_handle ch
)
5659 struct _pkinit_cert_data
*cd
= (struct _pkinit_cert_data
*)ch
;
5660 if (cd
== NULL
|| cd
->magic
!= CERT_MAGIC
)
5667 * Get certificate Key Usage and Extended Key Usage
5670 static krb5_error_code
5671 crypto_retieve_X509_key_usage(krb5_context context
,
5672 pkinit_plg_crypto_context plgcctx
,
5673 pkinit_req_crypto_context reqcctx
,
5675 unsigned int *ret_ku_bits
,
5676 unsigned int *ret_eku_bits
)
5678 /* Solaris Kerberos */
5680 unsigned int eku_bits
= 0, ku_bits
= 0;
5681 ASN1_BIT_STRING
*usage
= NULL
;
5683 if (ret_ku_bits
== NULL
&& ret_eku_bits
== NULL
)
5689 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__
);
5693 /* Start with Extended Key usage */
5694 i
= X509_get_ext_by_NID(x
, NID_ext_key_usage
, -1);
5696 EXTENDED_KEY_USAGE
*eku
;
5698 eku
= X509_get_ext_d2i(x
, NID_ext_key_usage
, NULL
, NULL
);
5700 for (i
= 0; i
< sk_ASN1_OBJECT_num(eku
); i
++) {
5701 ASN1_OBJECT
*certoid
;
5702 certoid
= sk_ASN1_OBJECT_value(eku
, i
);
5703 if ((OBJ_cmp(certoid
, plgcctx
->id_pkinit_KPClientAuth
)) == 0)
5704 eku_bits
|= PKINIT_EKU_PKINIT
;
5705 else if ((OBJ_cmp(certoid
, OBJ_nid2obj(NID_ms_smartcard_login
))) == 0)
5706 eku_bits
|= PKINIT_EKU_MSSCLOGIN
;
5707 else if ((OBJ_cmp(certoid
, OBJ_nid2obj(NID_client_auth
))) == 0)
5708 eku_bits
|= PKINIT_EKU_CLIENTAUTH
;
5709 else if ((OBJ_cmp(certoid
, OBJ_nid2obj(NID_email_protect
))) == 0)
5710 eku_bits
|= PKINIT_EKU_EMAILPROTECTION
;
5712 EXTENDED_KEY_USAGE_free(eku
);
5715 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__
, eku_bits
);
5716 *ret_eku_bits
= eku_bits
;
5719 /* Now the Key Usage bits */
5723 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__
);
5727 /* Make sure usage exists before checking bits */
5728 usage
= X509_get_ext_d2i(x
, NID_key_usage
, NULL
, NULL
);
5730 if (!ku_reject(x
, X509v3_KU_DIGITAL_SIGNATURE
))
5731 ku_bits
|= PKINIT_KU_DIGITALSIGNATURE
;
5732 if (!ku_reject(x
, X509v3_KU_KEY_ENCIPHERMENT
))
5733 ku_bits
|= PKINIT_KU_KEYENCIPHERMENT
;
5734 ASN1_BIT_STRING_free(usage
);
5737 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__
, ku_bits
);
5738 *ret_ku_bits
= ku_bits
;
5745 * Return a string format of an X509_NAME in buf where
5746 * size is an in/out parameter. On input it is the size
5747 * of the buffer, and on output it is the actual length
5749 * If buf is NULL, returns the length req'd to hold name
5752 X509_NAME_oneline_ex(X509_NAME
* a
,
5759 out
= BIO_new(BIO_s_mem ());
5760 if (X509_NAME_print_ex(out
, a
, 0, flag
) > 0) {
5761 if (buf
!= NULL
&& *size
> (int) BIO_number_written(out
)) {
5762 (void) memset(buf
, 0, *size
);
5763 BIO_read(out
, buf
, (int) BIO_number_written(out
));
5766 *size
= BIO_number_written(out
);
5774 * Get certificate information
5777 crypto_cert_get_matching_data(krb5_context context
,
5778 pkinit_cert_handle ch
,
5779 pkinit_cert_matching_data
**ret_md
)
5781 krb5_error_code retval
;
5782 pkinit_cert_matching_data
*md
;
5783 krb5_principal
*pkinit_sans
=NULL
, *upn_sans
= NULL
;
5784 struct _pkinit_cert_data
*cd
= (struct _pkinit_cert_data
*)ch
;
5786 char buf
[DN_BUF_LEN
];
5787 unsigned int bufsize
= sizeof(buf
);
5789 if (cd
== NULL
|| cd
->magic
!= CERT_MAGIC
)
5794 md
= calloc(1, sizeof(*md
));
5800 /* get the subject name (in rfc2253 format) */
5801 X509_NAME_oneline_ex(X509_get_subject_name(cd
->cred
->cert
),
5802 buf
, &bufsize
, XN_FLAG_SEP_COMMA_PLUS
);
5803 md
->subject_dn
= strdup(buf
);
5804 if (md
->subject_dn
== NULL
) {
5809 /* get the issuer name (in rfc2253 format) */
5810 X509_NAME_oneline_ex(X509_get_issuer_name(cd
->cred
->cert
),
5811 buf
, &bufsize
, XN_FLAG_SEP_COMMA_PLUS
);
5812 md
->issuer_dn
= strdup(buf
);
5813 if (md
->issuer_dn
== NULL
) {
5818 /* get the san data */
5819 retval
= crypto_retrieve_X509_sans(context
, cd
->plgctx
, cd
->reqctx
,
5820 cd
->cred
->cert
, &pkinit_sans
,
5826 if (pkinit_sans
!= NULL
) {
5827 for (i
= 0; pkinit_sans
[i
] != NULL
; i
++)
5830 if (upn_sans
!= NULL
) {
5831 for (i
= 0; upn_sans
[i
] != NULL
; i
++)
5835 md
->sans
= calloc((size_t)j
+1, sizeof(*md
->sans
));
5836 if (md
->sans
== NULL
) {
5841 if (pkinit_sans
!= NULL
) {
5842 for (i
= 0; pkinit_sans
[i
] != NULL
; i
++)
5843 md
->sans
[j
++] = pkinit_sans
[i
];
5846 if (upn_sans
!= NULL
) {
5847 for (i
= 0; upn_sans
[i
] != NULL
; i
++)
5848 md
->sans
[j
++] = upn_sans
[i
];
5855 /* get the KU and EKU data */
5857 retval
= crypto_retieve_X509_key_usage(context
, cd
->plgctx
, cd
->reqctx
,
5859 &md
->ku_bits
, &md
->eku_bits
);
5868 crypto_cert_free_matching_data(context
, md
);
5874 * Free certificate information
5877 crypto_cert_free_matching_data(krb5_context context
,
5878 pkinit_cert_matching_data
*md
)
5886 free(md
->subject_dn
);
5888 free(md
->issuer_dn
);
5890 for (i
= 0, p
= md
->sans
[i
]; p
!= NULL
; p
= md
->sans
[++i
])
5891 krb5_free_principal(context
, p
);
5899 * Make this matching certificate "the chosen one"
5903 crypto_cert_select(krb5_context context
,
5904 pkinit_cert_matching_data
*md
)
5906 struct _pkinit_cert_data
*cd
;
5910 cd
= (struct _pkinit_cert_data
*)md
->ch
;
5911 if (cd
== NULL
|| cd
->magic
!= CERT_MAGIC
)
5914 /* copy the selected cert into our id_cryptoctx */
5915 if (cd
->idctx
->my_certs
!= NULL
) {
5916 sk_X509_pop_free(cd
->idctx
->my_certs
, X509_free
);
5918 cd
->idctx
->my_certs
= sk_X509_new_null();
5919 sk_X509_push(cd
->idctx
->my_certs
, cd
->cred
->cert
);
5920 cd
->idctx
->creds
[cd
->index
]->cert
= NULL
; /* Don't free it twice */
5921 cd
->idctx
->cert_index
= 0;
5923 if (cd
->idctx
->pkcs11_method
!= 1) {
5924 cd
->idctx
->my_key
= cd
->cred
->key
;
5925 cd
->idctx
->creds
[cd
->index
]->key
= NULL
; /* Don't free it twice */
5927 #ifndef WITHOUT_PKCS11
5929 cd
->idctx
->cert_id
= cd
->cred
->cert_id
;
5930 cd
->idctx
->creds
[cd
->index
]->cert_id
= NULL
; /* Don't free it twice */
5931 cd
->idctx
->cert_id_len
= cd
->cred
->cert_id_len
;
5938 * Choose the default certificate as "the chosen one"
5941 crypto_cert_select_default(krb5_context context
,
5942 pkinit_plg_crypto_context plg_cryptoctx
,
5943 pkinit_req_crypto_context req_cryptoctx
,
5944 pkinit_identity_crypto_context id_cryptoctx
)
5946 krb5_error_code retval
;
5949 retval
= crypto_cert_get_count(context
, plg_cryptoctx
, req_cryptoctx
,
5950 id_cryptoctx
, &cert_count
);
5952 pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
5953 __FUNCTION__
, retval
, error_message(retval
));
5956 if (cert_count
!= 1) {
5957 /* Solaris Kerberos: Improved error messages */
5959 krb5_set_error_message(context
, retval
,
5960 gettext("Failed to select default certificate: "
5961 "found %d certs to choose from but there must be exactly one"),
5963 pkiDebug("%s: ERROR: There are %d certs to choose from, "
5964 "but there must be exactly one.\n",
5965 __FUNCTION__
, cert_count
);
5968 /* copy the selected cert into our id_cryptoctx */
5969 if (id_cryptoctx
->my_certs
!= NULL
) {
5970 sk_X509_pop_free(id_cryptoctx
->my_certs
, X509_free
);
5972 id_cryptoctx
->my_certs
= sk_X509_new_null();
5973 sk_X509_push(id_cryptoctx
->my_certs
, id_cryptoctx
->creds
[0]->cert
);
5974 id_cryptoctx
->creds
[0]->cert
= NULL
; /* Don't free it twice */
5975 id_cryptoctx
->cert_index
= 0;
5977 if (id_cryptoctx
->pkcs11_method
!= 1) {
5978 id_cryptoctx
->my_key
= id_cryptoctx
->creds
[0]->key
;
5979 id_cryptoctx
->creds
[0]->key
= NULL
; /* Don't free it twice */
5981 #ifndef WITHOUT_PKCS11
5983 id_cryptoctx
->cert_id
= id_cryptoctx
->creds
[0]->cert_id
;
5984 id_cryptoctx
->creds
[0]->cert_id
= NULL
; /* Don't free it twice */
5985 id_cryptoctx
->cert_id_len
= id_cryptoctx
->creds
[0]->cert_id_len
;
5995 static krb5_error_code
5996 load_cas_and_crls(krb5_context context
,
5997 pkinit_plg_crypto_context plg_cryptoctx
,
5998 pkinit_req_crypto_context req_cryptoctx
,
5999 pkinit_identity_crypto_context id_cryptoctx
,
6003 STACK_OF(X509_INFO
) *sk
= NULL
;
6004 STACK_OF(X509
) *ca_certs
= NULL
;
6005 STACK_OF(X509_CRL
) *ca_crls
= NULL
;
6007 /* Solaris Kerberos */
6008 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
6011 /* If there isn't already a stack in the context,
6012 * create a temporary one now */
6014 case CATYPE_ANCHORS
:
6015 if (id_cryptoctx
->trustedCAs
!= NULL
)
6016 ca_certs
= id_cryptoctx
->trustedCAs
;
6018 ca_certs
= sk_X509_new_null();
6019 if (ca_certs
== NULL
)
6023 case CATYPE_INTERMEDIATES
:
6024 if (id_cryptoctx
->intermediateCAs
!= NULL
)
6025 ca_certs
= id_cryptoctx
->intermediateCAs
;
6027 ca_certs
= sk_X509_new_null();
6028 if (ca_certs
== NULL
)
6033 if (id_cryptoctx
->revoked
!= NULL
)
6034 ca_crls
= id_cryptoctx
->revoked
;
6036 ca_crls
= sk_X509_CRL_new_null();
6037 if (ca_crls
== NULL
)
6045 if (!(in
= BIO_new_file(filename
, "r"))) {
6047 pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__
,
6048 filename
, error_message(errno
));
6052 /* This loads from a file, a stack of x509/crl/pkey sets */
6053 if ((sk
= PEM_X509_INFO_read_bio(in
, NULL
, NULL
, NULL
)) == NULL
) {
6054 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__
, filename
);
6059 /* scan over the stack created from loading the file contents,
6060 * weed out duplicates, and push new ones onto the return stack
6062 for (i
= 0; i
< sk_X509_INFO_num(sk
); i
++) {
6063 X509_INFO
*xi
= sk_X509_INFO_value(sk
, i
);
6064 if (xi
!= NULL
&& xi
->x509
!= NULL
&& catype
!= CATYPE_CRLS
) {
6065 int j
= 0, size
= sk_X509_num(ca_certs
), flag
= 0;
6068 sk_X509_push(ca_certs
, xi
->x509
);
6072 for (j
= 0; j
< size
; j
++) {
6073 X509
*x
= sk_X509_value(ca_certs
, j
);
6074 flag
= X509_cmp(x
, xi
->x509
);
6081 sk_X509_push(ca_certs
, X509_dup(xi
->x509
));
6083 } else if (xi
!= NULL
&& xi
->crl
!= NULL
&& catype
== CATYPE_CRLS
) {
6084 int j
= 0, size
= sk_X509_CRL_num(ca_crls
), flag
= 0;
6086 sk_X509_CRL_push(ca_crls
, xi
->crl
);
6090 for (j
= 0; j
< size
; j
++) {
6091 X509_CRL
*x
= sk_X509_CRL_value(ca_crls
, j
);
6092 flag
= X509_CRL_cmp(x
, xi
->crl
);
6099 sk_X509_CRL_push(ca_crls
, X509_CRL_dup(xi
->crl
));
6104 /* If we added something and there wasn't a stack in the
6105 * context before, add the temporary stack to the context.
6108 case CATYPE_ANCHORS
:
6109 if (sk_X509_num(ca_certs
) == 0) {
6110 pkiDebug("no anchors in file, %s\n", filename
);
6111 if (id_cryptoctx
->trustedCAs
== NULL
)
6112 sk_X509_free(ca_certs
);
6114 if (id_cryptoctx
->trustedCAs
== NULL
)
6115 id_cryptoctx
->trustedCAs
= ca_certs
;
6118 case CATYPE_INTERMEDIATES
:
6119 if (sk_X509_num(ca_certs
) == 0) {
6120 pkiDebug("no intermediates in file, %s\n", filename
);
6121 if (id_cryptoctx
->intermediateCAs
== NULL
)
6122 sk_X509_free(ca_certs
);
6124 if (id_cryptoctx
->intermediateCAs
== NULL
)
6125 id_cryptoctx
->intermediateCAs
= ca_certs
;
6129 if (sk_X509_CRL_num(ca_crls
) == 0) {
6130 pkiDebug("no crls in file, %s\n", filename
);
6131 if (id_cryptoctx
->revoked
== NULL
)
6132 sk_X509_CRL_free(ca_crls
);
6134 if (id_cryptoctx
->revoked
== NULL
)
6135 id_cryptoctx
->revoked
= ca_crls
;
6139 /* Should have been caught above! */
6142 /* Solaris Kerberos: removed "break" as it's never reached */
6151 sk_X509_INFO_pop_free(sk
, X509_INFO_free
);
6156 static krb5_error_code
6157 load_cas_and_crls_dir(krb5_context context
,
6158 pkinit_plg_crypto_context plg_cryptoctx
,
6159 pkinit_req_crypto_context req_cryptoctx
,
6160 pkinit_identity_crypto_context id_cryptoctx
,
6164 krb5_error_code retval
= EINVAL
;
6166 struct dirent
*dentry
= NULL
;
6167 char filename
[1024];
6169 if (dirname
== NULL
)
6172 d
= opendir(dirname
);
6176 while ((dentry
= readdir(d
))) {
6177 if (strlen(dirname
) + strlen(dentry
->d_name
) + 2 > sizeof(filename
)) {
6178 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
6179 __FUNCTION__
, dirname
, dentry
->d_name
);
6182 /* Ignore subdirectories and anything starting with a dot */
6184 if (dentry
->d_type
== DT_DIR
)
6187 if (dentry
->d_name
[0] == '.')
6189 (void) snprintf(filename
, sizeof(filename
), "%s/%s", dirname
, dentry
->d_name
);
6191 retval
= load_cas_and_crls(context
, plg_cryptoctx
, req_cryptoctx
,
6192 id_cryptoctx
, catype
, filename
);
6208 crypto_load_cas_and_crls(krb5_context context
,
6209 pkinit_plg_crypto_context plg_cryptoctx
,
6210 pkinit_req_crypto_context req_cryptoctx
,
6211 pkinit_identity_opts
*idopts
,
6212 pkinit_identity_crypto_context id_cryptoctx
,
6217 pkiDebug("%s: called with idtype %s and catype %s\n",
6218 __FUNCTION__
, idtype2string(idtype
), catype2string(catype
));
6219 /* Solaris Kerberos: Removed "break"'s as they are never reached */
6222 return load_cas_and_crls(context
, plg_cryptoctx
, req_cryptoctx
,
6223 id_cryptoctx
, catype
, id
);
6225 return load_cas_and_crls_dir(context
, plg_cryptoctx
, req_cryptoctx
,
6226 id_cryptoctx
, catype
, id
);
6232 static krb5_error_code
6233 create_identifiers_from_stack(STACK_OF(X509
) *sk
,
6234 krb5_external_principal_identifier
*** ids
)
6236 krb5_error_code retval
= ENOMEM
;
6237 int i
= 0, sk_size
= sk_X509_num(sk
);
6238 krb5_external_principal_identifier
**krb5_cas
= NULL
;
6240 X509_NAME
*xn
= NULL
;
6241 unsigned char *p
= NULL
;
6243 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6244 char buf
[DN_BUF_LEN
];
6249 malloc((sk_size
+ 1) * sizeof(krb5_external_principal_identifier
*));
6250 if (krb5_cas
== NULL
)
6252 krb5_cas
[sk_size
] = NULL
;
6254 for (i
= 0; i
< sk_size
; i
++) {
6255 krb5_cas
[i
] = (krb5_external_principal_identifier
*)malloc(sizeof(krb5_external_principal_identifier
));
6257 x
= sk_X509_value(sk
, i
);
6259 X509_NAME_oneline(X509_get_subject_name(x
), buf
, sizeof(buf
));
6260 pkiDebug("#%d cert= %s\n", i
, buf
);
6262 /* fill-in subjectName */
6263 krb5_cas
[i
]->subjectName
.magic
= 0;
6264 krb5_cas
[i
]->subjectName
.length
= 0;
6265 krb5_cas
[i
]->subjectName
.data
= NULL
;
6267 xn
= X509_get_subject_name(x
);
6268 len
= i2d_X509_NAME(xn
, NULL
);
6269 if ((p
= krb5_cas
[i
]->subjectName
.data
= (unsigned char *)malloc((size_t) len
)) == NULL
)
6271 i2d_X509_NAME(xn
, &p
);
6272 krb5_cas
[i
]->subjectName
.length
= len
;
6274 /* fill-in issuerAndSerialNumber */
6275 krb5_cas
[i
]->issuerAndSerialNumber
.length
= 0;
6276 krb5_cas
[i
]->issuerAndSerialNumber
.magic
= 0;
6277 krb5_cas
[i
]->issuerAndSerialNumber
.data
= NULL
;
6279 #ifdef LONGHORN_BETA_COMPAT
6280 if (longhorn
== 0) { /* XXX Longhorn doesn't like this */
6282 is
= PKCS7_ISSUER_AND_SERIAL_new();
6283 X509_NAME_set(&is
->issuer
, X509_get_issuer_name(x
));
6284 ASN1_INTEGER_free(is
->serial
);
6285 is
->serial
= ASN1_INTEGER_dup(X509_get_serialNumber(x
));
6286 len
= i2d_PKCS7_ISSUER_AND_SERIAL(is
, NULL
);
6287 if ((p
= krb5_cas
[i
]->issuerAndSerialNumber
.data
=
6288 (unsigned char *)malloc((size_t) len
)) == NULL
)
6290 i2d_PKCS7_ISSUER_AND_SERIAL(is
, &p
);
6291 krb5_cas
[i
]->issuerAndSerialNumber
.length
= len
;
6292 #ifdef LONGHORN_BETA_COMPAT
6296 /* fill-in subjectKeyIdentifier */
6297 krb5_cas
[i
]->subjectKeyIdentifier
.length
= 0;
6298 krb5_cas
[i
]->subjectKeyIdentifier
.magic
= 0;
6299 krb5_cas
[i
]->subjectKeyIdentifier
.data
= NULL
;
6302 #ifdef LONGHORN_BETA_COMPAT
6303 if (longhorn
== 0) { /* XXX Longhorn doesn't like this */
6305 if (X509_get_ext_by_NID(x
, NID_subject_key_identifier
, -1) >= 0) {
6306 ASN1_OCTET_STRING
*ikeyid
= NULL
;
6308 if ((ikeyid
= X509_get_ext_d2i(x
, NID_subject_key_identifier
, NULL
,
6310 len
= i2d_ASN1_OCTET_STRING(ikeyid
, NULL
);
6311 if ((p
= krb5_cas
[i
]->subjectKeyIdentifier
.data
=
6312 (unsigned char *)malloc((size_t) len
)) == NULL
)
6314 i2d_ASN1_OCTET_STRING(ikeyid
, &p
);
6315 krb5_cas
[i
]->subjectKeyIdentifier
.length
= len
;
6318 ASN1_OCTET_STRING_free(ikeyid
);
6320 #ifdef LONGHORN_BETA_COMPAT
6324 if (is
->issuer
!= NULL
)
6325 X509_NAME_free(is
->issuer
);
6326 if (is
->serial
!= NULL
)
6327 ASN1_INTEGER_free(is
->serial
);
6337 free_krb5_external_principal_identifier(&krb5_cas
);
6343 static krb5_error_code
6344 create_krb5_invalidCertificates(krb5_context context
,
6345 pkinit_plg_crypto_context plg_cryptoctx
,
6346 pkinit_req_crypto_context req_cryptoctx
,
6347 pkinit_identity_crypto_context id_cryptoctx
,
6348 krb5_external_principal_identifier
*** ids
)
6351 krb5_error_code retval
= ENOMEM
;
6352 STACK_OF(X509
) *sk
= NULL
;
6355 if (req_cryptoctx
->received_cert
== NULL
)
6356 return KRB5KDC_ERR_PREAUTH_FAILED
;
6358 sk
= sk_X509_new_null();
6361 sk_X509_push(sk
, req_cryptoctx
->received_cert
);
6363 retval
= create_identifiers_from_stack(sk
, ids
);
6373 create_krb5_supportedCMSTypes(krb5_context context
,
6374 pkinit_plg_crypto_context plg_cryptoctx
,
6375 pkinit_req_crypto_context req_cryptoctx
,
6376 pkinit_identity_crypto_context id_cryptoctx
,
6377 krb5_algorithm_identifier
***oids
)
6380 krb5_error_code retval
= ENOMEM
;
6381 krb5_algorithm_identifier
**loids
= NULL
;
6382 krb5_octet_data des3oid
= {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
6385 loids
= malloc(2 * sizeof(krb5_algorithm_identifier
*));
6389 loids
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
6390 if (loids
[0] == NULL
) {
6394 retval
= pkinit_copy_krb5_octet_data(&loids
[0]->algorithm
, &des3oid
);
6400 loids
[0]->parameters
.length
= 0;
6401 loids
[0]->parameters
.data
= NULL
;
6412 create_krb5_trustedCertifiers(krb5_context context
,
6413 pkinit_plg_crypto_context plg_cryptoctx
,
6414 pkinit_req_crypto_context req_cryptoctx
,
6415 pkinit_identity_crypto_context id_cryptoctx
,
6416 krb5_external_principal_identifier
*** ids
)
6419 /* Solaris Kerberos */
6420 STACK_OF(X509
) *sk
= id_cryptoctx
->trustedCAs
;
6423 if (id_cryptoctx
->trustedCAs
== NULL
)
6424 return KRB5KDC_ERR_PREAUTH_FAILED
;
6426 return create_identifiers_from_stack(sk
, ids
);
6432 create_krb5_trustedCas(krb5_context context
,
6433 pkinit_plg_crypto_context plg_cryptoctx
,
6434 pkinit_req_crypto_context req_cryptoctx
,
6435 pkinit_identity_crypto_context id_cryptoctx
,
6437 krb5_trusted_ca
*** ids
)
6439 krb5_error_code retval
= ENOMEM
;
6440 STACK_OF(X509
) *sk
= id_cryptoctx
->trustedCAs
;
6441 int i
= 0, len
= 0, sk_size
= sk_X509_num(sk
);
6442 krb5_trusted_ca
**krb5_cas
= NULL
;
6444 char buf
[DN_BUF_LEN
];
6445 X509_NAME
*xn
= NULL
;
6446 unsigned char *p
= NULL
;
6447 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6450 if (id_cryptoctx
->trustedCAs
== NULL
)
6451 return KRB5KDC_ERR_PREAUTH_FAILED
;
6453 krb5_cas
= malloc((sk_size
+ 1) * sizeof(krb5_trusted_ca
*));
6454 if (krb5_cas
== NULL
)
6456 krb5_cas
[sk_size
] = NULL
;
6458 for (i
= 0; i
< sk_size
; i
++) {
6459 krb5_cas
[i
] = (krb5_trusted_ca
*)malloc(sizeof(krb5_trusted_ca
));
6460 if (krb5_cas
[i
] == NULL
)
6462 x
= sk_X509_value(sk
, i
);
6464 X509_NAME_oneline(X509_get_subject_name(x
), buf
, sizeof(buf
));
6465 pkiDebug("#%d cert= %s\n", i
, buf
);
6468 case choice_trusted_cas_principalName
:
6469 krb5_cas
[i
]->choice
= choice_trusted_cas_principalName
;
6471 case choice_trusted_cas_caName
:
6472 krb5_cas
[i
]->choice
= choice_trusted_cas_caName
;
6473 krb5_cas
[i
]->u
.caName
.data
= NULL
;
6474 krb5_cas
[i
]->u
.caName
.length
= 0;
6475 xn
= X509_get_subject_name(x
);
6476 len
= i2d_X509_NAME(xn
, NULL
);
6477 if ((p
= krb5_cas
[i
]->u
.caName
.data
=
6478 (unsigned char *)malloc((size_t) len
)) == NULL
)
6480 i2d_X509_NAME(xn
, &p
);
6481 krb5_cas
[i
]->u
.caName
.length
= len
;
6483 case choice_trusted_cas_issuerAndSerial
:
6484 krb5_cas
[i
]->choice
= choice_trusted_cas_issuerAndSerial
;
6485 krb5_cas
[i
]->u
.issuerAndSerial
.data
= NULL
;
6486 krb5_cas
[i
]->u
.issuerAndSerial
.length
= 0;
6487 is
= PKCS7_ISSUER_AND_SERIAL_new();
6488 X509_NAME_set(&is
->issuer
, X509_get_issuer_name(x
));
6489 ASN1_INTEGER_free(is
->serial
);
6490 is
->serial
= ASN1_INTEGER_dup(X509_get_serialNumber(x
));
6491 len
= i2d_PKCS7_ISSUER_AND_SERIAL(is
, NULL
);
6492 if ((p
= krb5_cas
[i
]->u
.issuerAndSerial
.data
=
6493 (unsigned char *)malloc((size_t) len
)) == NULL
)
6495 i2d_PKCS7_ISSUER_AND_SERIAL(is
, &p
);
6496 krb5_cas
[i
]->u
.issuerAndSerial
.length
= len
;
6498 if (is
->issuer
!= NULL
)
6499 X509_NAME_free(is
->issuer
);
6500 if (is
->serial
!= NULL
)
6501 ASN1_INTEGER_free(is
->serial
);
6512 free_krb5_trusted_ca(&krb5_cas
);
6519 create_issuerAndSerial(krb5_context context
,
6520 pkinit_plg_crypto_context plg_cryptoctx
,
6521 pkinit_req_crypto_context req_cryptoctx
,
6522 pkinit_identity_crypto_context id_cryptoctx
,
6523 unsigned char **out
,
6524 unsigned int *out_len
)
6526 unsigned char *p
= NULL
;
6527 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6529 krb5_error_code retval
= ENOMEM
;
6530 X509
*cert
= req_cryptoctx
->received_cert
;
6534 if (req_cryptoctx
->received_cert
== NULL
)
6537 is
= PKCS7_ISSUER_AND_SERIAL_new();
6538 X509_NAME_set(&is
->issuer
, X509_get_issuer_name(cert
));
6539 ASN1_INTEGER_free(is
->serial
);
6540 is
->serial
= ASN1_INTEGER_dup(X509_get_serialNumber(cert
));
6541 len
= i2d_PKCS7_ISSUER_AND_SERIAL(is
, NULL
);
6542 if ((p
= *out
= (unsigned char *)malloc((size_t) len
)) == NULL
)
6544 i2d_PKCS7_ISSUER_AND_SERIAL(is
, &p
);
6549 X509_NAME_free(is
->issuer
);
6550 ASN1_INTEGER_free(is
->serial
);
6557 pkcs7_decrypt(krb5_context context
,
6558 pkinit_identity_crypto_context id_cryptoctx
,
6563 /* Solaris Kerberos */
6570 if(!PKCS7_type_is_enveloped(p7
)) {
6571 pkiDebug("wrong pkcs7 content type\n");
6575 if(!(tmpmem
= pkcs7_dataDecode(context
, id_cryptoctx
, p7
))) {
6576 pkiDebug("unable to decrypt pkcs7 object\n");
6579 /* Solaris Kerberos: Suppress sun studio compiler warning */
6580 #pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED)
6582 i
= BIO_read(tmpmem
, buf
, sizeof(buf
));
6584 BIO_write(data
, buf
, i
);
6585 BIO_free_all(tmpmem
);
6588 #pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED)
6594 pkinit_process_td_trusted_certifiers(
6595 krb5_context context
,
6596 pkinit_plg_crypto_context plg_cryptoctx
,
6597 pkinit_req_crypto_context req_cryptoctx
,
6598 pkinit_identity_crypto_context id_cryptoctx
,
6599 krb5_external_principal_identifier
**krb5_trusted_certifiers
,
6602 krb5_error_code retval
= ENOMEM
;
6603 STACK_OF(X509_NAME
) *sk_xn
= NULL
;
6604 X509_NAME
*xn
= NULL
;
6605 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6606 ASN1_OCTET_STRING
*id
= NULL
;
6607 const unsigned char *p
= NULL
;
6608 char buf
[DN_BUF_LEN
];
6611 if (td_type
== TD_TRUSTED_CERTIFIERS
)
6612 pkiDebug("received trusted certifiers\n");
6614 pkiDebug("received invalid certificate\n");
6616 sk_xn
= sk_X509_NAME_new_null();
6617 while(krb5_trusted_certifiers
[i
] != NULL
) {
6618 if (krb5_trusted_certifiers
[i
]->subjectName
.data
!= NULL
) {
6619 p
= krb5_trusted_certifiers
[i
]->subjectName
.data
;
6620 xn
= d2i_X509_NAME(NULL
, &p
,
6621 (int)krb5_trusted_certifiers
[i
]->subjectName
.length
);
6624 X509_NAME_oneline(xn
, buf
, sizeof(buf
));
6625 if (td_type
== TD_TRUSTED_CERTIFIERS
)
6626 pkiDebug("#%d cert = %s is trusted by kdc\n", i
, buf
);
6628 pkiDebug("#%d cert = %s is invalid\n", i
, buf
);
6629 sk_X509_NAME_push(sk_xn
, xn
);
6632 if (krb5_trusted_certifiers
[i
]->issuerAndSerialNumber
.data
!= NULL
) {
6633 p
= krb5_trusted_certifiers
[i
]->issuerAndSerialNumber
.data
;
6634 is
= d2i_PKCS7_ISSUER_AND_SERIAL(NULL
, &p
,
6635 (int)krb5_trusted_certifiers
[i
]->issuerAndSerialNumber
.length
);
6638 X509_NAME_oneline(is
->issuer
, buf
, sizeof(buf
));
6639 if (td_type
== TD_TRUSTED_CERTIFIERS
)
6640 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i
,
6641 buf
, ASN1_INTEGER_get(is
->serial
));
6643 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i
, buf
,
6644 ASN1_INTEGER_get(is
->serial
));
6645 PKCS7_ISSUER_AND_SERIAL_free(is
);
6648 if (krb5_trusted_certifiers
[i
]->subjectKeyIdentifier
.data
!= NULL
) {
6649 p
= krb5_trusted_certifiers
[i
]->subjectKeyIdentifier
.data
;
6650 id
= d2i_ASN1_OCTET_STRING(NULL
, &p
,
6651 (int)krb5_trusted_certifiers
[i
]->subjectKeyIdentifier
.length
);
6655 ASN1_OCTET_STRING_free(id
);
6659 /* XXX Since we not doing anything with received trusted certifiers
6660 * return an error. this is the place where we can pick a different
6661 * client certificate based on the information in td_trusted_certifiers
6663 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
6666 sk_X509_NAME_pop_free(sk_xn
, X509_NAME_free
);
6672 pkcs7_dataDecode(krb5_context context
,
6673 pkinit_identity_crypto_context id_cryptoctx
,
6677 unsigned int jj
= 0, tmp_len
= 0;
6678 BIO
*out
=NULL
,*etmp
=NULL
,*bio
=NULL
;
6679 unsigned char *tmp
=NULL
;
6680 ASN1_OCTET_STRING
*data_body
=NULL
;
6681 const EVP_CIPHER
*evp_cipher
=NULL
;
6682 EVP_CIPHER_CTX
*evp_ctx
=NULL
;
6683 X509_ALGOR
*enc_alg
=NULL
;
6684 STACK_OF(PKCS7_RECIP_INFO
) *rsk
=NULL
;
6685 /* Solaris Kerberos: Not used */
6687 X509_ALGOR
*xalg
=NULL
;
6689 PKCS7_RECIP_INFO
*ri
=NULL
;
6690 X509
*cert
= sk_X509_value(id_cryptoctx
->my_certs
,
6691 id_cryptoctx
->cert_index
);
6693 p7
->state
=PKCS7_S_HEADER
;
6695 rsk
=p7
->d
.enveloped
->recipientinfo
;
6696 enc_alg
=p7
->d
.enveloped
->enc_data
->algorithm
;
6697 data_body
=p7
->d
.enveloped
->enc_data
->enc_data
;
6698 evp_cipher
=EVP_get_cipherbyobj(enc_alg
->algorithm
);
6699 if (evp_cipher
== NULL
) {
6700 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,PKCS7_R_UNSUPPORTED_CIPHER_TYPE
);
6703 /* Solaris Kerberos: Not used */
6705 xalg
=p7
->d
.enveloped
->enc_data
->algorithm
;
6708 if ((etmp
=BIO_new(BIO_f_cipher())) == NULL
) {
6709 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,ERR_R_BIO_LIB
);
6713 /* It was encrypted, we need to decrypt the secret key
6714 * with the private key */
6716 /* Find the recipientInfo which matches the passed certificate
6721 for (i
=0; i
<sk_PKCS7_RECIP_INFO_num(rsk
); i
++) {
6723 ri
=sk_PKCS7_RECIP_INFO_value(rsk
,i
);
6724 tmp_ret
= X509_NAME_cmp(ri
->issuer_and_serial
->issuer
,
6725 X509_get_issuer_name(cert
));
6727 tmp_ret
= ASN1_INTEGER_cmp(X509_get_serialNumber(cert
),
6728 ri
->issuer_and_serial
->serial
);
6735 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,
6736 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE
);
6741 /* If we haven't got a certificate try each ri in turn */
6744 for (i
=0; i
<sk_PKCS7_RECIP_INFO_num(rsk
); i
++) {
6745 ri
=sk_PKCS7_RECIP_INFO_value(rsk
,i
);
6746 jj
= pkinit_decode_data(context
, id_cryptoctx
,
6747 (unsigned char *)ASN1_STRING_get0_data(ri
->enc_key
),
6748 ASN1_STRING_length(ri
->enc_key
),
6751 PKCS7err(PKCS7_F_PKCS7_DATADECODE
, ERR_R_EVP_LIB
);
6755 if (!jj
&& tmp_len
> 0) {
6765 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE
);
6770 jj
= pkinit_decode_data(context
, id_cryptoctx
,
6771 (unsigned char *)ASN1_STRING_get0_data(ri
->enc_key
),
6772 ASN1_STRING_length(ri
->enc_key
),
6774 /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */
6775 if (jj
|| tmp_len
== 0) {
6776 PKCS7err(PKCS7_F_PKCS7_DATADECODE
, ERR_R_EVP_LIB
);
6783 BIO_get_cipher_ctx(etmp
,&evp_ctx
);
6784 if (EVP_CipherInit_ex(evp_ctx
,evp_cipher
,NULL
,NULL
,NULL
,0) <= 0)
6786 if (EVP_CIPHER_asn1_to_param(evp_ctx
,enc_alg
->parameter
) < 0)
6789 if (jj
!= EVP_CIPHER_CTX_key_length(evp_ctx
)) {
6790 /* Some S/MIME clients don't use the same key
6791 * and effective key length. The key length is
6792 * determined by the size of the decrypted RSA key.
6794 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx
, (int)jj
)) {
6795 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,
6796 PKCS7_R_DECRYPT_ERROR
);
6800 if (EVP_CipherInit_ex(evp_ctx
,NULL
,NULL
,tmp
,NULL
,0) <= 0)
6803 OPENSSL_cleanse(tmp
,jj
);
6811 if (data_body
->length
> 0)
6812 bio
= BIO_new_mem_buf(data_body
->data
, data_body
->length
);
6814 bio
=BIO_new(BIO_s_mem());
6815 BIO_set_mem_eof_return(bio
,0);
6820 /* Solaris Kerberos */
6824 if (out
!= NULL
) BIO_free_all(out
);
6825 if (etmp
!= NULL
) BIO_free_all(etmp
);
6826 if (bio
!= NULL
) BIO_free_all(bio
);
6836 static krb5_error_code
6837 der_decode_data(unsigned char *data
, long data_len
,
6838 unsigned char **out
, long *out_len
)
6840 /* Solaris Kerberos */
6841 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
6842 ASN1_OCTET_STRING
*s
= NULL
;
6843 const unsigned char *p
= data
;
6845 if ((s
= d2i_ASN1_BIT_STRING(NULL
, &p
, data_len
)) == NULL
)
6847 *out_len
= s
->length
;
6848 if ((*out
= (unsigned char *) malloc((size_t) *out_len
+ 1)) == NULL
) {
6852 (void) memcpy(*out
, s
->data
, (size_t) s
->length
);
6853 (*out
)[s
->length
] = '\0';
6858 ASN1_OCTET_STRING_free(s
);
6866 print_dh(DH
* dh
, char *msg
)
6868 BIO
*bio_err
= NULL
;
6870 bio_err
= BIO_new(BIO_s_file());
6871 BIO_set_fp(bio_err
, stderr
, BIO_NOCLOSE
| BIO_FP_TEXT
);
6874 BIO_puts(bio_err
, (const char *)msg
);
6876 DHparams_print(bio_err
, dh
);
6878 BN_print(bio_err
, dh
->q
);
6879 BIO_puts(bio_err
, (const char *)"\n");
6885 print_pubkey(BIGNUM
* key
, char *msg
)
6887 BIO
*bio_err
= NULL
;
6889 bio_err
= BIO_new(BIO_s_file());
6890 BIO_set_fp(bio_err
, stderr
, BIO_NOCLOSE
| BIO_FP_TEXT
);
6893 BIO_puts(bio_err
, (const char *)msg
);
6895 BN_print(bio_err
, key
);
6896 BIO_puts(bio_err
, "\n");
6905 * Error message generation has changed so gettext() can be used
6909 pkinit_pkcs11_code_to_text(int err
)
6914 for (i
= 0; pkcs11_errstrings
[i
].text
!= NULL
; i
++)
6915 if (pkcs11_errstrings
[i
].code
== err
)
6917 if (pkcs11_errstrings
[i
].text
!= NULL
)
6918 return (pkcs11_errstrings
[i
].text
);
6919 snprintf(uc
, 64, gettext("unknown code 0x%x"), err
);
6925 pkinit_pkcs11_code_to_text(int err
) {
6926 return pkcs11_error_table(err
);