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