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