1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * COPYRIGHT (C) 2006,2007
4 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
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
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
32 #include "pkinit_crypto_openssl.h"
37 #include <arpa/inet.h>
39 static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
40 static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
42 static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
43 static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
45 static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
46 static void pkinit_fini_certs(pkinit_identity_crypto_context ctx);
48 static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx);
49 static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
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);
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);
61 static krb5_error_code create_signature
62 (unsigned char **, unsigned int *, unsigned char *, unsigned int,
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);
70 static krb5_error_code decode_data
71 (uint8_t **, unsigned int *, const uint8_t *, unsigned int, EVP_PKEY *pkey,
75 static void print_dh(DH *, char *);
76 static void print_pubkey(BIGNUM *, char *);
79 static int prepare_enc_data
80 (const uint8_t *indata, int indata_len, uint8_t **outdata, int *outdata_len);
82 static int openssl_callback (int, X509_STORE_CTX *);
83 static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
85 static int pkcs7_decrypt
86 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
89 static BIO * pkcs7_dataDecode
90 (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
93 static ASN1_OBJECT * pkinit_pkcs7type2oid
94 (pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type);
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);
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);
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);
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 */
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);
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);
146 static krb5_error_code
147 create_identifiers_from_stack(STACK_OF(X509) *sk,
148 krb5_external_principal_identifier *** ids);
150 wrap_signeddata(unsigned char *data, unsigned int data_len,
151 unsigned char **out, unsigned int *out_len);
154 pkinit_pkcs11_code_to_text(int err);
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)
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)
194 #if OPENSSL_VERSION_NUMBER < 0x10100000L
196 /* 1.1 standardizes constructor and destructor names, renaming
197 * EVP_MD_CTX_{create,destroy} and deprecating ASN1_STRING_data. */
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
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. */
206 #define OBJ_get0_data(o) ((o)->data)
207 #define OBJ_length(o) ((o)->length)
209 #define DH_set0_pqg compat_dh_set0_pqg
210 static int compat_dh_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
212 /* The real function frees the old values and does argument checking, but
213 * our code doesn't need that. */
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)
232 #define DH_get0_key compat_dh_get0_key
233 static void compat_dh_get0_key(const DH *dh, const BIGNUM **pub,
239 *priv = dh->priv_key;
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)))
247 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
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)))
254 static struct pkcs11_errstrings {
257 } pkcs11_errstrings[] = {
260 { 0x2, "host memory" },
261 { 0x3, "slot id invalid" },
262 { 0x5, "general error" },
263 { 0x6, "function failed" },
264 { 0x7, "arguments bad" },
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" },
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
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
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
468 MAKE_INIT_FUNCTION(pkinit_openssl_init);
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)))
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
483 static krb5_error_code
484 oerr(krb5_context context, krb5_error_code code, const char *fmt, ...)
492 code = KRB5KDC_ERR_PREAUTH_FAILED;
495 r = vasprintf(&str, fmt, ap);
500 err = ERR_peek_error();
502 krb5_set_error_message(context, code, _("%s: %s"), str,
503 ERR_reason_error_string(err));
505 krb5_set_error_message(context, code, "%s", str);
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);
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.
524 static krb5_error_code
525 oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx,
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);
532 return oerr(context, code, _("%s (depth %d): %s"), msg, depth, errstr);
536 pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
538 krb5_error_code retval = ENOMEM;
539 pkinit_plg_crypto_context ctx = NULL;
541 (void)CALL_INIT_FUNCTION(pkinit_openssl_init);
543 ctx = malloc(sizeof(*ctx));
546 memset(ctx, 0, sizeof(*ctx));
548 pkiDebug("%s: initializing openssl crypto context at %p\n",
550 retval = pkinit_init_pkinit_oids(ctx);
554 retval = pkinit_init_dh_params(ctx);
561 if (retval && ctx != NULL)
562 pkinit_fini_plg_crypto(ctx);
568 pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
570 pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
572 if (cryptoctx == NULL)
574 pkinit_fini_pkinit_oids(cryptoctx);
575 pkinit_fini_dh_params(cryptoctx);
580 pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
582 krb5_error_code retval = ENOMEM;
583 pkinit_identity_crypto_context ctx = NULL;
585 ctx = malloc(sizeof(*ctx));
588 memset(ctx, 0, sizeof(*ctx));
590 ctx->identity = NULL;
592 retval = pkinit_init_certs(ctx);
596 retval = pkinit_init_pkcs11(ctx);
600 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
606 pkinit_fini_identity_crypto(ctx);
613 pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
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);
628 pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
630 krb5_error_code retval = ENOMEM;
631 pkinit_req_crypto_context ctx = NULL;
633 ctx = malloc(sizeof(*ctx));
636 memset(ctx, 0, sizeof(*ctx));
639 ctx->received_cert = NULL;
643 pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
653 pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
655 if (req_cryptoctx == NULL)
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);
667 static krb5_error_code
668 pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
670 ctx->id_pkinit_san = OBJ_txt2obj("1.3.6.1.5.2.2", 1);
671 if (ctx->id_pkinit_san == NULL)
674 ctx->id_pkinit_authData = OBJ_txt2obj("1.3.6.1.5.2.3.1", 1);
675 if (ctx->id_pkinit_authData == NULL)
678 ctx->id_pkinit_DHKeyData = OBJ_txt2obj("1.3.6.1.5.2.3.2", 1);
679 if (ctx->id_pkinit_DHKeyData == NULL)
682 ctx->id_pkinit_rkeyData = OBJ_txt2obj("1.3.6.1.5.2.3.3", 1);
683 if (ctx->id_pkinit_rkeyData == NULL)
686 ctx->id_pkinit_KPClientAuth = OBJ_txt2obj("1.3.6.1.5.2.3.4", 1);
687 if (ctx->id_pkinit_KPClientAuth == NULL)
690 ctx->id_pkinit_KPKdc = OBJ_txt2obj("1.3.6.1.5.2.3.5", 1);
691 if (ctx->id_pkinit_KPKdc == NULL)
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)
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)
702 ctx->id_kp_serverAuth = OBJ_txt2obj("1.3.6.1.5.5.7.3.1", 1);
703 if (ctx->id_kp_serverAuth == NULL)
709 static krb5_error_code
710 get_cert(char *filename, X509 **retcert)
715 krb5_error_code retval;
717 if (filename == NULL || retcert == NULL)
722 tmp = BIO_new(BIO_s_file());
726 code = BIO_read_filename(tmp, filename);
732 cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
735 pkiDebug("failed to read certificate from %s\n", filename);
746 struct get_key_cb_data {
747 krb5_context context;
748 pkinit_identity_crypto_context id_cryptoctx;
751 const char *password;
755 get_key_cb(char *buf, int size, int rwflag, void *userdata)
757 struct get_key_cb_data *data = userdata;
758 pkinit_identity_crypto_context id_cryptoctx;
761 krb5_prompt_type prompt_type;
762 krb5_error_code retval;
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);
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)
775 if (asprintf(&prompt, "%s %s", _("Pass phrase for"),
780 kprompt.prompt = prompt;
782 kprompt.reply = &rdat;
783 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
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);
796 /* Just use the already-supplied password. */
797 rdat.length = strlen(data->password);
798 if ((int)rdat.length >= size)
800 snprintf(buf, size, "%s", data->password);
802 return (int)rdat.length;
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)
810 EVP_PKEY *pkey = NULL;
812 struct get_key_cb_data cb_data;
814 krb5_error_code retval;
816 if (filename == NULL || retkey == NULL)
819 tmp = BIO_new(BIO_s_file());
823 code = BIO_read_filename(tmp, filename);
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) {
836 pkiDebug("failed to read private key from %s\n", filename);
848 pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
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);
863 /* Construct an OpenSSL DH object for an Oakley group. */
865 make_oakley_dh(uint8_t *prime, size_t len)
868 BIGNUM *p = NULL, *q = NULL, *g = NULL;
870 p = BN_bin2bn(prime, len, NULL);
876 if (!BN_rshift1(q, p))
881 if (!BN_set_word(g, DH_GENERATOR_2))
887 DH_set0_pqg(dh, p, q, g);
897 static krb5_error_code
898 pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
900 krb5_error_code retval = ENOMEM;
902 plgctx->dh_1024 = make_oakley_dh(oakley_1024, sizeof(oakley_1024));
903 if (plgctx->dh_1024 == NULL)
906 plgctx->dh_2048 = make_oakley_dh(oakley_2048, sizeof(oakley_2048));
907 if (plgctx->dh_2048 == NULL)
910 plgctx->dh_4096 = make_oakley_dh(oakley_4096, sizeof(oakley_4096));
911 if (plgctx->dh_4096 == NULL)
918 pkinit_fini_dh_params(plgctx);
924 pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)
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);
933 plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL;
936 static krb5_error_code
937 pkinit_init_certs(pkinit_identity_crypto_context ctx)
939 krb5_error_code retval = ENOMEM;
942 for (i = 0; i < MAX_CREDS_ALLOWED; i++)
943 ctx->creds[i] = NULL;
944 ctx->my_certs = NULL;
947 ctx->trustedCAs = NULL;
948 ctx->intermediateCAs = NULL;
956 pkinit_fini_certs(pkinit_identity_crypto_context ctx)
961 if (ctx->my_certs != NULL)
962 sk_X509_pop_free(ctx->my_certs, X509_free);
964 if (ctx->my_key != NULL)
965 EVP_PKEY_free(ctx->my_key);
967 if (ctx->trustedCAs != NULL)
968 sk_X509_pop_free(ctx->trustedCAs, X509_free);
970 if (ctx->intermediateCAs != NULL)
971 sk_X509_pop_free(ctx->intermediateCAs, X509_free);
973 if (ctx->revoked != NULL)
974 sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free);
977 static krb5_error_code
978 pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
980 krb5_error_code retval = ENOMEM;
982 #ifndef WITHOUT_PKCS11
983 ctx->p11_module_name = strdup(PKCS11_MODNAME);
984 if (ctx->p11_module_name == NULL)
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;
993 ctx->pkcs11_method = 0;
1000 pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
1002 #ifndef WITHOUT_PKCS11
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;
1011 ctx->p11->C_Finalize(NULL_PTR);
1014 if (ctx->p11_module != NULL) {
1015 pkinit_C_UnloadModule(ctx->p11_module);
1016 ctx->p11_module = NULL;
1018 free(ctx->p11_module_name);
1019 free(ctx->token_label);
1021 free(ctx->cert_label);
1026 pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
1027 krb5_prompter_fct prompter,
1028 void *prompter_data)
1030 id_cryptoctx->prompter = prompter;
1031 id_cryptoctx->prompter_data = prompter_data;
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)
1042 ASN1_OCTET_STRING *ostr = NULL;
1046 ostr = ASN1_OCTET_STRING_new();
1049 if (!ASN1_OCTET_STRING_set(ostr, (unsigned char *)data, data_len))
1055 p7->type = OBJ_dup(oid);
1056 if (p7->type == NULL)
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. */
1064 p7->d.other = ASN1_TYPE_new();
1065 if (p7->d.other == NULL)
1067 p7->d.other->type = V_ASN1_OCTET_STRING;
1068 p7->d.other->value.octet_string = ostr;
1076 ASN1_OCTET_STRING_free(ostr);
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 */
1088 unsigned char *data, unsigned int data_len,
1089 unsigned char **out_data, unsigned int *out_data_len)
1091 krb5_error_code retval = ENOMEM;
1096 /* Pick the correct oid for the eContentInfo. */
1097 oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
1100 retval = create_contentinfo(context, oid, data, data_len, &p7);
1103 *out_data_len = i2d_PKCS7(p7, NULL);
1104 if (!(*out_data_len)) {
1105 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1109 if ((p = *out_data = malloc(*out_data_len)) == NULL)
1112 /* DER encode PKCS7 data */
1113 retval = i2d_PKCS7(p7, &p);
1115 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
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,
1133 int include_certchain,
1134 unsigned char *data,
1135 unsigned int data_len,
1136 unsigned char **signed_data,
1137 unsigned int *signed_data_len)
1139 krb5_error_code retval = ENOMEM;
1140 PKCS7 *p7 = NULL, *inner_p7 = NULL;
1141 PKCS7_SIGNED *p7s = NULL;
1142 PKCS7_SIGNER_INFO *p7si = NULL;
1144 STACK_OF(X509) * cert_stack = NULL;
1145 ASN1_OCTET_STRING *digest_attr = NULL;
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;
1159 ASN1_OBJECT *oid = NULL, *oid_copy;
1161 /* Start creating PKCS7 data. */
1162 if ((p7 = PKCS7_new()) == NULL)
1164 p7->type = OBJ_nid2obj(NID_pkcs7_signed);
1166 if ((p7s = PKCS7_SIGNED_new()) == NULL)
1169 if (!ASN1_INTEGER_set(p7s->version, 3))
1172 /* pick the correct oid for the eContentInfo */
1173 oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
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)
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));
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;
1194 if ((certstore = X509_STORE_new()) == NULL)
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)
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"));
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));
1218 X509_STORE_CTX_free(certctx);
1219 X509_STORE_free(certstore);
1220 sk_X509_pop_free(certstack, X509_free);
1222 p7s->cert = cert_stack;
1224 /* fill-in PKCS7_SIGNER_INFO */
1225 if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
1227 if (!ASN1_INTEGER_set(p7si->version, 1))
1229 if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
1230 X509_get_issuer_name(cert)))
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))))
1239 /* will not fill-out EVP_PKEY because it's on the smartcard */
1241 /* Set digest algs */
1242 p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
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)
1248 p7si->digest_alg->parameter->type = V_ASN1_NULL;
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()))
1256 p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
1258 if (cms_msg_type == CMS_SIGN_DRAFT9){
1259 /* don't include signed attributes for pa-type 15 request */
1263 /* add signed attributes */
1264 /* compute sha1 digest over the EncapsulatedContentInfo */
1265 ctx = EVP_MD_CTX_new();
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);
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);
1280 /* create a content-type attr */
1281 oid_copy = OBJ_dup(oid);
1282 if (oid_copy == NULL)
1284 PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
1285 V_ASN1_OBJECT, oid_copy);
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));
1294 } /* signed attributes */
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 }
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();
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);
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);
1319 alg = X509_ALGOR_new();
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)
1328 digest = ASN1_OCTET_STRING_new();
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)
1337 digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
1339 y = digestInfo_buf = malloc(digestInfo_len);
1340 if (digestInfo_buf == NULL)
1342 ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
1344 i2d_X509_ALGOR(alg, &y);
1345 i2d_ASN1_OCTET_STRING(digest, &y);
1347 pkiDebug("signing buffer\n");
1348 print_buffer(digestInfo_buf, digestInfo_len);
1349 print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
1351 retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
1352 digestInfo_len, &sig, &sig_len);
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,
1362 print_buffer(sig, sig_len);
1364 if (cms_msg_type != CMS_SIGN_DRAFT9 )
1370 if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
1372 retval = oerr(context, 0, _("Failed to add digest attribute"));
1375 /* adder signer_info to pkcs7 signed */
1376 if (!PKCS7_add_signer(p7, p7si))
1378 } /* we have a certificate */
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;
1386 *signed_data_len = i2d_PKCS7(p7, NULL);
1387 if (!(*signed_data_len)) {
1388 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1392 if ((p = *signed_data = malloc(*signed_data_len)) == NULL)
1395 /* DER encode PKCS7 data */
1396 retval = i2d_PKCS7(p7, &p);
1398 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1404 if (cms_msg_type == CMS_SIGN_CLIENT) {
1405 print_buffer_bin(*signed_data, *signed_data_len,
1406 "/tmp/client_pkcs7_signeddata");
1408 if (cms_msg_type == CMS_SIGN_SERVER) {
1409 print_buffer_bin(*signed_data, *signed_data_len,
1410 "/tmp/kdc_pkcs7_signeddata");
1412 print_buffer_bin(*signed_data, *signed_data_len,
1413 "/tmp/draft9_pkcs7_signeddata");
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) {
1425 free(digestInfo_buf);
1428 ASN1_OCTET_STRING_free(digest);
1432 X509_ALGOR_free(alg);
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,
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,
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.
1464 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
1465 CMS_ContentInfo *cms = NULL;
1467 int flags = CMS_NO_SIGNER_CERT_VERIFY;
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;
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];
1490 print_buffer_bin(signed_data, signed_data_len,
1491 "/tmp/client_received_pkcs7_signeddata");
1496 oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
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"));
1505 etype = CMS_get0_eContentType(cms);
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.
1512 type = CMS_get0_type(cms);
1513 if (is_signed && !OBJ_cmp(type, oid)) {
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 "
1524 *data_len = ASN1_STRING_length(*octets);
1525 d = malloc(*data_len);
1530 memcpy(d, ASN1_STRING_get0_data(*octets), *data_len);
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",
1538 krb5_set_error_message(context, retval, _("wrong oid\n"));
1543 /* setup to verify X509 certificate used to sign CMS message */
1544 if (!(store = X509_STORE_new()))
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);
1552 X509_STORE_set_verify_cb(store, openssl_callback_ignore_crls);
1553 X509_STORE_set_flags(store, vflags);
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.
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 */
1570 /* We cannot use CMS_dataInit because there may be no digest */
1571 octets = pkinit_CMS_get0_content_signed(cms);
1573 out = BIO_new_mem_buf((*octets)->data, (*octets)->length);
1577 pkinit_CMS_SignerInfo_get_cert(cms, si, &x);
1581 /* create available CRL information (get local CRLs and include CRLs
1582 * received in the CMS message
1584 signerRevoked = CMS_get1_crls(cms);
1585 if (idctx->revoked == NULL)
1586 revoked = signerRevoked;
1587 else if (signerRevoked == NULL)
1588 revoked = idctx->revoked;
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));
1599 /* create available intermediate CAs chains (get local intermediateCAs and
1600 * include the CA chain received in the CMS message
1602 signerCerts = CMS_get1_certs(cms);
1603 if (idctx->intermediateCAs == NULL)
1604 intermediateCAs = signerCerts;
1605 else if (signerCerts == NULL)
1606 intermediateCAs = idctx->intermediateCAs;
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));
1614 size = sk_X509_num(signerCerts);
1615 for (i = 0; i < size; i++) {
1616 sk_X509_push(intermediateCAs, sk_X509_value(signerCerts, i));
1620 /* initialize x509 context with the received certificate and
1621 * trusted and intermediate CA chains and CRLs
1623 cert_ctx = X509_STORE_CTX_new();
1624 if (cert_ctx == NULL)
1626 if (!X509_STORE_CTX_init(cert_ctx, store, x, intermediateCAs))
1629 X509_STORE_CTX_set0_crls(cert_ctx, revoked);
1631 /* add trusted CAs certificates for cert verification */
1632 if (idctx->trustedCAs != NULL)
1633 X509_STORE_CTX_trusted_stack(cert_ctx, idctx->trustedCAs);
1635 pkiDebug("unable to find any trusted CAs\n");
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);
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);
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);
1668 i = X509_verify_cert(cert_ctx);
1670 int j = X509_STORE_CTX_get_error(cert_ctx);
1673 cert = X509_STORE_CTX_get_current_cert(cert_ctx);
1674 reqctx->received_cert = X509_dup(cert);
1676 case X509_V_ERR_CERT_REVOKED:
1677 retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
1679 case X509_V_ERR_UNABLE_TO_GET_CRL:
1680 retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN;
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;
1687 retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
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));
1694 X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
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);
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);
1712 X509_STORE_CTX_free(cert_ctx);
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;
1724 case PKCS7_R_SIGNATURE_FAILURE:
1726 retval = KRB5KDC_ERR_INVALID_SIG;
1728 (void)oerr(context, retval, _("Failed to verify CMS message"));
1731 } /* message was signed */
1732 if (!OBJ_cmp(etype, oid))
1734 else if (cms_msg_type == CMS_SIGN_DRAFT9) {
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
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))
1751 pkiDebug("CMS Verification successful\n");
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");
1760 /* transfer the data from CMS message into return buffer */
1764 if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
1766 remain = BIO_read(out, &((*data)[size]), 1024 * 10);
1775 reqctx->received_cert = X509_dup(x);
1777 /* generate authorization data */
1778 if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) {
1780 if (authz_data == NULL || authz_data_len == NULL)
1784 retval = create_identifiers_from_stack(verified_chain,
1785 &krb5_verified_chain);
1787 pkiDebug("create_identifiers_from_stack failed\n");
1791 retval = k5int_encode_krb5_td_trusted_certifiers((krb5_external_principal_identifier *const *)krb5_verified_chain, &authz);
1793 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
1797 print_buffer_bin((unsigned char *)authz->data, authz->length,
1798 "/tmp/kdc_ad_initial_verified_cas");
1800 *authz_data = malloc(authz->length);
1801 if (*authz_data == NULL) {
1805 memcpy(*authz_data, authz->data, authz->length);
1806 *authz_data_len = authz->length;
1816 X509_STORE_free(store);
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);
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);
1833 krb5_free_data(context, authz);
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)
1851 krb5_error_code retval = ENOMEM;
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;
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;
1866 case KRB5_PADATA_PK_AS_REQ:
1867 cms_msg_type = CMS_ENVEL_SERVER;
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);
1877 pkiDebug("failed to create pkcs7 signed data\n");
1881 /* check we have client's certificate */
1882 if (reqctx->received_cert == NULL) {
1883 retval = KRB5KDC_ERR_PREAUTH_FAILED;
1886 encerts = sk_X509_new_null();
1887 sk_X509_push(encerts, reqctx->received_cert);
1889 cipher = EVP_des_ede3_cbc();
1890 in = BIO_new(BIO_s_mem());
1892 case KRB5_PADATA_PK_AS_REQ:
1893 prepare_enc_data(signed_data, signed_data_len, &enc_data,
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);
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);
1914 p7 = PKCS7_encrypt(encerts, in, cipher, flags);
1916 retval = oerr(context, 0, _("Failed to encrypt PKCS7 object"));
1920 case KRB5_PADATA_PK_AS_REQ:
1921 p7->d.enveloped->enc_data->content_type =
1922 OBJ_nid2obj(NID_pkcs7_signed);
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);
1934 *out_len = i2d_PKCS7(p7, NULL);
1935 if (!*out_len || (p = *out = malloc(*out_len)) == NULL) {
1939 retval = i2d_PKCS7(p7, &p);
1941 retval = oerr(context, 0, _("Failed to DER encode PKCS7"));
1947 print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data");
1957 if (encerts != NULL)
1958 sk_X509_free(encerts);
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)
1975 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
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;
1986 print_buffer_bin(enveloped_data, enveloped_data_len,
1987 "/tmp/client_envelopeddata");
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"));
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");
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");
2008 retval = oerr(context, 0, _("Failed to decrypt PKCS7 message"));
2012 /* transfer the decoded PKCS7 SignedData message into a separate buffer */
2014 if ((tmp_buf = realloc(tmp_buf, size + 1024 * 10)) == NULL)
2016 i = BIO_read(out, &(tmp_buf[size]), 1024 * 10);
2025 print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack");
2027 /* verify PKCS7 SignedData message */
2029 case KRB5_PADATA_PK_AS_REP:
2030 msg_type = CMS_ENVEL_SERVER;
2033 case KRB5_PADATA_PK_AS_REP_OLD:
2034 msg_type = CMS_SIGN_DRAFT9;
2037 pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__, pa_type);
2038 retval = KRB5KDC_ERR_PREAUTH_FAILED;
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.
2047 if (msg_type == CMS_ENVEL_SERVER) {
2048 retval = wrap_signeddata(tmp_buf, tmp_buf_len,
2049 &tmp_buf2, &tmp_buf2_len);
2051 pkiDebug("failed to encode signeddata\n");
2055 vfy_buf_len = tmp_buf2_len;
2059 vfy_buf_len = tmp_buf_len;
2063 print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2");
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);
2073 pkiDebug("PKCS7 Verification Success\n");
2075 pkiDebug("PKCS7 Verification Failure\n");
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,
2098 krb5_principal **princs_ret,
2099 krb5_principal **upn_ret,
2100 unsigned char ***dns_ret)
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;
2110 if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
2111 pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
2116 pkiDebug("%s: no certificate!\n", __FUNCTION__);
2120 X509_NAME_oneline(X509_get_subject_name(cert),
2122 pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
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;
2129 unsigned int num_sans = 0;
2131 if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) {
2132 pkiDebug("%s: found no subject alt name extensions\n",
2136 num_sans = sk_GENERAL_NAME_num(ialt);
2138 pkiDebug("%s: found %d subject alt name extension(s)\n",
2139 __FUNCTION__, num_sans);
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) {
2149 if (upn_ret != NULL) {
2150 upns = calloc(num_sans + 1, sizeof(krb5_principal));
2156 if (dns_ret != NULL) {
2157 dnss = calloc(num_sans + 1, sizeof(*dnss));
2164 for (i = 0; i < num_sans; i++) {
2165 krb5_data name = { 0, 0, NULL };
2167 gen = sk_GENERAL_NAME_value(ialt, i);
2168 switch (gen->type) {
2170 name.length = gen->d.otherName->value->value.sequence->length;
2171 name.data = (char *)gen->d.otherName->value->value.sequence->data;
2173 && OBJ_cmp(plgctx->id_pkinit_san,
2174 gen->d.otherName->type_id) == 0) {
2176 print_buffer_bin((unsigned char *)name.data, name.length,
2179 ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
2181 pkiDebug("%s: failed decoding pkinit san value\n",
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))
2193 ret = krb5_parse_name(context, name.data, &upns[u]);
2195 pkiDebug("%s: failed parsing ms-upn san value\n",
2202 pkiDebug("%s: unrecognized othername oid in SAN\n",
2210 /* Prevent abuse of embedded null characters. */
2211 if (memchr(gen->d.dNSName->data, '\0',
2212 gen->d.dNSName->length))
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",
2228 pkiDebug("%s: SAN type = %d expecting %d\n",
2229 __FUNCTION__, gen->type, GEN_OTHERNAME);
2232 sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
2237 *princs_ret = princs;
2245 if (princs != NULL) {
2246 for (i = 0; princs[i] != NULL; i++)
2247 krb5_free_principal(context, princs[i]);
2251 for (i = 0; upns[i] != NULL; i++)
2252 krb5_free_principal(context, upns[i]);
2256 for (i = 0; dnss[i] != NULL; i++)
2265 crypto_retrieve_signer_identity(krb5_context context,
2266 pkinit_identity_crypto_context id_cryptoctx,
2267 const char **identity)
2269 *identity = id_cryptoctx->identity;
2270 if (*identity == NULL)
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)
2284 krb5_error_code retval = EINVAL;
2286 if (reqctx->received_cert == NULL) {
2287 pkiDebug("%s: No certificate!\n", __FUNCTION__);
2291 return crypto_retrieve_X509_sans(context, plgctx, reqctx,
2292 reqctx->received_cert, princs_ret,
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,
2305 char buf[DN_BUF_LEN];
2307 krb5_error_code retval = EINVAL;
2311 if (reqctx->received_cert == NULL)
2314 X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
2316 pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
2318 if ((i = X509_get_ext_by_NID(reqctx->received_cert,
2319 NID_ext_key_usage, -1)) >= 0) {
2320 EXTENDED_KEY_USAGE *extusage;
2322 extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage,
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;
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))
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))
2346 EXTENDED_KEY_USAGE_free(extusage);
2349 ASN1_BIT_STRING *usage = NULL;
2350 pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
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))) {
2357 if (!ku_reject(reqctx->received_cert,
2358 X509v3_KU_DIGITAL_SIGNATURE)) {
2359 pkiDebug("%s: found digitalSignature KU\n",
2363 pkiDebug("%s: didn't find digitalSignature KU\n",
2366 ASN1_BIT_STRING_free(usage);
2371 pkiDebug("%s: returning retval %d, valid_eku %d\n",
2372 __FUNCTION__, retval, *valid_eku);
2377 pkinit_octetstring2key(krb5_context context,
2380 unsigned int dh_key_len,
2381 krb5_keyblock *key_block)
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;
2390 if ((buf = malloc(dh_key_len)) == NULL) {
2394 memset(buf, 0, dh_key_len);
2402 SHA1_Update(&c, &counter, 1);
2403 SHA1_Update(&c, key, dh_key_len);
2406 if (dh_key_len - offset < sizeof(md))
2407 memcpy(buf + offset, md, dh_key_len - offset);
2409 memcpy(buf + offset, md, sizeof(md));
2411 offset += sizeof(md);
2413 } while (offset < dh_key_len);
2415 key_block->magic = 0;
2416 key_block->enctype = etype;
2418 retval = krb5_c_keylengths(context, etype, &keybytes, &keylength);
2422 key_block->length = keylength;
2423 key_block->contents = malloc(keylength);
2424 if (key_block->contents == NULL) {
2429 random_data.length = keybytes;
2430 random_data.data = (char *)buf;
2432 retval = krb5_c_random_to_key(context, etype, &random_data, key_block);
2436 /* If this is an error return, free the allocated keyblock, if any */
2438 krb5_free_keyblock_contents(context, key_block);
2446 * Given an algorithm_identifier, this function returns the hash length
2447 * and EVP function associated with that algorithm.
2449 static krb5_error_code
2450 pkinit_alg_values(krb5_context context,
2451 const krb5_data *alg_id,
2453 const EVP_MD *(**func)(void))
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))) {
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))) {
2467 *func = &EVP_sha256;
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))) {
2473 *func = &EVP_sha512;
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;
2480 } /* pkinit_alg_values() */
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:
2488 * 1. reps = keydatalen (K) / hash length (H)
2490 * 2. Initialize a 32-bit, big-endian bit string counter as 1.
2492 * 3. For i = 1 to reps by 1, do the following:
2494 * - Compute Hashi = H(counter || Z || OtherInfo).
2496 * - Increment counter (modulo 2^32)
2498 * 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
2501 pkinit_alg_agility_kdf(krb5_context context,
2504 krb5_const_principal party_u_info,
2505 krb5_const_principal party_v_info,
2506 krb5_enctype enctype,
2508 krb5_data *pk_as_rep,
2509 krb5_keyblock *key_block)
2511 krb5_error_code retval = 0;
2513 unsigned int reps = 0;
2514 uint32_t counter = 1; /* Does this type work on Windows? */
2516 size_t hash_len = 0;
2517 size_t rand_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);
2528 /* initialize random_data here to make clean-up safe */
2529 random_data.length = 0;
2530 random_data.data = NULL;
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,
2539 random_data.length = rand_len;
2540 key_block->length = key_len;
2542 if (NULL == (key_block->contents = malloc(key_block->length))) {
2547 memset (key_block->contents, 0, key_block->length);
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();
2554 if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
2557 /* 1. reps = keydatalen (K) / hash length (H) */
2558 reps = key_block->length/hash_len;
2560 /* ... and round up, if necessary */
2561 if (key_block->length > (reps * hash_len))
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))) {
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,
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*/
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)))
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)
2595 for (counter = 1; counter <= reps; counter++) {
2597 uint32_t be_counter = htonl(counter);
2599 ctx = EVP_MD_CTX_new();
2601 retval = KRB5_CRYPTO_INTERNAL;
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;
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;
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;
2630 assert(s == hash_len);
2632 EVP_MD_CTX_free(ctx);
2636 retval = krb5_c_random_to_key(context, enctype, &random_data,
2640 EVP_MD_CTX_free(ctx);
2642 /* If this has been an error, free the allocated key_block, if any */
2644 krb5_free_keyblock_contents(context, key_block);
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);
2654 } /*pkinit_alg_agility_kdf() */
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. */
2659 compute_dh(unsigned char *buf, int size, BIGNUM *server_pub_key, DH *dh)
2663 len = DH_compute_key(buf, server_pub_key, dh);
2664 assert(len >= 0 && len <= size);
2667 memmove(buf + pad, buf, len);
2668 memset(buf, 0, pad);
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,
2678 unsigned char **dh_params,
2679 unsigned int *dh_params_len,
2680 unsigned char **dh_pubkey,
2681 unsigned int *dh_pubkey_len)
2683 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
2684 unsigned char *buf = NULL;
2686 ASN1_INTEGER *pub_key = NULL;
2687 const BIGNUM *pubkey_bn, *p, *q, *g;
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)
2700 DH_generate_key(cryptoctx->dh);
2701 DH_get0_key(cryptoctx->dh, &pubkey_bn, NULL);
2703 DH_check(cryptoctx->dh, &dh_err);
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");
2716 print_dh(cryptoctx->dh, "client's DH params\n");
2717 print_pubkey(cryptoctx->dh->pub_key, "client's pub_key=");
2720 DH_check_pub_key(cryptoctx->dh, pubkey_bn, &dh_err);
2722 pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
2727 /* aglo: usually we could just call i2d_DHparams to encode DH params
2728 * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
2730 DH_get0_pqg(cryptoctx->dh, &p, &q, &g);
2731 retval = pkinit_encode_dh_params(p, g, q, dh_params, dh_params_len);
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
2741 pub_key = BN_to_ASN1_INTEGER(pubkey_bn, NULL);
2742 if (pub_key == NULL) {
2746 *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
2747 if ((buf = *dh_pubkey = malloc(*dh_pubkey_len)) == NULL) {
2751 i2d_ASN1_INTEGER(pub_key, &buf);
2753 if (pub_key != NULL)
2754 ASN1_INTEGER_free(pub_key);
2760 if (cryptoctx->dh != NULL)
2761 DH_free(cryptoctx->dh);
2762 cryptoctx->dh = NULL;
2767 if (pub_key != NULL)
2768 ASN1_INTEGER_free(pub_key);
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)
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;
2788 *client_key_len = DH_size(cryptoctx->dh);
2789 if ((*client_key = malloc(*client_key_len)) == NULL) {
2793 p = subjectPublicKey_data;
2794 pub_key = d2i_ASN1_INTEGER(NULL, &p, (long)subjectPublicKey_length);
2795 if (pub_key == NULL)
2797 if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL)
2800 compute_dh(*client_key, *client_key_len, server_pub_key, cryptoctx->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);
2808 if (server_pub_key != NULL)
2809 BN_free(server_pub_key);
2810 if (pub_key != NULL)
2811 ASN1_INTEGER_free(pub_key);
2818 if (pub_key != NULL)
2819 ASN1_INTEGER_free(pub_key);
2824 /* Return 1 if dh is a permitted well-known group, otherwise return 0. */
2826 check_dh_wellknown(pkinit_plg_crypto_context cryptoctx, DH *dh, int nbits)
2831 /* Oakley MODP group 2 */
2832 if (pkinit_check_dh_params(cryptoctx->dh_1024, dh) == 0)
2837 /* Oakley MODP group 14 */
2838 if (pkinit_check_dh_params(cryptoctx->dh_2048, dh) == 0)
2843 /* Oakley MODP group 16 */
2844 if (pkinit_check_dh_params(cryptoctx->dh_4096, dh) == 0)
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,
2865 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
2867 dh = decode_dh_params((uint8_t *)dh_params->data, dh_params->length);
2869 pkiDebug("failed to decode dhparams\n");
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);
2882 if (check_dh_wellknown(cryptoctx, dh, dh_prime_bits))
2887 req_cryptoctx->dh = dh;
2894 /* Duplicate a DH handle (parameters only, not public or private key). */
2896 dup_dh_params(const DH *src)
2898 const BIGNUM *oldp, *oldq, *oldg;
2899 BIGNUM *p = NULL, *q = NULL, *g = NULL;
2902 DH_get0_pqg(src, &oldp, &oldq, &oldg);
2907 if (p == NULL || q == NULL || g == NULL || dh == NULL) {
2914 DH_set0_pqg(dh, p, q, g);
2918 /* kdc's dh function */
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)
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;
2938 *dh_pubkey = *server_key = NULL;
2939 *dh_pubkey_len = *server_key_len = 0;
2941 /* get client's received DH parameters that we saved in server_check_dh */
2943 dh_server = dup_dh_params(dh);
2944 if (dh_server == NULL)
2947 /* decode client's public key */
2949 pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len);
2950 if (pub_key == NULL)
2952 client_pubkey = ASN1_INTEGER_to_BN(pub_key, NULL);
2953 if (client_pubkey == NULL)
2955 ASN1_INTEGER_free(pub_key);
2957 if (!DH_generate_key(dh_server))
2959 DH_get0_key(dh_server, &server_pubkey, NULL);
2961 /* generate DH session key */
2962 *server_key_len = DH_size(dh_server);
2963 if ((*server_key = malloc(*server_key_len)) == NULL)
2965 compute_dh(*server_key, *server_key_len, client_pubkey, dh_server);
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);
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
2982 pub_key = BN_to_ASN1_INTEGER(server_pubkey, NULL);
2983 if (pub_key == NULL)
2985 *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
2986 if ((p = *dh_pubkey = malloc(*dh_pubkey_len)) == NULL)
2988 i2d_ASN1_INTEGER(pub_key, &p);
2989 if (pub_key != NULL)
2990 ASN1_INTEGER_free(pub_key);
2994 if (dh_server != NULL)
2999 BN_free(client_pubkey);
3008 pkinit_openssl_init()
3010 /* Initialize OpenSSL. */
3011 ERR_load_crypto_strings();
3012 OpenSSL_add_all_algorithms();
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)
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;
3025 if ((ap = BN_to_ASN1_INTEGER(p, NULL)) == NULL)
3027 if ((ag = BN_to_ASN1_INTEGER(g, NULL)) == NULL)
3029 if ((aq = BN_to_ASN1_INTEGER(q, NULL)) == NULL)
3031 bufsize = i2d_ASN1_INTEGER(ap, NULL);
3032 bufsize += i2d_ASN1_INTEGER(ag, NULL);
3033 bufsize += i2d_ASN1_INTEGER(aq, NULL);
3035 r = ASN1_object_size(1, bufsize, V_ASN1_SEQUENCE);
3037 tmp = *buf = malloc((size_t) r);
3041 ASN1_put_object(&tmp, 1, bufsize, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3043 i2d_ASN1_INTEGER(ap, &tmp);
3044 i2d_ASN1_INTEGER(ag, &tmp);
3045 i2d_ASN1_INTEGER(aq, &tmp);
3053 ASN1_INTEGER_free(ap);
3055 ASN1_INTEGER_free(ag);
3057 ASN1_INTEGER_free(aq);
3062 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
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
3073 ASN1_BIT_STRING *seed;
3082 int_dhvparams *vparams;
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)
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)
3099 decode_dh_params(const uint8_t *p, unsigned int len)
3101 int_dhx942_dh *params;
3108 params = (int_dhx942_dh *)ASN1_item_d2i(NULL, &p, len,
3109 ASN1_ITEM_rptr(DHxparams));
3110 if (params == NULL) {
3115 /* Steal the p, q, and g values from dhparams for dh. Ignore j and
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));
3123 #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
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
3133 decode_dh_params_int(DH ** a, uint8_t **pp, unsigned int len)
3135 ASN1_INTEGER ai, *aip = NULL;
3136 long length = (long) len;
3138 M_ASN1_D2I_vars(a, DH *, DH_new);
3141 M_ASN1_D2I_start_sequence();
3145 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
3149 ret->p = ASN1_INTEGER_to_BN(aip, NULL);
3152 if (ai.data != NULL) {
3153 OPENSSL_free(ai.data);
3158 M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
3162 ret->g = ASN1_INTEGER_to_BN(aip, NULL);
3165 if (ai.data != NULL) {
3166 OPENSSL_free(ai.data);
3172 M_ASN1_D2I_get_opt(aip, d2i_ASN1_INTEGER, V_ASN1_INTEGER);
3173 if (aip == NULL || ai.data == NULL)
3176 ret->q = ASN1_INTEGER_to_BN(aip, NULL);
3179 if (ai.data != NULL) {
3180 OPENSSL_free(ai.data);
3186 M_ASN1_D2I_end_sequence();
3187 M_ASN1_D2I_Finish(a, DH_free, 0);
3192 decode_dh_params(const uint8_t *p, unsigned int len)
3194 uint8_t *ptr = (uint8_t *)p;
3196 return decode_dh_params_int(NULL, &ptr, len);
3199 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
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,
3208 krb5_pa_data ***e_data_out)
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;
3216 case TD_TRUSTED_CERTIFIERS:
3217 retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
3218 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
3220 pkiDebug("create_krb5_trustedCertifiers failed\n");
3224 case TD_INVALID_CERTIFICATES:
3225 retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
3226 req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
3228 pkiDebug("create_krb5_invalidCertificates failed\n");
3237 retval = k5int_encode_krb5_td_trusted_certifiers((krb5_external_principal_identifier *const *)krb5_trusted_certifiers, &td_certifiers);
3239 pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
3243 print_buffer_bin((unsigned char *)td_certifiers->data,
3244 td_certifiers->length, "/tmp/kdc_td_certifiers");
3246 pa_data = malloc(2 * sizeof(krb5_pa_data *));
3247 if (pa_data == NULL) {
3252 pa_data[0] = malloc(sizeof(krb5_pa_data));
3253 if (pa_data[0] == NULL) {
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;
3265 if (krb5_trusted_certifiers != NULL)
3266 free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
3267 free(td_certifiers);
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)
3278 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
3280 retval = pkinit_create_sequence_of_principal_identifiers(context,
3281 plg_cryptoctx, req_cryptoctx, id_cryptoctx,
3282 TD_TRUSTED_CERTIFIERS, e_data_out);
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)
3295 krb5_error_code retval = KRB5KRB_ERR_GENERIC;
3297 retval = pkinit_create_sequence_of_principal_identifiers(context,
3298 plg_cryptoctx, req_cryptoctx, id_cryptoctx,
3299 TD_INVALID_CERTIFICATES, e_data_out);
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)
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;
3320 if (opts->dh_min_bits > 4096)
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);
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);
3335 DH_get0_pqg(plg_cryptoctx->dh_4096, &p, &q, &g);
3336 retval = pkinit_encode_dh_params(p, g, q, &buf3, &buf3_len);
3340 if (opts->dh_min_bits <= 1024) {
3341 algId = malloc(4 * sizeof(krb5_algorithm_identifier *));
3345 algId[0] = malloc(sizeof(krb5_algorithm_identifier));
3346 if (algId[0] == NULL)
3348 algId[0]->parameters.data = malloc(buf2_len);
3349 if (algId[0]->parameters.data == NULL)
3351 memcpy(algId[0]->parameters.data, buf2, buf2_len);
3352 algId[0]->parameters.length = buf2_len;
3353 algId[0]->algorithm = dh_oid;
3355 algId[1] = malloc(sizeof(krb5_algorithm_identifier));
3356 if (algId[1] == NULL)
3358 algId[1]->parameters.data = malloc(buf3_len);
3359 if (algId[1]->parameters.data == NULL)
3361 memcpy(algId[1]->parameters.data, buf3, buf3_len);
3362 algId[1]->parameters.length = buf3_len;
3363 algId[1]->algorithm = dh_oid;
3365 algId[2] = malloc(sizeof(krb5_algorithm_identifier));
3366 if (algId[2] == NULL)
3368 algId[2]->parameters.data = malloc(buf1_len);
3369 if (algId[2]->parameters.data == NULL)
3371 memcpy(algId[2]->parameters.data, buf1, buf1_len);
3372 algId[2]->parameters.length = buf1_len;
3373 algId[2]->algorithm = dh_oid;
3375 } else if (opts->dh_min_bits <= 2048) {
3376 algId = malloc(3 * sizeof(krb5_algorithm_identifier *));
3380 algId[0] = malloc(sizeof(krb5_algorithm_identifier));
3381 if (algId[0] == NULL)
3383 algId[0]->parameters.data = malloc(buf2_len);
3384 if (algId[0]->parameters.data == NULL)
3386 memcpy(algId[0]->parameters.data, buf2, buf2_len);
3387 algId[0]->parameters.length = buf2_len;
3388 algId[0]->algorithm = dh_oid;
3390 algId[1] = malloc(sizeof(krb5_algorithm_identifier));
3391 if (algId[1] == NULL)
3393 algId[1]->parameters.data = malloc(buf3_len);
3394 if (algId[1]->parameters.data == NULL)
3396 memcpy(algId[1]->parameters.data, buf3, buf3_len);
3397 algId[1]->parameters.length = buf3_len;
3398 algId[1]->algorithm = dh_oid;
3400 } else if (opts->dh_min_bits <= 4096) {
3401 algId = malloc(2 * sizeof(krb5_algorithm_identifier *));
3405 algId[0] = malloc(sizeof(krb5_algorithm_identifier));
3406 if (algId[0] == NULL)
3408 algId[0]->parameters.data = malloc(buf3_len);
3409 if (algId[0]->parameters.data == NULL)
3411 memcpy(algId[0]->parameters.data, buf3, buf3_len);
3412 algId[0]->parameters.length = buf3_len;
3413 algId[0]->algorithm = dh_oid;
3416 retval = k5int_encode_krb5_td_dh_parameters((krb5_algorithm_identifier *const *)algId, &encoded_algId);
3420 print_buffer_bin((unsigned char *)encoded_algId->data,
3421 encoded_algId->length, "/tmp/kdc_td_dh_params");
3423 pa_data = malloc(2 * sizeof(krb5_pa_data *));
3424 if (pa_data == NULL) {
3429 pa_data[0] = malloc(sizeof(krb5_pa_data));
3430 if (pa_data[0] == NULL) {
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;
3445 free(encoded_algId);
3447 if (algId != NULL) {
3448 while(algId[i] != NULL) {
3449 free(algId[i]->parameters.data);
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,
3468 PKCS7_ISSUER_AND_SERIAL *is = NULL;
3469 const unsigned char *p = pdid_buf;
3471 X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
3474 pkiDebug("found kdcPkId in AS REQ\n");
3475 is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
3477 return KRB5KDC_ERR_PREAUTH_FAILED;
3479 status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
3481 status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
3486 X509_NAME_free(is->issuer);
3487 ASN1_INTEGER_free(is->serial);
3493 /* Check parameters against a well-known DH group. */
3495 pkinit_check_dh_params(DH *dh1, DH *dh2)
3497 const BIGNUM *p1, *p2, *g1, *g2;
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");
3505 if (BN_cmp(g1, g2) != 0) {
3506 pkiDebug("bad g dhparameter\n");
3509 pkiDebug("good %d dhparams\n", BN_num_bits(p1));
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,
3521 krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3522 int i = 0, use_sent_dh = 0, ok = 0;
3524 pkiDebug("dh parameters\n");
3526 while (algId[i] != NULL) {
3529 int dh_prime_bits = 0;
3531 if (algId[i]->algorithm.length != dh_oid.length ||
3532 memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
3535 dh = decode_dh_params((uint8_t *)algId[i]->parameters.data,
3536 algId[i]->parameters.length);
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);
3545 *new_dh_size = dh_prime_bits;
3548 DH_check(dh, &retval);
3550 pkiDebug("DH parameters provided by server are unacceptable\n");
3551 retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
3561 if (req_cryptoctx->dh != NULL) {
3562 DH_free(req_cryptoctx->dh);
3563 req_cryptoctx->dh = NULL;
3566 req_cryptoctx->dh = dh;
3580 openssl_callback(int ok, X509_STORE_CTX * ctx)
3584 char buf[DN_BUF_LEN];
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));
3596 openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
3600 return X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL;
3603 static ASN1_OBJECT *
3604 pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
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;
3622 wrap_signeddata(unsigned char *data, unsigned int data_len,
3623 unsigned char **out, unsigned int *out_len)
3626 unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
3627 ASN1_OBJECT *oid = NULL;
3628 unsigned char *p = NULL;
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);
3633 /* Add the signedData OID and adjust lengths */
3634 oid = OBJ_nid2obj(NID_pkcs7_signed);
3635 oid_len = i2d_ASN1_OBJECT(oid, NULL);
3637 tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
3639 p = *out = malloc(tot_len);
3640 if (p == NULL) return -1;
3642 ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
3643 V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
3645 i2d_ASN1_OBJECT(oid, &p);
3647 ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
3648 memcpy(p, data, data_len);
3656 prepare_enc_data(const uint8_t *indata, int indata_len, uint8_t **outdata,
3661 const uint8_t *p = indata, *oldp;
3663 if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80)
3665 if (tag != V_ASN1_SEQUENCE)
3669 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3674 if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80)
3677 *outdata = malloc(tlen);
3678 if (*outdata == NULL)
3680 memcpy(*outdata, p, tlen);
3681 *outdata_len = tlen;
3685 #ifndef WITHOUT_PKCS11
3687 pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p)
3690 CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
3692 pkiDebug("loading module \"%s\"... ", modname);
3693 handle = dlopen(modname, RTLD_NOW);
3694 if (handle == NULL) {
3695 pkiDebug("not found\n");
3698 getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(handle, "C_GetFunctionList");
3699 if (getflist == NULL || (*getflist)(p11p) != CKR_OK) {
3701 pkiDebug("failed\n");
3709 pkinit_C_UnloadModule(void *handle)
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)
3722 const char *warning;
3723 krb5_prompt kprompt;
3724 krb5_prompt_type prompt_type;
3727 if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
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;
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)";
3745 if (asprintf(&prompt, "%.*s PIN%s", (int) sizeof (tip->label),
3746 tip->label, warning) < 0)
3748 rdat.data = malloc(tip->ulMaxPinLen + 2);
3749 rdat.length = tip->ulMaxPinLen + 1;
3751 kprompt.prompt = prompt;
3753 kprompt.reply = &rdat;
3754 prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
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);
3765 r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
3766 (u_char *) rdat.data, rdat.length);
3769 pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r));
3770 r = KRB5KDC_ERR_PREAUTH_FAILED;
3778 static krb5_error_code
3779 pkinit_open_session(krb5_context context,
3780 pkinit_identity_crypto_context cctx)
3786 CK_SLOT_ID_PTR slotlist;
3787 CK_TOKEN_INFO tinfo;
3789 const char *password;
3791 if (cctx->p11_module != NULL)
3792 return 0; /* session already open */
3796 pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11);
3797 if (cctx->p11_module == NULL)
3798 return KRB5KDC_ERR_PREAUTH_FAILED;
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;
3806 /* Get the list of available slots */
3807 if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK)
3808 return KRB5KDC_ERR_PREAUTH_FAILED;
3810 return KRB5KDC_ERR_PREAUTH_FAILED;
3811 slotlist = calloc(count, sizeof(CK_SLOT_ID));
3812 if (slotlist == NULL)
3814 if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK)
3815 return KRB5KDC_ERR_PREAUTH_FAILED;
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])
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;
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;
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] != ' ')
3842 label_len = cp - tinfo.label;
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))
3850 cctx->p11->C_CloseSession(cctx->session);
3854 pkiDebug("open_session: no matching token found\n");
3855 return KRB5KDC_ERR_PREAUTH_FAILED;
3857 cctx->slotid = slotlist[i];
3859 pkiDebug("open_session: slotid %d (%lu of %d)\n", (int)cctx->slotid,
3860 i + 1, (int) count);
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)
3872 if (asprintf(&p11name,
3873 "PKCS11:module_name=%s,token=%.*s",
3874 cctx->p11_module_name,
3875 (int)label_len, tinfo.label) < 0)
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);
3886 return KRB5KRB_ERR_GENERIC;
3888 /* Look up a responder-supplied password for the token. */
3889 password = pkinit_find_deferred_id(cctx->deferred_ids, p11name);
3891 r = pkinit_login(context, cctx, &tinfo, password);
3898 * Look for a key that's:
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
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)
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.
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.
3915 pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
3916 CK_ATTRIBUTE_TYPE usage,
3917 CK_OBJECT_HANDLE *objp)
3919 CK_OBJECT_CLASS cls;
3920 CK_ATTRIBUTE attrs[4];
3922 CK_KEY_TYPE keytype;
3923 unsigned int nattrs = 0;
3925 #ifdef PKINIT_USE_KEY_USAGE
3926 CK_BBOOL true_false;
3929 cls = CKO_PRIVATE_KEY;
3930 attrs[nattrs].type = CKA_CLASS;
3931 attrs[nattrs].pValue = &cls;
3932 attrs[nattrs].ulValueLen = sizeof cls;
3935 #ifdef PKINIT_USE_KEY_USAGE
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.
3943 attrs[nattrs].type = usage;
3944 attrs[nattrs].pValue = &true_false;
3945 attrs[nattrs].ulValueLen = sizeof true_false;
3950 attrs[nattrs].type = CKA_KEY_TYPE;
3951 attrs[nattrs].pValue = &keytype;
3952 attrs[nattrs].ulValueLen = sizeof keytype;
3955 attrs[nattrs].type = CKA_ID;
3956 attrs[nattrs].pValue = id_cryptoctx->cert_id;
3957 attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
3960 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
3962 pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
3963 pkinit_pkcs11_code_to_text(r));
3964 return KRB5KDC_ERR_PREAUTH_FAILED;
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;
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)
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;
3991 #ifndef WITHOUT_PKCS11
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
4000 pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,
4001 CK_BYTE_PTR pEncryptedData,
4002 CK_ULONG ulEncryptedDataLen,
4004 CK_ULONG_PTR pulDataLen)
4008 rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData,
4009 ulEncryptedDataLen, pData, pulDataLen);
4011 pkiDebug("pData %p *pulDataLen %d\n", (void *) pData,
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)
4024 CK_OBJECT_HANDLE obj;
4030 if (pkinit_open_session(context, id_cryptoctx)) {
4031 pkiDebug("can't open pkcs11 session\n");
4032 return KRB5KDC_ERR_PREAUTH_FAILED;
4035 pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj);
4037 mech.mechanism = CKM_RSA_PKCS;
4038 mech.pParameter = NULL;
4039 mech.ulParameterLen = 0;
4041 if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech,
4043 pkiDebug("C_DecryptInit: 0x%x\n", (int) r);
4044 return KRB5KDC_ERR_PREAUTH_FAILED;
4046 pkiDebug("data_len = %d\n", data_len);
4047 cp = malloc((size_t) 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,
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;
4062 pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len);
4063 *decoded_data_len = len;
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)
4076 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
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
4083 retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data,
4084 data_len, decoded_data, decoded_data_len);
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)
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;
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)
4115 CK_OBJECT_HANDLE obj;
4121 if (pkinit_open_session(context, id_cryptoctx)) {
4122 pkiDebug("can't open pkcs11 session\n");
4123 return KRB5KDC_ERR_PREAUTH_FAILED;
4126 pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
4128 mech.mechanism = id_cryptoctx->mech;
4129 mech.pParameter = NULL;
4130 mech.ulParameterLen = 0;
4132 if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
4134 pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r));
4135 return KRB5KDC_ERR_PREAUTH_FAILED;
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.
4142 len = PK_SIGLEN_GUESS;
4143 cp = malloc((size_t) len);
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)) {
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);
4157 pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r));
4158 return KRB5KDC_ERR_PREAUTH_FAILED;
4160 pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
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)
4176 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4178 if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1)
4179 retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len,
4181 #ifndef WITHOUT_PKCS11
4183 retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len,
4192 decode_data(uint8_t **out_data, unsigned int *out_data_len,
4193 const uint8_t *data, unsigned int data_len, EVP_PKEY *pkey,
4197 unsigned char *buf = NULL;
4200 if (cert && !X509_check_private_key(cert, pkey)) {
4201 pkiDebug("private key does not match certificate\n");
4205 buf_len = EVP_PKEY_size(pkey);
4206 buf = malloc((size_t) buf_len + 10);
4210 #if OPENSSL_VERSION_NUMBER >= 0x00909000L
4211 retval = EVP_PKEY_decrypt_old(buf, data, (int)data_len, pkey);
4213 retval = EVP_PKEY_decrypt(buf, data, (int)data_len, pkey);
4216 pkiDebug("unable to decrypt received data (len=%d)\n", data_len);
4221 *out_data_len = retval;
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)
4230 krb5_error_code retval = ENOMEM;
4236 ctx = EVP_MD_CTX_new();
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)
4244 EVP_SignFinal(ctx, *sig, sig_len, pkey);
4249 EVP_MD_CTX_free(ctx);
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.
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)
4268 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4270 req_cryptoctx->received_cert = NULL;
4276 reassemble_pkcs12_name(const char *filename)
4280 if (asprintf(&ret, "PKCS12:%s", filename) < 0)
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)
4293 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4294 char *prompt_string = NULL;
4301 if (idopts->cert_filename == NULL) {
4302 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
4306 if (idopts->key_filename == NULL) {
4307 pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
4311 fp = fopen(idopts->cert_filename, "rb");
4313 pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
4314 idopts->cert_filename, errno);
4317 set_cloexec_file(fp);
4319 p12 = d2i_PKCS12_fp(fp, NULL);
4322 pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
4323 idopts->cert_filename);
4327 * Try parsing with no pass phrase first. If that fails,
4328 * prompt for the pass phrase and try again.
4330 ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
4333 krb5_prompt kprompt;
4334 krb5_prompt_type prompt_type;
4336 char prompt_reply[128];
4337 char *prompt_prefix = _("Pass phrase for");
4338 char *p12name = reassemble_pkcs12_name(idopts->cert_filename);
4341 pkiDebug("Initial PKCS12_parse with no password failed\n");
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,
4351 /* Try to read a responder-supplied password. */
4352 tmp = pkinit_find_deferred_id(id_cryptoctx->deferred_ids, p12name);
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. */
4362 /* Ask using a prompter. */
4363 memset(prompt_reply, '\0', sizeof(prompt_reply));
4364 rdat.data = prompt_reply;
4365 rdat.length = sizeof(prompt_reply);
4367 if (asprintf(&prompt_string, "%s %s", prompt_prefix,
4368 idopts->cert_filename) < 0) {
4369 prompt_string = NULL;
4372 kprompt.prompt = prompt_string;
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);
4382 pkiDebug("Failed to prompt for PKCS12 password");
4387 ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
4389 pkiDebug("Second PKCS12_parse with password failed\n");
4393 id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
4394 if (id_cryptoctx->creds[0] == NULL)
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;
4403 id_cryptoctx->creds[0]->key = y;
4404 id_cryptoctx->creds[1] = NULL;
4409 free(prompt_string);
4422 reassemble_files_name(const char *certfile, const char *keyfile)
4426 if (keyfile != NULL) {
4427 if (asprintf(&ret, "FILE:%s,%s", certfile, keyfile) < 0)
4430 if (asprintf(&ret, "FILE:%s", certfile) < 0)
4436 static krb5_error_code
4437 pkinit_load_fs_cert_and_key(krb5_context context,
4438 pkinit_identity_crypto_context id_cryptoctx,
4443 krb5_error_code retval;
4446 char *fsname = NULL;
4447 const char *password;
4449 fsname = reassemble_files_name(certname, keyname);
4451 /* Try to read a responder-supplied password. */
4452 password = pkinit_find_deferred_id(id_cryptoctx->deferred_ids, fsname);
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'"),
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);
4468 id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
4469 if (id_cryptoctx->creds[cindex] == NULL) {
4473 id_cryptoctx->creds[cindex]->name = reassemble_files_name(certname,
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;
4480 id_cryptoctx->creds[cindex]->key = y;
4481 id_cryptoctx->creds[cindex+1] = NULL;
4487 if (retval != 0 || y == NULL) {
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)
4504 krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
4506 if (idopts->cert_filename == NULL) {
4507 pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
4511 if (idopts->key_filename == NULL) {
4512 pkiDebug("%s: failed to get user's private key location\n",
4517 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
4518 idopts->cert_filename,
4519 idopts->key_filename, 0);
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)
4532 krb5_error_code retval = ENOMEM;
4534 struct dirent *dentry = NULL;
4535 char certname[1024];
4538 char *dirname, *suf;
4540 if (idopts->cert_filename == NULL) {
4541 pkiDebug("%s: failed to get user's certificate directory location\n",
4546 dirname = idopts->cert_filename;
4547 d = opendir(dirname);
4552 * We'll assume that certs are named XXX.crt and the corresponding
4553 * key is named XXX.key
4555 while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) {
4556 /* Ignore subdirectories and anything starting with a dot */
4558 if (dentry->d_type == DT_DIR)
4561 if (dentry->d_name[0] == '.')
4563 len = strlen(dentry->d_name);
4566 suf = dentry->d_name + (len - 4);
4567 if (strncmp(suf, ".crt", 4) != 0)
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);
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';
4583 retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
4584 certname, keyname, i);
4586 pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
4587 __FUNCTION__, dentry->d_name);
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);
4610 #ifndef WITHOUT_PKCS11
4612 reassemble_pkcs11_name(pkinit_identity_opts *idopts)
4618 k5_buf_init_dynamic(&buf);
4619 k5_buf_add(&buf, "PKCS11:");
4621 if (idopts->p11_module_name != NULL) {
4622 k5_buf_add_fmt(&buf, "%smodule_name=%s", n++ ? ":" : "",
4623 idopts->p11_module_name);
4625 if (idopts->token_label != NULL) {
4626 k5_buf_add_fmt(&buf, "%stoken=%s", n++ ? ":" : "",
4627 idopts->token_label);
4629 if (idopts->cert_label != NULL) {
4630 k5_buf_add_fmt(&buf, "%scertlabel=%s", n++ ? ":" : "",
4631 idopts->cert_label);
4633 if (idopts->cert_id_string != NULL) {
4634 k5_buf_add_fmt(&buf, "%scertid=%s", n++ ? ":" : "",
4635 idopts->cert_id_string);
4637 if (idopts->slotid != PK_NOSLOT) {
4638 k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "",
4639 (long)idopts->slotid);
4641 if (k5_buf_status(&buf) == 0)
4642 ret = strdup(buf.data);
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)
4657 #ifdef PKINIT_USE_MECH_LIST
4658 CK_MECHANISM_TYPE_PTR mechp;
4659 CK_MECHANISM_INFO info;
4661 CK_OBJECT_CLASS cls;
4662 CK_OBJECT_HANDLE obj;
4663 CK_ATTRIBUTE attrs[4];
4665 CK_CERTIFICATE_TYPE certtype;
4666 CK_BYTE_PTR cert = NULL, cert_id;
4667 const unsigned char *cp;
4669 unsigned int nattrs;
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)
4679 if (idopts->token_label != NULL) {
4680 id_cryptoctx->token_label = strdup(idopts->token_label);
4681 if (id_cryptoctx->token_label == NULL)
4684 if (idopts->cert_label != NULL) {
4685 id_cryptoctx->cert_label = strdup(idopts->cert_label);
4686 if (id_cryptoctx->cert_label == NULL)
4689 /* Convert the ascii cert_id string into a binary blob */
4690 if (idopts->cert_id_string != NULL) {
4692 BN_hex2bn(&bn, idopts->cert_id_string);
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) {
4701 BN_bn2bin(bn, id_cryptoctx->cert_id);
4704 id_cryptoctx->slotid = idopts->slotid;
4705 id_cryptoctx->pkcs11_method = 1;
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;
4712 if (id_cryptoctx->defer_id_prompt) {
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.
4718 pkinit_fini_pkcs11(id_cryptoctx);
4719 pkinit_init_pkcs11(id_cryptoctx);
4723 #ifndef PKINIT_USE_MECH_LIST
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.
4731 id_cryptoctx->mech = CKM_RSA_PKCS;
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;
4738 mechp = malloc(count * sizeof (CK_MECHANISM_TYPE));
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");
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;
4761 pkiDebug("got %d mechs from card\n", (int) count);
4764 cls = CKO_CERTIFICATE;
4765 attrs[0].type = CKA_CLASS;
4766 attrs[0].pValue = &cls;
4767 attrs[0].ulValueLen = sizeof cls;
4769 certtype = CKC_X_509;
4770 attrs[1].type = CKA_CERTIFICATE_TYPE;
4771 attrs[1].pValue = &certtype;
4772 attrs[1].ulValueLen = sizeof certtype;
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;
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);
4790 r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
4792 pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r));
4793 return KRB5KDC_ERR_PREAUTH_FAILED;
4796 for (i = 0; ; i++) {
4797 if (i >= MAX_CREDS_ALLOWED)
4798 return KRB5KDC_ERR_PREAUTH_FAILED;
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;
4807 /* Get cert and id len */
4808 attrs[0].type = CKA_VALUE;
4809 attrs[0].pValue = NULL;
4810 attrs[0].ulValueLen = 0;
4812 attrs[1].type = CKA_ID;
4813 attrs[1].pValue = NULL;
4814 attrs[1].ulValueLen = 0;
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;
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)
4826 /* Read the cert and id off the card */
4828 attrs[0].type = CKA_VALUE;
4829 attrs[0].pValue = cert;
4831 attrs[1].type = CKA_ID;
4832 attrs[1].pValue = cert_id;
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;
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);
4844 cp = (unsigned char *) cert;
4845 x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen);
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;
4858 id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
4860 return KRB5KDC_ERR_PREAUTH_FAILED;
4867 free_cred_info(krb5_context context,
4868 pkinit_identity_crypto_context id_cryptoctx,
4869 struct _pkinit_cred_info *cred)
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);
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)
4892 if (id_cryptoctx == NULL)
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;
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)
4913 krb5_error_code retval;
4915 id_cryptoctx->defer_id_prompt = defer_id_prompts;
4917 switch(idopts->idtype) {
4919 retval = pkinit_get_certs_fs(context, plg_cryptoctx,
4920 req_cryptoctx, idopts,
4921 id_cryptoctx, princ);
4924 retval = pkinit_get_certs_dir(context, plg_cryptoctx,
4925 req_cryptoctx, idopts,
4926 id_cryptoctx, princ);
4928 #ifndef WITHOUT_PKCS11
4930 retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx,
4931 req_cryptoctx, idopts,
4932 id_cryptoctx, princ);
4936 retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx,
4937 req_cryptoctx, idopts,
4938 id_cryptoctx, princ);
4951 * Get number of certificates available after crypto_load_certs()
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,
4962 if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
4966 count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
4968 *cert_count = count;
4974 * Begin iteration over the certs loaded in crypto_load_certs()
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)
4983 struct _pkinit_cert_iter_data *id;
4985 if (id_cryptoctx == NULL || ih_ret == NULL)
4987 if (id_cryptoctx->creds[0] == NULL) /* No cred info available */
4990 id = calloc(1, sizeof(*id));
4993 id->magic = ITER_MAGIC;
4994 id->plgctx = plg_cryptoctx,
4995 id->reqctx = req_cryptoctx,
4996 id->idctx = id_cryptoctx;
4998 *ih_ret = (pkinit_cert_iter_handle) id;
5003 * End iteration over the certs loaded in crypto_load_certs()
5006 crypto_cert_iteration_end(krb5_context context,
5007 pkinit_cert_iter_handle ih)
5009 struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
5011 if (id == NULL || id->magic != ITER_MAGIC)
5018 * Get next certificate handle
5021 crypto_cert_iteration_next(krb5_context context,
5022 pkinit_cert_iter_handle ih,
5023 pkinit_cert_handle *ch_ret)
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;
5029 if (id == NULL || id->magic != ITER_MAGIC)
5035 id_cryptoctx = id->idctx;
5036 if (id_cryptoctx == NULL)
5039 if (id_cryptoctx->creds[id->index] == NULL)
5040 return PKINIT_ITER_NO_MORE;
5042 cd = calloc(1, sizeof(*cd));
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;
5057 * Release cert handle
5060 crypto_cert_release(krb5_context context,
5061 pkinit_cert_handle ch)
5063 struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
5064 if (cd == NULL || cd->magic != CERT_MAGIC)
5071 * Get certificate Key Usage and Extended Key Usage
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,
5078 unsigned int *ret_ku_bits,
5079 unsigned int *ret_eku_bits)
5081 krb5_error_code retval = 0;
5083 unsigned int eku_bits = 0, ku_bits = 0;
5084 ASN1_BIT_STRING *usage = NULL;
5086 if (ret_ku_bits == NULL && ret_eku_bits == NULL)
5092 pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__);
5096 /* Start with Extended Key usage */
5097 i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
5099 EXTENDED_KEY_USAGE *eku;
5101 eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
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;
5115 EXTENDED_KEY_USAGE_free(eku);
5118 pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits);
5119 *ret_eku_bits = eku_bits;
5122 /* Now the Key Usage bits */
5126 pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__);
5130 /* Make sure usage exists before checking bits */
5132 usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL);
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);
5141 pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits);
5142 *ret_ku_bits = ku_bits;
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
5153 * If buf is NULL, returns the length req'd to hold name
5156 X509_NAME_oneline_ex(X509_NAME * a,
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));
5170 *size = BIO_number_written(out);
5178 * Get certificate information
5181 crypto_cert_get_matching_data(krb5_context context,
5182 pkinit_cert_handle ch,
5183 pkinit_cert_matching_data **ret_md)
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;
5190 char buf[DN_BUF_LEN];
5191 unsigned int bufsize = sizeof(buf);
5193 if (cd == NULL || cd->magic != CERT_MAGIC)
5198 md = calloc(1, sizeof(*md));
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) {
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) {
5222 /* get the san data */
5223 retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,
5224 cd->cred->cert, &pkinit_sans,
5230 if (pkinit_sans != NULL) {
5231 for (i = 0; pkinit_sans[i] != NULL; i++)
5234 if (upn_sans != NULL) {
5235 for (i = 0; upn_sans[i] != NULL; i++)
5239 md->sans = calloc((size_t)j+1, sizeof(*md->sans));
5240 if (md->sans == NULL) {
5245 if (pkinit_sans != NULL) {
5246 for (i = 0; pkinit_sans[i] != NULL; i++)
5247 md->sans[j++] = pkinit_sans[i];
5250 if (upn_sans != NULL) {
5251 for (i = 0; upn_sans[i] != NULL; i++)
5252 md->sans[j++] = upn_sans[i];
5259 /* get the KU and EKU data */
5261 retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx,
5263 &md->ku_bits, &md->eku_bits);
5272 crypto_cert_free_matching_data(context, md);
5278 * Free certificate information
5281 crypto_cert_free_matching_data(krb5_context context,
5282 pkinit_cert_matching_data *md)
5290 free(md->subject_dn);
5292 free(md->issuer_dn);
5294 for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i])
5295 krb5_free_principal(context, p);
5303 * Make this matching certificate "the chosen one"
5306 crypto_cert_select(krb5_context context,
5307 pkinit_cert_matching_data *md)
5309 struct _pkinit_cert_data *cd;
5313 cd = (struct _pkinit_cert_data *)md->ch;
5314 if (cd == NULL || cd->magic != CERT_MAGIC)
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);
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);
5328 cd->idctx->identity = NULL;
5329 cd->idctx->creds[cd->index]->cert = NULL; /* Don't free it twice */
5330 cd->idctx->cert_index = 0;
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 */
5336 #ifndef WITHOUT_PKCS11
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;
5347 * Choose the default certificate as "the chosen one"
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)
5355 krb5_error_code retval;
5358 retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
5359 id_cryptoctx, &cert_count);
5361 pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
5362 __FUNCTION__, retval, error_message(retval));
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);
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);
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);
5384 id_cryptoctx->identity = NULL;
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 */
5390 #ifndef WITHOUT_PKCS11
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;
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,
5412 STACK_OF(X509_INFO) *sk = NULL;
5413 STACK_OF(X509) *ca_certs = NULL;
5414 STACK_OF(X509_CRL) *ca_crls = NULL;
5416 krb5_error_code retval = ENOMEM;
5419 /* If there isn't already a stack in the context,
5420 * create a temporary one now */
5422 case CATYPE_ANCHORS:
5423 if (id_cryptoctx->trustedCAs != NULL)
5424 ca_certs = id_cryptoctx->trustedCAs;
5426 ca_certs = sk_X509_new_null();
5427 if (ca_certs == NULL)
5431 case CATYPE_INTERMEDIATES:
5432 if (id_cryptoctx->intermediateCAs != NULL)
5433 ca_certs = id_cryptoctx->intermediateCAs;
5435 ca_certs = sk_X509_new_null();
5436 if (ca_certs == NULL)
5441 if (id_cryptoctx->revoked != NULL)
5442 ca_crls = id_cryptoctx->revoked;
5444 ca_crls = sk_X509_CRL_new_null();
5445 if (ca_crls == NULL)
5453 if (!(in = BIO_new_file(filename, "r"))) {
5454 retval = oerr(context, 0, _("Cannot open file '%s'"), filename);
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);
5465 /* scan over the stack created from loading the file contents,
5466 * weed out duplicates, and push new ones onto the return stack
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;
5474 sk_X509_push(ca_certs, xi->x509);
5478 for (j = 0; j < size; j++) {
5479 X509 *x = sk_X509_value(ca_certs, j);
5480 flag = X509_cmp(x, xi->x509);
5487 sk_X509_push(ca_certs, X509_dup(xi->x509));
5489 } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) {
5490 int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0;
5492 sk_X509_CRL_push(ca_crls, xi->crl);
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);
5505 sk_X509_CRL_push(ca_crls, X509_CRL_dup(xi->crl));
5510 /* If we added something and there wasn't a stack in the
5511 * context before, add the temporary stack to the context.
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);
5520 if (id_cryptoctx->trustedCAs == NULL)
5521 id_cryptoctx->trustedCAs = ca_certs;
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);
5530 if (id_cryptoctx->intermediateCAs == NULL)
5531 id_cryptoctx->intermediateCAs = ca_certs;
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);
5540 if (id_cryptoctx->revoked == NULL)
5541 id_cryptoctx->revoked = ca_crls;
5545 /* Should have been caught above! */
5557 sk_X509_INFO_pop_free(sk, X509_INFO_free);
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,
5570 krb5_error_code retval = EINVAL;
5572 struct dirent *dentry = NULL;
5573 char filename[1024];
5575 if (dirname == NULL)
5578 d = opendir(dirname);
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);
5588 /* Ignore subdirectories and anything starting with a dot */
5590 if (dentry->d_type == DT_DIR)
5593 if (dentry->d_name[0] == '.')
5595 snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
5597 retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
5598 id_cryptoctx, catype, filename);
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,
5622 pkiDebug("%s: called with idtype %s and catype %s\n",
5623 __FUNCTION__, idtype2string(idtype), catype2string(catype));
5626 return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
5627 id_cryptoctx, catype, id);
5630 return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
5631 id_cryptoctx, catype, id);
5639 static krb5_error_code
5640 create_identifiers_from_stack(STACK_OF(X509) *sk,
5641 krb5_external_principal_identifier *** ids)
5643 int i = 0, sk_size = sk_X509_num(sk);
5644 krb5_external_principal_identifier **krb5_cas = NULL;
5646 X509_NAME *xn = NULL;
5647 unsigned char *p = NULL;
5649 PKCS7_ISSUER_AND_SERIAL *is = NULL;
5650 char buf[DN_BUF_LEN];
5654 krb5_cas = calloc(sk_size + 1, sizeof(*krb5_cas));
5655 if (krb5_cas == NULL)
5658 for (i = 0; i < sk_size; i++) {
5659 krb5_cas[i] = malloc(sizeof(krb5_external_principal_identifier));
5661 x = sk_X509_value(sk, i);
5663 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
5664 pkiDebug("#%d cert= %s\n", i, buf);
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;
5671 xn = X509_get_subject_name(x);
5672 len = i2d_X509_NAME(xn, NULL);
5673 if ((p = malloc((size_t) len)) == NULL)
5675 krb5_cas[i]->subjectName.data = (char *)p;
5676 i2d_X509_NAME(xn, &p);
5677 krb5_cas[i]->subjectName.length = len;
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;
5684 is = PKCS7_ISSUER_AND_SERIAL_new();
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)
5692 len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
5696 krb5_cas[i]->issuerAndSerialNumber.data = (char *)p;
5697 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
5698 krb5_cas[i]->issuerAndSerialNumber.length = len;
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;
5705 if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
5706 ASN1_OCTET_STRING *ikeyid;
5708 ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
5710 if (ikeyid != NULL) {
5711 len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
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);
5721 PKCS7_ISSUER_AND_SERIAL_free(is);
5729 free_krb5_external_principal_identifier(&krb5_cas);
5730 PKCS7_ISSUER_AND_SERIAL_free(is);
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)
5742 krb5_error_code retval = ENOMEM;
5743 STACK_OF(X509) *sk = NULL;
5746 if (req_cryptoctx->received_cert == NULL)
5747 return KRB5KDC_ERR_PREAUTH_FAILED;
5749 sk = sk_X509_new_null();
5752 sk_X509_push(sk, req_cryptoctx->received_cert);
5754 retval = create_identifiers_from_stack(sk, ids);
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)
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" };
5775 loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
5779 loids[0] = malloc(sizeof(krb5_algorithm_identifier));
5780 if (loids[0] == NULL) {
5784 retval = pkinit_copy_krb5_data(&loids[0]->algorithm, &des3oid);
5790 loids[0]->parameters.length = 0;
5791 loids[0]->parameters.data = NULL;
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)
5808 krb5_error_code retval = ENOMEM;
5809 STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
5812 if (id_cryptoctx->trustedCAs == NULL)
5813 return KRB5KDC_ERR_PREAUTH_FAILED;
5815 retval = create_identifiers_from_stack(sk, ids);
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)
5828 unsigned char *p = NULL;
5829 PKCS7_ISSUER_AND_SERIAL *is = NULL;
5831 krb5_error_code retval = ENOMEM;
5832 X509 *cert = req_cryptoctx->received_cert;
5836 if (req_cryptoctx->received_cert == NULL)
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)
5846 i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
5851 X509_NAME_free(is->issuer);
5852 ASN1_INTEGER_free(is->serial);
5859 pkcs7_decrypt(krb5_context context,
5860 pkinit_identity_crypto_context id_cryptoctx,
5865 int retval = 0, i = 0;
5871 if(!PKCS7_type_is_enveloped(p7)) {
5872 pkiDebug("wrong pkcs7 content type\n");
5876 if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) {
5877 pkiDebug("unable to decrypt pkcs7 object\n");
5882 i = BIO_read(tmpmem, buf, sizeof(buf));
5884 BIO_write(data, buf, i);
5885 BIO_free_all(tmpmem);
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,
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];
5909 if (td_type == TD_TRUSTED_CERTIFIERS)
5910 pkiDebug("received trusted certifiers\n");
5912 pkiDebug("received invalid certificate\n");
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);
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);
5926 pkiDebug("#%d cert = %s is invalid\n", i, buf);
5927 sk_X509_NAME_push(sk_xn, xn);
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);
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));
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);
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);
5955 ASN1_OCTET_STRING_free(id);
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
5963 retval = KRB5KDC_ERR_PREAUTH_FAILED;
5966 sk_X509_NAME_pop_free(sk_xn, X509_NAME_free);
5972 pkcs7_dataDecode(krb5_context context,
5973 pkinit_identity_crypto_context id_cryptoctx,
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;
5986 p7->state=PKCS7_S_HEADER;
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);
5997 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) {
5998 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
6002 /* It was encrypted, we need to decrypt the secret key
6003 * with the private key */
6005 /* RFC 4556 section 3.2.3.2 requires that there be exactly one
6007 if (sk_PKCS7_RECIP_INFO_num(rsk) != 1) {
6008 pkiDebug("invalid number of EnvelopedData RecipientInfos\n");
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);
6018 BIO_get_cipher_ctx(etmp,&evp_ctx);
6019 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
6021 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
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);
6030 if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
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.
6043 if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)eklen)) {
6049 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0)
6058 if (data_body->length > 0)
6059 bio = BIO_new_mem_buf(data_body->data, data_body->length);
6061 bio=BIO_new(BIO_s_mem());
6062 BIO_set_mem_eof_return(bio,0);
6069 if (out != NULL) BIO_free_all(out);
6070 if (etmp != NULL) BIO_free_all(etmp);
6071 if (bio != NULL) BIO_free_all(bio);
6075 OPENSSL_cleanse(ek, eklen);
6079 OPENSSL_cleanse(tkey, tkeylen);
6087 print_dh(DH * dh, char *msg)
6089 BIO *bio_err = NULL;
6091 bio_err = BIO_new(BIO_s_file());
6092 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
6095 BIO_puts(bio_err, (const char *)msg);
6097 DHparams_print(bio_err, dh);
6099 BIO_puts(bio_err, "private key: ");
6100 BN_print(bio_err, dh->priv_key);
6101 BIO_puts(bio_err, (const char *)"\n");
6107 print_pubkey(BIGNUM * key, char *msg)
6109 BIO *bio_err = NULL;
6111 bio_err = BIO_new(BIO_s_file());
6112 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
6115 BIO_puts(bio_err, (const char *)msg);
6117 BN_print(bio_err, key);
6118 BIO_puts(bio_err, "\n");
6126 pkinit_pkcs11_code_to_text(int err)
6131 for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
6132 if (pkcs11_errstrings[i].code == err)
6134 if (pkcs11_errstrings[i].text != NULL)
6135 return (pkcs11_errstrings[i].text);
6136 snprintf(uc, sizeof(uc), _("unknown code 0x%x"), err);
6141 * Add an item to the pkinit_identity_crypto_context's list of deferred
6145 crypto_set_deferred_id(krb5_context context,
6146 pkinit_identity_crypto_context id_cryptoctx,
6147 const char *identity, const char *password)
6149 unsigned long ck_flags;
6151 ck_flags = pkinit_get_deferred_id_flags(id_cryptoctx->deferred_ids,
6153 return pkinit_set_deferred_id(&id_cryptoctx->deferred_ids,
6154 identity, ck_flags, password);
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().
6162 const pkinit_deferred_id *
6163 crypto_get_deferred_ids(krb5_context context,
6164 pkinit_identity_crypto_context id_cryptoctx)
6166 pkinit_deferred_id *deferred;
6167 const pkinit_deferred_id *ret;
6169 deferred = id_cryptoctx->deferred_ids;
6170 ret = (const pkinit_deferred_id *)deferred;