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.
45 /* Solaris Kerberos */
48 #include <security/pam_appl.h>
54 * Q: What is this SILLYDECRYPT stuff about?
55 * A: When using the ActivCard Linux pkcs11 library (v2.0.1),
56 * the decrypt function fails. By inserting an extra
57 * function call, which serves nothing but to change the
58 * stack, we were able to work around the issue. If the
59 * ActivCard library is fixed in the future, this
60 * definition and related code can be removed.
64 #include "pkinit_crypto_openssl.h"
68 * Changed to a switch statement so gettext() can be used
69 * for internationization.
70 * Use defined constants rather than raw numbers for error codes.
73 pkcs11_error_table(short code
) {
76 return (gettext("ok"));
78 return (gettext("cancel"));
80 return (gettext("host memory"));
81 case CKR_SLOT_ID_INVALID
:
82 return (gettext("slot id invalid"));
83 case CKR_GENERAL_ERROR
:
84 return (gettext("general error"));
85 case CKR_FUNCTION_FAILED
:
86 return (gettext("function failed"));
87 case CKR_ARGUMENTS_BAD
:
88 return (gettext("arguments bad"));
90 return (gettext("no event"));
91 case CKR_NEED_TO_CREATE_THREADS
:
92 return (gettext("need to create threads"));
94 return (gettext("cant lock"));
95 case CKR_ATTRIBUTE_READ_ONLY
:
96 return (gettext("attribute read only"));
97 case CKR_ATTRIBUTE_SENSITIVE
:
98 return (gettext("attribute sensitive"));
99 case CKR_ATTRIBUTE_TYPE_INVALID
:
100 return (gettext("attribute type invalid"));
101 case CKR_ATTRIBUTE_VALUE_INVALID
:
102 return (gettext("attribute value invalid"));
103 case CKR_DATA_INVALID
:
104 return (gettext("data invalid"));
105 case CKR_DATA_LEN_RANGE
:
106 return (gettext("data len range"));
107 case CKR_DEVICE_ERROR
:
108 return (gettext("device error"));
109 case CKR_DEVICE_MEMORY
:
110 return (gettext("device memory"));
111 case CKR_DEVICE_REMOVED
:
112 return (gettext("device removed"));
113 case CKR_ENCRYPTED_DATA_INVALID
:
114 return (gettext("encrypted data invalid"));
115 case CKR_ENCRYPTED_DATA_LEN_RANGE
:
116 return (gettext("encrypted data len range"));
117 case CKR_FUNCTION_CANCELED
:
118 return (gettext("function canceled"));
119 case CKR_FUNCTION_NOT_PARALLEL
:
120 return (gettext("function not parallel"));
121 case CKR_FUNCTION_NOT_SUPPORTED
:
122 return (gettext("function not supported"));
123 case CKR_KEY_HANDLE_INVALID
:
124 return (gettext("key handle invalid"));
125 case CKR_KEY_SIZE_RANGE
:
126 return (gettext("key size range"));
127 case CKR_KEY_TYPE_INCONSISTENT
:
128 return (gettext("key type inconsistent"));
129 case CKR_KEY_NOT_NEEDED
:
130 return (gettext("key not needed"));
131 case CKR_KEY_CHANGED
:
132 return (gettext("key changed"));
134 return (gettext("key needed"));
135 case CKR_KEY_INDIGESTIBLE
:
136 return (gettext("key indigestible"));
137 case CKR_KEY_FUNCTION_NOT_PERMITTED
:
138 return (gettext("key function not permitted"));
139 case CKR_KEY_NOT_WRAPPABLE
:
140 return (gettext("key not wrappable"));
141 case CKR_KEY_UNEXTRACTABLE
:
142 return (gettext("key unextractable"));
143 case CKR_MECHANISM_INVALID
:
144 return (gettext("mechanism invalid"));
145 case CKR_MECHANISM_PARAM_INVALID
:
146 return (gettext("mechanism param invalid"));
147 case CKR_OBJECT_HANDLE_INVALID
:
148 return (gettext("object handle invalid"));
149 case CKR_OPERATION_ACTIVE
:
150 return (gettext("operation active"));
151 case CKR_OPERATION_NOT_INITIALIZED
:
152 return (gettext("operation not initialized"));
153 case CKR_PIN_INCORRECT
:
154 return (gettext("pin incorrect"));
155 case CKR_PIN_INVALID
:
156 return (gettext("pin invalid"));
157 case CKR_PIN_LEN_RANGE
:
158 return (gettext("pin len range"));
159 case CKR_PIN_EXPIRED
:
160 return (gettext("pin expired"));
162 return (gettext("pin locked"));
163 case CKR_SESSION_CLOSED
:
164 return (gettext("session closed"));
165 case CKR_SESSION_COUNT
:
166 return (gettext("session count"));
167 case CKR_SESSION_HANDLE_INVALID
:
168 return (gettext("session handle invalid"));
169 case CKR_SESSION_PARALLEL_NOT_SUPPORTED
:
170 return (gettext("session parallel not supported"));
171 case CKR_SESSION_READ_ONLY
:
172 return (gettext("session read only"));
173 case CKR_SESSION_EXISTS
:
174 return (gettext("session exists"));
175 case CKR_SESSION_READ_ONLY_EXISTS
:
176 return (gettext("session read only exists"));
177 case CKR_SESSION_READ_WRITE_SO_EXISTS
:
178 return (gettext("session read write so exists"));
179 case CKR_SIGNATURE_INVALID
:
180 return (gettext("signature invalid"));
181 case CKR_SIGNATURE_LEN_RANGE
:
182 return (gettext("signature len range"));
183 case CKR_TEMPLATE_INCOMPLETE
:
184 return (gettext("template incomplete"));
185 case CKR_TEMPLATE_INCONSISTENT
:
186 return (gettext("template inconsistent"));
187 case CKR_TOKEN_NOT_PRESENT
:
188 return (gettext("token not present"));
189 case CKR_TOKEN_NOT_RECOGNIZED
:
190 return (gettext("token not recognized"));
191 case CKR_TOKEN_WRITE_PROTECTED
:
192 return (gettext("token write protected"));
193 case CKR_UNWRAPPING_KEY_HANDLE_INVALID
:
194 return (gettext("unwrapping key handle invalid"));
195 case CKR_UNWRAPPING_KEY_SIZE_RANGE
:
196 return (gettext("unwrapping key size range"));
197 case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
:
198 return (gettext("unwrapping key type inconsistent"));
199 case CKR_USER_ALREADY_LOGGED_IN
:
200 return (gettext("user already logged in"));
201 case CKR_USER_NOT_LOGGED_IN
:
202 return (gettext("user not logged in"));
203 case CKR_USER_PIN_NOT_INITIALIZED
:
204 return (gettext("user pin not initialized"));
205 case CKR_USER_TYPE_INVALID
:
206 return (gettext("user type invalid"));
207 case CKR_USER_ANOTHER_ALREADY_LOGGED_IN
:
208 return (gettext("user another already logged in"));
209 case CKR_USER_TOO_MANY_TYPES
:
210 return (gettext("user too many types"));
211 case CKR_WRAPPED_KEY_INVALID
:
212 return (gettext("wrapped key invalid"));
213 case CKR_WRAPPED_KEY_LEN_RANGE
:
214 return (gettext("wrapped key len range"));
215 case CKR_WRAPPING_KEY_HANDLE_INVALID
:
216 return (gettext("wrapping key handle invalid"));
217 case CKR_WRAPPING_KEY_SIZE_RANGE
:
218 return (gettext("wrapping key size range"));
219 case CKR_WRAPPING_KEY_TYPE_INCONSISTENT
:
220 return (gettext("wrapping key type inconsistent"));
221 case CKR_RANDOM_SEED_NOT_SUPPORTED
:
222 return (gettext("random seed not supported"));
223 case CKR_RANDOM_NO_RNG
:
224 return (gettext("random no rng"));
225 case CKR_DOMAIN_PARAMS_INVALID
:
226 return (gettext("domain params invalid"));
227 case CKR_BUFFER_TOO_SMALL
:
228 return (gettext("buffer too small"));
229 case CKR_SAVED_STATE_INVALID
:
230 return (gettext("saved state invalid"));
231 case CKR_INFORMATION_SENSITIVE
:
232 return (gettext("information sensitive"));
233 case CKR_STATE_UNSAVEABLE
:
234 return (gettext("state unsaveable"));
235 case CKR_CRYPTOKI_NOT_INITIALIZED
:
236 return (gettext("cryptoki not initialized"));
237 case CKR_CRYPTOKI_ALREADY_INITIALIZED
:
238 return (gettext("cryptoki already initialized"));
240 return (gettext("mutex bad"));
241 case CKR_MUTEX_NOT_LOCKED
:
242 return (gettext("mutex not locked"));
243 case CKR_FUNCTION_REJECTED
:
244 return (gettext("function rejected"));
246 return (gettext("unknown error"));
251 unsigned char pkinit_1024_dhprime
[128] = {
252 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
253 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
254 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
255 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
256 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
257 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
258 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
259 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
260 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
261 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
262 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
263 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
264 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
265 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
266 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
267 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
270 unsigned char pkinit_2048_dhprime
[2048/8] = {
271 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
272 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
273 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
274 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
275 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
276 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
277 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
278 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
279 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
280 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
281 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
282 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
283 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
284 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
285 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
286 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
287 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
288 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
289 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
290 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
291 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
292 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
293 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
294 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
295 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
296 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
297 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
298 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
299 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
300 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
301 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
302 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
305 unsigned char pkinit_4096_dhprime
[4096/8] = {
306 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
307 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
308 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
309 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
310 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
311 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
312 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
313 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
314 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
315 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
316 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
317 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
318 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
319 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
320 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
321 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
322 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
323 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
324 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
325 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
326 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
327 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
328 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
329 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
330 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
331 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
332 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
333 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
334 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
335 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
336 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
337 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
338 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
339 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
340 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
341 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
342 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
343 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
344 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
345 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
346 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
347 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
348 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
349 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
350 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
351 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
352 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
353 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
354 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
355 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
356 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
357 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
358 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
359 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
360 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
361 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
362 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
363 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
364 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
365 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
366 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
367 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
368 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
369 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
372 /* Solaris Kerberos */
373 static k5_mutex_t oids_mutex
= K5_MUTEX_PARTIAL_INITIALIZER
;
374 static int pkinit_oids_refs
= 0;
377 pkinit_init_plg_crypto(pkinit_plg_crypto_context
*cryptoctx
) {
379 krb5_error_code retval
= ENOMEM
;
380 pkinit_plg_crypto_context ctx
= NULL
;
382 /* initialize openssl routines */
383 /* Solaris Kerberos */
384 retval
= openssl_init();
388 ctx
= (pkinit_plg_crypto_context
)malloc(sizeof(*ctx
));
391 (void) memset(ctx
, 0, sizeof(*ctx
));
393 pkiDebug("%s: initializing openssl crypto context at %p\n",
395 retval
= pkinit_init_pkinit_oids(ctx
);
399 retval
= pkinit_init_dh_params(ctx
);
406 if (retval
&& ctx
!= NULL
)
407 pkinit_fini_plg_crypto(ctx
);
413 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx
)
415 pkiDebug("%s: freeing context at %p\n", __FUNCTION__
, cryptoctx
);
417 if (cryptoctx
== NULL
)
419 pkinit_fini_pkinit_oids(cryptoctx
);
420 pkinit_fini_dh_params(cryptoctx
);
425 pkinit_init_identity_crypto(pkinit_identity_crypto_context
*idctx
)
427 krb5_error_code retval
= ENOMEM
;
428 pkinit_identity_crypto_context ctx
= NULL
;
430 ctx
= (pkinit_identity_crypto_context
)malloc(sizeof(*ctx
));
433 (void) memset(ctx
, 0, sizeof(*ctx
));
435 retval
= pkinit_init_certs(ctx
);
439 retval
= pkinit_init_pkcs11(ctx
);
443 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__
, ctx
);
449 pkinit_fini_identity_crypto(ctx
);
456 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx
)
461 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__
, idctx
);
462 pkinit_fini_certs(idctx
);
463 pkinit_fini_pkcs11(idctx
);
468 pkinit_init_req_crypto(pkinit_req_crypto_context
*cryptoctx
)
471 pkinit_req_crypto_context ctx
= NULL
;
473 /* Solaris Kerberos */
474 if (cryptoctx
== NULL
)
477 ctx
= (pkinit_req_crypto_context
)malloc(sizeof(*ctx
));
480 (void) memset(ctx
, 0, sizeof(*ctx
));
483 ctx
->received_cert
= NULL
;
487 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__
, ctx
);
493 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx
)
495 if (req_cryptoctx
== NULL
)
498 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__
, req_cryptoctx
);
499 if (req_cryptoctx
->dh
!= NULL
)
500 DH_free(req_cryptoctx
->dh
);
501 if (req_cryptoctx
->received_cert
!= NULL
)
502 X509_free(req_cryptoctx
->received_cert
);
507 static krb5_error_code
508 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx
)
510 krb5_error_code retval
= ENOMEM
;
514 * If OpenSSL already knows about the OID, use the
515 * existing definition. Otherwise, create an OID object.
517 #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \
518 nid = OBJ_txt2nid(oid); \
519 if (nid == NID_undef) { \
520 nid = OBJ_create(oid, sn, ln); \
521 if (nid == NID_undef) { \
522 pkiDebug("Error creating oid object for '%s'\n", oid); \
526 ctx->vn = OBJ_nid2obj(nid);
528 /* Solaris Kerberos */
529 retval
= k5_mutex_lock(&oids_mutex
);
533 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san
,
534 "id-pkinit-san", "KRB5PrincipalName");
536 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.1", id_pkinit_authData
,
537 "id-pkinit-authdata", "PKINIT signedAuthPack");
539 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.2", id_pkinit_DHKeyData
,
540 "id-pkinit-DHKeyData", "PKINIT dhSignedData");
542 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.3", id_pkinit_rkeyData
,
543 "id-pkinit-rkeyData", "PKINIT encKeyPack");
545 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.4", id_pkinit_KPClientAuth
,
546 "id-pkinit-KPClientAuth", "PKINIT Client EKU");
548 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.5", id_pkinit_KPKdc
,
549 "id-pkinit-KPKdc", "KDC EKU");
552 CREATE_OBJ_IF_NEEDED("1.2.840.113549.1.7.1", id_pkinit_authData9
,
553 "id-pkcs7-data", "PKCS7 data");
555 /* See note in pkinit_pkcs7type2oid() */
556 ctx
->id_pkinit_authData9
= NULL
;
559 CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.2", id_ms_kp_sc_logon
,
560 "id-ms-kp-sc-logon EKU", "Microsoft SmartCard Login EKU");
562 CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn
,
563 "id-ms-san-upn", "Microsoft Universal Principal Name");
565 CREATE_OBJ_IF_NEEDED("1.3.6.1.5.5.7.3.1", id_kp_serverAuth
,
566 "id-kp-serverAuth EKU", "Server Authentication EKU");
572 /* Solaris Kerberos */
573 k5_mutex_unlock(&oids_mutex
);
579 static krb5_error_code
580 get_cert(char *filename
, X509
**retcert
)
585 krb5_error_code retval
;
587 if (filename
== NULL
|| retcert
== NULL
)
592 tmp
= BIO_new(BIO_s_file());
596 code
= BIO_read_filename(tmp
, filename
);
602 cert
= (X509
*) PEM_read_bio_X509(tmp
, NULL
, NULL
, NULL
);
605 pkiDebug("failed to read certificate from %s\n", filename
);
616 static krb5_error_code
617 get_key(char *filename
, EVP_PKEY
**retkey
)
619 EVP_PKEY
*pkey
= NULL
;
622 krb5_error_code retval
;
624 if (filename
== NULL
|| retkey
== NULL
)
627 tmp
= BIO_new(BIO_s_file());
631 code
= BIO_read_filename(tmp
, filename
);
636 pkey
= (EVP_PKEY
*) PEM_read_bio_PrivateKey(tmp
, NULL
, NULL
, NULL
);
639 pkiDebug("failed to read private key from %s\n", filename
);
651 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx
)
656 /* Only call OBJ_cleanup once! */
657 /* Solaris Kerberos: locking */
658 k5_mutex_lock(&oids_mutex
);
659 if (--pkinit_oids_refs
== 0)
661 k5_mutex_unlock(&oids_mutex
);
664 static krb5_error_code
665 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx
)
667 krb5_error_code retval
= ENOMEM
;
669 plgctx
->dh_1024
= DH_new();
670 if (plgctx
->dh_1024
== NULL
)
672 plgctx
->dh_1024
->p
= BN_bin2bn(pkinit_1024_dhprime
,
673 sizeof(pkinit_1024_dhprime
), NULL
);
674 if ((plgctx
->dh_1024
->g
= BN_new()) == NULL
||
675 (plgctx
->dh_1024
->q
= BN_new()) == NULL
)
677 BN_set_word(plgctx
->dh_1024
->g
, DH_GENERATOR_2
);
678 BN_rshift1(plgctx
->dh_1024
->q
, plgctx
->dh_1024
->p
);
680 plgctx
->dh_2048
= DH_new();
681 if (plgctx
->dh_2048
== NULL
)
683 plgctx
->dh_2048
->p
= BN_bin2bn(pkinit_2048_dhprime
,
684 sizeof(pkinit_2048_dhprime
), NULL
);
685 if ((plgctx
->dh_2048
->g
= BN_new()) == NULL
||
686 (plgctx
->dh_2048
->q
= BN_new()) == NULL
)
688 BN_set_word(plgctx
->dh_2048
->g
, DH_GENERATOR_2
);
689 BN_rshift1(plgctx
->dh_2048
->q
, plgctx
->dh_2048
->p
);
691 plgctx
->dh_4096
= DH_new();
692 if (plgctx
->dh_4096
== NULL
)
694 plgctx
->dh_4096
->p
= BN_bin2bn(pkinit_4096_dhprime
,
695 sizeof(pkinit_4096_dhprime
), NULL
);
696 if ((plgctx
->dh_4096
->g
= BN_new()) == NULL
||
697 (plgctx
->dh_4096
->q
= BN_new()) == NULL
)
699 BN_set_word(plgctx
->dh_4096
->g
, DH_GENERATOR_2
);
700 BN_rshift1(plgctx
->dh_4096
->q
, plgctx
->dh_4096
->p
);
706 pkinit_fini_dh_params(plgctx
);
712 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx
)
714 if (plgctx
->dh_1024
!= NULL
)
715 DH_free(plgctx
->dh_1024
);
716 if (plgctx
->dh_2048
!= NULL
)
717 DH_free(plgctx
->dh_2048
);
718 if (plgctx
->dh_4096
!= NULL
)
719 DH_free(plgctx
->dh_4096
);
721 plgctx
->dh_1024
= plgctx
->dh_2048
= plgctx
->dh_4096
= NULL
;
724 static krb5_error_code
725 pkinit_init_certs(pkinit_identity_crypto_context ctx
)
727 /* Solaris Kerberos */
730 for (i
= 0; i
< MAX_CREDS_ALLOWED
; i
++)
731 ctx
->creds
[i
] = NULL
;
732 ctx
->my_certs
= NULL
;
735 ctx
->trustedCAs
= NULL
;
736 ctx
->intermediateCAs
= NULL
;
743 pkinit_fini_certs(pkinit_identity_crypto_context ctx
)
748 if (ctx
->my_certs
!= NULL
)
749 sk_X509_pop_free(ctx
->my_certs
, X509_free
);
751 if (ctx
->my_key
!= NULL
)
752 EVP_PKEY_free(ctx
->my_key
);
754 if (ctx
->trustedCAs
!= NULL
)
755 sk_X509_pop_free(ctx
->trustedCAs
, X509_free
);
757 if (ctx
->intermediateCAs
!= NULL
)
758 sk_X509_pop_free(ctx
->intermediateCAs
, X509_free
);
760 if (ctx
->revoked
!= NULL
)
761 sk_X509_CRL_pop_free(ctx
->revoked
, X509_CRL_free
);
764 static krb5_error_code
765 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx
)
767 /* Solaris Kerberos */
769 #ifndef WITHOUT_PKCS11
770 ctx
->p11_module_name
= strdup(PKCS11_MODNAME
);
771 if (ctx
->p11_module_name
== NULL
)
773 ctx
->p11_module
= NULL
;
774 ctx
->slotid
= PK_NOSLOT
;
775 ctx
->token_label
= NULL
;
776 ctx
->cert_label
= NULL
;
778 ctx
->session
= CK_INVALID_HANDLE
;
780 ctx
->p11flags
= 0; /* Solaris Kerberos */
782 ctx
->pkcs11_method
= 0;
783 (void) memset(ctx
->creds
, 0, sizeof(ctx
->creds
));
789 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx
)
791 #ifndef WITHOUT_PKCS11
795 if (ctx
->p11
!= NULL
) {
796 if (ctx
->session
!= CK_INVALID_HANDLE
) {
797 ctx
->p11
->C_CloseSession(ctx
->session
);
798 ctx
->session
= CK_INVALID_HANDLE
;
802 * Only call C_Finalize if the process was not already using pkcs11.
804 if (ctx
->finalize_pkcs11
== TRUE
)
805 ctx
->p11
->C_Finalize(NULL_PTR
);
809 if (ctx
->p11_module
!= NULL
) {
810 pkinit_C_UnloadModule(ctx
->p11_module
);
811 ctx
->p11_module
= NULL
;
813 free(ctx
->p11_module_name
);
814 free(ctx
->token_label
);
816 free(ctx
->cert_label
);
817 if (ctx
->PIN
!= NULL
) {
818 (void) memset(ctx
->PIN
, 0, strlen(ctx
->PIN
));
825 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx
,
826 krb5_prompter_fct prompter
,
829 id_cryptoctx
->prompter
= prompter
;
830 id_cryptoctx
->prompter_data
= prompter_data
;
837 cms_signeddata_create(krb5_context context
,
838 pkinit_plg_crypto_context plg_cryptoctx
,
839 pkinit_req_crypto_context req_cryptoctx
,
840 pkinit_identity_crypto_context id_cryptoctx
,
842 int include_certchain
,
844 unsigned int data_len
,
845 unsigned char **signed_data
,
846 unsigned int *signed_data_len
)
848 /* Solaris Kerberos */
849 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
850 PKCS7
*p7
= NULL
, *inner_p7
= NULL
;
851 PKCS7_SIGNED
*p7s
= NULL
;
852 PKCS7_SIGNER_INFO
*p7si
= NULL
;
854 ASN1_TYPE
*pkinit_data
= NULL
;
855 STACK_OF(X509
) * cert_stack
= NULL
;
856 ASN1_OCTET_STRING
*digest_attr
= NULL
;
857 EVP_MD_CTX ctx
, ctx2
;
858 const EVP_MD
*md_tmp
= NULL
;
859 unsigned char md_data
[EVP_MAX_MD_SIZE
], md_data2
[EVP_MAX_MD_SIZE
];
860 unsigned char *digestInfo_buf
= NULL
, *abuf
= NULL
;
861 unsigned int md_len
, md_len2
, alen
, digestInfo_len
;
862 STACK_OF(X509_ATTRIBUTE
) * sk
;
863 unsigned char *sig
= NULL
;
864 unsigned int sig_len
= 0;
865 X509_ALGOR
*alg
= NULL
;
866 ASN1_OCTET_STRING
*digest
= NULL
;
867 unsigned int alg_len
= 0, digest_len
= 0;
868 unsigned char *y
= NULL
, *alg_buf
= NULL
, *digest_buf
= NULL
;
870 ASN1_OBJECT
*oid
= NULL
;
872 /* Solaris Kerberos */
873 if (signed_data
== NULL
)
876 if (signed_data_len
== NULL
)
879 /* start creating PKCS7 data */
880 if ((p7
= PKCS7_new()) == NULL
)
882 p7
->type
= OBJ_nid2obj(NID_pkcs7_signed
);
884 if ((p7s
= PKCS7_SIGNED_new()) == NULL
)
887 if (!ASN1_INTEGER_set(p7s
->version
, 3))
890 /* create a cert chain that has at least the signer's certificate */
891 if ((cert_stack
= sk_X509_new_null()) == NULL
)
894 cert
= sk_X509_value(id_cryptoctx
->my_certs
, id_cryptoctx
->cert_index
);
895 if (!include_certchain
) {
896 pkiDebug("only including signer's certificate\n");
897 sk_X509_push(cert_stack
, X509_dup(cert
));
899 /* create a cert chain */
900 X509_STORE
*certstore
= NULL
;
901 X509_STORE_CTX certctx
;
902 STACK_OF(X509
) *certstack
= NULL
;
903 char buf
[DN_BUF_LEN
];
906 if ((certstore
= X509_STORE_new()) == NULL
)
908 pkiDebug("building certificate chain\n");
909 X509_STORE_set_verify_cb_func(certstore
, openssl_callback
);
910 X509_STORE_CTX_init(&certctx
, certstore
, cert
,
911 id_cryptoctx
->intermediateCAs
);
912 X509_STORE_CTX_trusted_stack(&certctx
, id_cryptoctx
->trustedCAs
);
913 /* Solaris Kerberos */
914 if (X509_verify_cert(&certctx
) <= 0) {
915 pkiDebug("failed to create a certificate chain: %s\n",
916 X509_verify_cert_error_string(X509_STORE_CTX_get_error(&certctx
)));
917 if (!sk_X509_num(id_cryptoctx
->trustedCAs
))
918 pkiDebug("No trusted CAs found. Check your X509_anchors\n");
921 certstack
= X509_STORE_CTX_get1_chain(&certctx
);
922 size
= sk_X509_num(certstack
);
923 pkiDebug("size of certificate chain = %d\n", size
);
924 for(i
= 0; i
< size
- 1; i
++) {
925 X509
*x
= sk_X509_value(certstack
, i
);
926 X509_NAME_oneline(X509_get_subject_name(x
), buf
, sizeof(buf
));
927 pkiDebug("cert #%d: %s\n", i
, buf
);
928 sk_X509_push(cert_stack
, X509_dup(x
));
930 X509_STORE_CTX_cleanup(&certctx
);
931 X509_STORE_free(certstore
);
932 sk_X509_pop_free(certstack
, X509_free
);
934 p7s
->cert
= cert_stack
;
936 /* fill-in PKCS7_SIGNER_INFO */
937 if ((p7si
= PKCS7_SIGNER_INFO_new()) == NULL
)
939 if (!ASN1_INTEGER_set(p7si
->version
, 1))
941 if (!X509_NAME_set(&p7si
->issuer_and_serial
->issuer
,
942 X509_get_issuer_name(cert
)))
944 /* because ASN1_INTEGER_set is used to set a 'long' we will do
945 * things the ugly way. */
946 M_ASN1_INTEGER_free(p7si
->issuer_and_serial
->serial
);
947 if (!(p7si
->issuer_and_serial
->serial
=
948 M_ASN1_INTEGER_dup(X509_get_serialNumber(cert
))))
951 /* will not fill-out EVP_PKEY because it's on the smartcard */
953 /* Set digest algs */
954 p7si
->digest_alg
->algorithm
= OBJ_nid2obj(NID_sha1
);
956 if (p7si
->digest_alg
->parameter
!= NULL
)
957 ASN1_TYPE_free(p7si
->digest_alg
->parameter
);
958 if ((p7si
->digest_alg
->parameter
= ASN1_TYPE_new()) == NULL
)
960 p7si
->digest_alg
->parameter
->type
= V_ASN1_NULL
;
963 if (p7si
->digest_enc_alg
->parameter
!= NULL
)
964 ASN1_TYPE_free(p7si
->digest_enc_alg
->parameter
);
965 p7si
->digest_enc_alg
->algorithm
= OBJ_nid2obj(NID_sha1WithRSAEncryption
);
966 if (!(p7si
->digest_enc_alg
->parameter
= ASN1_TYPE_new()))
968 p7si
->digest_enc_alg
->parameter
->type
= V_ASN1_NULL
;
970 /* pick the correct oid for the eContentInfo */
971 oid
= pkinit_pkcs7type2oid(plg_cryptoctx
, cms_msg_type
);
975 if (cms_msg_type
== CMS_SIGN_DRAFT9
) {
976 /* don't include signed attributes for pa-type 15 request */
980 /* add signed attributes */
981 /* compute sha1 digest over the EncapsulatedContentInfo */
982 EVP_MD_CTX_init(&ctx
);
983 EVP_DigestInit_ex(&ctx
, EVP_sha1(), NULL
);
984 EVP_DigestUpdate(&ctx
, data
, data_len
);
985 md_tmp
= EVP_MD_CTX_md(&ctx
);
986 EVP_DigestFinal_ex(&ctx
, md_data
, &md_len
);
988 /* create a message digest attr */
989 digest_attr
= ASN1_OCTET_STRING_new();
990 ASN1_OCTET_STRING_set(digest_attr
, md_data
, (int)md_len
);
991 PKCS7_add_signed_attribute(p7si
, NID_pkcs9_messageDigest
,
992 V_ASN1_OCTET_STRING
, (char *) digest_attr
);
994 /* create a content-type attr */
995 PKCS7_add_signed_attribute(p7si
, NID_pkcs9_contentType
,
998 /* create the signature over signed attributes. get DER encoded value */
999 /* This is the place where smartcard signature needs to be calculated */
1000 sk
= p7si
->auth_attr
;
1001 alen
= ASN1_item_i2d((ASN1_VALUE
*) sk
, &abuf
,
1002 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN
));
1007 #ifndef WITHOUT_PKCS11
1008 /* Some tokens can only do RSAEncryption without sha1 hash */
1009 /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
1010 * function and the hash value into an ASN.1 value of type DigestInfo
1011 * DigestInfo::=SEQUENCE {
1012 * digestAlgorithm AlgorithmIdentifier,
1013 * digest OCTET STRING }
1015 if (id_cryptoctx
->pkcs11_method
== 1 &&
1016 id_cryptoctx
->mech
== CKM_RSA_PKCS
) {
1017 pkiDebug("mech = CKM_RSA_PKCS\n");
1018 EVP_MD_CTX_init(&ctx2
);
1019 /* if this is not draft9 request, include digest signed attribute */
1020 if (cms_msg_type
!= CMS_SIGN_DRAFT9
)
1021 EVP_DigestInit_ex(&ctx2
, md_tmp
, NULL
);
1023 EVP_DigestInit_ex(&ctx2
, EVP_sha1(), NULL
);
1024 EVP_DigestUpdate(&ctx2
, abuf
, alen
);
1025 EVP_DigestFinal_ex(&ctx2
, md_data2
, &md_len2
);
1027 alg
= X509_ALGOR_new();
1030 alg
->algorithm
= OBJ_nid2obj(NID_sha1
);
1031 alg
->parameter
= NULL
;
1032 alg_len
= i2d_X509_ALGOR(alg
, NULL
);
1033 alg_buf
= (unsigned char *)malloc(alg_len
);
1034 if (alg_buf
== NULL
)
1037 digest
= ASN1_OCTET_STRING_new();
1040 ASN1_OCTET_STRING_set(digest
, md_data2
, (int)md_len2
);
1041 digest_len
= i2d_ASN1_OCTET_STRING(digest
, NULL
);
1042 digest_buf
= (unsigned char *)malloc(digest_len
);
1043 if (digest_buf
== NULL
)
1046 digestInfo_len
= ASN1_object_size(1, (int)(alg_len
+ digest_len
),
1048 y
= digestInfo_buf
= (unsigned char *)malloc(digestInfo_len
);
1049 if (digestInfo_buf
== NULL
)
1051 ASN1_put_object(&y
, 1, (int)(alg_len
+ digest_len
), V_ASN1_SEQUENCE
,
1053 i2d_X509_ALGOR(alg
, &y
);
1054 i2d_ASN1_OCTET_STRING(digest
, &y
);
1056 pkiDebug("signing buffer\n");
1057 print_buffer(digestInfo_buf
, digestInfo_len
);
1058 print_buffer_bin(digestInfo_buf
, digestInfo_len
, "/tmp/pkcs7_tosign");
1060 retval
= pkinit_sign_data(context
, id_cryptoctx
, digestInfo_buf
,
1061 digestInfo_len
, &sig
, &sig_len
);
1065 pkiDebug("mech = %s\n",
1066 id_cryptoctx
->pkcs11_method
== 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
1067 retval
= pkinit_sign_data(context
, id_cryptoctx
, abuf
, alen
,
1071 print_buffer(sig
, sig_len
);
1073 if (cms_msg_type
!= CMS_SIGN_DRAFT9
)
1079 if (!ASN1_STRING_set(p7si
->enc_digest
, (unsigned char *) sig
,
1081 unsigned long err
= ERR_peek_error();
1082 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1083 krb5_set_error_message(context
, retval
, "%s\n",
1084 ERR_error_string(err
, NULL
));
1085 pkiDebug("failed to add a signed digest attribute\n");
1088 /* adder signer_info to pkcs7 signed */
1089 if (!PKCS7_add_signer(p7
, p7si
))
1092 /* start on adding data to the pkcs7 signed */
1093 if ((inner_p7
= PKCS7_new()) == NULL
)
1095 if ((pkinit_data
= ASN1_TYPE_new()) == NULL
)
1097 pkinit_data
->type
= V_ASN1_OCTET_STRING
;
1098 if ((pkinit_data
->value
.octet_string
= ASN1_OCTET_STRING_new()) == NULL
)
1100 if (!ASN1_OCTET_STRING_set(pkinit_data
->value
.octet_string
, data
,
1102 unsigned long err
= ERR_peek_error();
1103 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1104 krb5_set_error_message(context
, retval
, "%s\n",
1105 ERR_error_string(err
, NULL
));
1106 pkiDebug("failed to add pkcs7 data\n");
1110 if (!PKCS7_set0_type_other(inner_p7
, OBJ_obj2nid(oid
), pkinit_data
))
1113 if (p7s
->contents
!= NULL
)
1114 PKCS7_free(p7s
->contents
);
1115 p7s
->contents
= inner_p7
;
1117 *signed_data_len
= i2d_PKCS7(p7
, NULL
);
1118 if (!(*signed_data_len
)) {
1119 unsigned long err
= ERR_peek_error();
1120 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1121 krb5_set_error_message(context
, retval
, "%s\n",
1122 ERR_error_string(err
, NULL
));
1123 pkiDebug("failed to der encode pkcs7\n");
1126 if ((p
= *signed_data
=
1127 (unsigned char *) malloc((size_t)*signed_data_len
)) == NULL
)
1130 /* DER encode PKCS7 data */
1131 retval
= i2d_PKCS7(p7
, &p
);
1133 unsigned long err
= ERR_peek_error();
1134 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1135 krb5_set_error_message(context
, retval
, "%s\n",
1136 ERR_error_string(err
, NULL
));
1137 pkiDebug("failed to der encode pkcs7\n");
1143 if (cms_msg_type
== CMS_SIGN_CLIENT
) {
1144 print_buffer_bin(*signed_data
, *signed_data_len
,
1145 "/tmp/client_pkcs7_signeddata");
1147 if (cms_msg_type
== CMS_SIGN_SERVER
) {
1148 print_buffer_bin(*signed_data
, *signed_data_len
,
1149 "/tmp/kdc_pkcs7_signeddata");
1151 print_buffer_bin(*signed_data
, *signed_data_len
,
1152 "/tmp/draft9_pkcs7_signeddata");
1158 if (cms_msg_type
!= CMS_SIGN_DRAFT9
)
1159 EVP_MD_CTX_cleanup(&ctx
);
1160 #ifndef WITHOUT_PKCS11
1161 if (id_cryptoctx
->pkcs11_method
== 1 &&
1162 id_cryptoctx
->mech
== CKM_RSA_PKCS
) {
1163 EVP_MD_CTX_cleanup(&ctx2
);
1164 if (digest_buf
!= NULL
)
1166 if (digestInfo_buf
!= NULL
)
1167 free(digestInfo_buf
);
1168 if (alg_buf
!= NULL
)
1171 ASN1_OCTET_STRING_free(digest
);
1175 X509_ALGOR_free(alg
);
1186 cms_signeddata_verify(krb5_context context
,
1187 pkinit_plg_crypto_context plgctx
,
1188 pkinit_req_crypto_context reqctx
,
1189 pkinit_identity_crypto_context idctx
,
1191 int require_crl_checking
,
1192 unsigned char *signed_data
,
1193 unsigned int signed_data_len
,
1194 unsigned char **data
,
1195 unsigned int *data_len
,
1196 unsigned char **authz_data
,
1197 unsigned int *authz_data_len
)
1199 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1202 int flags
= PKCS7_NOVERIFY
, i
= 0;
1203 unsigned int vflags
= 0, size
= 0;
1204 const unsigned char *p
= signed_data
;
1205 STACK_OF(PKCS7_SIGNER_INFO
) *si_sk
= NULL
;
1206 PKCS7_SIGNER_INFO
*si
= NULL
;
1208 X509_STORE
*store
= NULL
;
1209 X509_STORE_CTX cert_ctx
;
1210 STACK_OF(X509
) *intermediateCAs
= NULL
;
1211 STACK_OF(X509_CRL
) *revoked
= NULL
;
1212 STACK_OF(X509
) *verified_chain
= NULL
;
1213 ASN1_OBJECT
*oid
= NULL
;
1214 krb5_external_principal_identifier
**krb5_verified_chain
= NULL
;
1215 krb5_data
*authz
= NULL
;
1216 char buf
[DN_BUF_LEN
];
1219 print_buffer_bin(signed_data
, signed_data_len
,
1220 "/tmp/client_received_pkcs7_signeddata");
1223 /* Do this early enough to create the shadow OID for pkcs7-data if needed */
1224 oid
= pkinit_pkcs7type2oid(plgctx
, cms_msg_type
);
1228 /* decode received PKCS7 message */
1229 if ((p7
= d2i_PKCS7(NULL
, &p
, (int)signed_data_len
)) == NULL
) {
1230 unsigned long err
= ERR_peek_error();
1231 krb5_set_error_message(context
, retval
, "%s\n",
1232 ERR_error_string(err
, NULL
));
1233 pkiDebug("%s: failed to decode message: %s\n",
1234 __FUNCTION__
, ERR_error_string(err
, NULL
));
1238 /* verify that the received message is PKCS7 SignedData message */
1239 if (OBJ_obj2nid(p7
->type
) != NID_pkcs7_signed
) {
1240 pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
1241 OBJ_obj2nid(p7
->type
));
1242 krb5_set_error_message(context
, retval
, "wrong oid\n");
1246 /* setup to verify X509 certificate used to sign PKCS7 message */
1247 if (!(store
= X509_STORE_new()))
1250 /* check if we are inforcing CRL checking */
1251 vflags
= X509_V_FLAG_CRL_CHECK
|X509_V_FLAG_CRL_CHECK_ALL
;
1252 if (require_crl_checking
)
1253 X509_STORE_set_verify_cb_func(store
, openssl_callback
);
1255 X509_STORE_set_verify_cb_func(store
, openssl_callback_ignore_crls
);
1256 X509_STORE_set_flags(store
, vflags
);
1258 /* get the signer's information from the PKCS7 message */
1259 if ((si_sk
= PKCS7_get_signer_info(p7
)) == NULL
)
1261 if ((si
= sk_PKCS7_SIGNER_INFO_value(si_sk
, 0)) == NULL
)
1263 if ((x
= PKCS7_cert_from_signer_info(p7
, si
)) == NULL
)
1266 /* create available CRL information (get local CRLs and include CRLs
1267 * received in the PKCS7 message
1269 if (idctx
->revoked
== NULL
)
1270 revoked
= p7
->d
.sign
->crl
;
1271 else if (p7
->d
.sign
->crl
== NULL
)
1272 revoked
= idctx
->revoked
;
1274 size
= sk_X509_CRL_num(idctx
->revoked
);
1275 revoked
= sk_X509_CRL_new_null();
1276 for (i
= 0; i
< size
; i
++)
1277 sk_X509_CRL_push(revoked
, sk_X509_CRL_value(idctx
->revoked
, i
));
1278 size
= sk_X509_CRL_num(p7
->d
.sign
->crl
);
1279 for (i
= 0; i
< size
; i
++)
1280 sk_X509_CRL_push(revoked
, sk_X509_CRL_value(p7
->d
.sign
->crl
, i
));
1283 /* create available intermediate CAs chains (get local intermediateCAs and
1284 * include the CA chain received in the PKCS7 message
1286 if (idctx
->intermediateCAs
== NULL
)
1287 intermediateCAs
= p7
->d
.sign
->cert
;
1288 else if (p7
->d
.sign
->cert
== NULL
)
1289 intermediateCAs
= idctx
->intermediateCAs
;
1291 size
= sk_X509_num(idctx
->intermediateCAs
);
1292 intermediateCAs
= sk_X509_new_null();
1293 for (i
= 0; i
< size
; i
++) {
1294 sk_X509_push(intermediateCAs
,
1295 sk_X509_value(idctx
->intermediateCAs
, i
));
1297 size
= sk_X509_num(p7
->d
.sign
->cert
);
1298 for (i
= 0; i
< size
; i
++) {
1299 sk_X509_push(intermediateCAs
, sk_X509_value(p7
->d
.sign
->cert
, i
));
1303 /* initialize x509 context with the received certificate and
1304 * trusted and intermediate CA chains and CRLs
1306 if (!X509_STORE_CTX_init(&cert_ctx
, store
, x
, intermediateCAs
))
1309 X509_STORE_CTX_set0_crls(&cert_ctx
, revoked
);
1311 /* add trusted CAs certificates for cert verification */
1312 if (idctx
->trustedCAs
!= NULL
)
1313 X509_STORE_CTX_trusted_stack(&cert_ctx
, idctx
->trustedCAs
);
1315 pkiDebug("unable to find any trusted CAs\n");
1318 #ifdef DEBUG_CERTCHAIN
1319 if (intermediateCAs
!= NULL
) {
1320 size
= sk_X509_num(intermediateCAs
);
1321 pkiDebug("untrusted cert chain of size %d\n", size
);
1322 for (i
= 0; i
< size
; i
++) {
1323 X509_NAME_oneline(X509_get_subject_name(
1324 sk_X509_value(intermediateCAs
, i
)), buf
, sizeof(buf
));
1325 pkiDebug("cert #%d: %s\n", i
, buf
);
1328 if (idctx
->trustedCAs
!= NULL
) {
1329 size
= sk_X509_num(idctx
->trustedCAs
);
1330 pkiDebug("trusted cert chain of size %d\n", size
);
1331 for (i
= 0; i
< size
; i
++) {
1332 X509_NAME_oneline(X509_get_subject_name(
1333 sk_X509_value(idctx
->trustedCAs
, i
)), buf
, sizeof(buf
));
1334 pkiDebug("cert #%d: %s\n", i
, buf
);
1337 if (revoked
!= NULL
) {
1338 size
= sk_X509_CRL_num(revoked
);
1339 pkiDebug("CRL chain of size %d\n", size
);
1340 for (i
= 0; i
< size
; i
++) {
1341 X509_CRL
*crl
= sk_X509_CRL_value(revoked
, i
);
1342 X509_NAME_oneline(X509_CRL_get_issuer(crl
), buf
, sizeof(buf
));
1343 pkiDebug("crls by CA #%d: %s\n", i
, buf
);
1348 i
= X509_verify_cert(&cert_ctx
);
1350 int j
= X509_STORE_CTX_get_error(&cert_ctx
);
1352 reqctx
->received_cert
= X509_dup(cert_ctx
.current_cert
);
1354 case X509_V_ERR_CERT_REVOKED
:
1355 retval
= KRB5KDC_ERR_REVOKED_CERTIFICATE
;
1357 case X509_V_ERR_UNABLE_TO_GET_CRL
:
1358 retval
= KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN
;
1360 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
:
1361 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
1362 retval
= KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE
;
1365 retval
= KRB5KDC_ERR_INVALID_CERTIFICATE
;
1367 X509_NAME_oneline(X509_get_subject_name(
1368 reqctx
->received_cert
), buf
, sizeof(buf
));
1369 pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf
, j
,
1370 X509_verify_cert_error_string(j
));
1371 krb5_set_error_message(context
, retval
, "%s\n",
1372 X509_verify_cert_error_string(j
));
1373 #ifdef DEBUG_CERTCHAIN
1374 size
= sk_X509_num(p7
->d
.sign
->cert
);
1375 pkiDebug("received cert chain of size %d\n", size
);
1376 for (j
= 0; j
< size
; j
++) {
1377 X509
*tmp_cert
= sk_X509_value(p7
->d
.sign
->cert
, j
);
1378 X509_NAME_oneline(X509_get_subject_name(tmp_cert
), buf
, sizeof(buf
));
1379 pkiDebug("cert #%d: %s\n", j
, buf
);
1383 /* retrieve verified certificate chain */
1384 if (cms_msg_type
== CMS_SIGN_CLIENT
|| cms_msg_type
== CMS_SIGN_DRAFT9
)
1385 verified_chain
= X509_STORE_CTX_get1_chain(&cert_ctx
);
1387 X509_STORE_CTX_cleanup(&cert_ctx
);
1391 out
= BIO_new(BIO_s_mem());
1392 if (cms_msg_type
== CMS_SIGN_DRAFT9
)
1393 flags
|= PKCS7_NOATTR
;
1394 if (PKCS7_verify(p7
, NULL
, store
, NULL
, out
, flags
)) {
1397 if (!OBJ_cmp(p7
->d
.sign
->contents
->type
, oid
))
1399 else if (cms_msg_type
== CMS_SIGN_DRAFT9
) {
1401 * Various implementations of the pa-type 15 request use
1402 * different OIDS. We check that the returned object
1403 * has any of the acceptable OIDs
1405 ASN1_OBJECT
*client_oid
= NULL
, *server_oid
= NULL
, *rsa_oid
= NULL
;
1406 client_oid
= pkinit_pkcs7type2oid(plgctx
, CMS_SIGN_CLIENT
);
1407 server_oid
= pkinit_pkcs7type2oid(plgctx
, CMS_SIGN_SERVER
);
1408 rsa_oid
= pkinit_pkcs7type2oid(plgctx
, CMS_ENVEL_SERVER
);
1409 if (!OBJ_cmp(p7
->d
.sign
->contents
->type
, client_oid
) ||
1410 !OBJ_cmp(p7
->d
.sign
->contents
->type
, server_oid
) ||
1411 !OBJ_cmp(p7
->d
.sign
->contents
->type
, rsa_oid
))
1416 pkiDebug("PKCS7 Verification successful\n");
1418 pkiDebug("wrong oid in eContentType\n");
1419 print_buffer((unsigned char *)p7
->d
.sign
->contents
->type
->data
,
1420 (unsigned int)p7
->d
.sign
->contents
->type
->length
);
1421 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1422 krb5_set_error_message(context
, retval
, "wrong oid\n");
1427 unsigned long err
= ERR_peek_error();
1428 switch(ERR_GET_REASON(err
)) {
1429 case PKCS7_R_DIGEST_FAILURE
:
1430 retval
= KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED
;
1432 case PKCS7_R_SIGNATURE_FAILURE
:
1434 retval
= KRB5KDC_ERR_INVALID_SIG
;
1436 pkiDebug("PKCS7 Verification failure\n");
1437 krb5_set_error_message(context
, retval
, "%s\n",
1438 ERR_error_string(err
, NULL
));
1442 /* transfer the data from PKCS7 message into return buffer */
1444 if ((*data
= realloc(*data
, size
+ 1024 * 10)) == NULL
)
1446 i
= BIO_read(out
, &((*data
)[size
]), 1024 * 10);
1454 reqctx
->received_cert
= X509_dup(x
);
1456 /* generate authorization data */
1457 if (cms_msg_type
== CMS_SIGN_CLIENT
|| cms_msg_type
== CMS_SIGN_DRAFT9
) {
1459 if (authz_data
== NULL
|| authz_data_len
== NULL
)
1463 retval
= create_identifiers_from_stack(verified_chain
,
1464 &krb5_verified_chain
);
1466 pkiDebug("create_identifiers_from_stack failed\n");
1470 retval
= k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier
**)krb5_verified_chain
, &authz
);
1472 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
1476 print_buffer_bin((unsigned char *)authz
->data
, authz
->length
,
1477 "/tmp/kdc_ad_initial_verified_cas");
1479 *authz_data
= (unsigned char *)malloc(authz
->length
);
1480 if (*authz_data
== NULL
) {
1484 (void) memcpy(*authz_data
, authz
->data
, authz
->length
);
1485 *authz_data_len
= authz
->length
;
1494 X509_STORE_free(store
);
1496 if (idctx
->intermediateCAs
!= NULL
&& p7
->d
.sign
->cert
)
1497 sk_X509_free(intermediateCAs
);
1498 if (idctx
->revoked
!= NULL
&& p7
->d
.sign
->crl
)
1499 sk_X509_CRL_free(revoked
);
1502 if (verified_chain
!= NULL
)
1503 sk_X509_pop_free(verified_chain
, X509_free
);
1504 if (krb5_verified_chain
!= NULL
)
1505 free_krb5_external_principal_identifier(&krb5_verified_chain
);
1507 krb5_free_data(context
, authz
);
1513 cms_envelopeddata_create(krb5_context context
,
1514 pkinit_plg_crypto_context plgctx
,
1515 pkinit_req_crypto_context reqctx
,
1516 pkinit_identity_crypto_context idctx
,
1517 krb5_preauthtype pa_type
,
1518 int include_certchain
,
1519 unsigned char *key_pack
,
1520 unsigned int key_pack_len
,
1521 unsigned char **out
,
1522 unsigned int *out_len
)
1525 /* Solaris Kerberos */
1526 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
1529 unsigned char *p
= NULL
, *signed_data
= NULL
, *enc_data
= NULL
;
1530 int signed_data_len
= 0, enc_data_len
= 0, flags
= PKCS7_BINARY
;
1531 STACK_OF(X509
) *encerts
= NULL
;
1532 const EVP_CIPHER
*cipher
= NULL
;
1535 /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */
1536 switch ((int)pa_type
) {
1537 case KRB5_PADATA_PK_AS_REQ_OLD
:
1538 case KRB5_PADATA_PK_AS_REP_OLD
:
1539 cms_msg_type
= CMS_SIGN_DRAFT9
;
1541 case KRB5_PADATA_PK_AS_REQ
:
1542 cms_msg_type
= CMS_ENVEL_SERVER
;
1545 /* Solaris Kerberos */
1550 retval
= cms_signeddata_create(context
, plgctx
, reqctx
, idctx
,
1551 cms_msg_type
, include_certchain
, key_pack
, key_pack_len
,
1552 &signed_data
, (unsigned int *)&signed_data_len
);
1554 pkiDebug("failed to create pkcs7 signed data\n");
1558 /* check we have client's certificate */
1559 if (reqctx
->received_cert
== NULL
) {
1560 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1563 encerts
= sk_X509_new_null();
1564 sk_X509_push(encerts
, reqctx
->received_cert
);
1566 cipher
= EVP_des_ede3_cbc();
1567 in
= BIO_new(BIO_s_mem());
1569 case KRB5_PADATA_PK_AS_REQ
:
1570 prepare_enc_data(signed_data
, signed_data_len
, &enc_data
,
1572 retval
= BIO_write(in
, enc_data
, enc_data_len
);
1573 if (retval
!= enc_data_len
) {
1574 pkiDebug("BIO_write only wrote %d\n", retval
);
1578 case KRB5_PADATA_PK_AS_REP_OLD
:
1579 case KRB5_PADATA_PK_AS_REQ_OLD
:
1580 retval
= BIO_write(in
, signed_data
, signed_data_len
);
1581 if (retval
!= signed_data_len
) {
1582 pkiDebug("BIO_write only wrote %d\n", retval
);
1583 /* Solaris Kerberos */
1584 retval
= KRB5KRB_ERR_GENERIC
;
1593 p7
= PKCS7_encrypt(encerts
, in
, cipher
, flags
);
1595 pkiDebug("failed to encrypt PKCS7 object\n");
1600 case KRB5_PADATA_PK_AS_REQ
:
1601 p7
->d
.enveloped
->enc_data
->content_type
=
1602 OBJ_nid2obj(NID_pkcs7_signed
);
1604 case KRB5_PADATA_PK_AS_REP_OLD
:
1605 case KRB5_PADATA_PK_AS_REQ_OLD
:
1606 p7
->d
.enveloped
->enc_data
->content_type
=
1607 OBJ_nid2obj(NID_pkcs7_data
);
1611 *out_len
= i2d_PKCS7(p7
, NULL
);
1612 if (!*out_len
|| (p
= *out
= (unsigned char *)malloc(*out_len
)) == NULL
) {
1616 retval
= i2d_PKCS7(p7
, &p
);
1618 pkiDebug("unable to write pkcs7 object\n");
1624 print_buffer_bin(*out
, *out_len
, "/tmp/kdc_enveloped_data");
1632 if (signed_data
!= NULL
)
1634 if (enc_data
!= NULL
)
1636 if (encerts
!= NULL
)
1637 sk_X509_free(encerts
);
1643 cms_envelopeddata_verify(krb5_context context
,
1644 pkinit_plg_crypto_context plg_cryptoctx
,
1645 pkinit_req_crypto_context req_cryptoctx
,
1646 pkinit_identity_crypto_context id_cryptoctx
,
1647 krb5_preauthtype pa_type
,
1648 int require_crl_checking
,
1649 unsigned char *enveloped_data
,
1650 unsigned int enveloped_data_len
,
1651 unsigned char **data
,
1652 unsigned int *data_len
)
1654 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1658 unsigned int size
= 0;
1659 const unsigned char *p
= enveloped_data
;
1660 unsigned int tmp_buf_len
= 0, tmp_buf2_len
= 0, vfy_buf_len
= 0;
1661 unsigned char *tmp_buf
= NULL
, *tmp_buf2
= NULL
, *vfy_buf
= NULL
;
1665 print_buffer_bin(enveloped_data
, enveloped_data_len
,
1666 "/tmp/client_envelopeddata");
1668 /* decode received PKCS7 message */
1669 if ((p7
= d2i_PKCS7(NULL
, &p
, (int)enveloped_data_len
)) == NULL
) {
1670 unsigned long err
= ERR_peek_error();
1671 pkiDebug("failed to decode pkcs7\n");
1672 krb5_set_error_message(context
, retval
, "%s\n",
1673 ERR_error_string(err
, NULL
));
1677 /* verify that the received message is PKCS7 EnvelopedData message */
1678 if (OBJ_obj2nid(p7
->type
) != NID_pkcs7_enveloped
) {
1679 pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
1680 OBJ_obj2nid(p7
->type
));
1681 krb5_set_error_message(context
, retval
, "wrong oid\n");
1685 /* decrypt received PKCS7 message */
1686 out
= BIO_new(BIO_s_mem());
1687 if (pkcs7_decrypt(context
, id_cryptoctx
, p7
, out
)) {
1688 pkiDebug("PKCS7 decryption successful\n");
1690 unsigned long err
= ERR_peek_error();
1692 krb5_set_error_message(context
, retval
, "%s\n",
1693 ERR_error_string(err
, NULL
));
1694 pkiDebug("PKCS7 decryption failed\n");
1698 /* transfer the decoded PKCS7 SignedData message into a separate buffer */
1700 if ((tmp_buf
= realloc(tmp_buf
, size
+ 1024 * 10)) == NULL
)
1702 i
= BIO_read(out
, &(tmp_buf
[size
]), 1024 * 10);
1711 print_buffer_bin(tmp_buf
, tmp_buf_len
, "/tmp/client_enc_keypack");
1713 /* verify PKCS7 SignedData message */
1715 case KRB5_PADATA_PK_AS_REP
:
1716 msg_type
= CMS_ENVEL_SERVER
;
1719 case KRB5_PADATA_PK_AS_REP_OLD
:
1720 msg_type
= CMS_SIGN_DRAFT9
;
1723 pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__
, pa_type
);
1724 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
1728 * If this is the RFC style, wrap the signed data to make
1729 * decoding easier in the verify routine.
1730 * For draft9-compatible, we don't do anything because it
1731 * is already wrapped.
1733 #ifdef LONGHORN_BETA_COMPAT
1735 * The Longhorn server returns the expected RFC-style data, but
1736 * it is missing the sequence tag and length, so it requires
1737 * special processing when wrapping.
1738 * This will hopefully be fixed before the final release and
1739 * this can all be removed.
1741 if (msg_type
== CMS_ENVEL_SERVER
|| longhorn
== 1) {
1742 retval
= wrap_signeddata(tmp_buf
, tmp_buf_len
,
1743 &tmp_buf2
, &tmp_buf2_len
, longhorn
);
1745 pkiDebug("failed to encode signeddata\n");
1749 vfy_buf_len
= tmp_buf2_len
;
1753 vfy_buf_len
= tmp_buf_len
;
1756 if (msg_type
== CMS_ENVEL_SERVER
) {
1757 retval
= wrap_signeddata(tmp_buf
, tmp_buf_len
,
1758 &tmp_buf2
, &tmp_buf2_len
);
1760 pkiDebug("failed to encode signeddata\n");
1764 vfy_buf_len
= tmp_buf2_len
;
1768 vfy_buf_len
= tmp_buf_len
;
1773 print_buffer_bin(vfy_buf
, vfy_buf_len
, "/tmp/client_enc_keypack2");
1776 retval
= cms_signeddata_verify(context
, plg_cryptoctx
, req_cryptoctx
,
1777 id_cryptoctx
, msg_type
,
1778 require_crl_checking
,
1779 vfy_buf
, vfy_buf_len
,
1780 data
, data_len
, NULL
, NULL
);
1783 pkiDebug("PKCS7 Verification Success\n");
1785 pkiDebug("PKCS7 Verification Failure\n");
1804 static krb5_error_code
1805 crypto_retrieve_X509_sans(krb5_context context
,
1806 pkinit_plg_crypto_context plgctx
,
1807 pkinit_req_crypto_context reqctx
,
1809 krb5_principal
**princs_ret
,
1810 krb5_principal
**upn_ret
,
1811 unsigned char ***dns_ret
)
1813 krb5_error_code retval
= EINVAL
;
1814 char buf
[DN_BUF_LEN
];
1815 int p
= 0, u
= 0, d
= 0;
1816 krb5_principal
*princs
= NULL
;
1817 krb5_principal
*upns
= NULL
;
1818 unsigned char **dnss
= NULL
;
1819 int i
, num_found
= 0;
1821 if (princs_ret
== NULL
&& upn_ret
== NULL
&& dns_ret
== NULL
) {
1822 pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__
);
1827 pkiDebug("%s: no certificate!\n", __FUNCTION__
);
1831 X509_NAME_oneline(X509_get_subject_name(cert
),
1833 pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__
, buf
);
1835 if ((i
= X509_get_ext_by_NID(cert
, NID_subject_alt_name
, -1)) >= 0) {
1836 X509_EXTENSION
*ext
= NULL
;
1837 GENERAL_NAMES
*ialt
= NULL
;
1838 GENERAL_NAME
*gen
= NULL
;
1840 unsigned int num_sans
= 0;
1842 if (!(ext
= X509_get_ext(cert
, i
)) || !(ialt
= X509V3_EXT_d2i(ext
))) {
1843 pkiDebug("%s: found no subject alt name extensions\n",
1847 num_sans
= sk_GENERAL_NAME_num(ialt
);
1849 pkiDebug("%s: found %d subject alt name extension(s)\n",
1850 __FUNCTION__
, num_sans
);
1852 /* OK, we're likely returning something. Allocate return values */
1853 if (princs_ret
!= NULL
) {
1854 princs
= calloc(num_sans
+ 1, sizeof(krb5_principal
));
1855 if (princs
== NULL
) {
1860 if (upn_ret
!= NULL
) {
1861 upns
= calloc(num_sans
+ 1, sizeof(krb5_principal
));
1867 if (dns_ret
!= NULL
) {
1868 dnss
= calloc(num_sans
+ 1, sizeof(*dnss
));
1875 for (i
= 0; i
< num_sans
; i
++) {
1876 krb5_data name
= { 0, 0, NULL
};
1878 gen
= sk_GENERAL_NAME_value(ialt
, i
);
1879 switch (gen
->type
) {
1881 name
.length
= gen
->d
.otherName
->value
->value
.sequence
->length
;
1882 name
.data
= (char *)gen
->d
.otherName
->value
->value
.sequence
->data
;
1884 && OBJ_cmp(plgctx
->id_pkinit_san
,
1885 gen
->d
.otherName
->type_id
) == 0) {
1887 print_buffer_bin((unsigned char *)name
.data
, name
.length
,
1890 ret
= k5int_decode_krb5_principal_name(&name
, &princs
[p
]);
1892 pkiDebug("%s: failed decoding pkinit san value\n",
1898 } else if (upns
!= NULL
1899 && OBJ_cmp(plgctx
->id_ms_san_upn
,
1900 gen
->d
.otherName
->type_id
) == 0) {
1901 ret
= krb5_parse_name(context
, name
.data
, &upns
[u
]);
1903 pkiDebug("%s: failed parsing ms-upn san value\n",
1910 pkiDebug("%s: unrecognized othername oid in SAN\n",
1918 pkiDebug("%s: found dns name = %s\n",
1919 __FUNCTION__
, gen
->d
.dNSName
->data
);
1920 dnss
[d
] = (unsigned char *)
1921 strdup((char *)gen
->d
.dNSName
->data
);
1922 if (dnss
[d
] == NULL
) {
1923 pkiDebug("%s: failed to duplicate dns name\n",
1932 pkiDebug("%s: SAN type = %d expecting %d\n",
1933 __FUNCTION__
, gen
->type
, GEN_OTHERNAME
);
1936 sk_GENERAL_NAME_pop_free(ialt
, GENERAL_NAME_free
);
1941 *princs_ret
= princs
;
1949 if (princs
!= NULL
) {
1950 for (i
= 0; princs
[i
] != NULL
; i
++)
1951 krb5_free_principal(context
, princs
[i
]);
1955 for (i
= 0; upns
[i
] != NULL
; i
++)
1956 krb5_free_principal(context
, upns
[i
]);
1960 for (i
= 0; dnss
[i
] != NULL
; i
++)
1970 crypto_retrieve_cert_sans(krb5_context context
,
1971 pkinit_plg_crypto_context plgctx
,
1972 pkinit_req_crypto_context reqctx
,
1973 pkinit_identity_crypto_context idctx
,
1974 krb5_principal
**princs_ret
,
1975 krb5_principal
**upn_ret
,
1976 unsigned char ***dns_ret
)
1978 krb5_error_code retval
= EINVAL
;
1980 if (reqctx
->received_cert
== NULL
) {
1981 pkiDebug("%s: No certificate!\n", __FUNCTION__
);
1985 return crypto_retrieve_X509_sans(context
, plgctx
, reqctx
,
1986 reqctx
->received_cert
, princs_ret
,
1992 crypto_check_cert_eku(krb5_context context
,
1993 pkinit_plg_crypto_context plgctx
,
1994 pkinit_req_crypto_context reqctx
,
1995 pkinit_identity_crypto_context idctx
,
1996 int checking_kdc_cert
,
1997 int allow_secondary_usage
,
2000 char buf
[DN_BUF_LEN
];
2002 krb5_error_code retval
= EINVAL
;
2005 /* Solaris Kerberos */
2006 if (valid_eku
== NULL
)
2010 if (reqctx
->received_cert
== NULL
)
2013 X509_NAME_oneline(X509_get_subject_name(reqctx
->received_cert
),
2015 pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__
, buf
);
2017 if ((i
= X509_get_ext_by_NID(reqctx
->received_cert
,
2018 NID_ext_key_usage
, -1)) >= 0) {
2019 EXTENDED_KEY_USAGE
*extusage
;
2021 extusage
= X509_get_ext_d2i(reqctx
->received_cert
, NID_ext_key_usage
,
2024 pkiDebug("%s: found eku info in the cert\n", __FUNCTION__
);
2025 for (i
= 0; found_eku
== 0 && i
< sk_ASN1_OBJECT_num(extusage
); i
++) {
2026 ASN1_OBJECT
*tmp_oid
;
2028 tmp_oid
= sk_ASN1_OBJECT_value(extusage
, i
);
2029 pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
2030 __FUNCTION__
, i
+1, sk_ASN1_OBJECT_num(extusage
),
2031 allow_secondary_usage
);
2032 if (checking_kdc_cert
) {
2033 if ((OBJ_cmp(tmp_oid
, plgctx
->id_pkinit_KPKdc
) == 0)
2034 || (allow_secondary_usage
2035 && OBJ_cmp(tmp_oid
, plgctx
->id_kp_serverAuth
) == 0))
2038 if ((OBJ_cmp(tmp_oid
, plgctx
->id_pkinit_KPClientAuth
) == 0)
2039 || (allow_secondary_usage
2040 && OBJ_cmp(tmp_oid
, plgctx
->id_ms_kp_sc_logon
) == 0))
2045 EXTENDED_KEY_USAGE_free(extusage
);
2048 ASN1_BIT_STRING
*usage
= NULL
;
2049 pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__
);
2051 /* check that digitalSignature KeyUsage is present */
2052 if ((usage
= X509_get_ext_d2i(reqctx
->received_cert
,
2053 NID_key_usage
, NULL
, NULL
))) {
2055 if (!ku_reject(reqctx
->received_cert
,
2056 X509v3_KU_DIGITAL_SIGNATURE
)) {
2057 pkiDebug("%s: found digitalSignature KU\n",
2061 pkiDebug("%s: didn't find digitalSignature KU\n",
2064 ASN1_BIT_STRING_free(usage
);
2069 pkiDebug("%s: returning retval %d, valid_eku %d\n",
2070 __FUNCTION__
, retval
, *valid_eku
);
2075 pkinit_octetstring2key(krb5_context context
,
2078 unsigned int dh_key_len
,
2079 krb5_keyblock
* key_block
)
2081 krb5_error_code retval
;
2082 unsigned char *buf
= NULL
;
2083 unsigned char md
[SHA_DIGEST_LENGTH
];
2084 unsigned char counter
;
2085 size_t keybytes
, keylength
, offset
;
2086 krb5_data random_data
;
2089 if ((buf
= (unsigned char *) malloc(dh_key_len
)) == NULL
) {
2093 (void) memset(buf
, 0, dh_key_len
);
2101 SHA1_Update(&c
, &counter
, 1);
2102 SHA1_Update(&c
, key
, dh_key_len
);
2105 if (dh_key_len
- offset
< sizeof(md
))
2106 (void) memcpy(buf
+ offset
, md
, dh_key_len
- offset
);
2108 (void) memcpy(buf
+ offset
, md
, sizeof(md
));
2110 offset
+= sizeof(md
);
2112 } while (offset
< dh_key_len
);
2114 /* Solaris Kerberos */
2115 key_block
->magic
= KV5M_KEYBLOCK
;
2116 key_block
->enctype
= etype
;
2118 retval
= krb5_c_keylengths(context
, etype
, &keybytes
, &keylength
);
2122 key_block
->length
= keylength
;
2123 key_block
->contents
= calloc(keylength
, sizeof(unsigned char *));
2124 if (key_block
->contents
== NULL
) {
2129 random_data
.length
= keybytes
;
2130 random_data
.data
= (char *)buf
;
2132 retval
= krb5_c_random_to_key(context
, etype
, &random_data
, key_block
);
2136 if (retval
&& key_block
->contents
!= NULL
&& key_block
->length
!= 0) {
2137 (void) memset(key_block
->contents
, 0, key_block
->length
);
2138 key_block
->length
= 0;
2146 client_create_dh(krb5_context context
,
2147 pkinit_plg_crypto_context plg_cryptoctx
,
2148 pkinit_req_crypto_context cryptoctx
,
2149 pkinit_identity_crypto_context id_cryptoctx
,
2151 unsigned char **dh_params
,
2152 unsigned int *dh_params_len
,
2153 unsigned char **dh_pubkey
,
2154 unsigned int *dh_pubkey_len
)
2156 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
2157 unsigned char *buf
= NULL
;
2159 ASN1_INTEGER
*pub_key
= NULL
;
2161 if (cryptoctx
->dh
== NULL
) {
2162 if ((cryptoctx
->dh
= DH_new()) == NULL
)
2164 if ((cryptoctx
->dh
->g
= BN_new()) == NULL
||
2165 (cryptoctx
->dh
->q
= BN_new()) == NULL
)
2170 pkiDebug("client uses 1024 DH keys\n");
2171 cryptoctx
->dh
->p
= get_rfc2409_prime_1024(NULL
);
2174 pkiDebug("client uses 2048 DH keys\n");
2175 cryptoctx
->dh
->p
= BN_bin2bn(pkinit_2048_dhprime
,
2176 sizeof(pkinit_2048_dhprime
), NULL
);
2179 pkiDebug("client uses 4096 DH keys\n");
2180 cryptoctx
->dh
->p
= BN_bin2bn(pkinit_4096_dhprime
,
2181 sizeof(pkinit_4096_dhprime
), NULL
);
2187 BN_set_word((cryptoctx
->dh
->g
), DH_GENERATOR_2
);
2188 BN_rshift1(cryptoctx
->dh
->q
, cryptoctx
->dh
->p
);
2191 DH_generate_key(cryptoctx
->dh
);
2192 /* Solaris Kerberos */
2194 DH_check(cryptoctx
->dh
, &dh_err
);
2196 pkiDebug("Warning: dh_check failed with %d\n", dh_err
);
2197 if (dh_err
& DH_CHECK_P_NOT_PRIME
)
2198 pkiDebug("p value is not prime\n");
2199 if (dh_err
& DH_CHECK_P_NOT_SAFE_PRIME
)
2200 pkiDebug("p value is not a safe prime\n");
2201 if (dh_err
& DH_UNABLE_TO_CHECK_GENERATOR
)
2202 pkiDebug("unable to check the generator value\n");
2203 if (dh_err
& DH_NOT_SUITABLE_GENERATOR
)
2204 pkiDebug("the g value is not a generator\n");
2208 print_dh(cryptoctx
->dh
, "client's DH params\n");
2209 print_pubkey(cryptoctx
->dh
->pub_key
, "client's pub_key=");
2212 DH_check_pub_key(cryptoctx
->dh
, cryptoctx
->dh
->pub_key
, &dh_err
);
2214 pkiDebug("dh_check_pub_key failed with %d\n", dh_err
);
2219 /* aglo: usually we could just call i2d_DHparams to encode DH params
2220 * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
2222 retval
= pkinit_encode_dh_params(cryptoctx
->dh
->p
, cryptoctx
->dh
->g
,
2223 cryptoctx
->dh
->q
, dh_params
, dh_params_len
);
2227 /* pack DH public key */
2228 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2229 * encoding shall be used as the contents (the value) of the
2230 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2233 if ((pub_key
= BN_to_ASN1_INTEGER(cryptoctx
->dh
->pub_key
, NULL
)) == NULL
)
2235 *dh_pubkey_len
= i2d_ASN1_INTEGER(pub_key
, NULL
);
2236 if ((buf
= *dh_pubkey
= (unsigned char *)
2237 malloc((size_t) *dh_pubkey_len
)) == NULL
) {
2241 i2d_ASN1_INTEGER(pub_key
, &buf
);
2243 if (pub_key
!= NULL
)
2244 ASN1_INTEGER_free(pub_key
);
2250 if (cryptoctx
->dh
!= NULL
)
2251 DH_free(cryptoctx
->dh
);
2252 cryptoctx
->dh
= NULL
;
2257 if (pub_key
!= NULL
)
2258 ASN1_INTEGER_free(pub_key
);
2265 client_process_dh(krb5_context context
,
2266 pkinit_plg_crypto_context plg_cryptoctx
,
2267 pkinit_req_crypto_context cryptoctx
,
2268 pkinit_identity_crypto_context id_cryptoctx
,
2269 unsigned char *subjectPublicKey_data
,
2270 unsigned int subjectPublicKey_length
,
2271 unsigned char **client_key
,
2272 unsigned int *client_key_len
)
2274 /* Solaris Kerberos */
2275 krb5_error_code retval
= KRB5_PREAUTH_FAILED
;
2276 BIGNUM
*server_pub_key
= NULL
;
2277 ASN1_INTEGER
*pub_key
= NULL
;
2278 const unsigned char *p
= NULL
;
2279 unsigned char *data
= NULL
;
2282 /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */
2284 if (der_decode_data(subjectPublicKey_data
, (long)subjectPublicKey_length
,
2285 &data
, &data_len
) != 0) {
2286 pkiDebug("failed to decode subjectPublicKey\n");
2287 /* Solaris Kerberos */
2288 retval
= KRB5_PREAUTH_FAILED
;
2292 *client_key_len
= DH_size(cryptoctx
->dh
);
2293 if ((*client_key
= (unsigned char *)
2294 malloc((size_t) *client_key_len
)) == NULL
) {
2299 if ((pub_key
= d2i_ASN1_INTEGER(NULL
, &p
, data_len
)) == NULL
)
2301 if ((server_pub_key
= ASN1_INTEGER_to_BN(pub_key
, NULL
)) == NULL
)
2304 DH_compute_key(*client_key
, server_pub_key
, cryptoctx
->dh
);
2306 print_pubkey(server_pub_key
, "server's pub_key=");
2307 pkiDebug("client secret key (%d)= ", *client_key_len
);
2308 print_buffer(*client_key
, *client_key_len
);
2312 if (server_pub_key
!= NULL
)
2313 BN_free(server_pub_key
);
2314 if (pub_key
!= NULL
)
2315 ASN1_INTEGER_free(pub_key
);
2323 if (pub_key
!= NULL
)
2324 ASN1_INTEGER_free(pub_key
);
2332 server_check_dh(krb5_context context
,
2333 pkinit_plg_crypto_context cryptoctx
,
2334 pkinit_req_crypto_context req_cryptoctx
,
2335 pkinit_identity_crypto_context id_cryptoctx
,
2336 krb5_octet_data
*dh_params
,
2340 unsigned char *tmp
= NULL
;
2342 krb5_error_code retval
= KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
;
2344 tmp
= dh_params
->data
;
2346 dh
= pkinit_decode_dh_params(&dh
, &tmp
, dh_params
->length
);
2348 pkiDebug("failed to decode dhparams\n");
2352 /* KDC SHOULD check to see if the key parameters satisfy its policy */
2353 dh_prime_bits
= BN_num_bits(dh
->p
);
2354 if (minbits
&& dh_prime_bits
< minbits
) {
2355 pkiDebug("client sent dh params with %d bits, we require %d\n",
2356 dh_prime_bits
, minbits
);
2360 /* check dhparams is group 2 */
2361 if (pkinit_check_dh_params(cryptoctx
->dh_1024
->p
,
2362 dh
->p
, dh
->g
, dh
->q
) == 0) {
2367 /* check dhparams is group 14 */
2368 if (pkinit_check_dh_params(cryptoctx
->dh_2048
->p
,
2369 dh
->p
, dh
->g
, dh
->q
) == 0) {
2374 /* check dhparams is group 16 */
2375 if (pkinit_check_dh_params(cryptoctx
->dh_4096
->p
,
2376 dh
->p
, dh
->g
, dh
->q
) == 0) {
2383 req_cryptoctx
->dh
= dh
;
2390 /* kdc's dh function */
2393 server_process_dh(krb5_context context
,
2394 pkinit_plg_crypto_context plg_cryptoctx
,
2395 pkinit_req_crypto_context cryptoctx
,
2396 pkinit_identity_crypto_context id_cryptoctx
,
2397 unsigned char *data
,
2398 unsigned int data_len
,
2399 unsigned char **dh_pubkey
,
2400 unsigned int *dh_pubkey_len
,
2401 unsigned char **server_key
,
2402 unsigned int *server_key_len
)
2404 /* Solaris Kerberos */
2405 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2406 DH
*dh
= NULL
, *dh_server
= NULL
;
2407 unsigned char *p
= NULL
;
2408 ASN1_INTEGER
*pub_key
= NULL
;
2410 /* get client's received DH parameters that we saved in server_check_dh */
2413 dh_server
= DH_new();
2414 if (dh_server
== NULL
)
2416 dh_server
->p
= BN_dup(dh
->p
);
2417 dh_server
->g
= BN_dup(dh
->g
);
2418 dh_server
->q
= BN_dup(dh
->q
);
2420 /* decode client's public key */
2422 pub_key
= d2i_ASN1_INTEGER(NULL
, (const unsigned char **)&p
, (int)data_len
);
2423 if (pub_key
== NULL
)
2425 dh
->pub_key
= ASN1_INTEGER_to_BN(pub_key
, NULL
);
2426 if (dh
->pub_key
== NULL
)
2428 ASN1_INTEGER_free(pub_key
);
2430 if (!DH_generate_key(dh_server
))
2433 /* generate DH session key */
2434 *server_key_len
= DH_size(dh_server
);
2435 if ((*server_key
= (unsigned char *) malloc((size_t)*server_key_len
)) == NULL
)
2437 DH_compute_key(*server_key
, dh
->pub_key
, dh_server
);
2440 print_dh(dh_server
, "client&server's DH params\n");
2441 print_pubkey(dh
->pub_key
, "client's pub_key=");
2442 print_pubkey(dh_server
->pub_key
, "server's pub_key=");
2443 pkiDebug("server secret key=");
2444 print_buffer(*server_key
, *server_key_len
);
2448 /* pack DH public key */
2449 /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
2450 * encoding shall be used as the contents (the value) of the
2451 * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
2454 if ((pub_key
= BN_to_ASN1_INTEGER(dh_server
->pub_key
, NULL
)) == NULL
)
2456 *dh_pubkey_len
= i2d_ASN1_INTEGER(pub_key
, NULL
);
2457 if ((p
= *dh_pubkey
= (unsigned char *) malloc((size_t)*dh_pubkey_len
)) == NULL
)
2459 i2d_ASN1_INTEGER(pub_key
, &p
);
2460 if (pub_key
!= NULL
)
2461 ASN1_INTEGER_free(pub_key
);
2465 if (dh_server
!= NULL
)
2470 if (dh_server
!= NULL
)
2480 * Add locking around did_init to make it MT-safe.
2482 static krb5_error_code
2485 krb5_error_code ret
= 0;
2486 static int did_init
= 0;
2487 static k5_mutex_t init_mutex
= K5_MUTEX_PARTIAL_INITIALIZER
;
2489 ret
= k5_mutex_lock(&init_mutex
);
2492 /* initialize openssl routines */
2493 CRYPTO_malloc_init();
2494 ERR_load_crypto_strings();
2495 OpenSSL_add_all_algorithms();
2498 k5_mutex_unlock(&init_mutex
);
2503 static krb5_error_code
2504 pkinit_encode_dh_params(BIGNUM
*p
, BIGNUM
*g
, BIGNUM
*q
,
2505 unsigned char **buf
, unsigned int *buf_len
)
2507 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
2508 int bufsize
= 0, r
= 0;
2509 unsigned char *tmp
= NULL
;
2510 ASN1_INTEGER
*ap
= NULL
, *ag
= NULL
, *aq
= NULL
;
2512 if ((ap
= BN_to_ASN1_INTEGER(p
, NULL
)) == NULL
)
2514 if ((ag
= BN_to_ASN1_INTEGER(g
, NULL
)) == NULL
)
2516 if ((aq
= BN_to_ASN1_INTEGER(q
, NULL
)) == NULL
)
2518 bufsize
= i2d_ASN1_INTEGER(ap
, NULL
);
2519 bufsize
+= i2d_ASN1_INTEGER(ag
, NULL
);
2520 bufsize
+= i2d_ASN1_INTEGER(aq
, NULL
);
2522 r
= ASN1_object_size(1, bufsize
, V_ASN1_SEQUENCE
);
2524 tmp
= *buf
= (unsigned char *)malloc((size_t) r
);
2528 ASN1_put_object(&tmp
, 1, bufsize
, V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
2530 i2d_ASN1_INTEGER(ap
, &tmp
);
2531 i2d_ASN1_INTEGER(ag
, &tmp
);
2532 i2d_ASN1_INTEGER(aq
, &tmp
);
2540 ASN1_INTEGER_free(ap
);
2542 ASN1_INTEGER_free(ag
);
2544 ASN1_INTEGER_free(aq
);
2550 pkinit_decode_dh_params(DH
** a
, unsigned char **pp
, unsigned int len
)
2552 ASN1_INTEGER ai
, *aip
= NULL
;
2553 long length
= (long) len
;
2555 M_ASN1_D2I_vars(a
, DH
*, DH_new
);
2558 M_ASN1_D2I_start_sequence();
2562 M_ASN1_D2I_get_x(ASN1_INTEGER
, aip
, d2i_ASN1_INTEGER
);
2566 (*a
)->p
= ASN1_INTEGER_to_BN(aip
, NULL
);
2567 if ((*a
)->p
== NULL
)
2569 if (ai
.data
!= NULL
) {
2570 OPENSSL_free(ai
.data
);
2575 M_ASN1_D2I_get_x(ASN1_INTEGER
, aip
, d2i_ASN1_INTEGER
);
2579 (*a
)->g
= ASN1_INTEGER_to_BN(aip
, NULL
);
2580 if ((*a
)->g
== NULL
)
2582 if (ai
.data
!= NULL
) {
2583 OPENSSL_free(ai
.data
);
2589 M_ASN1_D2I_get_x(ASN1_INTEGER
, aip
, d2i_ASN1_INTEGER
);
2593 (*a
)->q
= ASN1_INTEGER_to_BN(aip
, NULL
);
2594 if ((*a
)->q
== NULL
)
2596 if (ai
.data
!= NULL
) {
2597 OPENSSL_free(ai
.data
);
2603 M_ASN1_D2I_end_sequence();
2604 M_ASN1_D2I_Finish(a
, DH_free
, 0);
2608 static krb5_error_code
2609 pkinit_create_sequence_of_principal_identifiers(
2610 krb5_context context
,
2611 pkinit_plg_crypto_context plg_cryptoctx
,
2612 pkinit_req_crypto_context req_cryptoctx
,
2613 pkinit_identity_crypto_context id_cryptoctx
,
2615 krb5_data
**out_data
)
2617 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2618 krb5_external_principal_identifier
**krb5_trusted_certifiers
= NULL
;
2619 krb5_data
*td_certifiers
= NULL
, *data
= NULL
;
2620 krb5_typed_data
**typed_data
= NULL
;
2623 case TD_TRUSTED_CERTIFIERS
:
2624 retval
= create_krb5_trustedCertifiers(context
, plg_cryptoctx
,
2625 req_cryptoctx
, id_cryptoctx
, &krb5_trusted_certifiers
);
2627 pkiDebug("create_krb5_trustedCertifiers failed\n");
2631 case TD_INVALID_CERTIFICATES
:
2632 retval
= create_krb5_invalidCertificates(context
, plg_cryptoctx
,
2633 req_cryptoctx
, id_cryptoctx
, &krb5_trusted_certifiers
);
2635 pkiDebug("create_krb5_invalidCertificates failed\n");
2644 retval
= k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier
**)krb5_trusted_certifiers
, &td_certifiers
);
2646 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
2650 print_buffer_bin((unsigned char *)td_certifiers
->data
,
2651 td_certifiers
->length
, "/tmp/kdc_td_certifiers");
2653 typed_data
= malloc (2 * sizeof(krb5_typed_data
*));
2654 if (typed_data
== NULL
) {
2658 typed_data
[1] = NULL
;
2659 init_krb5_typed_data(&typed_data
[0]);
2660 if (typed_data
[0] == NULL
) {
2664 typed_data
[0]->type
= type
;
2665 typed_data
[0]->length
= td_certifiers
->length
;
2666 typed_data
[0]->data
= (unsigned char *)td_certifiers
->data
;
2667 retval
= k5int_encode_krb5_typed_data((const krb5_typed_data
**)typed_data
,
2670 pkiDebug("encode_krb5_typed_data failed\n");
2674 print_buffer_bin((unsigned char *)data
->data
, data
->length
,
2677 *out_data
= (krb5_data
*)malloc(sizeof(krb5_data
));
2678 (*out_data
)->length
= data
->length
;
2679 (*out_data
)->data
= (char *)malloc(data
->length
);
2680 (void) memcpy((*out_data
)->data
, data
->data
, data
->length
);
2685 if (krb5_trusted_certifiers
!= NULL
)
2686 free_krb5_external_principal_identifier(&krb5_trusted_certifiers
);
2693 free(td_certifiers
);
2695 if (typed_data
!= NULL
)
2696 free_krb5_typed_data(&typed_data
);
2702 pkinit_create_td_trusted_certifiers(krb5_context context
,
2703 pkinit_plg_crypto_context plg_cryptoctx
,
2704 pkinit_req_crypto_context req_cryptoctx
,
2705 pkinit_identity_crypto_context id_cryptoctx
,
2706 krb5_data
**out_data
)
2708 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2710 retval
= pkinit_create_sequence_of_principal_identifiers(context
,
2711 plg_cryptoctx
, req_cryptoctx
, id_cryptoctx
,
2712 TD_TRUSTED_CERTIFIERS
, out_data
);
2718 pkinit_create_td_invalid_certificate(
2719 krb5_context context
,
2720 pkinit_plg_crypto_context plg_cryptoctx
,
2721 pkinit_req_crypto_context req_cryptoctx
,
2722 pkinit_identity_crypto_context id_cryptoctx
,
2723 krb5_data
**out_data
)
2725 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2727 retval
= pkinit_create_sequence_of_principal_identifiers(context
,
2728 plg_cryptoctx
, req_cryptoctx
, id_cryptoctx
,
2729 TD_INVALID_CERTIFICATES
, out_data
);
2736 pkinit_create_td_dh_parameters(krb5_context context
,
2737 pkinit_plg_crypto_context plg_cryptoctx
,
2738 pkinit_req_crypto_context req_cryptoctx
,
2739 pkinit_identity_crypto_context id_cryptoctx
,
2740 pkinit_plg_opts
*opts
,
2741 krb5_data
**out_data
)
2743 /* Solaris Kerberos */
2744 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
2745 unsigned int buf1_len
= 0, buf2_len
= 0, buf3_len
= 0, i
= 0;
2746 unsigned char *buf1
= NULL
, *buf2
= NULL
, *buf3
= NULL
;
2747 krb5_typed_data
**typed_data
= NULL
;
2748 krb5_data
*data
= NULL
, *encoded_algId
= NULL
;
2749 krb5_algorithm_identifier
**algId
= NULL
;
2751 /* Solaris Kerberos */
2752 if (opts
->dh_min_bits
> 4096) {
2757 if (opts
->dh_min_bits
<= 1024) {
2758 retval
= pkinit_encode_dh_params(plg_cryptoctx
->dh_1024
->p
,
2759 plg_cryptoctx
->dh_1024
->g
, plg_cryptoctx
->dh_1024
->q
,
2764 if (opts
->dh_min_bits
<= 2048) {
2765 retval
= pkinit_encode_dh_params(plg_cryptoctx
->dh_2048
->p
,
2766 plg_cryptoctx
->dh_2048
->g
, plg_cryptoctx
->dh_2048
->q
,
2771 retval
= pkinit_encode_dh_params(plg_cryptoctx
->dh_4096
->p
,
2772 plg_cryptoctx
->dh_4096
->g
, plg_cryptoctx
->dh_4096
->q
,
2777 if (opts
->dh_min_bits
<= 1024) {
2778 algId
= malloc(4 * sizeof(krb5_algorithm_identifier
*));
2782 algId
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2783 if (algId
[0] == NULL
)
2785 algId
[0]->parameters
.data
= (unsigned char *)malloc(buf2_len
);
2786 if (algId
[0]->parameters
.data
== NULL
)
2788 (void) memcpy(algId
[0]->parameters
.data
, buf2
, buf2_len
);
2789 algId
[0]->parameters
.length
= buf2_len
;
2790 algId
[0]->algorithm
= dh_oid
;
2792 algId
[1] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2793 if (algId
[1] == NULL
)
2795 algId
[1]->parameters
.data
= (unsigned char *)malloc(buf3_len
);
2796 if (algId
[1]->parameters
.data
== NULL
)
2798 (void) memcpy(algId
[1]->parameters
.data
, buf3
, buf3_len
);
2799 algId
[1]->parameters
.length
= buf3_len
;
2800 algId
[1]->algorithm
= dh_oid
;
2802 algId
[2] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2803 if (algId
[2] == NULL
)
2805 algId
[2]->parameters
.data
= (unsigned char *)malloc(buf1_len
);
2806 if (algId
[2]->parameters
.data
== NULL
)
2808 (void) memcpy(algId
[2]->parameters
.data
, buf1
, buf1_len
);
2809 algId
[2]->parameters
.length
= buf1_len
;
2810 algId
[2]->algorithm
= dh_oid
;
2812 } else if (opts
->dh_min_bits
<= 2048) {
2813 algId
= malloc(3 * sizeof(krb5_algorithm_identifier
*));
2817 algId
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2818 if (algId
[0] == NULL
)
2820 algId
[0]->parameters
.data
= (unsigned char *)malloc(buf2_len
);
2821 if (algId
[0]->parameters
.data
== NULL
)
2823 (void) memcpy(algId
[0]->parameters
.data
, buf2
, buf2_len
);
2824 algId
[0]->parameters
.length
= buf2_len
;
2825 algId
[0]->algorithm
= dh_oid
;
2827 algId
[1] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2828 if (algId
[1] == NULL
)
2830 algId
[1]->parameters
.data
= (unsigned char *)malloc(buf3_len
);
2831 if (algId
[1]->parameters
.data
== NULL
)
2833 (void) memcpy(algId
[1]->parameters
.data
, buf3
, buf3_len
);
2834 algId
[1]->parameters
.length
= buf3_len
;
2835 algId
[1]->algorithm
= dh_oid
;
2837 } else if (opts
->dh_min_bits
<= 4096) {
2838 algId
= malloc(2 * sizeof(krb5_algorithm_identifier
*));
2842 algId
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
2843 if (algId
[0] == NULL
)
2845 algId
[0]->parameters
.data
= (unsigned char *)malloc(buf3_len
);
2846 if (algId
[0]->parameters
.data
== NULL
)
2848 (void) memcpy(algId
[0]->parameters
.data
, buf3
, buf3_len
);
2849 algId
[0]->parameters
.length
= buf3_len
;
2850 algId
[0]->algorithm
= dh_oid
;
2853 retval
= k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier
**)algId
, &encoded_algId
);
2857 print_buffer_bin((unsigned char *)encoded_algId
->data
,
2858 encoded_algId
->length
, "/tmp/kdc_td_dh_params");
2860 typed_data
= malloc (2 * sizeof(krb5_typed_data
*));
2861 if (typed_data
== NULL
) {
2865 typed_data
[1] = NULL
;
2866 init_krb5_typed_data(&typed_data
[0]);
2867 if (typed_data
== NULL
) {
2871 typed_data
[0]->type
= TD_DH_PARAMETERS
;
2872 typed_data
[0]->length
= encoded_algId
->length
;
2873 typed_data
[0]->data
= (unsigned char *)encoded_algId
->data
;
2874 retval
= k5int_encode_krb5_typed_data((const krb5_typed_data
**)typed_data
,
2877 pkiDebug("encode_krb5_typed_data failed\n");
2881 print_buffer_bin((unsigned char *)data
->data
, data
->length
,
2884 *out_data
= (krb5_data
*)malloc(sizeof(krb5_data
));
2885 if (*out_data
== NULL
)
2887 (*out_data
)->length
= data
->length
;
2888 (*out_data
)->data
= (char *)malloc(data
->length
);
2889 if ((*out_data
)->data
== NULL
) {
2894 (void) memcpy((*out_data
)->data
, data
->data
, data
->length
);
2906 if (typed_data
!= NULL
)
2907 free_krb5_typed_data(&typed_data
);
2908 free(encoded_algId
);
2910 if (algId
!= NULL
) {
2911 while(algId
[i
] != NULL
) {
2912 free(algId
[i
]->parameters
.data
);
2924 pkinit_check_kdc_pkid(krb5_context context
,
2925 pkinit_plg_crypto_context plg_cryptoctx
,
2926 pkinit_req_crypto_context req_cryptoctx
,
2927 pkinit_identity_crypto_context id_cryptoctx
,
2928 unsigned char *pdid_buf
,
2929 unsigned int pkid_len
,
2932 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
2933 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
2934 const unsigned char *p
= pdid_buf
;
2936 X509
*kdc_cert
= sk_X509_value(id_cryptoctx
->my_certs
, id_cryptoctx
->cert_index
);
2939 pkiDebug("found kdcPkId in AS REQ\n");
2940 is
= d2i_PKCS7_ISSUER_AND_SERIAL(NULL
, &p
, (int)pkid_len
);
2944 status
= X509_NAME_cmp(X509_get_issuer_name(kdc_cert
), is
->issuer
);
2946 status
= ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert
), is
->serial
);
2953 X509_NAME_free(is
->issuer
);
2954 ASN1_INTEGER_free(is
->serial
);
2961 pkinit_check_dh_params(BIGNUM
* p1
, BIGNUM
* p2
, BIGNUM
* g1
, BIGNUM
* q1
)
2963 BIGNUM
*g2
= NULL
, *q2
= NULL
;
2964 /* Solaris Kerberos */
2965 int retval
= EINVAL
;
2967 if (!BN_cmp(p1
, p2
)) {
2969 BN_set_word(g2
, DH_GENERATOR_2
);
2970 if (!BN_cmp(g1
, g2
)) {
2973 if (!BN_cmp(q1
, q2
)) {
2974 pkiDebug("good %d dhparams\n", BN_num_bits(p1
));
2977 pkiDebug("bad group 2 q dhparameter\n");
2980 pkiDebug("bad g dhparameter\n");
2983 pkiDebug("p is not well-known group 2 dhparameter\n");
2990 pkinit_process_td_dh_params(krb5_context context
,
2991 pkinit_plg_crypto_context cryptoctx
,
2992 pkinit_req_crypto_context req_cryptoctx
,
2993 pkinit_identity_crypto_context id_cryptoctx
,
2994 krb5_algorithm_identifier
**algId
,
2997 krb5_error_code retval
= KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
;
2998 int i
= 0, use_sent_dh
= 0, ok
= 0;
3000 pkiDebug("dh parameters\n");
3002 while (algId
[i
] != NULL
) {
3004 unsigned char *tmp
= NULL
;
3005 int dh_prime_bits
= 0;
3007 if (algId
[i
]->algorithm
.length
!= dh_oid
.length
||
3008 memcmp(algId
[i
]->algorithm
.data
, dh_oid
.data
, dh_oid
.length
))
3011 tmp
= algId
[i
]->parameters
.data
;
3013 dh
= pkinit_decode_dh_params(&dh
, &tmp
, algId
[i
]->parameters
.length
);
3014 dh_prime_bits
= BN_num_bits(dh
->p
);
3015 pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
3016 *new_dh_size
, dh_prime_bits
);
3017 switch(dh_prime_bits
) {
3019 if (pkinit_check_dh_params(cryptoctx
->dh_1024
->p
, dh
->p
,
3020 dh
->g
, dh
->q
) == 0) {
3021 *new_dh_size
= 1024;
3026 if (pkinit_check_dh_params(cryptoctx
->dh_2048
->p
, dh
->p
,
3027 dh
->g
, dh
->q
) == 0) {
3028 *new_dh_size
= 2048;
3033 if (pkinit_check_dh_params(cryptoctx
->dh_4096
->p
, dh
->p
,
3034 dh
->g
, dh
->q
) == 0) {
3035 *new_dh_size
= 4096;
3043 DH_check(dh
, &retval
);
3045 pkiDebug("DH parameters provided by server are unacceptable\n");
3046 retval
= KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED
;
3056 if (req_cryptoctx
->dh
!= NULL
) {
3057 DH_free(req_cryptoctx
->dh
);
3058 req_cryptoctx
->dh
= NULL
;
3061 req_cryptoctx
->dh
= dh
;
3076 openssl_callback(int ok
, X509_STORE_CTX
* ctx
)
3080 char buf
[DN_BUF_LEN
];
3082 X509_NAME_oneline(X509_get_subject_name(ctx
->current_cert
), buf
, sizeof(buf
));
3083 pkiDebug("cert = %s\n", buf
);
3084 pkiDebug("callback function: %d (%s)\n", ctx
->error
,
3085 X509_verify_cert_error_string(ctx
->error
));
3092 openssl_callback_ignore_crls(int ok
, X509_STORE_CTX
* ctx
)
3095 switch (ctx
->error
) {
3096 case X509_V_ERR_UNABLE_TO_GET_CRL
:
3105 static ASN1_OBJECT
*
3106 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx
, int pkcs7_type
)
3110 switch (pkcs7_type
) {
3111 case CMS_SIGN_CLIENT
:
3112 return cryptoctx
->id_pkinit_authData
;
3113 case CMS_SIGN_DRAFT9
:
3115 * Delay creating this OID until we know we need it.
3116 * It shadows an existing OpenSSL oid. If it
3117 * is created too early, it breaks things like
3118 * the use of pkcs12 (which uses pkcs7 structures).
3119 * We need this shadow version because our code
3120 * depends on the "other" type to be unknown to the
3123 if (cryptoctx
->id_pkinit_authData9
== NULL
) {
3124 pkiDebug("%s: Creating shadow instance of pkcs7-data oid\n",
3126 nid
= OBJ_create("1.2.840.113549.1.7.1", "id-pkcs7-data",
3128 if (nid
== NID_undef
)
3130 cryptoctx
->id_pkinit_authData9
= OBJ_nid2obj(nid
);
3132 return cryptoctx
->id_pkinit_authData9
;
3133 case CMS_SIGN_SERVER
:
3134 return cryptoctx
->id_pkinit_DHKeyData
;
3135 case CMS_ENVEL_SERVER
:
3136 return cryptoctx
->id_pkinit_rkeyData
;
3143 #ifdef LONGHORN_BETA_COMPAT
3146 * This is a version that worked with Longhorn Beta 3.
3149 wrap_signeddata(unsigned char *data
, unsigned int data_len
,
3150 unsigned char **out
, unsigned int *out_len
,
3151 int is_longhorn_server
)
3154 unsigned int orig_len
= 0, oid_len
= 0, tot_len
= 0;
3155 ASN1_OBJECT
*oid
= NULL
;
3156 unsigned char *p
= NULL
;
3158 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3159 __FUNCTION__
, is_longhorn_server
);
3161 /* Get length to wrap the original data with SEQUENCE tag */
3162 tot_len
= orig_len
= ASN1_object_size(1, (int)data_len
, V_ASN1_SEQUENCE
);
3164 if (is_longhorn_server
== 0) {
3165 /* Add the signedData OID and adjust lengths */
3166 oid
= OBJ_nid2obj(NID_pkcs7_signed
);
3167 oid_len
= i2d_ASN1_OBJECT(oid
, NULL
);
3169 tot_len
= ASN1_object_size(1, (int)(orig_len
+oid_len
), V_ASN1_SEQUENCE
);
3172 p
= *out
= (unsigned char *)malloc(tot_len
);
3173 if (p
== NULL
) return -1;
3175 if (is_longhorn_server
== 0) {
3176 ASN1_put_object(&p
, 1, (int)(orig_len
+oid_len
),
3177 V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3179 i2d_ASN1_OBJECT(oid
, &p
);
3181 ASN1_put_object(&p
, 1, (int)data_len
, 0, V_ASN1_CONTEXT_SPECIFIC
);
3183 ASN1_put_object(&p
, 1, (int)data_len
, V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3185 memcpy(p
, data
, data_len
);
3193 * This is a version that works with a patched Longhorn KDC.
3194 * (Which should match SP1 ??).
3197 wrap_signeddata(unsigned char *data
, unsigned int data_len
,
3198 unsigned char **out
, unsigned int *out_len
,
3199 int is_longhorn_server
)
3202 unsigned int oid_len
= 0, tot_len
= 0, wrap_len
= 0, tag_len
= 0;
3203 ASN1_OBJECT
*oid
= NULL
;
3204 unsigned char *p
= NULL
;
3206 pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
3207 __FUNCTION__
, is_longhorn_server
);
3209 /* New longhorn is missing another sequence */
3210 if (is_longhorn_server
== 1)
3211 wrap_len
= ASN1_object_size(1, (int)(data_len
), V_ASN1_SEQUENCE
);
3213 wrap_len
= data_len
;
3215 /* Get length to wrap the original data with SEQUENCE tag */
3216 tag_len
= ASN1_object_size(1, (int)wrap_len
, V_ASN1_SEQUENCE
);
3218 /* Always add oid */
3219 oid
= OBJ_nid2obj(NID_pkcs7_signed
);
3220 oid_len
= i2d_ASN1_OBJECT(oid
, NULL
);
3223 tot_len
= ASN1_object_size(1, (int)(oid_len
), V_ASN1_SEQUENCE
);
3225 p
= *out
= (unsigned char *)malloc(tot_len
);
3229 ASN1_put_object(&p
, 1, (int)(oid_len
),
3230 V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3232 i2d_ASN1_OBJECT(oid
, &p
);
3234 ASN1_put_object(&p
, 1, (int)wrap_len
, 0, V_ASN1_CONTEXT_SPECIFIC
);
3236 /* Wrap in extra seq tag */
3237 if (is_longhorn_server
== 1) {
3238 ASN1_put_object(&p
, 1, (int)data_len
, V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3240 (void) memcpy(p
, data
, data_len
);
3250 wrap_signeddata(unsigned char *data
, unsigned int data_len
,
3251 unsigned char **out
, unsigned int *out_len
)
3254 unsigned int orig_len
= 0, oid_len
= 0, tot_len
= 0;
3255 ASN1_OBJECT
*oid
= NULL
;
3256 unsigned char *p
= NULL
;
3258 /* Get length to wrap the original data with SEQUENCE tag */
3259 tot_len
= orig_len
= ASN1_object_size(1, (int)data_len
, V_ASN1_SEQUENCE
);
3261 /* Add the signedData OID and adjust lengths */
3262 oid
= OBJ_nid2obj(NID_pkcs7_signed
);
3263 oid_len
= i2d_ASN1_OBJECT(oid
, NULL
);
3265 tot_len
= ASN1_object_size(1, (int)(orig_len
+oid_len
), V_ASN1_SEQUENCE
);
3267 p
= *out
= (unsigned char *)malloc(tot_len
);
3268 if (p
== NULL
) return -1;
3270 ASN1_put_object(&p
, 1, (int)(orig_len
+oid_len
),
3271 V_ASN1_SEQUENCE
, V_ASN1_UNIVERSAL
);
3273 i2d_ASN1_OBJECT(oid
, &p
);
3275 ASN1_put_object(&p
, 1, (int)data_len
, 0, V_ASN1_CONTEXT_SPECIFIC
);
3276 (void) memcpy(p
, data
, data_len
);
3285 prepare_enc_data(unsigned char *indata
,
3287 unsigned char **outdata
,
3290 /* Solaris Kerberos */
3292 long length
= indata_len
;
3296 c
.pp
= (const unsigned char **)&indata
;
3297 c
.q
= *(const unsigned char **)&indata
;
3298 c
.error
= ERR_R_NESTED_ASN1_ERROR
;
3299 c
.p
= *(const unsigned char **)&indata
;
3300 c
.max
= (length
== 0)?0:(c
.p
+length
);
3302 asn1_GetSequence(&c
,&length
);
3304 ASN1_get_object(&c
.p
,&Tlen
,&Ttag
,&Tclass
,c
.slen
);
3306 ASN1_get_object(&c
.p
,&Tlen
,&Ttag
,&Tclass
,c
.slen
);
3308 asn1_const_Finish(&c
);
3310 *outdata
= (unsigned char *)malloc((size_t)Tlen
);
3311 /* Solaris Kerberos */
3312 if (outdata
== NULL
)
3315 (void) memcpy(*outdata
, c
.p
, (size_t)Tlen
);
3316 *outdata_len
= Tlen
;
3321 #ifndef WITHOUT_PKCS11
3323 pkinit_C_LoadModule(const char *modname
, CK_FUNCTION_LIST_PTR_PTR p11p
)
3326 CK_RV (*getflist
)(CK_FUNCTION_LIST_PTR_PTR
);
3328 pkiDebug("loading module \"%s\"... ", modname
);
3329 /* Solaris Kerberos */
3330 handle
= dlopen(modname
, RTLD_NOW
| RTLD_GROUP
);
3331 if (handle
== NULL
) {
3332 pkiDebug("not found\n");
3335 getflist
= (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR
)) dlsym(handle
, "C_GetFunctionList");
3336 if (getflist
== NULL
|| (*getflist
)(p11p
) != CKR_OK
) {
3337 (void) dlclose(handle
);
3338 pkiDebug("failed\n");
3346 pkinit_C_UnloadModule(void *handle
)
3348 /* Solaris Kerberos */
3349 if (dlclose(handle
) != 0)
3350 return CKR_GENERAL_ERROR
;
3356 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3359 * labelstr will be C string containing token label with trailing white space
3363 trim_token_label(CK_TOKEN_INFO
*tinfo
, char *labelstr
, unsigned int labelstr_len
)
3367 assert(labelstr_len
> sizeof (tinfo
->label
));
3369 * \0 terminate labelstr in case the last char in the token label is
3372 labelstr
[sizeof (tinfo
->label
)] = '\0';
3373 (void) memcpy(labelstr
, (char *) tinfo
->label
, sizeof (tinfo
->label
));
3375 /* init i so terminating \0 is skipped */
3376 for (i
= sizeof (tinfo
->label
) - 1; i
>= 0; i
--) {
3377 if (labelstr
[i
] == ' ')
3385 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3388 static krb5_error_code
3389 pkinit_prompt_user(krb5_context context
,
3390 pkinit_identity_crypto_context cctx
,
3396 krb5_prompt kprompt
;
3397 krb5_prompt_type prompt_type
;
3399 if (cctx
->prompter
== NULL
)
3402 kprompt
.prompt
= prompt
;
3403 kprompt
.hidden
= hidden
;
3404 kprompt
.reply
= reply
;
3406 * Note, assuming this type for now, may need to be passed in in the future.
3408 prompt_type
= KRB5_PROMPT_TYPE_PREAUTH
;
3410 /* PROMPTER_INVOCATION */
3411 k5int_set_prompt_types(context
, &prompt_type
);
3412 r
= (*cctx
->prompter
)(context
, cctx
->prompter_data
,
3413 NULL
, NULL
, 1, &kprompt
);
3414 k5int_set_prompt_types(context
, NULL
);
3419 * Solaris Kerberos: this function was changed to support a PIN being passed
3420 * in. If that is the case the user will not be prompted for their PIN.
3422 static krb5_error_code
3423 pkinit_login(krb5_context context
,
3424 pkinit_identity_crypto_context id_cryptoctx
,
3432 if (tip
->flags
& CKF_PROTECTED_AUTHENTICATION_PATH
) {
3435 } else if (id_cryptoctx
->PIN
!= NULL
) {
3436 if ((rdat
.data
= strdup(id_cryptoctx
->PIN
)) == NULL
)
3439 * Don't include NULL string terminator in length calculation as this
3440 * PIN is passed to the C_Login function and only the text chars should
3441 * be considered to be the PIN.
3443 rdat
.length
= strlen(id_cryptoctx
->PIN
);
3445 /* Solaris Kerberos - trim token label */
3446 char tmplabel
[sizeof (tip
->label
) + 1];
3448 if (!id_cryptoctx
->prompter
) {
3449 pkiDebug("pkinit_login: id_cryptoctx->prompter is NULL\n");
3450 /* Solaris Kerberos: Improved error messages */
3451 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3452 gettext("Failed to log into token: prompter function is NULL"));
3453 return (KRB5KDC_ERR_PREAUTH_FAILED
);
3455 /* Solaris Kerberos - Changes for gettext() */
3456 prompt_len
= sizeof (tip
->label
) + 256;
3457 if ((prompt
= (char *) malloc(prompt_len
)) == NULL
)
3460 /* Solaris Kerberos - trim token label which can be padded with space */
3461 trim_token_label(tip
, tmplabel
, sizeof (tmplabel
));
3462 (void) snprintf(prompt
, prompt_len
, gettext("%s PIN"), tmplabel
);
3464 /* Solaris Kerberos */
3465 if (tip
->flags
& CKF_USER_PIN_LOCKED
)
3466 (void) strlcat(prompt
, gettext(" (Warning: PIN locked)"), prompt_len
);
3467 else if (tip
->flags
& CKF_USER_PIN_FINAL_TRY
)
3468 (void) strlcat(prompt
, gettext(" (Warning: PIN final try)"), prompt_len
);
3469 else if (tip
->flags
& CKF_USER_PIN_COUNT_LOW
)
3470 (void) strlcat(prompt
, gettext(" (Warning: PIN count low)"), prompt_len
);
3471 rdat
.data
= malloc(tip
->ulMaxPinLen
+ 2);
3472 rdat
.length
= tip
->ulMaxPinLen
+ 1;
3474 * Note that the prompter function will set rdat.length such that the
3475 * NULL terminator is not included
3477 /* PROMPTER_INVOCATION */
3478 r
= pkinit_prompt_user(context
, id_cryptoctx
, &rdat
, prompt
, 1);
3483 r
= id_cryptoctx
->p11
->C_Login(id_cryptoctx
->session
, CKU_USER
,
3484 (u_char
*) rdat
.data
, rdat
.length
);
3487 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r
));
3488 /* Solaris Kerberos: Improved error messages */
3489 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3490 gettext("Failed to log into token: %s"),
3491 pkinit_pkcs11_code_to_text(r
));
3492 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3494 /* Solaris Kerberos: only need to login once */
3495 id_cryptoctx
->p11flags
|= C_LOGIN_DONE
;
3499 (void) memset(rdat
.data
, 0, rdat
.length
);
3507 * Solaris Kerberos: added these structs in support of prompting user for
3510 struct _token_entry
{
3512 CK_SESSION_HANDLE session
;
3513 CK_TOKEN_INFO token_info
;
3515 struct _token_choices
{
3516 unsigned int numtokens
;
3517 struct _token_entry
*token_array
;
3522 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3525 static krb5_error_code
3526 pkinit_prompt_token(krb5_context context
,
3527 pkinit_identity_crypto_context cctx
)
3531 char *token_prompt
= gettext("If you have a smartcard insert it now. "
3532 "Press enter to continue");
3534 reply
.data
= tmpbuf
;
3535 reply
.length
= sizeof(tmpbuf
);
3537 /* note, don't care about the reply */
3538 return (pkinit_prompt_user(context
, cctx
, &reply
, token_prompt
, 0));
3542 * Solaris Kerberos: new defines for prompting support.
3544 #define CHOOSE_THIS_TOKEN 0
3545 #define CHOOSE_RESCAN 1
3546 #define CHOOSE_SKIP 2
3547 #define CHOOSE_SEE_NEXT 3
3549 #define RESCAN_TOKENS -1
3550 #define SKIP_TOKENS -2
3553 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3556 * This prompts to user for various choices regarding a token to use. Note
3557 * that if there is no error, choice will be set to one of:
3558 * - the token_choices->token_array entry
3563 pkinit_choose_tokens(krb5_context context
,
3564 pkinit_identity_crypto_context cctx
,
3565 struct _token_choices
*token_choices
,
3570 * Assuming that PAM_MAX_MSG_SIZE is a reasonable restriction. Note that -
3571 * 2 is to account for the fact that a krb prompter to PAM conv bridge will
3574 char prompt
[PAM_MAX_MSG_SIZE
- 2];
3576 char tmplabel
[sizeof (token_choices
->token_array
->token_info
.label
) + 1];
3578 int i
, num_used
, tmpchoice
;
3580 assert(token_choices
!= NULL
);
3581 assert(choice
!= NULL
);
3583 /* Create the menu prompt */
3585 /* only need to do this once before the for loop */
3586 reply
.data
= tmpbuf
;
3588 for (i
= 0; i
< token_choices
->numtokens
; i
++) {
3590 trim_token_label(&token_choices
->token_array
[i
].token_info
, tmplabel
,
3593 if (i
== (token_choices
->numtokens
- 1)) {
3594 /* no more smartcards/tokens */
3595 if ((num_used
= snprintf(prompt
, sizeof (prompt
),
3596 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n",
3598 * TRANSLATION_NOTE: Translations of the
3599 * following 5 strings must not exceed 450
3602 gettext("Select one of the following and press enter:"),
3603 CHOOSE_THIS_TOKEN
, gettext("Use smartcard"), tmplabel
,
3604 gettext("in slot"), token_choices
->token_array
[i
].slotID
,
3605 CHOOSE_RESCAN
, gettext("Rescan for newly inserted smartcard"),
3606 CHOOSE_SKIP
, gettext("Skip smartcard authentication")))
3607 >= sizeof (prompt
)) {
3608 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3609 " sizeof prompt: %d\n", num_used
, sizeof (prompt
));
3610 krb5_set_error_message(context
, EINVAL
,
3611 gettext("In pkinit_choose_tokens: prompt size"
3612 " %d exceeds prompt buffer size %d"),
3613 num_used
, sizeof(prompt
));
3614 (void) snprintf(prompt
, sizeof (prompt
), "%s",
3615 gettext("Error: PKINIT prompt message is too large for buffer, "
3616 "please alert the system administrator. Press enter to "
3618 reply
.length
= sizeof(tmpbuf
);
3619 if ((r
= pkinit_prompt_user(context
, cctx
, &reply
, prompt
, 0)) != 0 )
3624 if ((num_used
= snprintf(prompt
, sizeof (prompt
),
3625 "%s\n%d: %s \"%s\" %s %d\n%d: %s\n%d: %s\n%d: %s\n",
3627 * TRANSLATION_NOTE: Translations of the
3628 * following 6 strings must not exceed 445
3631 gettext("Select one of the following and press enter:"),
3632 CHOOSE_THIS_TOKEN
, gettext("Use smartcard"), tmplabel
,
3633 gettext("in slot"), token_choices
->token_array
[i
].slotID
,
3634 CHOOSE_RESCAN
, gettext("Rescan for newly inserted smartcard"),
3635 CHOOSE_SKIP
, gettext("Skip smartcard authentication"),
3636 CHOOSE_SEE_NEXT
, gettext("See next smartcard")))
3637 >= sizeof (prompt
)) {
3639 pkiDebug("pkinit_choose_tokens: buffer overflow num_used: %d,"
3640 " sizeof prompt: %d\n", num_used
, sizeof (prompt
));
3641 krb5_set_error_message(context
, EINVAL
,
3642 gettext("In pkinit_choose_tokens: prompt size"
3643 " %d exceeds prompt buffer size %d"),
3644 num_used
, sizeof(prompt
));
3645 (void) snprintf(prompt
, sizeof (prompt
), "%s",
3646 gettext("Error: PKINIT prompt message is too large for buffer, "
3647 "please alert the system administrator. Press enter to "
3649 reply
.length
= sizeof(tmpbuf
);
3650 if ((r
= pkinit_prompt_user(context
, cctx
, &reply
, prompt
, 0)) != 0 )
3657 * reply.length needs to be reset to length of tmpbuf before calling
3660 reply
.length
= sizeof(tmpbuf
);
3661 if ((r
= pkinit_prompt_user(context
, cctx
, &reply
, prompt
, 0)) != 0 )
3664 if (reply
.length
== 0) {
3667 char *cp
= reply
.data
;
3668 /* reply better be digits */
3669 while (*cp
!= '\0') {
3670 if (!isdigit(*cp
++))
3674 tmpchoice
= (int) strtol(reply
.data
, (char **)NULL
, 10);
3679 switch (tmpchoice
) {
3680 case CHOOSE_THIS_TOKEN
:
3681 *choice
= i
; /* chosen entry of token_choices->token_array */
3684 *choice
= RESCAN_TOKENS
; /* rescan for new smartcard */
3687 *choice
= SKIP_TOKENS
; /* skip smartcard auth */
3689 case CHOOSE_SEE_NEXT
: /* see next smartcard */
3700 * Solaris Kerberos: this is a new function that does not exist yet in the MIT
3703 * Note, this isn't the best solution to providing a function to check the
3704 * certs in a token however I wanted to avoid rewriting a bunch of code so I
3705 * settled for some duplication of processing.
3707 static krb5_error_code
3708 check_load_certs(krb5_context context
,
3709 CK_SESSION_HANDLE session
,
3710 pkinit_plg_crypto_context plg_cryptoctx
,
3711 pkinit_req_crypto_context req_cryptoctx
,
3712 pkinit_identity_crypto_context id_cryptoctx
,
3713 krb5_principal princ
,
3717 CK_OBJECT_CLASS cls
;
3718 CK_OBJECT_HANDLE obj
;
3719 CK_ATTRIBUTE attrs
[4];
3721 CK_CERTIFICATE_TYPE certtype
;
3722 CK_BYTE_PTR cert
= NULL
, cert_id
= NULL
;
3723 const unsigned char *cp
;
3725 unsigned int nattrs
;
3728 cls
= CKO_CERTIFICATE
;
3729 attrs
[0].type
= CKA_CLASS
;
3730 attrs
[0].pValue
= &cls
;
3731 attrs
[0].ulValueLen
= sizeof cls
;
3733 certtype
= CKC_X_509
;
3734 attrs
[1].type
= CKA_CERTIFICATE_TYPE
;
3735 attrs
[1].pValue
= &certtype
;
3736 attrs
[1].ulValueLen
= sizeof certtype
;
3740 /* If a cert id and/or label were given, use them too */
3741 if (id_cryptoctx
->cert_id_len
> 0) {
3742 attrs
[nattrs
].type
= CKA_ID
;
3743 attrs
[nattrs
].pValue
= id_cryptoctx
->cert_id
;
3744 attrs
[nattrs
].ulValueLen
= id_cryptoctx
->cert_id_len
;
3747 if (id_cryptoctx
->cert_label
!= NULL
) {
3748 attrs
[nattrs
].type
= CKA_LABEL
;
3749 attrs
[nattrs
].pValue
= id_cryptoctx
->cert_label
;
3750 attrs
[nattrs
].ulValueLen
= strlen(id_cryptoctx
->cert_label
);
3754 r
= id_cryptoctx
->p11
->C_FindObjectsInit(session
, attrs
, nattrs
);
3756 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r
));
3757 krb5_set_error_message(context
, EINVAL
,
3758 gettext("PKCS11 error from C_FindObjectsInit: %s"),
3759 pkinit_pkcs11_code_to_text(r
));
3764 for (i
= 0; ; i
++) {
3765 if (i
>= MAX_CREDS_ALLOWED
) {
3770 /* Look for x.509 cert */
3771 /* Solaris Kerberos */
3772 if ((r
= id_cryptoctx
->p11
->C_FindObjects(session
, &obj
, 1, &count
))
3773 != CKR_OK
|| count
== 0) {
3774 id_cryptoctx
->creds
[i
] = NULL
;
3778 /* Get cert and id len */
3779 attrs
[0].type
= CKA_VALUE
;
3780 attrs
[0].pValue
= NULL
;
3781 attrs
[0].ulValueLen
= 0;
3783 attrs
[1].type
= CKA_ID
;
3784 attrs
[1].pValue
= NULL
;
3785 attrs
[1].ulValueLen
= 0;
3787 if ((r
= id_cryptoctx
->p11
->C_GetAttributeValue(session
,
3791 r
!= CKR_BUFFER_TOO_SMALL
) {
3792 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r
));
3793 krb5_set_error_message(context
, EINVAL
,
3794 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
3795 pkinit_pkcs11_code_to_text(r
));
3799 cert
= malloc((size_t) attrs
[0].ulValueLen
+ 1);
3804 cert_id
= malloc((size_t) attrs
[1].ulValueLen
+ 1);
3805 if (cert_id
== NULL
) {
3810 /* Read the cert and id off the card */
3812 attrs
[0].type
= CKA_VALUE
;
3813 attrs
[0].pValue
= cert
;
3815 attrs
[1].type
= CKA_ID
;
3816 attrs
[1].pValue
= cert_id
;
3818 if ((r
= id_cryptoctx
->p11
->C_GetAttributeValue(session
,
3819 obj
, attrs
, 2)) != CKR_OK
) {
3820 pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r
));
3821 krb5_set_error_message(context
, EINVAL
,
3822 gettext("Error from PKCS11 C_GetAttributeValue: %s"),
3823 pkinit_pkcs11_code_to_text(r
));
3828 pkiDebug("cert %d size %d id %d idlen %d\n", i
,
3829 (int) attrs
[0].ulValueLen
, (int) cert_id
[0],
3830 (int) attrs
[1].ulValueLen
);
3832 cp
= (unsigned char *) cert
;
3833 x
= d2i_X509(NULL
, &cp
, (int) attrs
[0].ulValueLen
);
3839 id_cryptoctx
->creds
[i
] = malloc(sizeof(struct _pkinit_cred_info
));
3840 if (id_cryptoctx
->creds
[i
] == NULL
) {
3844 id_cryptoctx
->creds
[i
]->cert
= x
;
3845 id_cryptoctx
->creds
[i
]->key
= NULL
;
3846 id_cryptoctx
->creds
[i
]->cert_id
= cert_id
;
3848 id_cryptoctx
->creds
[i
]->cert_id_len
= attrs
[1].ulValueLen
;
3852 id_cryptoctx
->p11
->C_FindObjectsFinal(session
);
3854 if (id_cryptoctx
->creds
[0] == NULL
|| id_cryptoctx
->creds
[0]->cert
== NULL
) {
3856 } else if (do_matching
){
3858 * Do not let pkinit_cert_matching set the primary cert in id_cryptoctx
3859 * as this will be done later.
3861 r
= pkinit_cert_matching(context
, plg_cryptoctx
, req_cryptoctx
,
3862 id_cryptoctx
, princ
, FALSE
);
3866 if ((r
!= 0 || !load_cert
) &&
3867 id_cryptoctx
->creds
[0] != NULL
&&
3868 id_cryptoctx
->creds
[0]->cert
!= NULL
) {
3870 * If there's an error or load_cert isn't 1 free all the certs loaded
3871 * onto id_cryptoctx.
3873 (void) crypto_free_cert_info(context
, plg_cryptoctx
, req_cryptoctx
,
3885 * Solaris Kerberos: this function has been significantly modified to prompt
3886 * the user in certain cases so defer to this version when resyncing MIT code.
3888 * pkinit_open_session now does several things including prompting the user if
3889 * do_matching is set which indicates the code is executing in a client
3890 * context. This function fills out a pkinit_identity_crypto_context with a
3891 * set of certs and a open session if a token can be found that matches all
3892 * supplied criteria. If no token is found then the user is prompted one time
3893 * to insert their token. If there is more than one token that matches all
3894 * client criteria the user is prompted to make a choice if in client context.
3895 * If do_matching is false (KDC context) then the first token matching all
3896 * server criteria is chosen.
3898 static krb5_error_code
3899 pkinit_open_session(krb5_context context
,
3900 pkinit_plg_crypto_context plg_cryptoctx
,
3901 pkinit_req_crypto_context req_cryptoctx
,
3902 pkinit_identity_crypto_context cctx
,
3903 krb5_principal princ
,
3908 CK_SLOT_ID_PTR slotlist
= NULL
, tmpslotlist
= NULL
;
3909 CK_TOKEN_INFO tinfo
;
3910 krb5_boolean tokenmatch
= FALSE
;
3911 CK_SESSION_HANDLE tmpsession
= CK_INVALID_HANDLE
;
3912 struct _token_choices token_choices
;
3915 if (cctx
->session
!= CK_INVALID_HANDLE
)
3916 return 0; /* session already open */
3919 if (cctx
->p11_module
== NULL
) {
3921 pkinit_C_LoadModule(cctx
->p11_module_name
, &cctx
->p11
);
3922 if (cctx
->p11_module
== NULL
)
3923 return KRB5KDC_ERR_PREAUTH_FAILED
;
3927 /* Solaris Kerberos: Don't fail if cryptoki is already initialized */
3928 r
= cctx
->p11
->C_Initialize(NULL
);
3929 if (r
!= CKR_OK
&& r
!= CKR_CRYPTOKI_ALREADY_INITIALIZED
) {
3930 pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r
));
3931 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3932 gettext("Error from PKCS11 C_Initialize: %s"),
3933 pkinit_pkcs11_code_to_text(r
));
3934 return KRB5KDC_ERR_PREAUTH_FAILED
;
3937 (void) memset(&token_choices
, 0, sizeof(token_choices
));
3941 * If C_Initialize was already called by the process before the pkinit
3942 * module was loaded then record that fact.
3943 * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether
3944 * or not C_Finalize() should be called.
3946 cctx
->finalize_pkcs11
=
3947 (r
== CKR_CRYPTOKI_ALREADY_INITIALIZED
? FALSE
: TRUE
);
3949 * First make sure that is an applicable slot otherwise fail.
3951 * Start by getting a count of all slots with or without tokens.
3954 if ((r
= cctx
->p11
->C_GetSlotList(FALSE
, NULL
, &count
)) != CKR_OK
) {
3955 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
3956 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3957 gettext("Error trying to get PKCS11 slot list: %s"),
3958 pkinit_pkcs11_code_to_text(r
));
3959 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3964 /* There are no slots so bail */
3965 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3966 krb5_set_error_message(context
, r
,
3967 gettext("No PKCS11 slots found"));
3968 pkiDebug("pkinit_open_session: no slots, count: %d\n", count
);
3970 } else if (cctx
->slotid
!= PK_NOSLOT
) {
3971 /* See if any of the slots match the specified slotID */
3972 tmpslotlist
= malloc(count
* sizeof (CK_SLOT_ID
));
3973 if (tmpslotlist
== NULL
) {
3974 krb5_set_error_message(context
, ENOMEM
,
3975 gettext("Memory allocation error:"));
3976 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3979 if ((r
= cctx
->p11
->C_GetSlotList(FALSE
, tmpslotlist
, &count
)) != CKR_OK
) {
3980 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
3981 gettext("Error trying to get PKCS11 slot list: %s"),
3982 pkinit_pkcs11_code_to_text(r
));
3983 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
3984 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3988 for (i
= 0; i
< count
&& cctx
->slotid
!= tmpslotlist
[i
]; i
++)
3992 /* no slots match */
3993 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
3994 krb5_set_error_message(context
, r
,
3995 gettext("Requested PKCS11 slot ID %d not found"),
3997 pkiDebug("open_session: no matching slot found for slotID %d\n",
4004 /* get count of slots that have tokens */
4005 if ((r
= cctx
->p11
->C_GetSlotList(TRUE
, NULL
, &count
)) != CKR_OK
) {
4006 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
4007 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4008 gettext("Error trying to get PKCS11 slot list: %s"),
4009 pkinit_pkcs11_code_to_text(r
));
4010 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4016 * Note, never prompt if !do_matching as this implies KDC side
4019 if (!(cctx
->p11flags
& C_PROMPTED_USER
) && do_matching
) {
4020 /* found slot(s) but no token so prompt and try again */
4021 if ((r
= pkinit_prompt_token(context
, cctx
)) == 0) {
4022 cctx
->p11flags
|= C_PROMPTED_USER
;
4025 pkiDebug("open_session: prompt for token/smart card failed\n");
4026 krb5_set_error_message(context
, r
,
4027 gettext("Prompt for token/smart card failed"));
4028 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4033 /* already prompted once so bailing */
4034 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4035 krb5_set_error_message(context
, r
,
4036 gettext("No smart card tokens found"));
4037 pkiDebug("pkinit_open_session: no token, already prompted\n");
4044 slotlist
= malloc(count
* sizeof (CK_SLOT_ID
));
4045 if (slotlist
== NULL
) {
4046 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4047 gettext("Memory allocation error"));
4048 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4052 * Solaris Kerberos: get list of PKCS11 slotid's that have tokens.
4054 if (cctx
->p11
->C_GetSlotList(TRUE
, slotlist
, &count
) != CKR_OK
) {
4055 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4056 gettext("Error trying to get PKCS11 slot list: %s"),
4057 pkinit_pkcs11_code_to_text(r
));
4058 pkiDebug("C_GetSlotList: %s\n", pkinit_pkcs11_code_to_text(r
));
4059 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4063 token_choices
.numtokens
= 0;
4064 token_choices
.token_array
= malloc(count
* sizeof (*token_choices
.token_array
));
4065 if (token_choices
.token_array
== NULL
) {
4066 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4067 krb5_set_error_message(context
, r
,
4068 gettext("Memory allocation error"));
4072 /* examine all the tokens */
4073 for (i
= 0; i
< count
; i
++) {
4075 * Solaris Kerberos: if a slotid was specified skip slots that don't
4078 if (cctx
->slotid
!= PK_NOSLOT
&& cctx
->slotid
!= slotlist
[i
])
4082 if ((r
= cctx
->p11
->C_OpenSession(slotlist
[i
], CKF_SERIAL_SESSION
,
4083 NULL
, NULL
, &tmpsession
)) != CKR_OK
) {
4084 pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r
));
4085 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4086 gettext("Error trying to open PKCS11 session: %s"),
4087 pkinit_pkcs11_code_to_text(r
));
4088 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4092 /* Get token info */
4093 if ((r
= cctx
->p11
->C_GetTokenInfo(slotlist
[i
], &tinfo
)) != CKR_OK
) {
4094 pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r
));
4095 krb5_set_error_message(context
, KRB5KDC_ERR_PREAUTH_FAILED
,
4096 gettext("Error trying to read PKCS11 token: %s"),
4097 pkinit_pkcs11_code_to_text(r
));
4098 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4099 cctx
->p11
->C_CloseSession(tmpsession
);
4103 if (cctx
->token_label
== NULL
) {
4105 * If the token doesn't require login to examine the certs then
4106 * let's check the certs out to see if any match the criteria if
4109 if (!(tinfo
.flags
& CKF_LOGIN_REQUIRED
)) {
4111 * It's okay to check the certs if we don't have to login but
4112 * don't load the certs onto cctx at this point, this will be
4113 * done later in this function for the chosen token.
4115 if ((r
= check_load_certs(context
, tmpsession
, plg_cryptoctx
,
4116 req_cryptoctx
, cctx
, princ
,
4117 do_matching
, 0)) == 0) {
4119 } else if (r
!= ENOENT
){
4120 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4121 cctx
->p11
->C_CloseSession(tmpsession
);
4124 /* ignore ENOENT here */
4131 /* + 1 so tokenlabelstr can be \0 terminated */
4132 char tokenlabelstr
[sizeof (tinfo
.label
) + 1];
4135 * Convert token label into C string with trailing white space
4138 trim_token_label(&tinfo
, tokenlabelstr
, sizeof (tokenlabelstr
));
4140 pkiDebug("open_session: slotid %d token found: \"%s\", "
4141 "cctx->token_label: \"%s\"\n",
4142 slotlist
[i
], tokenlabelstr
, (char *) cctx
->token_label
);
4144 if (!strcmp(cctx
->token_label
, tokenlabelstr
)) {
4145 if (!(tinfo
.flags
& CKF_LOGIN_REQUIRED
)) {
4147 * It's okay to check the certs if we don't have to login but
4148 * don't load the certs onto cctx at this point, this will be
4149 * done later in this function for the chosen token.
4151 if ((r
= check_load_certs(context
, tmpsession
, plg_cryptoctx
,
4152 req_cryptoctx
, cctx
, princ
,
4153 do_matching
, 0)) == 0) {
4155 } else if (r
!= ENOENT
){
4156 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4157 cctx
->p11
->C_CloseSession(tmpsession
);
4160 /* ignore ENOENT here */
4169 if (tokenmatch
== TRUE
) {
4170 /* add the token to token_choices.token_array */
4171 token_choices
.token_array
[token_choices
.numtokens
].slotID
= slotlist
[i
];
4172 token_choices
.token_array
[token_choices
.numtokens
].session
= tmpsession
;
4173 token_choices
.token_array
[token_choices
.numtokens
].token_info
= tinfo
;
4174 token_choices
.numtokens
++;
4175 /* !do_matching implies we take the first matching token */
4181 cctx
->p11
->C_CloseSession(tmpsession
);
4185 if (token_choices
.numtokens
== 0) {
4187 * Solaris Kerberos: prompt for token one time if there was no token
4188 * and do_matching is 1 (see earlier comment about do_matching).
4190 if (!(cctx
->p11flags
& C_PROMPTED_USER
) && do_matching
) {
4191 if ((r
= pkinit_prompt_token(context
, cctx
)) == 0) {
4192 cctx
->p11flags
|= C_PROMPTED_USER
;
4195 pkiDebug("open_session: prompt for token/smart card failed\n");
4196 krb5_set_error_message(context
, r
,
4197 gettext("Prompt for token/smart card failed"));
4198 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4202 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4203 krb5_set_error_message(context
, r
,
4204 gettext("No smart card tokens found"));
4205 pkiDebug("open_session: no matching token found\n");
4208 } else if (token_choices
.numtokens
== 1) {
4209 if ((token_choices
.token_array
[0].token_info
.flags
& CKF_LOGIN_REQUIRED
) &&
4210 !(cctx
->p11flags
& C_PROMPTED_USER
) &&
4212 if ((r
= pkinit_choose_tokens(context
, cctx
, &token_choices
, &choice
)) != 0) {
4213 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r
);
4214 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4215 krb5_set_error_message(context
, r
,
4216 gettext("Prompt for token/smart card failed"));
4219 if (choice
== RESCAN_TOKENS
) {
4220 /* rescan for new smartcard/token */
4221 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4222 /* close all sessions */
4223 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4225 free(token_choices
.token_array
);
4226 token_choices
.token_array
= NULL
;
4227 token_choices
.numtokens
= 0;
4229 } else if (choice
== SKIP_TOKENS
) {
4230 /* do not use smartcard/token for auth */
4231 cctx
->p11flags
|= (C_PROMPTED_USER
|C_SKIP_PKCS11_AUTH
);
4232 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4235 cctx
->p11flags
|= C_PROMPTED_USER
;
4238 choice
= 0; /* really the only choice is the first token_array entry */
4240 } else if (!(cctx
->p11flags
& C_PROMPTED_USER
) && do_matching
) {
4241 /* > 1 token so present menu of token choices, let the user decide. */
4242 if ((r
= pkinit_choose_tokens(context
, cctx
, &token_choices
, &choice
)) != 0) {
4243 pkiDebug("pkinit_open_session: pkinit_choose_tokens failed: %d\n", r
);
4244 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4245 krb5_set_error_message(context
, r
,
4246 gettext("Prompt for token/smart card failed"));
4249 if (choice
== RESCAN_TOKENS
) {
4250 /* rescan for new smartcard/token */
4251 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4252 /* close all sessions */
4253 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4255 free(token_choices
.token_array
);
4256 token_choices
.token_array
= NULL
;
4257 token_choices
.numtokens
= 0;
4259 } else if (choice
== SKIP_TOKENS
) {
4260 /* do not use smartcard/token for auth */
4261 cctx
->p11flags
|= (C_PROMPTED_USER
|C_SKIP_PKCS11_AUTH
);
4262 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4265 cctx
->p11flags
|= C_PROMPTED_USER
;
4268 r
= KRB5KDC_ERR_PREAUTH_FAILED
;
4272 cctx
->slotid
= token_choices
.token_array
[choice
].slotID
;
4273 cctx
->session
= token_choices
.token_array
[choice
].session
;
4275 pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx
->slotid
,
4276 i
+ 1, (int) count
);
4278 /* Login if needed */
4279 /* Solaris Kerberos: added cctx->p11flags check */
4280 if ((token_choices
.token_array
[choice
].token_info
.flags
& CKF_LOGIN_REQUIRED
) &&
4281 !(cctx
->p11flags
& C_LOGIN_DONE
)) {
4282 r
= pkinit_login(context
, cctx
, &token_choices
.token_array
[choice
].token_info
);
4286 /* Doing this again to load the certs into cctx. */
4287 r
= check_load_certs(context
, cctx
->session
, plg_cryptoctx
,
4288 req_cryptoctx
, cctx
, princ
, do_matching
, 1);
4296 if (token_choices
.token_array
!= NULL
) {
4298 /* close all sessions if there's an error */
4299 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4300 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4302 cctx
->session
= CK_INVALID_HANDLE
;
4304 /* close sessions not chosen */
4305 for (i
= 0; i
< token_choices
.numtokens
; i
++) {
4307 cctx
->p11
->C_CloseSession(token_choices
.token_array
[i
].session
);
4311 free(token_choices
.token_array
);
4318 * Look for a key that's:
4320 * 2. capable of the specified operation (usually signing or decrypting)
4321 * 3. RSA (this may be wrong but it's all we can do for now)
4322 * 4. matches the id of the cert we chose
4324 * You must call pkinit_get_certs before calling pkinit_find_private_key
4325 * (that's because we need the ID of the private key)
4327 * pkcs11 says the id of the key doesn't have to match that of the cert, but
4328 * I can't figure out any other way to decide which key to use.
4330 * We should only find one key that fits all the requirements.
4331 * If there are more than one, we just take the first one.
4336 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx
,
4337 CK_ATTRIBUTE_TYPE usage
,
4338 CK_OBJECT_HANDLE
*objp
)
4340 CK_OBJECT_CLASS cls
;
4341 CK_ATTRIBUTE attrs
[4];
4343 CK_KEY_TYPE keytype
;
4344 unsigned int nattrs
= 0;
4346 #ifdef PKINIT_USE_KEY_USAGE
4347 CK_BBOOL true_false
;
4350 cls
= CKO_PRIVATE_KEY
;
4351 attrs
[nattrs
].type
= CKA_CLASS
;
4352 attrs
[nattrs
].pValue
= &cls
;
4353 attrs
[nattrs
].ulValueLen
= sizeof cls
;
4356 #ifdef PKINIT_USE_KEY_USAGE
4358 * Some cards get confused if you try to specify a key usage,
4359 * so don't, and hope for the best. This will fail if you have
4360 * several keys with the same id and different usages but I have
4361 * not seen this on real cards.
4364 attrs
[nattrs
].type
= usage
;
4365 attrs
[nattrs
].pValue
= &true_false
;
4366 attrs
[nattrs
].ulValueLen
= sizeof true_false
;
4371 attrs
[nattrs
].type
= CKA_KEY_TYPE
;
4372 attrs
[nattrs
].pValue
= &keytype
;
4373 attrs
[nattrs
].ulValueLen
= sizeof keytype
;
4376 attrs
[nattrs
].type
= CKA_ID
;
4377 attrs
[nattrs
].pValue
= id_cryptoctx
->cert_id
;
4378 attrs
[nattrs
].ulValueLen
= id_cryptoctx
->cert_id_len
;
4381 r
= id_cryptoctx
->p11
->C_FindObjectsInit(id_cryptoctx
->session
, attrs
, nattrs
);
4383 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4384 pkinit_pkcs11_code_to_text(r
));
4385 return KRB5KDC_ERR_PREAUTH_FAILED
;
4388 r
= id_cryptoctx
->p11
->C_FindObjects(id_cryptoctx
->session
, objp
, 1, &count
);
4389 id_cryptoctx
->p11
->C_FindObjectsFinal(id_cryptoctx
->session
);
4390 pkiDebug("found %d private keys (%s)\n", (int) count
, pkinit_pkcs11_code_to_text(r
));
4394 * The CKA_ID may not be correctly set for the private key. For e.g. when
4395 * storing a private key in softtoken pktool(1) doesn't generate or store
4396 * a CKA_ID for the private key. Another way to identify the private key is
4397 * to look for a private key with the same RSA modulus as the public key
4398 * in the certificate.
4400 if (r
== CKR_OK
&& count
!= 1) {
4405 unsigned char *n_bytes
;
4407 cert
= sk_X509_value(id_cryptoctx
->my_certs
, 0);
4408 priv
= X509_get_pubkey(cert
);
4410 pkiDebug("Failed to extract pub key from cert\n");
4411 return KRB5KDC_ERR_PREAUTH_FAILED
;
4415 cls
= CKO_PRIVATE_KEY
;
4416 attrs
[nattrs
].type
= CKA_CLASS
;
4417 attrs
[nattrs
].pValue
= &cls
;
4418 attrs
[nattrs
].ulValueLen
= sizeof cls
;
4421 #ifdef PKINIT_USE_KEY_USAGE
4423 attrs
[nattrs
].type
= usage
;
4424 attrs
[nattrs
].pValue
= &true_false
;
4425 attrs
[nattrs
].ulValueLen
= sizeof true_false
;
4430 attrs
[nattrs
].type
= CKA_KEY_TYPE
;
4431 attrs
[nattrs
].pValue
= &keytype
;
4432 attrs
[nattrs
].ulValueLen
= sizeof keytype
;
4435 n_len
= BN_num_bytes(priv
->pkey
.rsa
->n
);
4436 n_bytes
= (unsigned char *) malloc((size_t) n_len
);
4437 if (n_bytes
== NULL
) {
4441 if (BN_bn2bin(priv
->pkey
.rsa
->n
, n_bytes
) == 0) {
4443 pkiDebug("zero-byte key modulus\n");
4444 return KRB5KDC_ERR_PREAUTH_FAILED
;
4447 attrs
[nattrs
].type
= CKA_MODULUS
;
4448 attrs
[nattrs
].ulValueLen
= n_len
;
4449 attrs
[nattrs
].pValue
= n_bytes
;
4453 r
= id_cryptoctx
->p11
->C_FindObjectsInit(id_cryptoctx
->session
, attrs
, nattrs
);
4456 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
4457 pkinit_pkcs11_code_to_text(r
));
4458 return KRB5KDC_ERR_PREAUTH_FAILED
;
4461 r
= id_cryptoctx
->p11
->C_FindObjects(id_cryptoctx
->session
, objp
, 1, &count
);
4462 id_cryptoctx
->p11
->C_FindObjectsFinal(id_cryptoctx
->session
);
4463 pkiDebug("found %d private keys (%s)\n", (int) count
, pkinit_pkcs11_code_to_text(r
));
4467 if (r
!= CKR_OK
|| count
< 1)
4468 return KRB5KDC_ERR_PREAUTH_FAILED
;
4474 static krb5_error_code
4475 pkinit_decode_data_fs(krb5_context context
,
4476 pkinit_identity_crypto_context id_cryptoctx
,
4477 unsigned char *data
,
4478 unsigned int data_len
,
4479 unsigned char **decoded_data
,
4480 unsigned int *decoded_data_len
)
4482 if (decode_data(decoded_data
, decoded_data_len
, data
, data_len
,
4483 id_cryptoctx
->my_key
, sk_X509_value(id_cryptoctx
->my_certs
,
4484 id_cryptoctx
->cert_index
)) <= 0) {
4485 pkiDebug("failed to decode data\n");
4486 return KRB5KDC_ERR_PREAUTH_FAILED
;
4491 #ifndef WITHOUT_PKCS11
4494 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx
,
4495 CK_BYTE_PTR pEncryptedData
,
4496 CK_ULONG ulEncryptedDataLen
,
4498 CK_ULONG_PTR pulDataLen
)
4502 rv
= id_cryptoctx
->p11
->C_Decrypt(id_cryptoctx
->session
, pEncryptedData
,
4503 ulEncryptedDataLen
, pData
, pulDataLen
);
4505 pkiDebug("pData %x *pulDataLen %d\n", (int) pData
, (int) *pulDataLen
);
4511 static krb5_error_code
4512 pkinit_decode_data_pkcs11(krb5_context context
,
4513 pkinit_identity_crypto_context id_cryptoctx
,
4514 unsigned char *data
,
4515 unsigned int data_len
,
4516 unsigned char **decoded_data
,
4517 unsigned int *decoded_data_len
)
4519 CK_OBJECT_HANDLE obj
;
4526 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4529 assert(id_cryptoctx
->p11
!= NULL
);
4531 /* Solaris Kerberos: Login, if needed, to access private object */
4532 if (!(id_cryptoctx
->p11flags
& C_LOGIN_DONE
)) {
4533 CK_TOKEN_INFO tinfo
;
4535 r
= id_cryptoctx
->p11
->C_GetTokenInfo(id_cryptoctx
->slotid
, &tinfo
);
4539 r
= pkinit_login(context
, id_cryptoctx
, &tinfo
);
4544 r
= pkinit_find_private_key(id_cryptoctx
, CKA_DECRYPT
, &obj
);
4548 mech
.mechanism
= CKM_RSA_PKCS
;
4549 mech
.pParameter
= NULL
;
4550 mech
.ulParameterLen
= 0;
4552 if ((r
= id_cryptoctx
->p11
->C_DecryptInit(id_cryptoctx
->session
, &mech
,
4554 pkiDebug("C_DecryptInit: 0x%x\n", (int) r
);
4555 return KRB5KDC_ERR_PREAUTH_FAILED
;
4557 pkiDebug("data_len = %d\n", data_len
);
4558 cp
= (unsigned char *)malloc((size_t) data_len
);
4563 pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n",
4564 (int) id_cryptoctx
->session
, (int) data
, (int) data_len
, (int) cp
,
4565 (int) &len
, (int) len
);
4566 if ((r
= pkinit_C_Decrypt(id_cryptoctx
, data
, (CK_ULONG
) data_len
,
4567 cp
, &len
)) != CKR_OK
) {
4569 if ((r
= id_cryptoctx
->p11
->C_Decrypt(id_cryptoctx
->session
, data
,
4570 (CK_ULONG
) data_len
, cp
, &len
)) != CKR_OK
) {
4572 pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r
));
4573 if (r
== CKR_BUFFER_TOO_SMALL
)
4574 pkiDebug("decrypt %d needs %d\n", (int) data_len
, (int) len
);
4575 return KRB5KDC_ERR_PREAUTH_FAILED
;
4577 pkiDebug("decrypt %d -> %d\n", (int) data_len
, (int) len
);
4578 *decoded_data_len
= len
;
4586 pkinit_decode_data(krb5_context context
,
4587 pkinit_identity_crypto_context id_cryptoctx
,
4588 unsigned char *data
,
4589 unsigned int data_len
,
4590 unsigned char **decoded_data
,
4591 unsigned int *decoded_data_len
)
4593 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
4595 if (id_cryptoctx
->pkcs11_method
!= 1)
4596 retval
= pkinit_decode_data_fs(context
, id_cryptoctx
, data
, data_len
,
4597 decoded_data
, decoded_data_len
);
4598 #ifndef WITHOUT_PKCS11
4600 retval
= pkinit_decode_data_pkcs11(context
, id_cryptoctx
, data
,
4601 data_len
, decoded_data
, decoded_data_len
);
4608 static krb5_error_code
4609 pkinit_sign_data_fs(krb5_context context
,
4610 pkinit_identity_crypto_context id_cryptoctx
,
4611 unsigned char *data
,
4612 unsigned int data_len
,
4613 unsigned char **sig
,
4614 unsigned int *sig_len
)
4616 if (create_signature(sig
, sig_len
, data
, data_len
,
4617 id_cryptoctx
->my_key
) != 0) {
4618 pkiDebug("failed to create the signature\n");
4619 return KRB5KDC_ERR_PREAUTH_FAILED
;
4624 #ifndef WITHOUT_PKCS11
4625 static krb5_error_code
4626 pkinit_sign_data_pkcs11(krb5_context context
,
4627 pkinit_identity_crypto_context id_cryptoctx
,
4628 unsigned char *data
,
4629 unsigned int data_len
,
4630 unsigned char **sig
,
4631 unsigned int *sig_len
)
4633 CK_OBJECT_HANDLE obj
;
4640 * Solaris Kerberos: assume session is open and libpkcs11 funcs have been
4643 assert(id_cryptoctx
->p11
!= NULL
);
4645 /* Solaris Kerberos: Login, if needed, to access private object */
4646 if (!(id_cryptoctx
->p11flags
& C_LOGIN_DONE
)) {
4647 CK_TOKEN_INFO tinfo
;
4649 r
= id_cryptoctx
->p11
->C_GetTokenInfo(id_cryptoctx
->slotid
, &tinfo
);
4653 r
= pkinit_login(context
, id_cryptoctx
, &tinfo
);
4658 r
= pkinit_find_private_key(id_cryptoctx
, CKA_SIGN
, &obj
);
4662 mech
.mechanism
= id_cryptoctx
->mech
;
4663 mech
.pParameter
= NULL
;
4664 mech
.ulParameterLen
= 0;
4666 if ((r
= id_cryptoctx
->p11
->C_SignInit(id_cryptoctx
->session
, &mech
,
4668 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r
));
4669 return KRB5KDC_ERR_PREAUTH_FAILED
;
4673 * Key len would give an upper bound on sig size, but there's no way to
4674 * get that. So guess, and if it's too small, re-malloc.
4676 len
= PK_SIGLEN_GUESS
;
4677 cp
= (unsigned char *)malloc((size_t) len
);
4681 r
= id_cryptoctx
->p11
->C_Sign(id_cryptoctx
->session
, data
,
4682 (CK_ULONG
) data_len
, cp
, &len
);
4683 if (r
== CKR_BUFFER_TOO_SMALL
|| (r
== CKR_OK
&& len
>= PK_SIGLEN_GUESS
)) {
4685 pkiDebug("C_Sign realloc %d\n", (int) len
);
4686 cp
= (unsigned char *)malloc((size_t) len
);
4687 r
= id_cryptoctx
->p11
->C_Sign(id_cryptoctx
->session
, data
,
4688 (CK_ULONG
) data_len
, cp
, &len
);
4691 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r
));
4692 return KRB5KDC_ERR_PREAUTH_FAILED
;
4694 pkiDebug("sign %d -> %d\n", (int) data_len
, (int) len
);
4703 pkinit_sign_data(krb5_context context
,
4704 pkinit_identity_crypto_context id_cryptoctx
,
4705 unsigned char *data
,
4706 unsigned int data_len
,
4707 unsigned char **sig
,
4708 unsigned int *sig_len
)
4710 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
4712 if (id_cryptoctx
== NULL
|| id_cryptoctx
->pkcs11_method
!= 1)
4713 retval
= pkinit_sign_data_fs(context
, id_cryptoctx
, data
, data_len
,
4715 #ifndef WITHOUT_PKCS11
4717 retval
= pkinit_sign_data_pkcs11(context
, id_cryptoctx
, data
, data_len
,
4725 static krb5_error_code
4726 decode_data(unsigned char **out_data
, unsigned int *out_data_len
,
4727 unsigned char *data
, unsigned int data_len
,
4728 EVP_PKEY
*pkey
, X509
*cert
)
4730 /* Solaris Kerberos */
4732 unsigned char *buf
= NULL
;
4735 /* Solaris Kerberos */
4736 if (out_data
== NULL
|| out_data_len
== NULL
)
4739 if (cert
&& !X509_check_private_key(cert
, pkey
)) {
4740 pkiDebug("private key does not match certificate\n");
4741 /* Solaris Kerberos */
4745 buf_len
= EVP_PKEY_size(pkey
);
4746 buf
= (unsigned char *)malloc((size_t) buf_len
+ 10);
4750 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4751 len
= EVP_PKEY_decrypt(buf
, data
, (int)data_len
, pkey
);
4753 len
= EVP_PKEY_decrypt_old(buf
, data
, (int)data_len
, pkey
);
4756 pkiDebug("unable to decrypt received data (len=%d)\n", data_len
);
4757 /* Solaris Kerberos */
4759 return KRB5KRB_ERR_GENERIC
;
4762 *out_data_len
= len
;
4767 static krb5_error_code
4768 create_signature(unsigned char **sig
, unsigned int *sig_len
,
4769 unsigned char *data
, unsigned int data_len
, EVP_PKEY
*pkey
)
4771 krb5_error_code retval
= ENOMEM
;
4775 /* Solaris Kerberos */
4778 EVP_VerifyInit(&md_ctx
, EVP_sha1());
4779 EVP_SignUpdate(&md_ctx
, data
, data_len
);
4780 *sig_len
= EVP_PKEY_size(pkey
);
4781 if ((*sig
= (unsigned char *) malloc((size_t) *sig_len
)) == NULL
)
4783 EVP_SignFinal(&md_ctx
, *sig
, sig_len
, pkey
);
4788 EVP_MD_CTX_cleanup(&md_ctx
);
4795 * This is not the routine the KDC uses to get its certificate.
4796 * This routine is intended to be called by the client
4797 * to obtain the KDC's certificate from some local storage
4798 * to be sent as a hint in its request to the KDC.
4802 pkinit_get_kdc_cert(krb5_context context
,
4803 pkinit_plg_crypto_context plg_cryptoctx
,
4804 pkinit_req_crypto_context req_cryptoctx
,
4805 pkinit_identity_crypto_context id_cryptoctx
,
4806 krb5_principal princ
)
4808 /* Solaris Kerberos */
4809 if (req_cryptoctx
== NULL
)
4812 req_cryptoctx
->received_cert
= NULL
;
4817 static krb5_error_code
4818 pkinit_get_certs_pkcs12(krb5_context context
,
4819 pkinit_plg_crypto_context plg_cryptoctx
,
4820 pkinit_req_crypto_context req_cryptoctx
,
4821 pkinit_identity_opts
*idopts
,
4822 pkinit_identity_crypto_context id_cryptoctx
,
4823 krb5_principal princ
)
4825 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
4832 if (idopts
->cert_filename
== NULL
) {
4833 /* Solaris Kerberos: Improved error messages */
4834 krb5_set_error_message(context
, retval
,
4835 gettext("Failed to get certificate location"));
4836 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__
);
4840 if (idopts
->key_filename
== NULL
) {
4841 /* Solaris Kerberos: Improved error messages */
4842 krb5_set_error_message(context
, retval
,
4843 gettext("Failed to get private key location"));
4844 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__
);
4848 fp
= fopen(idopts
->cert_filename
, "rb");
4850 /* Solaris Kerberos: Improved error messages */
4851 krb5_set_error_message(context
, retval
,
4852 gettext("Failed to open PKCS12 file '%s': %s"),
4853 idopts
->cert_filename
, error_message(errno
));
4854 pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
4855 idopts
->cert_filename
, errno
);
4859 p12
= d2i_PKCS12_fp(fp
, NULL
);
4862 krb5_set_error_message(context
, retval
,
4863 gettext("Failed to decode PKCS12 file '%s' contents"),
4864 idopts
->cert_filename
);
4865 pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
4866 idopts
->cert_filename
);
4870 * Try parsing with no pass phrase first. If that fails,
4871 * prompt for the pass phrase and try again.
4873 ret
= PKCS12_parse(p12
, NULL
, &y
, &x
, NULL
);
4876 krb5_prompt kprompt
;
4877 krb5_prompt_type prompt_type
;
4879 char prompt_string
[128];
4880 char prompt_reply
[128];
4881 /* Solaris Kerberos */
4882 char *prompt_prefix
= gettext("Pass phrase for");
4884 pkiDebug("Initial PKCS12_parse with no password failed\n");
4886 if (id_cryptoctx
->PIN
!= NULL
) {
4887 /* Solaris Kerberos: use PIN if set */
4888 rdat
.data
= id_cryptoctx
->PIN
;
4889 /* note rdat.length isn't needed in this case */
4891 (void) memset(prompt_reply
, '\0', sizeof(prompt_reply
));
4892 rdat
.data
= prompt_reply
;
4893 rdat
.length
= sizeof(prompt_reply
);
4895 r
= snprintf(prompt_string
, sizeof(prompt_string
), "%s %s",
4896 prompt_prefix
, idopts
->cert_filename
);
4897 if (r
>= sizeof(prompt_string
)) {
4898 pkiDebug("Prompt string, '%s %s', is too long!\n",
4899 prompt_prefix
, idopts
->cert_filename
);
4902 kprompt
.prompt
= prompt_string
;
4904 kprompt
.reply
= &rdat
;
4905 prompt_type
= KRB5_PROMPT_TYPE_PREAUTH
;
4907 /* PROMPTER_INVOCATION */
4908 k5int_set_prompt_types(context
, &prompt_type
);
4909 r
= (*id_cryptoctx
->prompter
)(context
, id_cryptoctx
->prompter_data
,
4910 NULL
, NULL
, 1, &kprompt
);
4911 k5int_set_prompt_types(context
, NULL
);
4914 ret
= PKCS12_parse(p12
, rdat
.data
, &y
, &x
, NULL
);
4916 /* Solaris Kerberos: Improved error messages */
4917 krb5_set_error_message(context
, retval
,
4918 gettext("Failed to parse PKCS12 file '%s' with password"),
4919 idopts
->cert_filename
);
4920 pkiDebug("Seconde PKCS12_parse with password failed\n");
4924 id_cryptoctx
->creds
[0] = malloc(sizeof(struct _pkinit_cred_info
));
4925 if (id_cryptoctx
->creds
[0] == NULL
)
4927 id_cryptoctx
->creds
[0]->cert
= x
;
4928 #ifndef WITHOUT_PKCS11
4929 id_cryptoctx
->creds
[0]->cert_id
= NULL
;
4930 id_cryptoctx
->creds
[0]->cert_id_len
= 0;
4932 id_cryptoctx
->creds
[0]->key
= y
;
4933 id_cryptoctx
->creds
[1] = NULL
;
4949 static krb5_error_code
4950 pkinit_load_fs_cert_and_key(krb5_context context
,
4951 pkinit_identity_crypto_context id_cryptoctx
,
4956 krb5_error_code retval
;
4960 /* load the certificate */
4961 retval
= get_cert(certname
, &x
);
4962 if (retval
!= 0 || x
== NULL
) {
4963 /* Solaris Kerberos: Improved error messages */
4964 krb5_set_error_message(context
, retval
,
4965 gettext("Failed to load user's certificate from %s: %s"),
4966 certname
, error_message(retval
));
4967 pkiDebug("failed to load user's certificate from '%s'\n", certname
);
4970 retval
= get_key(keyname
, &y
);
4971 if (retval
!= 0 || y
== NULL
) {
4972 /* Solaris Kerberos: Improved error messages */
4973 krb5_set_error_message(context
, retval
,
4974 gettext("Failed to load user's private key from %s: %s"),
4975 keyname
, error_message(retval
));
4976 pkiDebug("failed to load user's private key from '%s'\n", keyname
);
4980 id_cryptoctx
->creds
[cindex
] = malloc(sizeof(struct _pkinit_cred_info
));
4981 if (id_cryptoctx
->creds
[cindex
] == NULL
) {
4985 id_cryptoctx
->creds
[cindex
]->cert
= x
;
4986 #ifndef WITHOUT_PKCS11
4987 id_cryptoctx
->creds
[cindex
]->cert_id
= NULL
;
4988 id_cryptoctx
->creds
[cindex
]->cert_id_len
= 0;
4990 id_cryptoctx
->creds
[cindex
]->key
= y
;
4991 id_cryptoctx
->creds
[cindex
+1] = NULL
;
5006 static krb5_error_code
5007 pkinit_get_certs_fs(krb5_context context
,
5008 pkinit_plg_crypto_context plg_cryptoctx
,
5009 pkinit_req_crypto_context req_cryptoctx
,
5010 pkinit_identity_opts
*idopts
,
5011 pkinit_identity_crypto_context id_cryptoctx
,
5012 krb5_principal princ
)
5014 krb5_error_code retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
5016 if (idopts
->cert_filename
== NULL
) {
5017 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__
);
5021 if (idopts
->key_filename
== NULL
) {
5022 pkiDebug("%s: failed to get user's private key location\n",
5027 retval
= pkinit_load_fs_cert_and_key(context
, id_cryptoctx
,
5028 idopts
->cert_filename
,
5029 idopts
->key_filename
, 0);
5035 static krb5_error_code
5036 pkinit_get_certs_dir(krb5_context context
,
5037 pkinit_plg_crypto_context plg_cryptoctx
,
5038 pkinit_req_crypto_context req_cryptoctx
,
5039 pkinit_identity_opts
*idopts
,
5040 pkinit_identity_crypto_context id_cryptoctx
,
5041 krb5_principal princ
)
5043 /* Solaris Kerberos */
5044 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
5046 struct dirent
*dentry
= NULL
;
5047 char certname
[1024];
5050 char *dirname
, *suf
;
5052 /* Solaris Kerberos */
5056 if (idopts
->cert_filename
== NULL
) {
5057 pkiDebug("%s: failed to get user's certificate directory location\n",
5062 dirname
= idopts
->cert_filename
;
5063 d
= opendir(dirname
);
5065 /* Solaris Kerberos: Improved error messages */
5066 krb5_set_error_message(context
, errno
,
5067 gettext("Failed to open directory \"%s\": %s"),
5068 dirname
, error_message(errno
));
5073 * We'll assume that certs are named XXX.crt and the corresponding
5074 * key is named XXX.key
5076 while ((i
< MAX_CREDS_ALLOWED
) && (dentry
= readdir(d
)) != NULL
) {
5077 /* Ignore subdirectories and anything starting with a dot */
5079 if (dentry
->d_type
== DT_DIR
)
5082 if (dentry
->d_name
[0] == '.')
5084 len
= strlen(dentry
->d_name
);
5087 suf
= dentry
->d_name
+ (len
- 4);
5088 if (strncmp(suf
, ".crt", 4) != 0)
5091 /* Checked length */
5092 if (strlen(dirname
) + strlen(dentry
->d_name
) + 2 > sizeof(certname
)) {
5093 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
5094 __FUNCTION__
, dirname
, dentry
->d_name
);
5097 (void) snprintf(certname
, sizeof(certname
), "%s/%s", dirname
, dentry
->d_name
);
5098 (void) snprintf(keyname
, sizeof(keyname
), "%s/%s", dirname
, dentry
->d_name
);
5099 len
= strlen(keyname
);
5100 keyname
[len
- 3] = 'k';
5101 keyname
[len
- 2] = 'e';
5102 keyname
[len
- 1] = 'y';
5104 retval
= pkinit_load_fs_cert_and_key(context
, id_cryptoctx
,
5105 certname
, keyname
, i
);
5107 pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
5108 __FUNCTION__
, dentry
->d_name
);
5116 /* Solaris Kerberos: Improved error messages */
5117 krb5_set_error_message(context
, ENOENT
,
5118 gettext("No suitable cert/key pairs found in directory '%s'"),
5119 idopts
->cert_filename
);
5120 pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
5121 __FUNCTION__
, idopts
->cert_filename
);
5135 #ifndef WITHOUT_PKCS11
5137 static krb5_error_code
5138 pkinit_get_certs_pkcs11(krb5_context context
,
5139 pkinit_plg_crypto_context plg_cryptoctx
,
5140 pkinit_req_crypto_context req_cryptoctx
,
5141 pkinit_identity_opts
*idopts
,
5142 pkinit_identity_crypto_context id_cryptoctx
,
5143 krb5_principal princ
,
5146 #ifdef PKINIT_USE_MECH_LIST
5147 CK_MECHANISM_TYPE_PTR mechp
= NULL
;
5148 CK_MECHANISM_INFO info
;
5151 if (id_cryptoctx
->p11flags
& C_SKIP_PKCS11_AUTH
)
5152 return KRB5KDC_ERR_PREAUTH_FAILED
;
5154 /* Copy stuff from idopts -> id_cryptoctx */
5155 if (idopts
->p11_module_name
!= NULL
) {
5156 id_cryptoctx
->p11_module_name
= strdup(idopts
->p11_module_name
);
5157 if (id_cryptoctx
->p11_module_name
== NULL
)
5160 if (idopts
->token_label
!= NULL
) {
5161 id_cryptoctx
->token_label
= strdup(idopts
->token_label
);
5162 if (id_cryptoctx
->token_label
== NULL
)
5165 if (idopts
->cert_label
!= NULL
) {
5166 id_cryptoctx
->cert_label
= strdup(idopts
->cert_label
);
5167 if (id_cryptoctx
->cert_label
== NULL
)
5170 if (idopts
->PIN
!= NULL
) {
5171 id_cryptoctx
->PIN
= strdup(idopts
->PIN
);
5172 if (id_cryptoctx
->PIN
== NULL
)
5175 /* Convert the ascii cert_id string into a binary blob */
5178 * If the cert_id_string is empty then behave in a similar way to how
5179 * an empty certlabel is treated - i.e. don't fail now but rather continue
5180 * as though the certid wasn't specified.
5182 if (idopts
->cert_id_string
!= NULL
&& strlen(idopts
->cert_id_string
) != 0) {
5184 BN_hex2bn(&bn
, idopts
->cert_id_string
);
5187 id_cryptoctx
->cert_id_len
= BN_num_bytes(bn
);
5188 id_cryptoctx
->cert_id
= malloc((size_t) id_cryptoctx
->cert_id_len
);
5189 if (id_cryptoctx
->cert_id
== NULL
) {
5193 BN_bn2bin(bn
, id_cryptoctx
->cert_id
);
5196 id_cryptoctx
->slotid
= idopts
->slotid
;
5197 id_cryptoctx
->pkcs11_method
= 1;
5199 #ifndef PKINIT_USE_MECH_LIST
5201 * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
5202 * many cards seems to be confused about whether they are capable of
5203 * this or not. The safe thing seems to be to ignore the mechanism list,
5204 * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
5207 id_cryptoctx
->mech
= CKM_RSA_PKCS
;
5209 if ((r
= id_cryptoctx
->p11
->C_GetMechanismList(id_cryptoctx
->slotid
, NULL
,
5210 &count
)) != CKR_OK
|| count
<= 0) {
5211 pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r
));
5212 return KRB5KDC_ERR_PREAUTH_FAILED
;
5214 mechp
= (CK_MECHANISM_TYPE_PTR
) malloc(count
* sizeof (CK_MECHANISM_TYPE
));
5217 if ((r
= id_cryptoctx
->p11
->C_GetMechanismList(id_cryptoctx
->slotid
,
5218 mechp
, &count
)) != CKR_OK
) {
5220 return KRB5KDC_ERR_PREAUTH_FAILED
;
5222 for (i
= 0; i
< count
; i
++) {
5223 if ((r
= id_cryptoctx
->p11
->C_GetMechanismInfo(id_cryptoctx
->slotid
,
5224 mechp
[i
], &info
)) != CKR_OK
) {
5226 return KRB5KDC_ERR_PREAUTH_FAILED
;
5228 #ifdef DEBUG_MECHINFO
5229 pkiDebug("mech %x flags %x\n", (int) mechp
[i
], (int) info
.flags
);
5230 if ((info
.flags
& (CKF_SIGN
|CKF_DECRYPT
)) == (CKF_SIGN
|CKF_DECRYPT
))
5231 pkiDebug(" this mech is good for sign & decrypt\n");
5233 if (mechp
[i
] == CKM_RSA_PKCS
) {
5234 /* This seems backwards... */
5235 id_cryptoctx
->mech
=
5236 (info
.flags
& CKF_SIGN
) ? CKM_SHA1_RSA_PKCS
: CKM_RSA_PKCS
;
5241 pkiDebug("got %d mechs from card\n", (int) count
);
5244 return (pkinit_open_session(context
, plg_cryptoctx
, req_cryptoctx
,
5245 id_cryptoctx
, princ
, do_matching
));
5251 free_cred_info(krb5_context context
,
5252 pkinit_identity_crypto_context id_cryptoctx
,
5253 struct _pkinit_cred_info
*cred
)
5256 if (cred
->cert
!= NULL
)
5257 X509_free(cred
->cert
);
5258 if (cred
->key
!= NULL
)
5259 EVP_PKEY_free(cred
->key
);
5260 #ifndef WITHOUT_PKCS11
5261 free(cred
->cert_id
);
5269 crypto_free_cert_info(krb5_context context
,
5270 pkinit_plg_crypto_context plg_cryptoctx
,
5271 pkinit_req_crypto_context req_cryptoctx
,
5272 pkinit_identity_crypto_context id_cryptoctx
)
5276 if (id_cryptoctx
== NULL
)
5279 for (i
= 0; i
< MAX_CREDS_ALLOWED
; i
++) {
5280 if (id_cryptoctx
->creds
[i
] != NULL
) {
5281 free_cred_info(context
, id_cryptoctx
, id_cryptoctx
->creds
[i
]);
5282 id_cryptoctx
->creds
[i
] = NULL
;
5289 crypto_load_certs(krb5_context context
,
5290 pkinit_plg_crypto_context plg_cryptoctx
,
5291 pkinit_req_crypto_context req_cryptoctx
,
5292 pkinit_identity_opts
*idopts
,
5293 pkinit_identity_crypto_context id_cryptoctx
,
5294 krb5_principal princ
,
5297 krb5_error_code retval
;
5299 switch(idopts
->idtype
) {
5301 retval
= pkinit_get_certs_fs(context
, plg_cryptoctx
,
5302 req_cryptoctx
, idopts
,
5303 id_cryptoctx
, princ
);
5306 retval
= pkinit_get_certs_dir(context
, plg_cryptoctx
,
5307 req_cryptoctx
, idopts
,
5308 id_cryptoctx
, princ
);
5310 #ifndef WITHOUT_PKCS11
5312 retval
= pkinit_get_certs_pkcs11(context
, plg_cryptoctx
,
5313 req_cryptoctx
, idopts
,
5314 id_cryptoctx
, princ
, do_matching
);
5318 retval
= pkinit_get_certs_pkcs12(context
, plg_cryptoctx
,
5319 req_cryptoctx
, idopts
,
5320 id_cryptoctx
, princ
);
5325 /* Solaris Kerberos */
5331 * Get number of certificates available after crypto_load_certs()
5335 crypto_cert_get_count(krb5_context context
,
5336 pkinit_plg_crypto_context plg_cryptoctx
,
5337 pkinit_req_crypto_context req_cryptoctx
,
5338 pkinit_identity_crypto_context id_cryptoctx
,
5343 if (id_cryptoctx
== NULL
|| id_cryptoctx
->creds
[0] == NULL
)
5347 count
<= MAX_CREDS_ALLOWED
&& id_cryptoctx
->creds
[count
] != NULL
;
5349 *cert_count
= count
;
5355 * Begin iteration over the certs loaded in crypto_load_certs()
5359 crypto_cert_iteration_begin(krb5_context context
,
5360 pkinit_plg_crypto_context plg_cryptoctx
,
5361 pkinit_req_crypto_context req_cryptoctx
,
5362 pkinit_identity_crypto_context id_cryptoctx
,
5363 pkinit_cert_iter_handle
*ih_ret
)
5365 struct _pkinit_cert_iter_data
*id
;
5367 if (id_cryptoctx
== NULL
|| ih_ret
== NULL
)
5369 if (id_cryptoctx
->creds
[0] == NULL
) /* No cred info available */
5372 id
= calloc(1, sizeof(*id
));
5375 id
->magic
= ITER_MAGIC
;
5376 id
->plgctx
= plg_cryptoctx
,
5377 id
->reqctx
= req_cryptoctx
,
5378 id
->idctx
= id_cryptoctx
;
5380 *ih_ret
= (pkinit_cert_iter_handle
) id
;
5385 * End iteration over the certs loaded in crypto_load_certs()
5389 crypto_cert_iteration_end(krb5_context context
,
5390 pkinit_cert_iter_handle ih
)
5392 struct _pkinit_cert_iter_data
*id
= (struct _pkinit_cert_iter_data
*)ih
;
5394 if (id
== NULL
|| id
->magic
!= ITER_MAGIC
)
5401 * Get next certificate handle
5405 crypto_cert_iteration_next(krb5_context context
,
5406 pkinit_cert_iter_handle ih
,
5407 pkinit_cert_handle
*ch_ret
)
5409 struct _pkinit_cert_iter_data
*id
= (struct _pkinit_cert_iter_data
*)ih
;
5410 struct _pkinit_cert_data
*cd
;
5411 pkinit_identity_crypto_context id_cryptoctx
;
5413 if (id
== NULL
|| id
->magic
!= ITER_MAGIC
)
5419 id_cryptoctx
= id
->idctx
;
5420 if (id_cryptoctx
== NULL
)
5423 if (id_cryptoctx
->creds
[id
->index
] == NULL
)
5424 return PKINIT_ITER_NO_MORE
;
5426 cd
= calloc(1, sizeof(*cd
));
5430 cd
->magic
= CERT_MAGIC
;
5431 cd
->plgctx
= id
->plgctx
;
5432 cd
->reqctx
= id
->reqctx
;
5433 cd
->idctx
= id
->idctx
;
5434 cd
->index
= id
->index
;
5435 cd
->cred
= id_cryptoctx
->creds
[id
->index
++];
5436 *ch_ret
= (pkinit_cert_handle
)cd
;
5441 * Release cert handle
5445 crypto_cert_release(krb5_context context
,
5446 pkinit_cert_handle ch
)
5448 struct _pkinit_cert_data
*cd
= (struct _pkinit_cert_data
*)ch
;
5449 if (cd
== NULL
|| cd
->magic
!= CERT_MAGIC
)
5456 * Get certificate Key Usage and Extended Key Usage
5459 static krb5_error_code
5460 crypto_retieve_X509_key_usage(krb5_context context
,
5461 pkinit_plg_crypto_context plgcctx
,
5462 pkinit_req_crypto_context reqcctx
,
5464 unsigned int *ret_ku_bits
,
5465 unsigned int *ret_eku_bits
)
5467 /* Solaris Kerberos */
5469 unsigned int eku_bits
= 0, ku_bits
= 0;
5470 ASN1_BIT_STRING
*usage
= NULL
;
5472 if (ret_ku_bits
== NULL
&& ret_eku_bits
== NULL
)
5478 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__
);
5482 /* Start with Extended Key usage */
5483 i
= X509_get_ext_by_NID(x
, NID_ext_key_usage
, -1);
5485 EXTENDED_KEY_USAGE
*eku
;
5487 eku
= X509_get_ext_d2i(x
, NID_ext_key_usage
, NULL
, NULL
);
5489 for (i
= 0; i
< sk_ASN1_OBJECT_num(eku
); i
++) {
5490 ASN1_OBJECT
*certoid
;
5491 certoid
= sk_ASN1_OBJECT_value(eku
, i
);
5492 if ((OBJ_cmp(certoid
, plgcctx
->id_pkinit_KPClientAuth
)) == 0)
5493 eku_bits
|= PKINIT_EKU_PKINIT
;
5494 else if ((OBJ_cmp(certoid
, OBJ_nid2obj(NID_ms_smartcard_login
))) == 0)
5495 eku_bits
|= PKINIT_EKU_MSSCLOGIN
;
5496 else if ((OBJ_cmp(certoid
, OBJ_nid2obj(NID_client_auth
))) == 0)
5497 eku_bits
|= PKINIT_EKU_CLIENTAUTH
;
5498 else if ((OBJ_cmp(certoid
, OBJ_nid2obj(NID_email_protect
))) == 0)
5499 eku_bits
|= PKINIT_EKU_EMAILPROTECTION
;
5501 EXTENDED_KEY_USAGE_free(eku
);
5504 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__
, eku_bits
);
5505 *ret_eku_bits
= eku_bits
;
5508 /* Now the Key Usage bits */
5512 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__
);
5516 /* Make sure usage exists before checking bits */
5517 usage
= X509_get_ext_d2i(x
, NID_key_usage
, NULL
, NULL
);
5519 if (!ku_reject(x
, X509v3_KU_DIGITAL_SIGNATURE
))
5520 ku_bits
|= PKINIT_KU_DIGITALSIGNATURE
;
5521 if (!ku_reject(x
, X509v3_KU_KEY_ENCIPHERMENT
))
5522 ku_bits
|= PKINIT_KU_KEYENCIPHERMENT
;
5523 ASN1_BIT_STRING_free(usage
);
5526 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__
, ku_bits
);
5527 *ret_ku_bits
= ku_bits
;
5534 * Return a string format of an X509_NAME in buf where
5535 * size is an in/out parameter. On input it is the size
5536 * of the buffer, and on output it is the actual length
5538 * If buf is NULL, returns the length req'd to hold name
5541 X509_NAME_oneline_ex(X509_NAME
* a
,
5548 out
= BIO_new(BIO_s_mem ());
5549 if (X509_NAME_print_ex(out
, a
, 0, flag
) > 0) {
5550 if (buf
!= NULL
&& *size
> (int) BIO_number_written(out
)) {
5551 (void) memset(buf
, 0, *size
);
5552 BIO_read(out
, buf
, (int) BIO_number_written(out
));
5555 *size
= BIO_number_written(out
);
5563 * Get certificate information
5566 crypto_cert_get_matching_data(krb5_context context
,
5567 pkinit_cert_handle ch
,
5568 pkinit_cert_matching_data
**ret_md
)
5570 krb5_error_code retval
;
5571 pkinit_cert_matching_data
*md
;
5572 krb5_principal
*pkinit_sans
=NULL
, *upn_sans
= NULL
;
5573 struct _pkinit_cert_data
*cd
= (struct _pkinit_cert_data
*)ch
;
5575 char buf
[DN_BUF_LEN
];
5576 unsigned int bufsize
= sizeof(buf
);
5578 if (cd
== NULL
|| cd
->magic
!= CERT_MAGIC
)
5583 md
= calloc(1, sizeof(*md
));
5589 /* get the subject name (in rfc2253 format) */
5590 X509_NAME_oneline_ex(X509_get_subject_name(cd
->cred
->cert
),
5591 buf
, &bufsize
, XN_FLAG_SEP_COMMA_PLUS
);
5592 md
->subject_dn
= strdup(buf
);
5593 if (md
->subject_dn
== NULL
) {
5598 /* get the issuer name (in rfc2253 format) */
5599 X509_NAME_oneline_ex(X509_get_issuer_name(cd
->cred
->cert
),
5600 buf
, &bufsize
, XN_FLAG_SEP_COMMA_PLUS
);
5601 md
->issuer_dn
= strdup(buf
);
5602 if (md
->issuer_dn
== NULL
) {
5607 /* get the san data */
5608 retval
= crypto_retrieve_X509_sans(context
, cd
->plgctx
, cd
->reqctx
,
5609 cd
->cred
->cert
, &pkinit_sans
,
5615 if (pkinit_sans
!= NULL
) {
5616 for (i
= 0; pkinit_sans
[i
] != NULL
; i
++)
5619 if (upn_sans
!= NULL
) {
5620 for (i
= 0; upn_sans
[i
] != NULL
; i
++)
5624 md
->sans
= calloc((size_t)j
+1, sizeof(*md
->sans
));
5625 if (md
->sans
== NULL
) {
5630 if (pkinit_sans
!= NULL
) {
5631 for (i
= 0; pkinit_sans
[i
] != NULL
; i
++)
5632 md
->sans
[j
++] = pkinit_sans
[i
];
5635 if (upn_sans
!= NULL
) {
5636 for (i
= 0; upn_sans
[i
] != NULL
; i
++)
5637 md
->sans
[j
++] = upn_sans
[i
];
5644 /* get the KU and EKU data */
5646 retval
= crypto_retieve_X509_key_usage(context
, cd
->plgctx
, cd
->reqctx
,
5648 &md
->ku_bits
, &md
->eku_bits
);
5657 crypto_cert_free_matching_data(context
, md
);
5663 * Free certificate information
5666 crypto_cert_free_matching_data(krb5_context context
,
5667 pkinit_cert_matching_data
*md
)
5674 free(md
->subject_dn
);
5675 free(md
->issuer_dn
);
5677 for (i
= 0, p
= md
->sans
[i
]; p
!= NULL
; p
= md
->sans
[++i
])
5678 krb5_free_principal(context
, p
);
5686 * Make this matching certificate "the chosen one"
5690 crypto_cert_select(krb5_context context
,
5691 pkinit_cert_matching_data
*md
)
5693 struct _pkinit_cert_data
*cd
;
5697 cd
= (struct _pkinit_cert_data
*)md
->ch
;
5698 if (cd
== NULL
|| cd
->magic
!= CERT_MAGIC
)
5701 /* copy the selected cert into our id_cryptoctx */
5702 if (cd
->idctx
->my_certs
!= NULL
) {
5703 sk_X509_pop_free(cd
->idctx
->my_certs
, X509_free
);
5705 cd
->idctx
->my_certs
= sk_X509_new_null();
5706 sk_X509_push(cd
->idctx
->my_certs
, cd
->cred
->cert
);
5707 cd
->idctx
->creds
[cd
->index
]->cert
= NULL
; /* Don't free it twice */
5708 cd
->idctx
->cert_index
= 0;
5710 if (cd
->idctx
->pkcs11_method
!= 1) {
5711 cd
->idctx
->my_key
= cd
->cred
->key
;
5712 cd
->idctx
->creds
[cd
->index
]->key
= NULL
; /* Don't free it twice */
5714 #ifndef WITHOUT_PKCS11
5716 cd
->idctx
->cert_id
= cd
->cred
->cert_id
;
5717 cd
->idctx
->creds
[cd
->index
]->cert_id
= NULL
; /* Don't free it twice */
5718 cd
->idctx
->cert_id_len
= cd
->cred
->cert_id_len
;
5725 * Choose the default certificate as "the chosen one"
5728 crypto_cert_select_default(krb5_context context
,
5729 pkinit_plg_crypto_context plg_cryptoctx
,
5730 pkinit_req_crypto_context req_cryptoctx
,
5731 pkinit_identity_crypto_context id_cryptoctx
)
5733 krb5_error_code retval
;
5736 retval
= crypto_cert_get_count(context
, plg_cryptoctx
, req_cryptoctx
,
5737 id_cryptoctx
, &cert_count
);
5739 pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
5740 __FUNCTION__
, retval
, error_message(retval
));
5743 if (cert_count
!= 1) {
5744 /* Solaris Kerberos: Improved error messages */
5746 krb5_set_error_message(context
, retval
,
5747 gettext("Failed to select default certificate: "
5748 "found %d certs to choose from but there must be exactly one"),
5750 pkiDebug("%s: ERROR: There are %d certs to choose from, "
5751 "but there must be exactly one.\n",
5752 __FUNCTION__
, cert_count
);
5755 /* copy the selected cert into our id_cryptoctx */
5756 if (id_cryptoctx
->my_certs
!= NULL
) {
5757 sk_X509_pop_free(id_cryptoctx
->my_certs
, X509_free
);
5759 id_cryptoctx
->my_certs
= sk_X509_new_null();
5760 sk_X509_push(id_cryptoctx
->my_certs
, id_cryptoctx
->creds
[0]->cert
);
5761 id_cryptoctx
->creds
[0]->cert
= NULL
; /* Don't free it twice */
5762 id_cryptoctx
->cert_index
= 0;
5764 if (id_cryptoctx
->pkcs11_method
!= 1) {
5765 id_cryptoctx
->my_key
= id_cryptoctx
->creds
[0]->key
;
5766 id_cryptoctx
->creds
[0]->key
= NULL
; /* Don't free it twice */
5768 #ifndef WITHOUT_PKCS11
5770 id_cryptoctx
->cert_id
= id_cryptoctx
->creds
[0]->cert_id
;
5771 id_cryptoctx
->creds
[0]->cert_id
= NULL
; /* Don't free it twice */
5772 id_cryptoctx
->cert_id_len
= id_cryptoctx
->creds
[0]->cert_id_len
;
5782 static krb5_error_code
5783 load_cas_and_crls(krb5_context context
,
5784 pkinit_plg_crypto_context plg_cryptoctx
,
5785 pkinit_req_crypto_context req_cryptoctx
,
5786 pkinit_identity_crypto_context id_cryptoctx
,
5790 STACK_OF(X509_INFO
) *sk
= NULL
;
5791 STACK_OF(X509
) *ca_certs
= NULL
;
5792 STACK_OF(X509_CRL
) *ca_crls
= NULL
;
5794 /* Solaris Kerberos */
5795 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
5798 /* If there isn't already a stack in the context,
5799 * create a temporary one now */
5801 case CATYPE_ANCHORS
:
5802 if (id_cryptoctx
->trustedCAs
!= NULL
)
5803 ca_certs
= id_cryptoctx
->trustedCAs
;
5805 ca_certs
= sk_X509_new_null();
5806 if (ca_certs
== NULL
)
5810 case CATYPE_INTERMEDIATES
:
5811 if (id_cryptoctx
->intermediateCAs
!= NULL
)
5812 ca_certs
= id_cryptoctx
->intermediateCAs
;
5814 ca_certs
= sk_X509_new_null();
5815 if (ca_certs
== NULL
)
5820 if (id_cryptoctx
->revoked
!= NULL
)
5821 ca_crls
= id_cryptoctx
->revoked
;
5823 ca_crls
= sk_X509_CRL_new_null();
5824 if (ca_crls
== NULL
)
5832 if (!(in
= BIO_new_file(filename
, "r"))) {
5834 pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__
,
5835 filename
, error_message(errno
));
5839 /* This loads from a file, a stack of x509/crl/pkey sets */
5840 if ((sk
= PEM_X509_INFO_read_bio(in
, NULL
, NULL
, NULL
)) == NULL
) {
5841 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__
, filename
);
5846 /* scan over the stack created from loading the file contents,
5847 * weed out duplicates, and push new ones onto the return stack
5849 for (i
= 0; i
< sk_X509_INFO_num(sk
); i
++) {
5850 X509_INFO
*xi
= sk_X509_INFO_value(sk
, i
);
5851 if (xi
!= NULL
&& xi
->x509
!= NULL
&& catype
!= CATYPE_CRLS
) {
5852 int j
= 0, size
= sk_X509_num(ca_certs
), flag
= 0;
5855 sk_X509_push(ca_certs
, xi
->x509
);
5859 for (j
= 0; j
< size
; j
++) {
5860 X509
*x
= sk_X509_value(ca_certs
, j
);
5861 flag
= X509_cmp(x
, xi
->x509
);
5868 sk_X509_push(ca_certs
, X509_dup(xi
->x509
));
5870 } else if (xi
!= NULL
&& xi
->crl
!= NULL
&& catype
== CATYPE_CRLS
) {
5871 int j
= 0, size
= sk_X509_CRL_num(ca_crls
), flag
= 0;
5873 sk_X509_CRL_push(ca_crls
, xi
->crl
);
5877 for (j
= 0; j
< size
; j
++) {
5878 X509_CRL
*x
= sk_X509_CRL_value(ca_crls
, j
);
5879 flag
= X509_CRL_cmp(x
, xi
->crl
);
5886 sk_X509_CRL_push(ca_crls
, X509_CRL_dup(xi
->crl
));
5891 /* If we added something and there wasn't a stack in the
5892 * context before, add the temporary stack to the context.
5895 case CATYPE_ANCHORS
:
5896 if (sk_X509_num(ca_certs
) == 0) {
5897 pkiDebug("no anchors in file, %s\n", filename
);
5898 if (id_cryptoctx
->trustedCAs
== NULL
)
5899 sk_X509_free(ca_certs
);
5901 if (id_cryptoctx
->trustedCAs
== NULL
)
5902 id_cryptoctx
->trustedCAs
= ca_certs
;
5905 case CATYPE_INTERMEDIATES
:
5906 if (sk_X509_num(ca_certs
) == 0) {
5907 pkiDebug("no intermediates in file, %s\n", filename
);
5908 if (id_cryptoctx
->intermediateCAs
== NULL
)
5909 sk_X509_free(ca_certs
);
5911 if (id_cryptoctx
->intermediateCAs
== NULL
)
5912 id_cryptoctx
->intermediateCAs
= ca_certs
;
5916 if (sk_X509_CRL_num(ca_crls
) == 0) {
5917 pkiDebug("no crls in file, %s\n", filename
);
5918 if (id_cryptoctx
->revoked
== NULL
)
5919 sk_X509_CRL_free(ca_crls
);
5921 if (id_cryptoctx
->revoked
== NULL
)
5922 id_cryptoctx
->revoked
= ca_crls
;
5926 /* Should have been caught above! */
5929 /* Solaris Kerberos: removed "break" as it's never reached */
5938 sk_X509_INFO_pop_free(sk
, X509_INFO_free
);
5943 static krb5_error_code
5944 load_cas_and_crls_dir(krb5_context context
,
5945 pkinit_plg_crypto_context plg_cryptoctx
,
5946 pkinit_req_crypto_context req_cryptoctx
,
5947 pkinit_identity_crypto_context id_cryptoctx
,
5951 krb5_error_code retval
= EINVAL
;
5953 struct dirent
*dentry
= NULL
;
5954 char filename
[1024];
5956 if (dirname
== NULL
)
5959 d
= opendir(dirname
);
5963 while ((dentry
= readdir(d
))) {
5964 if (strlen(dirname
) + strlen(dentry
->d_name
) + 2 > sizeof(filename
)) {
5965 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
5966 __FUNCTION__
, dirname
, dentry
->d_name
);
5969 /* Ignore subdirectories and anything starting with a dot */
5971 if (dentry
->d_type
== DT_DIR
)
5974 if (dentry
->d_name
[0] == '.')
5976 (void) snprintf(filename
, sizeof(filename
), "%s/%s", dirname
, dentry
->d_name
);
5978 retval
= load_cas_and_crls(context
, plg_cryptoctx
, req_cryptoctx
,
5979 id_cryptoctx
, catype
, filename
);
5995 crypto_load_cas_and_crls(krb5_context context
,
5996 pkinit_plg_crypto_context plg_cryptoctx
,
5997 pkinit_req_crypto_context req_cryptoctx
,
5998 pkinit_identity_opts
*idopts
,
5999 pkinit_identity_crypto_context id_cryptoctx
,
6004 pkiDebug("%s: called with idtype %s and catype %s\n",
6005 __FUNCTION__
, idtype2string(idtype
), catype2string(catype
));
6006 /* Solaris Kerberos: Removed "break"'s as they are never reached */
6009 return load_cas_and_crls(context
, plg_cryptoctx
, req_cryptoctx
,
6010 id_cryptoctx
, catype
, id
);
6012 return load_cas_and_crls_dir(context
, plg_cryptoctx
, req_cryptoctx
,
6013 id_cryptoctx
, catype
, id
);
6019 static krb5_error_code
6020 create_identifiers_from_stack(STACK_OF(X509
) *sk
,
6021 krb5_external_principal_identifier
*** ids
)
6023 krb5_error_code retval
= ENOMEM
;
6024 int i
= 0, sk_size
= sk_X509_num(sk
);
6025 krb5_external_principal_identifier
**krb5_cas
= NULL
;
6027 X509_NAME
*xn
= NULL
;
6028 unsigned char *p
= NULL
;
6030 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6031 char buf
[DN_BUF_LEN
];
6036 malloc((sk_size
+ 1) * sizeof(krb5_external_principal_identifier
*));
6037 if (krb5_cas
== NULL
)
6039 krb5_cas
[sk_size
] = NULL
;
6041 for (i
= 0; i
< sk_size
; i
++) {
6042 krb5_cas
[i
] = (krb5_external_principal_identifier
*)malloc(sizeof(krb5_external_principal_identifier
));
6044 x
= sk_X509_value(sk
, i
);
6046 X509_NAME_oneline(X509_get_subject_name(x
), buf
, sizeof(buf
));
6047 pkiDebug("#%d cert= %s\n", i
, buf
);
6049 /* fill-in subjectName */
6050 krb5_cas
[i
]->subjectName
.magic
= 0;
6051 krb5_cas
[i
]->subjectName
.length
= 0;
6052 krb5_cas
[i
]->subjectName
.data
= NULL
;
6054 xn
= X509_get_subject_name(x
);
6055 len
= i2d_X509_NAME(xn
, NULL
);
6056 if ((p
= krb5_cas
[i
]->subjectName
.data
= (unsigned char *)malloc((size_t) len
)) == NULL
)
6058 i2d_X509_NAME(xn
, &p
);
6059 krb5_cas
[i
]->subjectName
.length
= len
;
6061 /* fill-in issuerAndSerialNumber */
6062 krb5_cas
[i
]->issuerAndSerialNumber
.length
= 0;
6063 krb5_cas
[i
]->issuerAndSerialNumber
.magic
= 0;
6064 krb5_cas
[i
]->issuerAndSerialNumber
.data
= NULL
;
6066 #ifdef LONGHORN_BETA_COMPAT
6067 if (longhorn
== 0) { /* XXX Longhorn doesn't like this */
6069 is
= PKCS7_ISSUER_AND_SERIAL_new();
6070 X509_NAME_set(&is
->issuer
, X509_get_issuer_name(x
));
6071 M_ASN1_INTEGER_free(is
->serial
);
6072 is
->serial
= M_ASN1_INTEGER_dup(X509_get_serialNumber(x
));
6073 len
= i2d_PKCS7_ISSUER_AND_SERIAL(is
, NULL
);
6074 if ((p
= krb5_cas
[i
]->issuerAndSerialNumber
.data
=
6075 (unsigned char *)malloc((size_t) len
)) == NULL
)
6077 i2d_PKCS7_ISSUER_AND_SERIAL(is
, &p
);
6078 krb5_cas
[i
]->issuerAndSerialNumber
.length
= len
;
6079 #ifdef LONGHORN_BETA_COMPAT
6083 /* fill-in subjectKeyIdentifier */
6084 krb5_cas
[i
]->subjectKeyIdentifier
.length
= 0;
6085 krb5_cas
[i
]->subjectKeyIdentifier
.magic
= 0;
6086 krb5_cas
[i
]->subjectKeyIdentifier
.data
= NULL
;
6089 #ifdef LONGHORN_BETA_COMPAT
6090 if (longhorn
== 0) { /* XXX Longhorn doesn't like this */
6092 if (X509_get_ext_by_NID(x
, NID_subject_key_identifier
, -1) >= 0) {
6093 ASN1_OCTET_STRING
*ikeyid
= NULL
;
6095 if ((ikeyid
= X509_get_ext_d2i(x
, NID_subject_key_identifier
, NULL
,
6097 len
= i2d_ASN1_OCTET_STRING(ikeyid
, NULL
);
6098 if ((p
= krb5_cas
[i
]->subjectKeyIdentifier
.data
=
6099 (unsigned char *)malloc((size_t) len
)) == NULL
)
6101 i2d_ASN1_OCTET_STRING(ikeyid
, &p
);
6102 krb5_cas
[i
]->subjectKeyIdentifier
.length
= len
;
6105 ASN1_OCTET_STRING_free(ikeyid
);
6107 #ifdef LONGHORN_BETA_COMPAT
6111 if (is
->issuer
!= NULL
)
6112 X509_NAME_free(is
->issuer
);
6113 if (is
->serial
!= NULL
)
6114 ASN1_INTEGER_free(is
->serial
);
6124 free_krb5_external_principal_identifier(&krb5_cas
);
6130 static krb5_error_code
6131 create_krb5_invalidCertificates(krb5_context context
,
6132 pkinit_plg_crypto_context plg_cryptoctx
,
6133 pkinit_req_crypto_context req_cryptoctx
,
6134 pkinit_identity_crypto_context id_cryptoctx
,
6135 krb5_external_principal_identifier
*** ids
)
6138 krb5_error_code retval
= ENOMEM
;
6139 STACK_OF(X509
) *sk
= NULL
;
6142 if (req_cryptoctx
->received_cert
== NULL
)
6143 return KRB5KDC_ERR_PREAUTH_FAILED
;
6145 sk
= sk_X509_new_null();
6148 sk_X509_push(sk
, req_cryptoctx
->received_cert
);
6150 retval
= create_identifiers_from_stack(sk
, ids
);
6160 create_krb5_supportedCMSTypes(krb5_context context
,
6161 pkinit_plg_crypto_context plg_cryptoctx
,
6162 pkinit_req_crypto_context req_cryptoctx
,
6163 pkinit_identity_crypto_context id_cryptoctx
,
6164 krb5_algorithm_identifier
***oids
)
6167 krb5_error_code retval
= ENOMEM
;
6168 krb5_algorithm_identifier
**loids
= NULL
;
6169 krb5_octet_data des3oid
= {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
6172 loids
= malloc(2 * sizeof(krb5_algorithm_identifier
*));
6176 loids
[0] = (krb5_algorithm_identifier
*)malloc(sizeof(krb5_algorithm_identifier
));
6177 if (loids
[0] == NULL
) {
6181 retval
= pkinit_copy_krb5_octet_data(&loids
[0]->algorithm
, &des3oid
);
6187 loids
[0]->parameters
.length
= 0;
6188 loids
[0]->parameters
.data
= NULL
;
6199 create_krb5_trustedCertifiers(krb5_context context
,
6200 pkinit_plg_crypto_context plg_cryptoctx
,
6201 pkinit_req_crypto_context req_cryptoctx
,
6202 pkinit_identity_crypto_context id_cryptoctx
,
6203 krb5_external_principal_identifier
*** ids
)
6206 /* Solaris Kerberos */
6207 STACK_OF(X509
) *sk
= id_cryptoctx
->trustedCAs
;
6210 if (id_cryptoctx
->trustedCAs
== NULL
)
6211 return KRB5KDC_ERR_PREAUTH_FAILED
;
6213 return create_identifiers_from_stack(sk
, ids
);
6219 create_krb5_trustedCas(krb5_context context
,
6220 pkinit_plg_crypto_context plg_cryptoctx
,
6221 pkinit_req_crypto_context req_cryptoctx
,
6222 pkinit_identity_crypto_context id_cryptoctx
,
6224 krb5_trusted_ca
*** ids
)
6226 krb5_error_code retval
= ENOMEM
;
6227 STACK_OF(X509
) *sk
= id_cryptoctx
->trustedCAs
;
6228 int i
= 0, len
= 0, sk_size
= sk_X509_num(sk
);
6229 krb5_trusted_ca
**krb5_cas
= NULL
;
6231 char buf
[DN_BUF_LEN
];
6232 X509_NAME
*xn
= NULL
;
6233 unsigned char *p
= NULL
;
6234 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6237 if (id_cryptoctx
->trustedCAs
== NULL
)
6238 return KRB5KDC_ERR_PREAUTH_FAILED
;
6240 krb5_cas
= malloc((sk_size
+ 1) * sizeof(krb5_trusted_ca
*));
6241 if (krb5_cas
== NULL
)
6243 krb5_cas
[sk_size
] = NULL
;
6245 for (i
= 0; i
< sk_size
; i
++) {
6246 krb5_cas
[i
] = (krb5_trusted_ca
*)malloc(sizeof(krb5_trusted_ca
));
6247 if (krb5_cas
[i
] == NULL
)
6249 x
= sk_X509_value(sk
, i
);
6251 X509_NAME_oneline(X509_get_subject_name(x
), buf
, sizeof(buf
));
6252 pkiDebug("#%d cert= %s\n", i
, buf
);
6255 case choice_trusted_cas_principalName
:
6256 krb5_cas
[i
]->choice
= choice_trusted_cas_principalName
;
6258 case choice_trusted_cas_caName
:
6259 krb5_cas
[i
]->choice
= choice_trusted_cas_caName
;
6260 krb5_cas
[i
]->u
.caName
.data
= NULL
;
6261 krb5_cas
[i
]->u
.caName
.length
= 0;
6262 xn
= X509_get_subject_name(x
);
6263 len
= i2d_X509_NAME(xn
, NULL
);
6264 if ((p
= krb5_cas
[i
]->u
.caName
.data
=
6265 (unsigned char *)malloc((size_t) len
)) == NULL
)
6267 i2d_X509_NAME(xn
, &p
);
6268 krb5_cas
[i
]->u
.caName
.length
= len
;
6270 case choice_trusted_cas_issuerAndSerial
:
6271 krb5_cas
[i
]->choice
= choice_trusted_cas_issuerAndSerial
;
6272 krb5_cas
[i
]->u
.issuerAndSerial
.data
= NULL
;
6273 krb5_cas
[i
]->u
.issuerAndSerial
.length
= 0;
6274 is
= PKCS7_ISSUER_AND_SERIAL_new();
6275 X509_NAME_set(&is
->issuer
, X509_get_issuer_name(x
));
6276 M_ASN1_INTEGER_free(is
->serial
);
6277 is
->serial
= M_ASN1_INTEGER_dup(X509_get_serialNumber(x
));
6278 len
= i2d_PKCS7_ISSUER_AND_SERIAL(is
, NULL
);
6279 if ((p
= krb5_cas
[i
]->u
.issuerAndSerial
.data
=
6280 (unsigned char *)malloc((size_t) len
)) == NULL
)
6282 i2d_PKCS7_ISSUER_AND_SERIAL(is
, &p
);
6283 krb5_cas
[i
]->u
.issuerAndSerial
.length
= len
;
6285 if (is
->issuer
!= NULL
)
6286 X509_NAME_free(is
->issuer
);
6287 if (is
->serial
!= NULL
)
6288 ASN1_INTEGER_free(is
->serial
);
6299 free_krb5_trusted_ca(&krb5_cas
);
6306 create_issuerAndSerial(krb5_context context
,
6307 pkinit_plg_crypto_context plg_cryptoctx
,
6308 pkinit_req_crypto_context req_cryptoctx
,
6309 pkinit_identity_crypto_context id_cryptoctx
,
6310 unsigned char **out
,
6311 unsigned int *out_len
)
6313 unsigned char *p
= NULL
;
6314 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6316 krb5_error_code retval
= ENOMEM
;
6317 X509
*cert
= req_cryptoctx
->received_cert
;
6321 if (req_cryptoctx
->received_cert
== NULL
)
6324 is
= PKCS7_ISSUER_AND_SERIAL_new();
6325 X509_NAME_set(&is
->issuer
, X509_get_issuer_name(cert
));
6326 M_ASN1_INTEGER_free(is
->serial
);
6327 is
->serial
= M_ASN1_INTEGER_dup(X509_get_serialNumber(cert
));
6328 len
= i2d_PKCS7_ISSUER_AND_SERIAL(is
, NULL
);
6329 if ((p
= *out
= (unsigned char *)malloc((size_t) len
)) == NULL
)
6331 i2d_PKCS7_ISSUER_AND_SERIAL(is
, &p
);
6336 X509_NAME_free(is
->issuer
);
6337 ASN1_INTEGER_free(is
->serial
);
6344 pkcs7_decrypt(krb5_context context
,
6345 pkinit_identity_crypto_context id_cryptoctx
,
6350 /* Solaris Kerberos */
6357 if(!PKCS7_type_is_enveloped(p7
)) {
6358 pkiDebug("wrong pkcs7 content type\n");
6362 if(!(tmpmem
= pkcs7_dataDecode(context
, id_cryptoctx
, p7
))) {
6363 pkiDebug("unable to decrypt pkcs7 object\n");
6366 /* Solaris Kerberos: Suppress sun studio compiler warning */
6367 #pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED)
6369 i
= BIO_read(tmpmem
, buf
, sizeof(buf
));
6371 BIO_write(data
, buf
, i
);
6372 BIO_free_all(tmpmem
);
6375 #pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED)
6381 pkinit_process_td_trusted_certifiers(
6382 krb5_context context
,
6383 pkinit_plg_crypto_context plg_cryptoctx
,
6384 pkinit_req_crypto_context req_cryptoctx
,
6385 pkinit_identity_crypto_context id_cryptoctx
,
6386 krb5_external_principal_identifier
**krb5_trusted_certifiers
,
6389 krb5_error_code retval
= ENOMEM
;
6390 STACK_OF(X509_NAME
) *sk_xn
= NULL
;
6391 X509_NAME
*xn
= NULL
;
6392 PKCS7_ISSUER_AND_SERIAL
*is
= NULL
;
6393 ASN1_OCTET_STRING
*id
= NULL
;
6394 const unsigned char *p
= NULL
;
6395 char buf
[DN_BUF_LEN
];
6398 if (td_type
== TD_TRUSTED_CERTIFIERS
)
6399 pkiDebug("received trusted certifiers\n");
6401 pkiDebug("received invalid certificate\n");
6403 sk_xn
= sk_X509_NAME_new_null();
6404 while(krb5_trusted_certifiers
[i
] != NULL
) {
6405 if (krb5_trusted_certifiers
[i
]->subjectName
.data
!= NULL
) {
6406 p
= krb5_trusted_certifiers
[i
]->subjectName
.data
;
6407 xn
= d2i_X509_NAME(NULL
, &p
,
6408 (int)krb5_trusted_certifiers
[i
]->subjectName
.length
);
6411 X509_NAME_oneline(xn
, buf
, sizeof(buf
));
6412 if (td_type
== TD_TRUSTED_CERTIFIERS
)
6413 pkiDebug("#%d cert = %s is trusted by kdc\n", i
, buf
);
6415 pkiDebug("#%d cert = %s is invalid\n", i
, buf
);
6416 sk_X509_NAME_push(sk_xn
, xn
);
6419 if (krb5_trusted_certifiers
[i
]->issuerAndSerialNumber
.data
!= NULL
) {
6420 p
= krb5_trusted_certifiers
[i
]->issuerAndSerialNumber
.data
;
6421 is
= d2i_PKCS7_ISSUER_AND_SERIAL(NULL
, &p
,
6422 (int)krb5_trusted_certifiers
[i
]->issuerAndSerialNumber
.length
);
6425 X509_NAME_oneline(is
->issuer
, buf
, sizeof(buf
));
6426 if (td_type
== TD_TRUSTED_CERTIFIERS
)
6427 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i
,
6428 buf
, ASN1_INTEGER_get(is
->serial
));
6430 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i
, buf
,
6431 ASN1_INTEGER_get(is
->serial
));
6432 PKCS7_ISSUER_AND_SERIAL_free(is
);
6435 if (krb5_trusted_certifiers
[i
]->subjectKeyIdentifier
.data
!= NULL
) {
6436 p
= krb5_trusted_certifiers
[i
]->subjectKeyIdentifier
.data
;
6437 id
= d2i_ASN1_OCTET_STRING(NULL
, &p
,
6438 (int)krb5_trusted_certifiers
[i
]->subjectKeyIdentifier
.length
);
6442 ASN1_OCTET_STRING_free(id
);
6446 /* XXX Since we not doing anything with received trusted certifiers
6447 * return an error. this is the place where we can pick a different
6448 * client certificate based on the information in td_trusted_certifiers
6450 retval
= KRB5KDC_ERR_PREAUTH_FAILED
;
6453 sk_X509_NAME_pop_free(sk_xn
, X509_NAME_free
);
6459 pkcs7_dataDecode(krb5_context context
,
6460 pkinit_identity_crypto_context id_cryptoctx
,
6464 unsigned int jj
= 0, tmp_len
= 0;
6465 BIO
*out
=NULL
,*etmp
=NULL
,*bio
=NULL
;
6466 unsigned char *tmp
=NULL
;
6467 ASN1_OCTET_STRING
*data_body
=NULL
;
6468 const EVP_CIPHER
*evp_cipher
=NULL
;
6469 EVP_CIPHER_CTX
*evp_ctx
=NULL
;
6470 X509_ALGOR
*enc_alg
=NULL
;
6471 STACK_OF(PKCS7_RECIP_INFO
) *rsk
=NULL
;
6472 /* Solaris Kerberos: Not used */
6474 X509_ALGOR
*xalg
=NULL
;
6476 PKCS7_RECIP_INFO
*ri
=NULL
;
6477 X509
*cert
= sk_X509_value(id_cryptoctx
->my_certs
,
6478 id_cryptoctx
->cert_index
);
6480 p7
->state
=PKCS7_S_HEADER
;
6482 rsk
=p7
->d
.enveloped
->recipientinfo
;
6483 enc_alg
=p7
->d
.enveloped
->enc_data
->algorithm
;
6484 data_body
=p7
->d
.enveloped
->enc_data
->enc_data
;
6485 evp_cipher
=EVP_get_cipherbyobj(enc_alg
->algorithm
);
6486 if (evp_cipher
== NULL
) {
6487 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,PKCS7_R_UNSUPPORTED_CIPHER_TYPE
);
6490 /* Solaris Kerberos: Not used */
6492 xalg
=p7
->d
.enveloped
->enc_data
->algorithm
;
6495 if ((etmp
=BIO_new(BIO_f_cipher())) == NULL
) {
6496 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,ERR_R_BIO_LIB
);
6500 /* It was encrypted, we need to decrypt the secret key
6501 * with the private key */
6503 /* Find the recipientInfo which matches the passed certificate
6508 for (i
=0; i
<sk_PKCS7_RECIP_INFO_num(rsk
); i
++) {
6510 ri
=sk_PKCS7_RECIP_INFO_value(rsk
,i
);
6511 tmp_ret
= X509_NAME_cmp(ri
->issuer_and_serial
->issuer
,
6512 cert
->cert_info
->issuer
);
6514 tmp_ret
= M_ASN1_INTEGER_cmp(cert
->cert_info
->serialNumber
,
6515 ri
->issuer_and_serial
->serial
);
6522 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,
6523 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE
);
6528 /* If we haven't got a certificate try each ri in turn */
6531 for (i
=0; i
<sk_PKCS7_RECIP_INFO_num(rsk
); i
++) {
6532 ri
=sk_PKCS7_RECIP_INFO_value(rsk
,i
);
6533 jj
= pkinit_decode_data(context
, id_cryptoctx
,
6534 M_ASN1_STRING_data(ri
->enc_key
),
6535 (unsigned int) M_ASN1_STRING_length(ri
->enc_key
),
6538 PKCS7err(PKCS7_F_PKCS7_DATADECODE
, ERR_R_EVP_LIB
);
6542 if (!jj
&& tmp_len
> 0) {
6552 PKCS7err(PKCS7_F_PKCS7_DATADECODE
, PKCS7_R_NO_RECIPIENT_MATCHES_KEY
);
6557 jj
= pkinit_decode_data(context
, id_cryptoctx
,
6558 M_ASN1_STRING_data(ri
->enc_key
),
6559 (unsigned int) M_ASN1_STRING_length(ri
->enc_key
),
6561 /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */
6562 if (jj
|| tmp_len
== 0) {
6563 PKCS7err(PKCS7_F_PKCS7_DATADECODE
, ERR_R_EVP_LIB
);
6570 BIO_get_cipher_ctx(etmp
,&evp_ctx
);
6571 if (EVP_CipherInit_ex(evp_ctx
,evp_cipher
,NULL
,NULL
,NULL
,0) <= 0)
6573 if (EVP_CIPHER_asn1_to_param(evp_ctx
,enc_alg
->parameter
) < 0)
6576 if (jj
!= EVP_CIPHER_CTX_key_length(evp_ctx
)) {
6577 /* Some S/MIME clients don't use the same key
6578 * and effective key length. The key length is
6579 * determined by the size of the decrypted RSA key.
6581 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx
, (int)jj
)) {
6582 PKCS7err(PKCS7_F_PKCS7_DATADECODE
,
6583 PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH
);
6587 if (EVP_CipherInit_ex(evp_ctx
,NULL
,NULL
,tmp
,NULL
,0) <= 0)
6590 OPENSSL_cleanse(tmp
,jj
);
6598 if (data_body
->length
> 0)
6599 bio
= BIO_new_mem_buf(data_body
->data
, data_body
->length
);
6601 bio
=BIO_new(BIO_s_mem());
6602 BIO_set_mem_eof_return(bio
,0);
6607 /* Solaris Kerberos */
6611 if (out
!= NULL
) BIO_free_all(out
);
6612 if (etmp
!= NULL
) BIO_free_all(etmp
);
6613 if (bio
!= NULL
) BIO_free_all(bio
);
6623 static krb5_error_code
6624 der_decode_data(unsigned char *data
, long data_len
,
6625 unsigned char **out
, long *out_len
)
6627 /* Solaris Kerberos */
6628 krb5_error_code retval
= KRB5KRB_ERR_GENERIC
;
6629 ASN1_OCTET_STRING
*s
= NULL
;
6630 const unsigned char *p
= data
;
6632 if ((s
= d2i_ASN1_BIT_STRING(NULL
, &p
, data_len
)) == NULL
)
6634 *out_len
= s
->length
;
6635 if ((*out
= (unsigned char *) malloc((size_t) *out_len
+ 1)) == NULL
) {
6639 (void) memcpy(*out
, s
->data
, (size_t) s
->length
);
6640 (*out
)[s
->length
] = '\0';
6645 ASN1_OCTET_STRING_free(s
);
6653 print_dh(DH
* dh
, char *msg
)
6655 BIO
*bio_err
= NULL
;
6657 bio_err
= BIO_new(BIO_s_file());
6658 BIO_set_fp(bio_err
, stderr
, BIO_NOCLOSE
| BIO_FP_TEXT
);
6661 BIO_puts(bio_err
, (const char *)msg
);
6663 DHparams_print(bio_err
, dh
);
6665 BN_print(bio_err
, dh
->q
);
6666 BIO_puts(bio_err
, (const char *)"\n");
6672 print_pubkey(BIGNUM
* key
, char *msg
)
6674 BIO
*bio_err
= NULL
;
6676 bio_err
= BIO_new(BIO_s_file());
6677 BIO_set_fp(bio_err
, stderr
, BIO_NOCLOSE
| BIO_FP_TEXT
);
6680 BIO_puts(bio_err
, (const char *)msg
);
6682 BN_print(bio_err
, key
);
6683 BIO_puts(bio_err
, "\n");
6692 * Error message generation has changed so gettext() can be used
6696 pkinit_pkcs11_code_to_text(int err
)
6701 for (i
= 0; pkcs11_errstrings
[i
].text
!= NULL
; i
++)
6702 if (pkcs11_errstrings
[i
].code
== err
)
6704 if (pkcs11_errstrings
[i
].text
!= NULL
)
6705 return (pkcs11_errstrings
[i
].text
);
6706 snprintf(uc
, 64, gettext("unknown code 0x%x"), err
);
6712 pkinit_pkcs11_code_to_text(int err
) {
6713 return pkcs11_error_table(err
);