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