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