1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * COPYRIGHT (C) 2006,2007
4 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
5 * ALL RIGHTS RESERVED
6 *
7 * Permission is granted to use, copy, create derivative works
8 * and redistribute this software and such derivative works
9 * for any purpose, so long as the name of The University of
10 * Michigan is not used in any advertising or publicity
11 * pertaining to the use of distribution of this software
12 * without specific, written prior authorization. If the
13 * above copyright notice or any other identification of the
14 * University of Michigan is included in any copy of any
15 * portion of this software, then the disclaimer below must
16 * also be included.
17 *
18 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
19 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
20 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
21 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
22 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
24 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
25 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
26 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
27 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
28 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGES.
30 */
31
32 #include "k5-int.h"
33 #include "pkinit_crypto_openssl.h"
34 #include "k5-buf.h"
35 #include "k5-err.h"
36 #include "k5-hex.h"
37 #include <unistd.h>
38 #include <dirent.h>
39 #include <arpa/inet.h>
40
41 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
42 #include <openssl/core_names.h>
43 #include <openssl/kdf.h>
44 #include <openssl/params.h>
45 #endif
46
47 static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
48 static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
49
50 static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
51 static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
52
53 static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
54 static void pkinit_fini_certs(pkinit_identity_crypto_context ctx);
55
56 static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx);
57 static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
58
59 static krb5_error_code pkinit_sign_data
60 (krb5_context context, pkinit_identity_crypto_context cryptoctx,
61 unsigned char *data, unsigned int data_len,
62 unsigned char **sig, unsigned int *sig_len);
63
64 static krb5_error_code create_signature
65 (unsigned char **, unsigned int *, unsigned char *, unsigned int,
66 EVP_PKEY *pkey);
67
68 static krb5_error_code pkinit_decode_data
69 (krb5_context context, pkinit_identity_crypto_context cryptoctx,
70 const uint8_t *data, unsigned int data_len, uint8_t **decoded,
71 unsigned int *decoded_len);
72
73 #ifdef DEBUG_DH
74 static void print_dh(DH *, char *);
75 static void print_pubkey(BIGNUM *, char *);
76 #endif
77
78 static int prepare_enc_data
79 (const uint8_t *indata, int indata_len, uint8_t **outdata, int *outdata_len);
80
81 static int openssl_callback (int, X509_STORE_CTX *);
82 static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
83
84 static int pkcs7_decrypt
85 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx, PKCS7 *p7,
86 unsigned char **data_out, unsigned int *len_out);
87
88 static ASN1_OBJECT * pkinit_pkcs7type2oid
89 (pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type);
90
91 static krb5_error_code pkinit_create_sequence_of_principal_identifiers
92 (krb5_context context, pkinit_plg_crypto_context plg_cryptoctx,
93 pkinit_req_crypto_context req_cryptoctx,
94 pkinit_identity_crypto_context id_cryptoctx,
95 int type, krb5_pa_data ***e_data_out);
96
97 #ifndef WITHOUT_PKCS11
98 static krb5_error_code pkinit_find_private_key
99 (pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage,
100 CK_OBJECT_HANDLE *objp);
101 static krb5_error_code pkinit_login
102 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
103 CK_TOKEN_INFO *tip, const char *password);
104 static krb5_error_code pkinit_open_session
105 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx);
106 #ifdef SILLYDECRYPT
107 CK_RV pkinit_C_Decrypt
108 (pkinit_identity_crypto_context id_cryptoctx,
109 CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
110 CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
111 #endif
112
113 static krb5_error_code pkinit_sign_data_pkcs11
114 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
115 unsigned char *data, unsigned int data_len,
116 unsigned char **sig, unsigned int *sig_len);
117 static krb5_error_code pkinit_decode_data_pkcs11
118 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
119 const uint8_t *data, unsigned int data_len, uint8_t **decoded_data,
120 unsigned int *decoded_data_len);
121 #endif /* WITHOUT_PKCS11 */
122
123 static krb5_error_code pkinit_sign_data_fs
124 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
125 unsigned char *data, unsigned int data_len,
126 unsigned char **sig, unsigned int *sig_len);
127 static krb5_error_code pkinit_decode_data_fs
128 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
129 const uint8_t *data, unsigned int data_len, uint8_t **decoded_data,
130 unsigned int *decoded_data_len);
131
132 static krb5_error_code
133 create_krb5_invalidCertificates(krb5_context context,
134 pkinit_plg_crypto_context plg_cryptoctx,
135 pkinit_req_crypto_context req_cryptoctx,
136 pkinit_identity_crypto_context id_cryptoctx,
137 krb5_external_principal_identifier *** ids);
138
139 static krb5_error_code
140 create_identifiers_from_stack(STACK_OF(X509) *sk,
141 krb5_external_principal_identifier *** ids);
142 static int
143 wrap_signeddata(unsigned char *data, unsigned int data_len,
144 unsigned char **out, unsigned int *out_len);
145
146 static const char *
147 pkcs11err(int err);
148
149
150 #if OPENSSL_VERSION_NUMBER < 0x10100000L
151
152 /* 1.1 standardizes constructor and destructor names, renaming
153 * EVP_MD_CTX_{create,destroy} and deprecating ASN1_STRING_data. */
154
155 #define EVP_MD_CTX_new EVP_MD_CTX_create
156 #define EVP_MD_CTX_free EVP_MD_CTX_destroy
157 #define ASN1_STRING_get0_data ASN1_STRING_data
158
159 /*
160 * 1.1 adds DHX support, which uses the RFC 3279 DomainParameters encoding we
161 * need for PKINIT. For 1.0 we must use the original DH type when creating
162 * EVP_PKEY objects.
163 */
164 #define EVP_PKEY_DHX EVP_PKEY_DH
165
166 /* 1.1 makes many handle types opaque and adds accessors. Add compatibility
167 * versions of the new accessors we use for pre-1.1. */
168
169 #define OBJ_get0_data(o) ((o)->data)
170 #define OBJ_length(o) ((o)->length)
171
172 #define DH_set0_key compat_dh_set0_key
173 static int
compat_dh_set0_key(DH * dh,BIGNUM * pub,BIGNUM * priv)174 compat_dh_set0_key(DH *dh, BIGNUM *pub, BIGNUM *priv)
175 {
176 if (pub != NULL) {
177 BN_clear_free(dh->pub_key);
178 dh->pub_key = pub;
179 }
180 if (priv != NULL) {
181 BN_clear_free(dh->priv_key);
182 dh->priv_key = priv;
183 }
184 return 1;
185 }
186
187 #define DH_get0_key compat_dh_get0_key
compat_dh_get0_key(const DH * dh,const BIGNUM ** pub,const BIGNUM ** priv)188 static void compat_dh_get0_key(const DH *dh, const BIGNUM **pub,
189 const BIGNUM **priv)
190 {
191 if (pub != NULL)
192 *pub = dh->pub_key;
193 if (priv != NULL)
194 *priv = dh->priv_key;
195 }
196
197 #define EVP_PKEY_get0_DH compat_get0_DH
198 static DH *
compat_get0_DH(const EVP_PKEY * pkey)199 compat_get0_DH(const EVP_PKEY *pkey)
200 {
201 if (pkey->type != EVP_PKEY_DH)
202 return NULL;
203 return pkey->pkey.dh;
204
205 }
206
207 /* Return true if the cert c includes a key usage which doesn't include u.
208 * Define using direct member access for pre-1.1. */
209 #define ku_reject(c, u) \
210 (((c)->ex_flags & EXFLAG_KUSAGE) && !((c)->ex_kusage & (u)))
211
212 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
213
214 /* Return true if the cert x includes a key usage which doesn't include u. */
215 #define ku_reject(c, u) (!(X509_get_key_usage(c) & (u)))
216
217 #endif
218
219 #if OPENSSL_VERSION_NUMBER < 0x30000000L
220 /* OpenSSL 3.0 changes several preferred function names. */
221 #define EVP_PKEY_parameters_eq EVP_PKEY_cmp_parameters
222 #define EVP_MD_CTX_get0_md EVP_MD_CTX_md
223 #define EVP_PKEY_get_size EVP_PKEY_size
224 #define EVP_PKEY_get_bits EVP_PKEY_bits
225
226 /*
227 * Convert *dh to an EVP_PKEY object, taking ownership of *dh and setting it to
228 * NULL. On error, return NULL and do not take ownership of or change *dh.
229 * OpenSSL 3.0 deprecates the low-level DH interfaces, so this helper will only
230 * be used with prior versions.
231 */
232 static EVP_PKEY *
dh_to_pkey(DH ** dh)233 dh_to_pkey(DH **dh)
234 {
235 EVP_PKEY *pkey;
236
237 pkey = EVP_PKEY_new();
238 if (pkey == NULL)
239 return NULL;
240 if (!EVP_PKEY_assign(pkey, EVP_PKEY_DHX, *dh)) {
241 EVP_PKEY_free(pkey);
242 return NULL;
243 }
244 *dh = NULL;
245 return pkey;
246 }
247 #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
248
249 /* Encode a bignum as an ASN.1 integer in DER. */
250 static int
encode_bn_der(const BIGNUM * bn,uint8_t ** der_out,int * len_out)251 encode_bn_der(const BIGNUM *bn, uint8_t **der_out, int *len_out)
252 {
253 ASN1_INTEGER *intval;
254 int len;
255 uint8_t *der = NULL, *outptr;
256
257 intval = BN_to_ASN1_INTEGER(bn, NULL);
258 if (intval == NULL)
259 return 0;
260 len = i2d_ASN1_INTEGER(intval, NULL);
261 if (len > 0 && (outptr = der = malloc(len)) != NULL)
262 (void)i2d_ASN1_INTEGER(intval, &outptr);
263 ASN1_INTEGER_free(intval);
264 if (der == NULL)
265 return 0;
266 *der_out = der;
267 *len_out = len;
268 return 1;
269 }
270
271 /* Decode an ASN.1 integer, returning a bignum. */
272 static BIGNUM *
decode_bn_der(const uint8_t * der,size_t len)273 decode_bn_der(const uint8_t *der, size_t len)
274 {
275 ASN1_INTEGER *intval;
276 BIGNUM *bn;
277
278 intval = d2i_ASN1_INTEGER(NULL, &der, len);
279 if (intval == NULL)
280 return NULL;
281 bn = ASN1_INTEGER_to_BN(intval, NULL);
282 ASN1_INTEGER_free(intval);
283 return bn;
284 }
285
286 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
287 static int
params_valid(EVP_PKEY * params)288 params_valid(EVP_PKEY *params)
289 {
290 EVP_PKEY_CTX *ctx;
291 int result;
292
293 ctx = EVP_PKEY_CTX_new(params, NULL);
294 if (ctx == NULL)
295 return 0;
296 result = EVP_PKEY_param_check(ctx);
297 EVP_PKEY_CTX_free(ctx);
298 return result == 1;
299 }
300 #else
301 static int
params_valid(EVP_PKEY * params)302 params_valid(EVP_PKEY *params)
303 {
304 DH *dh;
305 int codes;
306
307 dh = EVP_PKEY_get0_DH(params);
308 return (dh == NULL) ? 0 : (DH_check(dh, &codes) && codes == 0);
309 }
310 #endif
311
312 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
313
314 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
315 static EVP_PKEY *
decode_dh_params(const krb5_data * params_der)316 decode_dh_params(const krb5_data *params_der)
317 {
318 EVP_PKEY *pkey = NULL;
319 const uint8_t *inptr = (uint8_t *)params_der->data;
320 size_t len = params_der->length;
321 OSSL_DECODER_CTX *dctx;
322 int ok;
323
324 dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "type-specific", "DHX",
325 EVP_PKEY_KEY_PARAMETERS, NULL, NULL);
326 if (dctx == NULL)
327 return NULL;
328
329 ok = OSSL_DECODER_from_data(dctx, &inptr, &len);
330 OSSL_DECODER_CTX_free(dctx);
331 return ok ? pkey : NULL;
332 }
333 #else
334 static EVP_PKEY *
decode_dh_params(const krb5_data * params_der)335 decode_dh_params(const krb5_data *params_der)
336 {
337 const uint8_t *p = (uint8_t *)params_der->data;
338 DH *dh;
339 EVP_PKEY *pkey;
340
341 dh = d2i_DHxparams(NULL, &p, params_der->length);
342 pkey = dh_to_pkey(&dh);
343 DH_free(dh);
344 return pkey;
345 }
346 #endif
347
348 static krb5_error_code
encode_spki(EVP_PKEY * pkey,krb5_data * spki_out)349 encode_spki(EVP_PKEY *pkey, krb5_data *spki_out)
350 {
351 krb5_error_code ret = ENOMEM;
352 int len;
353 uint8_t *outptr;
354
355 len = i2d_PUBKEY(pkey, NULL);
356 ret = alloc_data(spki_out, len);
357 if (ret)
358 goto cleanup;
359 outptr = (uint8_t *)spki_out->data;
360 (void)i2d_PUBKEY(pkey, &outptr);
361
362 cleanup:
363 return ret;
364 }
365
366 static EVP_PKEY *
decode_spki(const krb5_data * spki)367 decode_spki(const krb5_data *spki)
368 {
369 const uint8_t *inptr = (uint8_t *)spki->data;
370
371 return d2i_PUBKEY(NULL, &inptr, spki->length);
372 }
373
374 #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
375
376 /*
377 * OpenSSL 1.0 has no DHX support, so we need a custom decoder for RFC 3279
378 * DomainParameters, and we need to use X509_PUBKEY values to marshal
379 * SubjectPublicKeyInfo.
380 */
381
382 typedef struct {
383 ASN1_BIT_STRING *seed;
384 BIGNUM *counter;
385 } int_dhvparams;
386
387 typedef struct {
388 BIGNUM *p;
389 BIGNUM *q;
390 BIGNUM *g;
391 BIGNUM *j;
392 int_dhvparams *vparams;
393 } int_dhxparams;
394
395 ASN1_SEQUENCE(int_dhvparams) = {
396 ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING),
397 ASN1_SIMPLE(int_dhvparams, counter, BIGNUM)
398 } ASN1_SEQUENCE_END(int_dhvparams);
399
400 ASN1_SEQUENCE(int_dhxparams) = {
401 ASN1_SIMPLE(int_dhxparams, p, BIGNUM),
402 ASN1_SIMPLE(int_dhxparams, g, BIGNUM),
403 ASN1_SIMPLE(int_dhxparams, q, BIGNUM),
404 ASN1_OPT(int_dhxparams, j, BIGNUM),
405 ASN1_OPT(int_dhxparams, vparams, int_dhvparams)
406 } ASN1_SEQUENCE_END(int_dhxparams);
407
408 static EVP_PKEY *
decode_dh_params(const krb5_data * params_der)409 decode_dh_params(const krb5_data *params_der)
410 {
411 int_dhxparams *params;
412 DH *dh;
413 EVP_PKEY *pkey;
414 const uint8_t *p;
415
416 dh = DH_new();
417 if (dh == NULL)
418 return NULL;
419
420 p = (uint8_t *)params_der->data;
421 params = (int_dhxparams *)ASN1_item_d2i(NULL, &p, params_der->length,
422 ASN1_ITEM_rptr(int_dhxparams));
423 if (params == NULL) {
424 DH_free(dh);
425 return NULL;
426 }
427
428 /* Steal p, q, and g from dhparams for dh. Ignore j and vparams. */
429 dh->p = params->p;
430 dh->q = params->q;
431 dh->g = params->g;
432 params->p = params->q = params->g = NULL;
433 ASN1_item_free((ASN1_VALUE *)params, ASN1_ITEM_rptr(int_dhxparams));
434 pkey = dh_to_pkey(&dh);
435 DH_free(dh);
436 return pkey;
437 }
438
439 static krb5_error_code
encode_spki(EVP_PKEY * pkey,krb5_data * spki_out)440 encode_spki(EVP_PKEY *pkey, krb5_data *spki_out)
441 {
442 krb5_error_code ret = ENOMEM;
443 const DH *dh;
444 uint8_t *param_der = NULL, *pubkey_der = NULL, *outptr;
445 int param_der_len, pubkey_der_len, len;
446 X509_PUBKEY pubkey;
447 int_dhxparams dhxparams;
448 X509_ALGOR algor;
449 ASN1_OBJECT algorithm;
450 ASN1_TYPE parameter;
451 ASN1_STRING param_str, pubkey_str;
452
453 dh = EVP_PKEY_get0_DH(pkey);
454 if (dh == NULL)
455 goto cleanup;
456
457 dhxparams.p = dh->p;
458 dhxparams.q = dh->q;
459 dhxparams.g = dh->g;
460 dhxparams.j = NULL;
461 dhxparams.vparams = NULL;
462 param_der_len = ASN1_item_i2d((ASN1_VALUE *)&dhxparams, ¶m_der,
463 ASN1_ITEM_rptr(int_dhxparams));
464 if (param_der_len < 0)
465 goto cleanup;
466 param_str.length = param_der_len;
467 param_str.type = V_ASN1_SEQUENCE;
468 param_str.data = param_der;
469 param_str.flags = 0;
470 parameter.type = V_ASN1_SEQUENCE;
471 parameter.value.sequence = ¶m_str;
472
473 memset(&algorithm, 0, sizeof(algorithm));
474 algorithm.data = (uint8_t *)dh_oid.data;
475 algorithm.length = dh_oid.length;
476
477 algor.algorithm = &algorithm;
478 algor.parameter = ¶meter;
479
480 if (!encode_bn_der(dh->pub_key, &pubkey_der, &pubkey_der_len))
481 goto cleanup;
482 pubkey_str.length = pubkey_der_len;
483 pubkey_str.type = V_ASN1_BIT_STRING;
484 pubkey_str.data = pubkey_der;
485 pubkey_str.flags = ASN1_STRING_FLAG_BITS_LEFT;
486
487 pubkey.algor = &algor;
488 pubkey.public_key = &pubkey_str;
489 len = i2d_X509_PUBKEY(&pubkey, NULL);
490 if (len < 0)
491 goto cleanup;
492 ret = alloc_data(spki_out, len);
493 if (ret)
494 goto cleanup;
495 outptr = (uint8_t *)spki_out->data;
496 i2d_X509_PUBKEY(&pubkey, &outptr);
497
498 cleanup:
499 OPENSSL_free(param_der);
500 free(pubkey_der);
501 return ret;
502 }
503
504 static EVP_PKEY *
decode_spki(const krb5_data * spki)505 decode_spki(const krb5_data *spki)
506 {
507 X509_PUBKEY *pubkey = NULL;
508 const uint8_t *inptr;
509 DH *dh;
510 EVP_PKEY *pkey = NULL, *pkey_ret = NULL;
511 const ASN1_STRING *params;
512 const ASN1_BIT_STRING *public_key;
513 krb5_data d;
514
515 inptr = (uint8_t *)spki->data;
516 pubkey = d2i_X509_PUBKEY(NULL, &inptr, spki->length);
517 if (pubkey == NULL)
518 goto cleanup;
519
520 if (pubkey->algor->parameter->type != V_ASN1_SEQUENCE)
521 goto cleanup;
522 params = pubkey->algor->parameter->value.sequence;
523 d = make_data(params->data, params->length);
524 pkey = decode_dh_params(&d);
525 if (pkey == NULL)
526 goto cleanup;
527 dh = EVP_PKEY_get0_DH(pkey);
528 if (dh == NULL)
529 goto cleanup;
530 public_key = pubkey->public_key;
531 dh->pub_key = decode_bn_der(public_key->data, public_key->length);
532 if (dh->pub_key == NULL)
533 goto cleanup;
534
535 pkey_ret = pkey;
536 pkey = NULL;
537
538 cleanup:
539 X509_PUBKEY_free(pubkey);
540 EVP_PKEY_free(pkey);
541 return pkey_ret;
542 }
543
544 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
545
546 /* Attempt to specify padded Diffie-Hellman result derivation. Don't error out
547 * if this fails since we also detect short results and adjust them. */
548 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
549 static void
set_padded_derivation(EVP_PKEY_CTX * ctx)550 set_padded_derivation(EVP_PKEY_CTX *ctx)
551 {
552 EVP_PKEY_CTX_set_dh_pad(ctx, 1);
553 }
554 #elif OPENSSL_VERSION_NUMBER >= 0x10100000L
555 static void
set_padded_derivation(EVP_PKEY_CTX * ctx)556 set_padded_derivation(EVP_PKEY_CTX *ctx)
557 {
558 /* We would use EVP_PKEY_CTX_set_dh_pad() but it doesn't work with DHX. */
559 EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
560 EVP_PKEY_CTRL_DH_PAD, 1, NULL);
561 }
562 #else
563 static void
set_padded_derivation(EVP_PKEY_CTX * ctx)564 set_padded_derivation(EVP_PKEY_CTX *ctx)
565 {
566 /* There's no support for padded derivation in 1.0. */
567 }
568 #endif
569
570 static int
dh_result(EVP_PKEY * pkey,EVP_PKEY * peer,uint8_t ** result_out,unsigned int * len_out)571 dh_result(EVP_PKEY *pkey, EVP_PKEY *peer,
572 uint8_t **result_out, unsigned int *len_out)
573 {
574 EVP_PKEY_CTX *derive_ctx = NULL;
575 int ok = 0;
576 uint8_t *buf = NULL;
577 size_t len, dh_size = EVP_PKEY_get_size(pkey);
578
579 *result_out = NULL;
580 *len_out = 0;
581
582 derive_ctx = EVP_PKEY_CTX_new(pkey, NULL);
583 if (derive_ctx == NULL)
584 goto cleanup;
585 if (EVP_PKEY_derive_init(derive_ctx) <= 0)
586 goto cleanup;
587 set_padded_derivation(derive_ctx);
588 if (EVP_PKEY_derive_set_peer(derive_ctx, peer) <= 0)
589 goto cleanup;
590
591 buf = malloc(dh_size);
592 if (buf == NULL)
593 goto cleanup;
594 len = dh_size;
595 if (EVP_PKEY_derive(derive_ctx, buf, &len) <= 0)
596 goto cleanup;
597 if (len < dh_size) { /* only possible without padded derivation */
598 memmove(buf + (dh_size - len), buf, len);
599 memset(buf, 0, dh_size - len);
600 }
601
602 ok = 1;
603 *result_out = buf;
604 *len_out = dh_size;
605 buf = NULL;
606
607 cleanup:
608 EVP_PKEY_CTX_free(derive_ctx);
609 free(buf);
610 return ok;
611 }
612
613 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
614 static int
dh_pubkey_der(EVP_PKEY * pkey,uint8_t ** pubkey_out,unsigned int * len_out)615 dh_pubkey_der(EVP_PKEY *pkey, uint8_t **pubkey_out, unsigned int *len_out)
616 {
617 BIGNUM *pubkey_bn = NULL;
618 int len, ok;
619 uint8_t *buf;
620
621 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &pubkey_bn))
622 return 0;
623 ok = encode_bn_der(pubkey_bn, &buf, &len);
624 BN_free(pubkey_bn);
625 if (ok) {
626 *pubkey_out = buf;
627 *len_out = len;
628 }
629 return ok;
630 }
631 #else
632 static int
dh_pubkey_der(EVP_PKEY * pkey,uint8_t ** pubkey_out,unsigned int * len_out)633 dh_pubkey_der(EVP_PKEY *pkey, uint8_t **pubkey_out, unsigned int *len_out)
634 {
635 const DH *dh;
636 const BIGNUM *pubkey_bn;
637 uint8_t *buf;
638 int len;
639
640 dh = EVP_PKEY_get0_DH(pkey);
641 if (dh == NULL)
642 return 0;
643 DH_get0_key(dh, &pubkey_bn, NULL);
644 if (!encode_bn_der(pubkey_bn, &buf, &len))
645 return 0;
646 *pubkey_out = buf;
647 *len_out = len;
648 return 1;
649 }
650 #endif
651
652 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
653 /* OpenSSL 1.1 and later will copy the q parameter when generating keys. */
654 static int
copy_q_openssl10(EVP_PKEY * src,EVP_PKEY * dest)655 copy_q_openssl10(EVP_PKEY *src, EVP_PKEY *dest)
656 {
657 return 1;
658 }
659 #else
660 /* OpenSSL 1.0 won't copy the q parameter, so we have to do it. */
661 static int
copy_q_openssl10(EVP_PKEY * src,EVP_PKEY * dest)662 copy_q_openssl10(EVP_PKEY *src, EVP_PKEY *dest)
663 {
664 DH *dhsrc = EVP_PKEY_get0_DH(src), *dhdest = EVP_PKEY_get0_DH(dest);
665
666 if (dhsrc == NULL || dhsrc->q == NULL || dhdest == NULL)
667 return 0;
668 if (dhdest->q != NULL)
669 return 1;
670 dhdest->q = BN_dup(dhsrc->q);
671 return dhdest->q != NULL;
672 }
673 #endif
674
675 static EVP_PKEY *
generate_dh_pkey(EVP_PKEY * params)676 generate_dh_pkey(EVP_PKEY *params)
677 {
678 EVP_PKEY_CTX *ctx = NULL;
679 EVP_PKEY *pkey = NULL;
680
681 ctx = EVP_PKEY_CTX_new(params, NULL);
682 if (ctx == NULL)
683 goto cleanup;
684 if (EVP_PKEY_keygen_init(ctx) <= 0)
685 goto cleanup;
686 if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
687 goto cleanup;
688 if (!copy_q_openssl10(params, pkey)) {
689 EVP_PKEY_free(pkey);
690 pkey = NULL;
691 }
692
693 cleanup:
694 EVP_PKEY_CTX_free(ctx);
695 return pkey;
696 }
697
698 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
699
700 static EVP_PKEY *
compose_dh_pkey(EVP_PKEY * params,const uint8_t * pubkey_der,size_t der_len)701 compose_dh_pkey(EVP_PKEY *params, const uint8_t *pubkey_der, size_t der_len)
702 {
703 EVP_PKEY *pkey = NULL, *pkey_ret = NULL;
704 BIGNUM *pubkey_bn = NULL;
705 uint8_t *pubkey_bin = NULL;
706 int binlen;
707
708 pkey = EVP_PKEY_dup(params);
709 if (pkey == NULL)
710 goto cleanup;
711
712 pubkey_bn = decode_bn_der(pubkey_der, der_len);
713 if (pubkey_bn == NULL)
714 goto cleanup;
715 binlen = EVP_PKEY_get_size(pkey);
716 pubkey_bin = malloc(binlen);
717 if (pubkey_bin == NULL)
718 goto cleanup;
719 if (BN_bn2binpad(pubkey_bn, pubkey_bin, binlen) != binlen)
720 goto cleanup;
721 if (EVP_PKEY_set1_encoded_public_key(pkey, pubkey_bin, binlen) != 1)
722 goto cleanup;
723
724 pkey_ret = pkey;
725 pkey = NULL;
726
727 cleanup:
728 EVP_PKEY_free(pkey);
729 BN_free(pubkey_bn);
730 free(pubkey_bin);
731 return pkey_ret;
732 }
733
734 #else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
735
736 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
737 static DH *
dup_dh_params(DH * src)738 dup_dh_params(DH *src)
739 {
740 return DHparams_dup(src);
741 }
742 #else
743 /* DHparams_dup() won't copy q in OpenSSL 1.0. */
744 static DH *
dup_dh_params(DH * src)745 dup_dh_params(DH *src)
746 {
747 DH *dh;
748
749 dh = DH_new();
750 if (dh == NULL)
751 return NULL;
752 dh->p = BN_dup(src->p);
753 dh->q = BN_dup(src->q);
754 dh->g = BN_dup(src->g);
755 if (dh->p == NULL || dh->q == NULL || dh->g == NULL) {
756 DH_free(dh);
757 return NULL;
758 }
759 return dh;
760 }
761 #endif
762
763 static EVP_PKEY *
compose_dh_pkey(EVP_PKEY * params,const uint8_t * pubkey_der,size_t der_len)764 compose_dh_pkey(EVP_PKEY *params, const uint8_t *pubkey_der, size_t der_len)
765 {
766 DH *dhparams, *dh = NULL;
767 EVP_PKEY *pkey = NULL;
768 BIGNUM *pubkey_bn = NULL;
769
770 pubkey_bn = decode_bn_der(pubkey_der, der_len);
771 if (pubkey_bn == NULL)
772 goto cleanup;
773
774 dhparams = EVP_PKEY_get0_DH(params);
775 if (dhparams == NULL)
776 goto cleanup;
777 dh = dup_dh_params(dhparams);
778 if (dh == NULL)
779 goto cleanup;
780 if (!DH_set0_key(dh, pubkey_bn, NULL))
781 goto cleanup;
782 pubkey_bn = NULL;
783
784 pkey = dh_to_pkey(&dh);
785
786 cleanup:
787 BN_free(pubkey_bn);
788 DH_free(dh);
789 return pkey;
790 }
791
792 #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
793
794 static struct pkcs11_errstrings {
795 short code;
796 char *text;
797 } pkcs11_errstrings[] = {
798 { 0x0, "ok" },
799 { 0x1, "cancel" },
800 { 0x2, "host memory" },
801 { 0x3, "slot id invalid" },
802 { 0x5, "general error" },
803 { 0x6, "function failed" },
804 { 0x7, "arguments bad" },
805 { 0x8, "no event" },
806 { 0x9, "need to create threads" },
807 { 0xa, "cant lock" },
808 { 0x10, "attribute read only" },
809 { 0x11, "attribute sensitive" },
810 { 0x12, "attribute type invalid" },
811 { 0x13, "attribute value invalid" },
812 { 0x20, "data invalid" },
813 { 0x21, "data len range" },
814 { 0x30, "device error" },
815 { 0x31, "device memory" },
816 { 0x32, "device removed" },
817 { 0x40, "encrypted data invalid" },
818 { 0x41, "encrypted data len range" },
819 { 0x50, "function canceled" },
820 { 0x51, "function not parallel" },
821 { 0x54, "function not supported" },
822 { 0x60, "key handle invalid" },
823 { 0x62, "key size range" },
824 { 0x63, "key type inconsistent" },
825 { 0x64, "key not needed" },
826 { 0x65, "key changed" },
827 { 0x66, "key needed" },
828 { 0x67, "key indigestible" },
829 { 0x68, "key function not permitted" },
830 { 0x69, "key not wrappable" },
831 { 0x6a, "key unextractable" },
832 { 0x70, "mechanism invalid" },
833 { 0x71, "mechanism param invalid" },
834 { 0x82, "object handle invalid" },
835 { 0x90, "operation active" },
836 { 0x91, "operation not initialized" },
837 { 0xa0, "pin incorrect" },
838 { 0xa1, "pin invalid" },
839 { 0xa2, "pin len range" },
840 { 0xa3, "pin expired" },
841 { 0xa4, "pin locked" },
842 { 0xb0, "session closed" },
843 { 0xb1, "session count" },
844 { 0xb3, "session handle invalid" },
845 { 0xb4, "session parallel not supported" },
846 { 0xb5, "session read only" },
847 { 0xb6, "session exists" },
848 { 0xb7, "session read only exists" },
849 { 0xb8, "session read write so exists" },
850 { 0xc0, "signature invalid" },
851 { 0xc1, "signature len range" },
852 { 0xd0, "template incomplete" },
853 { 0xd1, "template inconsistent" },
854 { 0xe0, "token not present" },
855 { 0xe1, "token not recognized" },
856 { 0xe2, "token write protected" },
857 { 0xf0, "unwrapping key handle invalid" },
858 { 0xf1, "unwrapping key size range" },
859 { 0xf2, "unwrapping key type inconsistent" },
860 { 0x100, "user already logged in" },
861 { 0x101, "user not logged in" },
862 { 0x102, "user pin not initialized" },
863 { 0x103, "user type invalid" },
864 { 0x104, "user another already logged in" },
865 { 0x105, "user too many types" },
866 { 0x110, "wrapped key invalid" },
867 { 0x112, "wrapped key len range" },
868 { 0x113, "wrapping key handle invalid" },
869 { 0x114, "wrapping key size range" },
870 { 0x115, "wrapping key type inconsistent" },
871 { 0x120, "random seed not supported" },
872 { 0x121, "random no rng" },
873 { 0x130, "domain params invalid" },
874 { 0x150, "buffer too small" },
875 { 0x160, "saved state invalid" },
876 { 0x170, "information sensitive" },
877 { 0x180, "state unsaveable" },
878 { 0x190, "cryptoki not initialized" },
879 { 0x191, "cryptoki already initialized" },
880 { 0x1a0, "mutex bad" },
881 { 0x1a1, "mutex not locked" },
882 { 0x200, "function rejected" },
883 { -1, NULL }
884 };
885
886 MAKE_INIT_FUNCTION(pkinit_openssl_init);
887
888 static krb5_error_code oerr(krb5_context context, krb5_error_code code,
889 const char *fmt, ...)
890 #if !defined(__cplusplus) && (__GNUC__ > 2)
891 __attribute__((__format__(__printf__, 3, 4)))
892 #endif
893 ;
894
895 /*
896 * Set an error string containing the formatted arguments and the first pending
897 * OpenSSL error. Write the formatted arguments and all pending OpenSSL error
898 * messages to the trace log. Return code, or KRB5KDC_ERR_PREAUTH_FAILED if
899 * code is 0.
900 */
901 static krb5_error_code
oerr(krb5_context context,krb5_error_code code,const char * fmt,...)902 oerr(krb5_context context, krb5_error_code code, const char *fmt, ...)
903 {
904 unsigned long err;
905 va_list ap;
906 char *str, buf[128];
907 int r;
908
909 if (!code)
910 code = KRB5KDC_ERR_PREAUTH_FAILED;
911
912 va_start(ap, fmt);
913 r = vasprintf(&str, fmt, ap);
914 va_end(ap);
915 if (r < 0)
916 return code;
917
918 err = ERR_peek_error();
919 if (err) {
920 krb5_set_error_message(context, code, _("%s: %s"), str,
921 ERR_reason_error_string(err));
922 } else {
923 krb5_set_error_message(context, code, "%s", str);
924 }
925
926 TRACE_PKINIT_OPENSSL_ERROR(context, str);
927 while ((err = ERR_get_error()) != 0) {
928 ERR_error_string_n(err, buf, sizeof(buf));
929 TRACE_PKINIT_OPENSSL_ERROR(context, buf);
930 }
931
932 free(str);
933 return code;
934 }
935
936 /*
937 * Set an appropriate error string containing msg for a certificate
938 * verification failure from certctx. Write the message and all pending
939 * OpenSSL error messages to the trace log. Return code, or
940 * KRB5KDC_ERR_PREAUTH_FAILED if code is 0.
941 */
942 static krb5_error_code
oerr_cert(krb5_context context,krb5_error_code code,X509_STORE_CTX * certctx,const char * msg)943 oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx,
944 const char *msg)
945 {
946 int depth = X509_STORE_CTX_get_error_depth(certctx);
947 int err = X509_STORE_CTX_get_error(certctx);
948 const char *errstr = X509_verify_cert_error_string(err);
949
950 return oerr(context, code, _("%s (depth %d): %s"), msg, depth, errstr);
951 }
952
953 krb5_error_code
pkinit_init_plg_crypto(pkinit_plg_crypto_context * cryptoctx)954 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
955 {
956 krb5_error_code retval = ENOMEM;
957 pkinit_plg_crypto_context ctx = NULL;
958
959 (void)CALL_INIT_FUNCTION(pkinit_openssl_init);
960
961 ctx = malloc(sizeof(*ctx));
962 if (ctx == NULL)
963 goto out;
964 memset(ctx, 0, sizeof(*ctx));
965
966 pkiDebug("%s: initializing openssl crypto context at %p\n",
967 __FUNCTION__, ctx);
968 retval = pkinit_init_pkinit_oids(ctx);
969 if (retval)
970 goto out;
971
972 retval = pkinit_init_dh_params(ctx);
973 if (retval)
974 goto out;
975
976 *cryptoctx = ctx;
977
978 out:
979 if (retval && ctx != NULL)
980 pkinit_fini_plg_crypto(ctx);
981
982 return retval;
983 }
984
985 void
pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)986 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
987 {
988 pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
989
990 if (cryptoctx == NULL)
991 return;
992 pkinit_fini_pkinit_oids(cryptoctx);
993 pkinit_fini_dh_params(cryptoctx);
994 free(cryptoctx);
995 }
996
997 krb5_error_code
pkinit_init_identity_crypto(pkinit_identity_crypto_context * idctx)998 pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
999 {
1000 krb5_error_code retval = ENOMEM;
1001 pkinit_identity_crypto_context ctx = NULL;
1002
1003 ctx = malloc(sizeof(*ctx));
1004 if (ctx == NULL)
1005 goto out;
1006 memset(ctx, 0, sizeof(*ctx));
1007
1008 ctx->identity = NULL;
1009
1010 retval = pkinit_init_certs(ctx);
1011 if (retval)
1012 goto out;
1013
1014 retval = pkinit_init_pkcs11(ctx);
1015 if (retval)
1016 goto out;
1017
1018 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
1019 *idctx = ctx;
1020
1021 out:
1022 if (retval) {
1023 if (ctx)
1024 pkinit_fini_identity_crypto(ctx);
1025 }
1026
1027 return retval;
1028 }
1029
1030 void
pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)1031 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
1032 {
1033 if (idctx == NULL)
1034 return;
1035
1036 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx);
1037 if (idctx->deferred_ids != NULL)
1038 pkinit_free_deferred_ids(idctx->deferred_ids);
1039 free(idctx->identity);
1040 pkinit_fini_certs(idctx);
1041 pkinit_fini_pkcs11(idctx);
1042 free(idctx);
1043 }
1044
1045 krb5_error_code
pkinit_init_req_crypto(pkinit_req_crypto_context * cryptoctx)1046 pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
1047 {
1048 krb5_error_code retval = ENOMEM;
1049 pkinit_req_crypto_context ctx = NULL;
1050
1051 ctx = malloc(sizeof(*ctx));
1052 if (ctx == NULL)
1053 goto out;
1054 memset(ctx, 0, sizeof(*ctx));
1055
1056 ctx->client_pkey = NULL;
1057 ctx->received_params = NULL;
1058 ctx->received_cert = NULL;
1059
1060 *cryptoctx = ctx;
1061
1062 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
1063 retval = 0;
1064 out:
1065 if (retval)
1066 free(ctx);
1067
1068 return retval;
1069 }
1070
1071 void
pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)1072 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
1073 {
1074 if (req_cryptoctx == NULL)
1075 return;
1076
1077 pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx);
1078 EVP_PKEY_free(req_cryptoctx->client_pkey);
1079 EVP_PKEY_free(req_cryptoctx->received_params);
1080 X509_free(req_cryptoctx->received_cert);
1081
1082 free(req_cryptoctx);
1083 }
1084
1085 static krb5_error_code
pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)1086 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
1087 {
1088 ctx->id_pkinit_san = OBJ_txt2obj("1.3.6.1.5.2.2", 1);
1089 if (ctx->id_pkinit_san == NULL)
1090 return ENOMEM;
1091
1092 ctx->id_pkinit_authData = OBJ_txt2obj("1.3.6.1.5.2.3.1", 1);
1093 if (ctx->id_pkinit_authData == NULL)
1094 return ENOMEM;
1095
1096 ctx->id_pkinit_DHKeyData = OBJ_txt2obj("1.3.6.1.5.2.3.2", 1);
1097 if (ctx->id_pkinit_DHKeyData == NULL)
1098 return ENOMEM;
1099
1100 ctx->id_pkinit_rkeyData = OBJ_txt2obj("1.3.6.1.5.2.3.3", 1);
1101 if (ctx->id_pkinit_rkeyData == NULL)
1102 return ENOMEM;
1103
1104 ctx->id_pkinit_KPClientAuth = OBJ_txt2obj("1.3.6.1.5.2.3.4", 1);
1105 if (ctx->id_pkinit_KPClientAuth == NULL)
1106 return ENOMEM;
1107
1108 ctx->id_pkinit_KPKdc = OBJ_txt2obj("1.3.6.1.5.2.3.5", 1);
1109 if (ctx->id_pkinit_KPKdc == NULL)
1110 return ENOMEM;
1111
1112 ctx->id_ms_kp_sc_logon = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.2", 1);
1113 if (ctx->id_ms_kp_sc_logon == NULL)
1114 return ENOMEM;
1115
1116 ctx->id_ms_san_upn = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1);
1117 if (ctx->id_ms_san_upn == NULL)
1118 return ENOMEM;
1119
1120 ctx->id_kp_serverAuth = OBJ_txt2obj("1.3.6.1.5.5.7.3.1", 1);
1121 if (ctx->id_kp_serverAuth == NULL)
1122 return ENOMEM;
1123
1124 return 0;
1125 }
1126
1127 static krb5_error_code
get_cert(char * filename,X509 ** retcert)1128 get_cert(char *filename, X509 **retcert)
1129 {
1130 X509 *cert = NULL;
1131 BIO *tmp = NULL;
1132 int code;
1133 krb5_error_code retval;
1134
1135 if (filename == NULL || retcert == NULL)
1136 return EINVAL;
1137
1138 *retcert = NULL;
1139
1140 tmp = BIO_new(BIO_s_file());
1141 if (tmp == NULL)
1142 return ENOMEM;
1143
1144 code = BIO_read_filename(tmp, filename);
1145 if (code == 0) {
1146 retval = errno;
1147 goto cleanup;
1148 }
1149
1150 cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
1151 if (cert == NULL) {
1152 retval = EIO;
1153 pkiDebug("failed to read certificate from %s\n", filename);
1154 goto cleanup;
1155 }
1156 *retcert = cert;
1157 retval = 0;
1158 cleanup:
1159 if (tmp != NULL)
1160 BIO_free(tmp);
1161 return retval;
1162 }
1163
1164 struct get_key_cb_data {
1165 krb5_context context;
1166 pkinit_identity_crypto_context id_cryptoctx;
1167 const char *fsname;
1168 char *filename;
1169 const char *password;
1170 };
1171
1172 static int
get_key_cb(char * buf,int size,int rwflag,void * userdata)1173 get_key_cb(char *buf, int size, int rwflag, void *userdata)
1174 {
1175 struct get_key_cb_data *data = userdata;
1176 pkinit_identity_crypto_context id_cryptoctx;
1177 krb5_data rdat;
1178 krb5_prompt kprompt;
1179 krb5_prompt_type prompt_type;
1180 krb5_error_code retval;
1181 char *prompt;
1182
1183 if (data->id_cryptoctx->defer_id_prompt) {
1184 /* Supply the identity name to be passed to a responder callback. */
1185 pkinit_set_deferred_id(&data->id_cryptoctx->deferred_ids,
1186 data->fsname, 0, NULL);
1187 return -1;
1188 }
1189 if (data->password == NULL) {
1190 /* We don't already have a password to use, so prompt for one. */
1191 if (data->id_cryptoctx->prompter == NULL)
1192 return -1;
1193 if (asprintf(&prompt, "%s %s", _("Pass phrase for"),
1194 data->filename) < 0)
1195 return -1;
1196 rdat.data = buf;
1197 rdat.length = size;
1198 kprompt.prompt = prompt;
1199 kprompt.hidden = 1;
1200 kprompt.reply = &rdat;
1201 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
1202
1203 /* PROMPTER_INVOCATION */
1204 k5int_set_prompt_types(data->context, &prompt_type);
1205 id_cryptoctx = data->id_cryptoctx;
1206 retval = (data->id_cryptoctx->prompter)(data->context,
1207 id_cryptoctx->prompter_data,
1208 NULL, NULL, 1, &kprompt);
1209 k5int_set_prompt_types(data->context, 0);
1210 free(prompt);
1211 if (retval != 0)
1212 return -1;
1213 } else {
1214 /* Just use the already-supplied password. */
1215 rdat.length = strlen(data->password);
1216 if ((int)rdat.length >= size)
1217 return -1;
1218 snprintf(buf, size, "%s", data->password);
1219 }
1220 return (int)rdat.length;
1221 }
1222
1223 static krb5_error_code
get_key(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,char * filename,const char * fsname,EVP_PKEY ** retkey,const char * password)1224 get_key(krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
1225 char *filename, const char *fsname, EVP_PKEY **retkey,
1226 const char *password)
1227 {
1228 EVP_PKEY *pkey = NULL;
1229 BIO *tmp = NULL;
1230 struct get_key_cb_data cb_data;
1231 int code;
1232 krb5_error_code retval;
1233
1234 if (filename == NULL || retkey == NULL)
1235 return EINVAL;
1236
1237 tmp = BIO_new(BIO_s_file());
1238 if (tmp == NULL)
1239 return ENOMEM;
1240
1241 code = BIO_read_filename(tmp, filename);
1242 if (code == 0) {
1243 retval = errno;
1244 goto cleanup;
1245 }
1246 cb_data.context = context;
1247 cb_data.id_cryptoctx = id_cryptoctx;
1248 cb_data.filename = filename;
1249 cb_data.fsname = fsname;
1250 cb_data.password = password;
1251 pkey = PEM_read_bio_PrivateKey(tmp, NULL, get_key_cb, &cb_data);
1252 if (pkey == NULL && !id_cryptoctx->defer_id_prompt) {
1253 retval = EIO;
1254 pkiDebug("failed to read private key from %s\n", filename);
1255 goto cleanup;
1256 }
1257 *retkey = pkey;
1258 retval = 0;
1259 cleanup:
1260 if (tmp != NULL)
1261 BIO_free(tmp);
1262 return retval;
1263 }
1264
1265 static void
pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)1266 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
1267 {
1268 if (ctx == NULL)
1269 return;
1270 ASN1_OBJECT_free(ctx->id_pkinit_san);
1271 ASN1_OBJECT_free(ctx->id_pkinit_authData);
1272 ASN1_OBJECT_free(ctx->id_pkinit_DHKeyData);
1273 ASN1_OBJECT_free(ctx->id_pkinit_rkeyData);
1274 ASN1_OBJECT_free(ctx->id_pkinit_KPClientAuth);
1275 ASN1_OBJECT_free(ctx->id_pkinit_KPKdc);
1276 ASN1_OBJECT_free(ctx->id_ms_kp_sc_logon);
1277 ASN1_OBJECT_free(ctx->id_ms_san_upn);
1278 ASN1_OBJECT_free(ctx->id_kp_serverAuth);
1279 }
1280
1281 static krb5_error_code
pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)1282 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
1283 {
1284 krb5_error_code retval = ENOMEM;
1285
1286 plgctx->dh_1024 = decode_dh_params(&oakley_1024);
1287 if (plgctx->dh_1024 == NULL)
1288 goto cleanup;
1289
1290 plgctx->dh_2048 = decode_dh_params(&oakley_2048);
1291 if (plgctx->dh_2048 == NULL)
1292 goto cleanup;
1293
1294 plgctx->dh_4096 = decode_dh_params(&oakley_4096);
1295 if (plgctx->dh_4096 == NULL)
1296 goto cleanup;
1297
1298 retval = 0;
1299
1300 cleanup:
1301 if (retval)
1302 pkinit_fini_dh_params(plgctx);
1303
1304 return retval;
1305 }
1306
1307 static void
pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)1308 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)
1309 {
1310 EVP_PKEY_free(plgctx->dh_1024);
1311 EVP_PKEY_free(plgctx->dh_2048);
1312 EVP_PKEY_free(plgctx->dh_4096);
1313 plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL;
1314 }
1315
1316 static krb5_error_code
pkinit_init_certs(pkinit_identity_crypto_context ctx)1317 pkinit_init_certs(pkinit_identity_crypto_context ctx)
1318 {
1319 krb5_error_code retval = ENOMEM;
1320 int i;
1321
1322 for (i = 0; i < MAX_CREDS_ALLOWED; i++)
1323 ctx->creds[i] = NULL;
1324 ctx->my_certs = NULL;
1325 ctx->cert_index = 0;
1326 ctx->my_key = NULL;
1327 ctx->trustedCAs = NULL;
1328 ctx->intermediateCAs = NULL;
1329 ctx->revoked = NULL;
1330
1331 retval = 0;
1332 return retval;
1333 }
1334
1335 static void
pkinit_fini_certs(pkinit_identity_crypto_context ctx)1336 pkinit_fini_certs(pkinit_identity_crypto_context ctx)
1337 {
1338 if (ctx == NULL)
1339 return;
1340
1341 if (ctx->my_certs != NULL)
1342 sk_X509_pop_free(ctx->my_certs, X509_free);
1343
1344 if (ctx->my_key != NULL)
1345 EVP_PKEY_free(ctx->my_key);
1346
1347 if (ctx->trustedCAs != NULL)
1348 sk_X509_pop_free(ctx->trustedCAs, X509_free);
1349
1350 if (ctx->intermediateCAs != NULL)
1351 sk_X509_pop_free(ctx->intermediateCAs, X509_free);
1352
1353 if (ctx->revoked != NULL)
1354 sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free);
1355 }
1356
1357 static krb5_error_code
pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)1358 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
1359 {
1360 krb5_error_code retval = ENOMEM;
1361
1362 #ifndef WITHOUT_PKCS11
1363 ctx->p11_module_name = strdup(PKCS11_MODNAME);
1364 if (ctx->p11_module_name == NULL)
1365 return retval;
1366 ctx->p11_module = NULL;
1367 ctx->slotid = PK_NOSLOT;
1368 ctx->token_label = NULL;
1369 ctx->cert_label = NULL;
1370 ctx->session = CK_INVALID_HANDLE;
1371 ctx->p11 = NULL;
1372 #endif
1373 ctx->pkcs11_method = 0;
1374
1375 retval = 0;
1376 return retval;
1377 }
1378
1379 static void
pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)1380 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
1381 {
1382 #ifndef WITHOUT_PKCS11
1383 if (ctx == NULL)
1384 return;
1385
1386 if (ctx->p11 != NULL) {
1387 if (ctx->session != CK_INVALID_HANDLE) {
1388 ctx->p11->C_CloseSession(ctx->session);
1389 ctx->session = CK_INVALID_HANDLE;
1390 }
1391 ctx->p11->C_Finalize(NULL_PTR);
1392 ctx->p11 = NULL;
1393 }
1394 if (ctx->p11_module != NULL) {
1395 krb5int_close_plugin(ctx->p11_module);
1396 ctx->p11_module = NULL;
1397 }
1398 free(ctx->p11_module_name);
1399 free(ctx->token_label);
1400 free(ctx->cert_id);
1401 free(ctx->cert_label);
1402 #endif
1403 }
1404
1405 krb5_error_code
pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,krb5_prompter_fct prompter,void * prompter_data)1406 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
1407 krb5_prompter_fct prompter,
1408 void *prompter_data)
1409 {
1410 id_cryptoctx->prompter = prompter;
1411 id_cryptoctx->prompter_data = prompter_data;
1412
1413 return 0;
1414 }
1415
1416 /* Create a CMS ContentInfo of type oid containing the octet string in data. */
1417 static krb5_error_code
create_contentinfo(krb5_context context,ASN1_OBJECT * oid,unsigned char * data,size_t data_len,PKCS7 ** p7_out)1418 create_contentinfo(krb5_context context, ASN1_OBJECT *oid,
1419 unsigned char *data, size_t data_len, PKCS7 **p7_out)
1420 {
1421 PKCS7 *p7 = NULL;
1422 ASN1_OCTET_STRING *ostr = NULL;
1423
1424 *p7_out = NULL;
1425
1426 ostr = ASN1_OCTET_STRING_new();
1427 if (ostr == NULL)
1428 goto oom;
1429 if (!ASN1_OCTET_STRING_set(ostr, (unsigned char *)data, data_len))
1430 goto oom;
1431
1432 p7 = PKCS7_new();
1433 if (p7 == NULL)
1434 goto oom;
1435 p7->type = OBJ_dup(oid);
1436 if (p7->type == NULL)
1437 goto oom;
1438
1439 p7->d.other = ASN1_TYPE_new();
1440 if (p7->d.other == NULL)
1441 goto oom;
1442 p7->d.other->type = V_ASN1_OCTET_STRING;
1443 p7->d.other->value.octet_string = ostr;
1444
1445 *p7_out = p7;
1446 return 0;
1447
1448 oom:
1449 if (ostr != NULL)
1450 ASN1_OCTET_STRING_free(ostr);
1451 if (p7 != NULL)
1452 PKCS7_free(p7);
1453 return ENOMEM;
1454 }
1455
1456 krb5_error_code
cms_contentinfo_create(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int cms_msg_type,unsigned char * data,unsigned int data_len,unsigned char ** out_data,unsigned int * out_data_len)1457 cms_contentinfo_create(krb5_context context, /* IN */
1458 pkinit_plg_crypto_context plg_cryptoctx, /* IN */
1459 pkinit_req_crypto_context req_cryptoctx, /* IN */
1460 pkinit_identity_crypto_context id_cryptoctx, /* IN */
1461 int cms_msg_type,
1462 unsigned char *data, unsigned int data_len,
1463 unsigned char **out_data, unsigned int *out_data_len)
1464 {
1465 krb5_error_code retval = ENOMEM;
1466 ASN1_OBJECT *oid;
1467 PKCS7 *p7 = NULL;
1468 unsigned char *p;
1469
1470 /* Pick the correct oid for the eContentInfo. */
1471 oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
1472 if (oid == NULL)
1473 goto cleanup;
1474 retval = create_contentinfo(context, oid, data, data_len, &p7);
1475 if (retval != 0)
1476 goto cleanup;
1477 *out_data_len = i2d_PKCS7(p7, NULL);
1478 if (!(*out_data_len)) {
1479 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1480 goto cleanup;
1481 }
1482 retval = ENOMEM;
1483 if ((p = *out_data = malloc(*out_data_len)) == NULL)
1484 goto cleanup;
1485
1486 /* DER encode PKCS7 data */
1487 retval = i2d_PKCS7(p7, &p);
1488 if (!retval) {
1489 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1490 goto cleanup;
1491 }
1492 retval = 0;
1493 cleanup:
1494 if (p7)
1495 PKCS7_free(p7);
1496 return retval;
1497 }
1498
1499
1500
1501 krb5_error_code
cms_signeddata_create(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int cms_msg_type,unsigned char * data,unsigned int data_len,unsigned char ** signed_data,unsigned int * signed_data_len)1502 cms_signeddata_create(krb5_context context,
1503 pkinit_plg_crypto_context plg_cryptoctx,
1504 pkinit_req_crypto_context req_cryptoctx,
1505 pkinit_identity_crypto_context id_cryptoctx,
1506 int cms_msg_type,
1507 unsigned char *data,
1508 unsigned int data_len,
1509 unsigned char **signed_data,
1510 unsigned int *signed_data_len)
1511 {
1512 krb5_error_code retval = ENOMEM;
1513 PKCS7 *p7 = NULL, *inner_p7 = NULL;
1514 PKCS7_SIGNED *p7s = NULL;
1515 PKCS7_SIGNER_INFO *p7si = NULL;
1516 unsigned char *p;
1517 STACK_OF(X509) * cert_stack = NULL;
1518 ASN1_OCTET_STRING *digest_attr = NULL;
1519 EVP_MD_CTX *ctx;
1520 const EVP_MD *md_tmp = NULL;
1521 unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
1522 unsigned char *digestInfo_buf = NULL, *abuf = NULL;
1523 unsigned int md_len, md_len2, alen, digestInfo_len;
1524 STACK_OF(X509_ATTRIBUTE) * sk;
1525 unsigned char *sig = NULL;
1526 unsigned int sig_len = 0;
1527 X509_ALGOR *alg = NULL;
1528 ASN1_OCTET_STRING *digest = NULL;
1529 unsigned int alg_len = 0, digest_len = 0;
1530 unsigned char *y = NULL;
1531 X509 *cert = NULL;
1532 ASN1_OBJECT *oid = NULL, *oid_copy;
1533
1534 /* Start creating PKCS7 data. */
1535 if ((p7 = PKCS7_new()) == NULL)
1536 goto cleanup;
1537 p7->type = OBJ_nid2obj(NID_pkcs7_signed);
1538
1539 if ((p7s = PKCS7_SIGNED_new()) == NULL)
1540 goto cleanup;
1541 p7->d.sign = p7s;
1542 if (!ASN1_INTEGER_set(p7s->version, 3))
1543 goto cleanup;
1544
1545 /* pick the correct oid for the eContentInfo */
1546 oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
1547 if (oid == NULL)
1548 goto cleanup;
1549
1550 if (id_cryptoctx->my_certs != NULL) {
1551 X509_STORE *certstore = NULL;
1552 X509_STORE_CTX *certctx;
1553 STACK_OF(X509) *certstack = NULL;
1554 char buf[DN_BUF_LEN];
1555 unsigned int i = 0, size = 0;
1556
1557 /* create a cert chain */
1558 if ((cert_stack = sk_X509_new_null()) == NULL)
1559 goto cleanup;
1560
1561 cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
1562
1563 certstore = X509_STORE_new();
1564 if (certstore == NULL)
1565 goto cleanup;
1566 pkiDebug("building certificate chain\n");
1567 X509_STORE_set_verify_cb(certstore, openssl_callback);
1568 certctx = X509_STORE_CTX_new();
1569 if (certctx == NULL)
1570 goto cleanup;
1571 X509_STORE_CTX_init(certctx, certstore, cert,
1572 id_cryptoctx->intermediateCAs);
1573 X509_STORE_CTX_trusted_stack(certctx, id_cryptoctx->trustedCAs);
1574 if (!X509_verify_cert(certctx)) {
1575 retval = oerr_cert(context, 0, certctx,
1576 _("Failed to verify own certificate"));
1577 goto cleanup;
1578 }
1579 certstack = X509_STORE_CTX_get1_chain(certctx);
1580 size = sk_X509_num(certstack);
1581 for (i = 0; i < size - 1; i++) {
1582 X509 *x = sk_X509_value(certstack, i);
1583 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
1584 TRACE_PKINIT_CERT_CHAIN_NAME(context, (int)i, buf);
1585 sk_X509_push(cert_stack, X509_dup(x));
1586 }
1587 X509_STORE_CTX_free(certctx);
1588 X509_STORE_free(certstore);
1589 sk_X509_pop_free(certstack, X509_free);
1590
1591 p7s->cert = cert_stack;
1592
1593 /* fill-in PKCS7_SIGNER_INFO */
1594 if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
1595 goto cleanup;
1596 if (!ASN1_INTEGER_set(p7si->version, 1))
1597 goto cleanup;
1598 if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
1599 X509_get_issuer_name(cert)))
1600 goto cleanup;
1601 /* because ASN1_INTEGER_set is used to set a 'long' we will do
1602 * things the ugly way. */
1603 ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
1604 if (!(p7si->issuer_and_serial->serial =
1605 ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
1606 goto cleanup;
1607
1608 /* will not fill-out EVP_PKEY because it's on the smartcard */
1609
1610 /* Set digest algs */
1611 p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha256);
1612
1613 if (p7si->digest_alg->parameter != NULL)
1614 ASN1_TYPE_free(p7si->digest_alg->parameter);
1615 if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
1616 goto cleanup;
1617 p7si->digest_alg->parameter->type = V_ASN1_NULL;
1618
1619 /* Set sig algs */
1620 if (p7si->digest_enc_alg->parameter != NULL)
1621 ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
1622 p7si->digest_enc_alg->algorithm =
1623 OBJ_nid2obj(NID_sha256WithRSAEncryption);
1624 if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
1625 goto cleanup;
1626 p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
1627
1628 /* add signed attributes */
1629 /* compute sha256 digest over the EncapsulatedContentInfo */
1630 ctx = EVP_MD_CTX_new();
1631 if (ctx == NULL)
1632 goto cleanup;
1633 EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
1634 EVP_DigestUpdate(ctx, data, data_len);
1635 md_tmp = EVP_MD_CTX_get0_md(ctx);
1636 EVP_DigestFinal_ex(ctx, md_data, &md_len);
1637 EVP_MD_CTX_free(ctx);
1638
1639 /* create a message digest attr */
1640 digest_attr = ASN1_OCTET_STRING_new();
1641 ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
1642 PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
1643 V_ASN1_OCTET_STRING, (char *)digest_attr);
1644
1645 /* create a content-type attr */
1646 oid_copy = OBJ_dup(oid);
1647 if (oid_copy == NULL)
1648 goto cleanup2;
1649 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
1650 V_ASN1_OBJECT, oid_copy);
1651
1652 /* create the signature over signed attributes. get DER encoded value */
1653 /* This is the place where smartcard signature needs to be calculated */
1654 sk = p7si->auth_attr;
1655 alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
1656 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
1657 if (abuf == NULL)
1658 goto cleanup2;
1659
1660 #ifndef WITHOUT_PKCS11
1661 /*
1662 * Some tokens can only do RSAEncryption without a hash. To compute
1663 * sha256WithRSAEncryption, encode the algorithm ID for the hash
1664 * function and the hash value into an ASN.1 value of type DigestInfo:
1665 * DigestInfo ::= SEQUENCE {
1666 * digestAlgorithm AlgorithmIdentifier,
1667 * digest OCTET STRING
1668 * }
1669 */
1670 if (id_cryptoctx->pkcs11_method == 1 &&
1671 id_cryptoctx->mech == CKM_RSA_PKCS) {
1672 pkiDebug("mech = CKM_RSA_PKCS\n");
1673 ctx = EVP_MD_CTX_new();
1674 if (ctx == NULL)
1675 goto cleanup;
1676 EVP_DigestInit_ex(ctx, md_tmp, NULL);
1677 EVP_DigestUpdate(ctx, abuf, alen);
1678 EVP_DigestFinal_ex(ctx, md_data2, &md_len2);
1679 EVP_MD_CTX_free(ctx);
1680
1681 alg = X509_ALGOR_new();
1682 if (alg == NULL)
1683 goto cleanup2;
1684 X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL);
1685 alg_len = i2d_X509_ALGOR(alg, NULL);
1686
1687 digest = ASN1_OCTET_STRING_new();
1688 if (digest == NULL)
1689 goto cleanup2;
1690 ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
1691 digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
1692
1693 digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
1694 V_ASN1_SEQUENCE);
1695 y = digestInfo_buf = malloc(digestInfo_len);
1696 if (digestInfo_buf == NULL)
1697 goto cleanup2;
1698 ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
1699 V_ASN1_UNIVERSAL);
1700 i2d_X509_ALGOR(alg, &y);
1701 i2d_ASN1_OCTET_STRING(digest, &y);
1702 #ifdef DEBUG_SIG
1703 pkiDebug("signing buffer\n");
1704 print_buffer(digestInfo_buf, digestInfo_len);
1705 print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
1706 #endif
1707 retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
1708 digestInfo_len, &sig, &sig_len);
1709 } else
1710 #endif
1711 {
1712 pkiDebug("mech = %s\n",
1713 id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS");
1714 retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
1715 &sig, &sig_len);
1716 }
1717 #ifdef DEBUG_SIG
1718 print_buffer(sig, sig_len);
1719 #endif
1720 free(abuf);
1721 if (retval)
1722 goto cleanup2;
1723
1724 /* Add signature */
1725 if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
1726 (int)sig_len)) {
1727 retval = oerr(context, 0, _("Failed to add digest attribute"));
1728 goto cleanup2;
1729 }
1730 /* adder signer_info to pkcs7 signed */
1731 if (!PKCS7_add_signer(p7, p7si))
1732 goto cleanup2;
1733 } /* we have a certificate */
1734
1735 /* start on adding data to the pkcs7 signed */
1736 retval = create_contentinfo(context, oid, data, data_len, &inner_p7);
1737 if (p7s->contents != NULL)
1738 PKCS7_free(p7s->contents);
1739 p7s->contents = inner_p7;
1740
1741 *signed_data_len = i2d_PKCS7(p7, NULL);
1742 if (!(*signed_data_len)) {
1743 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1744 goto cleanup2;
1745 }
1746 retval = ENOMEM;
1747 if ((p = *signed_data = malloc(*signed_data_len)) == NULL)
1748 goto cleanup2;
1749
1750 /* DER encode PKCS7 data */
1751 retval = i2d_PKCS7(p7, &p);
1752 if (!retval) {
1753 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1754 goto cleanup2;
1755 }
1756 retval = 0;
1757
1758 #ifdef DEBUG_ASN1
1759 if (cms_msg_type == CMS_SIGN_CLIENT) {
1760 print_buffer_bin(*signed_data, *signed_data_len,
1761 "/tmp/client_pkcs7_signeddata");
1762 } else {
1763 print_buffer_bin(*signed_data, *signed_data_len,
1764 "/tmp/kdc_pkcs7_signeddata");
1765 }
1766 #endif
1767
1768 cleanup2:
1769 if (p7si) {
1770 #ifndef WITHOUT_PKCS11
1771 if (id_cryptoctx->pkcs11_method == 1 &&
1772 id_cryptoctx->mech == CKM_RSA_PKCS) {
1773 free(digestInfo_buf);
1774 if (digest != NULL)
1775 ASN1_OCTET_STRING_free(digest);
1776 }
1777 #endif
1778 if (alg != NULL)
1779 X509_ALGOR_free(alg);
1780 }
1781 cleanup:
1782 if (p7 != NULL)
1783 PKCS7_free(p7);
1784 free(sig);
1785
1786 return retval;
1787 }
1788
1789 krb5_error_code
cms_signeddata_verify(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,int cms_msg_type,int require_crl_checking,unsigned char * signed_data,unsigned int signed_data_len,unsigned char ** data,unsigned int * data_len,unsigned char ** authz_data,unsigned int * authz_data_len,int * is_signed)1790 cms_signeddata_verify(krb5_context context,
1791 pkinit_plg_crypto_context plgctx,
1792 pkinit_req_crypto_context reqctx,
1793 pkinit_identity_crypto_context idctx,
1794 int cms_msg_type,
1795 int require_crl_checking,
1796 unsigned char *signed_data,
1797 unsigned int signed_data_len,
1798 unsigned char **data,
1799 unsigned int *data_len,
1800 unsigned char **authz_data,
1801 unsigned int *authz_data_len,
1802 int *is_signed)
1803 {
1804 /*
1805 * Warning: Since most openssl functions do not set retval, large chunks of
1806 * this function assume that retval is always a failure and may go to
1807 * cleanup without setting retval explicitly. Make sure retval is not set
1808 * to 0 or errors such as signature verification failure may be converted
1809 * to success with significant security consequences.
1810 */
1811 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
1812 CMS_ContentInfo *cms = NULL;
1813 BIO *out = NULL;
1814 int flags = CMS_NO_SIGNER_CERT_VERIFY;
1815 int valid_oid = 0;
1816 unsigned int i = 0;
1817 unsigned int vflags = 0, size = 0;
1818 const unsigned char *p = signed_data;
1819 STACK_OF(CMS_SignerInfo) *si_sk = NULL;
1820 CMS_SignerInfo *si = NULL;
1821 X509 *x = NULL;
1822 X509_STORE *store = NULL;
1823 X509_STORE_CTX *cert_ctx;
1824 STACK_OF(X509) *signerCerts = NULL;
1825 STACK_OF(X509) *intermediateCAs = NULL;
1826 STACK_OF(X509_CRL) *signerRevoked = NULL;
1827 STACK_OF(X509_CRL) *revoked = NULL;
1828 STACK_OF(X509) *verified_chain = NULL;
1829 ASN1_OBJECT *oid = NULL;
1830 const ASN1_OBJECT *type = NULL, *etype = NULL;
1831 ASN1_OCTET_STRING **octets;
1832 krb5_external_principal_identifier **krb5_verified_chain = NULL;
1833 krb5_data *authz = NULL;
1834 char buf[DN_BUF_LEN];
1835
1836 #ifdef DEBUG_ASN1
1837 print_buffer_bin(signed_data, signed_data_len,
1838 "/tmp/client_received_pkcs7_signeddata");
1839 #endif
1840 if (is_signed)
1841 *is_signed = 1;
1842
1843 oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
1844 if (oid == NULL)
1845 goto cleanup;
1846
1847 /* decode received CMS message */
1848 if ((cms = d2i_CMS_ContentInfo(NULL, &p, (int)signed_data_len)) == NULL) {
1849 retval = oerr(context, 0, _("Failed to decode CMS message"));
1850 goto cleanup;
1851 }
1852 etype = CMS_get0_eContentType(cms);
1853
1854 /*
1855 * Prior to 1.10 the MIT client incorrectly emitted the pkinit structure
1856 * directly in a CMS ContentInfo rather than using SignedData with no
1857 * signers. Handle that case.
1858 */
1859 type = CMS_get0_type(cms);
1860 if (is_signed && !OBJ_cmp(type, oid)) {
1861 unsigned char *d;
1862 *is_signed = 0;
1863 octets = CMS_get0_content(cms);
1864 if (!octets || ((*octets)->type != V_ASN1_OCTET_STRING)) {
1865 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1866 krb5_set_error_message(context, retval,
1867 _("Invalid pkinit packet: octet string "
1868 "expected"));
1869 goto cleanup;
1870 }
1871 *data_len = ASN1_STRING_length(*octets);
1872 d = malloc(*data_len);
1873 if (d == NULL) {
1874 retval = ENOMEM;
1875 goto cleanup;
1876 }
1877 memcpy(d, ASN1_STRING_get0_data(*octets), *data_len);
1878 *data = d;
1879 goto out;
1880 } else {
1881 /* Verify that the received message is CMS SignedData message. */
1882 if (OBJ_obj2nid(type) != NID_pkcs7_signed) {
1883 pkiDebug("Expected id-signedData CMS msg (received type = %d)\n",
1884 OBJ_obj2nid(type));
1885 krb5_set_error_message(context, retval, _("wrong oid\n"));
1886 goto cleanup;
1887 }
1888 }
1889
1890 /* setup to verify X509 certificate used to sign CMS message */
1891 if (!(store = X509_STORE_new()))
1892 goto cleanup;
1893
1894 /* check if we are inforcing CRL checking */
1895 vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
1896 if (require_crl_checking)
1897 X509_STORE_set_verify_cb(store, openssl_callback);
1898 else
1899 X509_STORE_set_verify_cb(store, openssl_callback_ignore_crls);
1900 X509_STORE_set_flags(store, vflags);
1901
1902 /*
1903 * Get the signer's information from the CMS message. Match signer ID
1904 * against anchors and intermediate CAs in case no certs are present in the
1905 * SignedData. If we start sending kdcPkId values in requests, we'll need
1906 * to match against the source of that information too.
1907 */
1908 CMS_set1_signers_certs(cms, NULL, 0);
1909 CMS_set1_signers_certs(cms, idctx->trustedCAs, CMS_NOINTERN);
1910 CMS_set1_signers_certs(cms, idctx->intermediateCAs, CMS_NOINTERN);
1911 if (((si_sk = CMS_get0_SignerInfos(cms)) == NULL) ||
1912 ((si = sk_CMS_SignerInfo_value(si_sk, 0)) == NULL)) {
1913 /* Not actually signed; anonymous case */
1914 if (!is_signed)
1915 goto cleanup;
1916 *is_signed = 0;
1917 /* We cannot use CMS_dataInit because there may be no digest */
1918 octets = CMS_get0_content(cms);
1919 if (octets)
1920 out = BIO_new_mem_buf((*octets)->data, (*octets)->length);
1921 if (out == NULL)
1922 goto cleanup;
1923 } else {
1924 CMS_SignerInfo_get0_algs(si, NULL, &x, NULL, NULL);
1925 if (x == NULL)
1926 goto cleanup;
1927
1928 /* create available CRL information (get local CRLs and include CRLs
1929 * received in the CMS message
1930 */
1931 signerRevoked = CMS_get1_crls(cms);
1932 if (idctx->revoked == NULL)
1933 revoked = signerRevoked;
1934 else if (signerRevoked == NULL)
1935 revoked = idctx->revoked;
1936 else {
1937 size = sk_X509_CRL_num(idctx->revoked);
1938 revoked = sk_X509_CRL_new_null();
1939 for (i = 0; i < size; i++)
1940 sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i));
1941 size = sk_X509_CRL_num(signerRevoked);
1942 for (i = 0; i < size; i++)
1943 sk_X509_CRL_push(revoked, sk_X509_CRL_value(signerRevoked, i));
1944 }
1945
1946 /* create available intermediate CAs chains (get local intermediateCAs and
1947 * include the CA chain received in the CMS message
1948 */
1949 signerCerts = CMS_get1_certs(cms);
1950 if (idctx->intermediateCAs == NULL)
1951 intermediateCAs = signerCerts;
1952 else if (signerCerts == NULL)
1953 intermediateCAs = idctx->intermediateCAs;
1954 else {
1955 size = sk_X509_num(idctx->intermediateCAs);
1956 intermediateCAs = sk_X509_new_null();
1957 for (i = 0; i < size; i++) {
1958 sk_X509_push(intermediateCAs,
1959 sk_X509_value(idctx->intermediateCAs, i));
1960 }
1961 size = sk_X509_num(signerCerts);
1962 for (i = 0; i < size; i++) {
1963 sk_X509_push(intermediateCAs, sk_X509_value(signerCerts, i));
1964 }
1965 }
1966
1967 /* initialize x509 context with the received certificate and
1968 * trusted and intermediate CA chains and CRLs
1969 */
1970 cert_ctx = X509_STORE_CTX_new();
1971 if (cert_ctx == NULL)
1972 goto cleanup;
1973 if (!X509_STORE_CTX_init(cert_ctx, store, x, intermediateCAs))
1974 goto cleanup;
1975
1976 X509_STORE_CTX_set0_crls(cert_ctx, revoked);
1977
1978 /* add trusted CAs certificates for cert verification */
1979 if (idctx->trustedCAs != NULL)
1980 X509_STORE_CTX_trusted_stack(cert_ctx, idctx->trustedCAs);
1981 else {
1982 pkiDebug("unable to find any trusted CAs\n");
1983 goto cleanup;
1984 }
1985 #ifdef DEBUG_CERTCHAIN
1986 if (intermediateCAs != NULL) {
1987 size = sk_X509_num(intermediateCAs);
1988 pkiDebug("untrusted cert chain of size %d\n", size);
1989 for (i = 0; i < size; i++) {
1990 X509_NAME_oneline(X509_get_subject_name(
1991 sk_X509_value(intermediateCAs, i)), buf, sizeof(buf));
1992 pkiDebug("cert #%d: %s\n", i, buf);
1993 }
1994 }
1995 if (idctx->trustedCAs != NULL) {
1996 size = sk_X509_num(idctx->trustedCAs);
1997 pkiDebug("trusted cert chain of size %d\n", size);
1998 for (i = 0; i < size; i++) {
1999 X509_NAME_oneline(X509_get_subject_name(
2000 sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf));
2001 pkiDebug("cert #%d: %s\n", i, buf);
2002 }
2003 }
2004 if (revoked != NULL) {
2005 size = sk_X509_CRL_num(revoked);
2006 pkiDebug("CRL chain of size %d\n", size);
2007 for (i = 0; i < size; i++) {
2008 X509_CRL *crl = sk_X509_CRL_value(revoked, i);
2009 X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf));
2010 pkiDebug("crls by CA #%d: %s\n", i , buf);
2011 }
2012 }
2013 #endif
2014
2015 i = X509_verify_cert(cert_ctx);
2016 if (i <= 0) {
2017 int j = X509_STORE_CTX_get_error(cert_ctx);
2018 X509 *cert;
2019
2020 cert = X509_STORE_CTX_get_current_cert(cert_ctx);
2021 reqctx->received_cert = X509_dup(cert);
2022 switch(j) {
2023 case X509_V_ERR_CERT_REVOKED:
2024 retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
2025 break;
2026 case X509_V_ERR_UNABLE_TO_GET_CRL:
2027 retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN;
2028 break;
2029 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
2030 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2031 retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE;
2032 break;
2033 default:
2034 retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
2035 }
2036 (void)oerr_cert(context, retval, cert_ctx,
2037 _("Failed to verify received certificate"));
2038 if (reqctx->received_cert == NULL)
2039 strlcpy(buf, "(none)", sizeof(buf));
2040 else
2041 X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
2042 buf, sizeof(buf));
2043 pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j,
2044 X509_verify_cert_error_string(j));
2045 #ifdef DEBUG_CERTCHAIN
2046 size = sk_X509_num(signerCerts);
2047 pkiDebug("received cert chain of size %d\n", size);
2048 for (j = 0; j < size; j++) {
2049 X509 *tmp_cert = sk_X509_value(signerCerts, j);
2050 X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf));
2051 pkiDebug("cert #%d: %s\n", j, buf);
2052 }
2053 #endif
2054 } else {
2055 /* retrieve verified certificate chain */
2056 if (cms_msg_type == CMS_SIGN_CLIENT)
2057 verified_chain = X509_STORE_CTX_get1_chain(cert_ctx);
2058 }
2059 X509_STORE_CTX_free(cert_ctx);
2060 if (i <= 0)
2061 goto cleanup;
2062 out = BIO_new(BIO_s_mem());
2063 if (CMS_verify(cms, NULL, store, NULL, out, flags) == 0) {
2064 if (ERR_peek_last_error() == CMS_R_VERIFICATION_FAILURE)
2065 retval = KRB5KDC_ERR_INVALID_SIG;
2066 else
2067 retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED;
2068 (void)oerr(context, retval, _("Failed to verify CMS message"));
2069 goto cleanup;
2070 }
2071 } /* message was signed */
2072 if (!OBJ_cmp(etype, oid))
2073 valid_oid = 1;
2074
2075 if (valid_oid)
2076 pkiDebug("CMS Verification successful\n");
2077 else {
2078 pkiDebug("wrong oid in eContentType\n");
2079 print_buffer(OBJ_get0_data(etype), OBJ_length(etype));
2080 retval = KRB5KDC_ERR_PREAUTH_FAILED;
2081 krb5_set_error_message(context, retval, "wrong oid\n");
2082 goto cleanup;
2083 }
2084
2085 /* transfer the data from CMS message into return buffer */
2086 for (size = 0;;) {
2087 int remain;
2088 retval = ENOMEM;
2089 if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
2090 goto cleanup;
2091 remain = BIO_read(out, &((*data)[size]), 1024 * 10);
2092 if (remain <= 0)
2093 break;
2094 else
2095 size += remain;
2096 }
2097 *data_len = size;
2098
2099 if (x) {
2100 reqctx->received_cert = X509_dup(x);
2101
2102 /* generate authorization data */
2103 if (cms_msg_type == CMS_SIGN_CLIENT) {
2104
2105 if (authz_data == NULL || authz_data_len == NULL)
2106 goto out;
2107
2108 *authz_data = NULL;
2109 retval = create_identifiers_from_stack(verified_chain,
2110 &krb5_verified_chain);
2111 if (retval) {
2112 pkiDebug("create_identifiers_from_stack failed\n");
2113 goto cleanup;
2114 }
2115
2116 retval = k5int_encode_krb5_td_trusted_certifiers((krb5_external_principal_identifier *const *)krb5_verified_chain, &authz);
2117 if (retval) {
2118 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
2119 goto cleanup;
2120 }
2121 #ifdef DEBUG_ASN1
2122 print_buffer_bin((unsigned char *)authz->data, authz->length,
2123 "/tmp/kdc_ad_initial_verified_cas");
2124 #endif
2125 *authz_data = malloc(authz->length);
2126 if (*authz_data == NULL) {
2127 retval = ENOMEM;
2128 goto cleanup;
2129 }
2130 memcpy(*authz_data, authz->data, authz->length);
2131 *authz_data_len = authz->length;
2132 }
2133 }
2134 out:
2135 retval = 0;
2136
2137 cleanup:
2138 if (out != NULL)
2139 BIO_free(out);
2140 if (store != NULL)
2141 X509_STORE_free(store);
2142 if (cms != NULL) {
2143 if (signerCerts != NULL)
2144 sk_X509_pop_free(signerCerts, X509_free);
2145 if (idctx->intermediateCAs != NULL && signerCerts)
2146 sk_X509_free(intermediateCAs);
2147 if (signerRevoked != NULL)
2148 sk_X509_CRL_pop_free(signerRevoked, X509_CRL_free);
2149 if (idctx->revoked != NULL && signerRevoked)
2150 sk_X509_CRL_free(revoked);
2151 CMS_ContentInfo_free(cms);
2152 }
2153 if (verified_chain != NULL)
2154 sk_X509_pop_free(verified_chain, X509_free);
2155 if (krb5_verified_chain != NULL)
2156 free_krb5_external_principal_identifier(&krb5_verified_chain);
2157 if (authz != NULL)
2158 krb5_free_data(context, authz);
2159
2160 return retval;
2161 }
2162
2163 krb5_error_code
cms_envelopeddata_create(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,krb5_preauthtype pa_type,unsigned char * key_pack,unsigned int key_pack_len,unsigned char ** out,unsigned int * out_len)2164 cms_envelopeddata_create(krb5_context context,
2165 pkinit_plg_crypto_context plgctx,
2166 pkinit_req_crypto_context reqctx,
2167 pkinit_identity_crypto_context idctx,
2168 krb5_preauthtype pa_type,
2169 unsigned char *key_pack,
2170 unsigned int key_pack_len,
2171 unsigned char **out,
2172 unsigned int *out_len)
2173 {
2174
2175 krb5_error_code retval = ENOMEM;
2176 PKCS7 *p7 = NULL;
2177 BIO *in = NULL;
2178 unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL;
2179 int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY;
2180 STACK_OF(X509) *encerts = NULL;
2181 const EVP_CIPHER *cipher = NULL;
2182
2183 retval = cms_signeddata_create(context, plgctx, reqctx, idctx,
2184 CMS_ENVEL_SERVER, key_pack, key_pack_len,
2185 &signed_data,
2186 (unsigned int *)&signed_data_len);
2187 if (retval) {
2188 pkiDebug("failed to create pkcs7 signed data\n");
2189 goto cleanup;
2190 }
2191
2192 /* check we have client's certificate */
2193 if (reqctx->received_cert == NULL) {
2194 retval = KRB5KDC_ERR_PREAUTH_FAILED;
2195 goto cleanup;
2196 }
2197 encerts = sk_X509_new_null();
2198 sk_X509_push(encerts, reqctx->received_cert);
2199
2200 cipher = EVP_des_ede3_cbc();
2201 in = BIO_new(BIO_s_mem());
2202 prepare_enc_data(signed_data, signed_data_len, &enc_data,
2203 &enc_data_len);
2204 retval = BIO_write(in, enc_data, enc_data_len);
2205 if (retval != enc_data_len) {
2206 pkiDebug("BIO_write only wrote %d\n", retval);
2207 goto cleanup;
2208 }
2209
2210 p7 = PKCS7_encrypt(encerts, in, cipher, flags);
2211 if (p7 == NULL) {
2212 retval = oerr(context, 0, _("Failed to encrypt PKCS7 object"));
2213 goto cleanup;
2214 }
2215 p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_signed);
2216
2217 *out_len = i2d_PKCS7(p7, NULL);
2218 if (!*out_len || (p = *out = malloc(*out_len)) == NULL) {
2219 retval = ENOMEM;
2220 goto cleanup;
2221 }
2222 retval = i2d_PKCS7(p7, &p);
2223 if (!retval) {
2224 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
2225 goto cleanup;
2226 }
2227 retval = 0;
2228
2229 #ifdef DEBUG_ASN1
2230 print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data");
2231 #endif
2232
2233 cleanup:
2234 if (p7 != NULL)
2235 PKCS7_free(p7);
2236 if (in != NULL)
2237 BIO_free(in);
2238 free(signed_data);
2239 free(enc_data);
2240 if (encerts != NULL)
2241 sk_X509_free(encerts);
2242
2243 return retval;
2244 }
2245
2246 krb5_error_code
cms_envelopeddata_verify(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_preauthtype pa_type,int require_crl_checking,unsigned char * enveloped_data,unsigned int enveloped_data_len,unsigned char ** data,unsigned int * data_len)2247 cms_envelopeddata_verify(krb5_context context,
2248 pkinit_plg_crypto_context plg_cryptoctx,
2249 pkinit_req_crypto_context req_cryptoctx,
2250 pkinit_identity_crypto_context id_cryptoctx,
2251 krb5_preauthtype pa_type,
2252 int require_crl_checking,
2253 unsigned char *enveloped_data,
2254 unsigned int enveloped_data_len,
2255 unsigned char **data,
2256 unsigned int *data_len)
2257 {
2258 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2259 PKCS7 *p7 = NULL;
2260 const unsigned char *p = enveloped_data;
2261 unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0;
2262 unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL;
2263
2264 #ifdef DEBUG_ASN1
2265 print_buffer_bin(enveloped_data, enveloped_data_len,
2266 "/tmp/client_envelopeddata");
2267 #endif
2268 /* decode received PKCS7 message */
2269 if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) {
2270 retval = oerr(context, 0, _("Failed to decode PKCS7"));
2271 goto cleanup;
2272 }
2273
2274 /* verify that the received message is PKCS7 EnvelopedData message */
2275 if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped ||
2276 p7->d.enveloped == NULL ||
2277 p7->d.enveloped->enc_data->enc_data == NULL) {
2278 pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
2279 OBJ_obj2nid(p7->type));
2280 krb5_set_error_message(context, retval, "wrong oid\n");
2281 goto cleanup;
2282 }
2283
2284 /* decrypt received PKCS7 message */
2285 if (pkcs7_decrypt(context, id_cryptoctx, p7, &tmp_buf, &tmp_buf_len)) {
2286 pkiDebug("PKCS7 decryption successful\n");
2287 } else {
2288 retval = oerr(context, 0, _("Failed to decrypt PKCS7 message"));
2289 goto cleanup;
2290 }
2291
2292 #ifdef DEBUG_ASN1
2293 print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack");
2294 #endif
2295 /* verify PKCS7 SignedData message */
2296 /* Wrap the signed data to make decoding easier in the verify routine. */
2297 retval = wrap_signeddata(tmp_buf, tmp_buf_len, &tmp_buf2, &tmp_buf2_len);
2298 if (retval) {
2299 pkiDebug("failed to encode signeddata\n");
2300 goto cleanup;
2301 }
2302 vfy_buf = tmp_buf2;
2303 vfy_buf_len = tmp_buf2_len;
2304
2305 #ifdef DEBUG_ASN1
2306 print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2");
2307 #endif
2308
2309 retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx,
2310 id_cryptoctx, CMS_ENVEL_SERVER,
2311 require_crl_checking,
2312 vfy_buf, vfy_buf_len,
2313 data, data_len, NULL, NULL, NULL);
2314
2315 if (!retval)
2316 pkiDebug("PKCS7 Verification Success\n");
2317 else {
2318 pkiDebug("PKCS7 Verification Failure\n");
2319 goto cleanup;
2320 }
2321
2322 retval = 0;
2323
2324 cleanup:
2325
2326 if (p7 != NULL)
2327 PKCS7_free(p7);
2328 free(tmp_buf);
2329 free(tmp_buf2);
2330
2331 return retval;
2332 }
2333
2334 static krb5_error_code
crypto_retrieve_X509_sans(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,X509 * cert,krb5_principal ** princs_ret,char *** upn_ret,unsigned char *** dns_ret)2335 crypto_retrieve_X509_sans(krb5_context context,
2336 pkinit_plg_crypto_context plgctx,
2337 pkinit_req_crypto_context reqctx,
2338 X509 *cert,
2339 krb5_principal **princs_ret, char ***upn_ret,
2340 unsigned char ***dns_ret)
2341 {
2342 krb5_error_code retval = EINVAL;
2343 char buf[DN_BUF_LEN];
2344 int p = 0, u = 0, d = 0, ret = 0, l;
2345 krb5_principal *princs = NULL;
2346 char **upns = NULL;
2347 unsigned char **dnss = NULL;
2348 unsigned int i, num_sans = 0;
2349 X509_EXTENSION *ext = NULL;
2350 GENERAL_NAMES *ialt = NULL;
2351 GENERAL_NAME *gen = NULL;
2352
2353 if (princs_ret != NULL)
2354 *princs_ret = NULL;
2355 if (upn_ret != NULL)
2356 *upn_ret = NULL;
2357 if (dns_ret != NULL)
2358 *dns_ret = NULL;
2359
2360 if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
2361 pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
2362 return retval;
2363 }
2364
2365 if (cert == NULL) {
2366 pkiDebug("%s: no certificate!\n", __FUNCTION__);
2367 return retval;
2368 }
2369
2370 X509_NAME_oneline(X509_get_subject_name(cert),
2371 buf, sizeof(buf));
2372
2373 l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
2374 if (l < 0)
2375 return 0;
2376
2377 if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
2378 TRACE_PKINIT_SAN_CERT_NONE(context, buf);
2379 goto cleanup;
2380 }
2381 num_sans = sk_GENERAL_NAME_num(ialt);
2382
2383 /* OK, we're likely returning something. Allocate return values */
2384 if (princs_ret != NULL) {
2385 princs = calloc(num_sans + 1, sizeof(krb5_principal));
2386 if (princs == NULL) {
2387 retval = ENOMEM;
2388 goto cleanup;
2389 }
2390 }
2391 if (upn_ret != NULL) {
2392 upns = calloc(num_sans + 1, sizeof(*upns));
2393 if (upns == NULL) {
2394 retval = ENOMEM;
2395 goto cleanup;
2396 }
2397 }
2398 if (dns_ret != NULL) {
2399 dnss = calloc(num_sans + 1, sizeof(*dnss));
2400 if (dnss == NULL) {
2401 retval = ENOMEM;
2402 goto cleanup;
2403 }
2404 }
2405
2406 for (i = 0; i < num_sans; i++) {
2407 krb5_data name = { 0, 0, NULL };
2408
2409 gen = sk_GENERAL_NAME_value(ialt, i);
2410 switch (gen->type) {
2411 case GEN_OTHERNAME:
2412 name.length = gen->d.otherName->value->value.sequence->length;
2413 name.data = (char *)gen->d.otherName->value->value.sequence->data;
2414 if (princs != NULL &&
2415 OBJ_cmp(plgctx->id_pkinit_san,
2416 gen->d.otherName->type_id) == 0) {
2417 #ifdef DEBUG_ASN1
2418 print_buffer_bin((unsigned char *)name.data, name.length,
2419 "/tmp/pkinit_san");
2420 #endif
2421 ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
2422 if (ret) {
2423 pkiDebug("%s: failed decoding pkinit san value\n",
2424 __FUNCTION__);
2425 } else {
2426 p++;
2427 }
2428 } else if (upns != NULL &&
2429 OBJ_cmp(plgctx->id_ms_san_upn,
2430 gen->d.otherName->type_id) == 0) {
2431 /* Prevent abuse of embedded null characters. */
2432 if (memchr(name.data, '\0', name.length))
2433 break;
2434 upns[u] = k5memdup0(name.data, name.length, &ret);
2435 if (upns[u] == NULL)
2436 goto cleanup;
2437 u++;
2438 } else {
2439 pkiDebug("%s: unrecognized othername oid in SAN\n",
2440 __FUNCTION__);
2441 continue;
2442 }
2443
2444 break;
2445 case GEN_DNS:
2446 if (dnss != NULL) {
2447 /* Prevent abuse of embedded null characters. */
2448 if (memchr(gen->d.dNSName->data, '\0', gen->d.dNSName->length))
2449 break;
2450 pkiDebug("%s: found dns name = %s\n", __FUNCTION__,
2451 gen->d.dNSName->data);
2452 dnss[d] = (unsigned char *)
2453 strdup((char *)gen->d.dNSName->data);
2454 if (dnss[d] == NULL) {
2455 pkiDebug("%s: failed to duplicate dns name\n",
2456 __FUNCTION__);
2457 } else {
2458 d++;
2459 }
2460 }
2461 break;
2462 default:
2463 pkiDebug("%s: SAN type = %d expecting %d\n", __FUNCTION__,
2464 gen->type, GEN_OTHERNAME);
2465 }
2466 }
2467 sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
2468
2469 TRACE_PKINIT_SAN_CERT_COUNT(context, (int)num_sans, p, u, d, buf);
2470
2471 retval = 0;
2472 if (princs != NULL && *princs != NULL) {
2473 *princs_ret = princs;
2474 princs = NULL;
2475 }
2476 if (upns != NULL && *upns != NULL) {
2477 *upn_ret = upns;
2478 upns = NULL;
2479 }
2480 if (dnss != NULL && *dnss != NULL) {
2481 *dns_ret = dnss;
2482 dnss = NULL;
2483 }
2484
2485 cleanup:
2486 for (i = 0; princs != NULL && princs[i] != NULL; i++)
2487 krb5_free_principal(context, princs[i]);
2488 free(princs);
2489 for (i = 0; upns != NULL && upns[i] != NULL; i++)
2490 free(upns[i]);
2491 free(upns);
2492 for (i = 0; dnss != NULL && dnss[i] != NULL; i++)
2493 free(dnss[i]);
2494 free(dnss);
2495 return retval;
2496 }
2497
2498 krb5_error_code
crypto_retrieve_signer_identity(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,const char ** identity)2499 crypto_retrieve_signer_identity(krb5_context context,
2500 pkinit_identity_crypto_context id_cryptoctx,
2501 const char **identity)
2502 {
2503 *identity = id_cryptoctx->identity;
2504 if (*identity == NULL)
2505 return ENOENT;
2506 return 0;
2507 }
2508
2509 krb5_error_code
crypto_retrieve_cert_sans(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,krb5_principal ** princs_ret,char *** upn_ret,unsigned char *** dns_ret)2510 crypto_retrieve_cert_sans(krb5_context context,
2511 pkinit_plg_crypto_context plgctx,
2512 pkinit_req_crypto_context reqctx,
2513 pkinit_identity_crypto_context idctx,
2514 krb5_principal **princs_ret, char ***upn_ret,
2515 unsigned char ***dns_ret)
2516 {
2517 krb5_error_code retval = EINVAL;
2518
2519 if (reqctx->received_cert == NULL) {
2520 pkiDebug("%s: No certificate!\n", __FUNCTION__);
2521 return retval;
2522 }
2523
2524 return crypto_retrieve_X509_sans(context, plgctx, reqctx,
2525 reqctx->received_cert, princs_ret,
2526 upn_ret, dns_ret);
2527 }
2528
2529 krb5_error_code
crypto_check_cert_eku(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_identity_crypto_context idctx,int checking_kdc_cert,int allow_secondary_usage,int * valid_eku)2530 crypto_check_cert_eku(krb5_context context,
2531 pkinit_plg_crypto_context plgctx,
2532 pkinit_req_crypto_context reqctx,
2533 pkinit_identity_crypto_context idctx,
2534 int checking_kdc_cert,
2535 int allow_secondary_usage,
2536 int *valid_eku)
2537 {
2538 char buf[DN_BUF_LEN];
2539 int found_eku = 0;
2540 krb5_error_code retval = EINVAL;
2541 int i;
2542
2543 *valid_eku = 0;
2544 if (reqctx->received_cert == NULL)
2545 goto cleanup;
2546
2547 X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
2548 buf, sizeof(buf));
2549
2550 if ((i = X509_get_ext_by_NID(reqctx->received_cert,
2551 NID_ext_key_usage, -1)) >= 0) {
2552 EXTENDED_KEY_USAGE *extusage;
2553
2554 extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage,
2555 NULL, NULL);
2556 if (extusage) {
2557 pkiDebug("%s: found eku info in the cert\n", __FUNCTION__);
2558 for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) {
2559 ASN1_OBJECT *tmp_oid;
2560
2561 tmp_oid = sk_ASN1_OBJECT_value(extusage, i);
2562 pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
2563 __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage),
2564 allow_secondary_usage);
2565 if (checking_kdc_cert) {
2566 if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0)
2567 || (allow_secondary_usage
2568 && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0))
2569 found_eku = 1;
2570 } else {
2571 if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0)
2572 || (allow_secondary_usage
2573 && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0))
2574 found_eku = 1;
2575 }
2576 }
2577 }
2578 EXTENDED_KEY_USAGE_free(extusage);
2579
2580 if (found_eku) {
2581 ASN1_BIT_STRING *usage = NULL;
2582
2583 /* check that digitalSignature KeyUsage is present */
2584 X509_check_ca(reqctx->received_cert);
2585 if ((usage = X509_get_ext_d2i(reqctx->received_cert,
2586 NID_key_usage, NULL, NULL))) {
2587
2588 if (!ku_reject(reqctx->received_cert,
2589 X509v3_KU_DIGITAL_SIGNATURE)) {
2590 TRACE_PKINIT_EKU(context);
2591 *valid_eku = 1;
2592 } else
2593 TRACE_PKINIT_EKU_NO_KU(context);
2594 }
2595 ASN1_BIT_STRING_free(usage);
2596 }
2597 }
2598 retval = 0;
2599 cleanup:
2600 pkiDebug("%s: returning retval %d, valid_eku %d\n",
2601 __FUNCTION__, retval, *valid_eku);
2602 return retval;
2603 }
2604
2605 krb5_error_code
pkinit_octetstring2key(krb5_context context,krb5_enctype etype,unsigned char * key,unsigned int dh_key_len,krb5_keyblock * key_block)2606 pkinit_octetstring2key(krb5_context context,
2607 krb5_enctype etype,
2608 unsigned char *key,
2609 unsigned int dh_key_len,
2610 krb5_keyblock *key_block)
2611 {
2612 krb5_error_code retval;
2613 unsigned char *buf = NULL;
2614 unsigned char md[SHA_DIGEST_LENGTH];
2615 unsigned char counter;
2616 size_t keybytes, keylength, offset;
2617 krb5_data random_data;
2618 EVP_MD_CTX *sha1_ctx = NULL;
2619
2620 buf = k5alloc(dh_key_len, &retval);
2621 if (buf == NULL)
2622 goto cleanup;
2623
2624 sha1_ctx = EVP_MD_CTX_new();
2625 if (sha1_ctx == NULL) {
2626 retval = KRB5_CRYPTO_INTERNAL;
2627 goto cleanup;
2628 }
2629
2630 counter = 0;
2631 offset = 0;
2632 do {
2633 if (!EVP_DigestInit(sha1_ctx, EVP_sha1()) ||
2634 !EVP_DigestUpdate(sha1_ctx, &counter, 1) ||
2635 !EVP_DigestUpdate(sha1_ctx, key, dh_key_len) ||
2636 !EVP_DigestFinal(sha1_ctx, md, NULL)) {
2637 retval = KRB5_CRYPTO_INTERNAL;
2638 goto cleanup;
2639 }
2640
2641 if (dh_key_len - offset < sizeof(md))
2642 memcpy(buf + offset, md, dh_key_len - offset);
2643 else
2644 memcpy(buf + offset, md, sizeof(md));
2645
2646 offset += sizeof(md);
2647 counter++;
2648 } while (offset < dh_key_len);
2649
2650 key_block->magic = 0;
2651 key_block->enctype = etype;
2652
2653 retval = krb5_c_keylengths(context, etype, &keybytes, &keylength);
2654 if (retval)
2655 goto cleanup;
2656
2657 key_block->length = keylength;
2658 key_block->contents = k5alloc(keylength, &retval);
2659 if (key_block->contents == NULL)
2660 goto cleanup;
2661
2662 random_data.length = keybytes;
2663 random_data.data = (char *)buf;
2664
2665 retval = krb5_c_random_to_key(context, etype, &random_data, key_block);
2666
2667 cleanup:
2668 EVP_MD_CTX_free(sha1_ctx);
2669 free(buf);
2670 /* If this is an error return, free the allocated keyblock, if any */
2671 if (retval) {
2672 krb5_free_keyblock_contents(context, key_block);
2673 }
2674
2675 return retval;
2676 }
2677
2678
2679 /* Return the OpenSSL descriptor for the given RFC 5652 OID specified in RFC
2680 * 8636. RFC 8636 defines a SHA384 variant, but we don't use it. */
2681 static const EVP_MD *
algid_to_md(const krb5_data * alg_id)2682 algid_to_md(const krb5_data *alg_id)
2683 {
2684 if (data_eq(*alg_id, sha1_id))
2685 return EVP_sha1();
2686 if (data_eq(*alg_id, sha256_id))
2687 return EVP_sha256();
2688 if (data_eq(*alg_id, sha512_id))
2689 return EVP_sha512();
2690 return NULL;
2691 }
2692
2693 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
2694
2695 #define sskdf openssl_sskdf
2696 static krb5_error_code
openssl_sskdf(krb5_context context,const EVP_MD * md,krb5_data * key,krb5_data * info,size_t len,krb5_data * out)2697 openssl_sskdf(krb5_context context, const EVP_MD *md, krb5_data *key,
2698 krb5_data *info, size_t len, krb5_data *out)
2699 {
2700 krb5_error_code ret;
2701 EVP_KDF *kdf = NULL;
2702 EVP_KDF_CTX *kctx = NULL;
2703 OSSL_PARAM params[4], *p = params;
2704
2705 ret = alloc_data(out, len);
2706 if (ret)
2707 goto cleanup;
2708
2709 kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
2710 if (kdf == NULL) {
2711 ret = oerr(context, KRB5_CRYPTO_INTERNAL, _("Failed to fetch SSKDF"));
2712 goto cleanup;
2713 }
2714
2715 kctx = EVP_KDF_CTX_new(kdf);
2716 if (!kctx) {
2717 ret = oerr(context, KRB5_CRYPTO_INTERNAL,
2718 _("Failed to instantiate SSKDF"));
2719 goto cleanup;
2720 }
2721
2722 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
2723 (char *)EVP_MD_get0_name(md), 0);
2724 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
2725 key->data, key->length);
2726 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
2727 info->data, info->length);
2728 *p = OSSL_PARAM_construct_end();
2729 if (EVP_KDF_derive(kctx, (uint8_t *)out->data, len, params) <= 0) {
2730 ret = oerr(context, KRB5_CRYPTO_INTERNAL,
2731 _("Failed to derive key using SSKDF"));
2732 goto cleanup;
2733 }
2734
2735 ret = 0;
2736
2737 cleanup:
2738 EVP_KDF_free(kdf);
2739 EVP_KDF_CTX_free(kctx);
2740 return ret;
2741 }
2742
2743 #else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
2744
2745 #define sskdf builtin_sskdf
2746 static krb5_error_code
builtin_sskdf(krb5_context context,const EVP_MD * md,krb5_data * key,krb5_data * info,size_t len,krb5_data * out)2747 builtin_sskdf(krb5_context context, const EVP_MD *md, krb5_data *key,
2748 krb5_data *info, size_t len, krb5_data *out)
2749 {
2750 krb5_error_code ret;
2751 uint32_t counter = 1, reps;
2752 uint8_t be_counter[4], *outptr;
2753 EVP_MD_CTX *ctx = NULL;
2754 unsigned int s, hash_len;
2755
2756 hash_len = EVP_MD_size(md);
2757
2758 /* 1. reps = keydatalen (K) / hash length (H) rounded up. */
2759 reps = (len + hash_len - 1) / hash_len;
2760
2761 /* Allocate enough space in the random data buffer to hash directly into
2762 * it, even if the last hash will make it bigger than the key length. */
2763 ret = alloc_data(out, reps * hash_len);
2764 if (ret)
2765 goto cleanup;
2766 out->length = len;
2767
2768 /*
2769 * 2. Initialize a 32-bit, big-endian bit string counter as 1.
2770 * 3. For i = 1 to reps by 1, do the following:
2771 * - Compute Hashi = H(counter || Z || OtherInfo).
2772 * - Increment counter (modulo 2^32)
2773 * 4. Set key = Hash1 || Hash2 || ... so that length of key is K
2774 * bytes.
2775 */
2776 outptr = (uint8_t *)out->data;
2777 for (counter = 1; counter <= reps; counter++) {
2778 store_32_be(counter, be_counter);
2779
2780 ctx = EVP_MD_CTX_new();
2781 if (ctx == NULL) {
2782 ret = KRB5_CRYPTO_INTERNAL;
2783 goto cleanup;
2784 }
2785
2786 /* - Compute Hashi = H(counter || Z || OtherInfo). */
2787 if (!EVP_DigestInit(ctx, md) ||
2788 !EVP_DigestUpdate(ctx, be_counter, 4) ||
2789 !EVP_DigestUpdate(ctx, key->data, key->length) ||
2790 !EVP_DigestUpdate(ctx, info->data, info->length) ||
2791 !EVP_DigestFinal(ctx, outptr, &s)) {
2792 ret = oerr(context, KRB5_CRYPTO_INTERNAL,
2793 _("Failed to compute digest"));
2794 goto cleanup;
2795 }
2796
2797 assert(s == hash_len);
2798 outptr += s;
2799
2800 EVP_MD_CTX_free(ctx);
2801 ctx = NULL;
2802 }
2803
2804 cleanup:
2805 EVP_MD_CTX_free(ctx);
2806 return ret;
2807 }
2808
2809 #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
2810
2811 /* id-pkinit-kdf family, as specified by RFC 8636. */
2812 krb5_error_code
pkinit_alg_agility_kdf(krb5_context context,krb5_data * secret,krb5_data * alg_oid,krb5_const_principal party_u_info,krb5_const_principal party_v_info,krb5_enctype enctype,krb5_data * as_req,krb5_data * pk_as_rep,krb5_keyblock * key_block)2813 pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
2814 krb5_data *alg_oid, krb5_const_principal party_u_info,
2815 krb5_const_principal party_v_info,
2816 krb5_enctype enctype, krb5_data *as_req,
2817 krb5_data *pk_as_rep, krb5_keyblock *key_block)
2818 {
2819 krb5_error_code ret;
2820 size_t rand_len = 0, key_len = 0;
2821 const EVP_MD *md;
2822 krb5_sp80056a_other_info other_info_fields;
2823 krb5_pkinit_supp_pub_info supp_pub_info_fields;
2824 krb5_data *other_info = NULL, *supp_pub_info = NULL;
2825 krb5_data random_data = empty_data();
2826 krb5_algorithm_identifier alg_id;
2827 char *hash_name = NULL;
2828
2829 ret = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
2830 if (ret)
2831 goto cleanup;
2832
2833 /* Allocate and initialize the key block. */
2834 key_block->magic = 0;
2835 key_block->enctype = enctype;
2836 key_block->length = key_len;
2837 key_block->contents = k5calloc(key_block->length, 1, &ret);
2838 if (key_block->contents == NULL)
2839 goto cleanup;
2840
2841 /* If this is anonymous pkinit, use the anonymous principle for
2842 * party_u_info. */
2843 if (party_u_info &&
2844 krb5_principal_compare_any_realm(context, party_u_info,
2845 krb5_anonymous_principal())) {
2846 party_u_info = (krb5_principal)krb5_anonymous_principal();
2847 }
2848
2849 md = algid_to_md(alg_oid);
2850 if (md == NULL) {
2851 krb5_set_error_message(context, KRB5_ERR_BAD_S2K_PARAMS,
2852 "Bad algorithm ID passed to PK-INIT KDF.");
2853 return KRB5_ERR_BAD_S2K_PARAMS;
2854 }
2855
2856 /* Encode the ASN.1 octet string for "SuppPubInfo". */
2857 supp_pub_info_fields.enctype = enctype;
2858 supp_pub_info_fields.as_req = *as_req;
2859 supp_pub_info_fields.pk_as_rep = *pk_as_rep;
2860 ret = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
2861 &supp_pub_info);
2862 if (ret)
2863 goto cleanup;
2864
2865 /* Now encode the ASN.1 octet string for "OtherInfo". */
2866 memset(&alg_id, 0, sizeof(alg_id));
2867 alg_id.algorithm = *alg_oid;
2868 other_info_fields.algorithm_identifier = alg_id;
2869 other_info_fields.party_u_info = (krb5_principal)party_u_info;
2870 other_info_fields.party_v_info = (krb5_principal)party_v_info;
2871 other_info_fields.supp_pub_info = *supp_pub_info;
2872 ret = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
2873 if (ret)
2874 goto cleanup;
2875
2876 ret = sskdf(context, md, secret, other_info, rand_len, &random_data);
2877 if (ret)
2878 goto cleanup;
2879
2880 ret = krb5_c_random_to_key(context, enctype, &random_data, key_block);
2881
2882 cleanup:
2883 if (ret)
2884 krb5_free_keyblock_contents(context, key_block);
2885 free(hash_name);
2886 zapfree(random_data.data, random_data.length);
2887 krb5_free_data(context, other_info);
2888 krb5_free_data(context, supp_pub_info);
2889 return ret;
2890 }
2891
2892 krb5_error_code
client_create_dh(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int dh_size,krb5_data * spki_out)2893 client_create_dh(krb5_context context,
2894 pkinit_plg_crypto_context plg_cryptoctx,
2895 pkinit_req_crypto_context cryptoctx,
2896 pkinit_identity_crypto_context id_cryptoctx,
2897 int dh_size, krb5_data *spki_out)
2898 {
2899 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2900 EVP_PKEY *params = NULL, *pkey = NULL;
2901
2902 *spki_out = empty_data();
2903
2904 if (cryptoctx->received_params != NULL)
2905 params = cryptoctx->received_params;
2906 else if (dh_size == 1024)
2907 params = plg_cryptoctx->dh_1024;
2908 else if (dh_size == 2048)
2909 params = plg_cryptoctx->dh_2048;
2910 else if (dh_size == 4096)
2911 params = plg_cryptoctx->dh_4096;
2912 else
2913 goto cleanup;
2914
2915 pkey = generate_dh_pkey(params);
2916 if (pkey == NULL)
2917 goto cleanup;
2918
2919 retval = encode_spki(pkey, spki_out);
2920 if (retval)
2921 goto cleanup;
2922
2923 EVP_PKEY_free(cryptoctx->client_pkey);
2924 cryptoctx->client_pkey = pkey;
2925 pkey = NULL;
2926
2927 cleanup:
2928 EVP_PKEY_free(pkey);
2929 return retval;
2930 }
2931
2932 krb5_error_code
client_process_dh(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char * subjectPublicKey_data,unsigned int subjectPublicKey_length,unsigned char ** client_key_out,unsigned int * client_key_len_out)2933 client_process_dh(krb5_context context,
2934 pkinit_plg_crypto_context plg_cryptoctx,
2935 pkinit_req_crypto_context cryptoctx,
2936 pkinit_identity_crypto_context id_cryptoctx,
2937 unsigned char *subjectPublicKey_data,
2938 unsigned int subjectPublicKey_length,
2939 unsigned char **client_key_out,
2940 unsigned int *client_key_len_out)
2941 {
2942 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2943 EVP_PKEY *server_pkey = NULL;
2944 uint8_t *client_key = NULL;
2945 unsigned int client_key_len;
2946
2947 *client_key_out = NULL;
2948 *client_key_len_out = 0;
2949
2950 server_pkey = compose_dh_pkey(cryptoctx->client_pkey,
2951 subjectPublicKey_data,
2952 subjectPublicKey_length);
2953 if (server_pkey == NULL)
2954 goto cleanup;
2955
2956 if (!dh_result(cryptoctx->client_pkey, server_pkey,
2957 &client_key, &client_key_len))
2958 goto cleanup;
2959
2960 #ifdef DEBUG_DH
2961 print_pubkey(server_pub_key, "server's pub_key=");
2962 pkiDebug("client computed key (%d)= ", client_key_len);
2963 print_buffer(client_key, client_key_len);
2964 #endif
2965
2966 *client_key_out = client_key;
2967 *client_key_len_out = client_key_len;
2968 client_key = NULL;
2969
2970 retval = 0;
2971
2972 cleanup:
2973 EVP_PKEY_free(server_pkey);
2974 free(client_key);
2975 return retval;
2976 }
2977
2978 /* Return 1 if dh is a permitted well-known group, otherwise return 0. */
2979 static int
check_dh_wellknown(pkinit_plg_crypto_context cryptoctx,EVP_PKEY * pkey,int nbits)2980 check_dh_wellknown(pkinit_plg_crypto_context cryptoctx, EVP_PKEY *pkey,
2981 int nbits)
2982 {
2983 if (nbits == 1024)
2984 return EVP_PKEY_parameters_eq(cryptoctx->dh_1024, pkey) == 1;
2985 else if (nbits == 2048)
2986 return EVP_PKEY_parameters_eq(cryptoctx->dh_2048, pkey) == 1;
2987 else if (nbits == 4096)
2988 return EVP_PKEY_parameters_eq(cryptoctx->dh_4096, pkey) == 1;
2989 return 0;
2990 }
2991
2992 krb5_error_code
server_check_dh(krb5_context context,pkinit_plg_crypto_context cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,const krb5_data * client_spki,int minbits)2993 server_check_dh(krb5_context context,
2994 pkinit_plg_crypto_context cryptoctx,
2995 pkinit_req_crypto_context req_cryptoctx,
2996 pkinit_identity_crypto_context id_cryptoctx,
2997 const krb5_data *client_spki,
2998 int minbits)
2999 {
3000 EVP_PKEY *client_pkey = NULL;
3001 int dh_prime_bits;
3002 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3003
3004 client_pkey = decode_spki(client_spki);
3005 if (client_pkey == NULL) {
3006 pkiDebug("failed to decode dhparams\n");
3007 goto cleanup;
3008 }
3009
3010 /* KDC SHOULD check to see if the key parameters satisfy its policy */
3011 dh_prime_bits = EVP_PKEY_get_bits(client_pkey);
3012 if (minbits && dh_prime_bits < minbits) {
3013 pkiDebug("client sent dh params with %d bits, we require %d\n",
3014 dh_prime_bits, minbits);
3015 goto cleanup;
3016 }
3017
3018 if (check_dh_wellknown(cryptoctx, client_pkey, dh_prime_bits))
3019 retval = 0;
3020
3021 cleanup:
3022 if (retval == 0)
3023 req_cryptoctx->client_pkey = client_pkey;
3024 else
3025 EVP_PKEY_free(client_pkey);
3026
3027 return retval;
3028 }
3029
3030 /* kdc's dh function */
3031 krb5_error_code
server_process_dh(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char ** dh_pubkey_out,unsigned int * dh_pubkey_len_out,unsigned char ** server_key_out,unsigned int * server_key_len_out)3032 server_process_dh(krb5_context context,
3033 pkinit_plg_crypto_context plg_cryptoctx,
3034 pkinit_req_crypto_context cryptoctx,
3035 pkinit_identity_crypto_context id_cryptoctx,
3036 unsigned char **dh_pubkey_out,
3037 unsigned int *dh_pubkey_len_out,
3038 unsigned char **server_key_out,
3039 unsigned int *server_key_len_out)
3040 {
3041 krb5_error_code retval = ENOMEM;
3042 EVP_PKEY *server_pkey = NULL;
3043 unsigned char *dh_pubkey = NULL, *server_key = NULL;
3044 unsigned int dh_pubkey_len = 0, server_key_len = 0;
3045
3046 *dh_pubkey_out = *server_key_out = NULL;
3047 *dh_pubkey_len_out = *server_key_len_out = 0;
3048
3049 /* Generate a server DH key with the same parameters as the client key. */
3050 server_pkey = generate_dh_pkey(cryptoctx->client_pkey);
3051 if (server_pkey == NULL)
3052 goto cleanup;
3053
3054 if (!dh_result(server_pkey, cryptoctx->client_pkey, &server_key,
3055 &server_key_len))
3056 goto cleanup;
3057
3058 if (!dh_pubkey_der(server_pkey, &dh_pubkey, &dh_pubkey_len))
3059 goto cleanup;
3060
3061 *dh_pubkey_out = dh_pubkey;
3062 *dh_pubkey_len_out = dh_pubkey_len;
3063 *server_key_out = server_key;
3064 *server_key_len_out = server_key_len;
3065 dh_pubkey = server_key = NULL;
3066
3067 retval = 0;
3068
3069 cleanup:
3070 EVP_PKEY_free(server_pkey);
3071 free(dh_pubkey);
3072 free(server_key);
3073
3074 return retval;
3075 }
3076
3077 int
pkinit_openssl_init()3078 pkinit_openssl_init()
3079 {
3080 /* Initialize OpenSSL. */
3081 ERR_load_crypto_strings();
3082 OpenSSL_add_all_algorithms();
3083 return 0;
3084 }
3085
3086 static krb5_error_code
pkinit_create_sequence_of_principal_identifiers(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int type,krb5_pa_data *** e_data_out)3087 pkinit_create_sequence_of_principal_identifiers(
3088 krb5_context context,
3089 pkinit_plg_crypto_context plg_cryptoctx,
3090 pkinit_req_crypto_context req_cryptoctx,
3091 pkinit_identity_crypto_context id_cryptoctx,
3092 int type,
3093 krb5_pa_data ***e_data_out)
3094 {
3095 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
3096 krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
3097 krb5_data *td_certifiers = NULL;
3098 krb5_pa_data **pa_data = NULL;
3099
3100 switch(type) {
3101 case TD_TRUSTED_CERTIFIERS:
3102 retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
3103 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
3104 if (retval) {
3105 pkiDebug("create_krb5_trustedCertifiers failed\n");
3106 goto cleanup;
3107 }
3108 break;
3109 case TD_INVALID_CERTIFICATES:
3110 retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
3111 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
3112 if (retval) {
3113 pkiDebug("create_krb5_invalidCertificates failed\n");
3114 goto cleanup;
3115 }
3116 break;
3117 default:
3118 retval = -1;
3119 goto cleanup;
3120 }
3121
3122 retval = k5int_encode_krb5_td_trusted_certifiers((krb5_external_principal_identifier *const *)krb5_trusted_certifiers, &td_certifiers);
3123 if (retval) {
3124 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
3125 goto cleanup;
3126 }
3127 #ifdef DEBUG_ASN1
3128 print_buffer_bin((unsigned char *)td_certifiers->data,
3129 td_certifiers->length, "/tmp/kdc_td_certifiers");
3130 #endif
3131 pa_data = malloc(2 * sizeof(krb5_pa_data *));
3132 if (pa_data == NULL) {
3133 retval = ENOMEM;
3134 goto cleanup;
3135 }
3136 pa_data[1] = NULL;
3137 pa_data[0] = malloc(sizeof(krb5_pa_data));
3138 if (pa_data[0] == NULL) {
3139 free(pa_data);
3140 retval = ENOMEM;
3141 goto cleanup;
3142 }
3143 pa_data[0]->pa_type = type;
3144 pa_data[0]->length = td_certifiers->length;
3145 pa_data[0]->contents = (krb5_octet *)td_certifiers->data;
3146 *e_data_out = pa_data;
3147 retval = 0;
3148
3149 cleanup:
3150 if (krb5_trusted_certifiers != NULL)
3151 free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
3152 free(td_certifiers);
3153 return retval;
3154 }
3155
3156 krb5_error_code
pkinit_create_td_trusted_certifiers(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_pa_data *** e_data_out)3157 pkinit_create_td_trusted_certifiers(krb5_context context,
3158 pkinit_plg_crypto_context plg_cryptoctx,
3159 pkinit_req_crypto_context req_cryptoctx,
3160 pkinit_identity_crypto_context id_cryptoctx,
3161 krb5_pa_data ***e_data_out)
3162 {
3163 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
3164
3165 retval = pkinit_create_sequence_of_principal_identifiers(context,
3166 plg_cryptoctx, req_cryptoctx, id_cryptoctx,
3167 TD_TRUSTED_CERTIFIERS, e_data_out);
3168
3169 return retval;
3170 }
3171
3172 krb5_error_code
pkinit_create_td_invalid_certificate(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_pa_data *** e_data_out)3173 pkinit_create_td_invalid_certificate(
3174 krb5_context context,
3175 pkinit_plg_crypto_context plg_cryptoctx,
3176 pkinit_req_crypto_context req_cryptoctx,
3177 pkinit_identity_crypto_context id_cryptoctx,
3178 krb5_pa_data ***e_data_out)
3179 {
3180 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
3181
3182 retval = pkinit_create_sequence_of_principal_identifiers(context,
3183 plg_cryptoctx, req_cryptoctx, id_cryptoctx,
3184 TD_INVALID_CERTIFICATES, e_data_out);
3185
3186 return retval;
3187 }
3188
3189 krb5_error_code
pkinit_create_td_dh_parameters(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,pkinit_plg_opts * opts,krb5_pa_data *** e_data_out)3190 pkinit_create_td_dh_parameters(krb5_context context,
3191 pkinit_plg_crypto_context plg_cryptoctx,
3192 pkinit_req_crypto_context req_cryptoctx,
3193 pkinit_identity_crypto_context id_cryptoctx,
3194 pkinit_plg_opts *opts,
3195 krb5_pa_data ***e_data_out)
3196 {
3197 krb5_error_code ret;
3198 int i;
3199 krb5_pa_data **pa_data = NULL;
3200 krb5_data *der_alglist = NULL;
3201 krb5_algorithm_identifier alg_1024 = { dh_oid, oakley_1024 };
3202 krb5_algorithm_identifier alg_2048 = { dh_oid, oakley_2048 };
3203 krb5_algorithm_identifier alg_4096 = { dh_oid, oakley_4096 };
3204 krb5_algorithm_identifier *alglist[4];
3205
3206 if (opts->dh_min_bits > 4096) {
3207 ret = KRB5KRB_ERR_GENERIC;
3208 goto cleanup;
3209 }
3210
3211 i = 0;
3212 if (opts->dh_min_bits <= 2048)
3213 alglist[i++] = &alg_2048;
3214 alglist[i++] = &alg_4096;
3215 if (opts->dh_min_bits <= 1024)
3216 alglist[i++] = &alg_1024;
3217 alglist[i] = NULL;
3218
3219 ret = k5int_encode_krb5_td_dh_parameters(alglist, &der_alglist);
3220 if (ret)
3221 goto cleanup;
3222
3223 pa_data = k5calloc(2, sizeof(*pa_data), &ret);
3224 if (pa_data == NULL)
3225 goto cleanup;
3226 pa_data[1] = NULL;
3227 pa_data[0] = k5alloc(sizeof(*pa_data[0]), &ret);
3228 if (pa_data[0] == NULL) {
3229 free(pa_data);
3230 goto cleanup;
3231 }
3232 pa_data[0]->pa_type = TD_DH_PARAMETERS;
3233 pa_data[0]->length = der_alglist->length;
3234 pa_data[0]->contents = (krb5_octet *)der_alglist->data;
3235 der_alglist->data = NULL;
3236 *e_data_out = pa_data;
3237
3238 cleanup:
3239 krb5_free_data(context, der_alglist);
3240 return ret;
3241 }
3242
3243 krb5_error_code
pkinit_check_kdc_pkid(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char * pdid_buf,unsigned int pkid_len,int * valid_kdcPkId)3244 pkinit_check_kdc_pkid(krb5_context context,
3245 pkinit_plg_crypto_context plg_cryptoctx,
3246 pkinit_req_crypto_context req_cryptoctx,
3247 pkinit_identity_crypto_context id_cryptoctx,
3248 unsigned char *pdid_buf,
3249 unsigned int pkid_len,
3250 int *valid_kdcPkId)
3251 {
3252 PKCS7_ISSUER_AND_SERIAL *is = NULL;
3253 const unsigned char *p = pdid_buf;
3254 int status = 1;
3255 X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
3256
3257 *valid_kdcPkId = 0;
3258 pkiDebug("found kdcPkId in AS REQ\n");
3259 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
3260 if (is == NULL)
3261 return KRB5KDC_ERR_PREAUTH_FAILED;
3262
3263 status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
3264 if (!status) {
3265 status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
3266 if (!status)
3267 *valid_kdcPkId = 1;
3268 }
3269
3270 X509_NAME_free(is->issuer);
3271 ASN1_INTEGER_free(is->serial);
3272 free(is);
3273
3274 return 0;
3275 }
3276
3277 krb5_error_code
pkinit_process_td_dh_params(krb5_context context,pkinit_plg_crypto_context cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_algorithm_identifier ** algId,int * new_dh_size)3278 pkinit_process_td_dh_params(krb5_context context,
3279 pkinit_plg_crypto_context cryptoctx,
3280 pkinit_req_crypto_context req_cryptoctx,
3281 pkinit_identity_crypto_context id_cryptoctx,
3282 krb5_algorithm_identifier **algId,
3283 int *new_dh_size)
3284 {
3285 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3286 EVP_PKEY *params = NULL;
3287 int i, dh_prime_bits, old_dh_size;
3288
3289 pkiDebug("dh parameters\n");
3290
3291 EVP_PKEY_free(req_cryptoctx->received_params);
3292 req_cryptoctx->received_params = NULL;
3293
3294 old_dh_size = *new_dh_size;
3295
3296 for (i = 0; algId[i] != NULL; i++) {
3297 /* Free any parameters from the previous iteration. */
3298 EVP_PKEY_free(params);
3299 params = NULL;
3300
3301 /* Skip any parameters for algorithms other than DH. */
3302 if (algId[i]->algorithm.length != dh_oid.length ||
3303 memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
3304 continue;
3305
3306 params = decode_dh_params(&algId[i]->parameters);
3307 if (params == NULL)
3308 continue;
3309 dh_prime_bits = EVP_PKEY_get_bits(params);
3310 /* Skip any parameters shorter than the previous size. */
3311 if (dh_prime_bits < old_dh_size)
3312 continue;
3313 pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
3314 *new_dh_size, dh_prime_bits);
3315
3316 /* If this is one of our well-known groups, just save the new size; we
3317 * will use our own copy of the parameters. */
3318 if (check_dh_wellknown(cryptoctx, params, dh_prime_bits)) {
3319 *new_dh_size = dh_prime_bits;
3320 retval = 0;
3321 goto cleanup;
3322 }
3323
3324 /* If the parameters aren't well-known but check out, save them. */
3325 if (params_valid(params)) {
3326 req_cryptoctx->received_params = params;
3327 params = NULL;
3328 retval = 0;
3329 goto cleanup;
3330 }
3331 }
3332
3333 cleanup:
3334 EVP_PKEY_free(params);
3335 return retval;
3336 }
3337
3338 static int
openssl_callback(int ok,X509_STORE_CTX * ctx)3339 openssl_callback(int ok, X509_STORE_CTX * ctx)
3340 {
3341 #ifdef DEBUG
3342 if (!ok) {
3343 X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
3344 int err = X509_STORE_CTX_get_error(ctx);
3345 const char *errmsg = X509_verify_cert_error_string(err);
3346 char buf[DN_BUF_LEN];
3347
3348 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
3349 pkiDebug("cert = %s\n", buf);
3350 pkiDebug("callback function: %d (%s)\n", err, errmsg);
3351 }
3352 #endif
3353 return ok;
3354 }
3355
3356 static int
openssl_callback_ignore_crls(int ok,X509_STORE_CTX * ctx)3357 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
3358 {
3359 if (ok)
3360 return ok;
3361 return X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL;
3362 }
3363
3364 static ASN1_OBJECT *
pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx,int pkcs7_type)3365 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
3366 {
3367 switch (pkcs7_type) {
3368 case CMS_SIGN_CLIENT:
3369 return cryptoctx->id_pkinit_authData;
3370 case CMS_SIGN_SERVER:
3371 return cryptoctx->id_pkinit_DHKeyData;
3372 case CMS_ENVEL_SERVER:
3373 return cryptoctx->id_pkinit_rkeyData;
3374 default:
3375 return NULL;
3376 }
3377
3378 }
3379
3380 static int
wrap_signeddata(unsigned char * data,unsigned int data_len,unsigned char ** out,unsigned int * out_len)3381 wrap_signeddata(unsigned char *data, unsigned int data_len,
3382 unsigned char **out, unsigned int *out_len)
3383 {
3384
3385 unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
3386 ASN1_OBJECT *oid = NULL;
3387 unsigned char *p = NULL;
3388
3389 /* Get length to wrap the original data with SEQUENCE tag */
3390 tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
3391
3392 /* Add the signedData OID and adjust lengths */
3393 oid = OBJ_nid2obj(NID_pkcs7_signed);
3394 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3395
3396 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
3397
3398 p = *out = malloc(tot_len);
3399 if (p == NULL) return -1;
3400
3401 ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
3402 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3403
3404 i2d_ASN1_OBJECT(oid, &p);
3405
3406 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3407 memcpy(p, data, data_len);
3408
3409 *out_len = tot_len;
3410
3411 return 0;
3412 }
3413
3414 static int
prepare_enc_data(const uint8_t * indata,int indata_len,uint8_t ** outdata,int * outdata_len)3415 prepare_enc_data(const uint8_t *indata, int indata_len, uint8_t **outdata,
3416 int *outdata_len)
3417 {
3418 int tag, class;
3419 long tlen, slen;
3420 const uint8_t *p = indata, *oldp;
3421
3422 if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80)
3423 return EINVAL;
3424 if (tag != V_ASN1_SEQUENCE)
3425 return EINVAL;
3426
3427 oldp = p;
3428 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3429 return EINVAL;
3430 p += tlen;
3431 slen -= (p - oldp);
3432
3433 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3434 return EINVAL;
3435
3436 *outdata = malloc(tlen);
3437 if (*outdata == NULL)
3438 return ENOMEM;
3439 memcpy(*outdata, p, tlen);
3440 *outdata_len = tlen;
3441 return 0;
3442 }
3443
3444 #ifndef WITHOUT_PKCS11
3445 static struct plugin_file_handle *
load_pkcs11_module(krb5_context context,const char * modname,CK_FUNCTION_LIST_PTR_PTR p11p)3446 load_pkcs11_module(krb5_context context, const char *modname,
3447 CK_FUNCTION_LIST_PTR_PTR p11p)
3448 {
3449 struct plugin_file_handle *handle = NULL;
3450 CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
3451 struct errinfo einfo = EMPTY_ERRINFO;
3452 const char *errmsg = NULL;
3453 void (*sym)();
3454 long err;
3455 CK_RV rv;
3456
3457 TRACE_PKINIT_PKCS11_OPEN(context, modname);
3458 err = krb5int_open_plugin(modname, &handle, &einfo);
3459 if (err) {
3460 errmsg = k5_get_error(&einfo, err);
3461 TRACE_PKINIT_PKCS11_OPEN_FAILED(context, errmsg);
3462 goto error;
3463 }
3464
3465 err = krb5int_get_plugin_func(handle, "C_GetFunctionList", &sym, &einfo);
3466 if (err) {
3467 errmsg = k5_get_error(&einfo, err);
3468 TRACE_PKINIT_PKCS11_GETSYM_FAILED(context, errmsg);
3469 goto error;
3470 }
3471
3472 getflist = (CK_RV (*)())sym;
3473 rv = (*getflist)(p11p);
3474 if (rv != CKR_OK) {
3475 TRACE_PKINIT_PKCS11_GETFLIST_FAILED(context, pkcs11err(rv));
3476 goto error;
3477 }
3478
3479 return handle;
3480
3481 error:
3482 k5_free_error(&einfo, errmsg);
3483 k5_clear_error(&einfo);
3484 if (handle != NULL)
3485 krb5int_close_plugin(handle);
3486 return NULL;
3487 }
3488
3489 static krb5_error_code
pkinit_login(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,CK_TOKEN_INFO * tip,const char * password)3490 pkinit_login(krb5_context context,
3491 pkinit_identity_crypto_context id_cryptoctx,
3492 CK_TOKEN_INFO *tip, const char *password)
3493 {
3494 krb5_data rdat;
3495 char *prompt;
3496 const char *warning;
3497 krb5_prompt kprompt;
3498 krb5_prompt_type prompt_type;
3499 int r = 0;
3500
3501 if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
3502 rdat.data = NULL;
3503 rdat.length = 0;
3504 } else if (password != NULL) {
3505 rdat.data = strdup(password);
3506 rdat.length = strlen(password);
3507 } else if (id_cryptoctx->prompter == NULL) {
3508 r = KRB5_LIBOS_CANTREADPWD;
3509 rdat.data = NULL;
3510 } else {
3511 if (tip->flags & CKF_USER_PIN_LOCKED)
3512 warning = " (Warning: PIN locked)";
3513 else if (tip->flags & CKF_USER_PIN_FINAL_TRY)
3514 warning = " (Warning: PIN final try)";
3515 else if (tip->flags & CKF_USER_PIN_COUNT_LOW)
3516 warning = " (Warning: PIN count low)";
3517 else
3518 warning = "";
3519 if (asprintf(&prompt, "%.*s PIN%s", (int) sizeof (tip->label),
3520 tip->label, warning) < 0)
3521 return ENOMEM;
3522 rdat.data = malloc(tip->ulMaxPinLen + 2);
3523 rdat.length = tip->ulMaxPinLen + 1;
3524
3525 kprompt.prompt = prompt;
3526 kprompt.hidden = 1;
3527 kprompt.reply = &rdat;
3528 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
3529
3530 /* PROMPTER_INVOCATION */
3531 k5int_set_prompt_types(context, &prompt_type);
3532 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
3533 NULL, NULL, 1, &kprompt);
3534 k5int_set_prompt_types(context, 0);
3535 free(prompt);
3536 }
3537
3538 if (r == 0) {
3539 r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
3540 (u_char *) rdat.data, rdat.length);
3541
3542 if (r != CKR_OK) {
3543 TRACE_PKINIT_PKCS11_LOGIN_FAILED(context, pkcs11err(r));
3544 r = KRB5KDC_ERR_PREAUTH_FAILED;
3545 }
3546 }
3547 free(rdat.data);
3548
3549 return r;
3550 }
3551
3552 static krb5_error_code
pkinit_open_session(krb5_context context,pkinit_identity_crypto_context cctx)3553 pkinit_open_session(krb5_context context,
3554 pkinit_identity_crypto_context cctx)
3555 {
3556 CK_ULONG i, pret;
3557 unsigned char *cp;
3558 size_t label_len;
3559 CK_ULONG count = 0;
3560 CK_SLOT_ID_PTR slotlist = NULL;
3561 CK_TOKEN_INFO tinfo;
3562 char *p11name = NULL;
3563 const char *password;
3564 krb5_error_code ret;
3565
3566 if (cctx->p11_module != NULL)
3567 return 0; /* session already open */
3568
3569 /* Load module */
3570 cctx->p11_module = load_pkcs11_module(context, cctx->p11_module_name,
3571 &cctx->p11);
3572 if (cctx->p11_module == NULL)
3573 return KRB5KDC_ERR_PREAUTH_FAILED;
3574
3575 /* Init */
3576 pret = cctx->p11->C_Initialize(NULL);
3577 if (pret != CKR_OK) {
3578 pkiDebug("C_Initialize: %s\n", pkcs11err(pret));
3579 return KRB5KDC_ERR_PREAUTH_FAILED;
3580 }
3581
3582 /* Get the list of available slots */
3583 if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK)
3584 return KRB5KDC_ERR_PREAUTH_FAILED;
3585 if (count == 0) {
3586 TRACE_PKINIT_PKCS11_NO_TOKEN(context);
3587 return KRB5KDC_ERR_PREAUTH_FAILED;
3588 }
3589 slotlist = calloc(count, sizeof(CK_SLOT_ID));
3590 if (slotlist == NULL)
3591 return ENOMEM;
3592 if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) {
3593 ret = KRB5KDC_ERR_PREAUTH_FAILED;
3594 goto cleanup;
3595 }
3596
3597 /* Look for the given token label, or if none given take the first one */
3598 for (i = 0; i < count; i++) {
3599 /* Skip slots that don't match the specified slotid, if given. */
3600 if (cctx->slotid != PK_NOSLOT && cctx->slotid != slotlist[i])
3601 continue;
3602
3603 /* Open session */
3604 pret = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
3605 NULL, NULL, &cctx->session);
3606 if (pret != CKR_OK) {
3607 pkiDebug("C_OpenSession: %s\n", pkcs11err(pret));
3608 ret = KRB5KDC_ERR_PREAUTH_FAILED;
3609 goto cleanup;
3610 }
3611
3612 /* Get token info */
3613 pret = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo);
3614 if (pret != CKR_OK) {
3615 pkiDebug("C_GetTokenInfo: %s\n", pkcs11err(pret));
3616 ret = KRB5KDC_ERR_PREAUTH_FAILED;
3617 goto cleanup;
3618 }
3619
3620 /* tinfo.label is zero-filled but not necessarily zero-terminated.
3621 * Find the length, ignoring any trailing spaces. */
3622 for (cp = tinfo.label + sizeof(tinfo.label); cp > tinfo.label; cp--) {
3623 if (cp[-1] != '\0' && cp[-1] != ' ')
3624 break;
3625 }
3626 label_len = cp - tinfo.label;
3627
3628 TRACE_PKINIT_PKCS11_SLOT(context, (int)slotlist[i], (int)label_len,
3629 tinfo.label);
3630 if (cctx->token_label == NULL ||
3631 (strlen(cctx->token_label) == label_len &&
3632 memcmp(cctx->token_label, tinfo.label, label_len) == 0))
3633 break;
3634 cctx->p11->C_CloseSession(cctx->session);
3635 }
3636 if (i >= count) {
3637 TRACE_PKINIT_PKCS11_NO_MATCH_TOKEN(context);
3638 ret = KRB5KDC_ERR_PREAUTH_FAILED;
3639 goto cleanup;
3640 }
3641 cctx->slotid = slotlist[i];
3642 pkiDebug("open_session: slotid %d (%lu of %d)\n", (int)cctx->slotid,
3643 i + 1, (int) count);
3644
3645 /* Login if needed */
3646 if (tinfo.flags & CKF_LOGIN_REQUIRED) {
3647 if (cctx->p11_module_name != NULL) {
3648 if (cctx->slotid != PK_NOSLOT) {
3649 if (asprintf(&p11name,
3650 "PKCS11:module_name=%s:slotid=%ld:token=%.*s",
3651 cctx->p11_module_name, (long)cctx->slotid,
3652 (int)label_len, tinfo.label) < 0)
3653 p11name = NULL;
3654 } else {
3655 if (asprintf(&p11name,
3656 "PKCS11:module_name=%s,token=%.*s",
3657 cctx->p11_module_name,
3658 (int)label_len, tinfo.label) < 0)
3659 p11name = NULL;
3660 }
3661 }
3662 if (cctx->defer_id_prompt) {
3663 /* Supply the identity name to be passed to the responder. */
3664 pkinit_set_deferred_id(&cctx->deferred_ids,
3665 p11name, tinfo.flags, NULL);
3666 ret = 0;
3667 goto cleanup;
3668 }
3669 /* Look up a responder-supplied password for the token. */
3670 password = pkinit_find_deferred_id(cctx->deferred_ids, p11name);
3671 ret = pkinit_login(context, cctx, &tinfo, password);
3672 if (ret)
3673 goto cleanup;
3674 }
3675
3676 ret = 0;
3677 cleanup:
3678 free(slotlist);
3679 free(p11name);
3680 return ret;
3681 }
3682
3683 /*
3684 * Look for a key that's:
3685 * 1. private
3686 * 2. capable of the specified operation (usually signing or decrypting)
3687 * 3. RSA (this may be wrong but it's all we can do for now)
3688 * 4. matches the id of the cert we chose
3689 *
3690 * You must call pkinit_get_certs before calling pkinit_find_private_key
3691 * (that's because we need the ID of the private key)
3692 *
3693 * pkcs11 says the id of the key doesn't have to match that of the cert, but
3694 * I can't figure out any other way to decide which key to use.
3695 *
3696 * We should only find one key that fits all the requirements.
3697 * If there are more than one, we just take the first one.
3698 */
3699
3700 krb5_error_code
pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,CK_ATTRIBUTE_TYPE usage,CK_OBJECT_HANDLE * objp)3701 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
3702 CK_ATTRIBUTE_TYPE usage,
3703 CK_OBJECT_HANDLE *objp)
3704 {
3705 CK_OBJECT_CLASS cls;
3706 CK_ATTRIBUTE attrs[4];
3707 CK_ULONG count;
3708 CK_KEY_TYPE keytype;
3709 unsigned int nattrs = 0;
3710 int r;
3711 #ifdef PKINIT_USE_KEY_USAGE
3712 CK_BBOOL true_false;
3713 #endif
3714
3715 cls = CKO_PRIVATE_KEY;
3716 attrs[nattrs].type = CKA_CLASS;
3717 attrs[nattrs].pValue = &cls;
3718 attrs[nattrs].ulValueLen = sizeof cls;
3719 nattrs++;
3720
3721 #ifdef PKINIT_USE_KEY_USAGE
3722 /*
3723 * Some cards get confused if you try to specify a key usage,
3724 * so don't, and hope for the best. This will fail if you have
3725 * several keys with the same id and different usages but I have
3726 * not seen this on real cards.
3727 */
3728 true_false = TRUE;
3729 attrs[nattrs].type = usage;
3730 attrs[nattrs].pValue = &true_false;
3731 attrs[nattrs].ulValueLen = sizeof true_false;
3732 nattrs++;
3733 #endif
3734
3735 keytype = CKK_RSA;
3736 attrs[nattrs].type = CKA_KEY_TYPE;
3737 attrs[nattrs].pValue = &keytype;
3738 attrs[nattrs].ulValueLen = sizeof keytype;
3739 nattrs++;
3740
3741 attrs[nattrs].type = CKA_ID;
3742 attrs[nattrs].pValue = id_cryptoctx->cert_id;
3743 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
3744 nattrs++;
3745
3746 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
3747 if (r != CKR_OK) {
3748 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
3749 pkcs11err(r));
3750 return KRB5KDC_ERR_PREAUTH_FAILED;
3751 }
3752
3753 r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
3754 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
3755 pkiDebug("found %d private keys (%s)\n", (int)count, pkcs11err(r));
3756 if (r != CKR_OK || count < 1)
3757 return KRB5KDC_ERR_PREAUTH_FAILED;
3758 return 0;
3759 }
3760 #endif
3761
3762 static krb5_error_code
pkinit_decode_data_fs(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,const uint8_t * data,unsigned int data_len,uint8_t ** decoded_data,unsigned int * decoded_data_len)3763 pkinit_decode_data_fs(krb5_context context,
3764 pkinit_identity_crypto_context id_cryptoctx,
3765 const uint8_t *data, unsigned int data_len,
3766 uint8_t **decoded_data, unsigned int *decoded_data_len)
3767 {
3768 X509 *cert = sk_X509_value(id_cryptoctx->my_certs,
3769 id_cryptoctx->cert_index);
3770 EVP_PKEY *pkey = id_cryptoctx->my_key;
3771 EVP_PKEY_CTX *ctx = NULL;
3772 uint8_t *buf = NULL;
3773 size_t buf_len = 0;
3774 int ok;
3775
3776 *decoded_data = NULL;
3777 *decoded_data_len = 0;
3778
3779 if (cert != NULL && !X509_check_private_key(cert, pkey)) {
3780 pkiDebug("private key does not match certificate\n");
3781 return KRB5KDC_ERR_PREAUTH_FAILED;
3782 }
3783
3784 ctx = EVP_PKEY_CTX_new(pkey, NULL);
3785 if (ctx == NULL)
3786 return KRB5KDC_ERR_PREAUTH_FAILED;
3787
3788 ok = EVP_PKEY_decrypt_init(ctx);
3789 if (!ok)
3790 goto cleanup;
3791
3792 /* Get the length of the eventual output. */
3793 ok = EVP_PKEY_decrypt(ctx, NULL, &buf_len, data, data_len);
3794 if (!ok) {
3795 pkiDebug("unable to decrypt received data\n");
3796 goto cleanup;
3797 }
3798
3799 buf = malloc(buf_len);
3800 if (buf == NULL) {
3801 ok = 0;
3802 goto cleanup;
3803 }
3804
3805 ok = EVP_PKEY_decrypt(ctx, buf, &buf_len, data, data_len);
3806 if (!ok) {
3807 pkiDebug("unable to decrypt received data\n");
3808 goto cleanup;
3809 }
3810
3811 *decoded_data = buf;
3812 *decoded_data_len = buf_len;
3813 buf = NULL;
3814 cleanup:
3815 zapfree(buf, buf_len);
3816 EVP_PKEY_CTX_free(ctx);
3817 return ok ? 0 : KRB5KDC_ERR_PREAUTH_FAILED;
3818 }
3819
3820 #ifndef WITHOUT_PKCS11
3821 /*
3822 * When using the ActivCard Linux pkcs11 library (v2.0.1), the decrypt function
3823 * fails. By inserting an extra function call, which serves nothing but to
3824 * change the stack, we were able to work around the issue. If the ActivCard
3825 * library is fixed in the future, this function can be inlined back into the
3826 * caller.
3827 */
3828 static CK_RV
pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)3829 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,
3830 CK_BYTE_PTR pEncryptedData,
3831 CK_ULONG ulEncryptedDataLen,
3832 CK_BYTE_PTR pData,
3833 CK_ULONG_PTR pulDataLen)
3834 {
3835 CK_RV rv = CKR_OK;
3836
3837 rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData,
3838 ulEncryptedDataLen, pData, pulDataLen);
3839 if (rv == CKR_OK) {
3840 pkiDebug("pData %p *pulDataLen %d\n", (void *) pData,
3841 (int) *pulDataLen);
3842 }
3843 return rv;
3844 }
3845
3846 static krb5_error_code
pkinit_decode_data_pkcs11(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,const uint8_t * data,unsigned int data_len,uint8_t ** decoded_data,unsigned int * decoded_data_len)3847 pkinit_decode_data_pkcs11(krb5_context context,
3848 pkinit_identity_crypto_context id_cryptoctx,
3849 const uint8_t *data, unsigned int data_len,
3850 uint8_t **decoded_data,
3851 unsigned int *decoded_data_len)
3852 {
3853 CK_OBJECT_HANDLE obj;
3854 CK_ULONG len;
3855 CK_MECHANISM mech;
3856 uint8_t *cp;
3857 int r;
3858
3859 *decoded_data = NULL;
3860 *decoded_data_len = 0;
3861
3862 if (pkinit_open_session(context, id_cryptoctx)) {
3863 pkiDebug("can't open pkcs11 session\n");
3864 return KRB5KDC_ERR_PREAUTH_FAILED;
3865 }
3866
3867 pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj);
3868
3869 mech.mechanism = CKM_RSA_PKCS;
3870 mech.pParameter = NULL;
3871 mech.ulParameterLen = 0;
3872
3873 if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech,
3874 obj)) != CKR_OK) {
3875 pkiDebug("C_DecryptInit: 0x%x\n", (int) r);
3876 return KRB5KDC_ERR_PREAUTH_FAILED;
3877 }
3878 pkiDebug("data_len = %d\n", data_len);
3879 cp = malloc((size_t) data_len);
3880 if (cp == NULL)
3881 return ENOMEM;
3882 len = data_len;
3883 pkiDebug("session %p edata %p edata_len %d data %p datalen @%p %d\n",
3884 (void *) id_cryptoctx->session, (void *) data, (int) data_len,
3885 (void *) cp, (void *) &len, (int) len);
3886 r = pkinit_C_Decrypt(id_cryptoctx, (CK_BYTE_PTR) data, (CK_ULONG) data_len,
3887 cp, &len);
3888 if (r != CKR_OK) {
3889 pkiDebug("C_Decrypt: %s\n", pkcs11err(r));
3890 if (r == CKR_BUFFER_TOO_SMALL)
3891 pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len);
3892 return KRB5KDC_ERR_PREAUTH_FAILED;
3893 }
3894 pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len);
3895 *decoded_data_len = len;
3896 *decoded_data = cp;
3897
3898 return 0;
3899 }
3900 #endif
3901
3902 krb5_error_code
pkinit_decode_data(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,const uint8_t * data,unsigned int data_len,uint8_t ** decoded_data,unsigned int * decoded_data_len)3903 pkinit_decode_data(krb5_context context,
3904 pkinit_identity_crypto_context id_cryptoctx,
3905 const uint8_t *data, unsigned int data_len,
3906 uint8_t **decoded_data, unsigned int *decoded_data_len)
3907 {
3908 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
3909
3910 *decoded_data = NULL;
3911 *decoded_data_len = 0;
3912
3913 if (id_cryptoctx->pkcs11_method != 1)
3914 retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len,
3915 decoded_data, decoded_data_len);
3916 #ifndef WITHOUT_PKCS11
3917 else
3918 retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data,
3919 data_len, decoded_data, decoded_data_len);
3920 #endif
3921
3922 return retval;
3923 }
3924
3925 static krb5_error_code
pkinit_sign_data_fs(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,unsigned char * data,unsigned int data_len,unsigned char ** sig,unsigned int * sig_len)3926 pkinit_sign_data_fs(krb5_context context,
3927 pkinit_identity_crypto_context id_cryptoctx,
3928 unsigned char *data,
3929 unsigned int data_len,
3930 unsigned char **sig,
3931 unsigned int *sig_len)
3932 {
3933 if (create_signature(sig, sig_len, data, data_len,
3934 id_cryptoctx->my_key) != 0) {
3935 pkiDebug("failed to create the signature\n");
3936 return KRB5KDC_ERR_PREAUTH_FAILED;
3937 }
3938 return 0;
3939 }
3940
3941 #ifndef WITHOUT_PKCS11
3942 static krb5_error_code
pkinit_sign_data_pkcs11(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,unsigned char * data,unsigned int data_len,unsigned char ** sig,unsigned int * sig_len)3943 pkinit_sign_data_pkcs11(krb5_context context,
3944 pkinit_identity_crypto_context id_cryptoctx,
3945 unsigned char *data,
3946 unsigned int data_len,
3947 unsigned char **sig,
3948 unsigned int *sig_len)
3949 {
3950 CK_OBJECT_HANDLE obj;
3951 CK_ULONG len;
3952 CK_MECHANISM mech;
3953 unsigned char *cp;
3954 int r;
3955
3956 if (pkinit_open_session(context, id_cryptoctx)) {
3957 pkiDebug("can't open pkcs11 session\n");
3958 return KRB5KDC_ERR_PREAUTH_FAILED;
3959 }
3960
3961 pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
3962
3963 mech.mechanism = id_cryptoctx->mech;
3964 mech.pParameter = NULL;
3965 mech.ulParameterLen = 0;
3966
3967 if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
3968 obj)) != CKR_OK) {
3969 pkiDebug("C_SignInit: %s\n", pkcs11err(r));
3970 return KRB5KDC_ERR_PREAUTH_FAILED;
3971 }
3972
3973 /*
3974 * Key len would give an upper bound on sig size, but there's no way to
3975 * get that. So guess, and if it's too small, re-malloc.
3976 */
3977 len = PK_SIGLEN_GUESS;
3978 cp = malloc((size_t) len);
3979 if (cp == NULL)
3980 return ENOMEM;
3981
3982 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
3983 (CK_ULONG) data_len, cp, &len);
3984 if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
3985 free(cp);
3986 pkiDebug("C_Sign realloc %d\n", (int) len);
3987 cp = malloc((size_t) len);
3988 r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
3989 (CK_ULONG) data_len, cp, &len);
3990 }
3991 if (r != CKR_OK) {
3992 pkiDebug("C_Sign: %s\n", pkcs11err(r));
3993 return KRB5KDC_ERR_PREAUTH_FAILED;
3994 }
3995 pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
3996 *sig_len = len;
3997 *sig = cp;
3998
3999 return 0;
4000 }
4001 #endif
4002
4003 krb5_error_code
pkinit_sign_data(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,unsigned char * data,unsigned int data_len,unsigned char ** sig,unsigned int * sig_len)4004 pkinit_sign_data(krb5_context context,
4005 pkinit_identity_crypto_context id_cryptoctx,
4006 unsigned char *data,
4007 unsigned int data_len,
4008 unsigned char **sig,
4009 unsigned int *sig_len)
4010 {
4011 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4012
4013 if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1)
4014 retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len,
4015 sig, sig_len);
4016 #ifndef WITHOUT_PKCS11
4017 else
4018 retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len,
4019 sig, sig_len);
4020 #endif
4021
4022 return retval;
4023 }
4024
4025
4026 static krb5_error_code
create_signature(unsigned char ** sig,unsigned int * sig_len,unsigned char * data,unsigned int data_len,EVP_PKEY * pkey)4027 create_signature(unsigned char **sig, unsigned int *sig_len,
4028 unsigned char *data, unsigned int data_len, EVP_PKEY *pkey)
4029 {
4030 krb5_error_code retval = ENOMEM;
4031 EVP_MD_CTX *ctx;
4032
4033 if (pkey == NULL)
4034 return retval;
4035
4036 ctx = EVP_MD_CTX_new();
4037 if (ctx == NULL)
4038 return ENOMEM;
4039 EVP_SignInit(ctx, EVP_sha256());
4040 EVP_SignUpdate(ctx, data, data_len);
4041 *sig_len = EVP_PKEY_size(pkey);
4042 if ((*sig = malloc(*sig_len)) == NULL)
4043 goto cleanup;
4044 EVP_SignFinal(ctx, *sig, sig_len, pkey);
4045
4046 retval = 0;
4047
4048 cleanup:
4049 EVP_MD_CTX_free(ctx);
4050
4051 return retval;
4052 }
4053
4054 /*
4055 * Note:
4056 * This is not the routine the KDC uses to get its certificate.
4057 * This routine is intended to be called by the client
4058 * to obtain the KDC's certificate from some local storage
4059 * to be sent as a hint in its request to the KDC.
4060 */
4061 krb5_error_code
pkinit_get_kdc_cert(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ)4062 pkinit_get_kdc_cert(krb5_context context,
4063 pkinit_plg_crypto_context plg_cryptoctx,
4064 pkinit_req_crypto_context req_cryptoctx,
4065 pkinit_identity_crypto_context id_cryptoctx,
4066 krb5_principal princ)
4067 {
4068 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4069
4070 req_cryptoctx->received_cert = NULL;
4071 retval = 0;
4072 return retval;
4073 }
4074
4075 static char *
reassemble_pkcs12_name(const char * filename)4076 reassemble_pkcs12_name(const char *filename)
4077 {
4078 char *ret;
4079
4080 if (asprintf(&ret, "PKCS12:%s", filename) < 0)
4081 return NULL;
4082 return ret;
4083 }
4084
4085 static krb5_error_code
pkinit_get_certs_pkcs12(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ)4086 pkinit_get_certs_pkcs12(krb5_context context,
4087 pkinit_plg_crypto_context plg_cryptoctx,
4088 pkinit_req_crypto_context req_cryptoctx,
4089 pkinit_identity_opts *idopts,
4090 pkinit_identity_crypto_context id_cryptoctx,
4091 krb5_principal princ)
4092 {
4093 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4094 char *prompt_string = NULL;
4095 X509 *x = NULL;
4096 PKCS12 *p12 = NULL;
4097 int ret;
4098 FILE *fp;
4099 EVP_PKEY *y = NULL;
4100
4101 if (idopts->cert_filename == NULL) {
4102 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
4103 goto cleanup;
4104 }
4105
4106 if (idopts->key_filename == NULL) {
4107 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
4108 goto cleanup;
4109 }
4110
4111 fp = fopen(idopts->cert_filename, "rb");
4112 if (fp == NULL) {
4113 TRACE_PKINIT_PKCS_OPEN_FAIL(context, idopts->cert_filename, errno);
4114 goto cleanup;
4115 }
4116 set_cloexec_file(fp);
4117
4118 p12 = d2i_PKCS12_fp(fp, NULL);
4119 fclose(fp);
4120 if (p12 == NULL) {
4121 TRACE_PKINIT_PKCS_DECODE_FAIL(context, idopts->cert_filename);
4122 goto cleanup;
4123 }
4124 /*
4125 * Try parsing with no pass phrase first. If that fails,
4126 * prompt for the pass phrase and try again.
4127 */
4128 ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
4129 if (ret == 0) {
4130 krb5_data rdat;
4131 krb5_prompt kprompt;
4132 krb5_prompt_type prompt_type;
4133 krb5_error_code r;
4134 char prompt_reply[128];
4135 char *prompt_prefix = _("Pass phrase for");
4136 char *p12name = reassemble_pkcs12_name(idopts->cert_filename);
4137 const char *tmp;
4138
4139 TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(context);
4140
4141 if (id_cryptoctx->defer_id_prompt) {
4142 /* Supply the identity name to be passed to the responder. */
4143 pkinit_set_deferred_id(&id_cryptoctx->deferred_ids, p12name, 0,
4144 NULL);
4145 free(p12name);
4146 retval = 0;
4147 goto cleanup;
4148 }
4149 /* Try to read a responder-supplied password. */
4150 tmp = pkinit_find_deferred_id(id_cryptoctx->deferred_ids, p12name);
4151 free(p12name);
4152 if (tmp != NULL) {
4153 /* Try using the responder-supplied password. */
4154 rdat.data = (char *)tmp;
4155 rdat.length = strlen(tmp);
4156 } else if (id_cryptoctx->prompter == NULL) {
4157 /* We can't use a prompter. */
4158 goto cleanup;
4159 } else {
4160 /* Ask using a prompter. */
4161 memset(prompt_reply, '\0', sizeof(prompt_reply));
4162 rdat.data = prompt_reply;
4163 rdat.length = sizeof(prompt_reply);
4164
4165 if (asprintf(&prompt_string, "%s %s", prompt_prefix,
4166 idopts->cert_filename) < 0) {
4167 prompt_string = NULL;
4168 goto cleanup;
4169 }
4170 kprompt.prompt = prompt_string;
4171 kprompt.hidden = 1;
4172 kprompt.reply = &rdat;
4173 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
4174 /* PROMPTER_INVOCATION */
4175 k5int_set_prompt_types(context, &prompt_type);
4176 r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
4177 NULL, NULL, 1, &kprompt);
4178 k5int_set_prompt_types(context, 0);
4179 if (r) {
4180 TRACE_PKINIT_PKCS_PROMPT_FAIL(context);
4181 goto cleanup;
4182 }
4183 }
4184
4185 ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
4186 if (ret == 0) {
4187 TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(context);
4188 goto cleanup;
4189 }
4190 }
4191 id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
4192 if (id_cryptoctx->creds[0] == NULL)
4193 goto cleanup;
4194 id_cryptoctx->creds[0]->name =
4195 reassemble_pkcs12_name(idopts->cert_filename);
4196 id_cryptoctx->creds[0]->cert = x;
4197 #ifndef WITHOUT_PKCS11
4198 id_cryptoctx->creds[0]->cert_id = NULL;
4199 id_cryptoctx->creds[0]->cert_id_len = 0;
4200 #endif
4201 id_cryptoctx->creds[0]->key = y;
4202 id_cryptoctx->creds[1] = NULL;
4203
4204 retval = 0;
4205
4206 cleanup:
4207 free(prompt_string);
4208 if (p12)
4209 PKCS12_free(p12);
4210 if (retval) {
4211 if (x != NULL)
4212 X509_free(x);
4213 if (y != NULL)
4214 EVP_PKEY_free(y);
4215 }
4216 return retval;
4217 }
4218
4219 static char *
reassemble_files_name(const char * certfile,const char * keyfile)4220 reassemble_files_name(const char *certfile, const char *keyfile)
4221 {
4222 char *ret;
4223
4224 if (keyfile != NULL) {
4225 if (asprintf(&ret, "FILE:%s,%s", certfile, keyfile) < 0)
4226 return NULL;
4227 } else {
4228 if (asprintf(&ret, "FILE:%s", certfile) < 0)
4229 return NULL;
4230 }
4231 return ret;
4232 }
4233
4234 static krb5_error_code
pkinit_load_fs_cert_and_key(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,char * certname,char * keyname,int cindex)4235 pkinit_load_fs_cert_and_key(krb5_context context,
4236 pkinit_identity_crypto_context id_cryptoctx,
4237 char *certname,
4238 char *keyname,
4239 int cindex)
4240 {
4241 krb5_error_code retval;
4242 X509 *x = NULL;
4243 EVP_PKEY *y = NULL;
4244 char *fsname = NULL;
4245 const char *password;
4246
4247 fsname = reassemble_files_name(certname, keyname);
4248
4249 /* Try to read a responder-supplied password. */
4250 password = pkinit_find_deferred_id(id_cryptoctx->deferred_ids, fsname);
4251
4252 /* Load the certificate. */
4253 retval = get_cert(certname, &x);
4254 if (retval) {
4255 retval = oerr(context, retval, _("Cannot read certificate file '%s'"),
4256 certname);
4257 }
4258 if (retval || x == NULL)
4259 goto cleanup;
4260 /* Load the key. */
4261 retval = get_key(context, id_cryptoctx, keyname, fsname, &y, password);
4262 if (retval)
4263 retval = oerr(context, retval, _("Cannot read key file '%s'"), fsname);
4264 if (retval || y == NULL)
4265 goto cleanup;
4266
4267 id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
4268 if (id_cryptoctx->creds[cindex] == NULL) {
4269 retval = ENOMEM;
4270 goto cleanup;
4271 }
4272 id_cryptoctx->creds[cindex]->name = reassemble_files_name(certname,
4273 keyname);
4274 id_cryptoctx->creds[cindex]->cert = x;
4275 #ifndef WITHOUT_PKCS11
4276 id_cryptoctx->creds[cindex]->cert_id = NULL;
4277 id_cryptoctx->creds[cindex]->cert_id_len = 0;
4278 #endif
4279 id_cryptoctx->creds[cindex]->key = y;
4280 id_cryptoctx->creds[cindex+1] = NULL;
4281
4282 retval = 0;
4283
4284 cleanup:
4285 free(fsname);
4286 if (retval != 0 || y == NULL) {
4287 if (x != NULL)
4288 X509_free(x);
4289 if (y != NULL)
4290 EVP_PKEY_free(y);
4291 }
4292 return retval;
4293 }
4294
4295 static krb5_error_code
pkinit_get_certs_fs(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ)4296 pkinit_get_certs_fs(krb5_context context,
4297 pkinit_plg_crypto_context plg_cryptoctx,
4298 pkinit_req_crypto_context req_cryptoctx,
4299 pkinit_identity_opts *idopts,
4300 pkinit_identity_crypto_context id_cryptoctx,
4301 krb5_principal princ)
4302 {
4303 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4304
4305 if (idopts->cert_filename == NULL) {
4306 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
4307 goto cleanup;
4308 }
4309
4310 if (idopts->key_filename == NULL) {
4311 TRACE_PKINIT_NO_PRIVKEY(context);
4312 goto cleanup;
4313 }
4314
4315 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
4316 idopts->cert_filename,
4317 idopts->key_filename, 0);
4318 cleanup:
4319 return retval;
4320 }
4321
4322 static krb5_error_code
pkinit_get_certs_dir(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ)4323 pkinit_get_certs_dir(krb5_context context,
4324 pkinit_plg_crypto_context plg_cryptoctx,
4325 pkinit_req_crypto_context req_cryptoctx,
4326 pkinit_identity_opts *idopts,
4327 pkinit_identity_crypto_context id_cryptoctx,
4328 krb5_principal princ)
4329 {
4330 krb5_error_code retval = ENOMEM;
4331 DIR *d = NULL;
4332 struct dirent *dentry = NULL;
4333 char certname[1024];
4334 char keyname[1024];
4335 int i = 0, len;
4336 char *dirname, *suf;
4337
4338 if (idopts->cert_filename == NULL) {
4339 TRACE_PKINIT_NO_CERT(context);
4340 return ENOENT;
4341 }
4342
4343 dirname = idopts->cert_filename;
4344 d = opendir(dirname);
4345 if (d == NULL)
4346 return errno;
4347
4348 /*
4349 * We'll assume that certs are named XXX.crt and the corresponding
4350 * key is named XXX.key
4351 */
4352 while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) {
4353 /* Ignore subdirectories and anything starting with a dot */
4354 #ifdef DT_DIR
4355 if (dentry->d_type == DT_DIR)
4356 continue;
4357 #endif
4358 if (dentry->d_name[0] == '.')
4359 continue;
4360 len = strlen(dentry->d_name);
4361 if (len < 5)
4362 continue;
4363 suf = dentry->d_name + (len - 4);
4364 if (strncmp(suf, ".crt", 4) != 0)
4365 continue;
4366
4367 /* Checked length */
4368 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) {
4369 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
4370 __FUNCTION__, dirname, dentry->d_name);
4371 continue;
4372 }
4373 snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name);
4374 snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name);
4375 len = strlen(keyname);
4376 keyname[len - 3] = 'k';
4377 keyname[len - 2] = 'e';
4378 keyname[len - 1] = 'y';
4379
4380 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
4381 certname, keyname, i);
4382 if (retval == 0) {
4383 TRACE_PKINIT_LOADED_CERT(context, dentry->d_name);
4384 i++;
4385 }
4386 else
4387 continue;
4388 }
4389
4390 if (!id_cryptoctx->defer_id_prompt && i == 0) {
4391 TRACE_PKINIT_NO_CERT_AND_KEY(context, idopts->cert_filename);
4392 retval = ENOENT;
4393 goto cleanup;
4394 }
4395
4396 retval = 0;
4397
4398 cleanup:
4399 if (d)
4400 closedir(d);
4401
4402 return retval;
4403 }
4404
4405 #ifndef WITHOUT_PKCS11
4406 static char *
reassemble_pkcs11_name(pkinit_identity_opts * idopts)4407 reassemble_pkcs11_name(pkinit_identity_opts *idopts)
4408 {
4409 struct k5buf buf;
4410 int n = 0;
4411
4412 k5_buf_init_dynamic(&buf);
4413 k5_buf_add(&buf, "PKCS11:");
4414 n = 0;
4415 if (idopts->p11_module_name != NULL) {
4416 k5_buf_add_fmt(&buf, "%smodule_name=%s", n++ ? ":" : "",
4417 idopts->p11_module_name);
4418 }
4419 if (idopts->token_label != NULL) {
4420 k5_buf_add_fmt(&buf, "%stoken=%s", n++ ? ":" : "",
4421 idopts->token_label);
4422 }
4423 if (idopts->cert_label != NULL) {
4424 k5_buf_add_fmt(&buf, "%scertlabel=%s", n++ ? ":" : "",
4425 idopts->cert_label);
4426 }
4427 if (idopts->cert_id_string != NULL) {
4428 k5_buf_add_fmt(&buf, "%scertid=%s", n++ ? ":" : "",
4429 idopts->cert_id_string);
4430 }
4431 if (idopts->slotid != PK_NOSLOT) {
4432 k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "",
4433 (long)idopts->slotid);
4434 }
4435 return k5_buf_cstring(&buf);
4436 }
4437
4438 static krb5_error_code
load_one_cert(CK_FUNCTION_LIST_PTR p11,CK_SESSION_HANDLE session,pkinit_identity_opts * idopts,pkinit_cred_info * cred_out)4439 load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session,
4440 pkinit_identity_opts *idopts, pkinit_cred_info *cred_out)
4441 {
4442 krb5_error_code ret;
4443 CK_ATTRIBUTE attrs[2];
4444 CK_BYTE_PTR cert = NULL, cert_id = NULL;
4445 CK_RV pret;
4446 const unsigned char *cp;
4447 CK_OBJECT_HANDLE obj;
4448 CK_ULONG count;
4449 X509 *x = NULL;
4450 pkinit_cred_info cred;
4451
4452 *cred_out = NULL;
4453
4454 /* Look for X.509 cert. */
4455 pret = p11->C_FindObjects(session, &obj, 1, &count);
4456 if (pret != CKR_OK || count <= 0)
4457 return 0;
4458
4459 /* Get cert and id len. */
4460 attrs[0].type = CKA_VALUE;
4461 attrs[0].pValue = NULL;
4462 attrs[0].ulValueLen = 0;
4463 attrs[1].type = CKA_ID;
4464 attrs[1].pValue = NULL;
4465 attrs[1].ulValueLen = 0;
4466 pret = p11->C_GetAttributeValue(session, obj, attrs, 2);
4467 if (pret != CKR_OK && pret != CKR_BUFFER_TOO_SMALL) {
4468 pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(pret));
4469 ret = KRB5KDC_ERR_PREAUTH_FAILED;
4470 goto cleanup;
4471 }
4472
4473 /* Allocate buffers and read the cert and id. */
4474 cert = k5alloc(attrs[0].ulValueLen + 1, &ret);
4475 if (cert == NULL)
4476 goto cleanup;
4477 cert_id = k5alloc(attrs[1].ulValueLen + 1, &ret);
4478 if (cert_id == NULL)
4479 goto cleanup;
4480 attrs[0].type = CKA_VALUE;
4481 attrs[0].pValue = cert;
4482 attrs[1].type = CKA_ID;
4483 attrs[1].pValue = cert_id;
4484 pret = p11->C_GetAttributeValue(session, obj, attrs, 2);
4485 if (pret != CKR_OK) {
4486 pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(pret));
4487 ret = KRB5KDC_ERR_PREAUTH_FAILED;
4488 goto cleanup;
4489 }
4490
4491 pkiDebug("cert: size %d, id %d, idlen %d\n", (int)attrs[0].ulValueLen,
4492 (int)cert_id[0], (int)attrs[1].ulValueLen);
4493
4494 cp = (unsigned char *)cert;
4495 x = d2i_X509(NULL, &cp, (int)attrs[0].ulValueLen);
4496 if (x == NULL) {
4497 ret = KRB5KDC_ERR_PREAUTH_FAILED;
4498 goto cleanup;
4499 }
4500
4501 cred = k5alloc(sizeof(struct _pkinit_cred_info), &ret);
4502 if (cred == NULL)
4503 goto cleanup;
4504
4505 cred->name = reassemble_pkcs11_name(idopts);
4506 cred->cert = x;
4507 cred->key = NULL;
4508 cred->cert_id = cert_id;
4509 cred->cert_id_len = attrs[1].ulValueLen;
4510
4511 *cred_out = cred;
4512 cert_id = NULL;
4513 ret = 0;
4514
4515 cleanup:
4516 free(cert);
4517 free(cert_id);
4518 return ret;
4519 }
4520
4521 static krb5_error_code
pkinit_get_certs_pkcs11(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ)4522 pkinit_get_certs_pkcs11(krb5_context context,
4523 pkinit_plg_crypto_context plg_cryptoctx,
4524 pkinit_req_crypto_context req_cryptoctx,
4525 pkinit_identity_opts *idopts,
4526 pkinit_identity_crypto_context id_cryptoctx,
4527 krb5_principal princ)
4528 {
4529 CK_OBJECT_CLASS cls;
4530 CK_ATTRIBUTE attrs[4];
4531 CK_CERTIFICATE_TYPE certtype;
4532 int i;
4533 unsigned int nattrs;
4534 krb5_error_code ret;
4535 CK_RV pret;
4536
4537 /* Copy stuff from idopts -> id_cryptoctx */
4538 if (idopts->p11_module_name != NULL) {
4539 free(id_cryptoctx->p11_module_name);
4540 id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name);
4541 if (id_cryptoctx->p11_module_name == NULL)
4542 return ENOMEM;
4543 }
4544 if (idopts->token_label != NULL) {
4545 id_cryptoctx->token_label = strdup(idopts->token_label);
4546 if (id_cryptoctx->token_label == NULL)
4547 return ENOMEM;
4548 }
4549 if (idopts->cert_label != NULL) {
4550 id_cryptoctx->cert_label = strdup(idopts->cert_label);
4551 if (id_cryptoctx->cert_label == NULL)
4552 return ENOMEM;
4553 }
4554 /* Convert the ascii cert_id string into a binary blob */
4555 if (idopts->cert_id_string != NULL) {
4556 ret = k5_hex_decode(idopts->cert_id_string, &id_cryptoctx->cert_id,
4557 &id_cryptoctx->cert_id_len);
4558 if (ret) {
4559 pkiDebug("Failed to convert certid string [%s]\n",
4560 idopts->cert_id_string);
4561 return ret;
4562 }
4563 }
4564 id_cryptoctx->slotid = idopts->slotid;
4565 id_cryptoctx->pkcs11_method = 1;
4566
4567 ret = pkinit_open_session(context, id_cryptoctx);
4568 if (ret)
4569 return ret;
4570 if (id_cryptoctx->defer_id_prompt) {
4571 /*
4572 * We need to reset all of the PKCS#11 state, so that the next time we
4573 * poke at it, it'll be in as close to the state it was in after we
4574 * loaded it the first time as we can make it.
4575 */
4576 pkinit_fini_pkcs11(id_cryptoctx);
4577 pkinit_init_pkcs11(id_cryptoctx);
4578 return 0;
4579 }
4580
4581 /*
4582 * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but
4583 * historically many cards seem to be confused about whether they are
4584 * capable of mechanisms or not. The safe thing seems to be to ignore the
4585 * mechanism list, always use CKM_RSA_PKCS and calculate the sha256 digest
4586 * ourselves.
4587 */
4588 id_cryptoctx->mech = CKM_RSA_PKCS;
4589
4590 cls = CKO_CERTIFICATE;
4591 attrs[0].type = CKA_CLASS;
4592 attrs[0].pValue = &cls;
4593 attrs[0].ulValueLen = sizeof(cls);
4594
4595 certtype = CKC_X_509;
4596 attrs[1].type = CKA_CERTIFICATE_TYPE;
4597 attrs[1].pValue = &certtype;
4598 attrs[1].ulValueLen = sizeof(certtype);
4599
4600 nattrs = 2;
4601
4602 /* If a cert id and/or label were given, use them too */
4603 if (id_cryptoctx->cert_id_len > 0) {
4604 attrs[nattrs].type = CKA_ID;
4605 attrs[nattrs].pValue = id_cryptoctx->cert_id;
4606 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
4607 nattrs++;
4608 }
4609 if (id_cryptoctx->cert_label != NULL) {
4610 attrs[nattrs].type = CKA_LABEL;
4611 attrs[nattrs].pValue = id_cryptoctx->cert_label;
4612 attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label);
4613 nattrs++;
4614 }
4615
4616 pret = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs,
4617 nattrs);
4618 if (pret != CKR_OK) {
4619 pkiDebug("C_FindObjectsInit: %s\n", pkcs11err(pret));
4620 return KRB5KDC_ERR_PREAUTH_FAILED;
4621 }
4622
4623 for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
4624 ret = load_one_cert(id_cryptoctx->p11, id_cryptoctx->session, idopts,
4625 &id_cryptoctx->creds[i]);
4626 if (ret)
4627 return ret;
4628 if (id_cryptoctx->creds[i] == NULL)
4629 break;
4630 }
4631 if (i == MAX_CREDS_ALLOWED)
4632 return KRB5KDC_ERR_PREAUTH_FAILED;
4633
4634 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
4635
4636 /* Check if we found no certs. */
4637 if (id_cryptoctx->creds[0] == NULL)
4638 return KRB5KDC_ERR_PREAUTH_FAILED;
4639 return 0;
4640 }
4641
4642 #endif /* !WITHOUT_PKCS11 */
4643
4644
4645 static void
free_cred_info(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,struct _pkinit_cred_info * cred)4646 free_cred_info(krb5_context context,
4647 pkinit_identity_crypto_context id_cryptoctx,
4648 struct _pkinit_cred_info *cred)
4649 {
4650 if (cred != NULL) {
4651 if (cred->cert != NULL)
4652 X509_free(cred->cert);
4653 if (cred->key != NULL)
4654 EVP_PKEY_free(cred->key);
4655 #ifndef WITHOUT_PKCS11
4656 free(cred->cert_id);
4657 #endif
4658 free(cred->name);
4659 free(cred);
4660 }
4661 }
4662
4663 krb5_error_code
crypto_free_cert_info(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx)4664 crypto_free_cert_info(krb5_context context,
4665 pkinit_plg_crypto_context plg_cryptoctx,
4666 pkinit_req_crypto_context req_cryptoctx,
4667 pkinit_identity_crypto_context id_cryptoctx)
4668 {
4669 int i;
4670
4671 if (id_cryptoctx == NULL)
4672 return EINVAL;
4673
4674 for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
4675 if (id_cryptoctx->creds[i] != NULL) {
4676 free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]);
4677 id_cryptoctx->creds[i] = NULL;
4678 }
4679 }
4680 return 0;
4681 }
4682
4683 krb5_error_code
crypto_load_certs(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,krb5_principal princ,krb5_boolean defer_id_prompts)4684 crypto_load_certs(krb5_context context,
4685 pkinit_plg_crypto_context plg_cryptoctx,
4686 pkinit_req_crypto_context req_cryptoctx,
4687 pkinit_identity_opts *idopts,
4688 pkinit_identity_crypto_context id_cryptoctx,
4689 krb5_principal princ,
4690 krb5_boolean defer_id_prompts)
4691 {
4692 krb5_error_code retval;
4693
4694 id_cryptoctx->defer_id_prompt = defer_id_prompts;
4695
4696 switch(idopts->idtype) {
4697 case IDTYPE_FILE:
4698 retval = pkinit_get_certs_fs(context, plg_cryptoctx,
4699 req_cryptoctx, idopts,
4700 id_cryptoctx, princ);
4701 break;
4702 case IDTYPE_DIR:
4703 retval = pkinit_get_certs_dir(context, plg_cryptoctx,
4704 req_cryptoctx, idopts,
4705 id_cryptoctx, princ);
4706 break;
4707 #ifndef WITHOUT_PKCS11
4708 case IDTYPE_PKCS11:
4709 retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx,
4710 req_cryptoctx, idopts,
4711 id_cryptoctx, princ);
4712 break;
4713 #endif
4714 case IDTYPE_PKCS12:
4715 retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx,
4716 req_cryptoctx, idopts,
4717 id_cryptoctx, princ);
4718 break;
4719 default:
4720 retval = EINVAL;
4721 }
4722 if (retval)
4723 goto cleanup;
4724
4725 cleanup:
4726 return retval;
4727 }
4728
4729 /*
4730 * Get certificate Key Usage and Extended Key Usage
4731 */
4732 static krb5_error_code
crypto_retrieve_X509_key_usage(krb5_context context,pkinit_plg_crypto_context plgcctx,pkinit_req_crypto_context reqcctx,X509 * x,unsigned int * ret_ku_bits,unsigned int * ret_eku_bits)4733 crypto_retrieve_X509_key_usage(krb5_context context,
4734 pkinit_plg_crypto_context plgcctx,
4735 pkinit_req_crypto_context reqcctx,
4736 X509 *x,
4737 unsigned int *ret_ku_bits,
4738 unsigned int *ret_eku_bits)
4739 {
4740 krb5_error_code retval = 0;
4741 int i;
4742 unsigned int eku_bits = 0, ku_bits = 0;
4743 ASN1_BIT_STRING *usage = NULL;
4744
4745 if (ret_ku_bits == NULL && ret_eku_bits == NULL)
4746 return EINVAL;
4747
4748 if (ret_eku_bits)
4749 *ret_eku_bits = 0;
4750 else {
4751 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__);
4752 goto check_kus;
4753 }
4754
4755 /* Start with Extended Key usage */
4756 i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
4757 if (i >= 0) {
4758 EXTENDED_KEY_USAGE *eku;
4759
4760 eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
4761 if (eku) {
4762 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
4763 ASN1_OBJECT *certoid;
4764 certoid = sk_ASN1_OBJECT_value(eku, i);
4765 if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0)
4766 eku_bits |= PKINIT_EKU_PKINIT;
4767 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0)
4768 eku_bits |= PKINIT_EKU_MSSCLOGIN;
4769 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0)
4770 eku_bits |= PKINIT_EKU_CLIENTAUTH;
4771 else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0)
4772 eku_bits |= PKINIT_EKU_EMAILPROTECTION;
4773 }
4774 EXTENDED_KEY_USAGE_free(eku);
4775 }
4776 }
4777 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits);
4778 *ret_eku_bits = eku_bits;
4779
4780 check_kus:
4781 /* Now the Key Usage bits */
4782 if (ret_ku_bits)
4783 *ret_ku_bits = 0;
4784 else {
4785 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__);
4786 goto out;
4787 }
4788
4789 /* Make sure usage exists before checking bits */
4790 X509_check_ca(x);
4791 usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL);
4792 if (usage) {
4793 if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
4794 ku_bits |= PKINIT_KU_DIGITALSIGNATURE;
4795 if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT))
4796 ku_bits |= PKINIT_KU_KEYENCIPHERMENT;
4797 ASN1_BIT_STRING_free(usage);
4798 }
4799
4800 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits);
4801 *ret_ku_bits = ku_bits;
4802 retval = 0;
4803 out:
4804 return retval;
4805 }
4806
4807 static krb5_error_code
rfc2253_name(X509_NAME * name,char ** str_out)4808 rfc2253_name(X509_NAME *name, char **str_out)
4809 {
4810 BIO *b = NULL;
4811 char *str;
4812
4813 *str_out = NULL;
4814 b = BIO_new(BIO_s_mem());
4815 if (b == NULL)
4816 return ENOMEM;
4817 if (X509_NAME_print_ex(b, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0)
4818 goto error;
4819 str = calloc(BIO_number_written(b) + 1, 1);
4820 if (str == NULL)
4821 goto error;
4822 BIO_read(b, str, BIO_number_written(b));
4823 BIO_free(b);
4824 *str_out = str;
4825 return 0;
4826
4827 error:
4828 BIO_free(b);
4829 return ENOMEM;
4830 }
4831
4832 /*
4833 * Get number of certificates available after crypto_load_certs()
4834 */
4835 static krb5_error_code
crypto_cert_get_count(pkinit_identity_crypto_context id_cryptoctx,int * cert_count)4836 crypto_cert_get_count(pkinit_identity_crypto_context id_cryptoctx,
4837 int *cert_count)
4838 {
4839 int count;
4840
4841 *cert_count = 0;
4842 if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
4843 return EINVAL;
4844
4845 for (count = 0;
4846 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
4847 count++);
4848 *cert_count = count;
4849 return 0;
4850 }
4851
4852 void
crypto_cert_free_matching_data(krb5_context context,pkinit_cert_matching_data * md)4853 crypto_cert_free_matching_data(krb5_context context,
4854 pkinit_cert_matching_data *md)
4855 {
4856 int i;
4857
4858 if (md == NULL)
4859 return;
4860 free(md->subject_dn);
4861 free(md->issuer_dn);
4862 for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++)
4863 krb5_free_principal(context, md->sans[i]);
4864 free(md->sans);
4865 for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++)
4866 free(md->upns[i]);
4867 free(md->upns);
4868 free(md);
4869 }
4870
4871 /*
4872 * Free certificate matching data.
4873 */
4874 void
crypto_cert_free_matching_data_list(krb5_context context,pkinit_cert_matching_data ** list)4875 crypto_cert_free_matching_data_list(krb5_context context,
4876 pkinit_cert_matching_data **list)
4877 {
4878 int i;
4879
4880 for (i = 0; list != NULL && list[i] != NULL; i++)
4881 crypto_cert_free_matching_data(context, list[i]);
4882 free(list);
4883 }
4884
4885 /*
4886 * Get certificate matching data for cert.
4887 */
4888 static krb5_error_code
get_matching_data(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,X509 * cert,pkinit_cert_matching_data ** md_out)4889 get_matching_data(krb5_context context,
4890 pkinit_plg_crypto_context plg_cryptoctx,
4891 pkinit_req_crypto_context req_cryptoctx, X509 *cert,
4892 pkinit_cert_matching_data **md_out)
4893 {
4894 krb5_error_code ret = ENOMEM;
4895 pkinit_cert_matching_data *md = NULL;
4896
4897 *md_out = NULL;
4898
4899 md = calloc(1, sizeof(*md));
4900 if (md == NULL)
4901 goto cleanup;
4902
4903 ret = rfc2253_name(X509_get_subject_name(cert), &md->subject_dn);
4904 if (ret)
4905 goto cleanup;
4906 ret = rfc2253_name(X509_get_issuer_name(cert), &md->issuer_dn);
4907 if (ret)
4908 goto cleanup;
4909
4910 /* Get the SAN data. */
4911 ret = crypto_retrieve_X509_sans(context, plg_cryptoctx, req_cryptoctx,
4912 cert, &md->sans, &md->upns, NULL);
4913 if (ret)
4914 goto cleanup;
4915
4916 /* Get the KU and EKU data. */
4917 ret = crypto_retrieve_X509_key_usage(context, plg_cryptoctx,
4918 req_cryptoctx, cert, &md->ku_bits,
4919 &md->eku_bits);
4920 if (ret)
4921 goto cleanup;
4922
4923 *md_out = md;
4924 md = NULL;
4925
4926 cleanup:
4927 crypto_cert_free_matching_data(context, md);
4928 return ret;
4929 }
4930
4931 krb5_error_code
crypto_cert_get_matching_data(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,pkinit_cert_matching_data *** md_out)4932 crypto_cert_get_matching_data(krb5_context context,
4933 pkinit_plg_crypto_context plg_cryptoctx,
4934 pkinit_req_crypto_context req_cryptoctx,
4935 pkinit_identity_crypto_context id_cryptoctx,
4936 pkinit_cert_matching_data ***md_out)
4937 {
4938 krb5_error_code ret;
4939 pkinit_cert_matching_data **md_list = NULL;
4940 int count, i;
4941
4942 ret = crypto_cert_get_count(id_cryptoctx, &count);
4943 if (ret)
4944 goto cleanup;
4945
4946 md_list = calloc(count + 1, sizeof(*md_list));
4947 if (md_list == NULL) {
4948 ret = ENOMEM;
4949 goto cleanup;
4950 }
4951
4952 for (i = 0; i < count; i++) {
4953 ret = get_matching_data(context, plg_cryptoctx, req_cryptoctx,
4954 id_cryptoctx->creds[i]->cert, &md_list[i]);
4955 if (ret) {
4956 pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n",
4957 __FUNCTION__, ret, error_message(ret));
4958 goto cleanup;
4959 }
4960 }
4961
4962 *md_out = md_list;
4963 md_list = NULL;
4964
4965 cleanup:
4966 crypto_cert_free_matching_data_list(context, md_list);
4967 return ret;
4968 }
4969
4970 /*
4971 * Set the certificate in idctx->creds[cred_index] as the selected certificate.
4972 */
4973 krb5_error_code
crypto_cert_select(krb5_context context,pkinit_identity_crypto_context idctx,size_t cred_index)4974 crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx,
4975 size_t cred_index)
4976 {
4977 pkinit_cred_info ci = NULL;
4978
4979 if (cred_index >= MAX_CREDS_ALLOWED || idctx->creds[cred_index] == NULL)
4980 return ENOENT;
4981
4982 ci = idctx->creds[cred_index];
4983 /* copy the selected cert into our id_cryptoctx */
4984 if (idctx->my_certs != NULL)
4985 sk_X509_pop_free(idctx->my_certs, X509_free);
4986 idctx->my_certs = sk_X509_new_null();
4987 sk_X509_push(idctx->my_certs, ci->cert);
4988 free(idctx->identity);
4989 /* hang on to the selected credential name */
4990 if (ci->name != NULL)
4991 idctx->identity = strdup(ci->name);
4992 else
4993 idctx->identity = NULL;
4994
4995 ci->cert = NULL; /* Don't free it twice */
4996 idctx->cert_index = 0;
4997 if (idctx->pkcs11_method != 1) {
4998 idctx->my_key = ci->key;
4999 ci->key = NULL; /* Don't free it twice */
5000 }
5001 #ifndef WITHOUT_PKCS11
5002 else {
5003 idctx->cert_id = ci->cert_id;
5004 ci->cert_id = NULL; /* Don't free it twice */
5005 idctx->cert_id_len = ci->cert_id_len;
5006 }
5007 #endif
5008 return 0;
5009 }
5010
5011 /*
5012 * Choose the default certificate as "the chosen one"
5013 */
5014 krb5_error_code
crypto_cert_select_default(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx)5015 crypto_cert_select_default(krb5_context context,
5016 pkinit_plg_crypto_context plg_cryptoctx,
5017 pkinit_req_crypto_context req_cryptoctx,
5018 pkinit_identity_crypto_context id_cryptoctx)
5019 {
5020 krb5_error_code retval;
5021 int cert_count;
5022
5023 retval = crypto_cert_get_count(id_cryptoctx, &cert_count);
5024 if (retval)
5025 goto errout;
5026
5027 if (cert_count != 1) {
5028 TRACE_PKINIT_NO_DEFAULT_CERT(context, cert_count);
5029 retval = EINVAL;
5030 goto errout;
5031 }
5032 /* copy the selected cert into our id_cryptoctx */
5033 if (id_cryptoctx->my_certs != NULL) {
5034 sk_X509_pop_free(id_cryptoctx->my_certs, X509_free);
5035 }
5036 id_cryptoctx->my_certs = sk_X509_new_null();
5037 sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert);
5038 id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */
5039 id_cryptoctx->cert_index = 0;
5040 /* hang on to the selected credential name */
5041 if (id_cryptoctx->creds[0]->name != NULL)
5042 id_cryptoctx->identity = strdup(id_cryptoctx->creds[0]->name);
5043 else
5044 id_cryptoctx->identity = NULL;
5045
5046 if (id_cryptoctx->pkcs11_method != 1) {
5047 id_cryptoctx->my_key = id_cryptoctx->creds[0]->key;
5048 id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */
5049 }
5050 #ifndef WITHOUT_PKCS11
5051 else {
5052 id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id;
5053 id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */
5054 id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len;
5055 }
5056 #endif
5057 retval = 0;
5058 errout:
5059 return retval;
5060 }
5061
5062
5063
5064 static krb5_error_code
load_cas_and_crls(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int catype,char * filename)5065 load_cas_and_crls(krb5_context context,
5066 pkinit_plg_crypto_context plg_cryptoctx,
5067 pkinit_req_crypto_context req_cryptoctx,
5068 pkinit_identity_crypto_context id_cryptoctx,
5069 int catype,
5070 char *filename)
5071 {
5072 STACK_OF(X509_INFO) *sk = NULL;
5073 STACK_OF(X509) *ca_certs = NULL;
5074 STACK_OF(X509_CRL) *ca_crls = NULL;
5075 BIO *in = NULL;
5076 krb5_error_code retval = ENOMEM;
5077 int i = 0;
5078
5079 /* If there isn't already a stack in the context,
5080 * create a temporary one now */
5081 switch(catype) {
5082 case CATYPE_ANCHORS:
5083 if (id_cryptoctx->trustedCAs != NULL)
5084 ca_certs = id_cryptoctx->trustedCAs;
5085 else {
5086 ca_certs = sk_X509_new_null();
5087 if (ca_certs == NULL)
5088 return ENOMEM;
5089 }
5090 break;
5091 case CATYPE_INTERMEDIATES:
5092 if (id_cryptoctx->intermediateCAs != NULL)
5093 ca_certs = id_cryptoctx->intermediateCAs;
5094 else {
5095 ca_certs = sk_X509_new_null();
5096 if (ca_certs == NULL)
5097 return ENOMEM;
5098 }
5099 break;
5100 case CATYPE_CRLS:
5101 if (id_cryptoctx->revoked != NULL)
5102 ca_crls = id_cryptoctx->revoked;
5103 else {
5104 ca_crls = sk_X509_CRL_new_null();
5105 if (ca_crls == NULL)
5106 return ENOMEM;
5107 }
5108 break;
5109 default:
5110 return ENOTSUP;
5111 }
5112
5113 if (!(in = BIO_new_file(filename, "r"))) {
5114 retval = oerr(context, 0, _("Cannot open file '%s'"), filename);
5115 goto cleanup;
5116 }
5117
5118 /* This loads from a file, a stack of x509/crl/pkey sets */
5119 if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) {
5120 pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename);
5121 retval = oerr(context, 0, _("Cannot read file '%s'"), filename);
5122 goto cleanup;
5123 }
5124
5125 /* scan over the stack created from loading the file contents,
5126 * weed out duplicates, and push new ones onto the return stack
5127 */
5128 for (i = 0; i < sk_X509_INFO_num(sk); i++) {
5129 X509_INFO *xi = sk_X509_INFO_value(sk, i);
5130 if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) {
5131 int j = 0, size = sk_X509_num(ca_certs), flag = 0;
5132
5133 if (!size) {
5134 sk_X509_push(ca_certs, xi->x509);
5135 xi->x509 = NULL;
5136 continue;
5137 }
5138 for (j = 0; j < size; j++) {
5139 X509 *x = sk_X509_value(ca_certs, j);
5140 flag = X509_cmp(x, xi->x509);
5141 if (flag == 0)
5142 break;
5143 else
5144 continue;
5145 }
5146 if (flag != 0) {
5147 sk_X509_push(ca_certs, X509_dup(xi->x509));
5148 }
5149 } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) {
5150 int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0;
5151 if (!size) {
5152 sk_X509_CRL_push(ca_crls, xi->crl);
5153 xi->crl = NULL;
5154 continue;
5155 }
5156 for (j = 0; j < size; j++) {
5157 X509_CRL *x = sk_X509_CRL_value(ca_crls, j);
5158 flag = X509_CRL_cmp(x, xi->crl);
5159 if (flag == 0)
5160 break;
5161 else
5162 continue;
5163 }
5164 if (flag != 0) {
5165 sk_X509_CRL_push(ca_crls, X509_CRL_dup(xi->crl));
5166 }
5167 }
5168 }
5169
5170 /* If we added something and there wasn't a stack in the
5171 * context before, add the temporary stack to the context.
5172 */
5173 switch(catype) {
5174 case CATYPE_ANCHORS:
5175 if (sk_X509_num(ca_certs) == 0) {
5176 TRACE_PKINIT_NO_CA_ANCHOR(context, filename);
5177 if (id_cryptoctx->trustedCAs == NULL)
5178 sk_X509_free(ca_certs);
5179 } else {
5180 if (id_cryptoctx->trustedCAs == NULL)
5181 id_cryptoctx->trustedCAs = ca_certs;
5182 }
5183 break;
5184 case CATYPE_INTERMEDIATES:
5185 if (sk_X509_num(ca_certs) == 0) {
5186 TRACE_PKINIT_NO_CA_INTERMEDIATE(context, filename);
5187 if (id_cryptoctx->intermediateCAs == NULL)
5188 sk_X509_free(ca_certs);
5189 } else {
5190 if (id_cryptoctx->intermediateCAs == NULL)
5191 id_cryptoctx->intermediateCAs = ca_certs;
5192 }
5193 break;
5194 case CATYPE_CRLS:
5195 if (sk_X509_CRL_num(ca_crls) == 0) {
5196 TRACE_PKINIT_NO_CRL(context, filename);
5197 if (id_cryptoctx->revoked == NULL)
5198 sk_X509_CRL_free(ca_crls);
5199 } else {
5200 if (id_cryptoctx->revoked == NULL)
5201 id_cryptoctx->revoked = ca_crls;
5202 }
5203 break;
5204 default:
5205 /* Should have been caught above! */
5206 retval = EINVAL;
5207 goto cleanup;
5208 break;
5209 }
5210
5211 retval = 0;
5212
5213 cleanup:
5214 if (in != NULL)
5215 BIO_free(in);
5216 if (sk != NULL)
5217 sk_X509_INFO_pop_free(sk, X509_INFO_free);
5218
5219 return retval;
5220 }
5221
5222 static krb5_error_code
load_cas_and_crls_dir(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,int catype,char * dirname)5223 load_cas_and_crls_dir(krb5_context context,
5224 pkinit_plg_crypto_context plg_cryptoctx,
5225 pkinit_req_crypto_context req_cryptoctx,
5226 pkinit_identity_crypto_context id_cryptoctx,
5227 int catype,
5228 char *dirname)
5229 {
5230 krb5_error_code retval = EINVAL;
5231 DIR *d = NULL;
5232 struct dirent *dentry = NULL;
5233 char filename[1024];
5234
5235 if (dirname == NULL)
5236 return EINVAL;
5237
5238 d = opendir(dirname);
5239 if (d == NULL)
5240 return ENOENT;
5241
5242 while ((dentry = readdir(d))) {
5243 if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) {
5244 pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
5245 __FUNCTION__, dirname, dentry->d_name);
5246 goto cleanup;
5247 }
5248 /* Ignore subdirectories and anything starting with a dot */
5249 #ifdef DT_DIR
5250 if (dentry->d_type == DT_DIR)
5251 continue;
5252 #endif
5253 if (dentry->d_name[0] == '.')
5254 continue;
5255 snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
5256
5257 retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
5258 id_cryptoctx, catype, filename);
5259 if (retval)
5260 goto cleanup;
5261 }
5262
5263 retval = 0;
5264
5265 cleanup:
5266 if (d != NULL)
5267 closedir(d);
5268
5269 return retval;
5270 }
5271
5272 krb5_error_code
crypto_load_cas_and_crls(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_opts * idopts,pkinit_identity_crypto_context id_cryptoctx,int idtype,int catype,char * id)5273 crypto_load_cas_and_crls(krb5_context context,
5274 pkinit_plg_crypto_context plg_cryptoctx,
5275 pkinit_req_crypto_context req_cryptoctx,
5276 pkinit_identity_opts *idopts,
5277 pkinit_identity_crypto_context id_cryptoctx,
5278 int idtype,
5279 int catype,
5280 char *id)
5281 {
5282 switch (idtype) {
5283 case IDTYPE_FILE:
5284 TRACE_PKINIT_LOAD_FROM_FILE(context, id);
5285 return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
5286 id_cryptoctx, catype, id);
5287 break;
5288 case IDTYPE_DIR:
5289 TRACE_PKINIT_LOAD_FROM_DIR(context, id);
5290 return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
5291 id_cryptoctx, catype, id);
5292 break;
5293 default:
5294 return ENOTSUP;
5295 break;
5296 }
5297 }
5298
5299 static krb5_error_code
create_identifiers_from_stack(STACK_OF (X509)* sk,krb5_external_principal_identifier *** ids)5300 create_identifiers_from_stack(STACK_OF(X509) *sk,
5301 krb5_external_principal_identifier *** ids)
5302 {
5303 int i = 0, sk_size = sk_X509_num(sk);
5304 krb5_external_principal_identifier **krb5_cas = NULL;
5305 X509 *x = NULL;
5306 X509_NAME *xn = NULL;
5307 unsigned char *p = NULL;
5308 int len = 0;
5309 PKCS7_ISSUER_AND_SERIAL *is = NULL;
5310 char buf[DN_BUF_LEN];
5311
5312 *ids = NULL;
5313
5314 krb5_cas = calloc(sk_size + 1, sizeof(*krb5_cas));
5315 if (krb5_cas == NULL)
5316 return ENOMEM;
5317
5318 for (i = 0; i < sk_size; i++) {
5319 krb5_cas[i] = malloc(sizeof(krb5_external_principal_identifier));
5320
5321 x = sk_X509_value(sk, i);
5322
5323 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
5324 pkiDebug("#%d cert= %s\n", i, buf);
5325
5326 /* fill-in subjectName */
5327 krb5_cas[i]->subjectName.magic = 0;
5328 krb5_cas[i]->subjectName.length = 0;
5329 krb5_cas[i]->subjectName.data = NULL;
5330
5331 xn = X509_get_subject_name(x);
5332 len = i2d_X509_NAME(xn, NULL);
5333 if ((p = malloc((size_t) len)) == NULL)
5334 goto oom;
5335 krb5_cas[i]->subjectName.data = (char *)p;
5336 i2d_X509_NAME(xn, &p);
5337 krb5_cas[i]->subjectName.length = len;
5338
5339 /* fill-in issuerAndSerialNumber */
5340 krb5_cas[i]->issuerAndSerialNumber.length = 0;
5341 krb5_cas[i]->issuerAndSerialNumber.magic = 0;
5342 krb5_cas[i]->issuerAndSerialNumber.data = NULL;
5343
5344 is = PKCS7_ISSUER_AND_SERIAL_new();
5345 if (is == NULL)
5346 goto oom;
5347 X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
5348 ASN1_INTEGER_free(is->serial);
5349 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
5350 if (is->serial == NULL)
5351 goto oom;
5352 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
5353 p = malloc(len);
5354 if (p == NULL)
5355 goto oom;
5356 krb5_cas[i]->issuerAndSerialNumber.data = (char *)p;
5357 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
5358 krb5_cas[i]->issuerAndSerialNumber.length = len;
5359
5360 /* fill-in subjectKeyIdentifier */
5361 krb5_cas[i]->subjectKeyIdentifier.length = 0;
5362 krb5_cas[i]->subjectKeyIdentifier.magic = 0;
5363 krb5_cas[i]->subjectKeyIdentifier.data = NULL;
5364
5365 if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
5366 ASN1_OCTET_STRING *ikeyid;
5367
5368 ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
5369 NULL);
5370 if (ikeyid != NULL) {
5371 len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
5372 p = malloc(len);
5373 if (p == NULL)
5374 goto oom;
5375 krb5_cas[i]->subjectKeyIdentifier.data = (char *)p;
5376 i2d_ASN1_OCTET_STRING(ikeyid, &p);
5377 krb5_cas[i]->subjectKeyIdentifier.length = len;
5378 ASN1_OCTET_STRING_free(ikeyid);
5379 }
5380 }
5381 PKCS7_ISSUER_AND_SERIAL_free(is);
5382 is = NULL;
5383 }
5384
5385 *ids = krb5_cas;
5386 return 0;
5387
5388 oom:
5389 free_krb5_external_principal_identifier(&krb5_cas);
5390 PKCS7_ISSUER_AND_SERIAL_free(is);
5391 return ENOMEM;
5392 }
5393
5394 static krb5_error_code
create_krb5_invalidCertificates(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_external_principal_identifier *** ids)5395 create_krb5_invalidCertificates(krb5_context context,
5396 pkinit_plg_crypto_context plg_cryptoctx,
5397 pkinit_req_crypto_context req_cryptoctx,
5398 pkinit_identity_crypto_context id_cryptoctx,
5399 krb5_external_principal_identifier *** ids)
5400 {
5401
5402 krb5_error_code retval = ENOMEM;
5403 STACK_OF(X509) *sk = NULL;
5404
5405 *ids = NULL;
5406 if (req_cryptoctx->received_cert == NULL)
5407 return KRB5KDC_ERR_PREAUTH_FAILED;
5408
5409 sk = sk_X509_new_null();
5410 if (sk == NULL)
5411 goto cleanup;
5412 sk_X509_push(sk, req_cryptoctx->received_cert);
5413
5414 retval = create_identifiers_from_stack(sk, ids);
5415
5416 sk_X509_free(sk);
5417 cleanup:
5418
5419 return retval;
5420 }
5421
5422 krb5_error_code
create_krb5_supportedCMSTypes(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_algorithm_identifier *** algs_out)5423 create_krb5_supportedCMSTypes(krb5_context context,
5424 pkinit_plg_crypto_context plg_cryptoctx,
5425 pkinit_req_crypto_context req_cryptoctx,
5426 pkinit_identity_crypto_context id_cryptoctx,
5427 krb5_algorithm_identifier ***algs_out)
5428 {
5429 krb5_error_code ret;
5430 krb5_algorithm_identifier **algs = NULL;
5431 size_t i, count;
5432
5433 *algs_out = NULL;
5434
5435 /* Count supported OIDs and allocate list (including null terminator). */
5436 for (count = 0; supported_cms_algs[count] != NULL; count++);
5437 algs = k5calloc(count + 1, sizeof(*algs), &ret);
5438 if (algs == NULL)
5439 goto cleanup;
5440
5441 /* Add an algorithm identifier for each OID, with no parameters. */
5442 for (i = 0; i < count; i++) {
5443 algs[i] = k5alloc(sizeof(*algs[i]), &ret);
5444 if (algs[i] == NULL)
5445 goto cleanup;
5446 ret = krb5int_copy_data_contents(context, supported_cms_algs[i],
5447 &algs[i]->algorithm);
5448 if (ret)
5449 goto cleanup;
5450 algs[i]->parameters = empty_data();
5451 }
5452
5453 *algs_out = algs;
5454 algs = NULL;
5455
5456 cleanup:
5457 free_krb5_algorithm_identifiers(&algs);
5458 return ret;
5459 }
5460
5461 krb5_error_code
create_krb5_trustedCertifiers(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_external_principal_identifier *** ids)5462 create_krb5_trustedCertifiers(krb5_context context,
5463 pkinit_plg_crypto_context plg_cryptoctx,
5464 pkinit_req_crypto_context req_cryptoctx,
5465 pkinit_identity_crypto_context id_cryptoctx,
5466 krb5_external_principal_identifier *** ids)
5467 {
5468
5469 krb5_error_code retval = ENOMEM;
5470 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
5471
5472 *ids = NULL;
5473 if (id_cryptoctx->trustedCAs == NULL)
5474 return KRB5KDC_ERR_PREAUTH_FAILED;
5475
5476 retval = create_identifiers_from_stack(sk, ids);
5477
5478 return retval;
5479 }
5480
5481 krb5_error_code
create_issuerAndSerial(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,unsigned char ** out,unsigned int * out_len)5482 create_issuerAndSerial(krb5_context context,
5483 pkinit_plg_crypto_context plg_cryptoctx,
5484 pkinit_req_crypto_context req_cryptoctx,
5485 pkinit_identity_crypto_context id_cryptoctx,
5486 unsigned char **out,
5487 unsigned int *out_len)
5488 {
5489 unsigned char *p = NULL;
5490 PKCS7_ISSUER_AND_SERIAL *is = NULL;
5491 int len = 0;
5492 krb5_error_code retval = ENOMEM;
5493 X509 *cert = req_cryptoctx->received_cert;
5494
5495 *out = NULL;
5496 *out_len = 0;
5497 if (req_cryptoctx->received_cert == NULL)
5498 return 0;
5499
5500 is = PKCS7_ISSUER_AND_SERIAL_new();
5501 X509_NAME_set(&is->issuer, X509_get_issuer_name(cert));
5502 ASN1_INTEGER_free(is->serial);
5503 is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert));
5504 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
5505 if ((p = *out = malloc((size_t) len)) == NULL)
5506 goto cleanup;
5507 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
5508 *out_len = len;
5509 retval = 0;
5510
5511 cleanup:
5512 X509_NAME_free(is->issuer);
5513 ASN1_INTEGER_free(is->serial);
5514 free(is);
5515
5516 return retval;
5517 }
5518
5519 krb5_error_code
pkinit_process_td_trusted_certifiers(krb5_context context,pkinit_plg_crypto_context plg_cryptoctx,pkinit_req_crypto_context req_cryptoctx,pkinit_identity_crypto_context id_cryptoctx,krb5_external_principal_identifier ** krb5_trusted_certifiers,int td_type)5520 pkinit_process_td_trusted_certifiers(
5521 krb5_context context,
5522 pkinit_plg_crypto_context plg_cryptoctx,
5523 pkinit_req_crypto_context req_cryptoctx,
5524 pkinit_identity_crypto_context id_cryptoctx,
5525 krb5_external_principal_identifier **krb5_trusted_certifiers,
5526 int td_type)
5527 {
5528 krb5_error_code retval = ENOMEM;
5529 STACK_OF(X509_NAME) *sk_xn = NULL;
5530 X509_NAME *xn = NULL;
5531 PKCS7_ISSUER_AND_SERIAL *is = NULL;
5532 ASN1_OCTET_STRING *id = NULL;
5533 const unsigned char *p = NULL;
5534 char buf[DN_BUF_LEN];
5535 int i = 0;
5536
5537 if (td_type == TD_TRUSTED_CERTIFIERS)
5538 pkiDebug("received trusted certifiers\n");
5539 else
5540 pkiDebug("received invalid certificate\n");
5541
5542 sk_xn = sk_X509_NAME_new_null();
5543 while(krb5_trusted_certifiers[i] != NULL) {
5544 if (krb5_trusted_certifiers[i]->subjectName.data != NULL) {
5545 p = (unsigned char *)krb5_trusted_certifiers[i]->subjectName.data;
5546 xn = d2i_X509_NAME(NULL, &p,
5547 (int)krb5_trusted_certifiers[i]->subjectName.length);
5548 if (xn == NULL)
5549 goto cleanup;
5550 X509_NAME_oneline(xn, buf, sizeof(buf));
5551 if (td_type == TD_TRUSTED_CERTIFIERS)
5552 pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf);
5553 else
5554 pkiDebug("#%d cert = %s is invalid\n", i, buf);
5555 sk_X509_NAME_push(sk_xn, xn);
5556 }
5557
5558 if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) {
5559 p = (unsigned char *)
5560 krb5_trusted_certifiers[i]->issuerAndSerialNumber.data;
5561 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p,
5562 (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length);
5563 if (is == NULL)
5564 goto cleanup;
5565 X509_NAME_oneline(is->issuer, buf, sizeof(buf));
5566 if (td_type == TD_TRUSTED_CERTIFIERS)
5567 pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i,
5568 buf, ASN1_INTEGER_get(is->serial));
5569 else
5570 pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf,
5571 ASN1_INTEGER_get(is->serial));
5572 PKCS7_ISSUER_AND_SERIAL_free(is);
5573 }
5574
5575 if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) {
5576 p = (unsigned char *)
5577 krb5_trusted_certifiers[i]->subjectKeyIdentifier.data;
5578 id = d2i_ASN1_OCTET_STRING(NULL, &p,
5579 (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length);
5580 if (id == NULL)
5581 goto cleanup;
5582 /* XXX */
5583 ASN1_OCTET_STRING_free(id);
5584 }
5585 i++;
5586 }
5587 /* XXX Since we not doing anything with received trusted certifiers
5588 * return an error. this is the place where we can pick a different
5589 * client certificate based on the information in td_trusted_certifiers
5590 */
5591 retval = KRB5KDC_ERR_PREAUTH_FAILED;
5592 cleanup:
5593 if (sk_xn != NULL)
5594 sk_X509_NAME_pop_free(sk_xn, X509_NAME_free);
5595
5596 return retval;
5597 }
5598
5599 /* Originally based on OpenSSL's PKCS7_dataDecode(), now modified to remove the
5600 * use of BIO objects and to fit the PKINIT internal interfaces. */
5601 static int
pkcs7_decrypt(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,PKCS7 * p7,unsigned char ** data_out,unsigned int * len_out)5602 pkcs7_decrypt(krb5_context context,
5603 pkinit_identity_crypto_context id_cryptoctx, PKCS7 *p7,
5604 unsigned char **data_out, unsigned int *len_out)
5605 {
5606 krb5_error_code ret;
5607 int ok = 0, plaintext_len = 0, final_len;
5608 unsigned int keylen = 0, eklen = 0, blocksize;
5609 unsigned char *ek = NULL, *tkey = NULL, *plaintext = NULL, *use_key;
5610 ASN1_OCTET_STRING *data_body = p7->d.enveloped->enc_data->enc_data;
5611 const EVP_CIPHER *evp_cipher;
5612 EVP_CIPHER_CTX *evp_ctx = NULL;
5613 X509_ALGOR *enc_alg = p7->d.enveloped->enc_data->algorithm;
5614 STACK_OF(PKCS7_RECIP_INFO) *rsk = p7->d.enveloped->recipientinfo;
5615 PKCS7_RECIP_INFO *ri = NULL;
5616
5617 *data_out = NULL;
5618 *len_out = 0;
5619
5620 p7->state = PKCS7_S_HEADER;
5621
5622 /* RFC 4556 section 3.2.3.2 requires that there be exactly one
5623 * recipientInfo. */
5624 if (sk_PKCS7_RECIP_INFO_num(rsk) != 1) {
5625 pkiDebug("invalid number of EnvelopedData RecipientInfos\n");
5626 return 0;
5627 }
5628 ri = sk_PKCS7_RECIP_INFO_value(rsk, 0);
5629
5630 evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
5631 if (evp_cipher == NULL)
5632 goto cleanup;
5633 keylen = EVP_CIPHER_key_length(evp_cipher);
5634 blocksize = EVP_CIPHER_block_size(evp_cipher);
5635
5636 evp_ctx = EVP_CIPHER_CTX_new();
5637 if (evp_ctx == NULL)
5638 goto cleanup;
5639 if (!EVP_DecryptInit(evp_ctx, evp_cipher, NULL, NULL) ||
5640 EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) <= 0)
5641 goto cleanup;
5642
5643 /* Generate a random symmetric key to avoid exposing timing data if RSA
5644 * decryption fails the padding check. */
5645 tkey = malloc(keylen);
5646 if (tkey == NULL || !EVP_CIPHER_CTX_rand_key(evp_ctx, tkey))
5647 goto cleanup;
5648
5649 /* Decrypt the secret key with the private key. */
5650 ret = pkinit_decode_data(context, id_cryptoctx,
5651 ASN1_STRING_get0_data(ri->enc_key),
5652 ASN1_STRING_length(ri->enc_key), &ek, &eklen);
5653 use_key = (ret || eklen != keylen) ? tkey : ek;
5654
5655 /* Allocate a plaintext buffer and decrypt data_body into it. */
5656 plaintext = malloc(data_body->length + blocksize);
5657 if (plaintext == NULL)
5658 goto cleanup;
5659 if (!EVP_DecryptInit(evp_ctx, NULL, use_key, NULL))
5660 goto cleanup;
5661 if (!EVP_DecryptUpdate(evp_ctx, plaintext, &plaintext_len,
5662 data_body->data, data_body->length))
5663 goto cleanup;
5664 if (!EVP_DecryptFinal(evp_ctx, plaintext + plaintext_len, &final_len))
5665 goto cleanup;
5666 plaintext_len += final_len;
5667
5668 *len_out = plaintext_len;
5669 *data_out = plaintext;
5670 plaintext = NULL;
5671 ok = 1;
5672
5673 cleanup:
5674 EVP_CIPHER_CTX_free(evp_ctx);
5675 zapfree(plaintext, plaintext_len);
5676 zapfree(ek, eklen);
5677 zapfree(tkey, keylen);
5678 return ok;
5679 }
5680
5681 #ifdef DEBUG_DH
5682 static void
print_dh(DH * dh,char * msg)5683 print_dh(DH * dh, char *msg)
5684 {
5685 BIO *bio_err = NULL;
5686
5687 bio_err = BIO_new(BIO_s_file());
5688 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
5689
5690 if (msg)
5691 BIO_puts(bio_err, (const char *)msg);
5692 if (dh)
5693 DHparams_print(bio_err, dh);
5694
5695 BIO_puts(bio_err, "private key: ");
5696 BN_print(bio_err, dh->priv_key);
5697 BIO_puts(bio_err, (const char *)"\n");
5698 BIO_free(bio_err);
5699
5700 }
5701
5702 static void
print_pubkey(BIGNUM * key,char * msg)5703 print_pubkey(BIGNUM * key, char *msg)
5704 {
5705 BIO *bio_err = NULL;
5706
5707 bio_err = BIO_new(BIO_s_file());
5708 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
5709
5710 if (msg)
5711 BIO_puts(bio_err, (const char *)msg);
5712 if (key)
5713 BN_print(bio_err, key);
5714 BIO_puts(bio_err, "\n");
5715
5716 BIO_free(bio_err);
5717
5718 }
5719 #endif
5720
5721 static const char *
pkcs11err(int err)5722 pkcs11err(int err)
5723 {
5724 int i;
5725
5726 for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
5727 if (pkcs11_errstrings[i].code == err)
5728 break;
5729 if (pkcs11_errstrings[i].text != NULL)
5730 return (pkcs11_errstrings[i].text);
5731
5732 return "unknown PKCS11 error";
5733 }
5734
5735 /*
5736 * Add an item to the pkinit_identity_crypto_context's list of deferred
5737 * identities.
5738 */
5739 krb5_error_code
crypto_set_deferred_id(krb5_context context,pkinit_identity_crypto_context id_cryptoctx,const char * identity,const char * password)5740 crypto_set_deferred_id(krb5_context context,
5741 pkinit_identity_crypto_context id_cryptoctx,
5742 const char *identity, const char *password)
5743 {
5744 unsigned long ck_flags;
5745
5746 ck_flags = pkinit_get_deferred_id_flags(id_cryptoctx->deferred_ids,
5747 identity);
5748 return pkinit_set_deferred_id(&id_cryptoctx->deferred_ids,
5749 identity, ck_flags, password);
5750 }
5751
5752 /*
5753 * Retrieve a read-only copy of the pkinit_identity_crypto_context's list of
5754 * deferred identities, sure to be valid only until the next time someone calls
5755 * either pkinit_set_deferred_id() or crypto_set_deferred_id().
5756 */
5757 const pkinit_deferred_id *
crypto_get_deferred_ids(krb5_context context,pkinit_identity_crypto_context id_cryptoctx)5758 crypto_get_deferred_ids(krb5_context context,
5759 pkinit_identity_crypto_context id_cryptoctx)
5760 {
5761 pkinit_deferred_id *deferred;
5762 const pkinit_deferred_id *ret;
5763
5764 deferred = id_cryptoctx->deferred_ids;
5765 ret = (const pkinit_deferred_id *)deferred;
5766 return ret;
5767 }
5768
5769 /* Return the received certificate as DER-encoded data. */
5770 krb5_error_code
crypto_encode_der_cert(krb5_context context,pkinit_req_crypto_context reqctx,uint8_t ** der_out,size_t * der_len)5771 crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx,
5772 uint8_t **der_out, size_t *der_len)
5773 {
5774 int len;
5775 unsigned char *der, *p;
5776
5777 *der_out = NULL;
5778 *der_len = 0;
5779
5780 if (reqctx->received_cert == NULL)
5781 return EINVAL;
5782 p = NULL;
5783 len = i2d_X509(reqctx->received_cert, NULL);
5784 if (len <= 0)
5785 return EINVAL;
5786 p = der = malloc(len);
5787 if (der == NULL)
5788 return ENOMEM;
5789 if (i2d_X509(reqctx->received_cert, &p) <= 0) {
5790 free(der);
5791 return EINVAL;
5792 }
5793 *der_out = der;
5794 *der_len = len;
5795 return 0;
5796 }
5797
5798 /*
5799 * Get the certificate matching data from the request certificate.
5800 */
5801 krb5_error_code
crypto_req_cert_matching_data(krb5_context context,pkinit_plg_crypto_context plgctx,pkinit_req_crypto_context reqctx,pkinit_cert_matching_data ** md_out)5802 crypto_req_cert_matching_data(krb5_context context,
5803 pkinit_plg_crypto_context plgctx,
5804 pkinit_req_crypto_context reqctx,
5805 pkinit_cert_matching_data **md_out)
5806 {
5807 *md_out = NULL;
5808
5809 if (reqctx == NULL || reqctx->received_cert == NULL)
5810 return ENOENT;
5811
5812 return get_matching_data(context, plgctx, reqctx, reqctx->received_cert,
5813 md_out);
5814 }
5815