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