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