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