6429 SMB domain join doesn't work with libreSSL
[unleashed.git] / usr / src / lib / libkmf / plugins / kmf_openssl / common / openssl_spi.c
blob1faa4bea34b9c863a4f8ef1d02075dfee89950cb
1 /*
2 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
4 * Use is subject to license terms.
5 */
6 /*
7 * Copyright (c) 2012, OmniTI Computer Consulting, Inc. All rights reserved.
8 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
9 * Copyright 2018 RackTop Systems.
12 * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
13 * project 2000.
16 * ====================================================================
17 * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
31 * 3. All advertising materials mentioning features or use of this
32 * software must display the following acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 * endorse or promote products derived from this software without
38 * prior written permission. For written permission, please contact
39 * licensing@OpenSSL.org.
41 * 5. Products derived from this software may not be called "OpenSSL"
42 * nor may "OpenSSL" appear in their names without prior written
43 * permission of the OpenSSL Project.
45 * 6. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the OpenSSL Project
48 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
64 * This product includes cryptographic software written by Eric Young
65 * (eay@cryptsoft.com). This product includes software written by Tim
66 * Hudson (tjh@cryptsoft.com).
70 #include <stdlib.h>
71 #include <kmfapiP.h>
72 #include <ber_der.h>
73 #include <fcntl.h>
74 #include <sys/stat.h>
75 #include <dirent.h>
76 #include <cryptoutil.h>
77 #include <synch.h>
78 #include <thread.h>
80 /* OPENSSL related headers */
81 #include <openssl/bio.h>
82 #include <openssl/bn.h>
83 #include <openssl/asn1.h>
84 #include <openssl/err.h>
85 #include <openssl/x509.h>
86 #include <openssl/rsa.h>
87 #include <openssl/dsa.h>
88 #include <openssl/x509v3.h>
89 #include <openssl/objects.h>
90 #include <openssl/pem.h>
91 #include <openssl/pkcs12.h>
92 #include <openssl/ocsp.h>
93 #include <openssl/des.h>
94 #include <openssl/rand.h>
95 #include "compat.h"
97 #define PRINT_ANY_EXTENSION (\
98 KMF_X509_EXT_KEY_USAGE |\
99 KMF_X509_EXT_CERT_POLICIES |\
100 KMF_X509_EXT_SUBJALTNAME |\
101 KMF_X509_EXT_BASIC_CONSTRAINTS |\
102 KMF_X509_EXT_NAME_CONSTRAINTS |\
103 KMF_X509_EXT_POLICY_CONSTRAINTS |\
104 KMF_X509_EXT_EXT_KEY_USAGE |\
105 KMF_X509_EXT_INHIBIT_ANY_POLICY |\
106 KMF_X509_EXT_AUTH_KEY_ID |\
107 KMF_X509_EXT_SUBJ_KEY_ID |\
108 KMF_X509_EXT_POLICY_MAPPING)
110 static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
111 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
112 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
113 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
114 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
115 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
116 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
117 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
118 0x91 };
120 static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
121 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
122 0x8e, 0xda, 0xce, 0x91, 0x5f };
124 static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
125 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
126 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
127 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
128 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
129 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
130 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
131 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
132 0x02 };
134 #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
135 h->lasterr.errcode = c;
137 #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
140 * Declare some new macros for managing stacks of EVP_PKEYS.
142 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
143 DECLARE_STACK_OF(EVP_PKEY)
145 #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
146 #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
147 #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
148 #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
149 #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
150 #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
151 (free_func))
153 #else
154 /* LINTED E_STATIC_UNUSED */
155 DEFINE_STACK_OF(EVP_PKEY)
156 #endif
158 mutex_t init_lock = DEFAULTMUTEX;
159 static int ssl_initialized = 0;
160 static BIO *bio_err = NULL;
162 static int
163 test_for_file(char *, mode_t);
164 static KMF_RETURN
165 openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
166 STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
168 static KMF_RETURN
169 local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
170 int, KMF_KEY_HANDLE *, char *);
172 static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
174 static KMF_RETURN
175 extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
176 CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
178 static KMF_RETURN
179 kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
180 char *, KMF_DATA *);
182 static KMF_RETURN
183 load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
184 char *, KMF_DATA **, uint32_t *);
186 static KMF_RETURN
187 sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
189 static EVP_PKEY *
190 ImportRawRSAKey(KMF_RAW_RSA_KEY *);
192 static KMF_RETURN
193 convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
195 KMF_RETURN
196 OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
198 void
199 OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
201 KMF_RETURN
202 OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
204 KMF_RETURN
205 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
207 KMF_RETURN
208 OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
210 KMF_RETURN
211 OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
213 KMF_RETURN
214 OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
216 KMF_RETURN
217 OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
218 KMF_DATA *, KMF_DATA *);
220 KMF_RETURN
221 OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
223 KMF_RETURN
224 OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
226 KMF_RETURN
227 OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
229 KMF_RETURN
230 OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
232 KMF_RETURN
233 OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
235 KMF_RETURN
236 OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
237 KMF_PRINTABLE_ITEM, char *);
239 KMF_RETURN
240 OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
242 KMF_RETURN
243 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
245 KMF_RETURN
246 OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
247 KMF_DATA *, KMF_DATA *);
249 KMF_RETURN
250 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
252 KMF_RETURN
253 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
255 KMF_RETURN
256 OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
258 KMF_RETURN
259 OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
261 KMF_RETURN
262 OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
264 KMF_RETURN
265 OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
267 KMF_RETURN
268 OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
270 KMF_RETURN
271 OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
273 static
274 KMF_PLUGIN_FUNCLIST openssl_plugin_table =
276 1, /* Version */
277 NULL, /* ConfigureKeystore */
278 OpenSSL_FindCert,
279 OpenSSL_FreeKMFCert,
280 OpenSSL_StoreCert,
281 NULL, /* ImportCert */
282 OpenSSL_ImportCRL,
283 OpenSSL_DeleteCert,
284 OpenSSL_DeleteCRL,
285 OpenSSL_CreateKeypair,
286 OpenSSL_FindKey,
287 OpenSSL_EncodePubKeyData,
288 OpenSSL_SignData,
289 OpenSSL_DeleteKey,
290 OpenSSL_ListCRL,
291 NULL, /* FindCRL */
292 OpenSSL_FindCertInCRL,
293 OpenSSL_GetErrorString,
294 OpenSSL_FindPrikeyByCert,
295 OpenSSL_DecryptData,
296 OpenSSL_ExportPK12,
297 OpenSSL_CreateSymKey,
298 OpenSSL_GetSymKeyValue,
299 NULL, /* SetTokenPin */
300 OpenSSL_StoreKey,
301 NULL /* Finalize */
304 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
305 static mutex_t *lock_cs;
306 static long *lock_count;
308 static void
309 /* ARGSUSED1 */
310 locking_cb(int mode, int type, char *file, int line)
312 if (mode & CRYPTO_LOCK) {
313 (void) mutex_lock(&(lock_cs[type]));
314 lock_count[type]++;
315 } else {
316 (void) mutex_unlock(&(lock_cs[type]));
320 static unsigned long
321 thread_id()
323 return ((unsigned long)thr_self());
325 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER */
327 KMF_PLUGIN_FUNCLIST *
328 KMF_Plugin_Initialize()
330 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
331 int i;
332 #endif
334 (void) mutex_lock(&init_lock);
335 if (!ssl_initialized) {
337 * Add support for extension OIDs that are not yet in the
338 * openssl default set.
340 (void) OBJ_create("2.5.29.30", "nameConstraints",
341 "X509v3 Name Constraints");
342 (void) OBJ_create("2.5.29.33", "policyMappings",
343 "X509v3 Policy Mappings");
344 (void) OBJ_create("2.5.29.36", "policyConstraints",
345 "X509v3 Policy Constraints");
346 (void) OBJ_create("2.5.29.46", "freshestCRL",
347 "X509v3 Freshest CRL");
348 (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
349 "X509v3 Inhibit Any-Policy");
351 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
353 * Set up for thread-safe operation.
354 * This is not required for OpenSSL 1.1
356 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
357 if (lock_cs == NULL) {
358 (void) mutex_unlock(&init_lock);
359 return (NULL);
362 lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
363 if (lock_count == NULL) {
364 OPENSSL_free(lock_cs);
365 (void) mutex_unlock(&init_lock);
366 return (NULL);
369 for (i = 0; i < CRYPTO_num_locks(); i++) {
370 lock_count[i] = 0;
371 (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
374 CRYPTO_set_id_callback((unsigned long (*)())thread_id);
375 if (CRYPTO_get_locking_callback() == NULL)
376 CRYPTO_set_locking_callback((void (*)())locking_cb);
378 (void) OpenSSL_add_all_algorithms();
380 /* Enable error strings for reporting */
381 (void) ERR_load_crypto_strings();
382 #endif
384 ssl_initialized = 1;
386 (void) mutex_unlock(&init_lock);
388 return (&openssl_plugin_table);
392 * Convert an SSL DN to a KMF DN.
394 static KMF_RETURN
395 get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
397 KMF_DATA derdata;
398 KMF_RETURN rv = KMF_OK;
399 uchar_t *tmp;
401 /* Convert to raw DER format */
402 derdata.Length = i2d_X509_NAME(sslDN, NULL);
403 if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
404 == NULL) {
405 return (KMF_ERR_MEMORY);
407 (void) i2d_X509_NAME(sslDN, &tmp);
409 /* Decode to KMF format */
410 rv = DerDecodeName(&derdata, kmfDN);
411 if (rv != KMF_OK) {
412 rv = KMF_ERR_BAD_CERT_FORMAT;
414 OPENSSL_free(derdata.Data);
416 return (rv);
420 isdir(char *path)
422 struct stat s;
424 if (stat(path, &s) == -1)
425 return (0);
427 return ((s.st_mode & S_IFMT) == S_IFDIR);
430 static KMF_RETURN
431 ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
433 KMF_RETURN rv = KMF_OK;
434 unsigned char *buf = NULL, *p;
435 int len;
438 * Convert the X509 internal struct to DER encoded data
440 if ((len = i2d_X509(x509cert, NULL)) < 0) {
441 SET_ERROR(kmfh, ERR_get_error());
442 rv = KMF_ERR_BAD_CERT_FORMAT;
443 goto cleanup;
445 if ((buf = malloc(len)) == NULL) {
446 SET_SYS_ERROR(kmfh, errno);
447 rv = KMF_ERR_MEMORY;
448 goto cleanup;
452 * i2d_X509 will increment the buf pointer so that we need to
453 * save it.
455 p = buf;
456 if ((len = i2d_X509(x509cert, &p)) < 0) {
457 SET_ERROR(kmfh, ERR_get_error());
458 free(buf);
459 rv = KMF_ERR_BAD_CERT_FORMAT;
460 goto cleanup;
463 /* caller's responsibility to free it */
464 cert->Data = buf;
465 cert->Length = len;
467 cleanup:
468 if (rv != KMF_OK) {
469 if (buf)
470 free(buf);
471 cert->Data = NULL;
472 cert->Length = 0;
475 return (rv);
479 static KMF_RETURN
480 check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
481 boolean_t *match)
483 KMF_RETURN rv = KMF_OK;
484 boolean_t findIssuer = FALSE;
485 boolean_t findSubject = FALSE;
486 boolean_t findSerial = FALSE;
487 KMF_X509_NAME issuerDN, subjectDN;
488 KMF_X509_NAME certIssuerDN, certSubjectDN;
490 *match = FALSE;
491 if (xcert == NULL) {
492 return (KMF_ERR_BAD_PARAMETER);
495 (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
496 (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
497 (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
498 (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
500 if (issuer != NULL && strlen(issuer)) {
501 rv = kmf_dn_parser(issuer, &issuerDN);
502 if (rv != KMF_OK)
503 return (KMF_ERR_BAD_PARAMETER);
505 rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
506 if (rv != KMF_OK) {
507 kmf_free_dn(&issuerDN);
508 return (KMF_ERR_BAD_PARAMETER);
511 findIssuer = TRUE;
513 if (subject != NULL && strlen(subject)) {
514 rv = kmf_dn_parser(subject, &subjectDN);
515 if (rv != KMF_OK) {
516 rv = KMF_ERR_BAD_PARAMETER;
517 goto cleanup;
520 rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
521 if (rv != KMF_OK) {
522 rv = KMF_ERR_BAD_PARAMETER;
523 goto cleanup;
525 findSubject = TRUE;
527 if (serial != NULL && serial->val != NULL)
528 findSerial = TRUE;
530 if (findSerial) {
531 BIGNUM *bn;
533 /* Comparing BIGNUMs is a pain! */
534 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
535 if (bn != NULL) {
536 int bnlen = BN_num_bytes(bn);
538 if (bnlen == serial->len) {
539 uchar_t *a = malloc(bnlen);
540 if (a == NULL) {
541 rv = KMF_ERR_MEMORY;
542 BN_free(bn);
543 goto cleanup;
545 bnlen = BN_bn2bin(bn, a);
546 *match = (memcmp(a, serial->val, serial->len) ==
548 rv = KMF_OK;
549 free(a);
551 BN_free(bn);
552 if (!(*match))
553 goto cleanup;
554 } else {
555 rv = KMF_OK;
556 goto cleanup;
559 if (findIssuer) {
560 *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
561 if ((*match) == B_FALSE) {
562 /* stop checking and bail */
563 rv = KMF_OK;
564 goto cleanup;
567 if (findSubject) {
568 *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
569 if ((*match) == B_FALSE) {
570 /* stop checking and bail */
571 rv = KMF_OK;
572 goto cleanup;
576 *match = TRUE;
577 cleanup:
578 if (findIssuer) {
579 kmf_free_dn(&issuerDN);
580 kmf_free_dn(&certIssuerDN);
582 if (findSubject) {
583 kmf_free_dn(&subjectDN);
584 kmf_free_dn(&certSubjectDN);
587 return (rv);
592 * This function loads a certificate file into an X509 data structure, and
593 * checks if its issuer, subject or the serial number matches with those
594 * values. If it matches, then return the X509 data structure.
596 static KMF_RETURN
597 load_X509cert(KMF_HANDLE *kmfh,
598 char *issuer, char *subject, KMF_BIGINT *serial,
599 char *pathname, X509 **outcert)
601 KMF_RETURN rv = KMF_OK;
602 X509 *xcert = NULL;
603 BIO *bcert = NULL;
604 boolean_t match = FALSE;
605 KMF_ENCODE_FORMAT format;
608 * auto-detect the file format, regardless of what
609 * the 'format' parameters in the params say.
611 rv = kmf_get_file_format(pathname, &format);
612 if (rv != KMF_OK) {
613 if (rv == KMF_ERR_OPEN_FILE)
614 rv = KMF_ERR_CERT_NOT_FOUND;
615 return (rv);
618 /* Not ASN1(DER) format */
619 if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
620 SET_ERROR(kmfh, ERR_get_error());
621 rv = KMF_ERR_OPEN_FILE;
622 goto cleanup;
625 if (format == KMF_FORMAT_PEM)
626 xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
627 else if (format == KMF_FORMAT_ASN1)
628 xcert = d2i_X509_bio(bcert, NULL);
629 else if (format == KMF_FORMAT_PKCS12) {
630 PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
631 if (p12 != NULL) {
632 (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
633 PKCS12_free(p12);
634 p12 = NULL;
635 } else {
636 SET_ERROR(kmfh, ERR_get_error());
637 rv = KMF_ERR_BAD_CERT_FORMAT;
639 } else {
640 rv = KMF_ERR_BAD_PARAMETER;
641 goto cleanup;
644 if (xcert == NULL) {
645 SET_ERROR(kmfh, ERR_get_error());
646 rv = KMF_ERR_BAD_CERT_FORMAT;
647 goto cleanup;
650 if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
651 match == FALSE) {
652 rv = KMF_ERR_CERT_NOT_FOUND;
653 goto cleanup;
656 if (outcert != NULL) {
657 *outcert = xcert;
660 cleanup:
661 if (bcert != NULL) (void) BIO_free(bcert);
662 if (rv != KMF_OK && xcert != NULL)
663 X509_free(xcert);
665 return (rv);
668 static int
669 datacmp(const void *a, const void *b)
671 KMF_DATA *adata = (KMF_DATA *)a;
672 KMF_DATA *bdata = (KMF_DATA *)b;
673 if (adata->Length > bdata->Length)
674 return (-1);
675 if (adata->Length < bdata->Length)
676 return (1);
677 return (0);
680 static KMF_RETURN
681 load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
682 KMF_CERT_VALIDITY validity, char *pathname,
683 KMF_DATA **certlist, uint32_t *numcerts)
685 KMF_RETURN rv = KMF_OK;
686 int i;
687 KMF_DATA *certs = NULL;
688 int nc = 0;
689 int hits = 0;
690 KMF_ENCODE_FORMAT format;
692 rv = kmf_get_file_format(pathname, &format);
693 if (rv != KMF_OK) {
694 if (rv == KMF_ERR_OPEN_FILE)
695 rv = KMF_ERR_CERT_NOT_FOUND;
696 return (rv);
698 if (format == KMF_FORMAT_ASN1) {
699 /* load a single certificate */
700 certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
701 if (certs == NULL)
702 return (KMF_ERR_MEMORY);
703 certs->Data = NULL;
704 certs->Length = 0;
705 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
706 pathname, certs);
707 if (rv == KMF_OK) {
708 *certlist = certs;
709 *numcerts = 1;
710 } else {
711 kmf_free_data(certs);
712 free(certs);
713 certs = NULL;
715 return (rv);
716 } else if (format == KMF_FORMAT_PKCS12) {
717 /* We need a credential to access a PKCS#12 file */
718 rv = KMF_ERR_BAD_CERT_FORMAT;
719 } else if (format == KMF_FORMAT_PEM ||
720 format != KMF_FORMAT_PEM_KEYPAIR) {
722 /* This function only works on PEM files */
723 rv = extract_pem(kmfh, issuer, subject, serial, pathname,
724 (uchar_t *)NULL, 0, NULL, &certs, &nc);
725 } else {
726 return (KMF_ERR_ENCODING);
729 if (rv != KMF_OK)
730 return (rv);
732 for (i = 0; i < nc; i++) {
733 if (validity == KMF_NONEXPIRED_CERTS) {
734 rv = kmf_check_cert_date(kmfh, &certs[i]);
735 } else if (validity == KMF_EXPIRED_CERTS) {
736 rv = kmf_check_cert_date(kmfh, &certs[i]);
737 if (rv == KMF_OK)
738 rv = KMF_ERR_CERT_NOT_FOUND;
739 if (rv == KMF_ERR_VALIDITY_PERIOD)
740 rv = KMF_OK;
742 if (rv != KMF_OK) {
743 /* Remove this cert from the list by clearing it. */
744 kmf_free_data(&certs[i]);
745 } else {
746 hits++; /* count valid certs found */
748 rv = KMF_OK;
750 if (rv == KMF_OK && hits > 0) {
752 * Sort the list of certs by length to put the cleared ones
753 * at the end so they don't get accessed by the caller.
755 qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
756 *certlist = certs;
758 /* since we sorted the list, just return the number of hits */
759 *numcerts = hits;
760 } else {
761 if (rv == KMF_OK && hits == 0)
762 rv = KMF_ERR_CERT_NOT_FOUND;
763 if (certs != NULL) {
764 free(certs);
765 certs = NULL;
768 return (rv);
771 static KMF_RETURN
772 kmf_load_cert(KMF_HANDLE *kmfh,
773 char *issuer, char *subject, KMF_BIGINT *serial,
774 KMF_CERT_VALIDITY validity,
775 char *pathname,
776 KMF_DATA *cert)
778 KMF_RETURN rv = KMF_OK;
779 X509 *x509cert = NULL;
781 rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
782 if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
783 rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
784 if (rv != KMF_OK) {
785 goto cleanup;
787 if (validity == KMF_NONEXPIRED_CERTS) {
788 rv = kmf_check_cert_date(kmfh, cert);
789 } else if (validity == KMF_EXPIRED_CERTS) {
790 rv = kmf_check_cert_date(kmfh, cert);
791 if (rv == KMF_OK) {
793 * This is a valid cert so skip it.
795 rv = KMF_ERR_CERT_NOT_FOUND;
797 if (rv == KMF_ERR_VALIDITY_PERIOD) {
799 * We want to return success when we
800 * find an invalid cert.
802 rv = KMF_OK;
803 goto cleanup;
807 cleanup:
808 if (x509cert != NULL)
809 X509_free(x509cert);
811 return (rv);
814 static KMF_RETURN
815 readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
817 KMF_RETURN ret = KMF_OK;
818 KMF_RAW_RSA_KEY rsa;
819 BerElement *asn1 = NULL;
820 BerValue filebuf;
821 BerValue OID = { NULL, 0 };
822 BerValue *Mod = NULL, *PubExp = NULL;
823 BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
824 BerValue *Coef = NULL;
825 BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
826 BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
827 BIGNUM *qminus1 = NULL;
828 BN_CTX *ctx = NULL;
830 *pkey = NULL;
832 filebuf.bv_val = (char *)filedata->Data;
833 filebuf.bv_len = filedata->Length;
835 asn1 = kmfder_init(&filebuf);
836 if (asn1 == NULL) {
837 ret = KMF_ERR_MEMORY;
838 goto out;
841 if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
842 &OID, &Mod, &PubExp, &PriExp, &Prime1,
843 &Prime2, &Coef) == -1) {
844 ret = KMF_ERR_ENCODING;
845 goto out;
849 * We have to derive the 2 Exponents using Bignumber math.
850 * Exp1 = PriExp mod (Prime1 - 1)
851 * Exp2 = PriExp mod (Prime2 - 1)
854 /* D = PrivateExponent */
855 D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
856 if (D == NULL) {
857 ret = KMF_ERR_MEMORY;
858 goto out;
861 /* P = Prime1 (first prime factor of Modulus) */
862 P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
863 if (D == NULL) {
864 ret = KMF_ERR_MEMORY;
865 goto out;
868 /* Q = Prime2 (second prime factor of Modulus) */
869 Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
871 if ((ctx = BN_CTX_new()) == NULL) {
872 ret = KMF_ERR_MEMORY;
873 goto out;
876 /* Compute (P - 1) */
877 pminus1 = BN_new();
878 (void) BN_sub(pminus1, P, BN_value_one());
880 /* Exponent1 = D mod (P - 1) */
881 Exp1 = BN_new();
882 (void) BN_mod(Exp1, D, pminus1, ctx);
884 /* Compute (Q - 1) */
885 qminus1 = BN_new();
886 (void) BN_sub(qminus1, Q, BN_value_one());
888 /* Exponent2 = D mod (Q - 1) */
889 Exp2 = BN_new();
890 (void) BN_mod(Exp2, D, qminus1, ctx);
892 /* Coef = (Inverse Q) mod P */
893 COEF = BN_new();
894 (void) BN_mod_inverse(COEF, Q, P, ctx);
896 /* Convert back to KMF format */
897 (void) memset(&rsa, 0, sizeof (rsa));
899 if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
900 goto out;
901 if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
902 goto out;
903 if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
904 goto out;
906 rsa.mod.val = (uchar_t *)Mod->bv_val;
907 rsa.mod.len = Mod->bv_len;
909 rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
910 rsa.pubexp.len = PubExp->bv_len;
912 rsa.priexp.val = (uchar_t *)PriExp->bv_val;
913 rsa.priexp.len = PriExp->bv_len;
915 rsa.prime1.val = (uchar_t *)Prime1->bv_val;
916 rsa.prime1.len = Prime1->bv_len;
918 rsa.prime2.val = (uchar_t *)Prime2->bv_val;
919 rsa.prime2.len = Prime2->bv_len;
921 *pkey = ImportRawRSAKey(&rsa);
922 out:
923 if (asn1 != NULL)
924 kmfber_free(asn1, 1);
926 if (OID.bv_val) {
927 free(OID.bv_val);
929 if (PriExp)
930 free(PriExp);
932 if (Mod)
933 free(Mod);
935 if (PubExp)
936 free(PubExp);
938 if (Coef) {
939 (void) memset(Coef->bv_val, 0, Coef->bv_len);
940 free(Coef->bv_val);
941 free(Coef);
943 if (Prime1)
944 free(Prime1);
945 if (Prime2)
946 free(Prime2);
948 if (ctx != NULL)
949 BN_CTX_free(ctx);
951 if (D)
952 BN_clear_free(D);
953 if (P)
954 BN_clear_free(P);
955 if (Q)
956 BN_clear_free(Q);
957 if (pminus1)
958 BN_clear_free(pminus1);
959 if (qminus1)
960 BN_clear_free(qminus1);
961 if (Exp1)
962 BN_clear_free(Exp1);
963 if (Exp2)
964 BN_clear_free(Exp2);
966 return (ret);
970 static EVP_PKEY *
971 openssl_load_key(KMF_HANDLE_T handle, const char *file)
973 BIO *keyfile = NULL;
974 EVP_PKEY *pkey = NULL;
975 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
976 KMF_ENCODE_FORMAT format;
977 KMF_RETURN rv;
978 KMF_DATA filedata;
980 if (file == NULL) {
981 return (NULL);
984 if (kmf_get_file_format((char *)file, &format) != KMF_OK)
985 return (NULL);
987 keyfile = BIO_new_file(file, "rb");
988 if (keyfile == NULL) {
989 goto end;
992 if (format == KMF_FORMAT_ASN1) {
993 pkey = d2i_PrivateKey_bio(keyfile, NULL);
994 if (pkey == NULL) {
996 (void) BIO_free(keyfile);
997 keyfile = NULL;
998 /* Try odd ASN.1 variations */
999 rv = kmf_read_input_file(kmfh, (char *)file,
1000 &filedata);
1001 if (rv == KMF_OK) {
1002 (void) readAltFormatPrivateKey(&filedata,
1003 &pkey);
1004 kmf_free_data(&filedata);
1007 } else if (format == KMF_FORMAT_PEM ||
1008 format == KMF_FORMAT_PEM_KEYPAIR) {
1009 pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
1010 if (pkey == NULL) {
1011 KMF_DATA derdata;
1013 * Check if this is the alt. format
1014 * RSA private key file.
1016 rv = kmf_read_input_file(kmfh, (char *)file,
1017 &filedata);
1018 if (rv == KMF_OK) {
1019 uchar_t *d = NULL;
1020 int len;
1021 rv = kmf_pem_to_der(filedata.Data,
1022 filedata.Length, &d, &len);
1023 if (rv == KMF_OK && d != NULL) {
1024 derdata.Data = d;
1025 derdata.Length = (size_t)len;
1026 (void) readAltFormatPrivateKey(
1027 &derdata, &pkey);
1028 free(d);
1030 kmf_free_data(&filedata);
1035 end:
1036 if (pkey == NULL)
1037 SET_ERROR(kmfh, ERR_get_error());
1039 if (keyfile != NULL)
1040 (void) BIO_free(keyfile);
1042 return (pkey);
1045 KMF_RETURN
1046 OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1048 KMF_RETURN rv = KMF_OK;
1049 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1050 int i, n;
1051 uint32_t maxcerts = 0;
1052 uint32_t *num_certs;
1053 KMF_X509_DER_CERT *kmf_cert = NULL;
1054 char *dirpath = NULL;
1055 char *filename = NULL;
1056 char *fullpath = NULL;
1057 char *issuer = NULL;
1058 char *subject = NULL;
1059 KMF_BIGINT *serial = NULL;
1060 KMF_CERT_VALIDITY validity;
1062 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1063 if (num_certs == NULL)
1064 return (KMF_ERR_BAD_PARAMETER);
1066 /* num_certs should reference the size of kmf_cert */
1067 maxcerts = *num_certs;
1068 if (maxcerts == 0)
1069 maxcerts = 0xFFFFFFFF;
1070 *num_certs = 0;
1072 /* Get the optional returned certificate list */
1073 kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1074 numattr);
1077 * The dirpath attribute and the filename attribute can not be NULL
1078 * at the same time.
1080 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1081 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1082 numattr);
1084 fullpath = get_fullpath(dirpath, filename);
1085 if (fullpath == NULL)
1086 return (KMF_ERR_BAD_PARAMETER);
1088 /* Get optional search criteria attributes */
1089 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1090 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1091 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1092 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1093 &validity, NULL);
1094 if (rv != KMF_OK) {
1095 validity = KMF_ALL_CERTS;
1096 rv = KMF_OK;
1099 if (isdir(fullpath)) {
1100 DIR *dirp;
1101 struct dirent *dp;
1103 n = 0;
1104 /* open all files in the directory and attempt to read them */
1105 if ((dirp = opendir(fullpath)) == NULL) {
1106 return (KMF_ERR_BAD_PARAMETER);
1108 while ((dp = readdir(dirp)) != NULL) {
1109 char *fname;
1110 KMF_DATA *certlist = NULL;
1111 uint32_t loaded_certs = 0;
1113 if (strcmp(dp->d_name, ".") == 0 ||
1114 strcmp(dp->d_name, "..") == 0)
1115 continue;
1117 fname = get_fullpath(fullpath, (char *)&dp->d_name);
1119 rv = load_certs(kmfh, issuer, subject, serial,
1120 validity, fname, &certlist, &loaded_certs);
1122 if (rv != KMF_OK) {
1123 free(fname);
1124 if (certlist != NULL) {
1125 for (i = 0; i < loaded_certs; i++)
1126 kmf_free_data(&certlist[i]);
1127 free(certlist);
1129 continue;
1132 /* If load succeeds, add certdata to the list */
1133 if (kmf_cert != NULL) {
1134 for (i = 0; i < loaded_certs &&
1135 n < maxcerts; i++) {
1136 kmf_cert[n].certificate.Data =
1137 certlist[i].Data;
1138 kmf_cert[n].certificate.Length =
1139 certlist[i].Length;
1141 kmf_cert[n].kmf_private.keystore_type =
1142 KMF_KEYSTORE_OPENSSL;
1143 kmf_cert[n].kmf_private.flags =
1144 KMF_FLAG_CERT_VALID;
1145 kmf_cert[n].kmf_private.label =
1146 strdup(fname);
1147 n++;
1150 * If maxcerts < loaded_certs, clean up the
1151 * certs that were not used.
1153 for (; i < loaded_certs; i++)
1154 kmf_free_data(&certlist[i]);
1155 } else {
1156 for (i = 0; i < loaded_certs; i++)
1157 kmf_free_data(&certlist[i]);
1158 n += loaded_certs;
1160 free(certlist);
1161 free(fname);
1163 (*num_certs) = n;
1164 if (*num_certs == 0)
1165 rv = KMF_ERR_CERT_NOT_FOUND;
1166 if (*num_certs > 0)
1167 rv = KMF_OK;
1168 exit:
1169 (void) closedir(dirp);
1170 } else {
1171 KMF_DATA *certlist = NULL;
1172 uint32_t loaded_certs = 0;
1174 rv = load_certs(kmfh, issuer, subject, serial, validity,
1175 fullpath, &certlist, &loaded_certs);
1176 if (rv != KMF_OK) {
1177 free(fullpath);
1178 return (rv);
1181 n = 0;
1182 if (kmf_cert != NULL && certlist != NULL) {
1183 for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1184 kmf_cert[n].certificate.Data =
1185 certlist[i].Data;
1186 kmf_cert[n].certificate.Length =
1187 certlist[i].Length;
1188 kmf_cert[n].kmf_private.keystore_type =
1189 KMF_KEYSTORE_OPENSSL;
1190 kmf_cert[n].kmf_private.flags =
1191 KMF_FLAG_CERT_VALID;
1192 kmf_cert[n].kmf_private.label =
1193 strdup(fullpath);
1194 n++;
1196 /* If maxcerts < loaded_certs, clean up */
1197 for (; i < loaded_certs; i++)
1198 kmf_free_data(&certlist[i]);
1199 } else if (certlist != NULL) {
1200 for (i = 0; i < loaded_certs; i++)
1201 kmf_free_data(&certlist[i]);
1202 n = loaded_certs;
1204 if (certlist != NULL)
1205 free(certlist);
1206 *num_certs = n;
1209 free(fullpath);
1211 return (rv);
1214 void
1215 /*ARGSUSED*/
1216 OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
1217 KMF_X509_DER_CERT *kmf_cert)
1219 if (kmf_cert != NULL) {
1220 if (kmf_cert->certificate.Data != NULL) {
1221 kmf_free_data(&kmf_cert->certificate);
1223 if (kmf_cert->kmf_private.label)
1224 free(kmf_cert->kmf_private.label);
1228 /*ARGSUSED*/
1229 KMF_RETURN
1230 OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1232 KMF_RETURN ret = KMF_OK;
1233 KMF_DATA *cert = NULL;
1234 char *outfilename = NULL;
1235 char *dirpath = NULL;
1236 char *fullpath = NULL;
1237 KMF_ENCODE_FORMAT format;
1239 /* Get the cert data */
1240 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1241 if (cert == NULL || cert->Data == NULL)
1242 return (KMF_ERR_BAD_PARAMETER);
1244 /* Check the output filename and directory attributes. */
1245 outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1246 numattr);
1247 if (outfilename == NULL)
1248 return (KMF_ERR_BAD_PARAMETER);
1250 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1251 fullpath = get_fullpath(dirpath, outfilename);
1252 if (fullpath == NULL)
1253 return (KMF_ERR_BAD_CERTFILE);
1255 /* Check the optional format attribute */
1256 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1257 &format, NULL);
1258 if (ret != KMF_OK) {
1259 /* If there is no format attribute, then default to PEM */
1260 format = KMF_FORMAT_PEM;
1261 ret = KMF_OK;
1262 } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1263 ret = KMF_ERR_BAD_CERT_FORMAT;
1264 goto out;
1267 /* Store the certificate in the file with the specified format */
1268 ret = kmf_create_cert_file(cert, format, fullpath);
1270 out:
1271 if (fullpath != NULL)
1272 free(fullpath);
1274 return (ret);
1278 KMF_RETURN
1279 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1281 KMF_RETURN rv;
1282 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1283 KMF_DATA certdata = { 0, NULL };
1284 char *dirpath = NULL;
1285 char *filename = NULL;
1286 char *fullpath = NULL;
1287 char *issuer = NULL;
1288 char *subject = NULL;
1289 KMF_BIGINT *serial = NULL;
1290 KMF_CERT_VALIDITY validity;
1293 * Get the DIRPATH and CERT_FILENAME attributes. They can not be
1294 * NULL at the same time.
1296 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1297 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1298 numattr);
1299 fullpath = get_fullpath(dirpath, filename);
1300 if (fullpath == NULL)
1301 return (KMF_ERR_BAD_PARAMETER);
1303 /* Get optional search criteria attributes */
1304 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1305 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1306 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1307 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1308 &validity, NULL);
1309 if (rv != KMF_OK) {
1310 validity = KMF_ALL_CERTS;
1311 rv = KMF_OK;
1314 if (isdir(fullpath)) {
1315 DIR *dirp;
1316 struct dirent *dp;
1318 /* open all files in the directory and attempt to read them */
1319 if ((dirp = opendir(fullpath)) == NULL) {
1320 return (KMF_ERR_BAD_PARAMETER);
1323 while ((dp = readdir(dirp)) != NULL) {
1324 if (strcmp(dp->d_name, ".") != 0 &&
1325 strcmp(dp->d_name, "..") != 0) {
1326 char *fname;
1328 fname = get_fullpath(fullpath,
1329 (char *)&dp->d_name);
1331 if (fname == NULL) {
1332 rv = KMF_ERR_MEMORY;
1333 break;
1336 rv = kmf_load_cert(kmfh, issuer, subject,
1337 serial, validity, fname, &certdata);
1339 if (rv == KMF_ERR_CERT_NOT_FOUND) {
1340 free(fname);
1341 kmf_free_data(&certdata);
1342 rv = KMF_OK;
1343 continue;
1344 } else if (rv != KMF_OK) {
1345 free(fname);
1346 break;
1349 if (unlink(fname) != 0) {
1350 SET_SYS_ERROR(kmfh, errno);
1351 rv = KMF_ERR_INTERNAL;
1352 free(fname);
1353 break;
1355 free(fname);
1356 kmf_free_data(&certdata);
1359 (void) closedir(dirp);
1360 } else {
1361 /* Just try to load a single certificate */
1362 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1363 fullpath, &certdata);
1364 if (rv == KMF_OK) {
1365 if (unlink(fullpath) != 0) {
1366 SET_SYS_ERROR(kmfh, errno);
1367 rv = KMF_ERR_INTERNAL;
1372 out:
1373 if (fullpath != NULL)
1374 free(fullpath);
1376 kmf_free_data(&certdata);
1378 return (rv);
1381 KMF_RETURN
1382 OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1383 KMF_DATA *keydata)
1385 KMF_RETURN rv = KMF_OK;
1386 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1387 int n;
1389 if (key == NULL || keydata == NULL ||
1390 key->keyp == NULL)
1391 return (KMF_ERR_BAD_PARAMETER);
1393 if (key->keyalg == KMF_RSA) {
1394 RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
1396 if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
1397 SET_ERROR(kmfh, ERR_get_error());
1398 return (KMF_ERR_ENCODING);
1400 RSA_free(pubkey);
1401 } else if (key->keyalg == KMF_DSA) {
1402 DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
1404 if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
1405 SET_ERROR(kmfh, ERR_get_error());
1406 return (KMF_ERR_ENCODING);
1408 DSA_free(pubkey);
1409 } else {
1410 return (KMF_ERR_BAD_PARAMETER);
1412 keydata->Length = n;
1414 cleanup:
1415 if (rv != KMF_OK) {
1416 if (keydata->Data)
1417 free(keydata->Data);
1418 keydata->Data = NULL;
1419 keydata->Length = 0;
1422 return (rv);
1425 static KMF_RETURN
1426 ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1427 KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
1429 int rv = 0;
1430 RSA *rsa;
1431 DSA *dsa;
1433 if (pkey == NULL || out == NULL)
1434 return (KMF_ERR_BAD_PARAMETER);
1436 switch (format) {
1437 case KMF_FORMAT_RAWKEY:
1438 /* same as ASN.1 */
1439 case KMF_FORMAT_ASN1:
1440 if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
1441 if (private)
1442 rv = i2d_RSAPrivateKey_bio(out, rsa);
1443 else
1444 rv = i2d_RSAPublicKey_bio(out, rsa);
1445 } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
1446 rv = i2d_DSAPrivateKey_bio(out, dsa);
1448 if (rv == 1) {
1449 rv = KMF_OK;
1450 } else {
1451 SET_ERROR(kmfh, rv);
1453 break;
1454 case KMF_FORMAT_PEM:
1455 if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
1456 if (private)
1457 rv = PEM_write_bio_RSAPrivateKey(out,
1458 rsa, NULL, NULL, 0, NULL,
1459 (cred != NULL ? cred->cred : NULL));
1460 else
1461 rv = PEM_write_bio_RSAPublicKey(out,
1462 rsa);
1463 } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
1464 rv = PEM_write_bio_DSAPrivateKey(out,
1465 dsa, NULL, NULL, 0, NULL,
1466 (cred != NULL ? cred->cred : NULL));
1469 if (rv == 1) {
1470 rv = KMF_OK;
1471 } else {
1472 SET_ERROR(kmfh, rv);
1474 break;
1476 default:
1477 rv = KMF_ERR_BAD_PARAMETER;
1480 return (rv);
1483 KMF_RETURN
1484 OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1485 KMF_ATTRIBUTE *attrlist)
1487 KMF_RETURN rv = KMF_OK;
1488 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1489 uint32_t eValue = RSA_F4;
1490 BIGNUM *eValue_bn = NULL;
1491 RSA *sslPrivKey = NULL;
1492 DSA *sslDSAKey = NULL;
1493 EVP_PKEY *eprikey = NULL;
1494 EVP_PKEY *epubkey = NULL;
1495 BIO *out = NULL;
1496 KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1497 uint32_t keylen = 1024;
1498 uint32_t keylen_size = sizeof (uint32_t);
1499 boolean_t storekey = TRUE;
1500 KMF_KEY_ALG keytype = KMF_RSA;
1502 eValue_bn = BN_new();
1503 if (eValue_bn == NULL)
1504 return (KMF_ERR_MEMORY);
1505 if (BN_set_word(eValue_bn, eValue) == 0) {
1506 rv = KMF_ERR_KEYGEN_FAILED;
1507 goto cleanup;
1510 rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1511 &storekey, NULL);
1512 if (rv != KMF_OK) {
1513 /* "storekey" is optional. Default is TRUE */
1514 rv = KMF_OK;
1517 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1518 (void *)&keytype, NULL);
1519 if (rv != KMF_OK)
1520 /* keytype is optional. KMF_RSA is default */
1521 rv = KMF_OK;
1523 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1524 if (pubkey == NULL) {
1525 rv = KMF_ERR_BAD_PARAMETER;
1526 goto cleanup;
1529 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1530 if (privkey == NULL) {
1531 rv = KMF_ERR_BAD_PARAMETER;
1532 goto cleanup;
1535 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1536 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1538 eprikey = EVP_PKEY_new();
1539 if (eprikey == NULL) {
1540 SET_ERROR(kmfh, ERR_get_error());
1541 rv = KMF_ERR_KEYGEN_FAILED;
1542 goto cleanup;
1544 epubkey = EVP_PKEY_new();
1545 if (epubkey == NULL) {
1546 SET_ERROR(kmfh, ERR_get_error());
1547 rv = KMF_ERR_KEYGEN_FAILED;
1548 goto cleanup;
1550 if (keytype == KMF_RSA) {
1551 KMF_BIGINT *rsaexp = NULL;
1553 rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1554 if (rsaexp != NULL) {
1555 if (rsaexp->len > 0 &&
1556 rsaexp->len <= sizeof (eValue) &&
1557 rsaexp->val != NULL) {
1558 /* LINTED E_BAD_PTR_CAST_ALIGN */
1559 eValue = *(uint32_t *)rsaexp->val;
1560 if (BN_set_word(eValue_bn, eValue) == 0) {
1561 rv = KMF_ERR_BAD_PARAMETER;
1562 goto cleanup;
1564 } else {
1565 rv = KMF_ERR_BAD_PARAMETER;
1566 goto cleanup;
1568 } else {
1569 /* RSA Exponent is optional. Default is 0x10001 */
1570 rv = KMF_OK;
1573 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1574 &keylen, &keylen_size);
1575 if (rv == KMF_ERR_ATTR_NOT_FOUND)
1576 /* keylen is optional, default is 1024 */
1577 rv = KMF_OK;
1578 if (rv != KMF_OK) {
1579 rv = KMF_ERR_BAD_PARAMETER;
1580 goto cleanup;
1583 sslPrivKey = RSA_new();
1584 if (sslPrivKey == NULL ||
1585 RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1586 == 0) {
1587 SET_ERROR(kmfh, ERR_get_error());
1588 rv = KMF_ERR_KEYGEN_FAILED;
1589 } else {
1590 (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
1591 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1592 privkey->keyalg = KMF_RSA;
1593 privkey->keyclass = KMF_ASYM_PRI;
1594 privkey->israw = FALSE;
1595 privkey->keyp = (void *)eprikey;
1597 /* OpenSSL derives the public key from the private */
1598 (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
1599 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1600 pubkey->keyalg = KMF_RSA;
1601 pubkey->israw = FALSE;
1602 pubkey->keyclass = KMF_ASYM_PUB;
1603 pubkey->keyp = (void *)epubkey;
1605 } else if (keytype == KMF_DSA) {
1606 BIGNUM *p, *q, *g;
1608 sslDSAKey = DSA_new();
1609 if (sslDSAKey == NULL) {
1610 SET_ERROR(kmfh, ERR_get_error());
1611 return (KMF_ERR_MEMORY);
1614 p = BN_bin2bn(P, sizeof (P), NULL);
1615 q = BN_bin2bn(Q, sizeof (Q), NULL);
1616 g = BN_bin2bn(G, sizeof (G), NULL);
1617 if (p == NULL || q == NULL || g == NULL) {
1618 BN_free(p);
1619 BN_free(q);
1620 BN_free(g);
1621 SET_ERROR(kmfh, ERR_get_error());
1622 rv = KMF_ERR_KEYGEN_FAILED;
1623 goto cleanup;
1626 if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
1627 SET_ERROR(kmfh, ERR_get_error());
1628 rv = KMF_ERR_KEYGEN_FAILED;
1629 goto cleanup;
1632 if (!DSA_generate_key(sslDSAKey)) {
1633 SET_ERROR(kmfh, ERR_get_error());
1634 rv = KMF_ERR_KEYGEN_FAILED;
1635 goto cleanup;
1638 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1639 privkey->keyalg = KMF_DSA;
1640 privkey->keyclass = KMF_ASYM_PRI;
1641 privkey->israw = FALSE;
1642 if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1643 privkey->keyp = (void *)eprikey;
1644 } else {
1645 SET_ERROR(kmfh, ERR_get_error());
1646 rv = KMF_ERR_KEYGEN_FAILED;
1647 goto cleanup;
1650 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1651 pubkey->keyalg = KMF_DSA;
1652 pubkey->keyclass = KMF_ASYM_PUB;
1653 pubkey->israw = FALSE;
1655 if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1656 pubkey->keyp = (void *)epubkey;
1657 } else {
1658 SET_ERROR(kmfh, ERR_get_error());
1659 rv = KMF_ERR_KEYGEN_FAILED;
1660 goto cleanup;
1664 if (rv != KMF_OK) {
1665 goto cleanup;
1668 if (storekey) {
1669 KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1670 int i = 0;
1671 char *keyfile = NULL, *dirpath = NULL;
1672 KMF_ENCODE_FORMAT format;
1674 * Construct a new attribute arrray and call openssl_store_key
1676 kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1677 privkey, sizeof (privkey));
1678 i++;
1680 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1681 if (dirpath != NULL) {
1682 storeattrs[i].type = KMF_DIRPATH_ATTR;
1683 storeattrs[i].pValue = dirpath;
1684 storeattrs[i].valueLen = strlen(dirpath);
1685 i++;
1686 } else {
1687 rv = KMF_OK; /* DIRPATH is optional */
1689 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1690 attrlist, numattr);
1691 if (keyfile != NULL) {
1692 storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1693 storeattrs[i].pValue = keyfile;
1694 storeattrs[i].valueLen = strlen(keyfile);
1695 i++;
1696 } else {
1697 goto cleanup; /* KEYFILE is required */
1699 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1700 (void *)&format, NULL);
1701 if (rv == KMF_OK) {
1702 storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1703 storeattrs[i].pValue = &format;
1704 storeattrs[i].valueLen = sizeof (format);
1705 i++;
1708 rv = OpenSSL_StoreKey(handle, i, storeattrs);
1711 cleanup:
1712 if (eValue_bn != NULL)
1713 BN_free(eValue_bn);
1715 if (rv != KMF_OK) {
1716 if (eprikey != NULL)
1717 EVP_PKEY_free(eprikey);
1719 if (epubkey != NULL)
1720 EVP_PKEY_free(epubkey);
1722 if (pubkey->keylabel) {
1723 free(pubkey->keylabel);
1724 pubkey->keylabel = NULL;
1727 if (privkey->keylabel) {
1728 free(privkey->keylabel);
1729 privkey->keylabel = NULL;
1732 pubkey->keyp = NULL;
1733 privkey->keyp = NULL;
1736 if (sslPrivKey)
1737 RSA_free(sslPrivKey);
1739 if (sslDSAKey)
1740 DSA_free(sslDSAKey);
1742 if (out != NULL)
1743 (void) BIO_free(out);
1745 return (rv);
1749 * Make sure the BN conversion is properly padded with 0x00
1750 * bytes. If not, signature verification for DSA signatures
1751 * may fail in the case where the bignum value does not use
1752 * all of the bits.
1754 static int
1755 fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) {
1756 int bytes = len - BN_num_bytes(bn);
1758 /* prepend with leading 0x00 if necessary */
1759 while (bytes-- > 0)
1760 *buf++ = 0;
1762 (void) BN_bn2bin(bn, buf);
1764 * Return the desired length since we prepended it
1765 * with the necessary 0x00 padding.
1767 return (len);
1770 KMF_RETURN
1771 OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1772 KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1774 KMF_RETURN ret = KMF_OK;
1775 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1776 KMF_ALGORITHM_INDEX AlgId;
1777 EVP_MD_CTX *ctx;
1778 const EVP_MD *md;
1780 if (key == NULL || AlgOID == NULL ||
1781 tobesigned == NULL || output == NULL ||
1782 tobesigned->Data == NULL ||
1783 output->Data == NULL)
1784 return (KMF_ERR_BAD_PARAMETER);
1786 /* Map the OID to an OpenSSL algorithm */
1787 AlgId = x509_algoid_to_algid(AlgOID);
1788 if (AlgId == KMF_ALGID_NONE)
1789 return (KMF_ERR_BAD_ALGORITHM);
1791 if (key->keyalg == KMF_RSA) {
1792 EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1793 uchar_t *p;
1794 int len;
1795 switch (AlgId) {
1796 #ifndef OPENSSL_NO_MD5
1797 case KMF_ALGID_MD5WithRSA:
1798 md = EVP_md5();
1799 break;
1800 #endif
1801 #ifndef OPENSSL_NO_SHA
1802 case KMF_ALGID_SHA1WithRSA:
1803 md = EVP_sha1();
1804 break;
1805 #endif
1806 #ifndef OPENSSL_NO_SHA256
1807 case KMF_ALGID_SHA256WithRSA:
1808 md = EVP_sha256();
1809 break;
1810 #endif
1811 #ifndef OPENSSL_NO_SHA512
1812 case KMF_ALGID_SHA384WithRSA:
1813 md = EVP_sha384();
1814 break;
1815 case KMF_ALGID_SHA512WithRSA:
1816 md = EVP_sha512();
1817 break;
1818 #endif
1819 case KMF_ALGID_RSA:
1820 md = NULL;
1821 break;
1822 default:
1823 return (KMF_ERR_BAD_ALGORITHM);
1826 if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1827 RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1829 p = output->Data;
1830 if ((len = RSA_private_encrypt(tobesigned->Length,
1831 tobesigned->Data, p, rsa,
1832 RSA_PKCS1_PADDING)) <= 0) {
1833 SET_ERROR(kmfh, ERR_get_error());
1834 ret = KMF_ERR_INTERNAL;
1836 output->Length = len;
1837 } else {
1838 if ((ctx = EVP_MD_CTX_new()) == NULL)
1839 return (KMF_ERR_MEMORY);
1840 (void) EVP_SignInit_ex(ctx, md, NULL);
1841 (void) EVP_SignUpdate(ctx, tobesigned->Data,
1842 (uint32_t)tobesigned->Length);
1843 len = (uint32_t)output->Length;
1844 p = output->Data;
1845 if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
1846 SET_ERROR(kmfh, ERR_get_error());
1847 len = 0;
1848 ret = KMF_ERR_INTERNAL;
1850 output->Length = len;
1851 EVP_MD_CTX_free(ctx);
1853 } else if (key->keyalg == KMF_DSA) {
1854 DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1856 uchar_t hash[EVP_MAX_MD_SIZE];
1857 uint32_t hashlen;
1858 DSA_SIG *dsasig;
1860 if (AlgId == KMF_ALGID_DSA ||
1861 AlgId == KMF_ALGID_SHA1WithDSA)
1862 md = EVP_sha1();
1863 else if (AlgId == KMF_ALGID_SHA256WithDSA)
1864 md = EVP_sha256();
1865 else /* Bad algorithm */
1866 return (KMF_ERR_BAD_ALGORITHM);
1869 * OpenSSL EVP_Sign operation automatically converts to
1870 * ASN.1 output so we do the operations separately so we
1871 * are assured of NOT getting ASN.1 output returned.
1872 * KMF does not want ASN.1 encoded results because
1873 * not all mechanisms return ASN.1 encodings (PKCS#11
1874 * and NSS return raw signature data).
1876 if ((ctx = EVP_MD_CTX_new()) == NULL)
1877 return (KMF_ERR_MEMORY);
1878 (void) EVP_DigestInit_ex(ctx, md, NULL);
1879 (void) EVP_DigestUpdate(ctx, tobesigned->Data,
1880 tobesigned->Length);
1881 (void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
1883 /* Only sign first 20 bytes for SHA2 */
1884 if (AlgId == KMF_ALGID_SHA256WithDSA)
1885 hashlen = 20;
1886 dsasig = DSA_do_sign(hash, hashlen, dsa);
1887 if (dsasig != NULL) {
1888 int i;
1889 const BIGNUM *r, *s;
1891 DSA_SIG_get0(dsasig, &r, &s);
1892 output->Length = i = fixbnlen(r, output->Data,
1893 hashlen);
1895 output->Length += fixbnlen(s, &output->Data[i],
1896 hashlen);
1898 DSA_SIG_free(dsasig);
1899 } else {
1900 SET_ERROR(kmfh, ERR_get_error());
1902 EVP_MD_CTX_free(ctx);
1903 } else {
1904 return (KMF_ERR_BAD_PARAMETER);
1906 cleanup:
1907 return (ret);
1910 KMF_RETURN
1911 /*ARGSUSED*/
1912 OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1913 int numattr, KMF_ATTRIBUTE *attrlist)
1915 KMF_RETURN rv = KMF_OK;
1916 KMF_KEY_HANDLE *key;
1917 boolean_t destroy = B_TRUE;
1919 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1920 if (key == NULL || key->keyp == NULL)
1921 return (KMF_ERR_BAD_PARAMETER);
1923 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1924 (void *)&destroy, NULL);
1925 if (rv != KMF_OK) {
1926 /* "destroy" is optional. Default is TRUE */
1927 rv = KMF_OK;
1930 if (key->keyclass != KMF_ASYM_PUB &&
1931 key->keyclass != KMF_ASYM_PRI &&
1932 key->keyclass != KMF_SYMMETRIC)
1933 return (KMF_ERR_BAD_KEY_CLASS);
1935 if (key->keyclass == KMF_SYMMETRIC) {
1936 kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1937 key->keyp = NULL;
1938 } else {
1939 if (key->keyp != NULL) {
1940 EVP_PKEY_free(key->keyp);
1941 key->keyp = NULL;
1945 if (key->keylabel != NULL) {
1946 EVP_PKEY *pkey = NULL;
1947 /* If the file exists, make sure it is a proper key. */
1948 pkey = openssl_load_key(handle, key->keylabel);
1949 if (pkey == NULL) {
1950 if (key->keylabel != NULL) {
1951 free(key->keylabel);
1952 key->keylabel = NULL;
1954 return (KMF_ERR_KEY_NOT_FOUND);
1956 EVP_PKEY_free(pkey);
1958 if (destroy) {
1959 if (unlink(key->keylabel) != 0) {
1960 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1961 SET_SYS_ERROR(kmfh, errno);
1962 rv = KMF_ERR_INTERNAL;
1965 if (key->keylabel != NULL) {
1966 free(key->keylabel);
1967 key->keylabel = NULL;
1970 return (rv);
1973 KMF_RETURN
1974 OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1976 KMF_RETURN ret = KMF_OK;
1977 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1978 char str[256]; /* OpenSSL needs at least 120 byte buffer */
1980 ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1981 if (strlen(str)) {
1982 *msgstr = (char *)strdup(str);
1983 if ((*msgstr) == NULL)
1984 ret = KMF_ERR_MEMORY;
1985 } else {
1986 *msgstr = NULL;
1989 return (ret);
1992 static int
1993 ext2NID(int kmfext)
1995 switch (kmfext) {
1996 case KMF_X509_EXT_KEY_USAGE:
1997 return (NID_key_usage);
1998 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1999 return (NID_private_key_usage_period);
2000 case KMF_X509_EXT_CERT_POLICIES:
2001 return (NID_certificate_policies);
2002 case KMF_X509_EXT_SUBJ_ALTNAME:
2003 return (NID_subject_alt_name);
2004 case KMF_X509_EXT_ISSUER_ALTNAME:
2005 return (NID_issuer_alt_name);
2006 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2007 return (NID_basic_constraints);
2008 case KMF_X509_EXT_EXT_KEY_USAGE:
2009 return (NID_ext_key_usage);
2010 case KMF_X509_EXT_AUTH_KEY_ID:
2011 return (NID_authority_key_identifier);
2012 case KMF_X509_EXT_CRL_DIST_POINTS:
2013 return (NID_crl_distribution_points);
2014 case KMF_X509_EXT_SUBJ_KEY_ID:
2015 return (NID_subject_key_identifier);
2016 case KMF_X509_EXT_POLICY_MAPPINGS:
2017 return (OBJ_sn2nid("policyMappings"));
2018 case KMF_X509_EXT_NAME_CONSTRAINTS:
2019 return (OBJ_sn2nid("nameConstraints"));
2020 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2021 return (OBJ_sn2nid("policyConstraints"));
2022 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2023 return (OBJ_sn2nid("inhibitAnyPolicy"));
2024 case KMF_X509_EXT_FRESHEST_CRL:
2025 return (OBJ_sn2nid("freshestCRL"));
2026 default:
2027 return (NID_undef);
2031 KMF_RETURN
2032 OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2033 KMF_PRINTABLE_ITEM flag, char *resultStr)
2035 KMF_RETURN ret = KMF_OK;
2036 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2037 X509 *xcert = NULL;
2038 unsigned char *outbuf = NULL;
2039 unsigned char *outbuf_p;
2040 int j;
2041 int ext_index, nid, len;
2042 BIO *mem = NULL;
2043 STACK_OF(OPENSSL_STRING) *emlst = NULL;
2044 X509_EXTENSION *ex;
2046 if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2047 return (KMF_ERR_BAD_PARAMETER);
2050 /* copy cert data to outbuf */
2051 outbuf = malloc(pcert->Length);
2052 if (outbuf == NULL) {
2053 return (KMF_ERR_MEMORY);
2055 (void) memcpy(outbuf, pcert->Data, pcert->Length);
2057 outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2058 xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2059 if (xcert == NULL) {
2060 SET_ERROR(kmfh, ERR_get_error());
2061 ret = KMF_ERR_ENCODING;
2062 goto out;
2065 mem = BIO_new(BIO_s_mem());
2066 if (mem == NULL) {
2067 SET_ERROR(kmfh, ERR_get_error());
2068 ret = KMF_ERR_MEMORY;
2069 goto out;
2072 switch (flag) {
2073 case KMF_CERT_ISSUER:
2074 (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2075 XN_FLAG_SEP_CPLUS_SPC);
2076 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2077 break;
2079 case KMF_CERT_SUBJECT:
2080 (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2081 XN_FLAG_SEP_CPLUS_SPC);
2082 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2083 break;
2085 case KMF_CERT_VERSION:
2086 (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2087 "%ld", X509_get_version(xcert));
2088 len = strlen(resultStr);
2089 break;
2091 case KMF_CERT_SERIALNUM:
2092 if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2093 (void) strcpy(resultStr, "0x");
2094 len = BIO_gets(mem, &resultStr[2],
2095 KMF_CERT_PRINTABLE_LEN - 2);
2097 break;
2099 case KMF_CERT_NOTBEFORE:
2100 (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
2101 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2102 break;
2104 case KMF_CERT_NOTAFTER:
2105 (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
2106 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2107 break;
2109 case KMF_CERT_PUBKEY_DATA:
2111 RSA *rsa;
2112 DSA *dsa;
2114 EVP_PKEY *pkey = X509_get_pubkey(xcert);
2115 if (pkey == NULL) {
2116 SET_ERROR(kmfh, ERR_get_error());
2117 ret = KMF_ERR_ENCODING;
2118 goto out;
2121 if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
2122 (void) BIO_printf(mem,
2123 "RSA Public Key: (%d bit)\n",
2124 RSA_bits(rsa));
2125 (void) RSA_print(mem, rsa, 0);
2127 } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
2128 (void) BIO_printf(mem,
2129 "%12sDSA Public Key:\n", "");
2130 (void) DSA_print(mem, dsa, 0);
2131 } else {
2132 (void) BIO_printf(mem,
2133 "%12sUnknown Public Key:\n", "");
2135 (void) BIO_printf(mem, "\n");
2136 EVP_PKEY_free(pkey);
2138 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2139 break;
2140 case KMF_CERT_SIGNATURE_ALG:
2141 case KMF_CERT_PUBKEY_ALG:
2143 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2144 ASN1_OBJECT *alg = NULL;
2145 #else
2146 const ASN1_OBJECT *alg = NULL;
2147 #endif
2149 if (flag == KMF_CERT_SIGNATURE_ALG) {
2150 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2151 alg = xcert->sig_alg->algorithm;
2152 #else
2153 const X509_ALGOR *sig_alg = NULL;
2155 X509_get0_signature(NULL, &sig_alg, xcert);
2156 if (sig_alg != NULL)
2157 X509_ALGOR_get0(&alg, NULL, NULL,
2158 sig_alg);
2159 #endif
2160 } else {
2161 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2162 alg = xcert->cert_info->key->algor->algorithm;
2163 #else
2164 X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2166 if (key != NULL)
2167 (void) X509_PUBKEY_get0_param(
2168 (ASN1_OBJECT **)&alg, NULL, 0,
2169 NULL, key);
2170 #endif
2173 if (alg == NULL)
2174 len = -1;
2175 else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
2176 len = BIO_read(mem, resultStr,
2177 KMF_CERT_PRINTABLE_LEN);
2179 break;
2181 case KMF_CERT_EMAIL:
2182 emlst = X509_get1_email(xcert);
2183 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2184 (void) BIO_printf(mem, "%s\n",
2185 sk_OPENSSL_STRING_value(emlst, j));
2187 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2188 X509_email_free(emlst);
2189 break;
2190 case KMF_X509_EXT_ISSUER_ALTNAME:
2191 case KMF_X509_EXT_SUBJ_ALTNAME:
2192 case KMF_X509_EXT_KEY_USAGE:
2193 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2194 case KMF_X509_EXT_CERT_POLICIES:
2195 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2196 case KMF_X509_EXT_NAME_CONSTRAINTS:
2197 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2198 case KMF_X509_EXT_EXT_KEY_USAGE:
2199 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2200 case KMF_X509_EXT_AUTH_KEY_ID:
2201 case KMF_X509_EXT_SUBJ_KEY_ID:
2202 case KMF_X509_EXT_POLICY_MAPPINGS:
2203 case KMF_X509_EXT_CRL_DIST_POINTS:
2204 case KMF_X509_EXT_FRESHEST_CRL:
2205 nid = ext2NID(flag);
2206 if (nid == NID_undef) {
2207 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2208 goto out;
2211 ext_index = X509_get_ext_by_NID(xcert, nid, -1);
2212 if (ext_index == -1) {
2213 SET_ERROR(kmfh, ERR_get_error());
2215 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2216 goto out;
2218 ex = X509_get_ext(xcert, ext_index);
2220 (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2222 if (BIO_printf(mem, ": %s\n",
2223 X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2224 SET_ERROR(kmfh, ERR_get_error());
2225 ret = KMF_ERR_ENCODING;
2226 goto out;
2228 if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2229 (void) BIO_printf(mem, "%*s", 4, "");
2230 (void) ASN1_STRING_print(mem,
2231 X509_EXTENSION_get_data(ex));
2233 if (BIO_write(mem, "\n", 1) <= 0) {
2234 SET_ERROR(kmfh, ERR_get_error());
2235 ret = KMF_ERR_ENCODING;
2236 goto out;
2238 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2240 if (len <= 0) {
2241 SET_ERROR(kmfh, ERR_get_error());
2242 ret = KMF_ERR_ENCODING;
2245 out:
2246 if (outbuf != NULL) {
2247 free(outbuf);
2250 if (xcert != NULL) {
2251 X509_free(xcert);
2254 if (mem != NULL) {
2255 (void) BIO_free(mem);
2258 return (ret);
2261 KMF_RETURN
2262 /*ARGSUSED*/
2263 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2264 KMF_ATTRIBUTE *attrlist)
2266 KMF_RETURN rv = KMF_OK;
2267 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2268 KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2269 KMF_KEY_HANDLE *key = NULL;
2270 uint32_t numkeys = 1; /* 1 key only */
2271 char *dirpath = NULL;
2272 char *keyfile = NULL;
2273 KMF_ATTRIBUTE new_attrlist[16];
2274 int i = 0;
2277 * This is really just a FindKey operation, reuse the
2278 * FindKey function.
2280 kmf_set_attr_at_index(new_attrlist, i,
2281 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2282 i++;
2284 kmf_set_attr_at_index(new_attrlist, i,
2285 KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2286 i++;
2288 kmf_set_attr_at_index(new_attrlist, i,
2289 KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2290 i++;
2292 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2293 if (key == NULL) {
2294 return (KMF_ERR_BAD_PARAMETER);
2295 } else {
2296 kmf_set_attr_at_index(new_attrlist, i,
2297 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2298 i++;
2301 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2302 if (dirpath != NULL) {
2303 kmf_set_attr_at_index(new_attrlist, i,
2304 KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2305 i++;
2308 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2309 if (keyfile == NULL)
2310 return (KMF_ERR_BAD_PARAMETER);
2311 else {
2312 kmf_set_attr_at_index(new_attrlist, i,
2313 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2314 i++;
2317 rv = OpenSSL_FindKey(handle, i, new_attrlist);
2318 return (rv);
2321 KMF_RETURN
2322 /*ARGSUSED*/
2323 OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2324 KMF_OID *AlgOID, KMF_DATA *ciphertext,
2325 KMF_DATA *output)
2327 KMF_RETURN ret = KMF_OK;
2328 RSA *rsa = NULL;
2329 unsigned int in_len = 0, out_len = 0;
2330 unsigned int total_decrypted = 0, modulus_len = 0;
2331 uint8_t *in_data, *out_data;
2332 int i, blocks;
2334 if (key == NULL || AlgOID == NULL ||
2335 ciphertext == NULL || output == NULL ||
2336 ciphertext->Data == NULL ||
2337 output->Data == NULL)
2338 return (KMF_ERR_BAD_PARAMETER);
2340 if (key->keyalg == KMF_RSA) {
2341 rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2342 modulus_len = RSA_size(rsa);
2343 } else {
2344 return (KMF_ERR_BAD_PARAMETER);
2347 blocks = ciphertext->Length/modulus_len;
2348 out_data = output->Data;
2349 in_data = ciphertext->Data;
2350 out_len = modulus_len - 11;
2351 in_len = modulus_len;
2353 for (i = 0; i < blocks; i++) {
2354 out_len = RSA_private_decrypt(in_len,
2355 in_data, out_data, rsa, RSA_PKCS1_PADDING);
2357 if (out_len == 0) {
2358 ret = KMF_ERR_INTERNAL;
2359 goto cleanup;
2362 out_data += out_len;
2363 total_decrypted += out_len;
2364 in_data += in_len;
2367 output->Length = total_decrypted;
2369 cleanup:
2370 RSA_free(rsa);
2371 if (ret != KMF_OK)
2372 output->Length = 0;
2374 return (ret);
2379 * This function will create a certid from issuer_cert and user_cert.
2380 * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2381 * certid memory after use.
2383 static KMF_RETURN
2384 create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2385 const KMF_DATA *user_cert, OCSP_CERTID **certid)
2387 KMF_RETURN ret = KMF_OK;
2388 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2389 X509 *issuer = NULL;
2390 X509 *cert = NULL;
2391 unsigned char *ptmp;
2393 if (issuer_cert == NULL || user_cert == NULL) {
2394 return (KMF_ERR_BAD_PARAMETER);
2397 /* convert the DER-encoded issuer cert to an internal X509 */
2398 ptmp = issuer_cert->Data;
2399 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2400 issuer_cert->Length);
2401 if (issuer == NULL) {
2402 SET_ERROR(kmfh, ERR_get_error());
2403 ret = KMF_ERR_OCSP_BAD_ISSUER;
2404 goto end;
2407 /* convert the DER-encoded user cert to an internal X509 */
2408 ptmp = user_cert->Data;
2409 cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2410 user_cert->Length);
2411 if (cert == NULL) {
2412 SET_ERROR(kmfh, ERR_get_error());
2414 ret = KMF_ERR_OCSP_BAD_CERT;
2415 goto end;
2418 /* create a CERTID */
2419 *certid = OCSP_cert_to_id(NULL, cert, issuer);
2420 if (*certid == NULL) {
2421 SET_ERROR(kmfh, ERR_get_error());
2422 ret = KMF_ERR_OCSP_CERTID;
2423 goto end;
2426 end:
2427 if (issuer != NULL) {
2428 X509_free(issuer);
2431 if (cert != NULL) {
2432 X509_free(cert);
2435 return (ret);
2438 KMF_RETURN
2439 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2440 int numattr, KMF_ATTRIBUTE *attrlist)
2442 KMF_RETURN ret = KMF_OK;
2443 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2444 OCSP_CERTID *id = NULL;
2445 OCSP_REQUEST *req = NULL;
2446 BIO *derbio = NULL;
2447 char *reqfile;
2448 KMF_DATA *issuer_cert;
2449 KMF_DATA *user_cert;
2451 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2452 attrlist, numattr);
2453 if (user_cert == NULL)
2454 return (KMF_ERR_BAD_PARAMETER);
2456 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2457 attrlist, numattr);
2458 if (issuer_cert == NULL)
2459 return (KMF_ERR_BAD_PARAMETER);
2461 reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2462 attrlist, numattr);
2463 if (reqfile == NULL)
2464 return (KMF_ERR_BAD_PARAMETER);
2466 ret = create_certid(handle, issuer_cert, user_cert, &id);
2467 if (ret != KMF_OK) {
2468 return (ret);
2471 /* Create an OCSP request */
2472 req = OCSP_REQUEST_new();
2473 if (req == NULL) {
2474 SET_ERROR(kmfh, ERR_get_error());
2475 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2476 goto end;
2479 if (!OCSP_request_add0_id(req, id)) {
2480 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2481 goto end;
2484 /* Write the request to the output file with DER encoding */
2485 derbio = BIO_new_file(reqfile, "wb");
2486 if (!derbio) {
2487 SET_ERROR(kmfh, ERR_get_error());
2488 ret = KMF_ERR_OPEN_FILE;
2489 goto end;
2491 if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2492 ret = KMF_ERR_ENCODING;
2495 end:
2497 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2498 * will also deallocate certid's space.
2500 if (req != NULL) {
2501 OCSP_REQUEST_free(req);
2504 if (derbio != NULL) {
2505 (void) BIO_free(derbio);
2508 return (ret);
2511 /* ocsp_find_signer_sk() is copied from openssl source */
2512 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
2514 int i;
2515 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2516 const ASN1_OCTET_STRING *pid;
2518 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2519 OCSP_RESPID *id = bs->tbsResponseData->responderId;
2521 if (id->type == V_OCSP_RESPID_NAME)
2522 return (X509_find_by_subject(certs, id->value.byName));
2524 pid = id->value.byKey;
2525 #else
2526 const X509_NAME *pname;
2528 if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2529 return (NULL);
2531 if (pname != NULL)
2532 return (X509_find_by_subject(certs, (X509_NAME *)pname));
2533 #endif
2535 /* Lookup by key hash */
2537 /* If key hash isn't SHA1 length then forget it */
2538 if (pid->length != SHA_DIGEST_LENGTH)
2539 return (NULL);
2541 keyhash = pid->data;
2542 /* Calculate hash of each key and compare */
2543 for (i = 0; i < sk_X509_num(certs); i++) {
2544 /* LINTED E_BAD_PTR_CAST_ALIGN */
2545 X509 *x = sk_X509_value(certs, i);
2546 /* Use pubkey_digest to get the key ID value */
2547 (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2548 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2549 return (x);
2551 return (NULL);
2554 /* ocsp_find_signer() is copied from openssl source */
2555 /* ARGSUSED2 */
2556 static int
2557 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2558 X509_STORE *st, unsigned long flags)
2560 X509 *signer;
2561 if ((signer = ocsp_find_signer_sk(certs, bs))) {
2562 *psigner = signer;
2563 return (2);
2566 if (!(flags & OCSP_NOINTERN) &&
2567 (signer = ocsp_find_signer_sk(
2568 (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
2569 *psigner = signer;
2570 return (1);
2572 /* Maybe lookup from store if by subject name */
2574 *psigner = NULL;
2575 return (0);
2579 * This function will verify the signature of a basic response, using
2580 * the public key from the OCSP responder certificate.
2582 static KMF_RETURN
2583 check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2584 KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2586 KMF_RETURN ret = KMF_OK;
2587 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2588 STACK_OF(X509) *cert_stack = NULL;
2589 X509 *signer = NULL;
2590 X509 *issuer = NULL;
2591 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2592 EVP_PKEY *skey = NULL;
2593 #else
2594 STACK_OF(X509) *cert_stack2 = NULL;
2595 #endif
2596 unsigned char *ptmp;
2598 if (bs == NULL || issuer_cert == NULL)
2599 return (KMF_ERR_BAD_PARAMETER);
2602 * Find the certificate that signed the basic response.
2604 * If signer_cert is not NULL, we will use that as the signer cert.
2605 * Otherwise, we will check if the issuer cert is actually the signer.
2606 * If we still do not find a signer, we will look for it from the
2607 * certificate list came with the response file.
2609 if (signer_cert != NULL) {
2610 ptmp = signer_cert->Data;
2611 signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2612 signer_cert->Length);
2613 if (signer == NULL) {
2614 SET_ERROR(kmfh, ERR_get_error());
2615 ret = KMF_ERR_OCSP_BAD_SIGNER;
2616 goto end;
2618 } else {
2620 * Convert the issuer cert into X509 and push it into a
2621 * stack to be used by ocsp_find_signer().
2623 ptmp = issuer_cert->Data;
2624 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2625 issuer_cert->Length);
2626 if (issuer == NULL) {
2627 SET_ERROR(kmfh, ERR_get_error());
2628 ret = KMF_ERR_OCSP_BAD_ISSUER;
2629 goto end;
2632 if ((cert_stack = sk_X509_new_null()) == NULL) {
2633 ret = KMF_ERR_INTERNAL;
2634 goto end;
2637 if (sk_X509_push(cert_stack, issuer) == NULL) {
2638 ret = KMF_ERR_INTERNAL;
2639 goto end;
2642 ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2643 if (!ret) {
2644 /* can not find the signer */
2645 ret = KMF_ERR_OCSP_BAD_SIGNER;
2646 goto end;
2650 /* Verify the signature of the response */
2651 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2652 skey = X509_get_pubkey(signer);
2653 if (skey == NULL) {
2654 ret = KMF_ERR_OCSP_BAD_SIGNER;
2655 goto end;
2658 ret = OCSP_BASICRESP_verify(bs, skey, 0);
2659 #else
2661 * Technique based on
2662 * https://mta.openssl.org/pipermail/openssl-users/
2663 * 2017-October/006814.html
2665 if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2666 ret = KMF_ERR_INTERNAL;
2667 goto end;
2670 if (sk_X509_push(cert_stack2, signer) == NULL) {
2671 ret = KMF_ERR_INTERNAL;
2672 goto end;
2675 ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2676 #endif
2678 if (ret == 0) {
2679 ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2680 goto end;
2683 end:
2684 if (issuer != NULL) {
2685 X509_free(issuer);
2688 if (signer != NULL) {
2689 X509_free(signer);
2692 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
2693 if (skey != NULL) {
2694 EVP_PKEY_free(skey);
2696 #else
2697 if (cert_stack2 != NULL) {
2698 sk_X509_free(cert_stack2);
2700 #endif
2702 if (cert_stack != NULL) {
2703 sk_X509_free(cert_stack);
2706 return (ret);
2709 KMF_RETURN
2710 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2711 int numattr, KMF_ATTRIBUTE *attrlist)
2713 KMF_RETURN ret = KMF_OK;
2714 BIO *derbio = NULL;
2715 OCSP_RESPONSE *resp = NULL;
2716 OCSP_BASICRESP *bs = NULL;
2717 OCSP_CERTID *id = NULL;
2718 OCSP_SINGLERESP *single = NULL;
2719 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2720 int index, status, reason;
2721 KMF_DATA *issuer_cert;
2722 KMF_DATA *user_cert;
2723 KMF_DATA *signer_cert;
2724 KMF_DATA *response;
2725 int *response_reason, *response_status, *cert_status;
2726 boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
2727 uint32_t response_lifetime;
2729 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2730 attrlist, numattr);
2731 if (issuer_cert == NULL)
2732 return (KMF_ERR_BAD_PARAMETER);
2734 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2735 attrlist, numattr);
2736 if (user_cert == NULL)
2737 return (KMF_ERR_BAD_PARAMETER);
2739 response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2740 attrlist, numattr);
2741 if (response == NULL)
2742 return (KMF_ERR_BAD_PARAMETER);
2744 response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2745 attrlist, numattr);
2746 if (response_status == NULL)
2747 return (KMF_ERR_BAD_PARAMETER);
2749 response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2750 attrlist, numattr);
2751 if (response_reason == NULL)
2752 return (KMF_ERR_BAD_PARAMETER);
2754 cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2755 attrlist, numattr);
2756 if (cert_status == NULL)
2757 return (KMF_ERR_BAD_PARAMETER);
2759 /* Read in the response */
2760 derbio = BIO_new_mem_buf(response->Data, response->Length);
2761 if (!derbio) {
2762 ret = KMF_ERR_MEMORY;
2763 return (ret);
2766 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2767 if (resp == NULL) {
2768 ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2769 goto end;
2772 /* Check the response status */
2773 status = OCSP_response_status(resp);
2774 *response_status = status;
2775 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2776 ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2777 goto end;
2780 #ifdef DEBUG
2781 printf("Successfully checked the response file status.\n");
2782 #endif /* DEBUG */
2784 /* Extract basic response */
2785 bs = OCSP_response_get1_basic(resp);
2786 if (bs == NULL) {
2787 ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2788 goto end;
2791 #ifdef DEBUG
2792 printf("Successfully retrieved the basic response.\n");
2793 #endif /* DEBUG */
2795 /* Check the basic response signature if required */
2796 ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2797 (void *)&ignore_response_sign, NULL);
2798 if (ret != KMF_OK)
2799 ret = KMF_OK;
2801 signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2802 attrlist, numattr);
2804 if (ignore_response_sign == B_FALSE) {
2805 ret = check_response_signature(handle, bs,
2806 signer_cert, issuer_cert);
2807 if (ret != KMF_OK)
2808 goto end;
2811 #ifdef DEBUG
2812 printf("Successfully verified the response signature.\n");
2813 #endif /* DEBUG */
2815 /* Create a certid for the certificate in question */
2816 ret = create_certid(handle, issuer_cert, user_cert, &id);
2817 if (ret != KMF_OK) {
2818 ret = KMF_ERR_OCSP_CERTID;
2819 goto end;
2822 #ifdef DEBUG
2823 printf("successfully created a certid for the cert.\n");
2824 #endif /* DEBUG */
2826 /* Find the index of the single response for the certid */
2827 index = OCSP_resp_find(bs, id, -1);
2828 if (index < 0) {
2829 /* cound not find this certificate in the response */
2830 ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2831 goto end;
2834 #ifdef DEBUG
2835 printf("Successfully found the single response index for the cert.\n");
2836 #endif /* DEBUG */
2838 /* Retrieve the single response and get the cert status */
2839 single = OCSP_resp_get0(bs, index);
2840 status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2841 &nextupd);
2842 if (status == V_OCSP_CERTSTATUS_GOOD) {
2843 *cert_status = OCSP_GOOD;
2844 } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2845 *cert_status = OCSP_UNKNOWN;
2846 } else { /* revoked */
2847 *cert_status = OCSP_REVOKED;
2848 *response_reason = reason;
2850 ret = KMF_OK;
2852 /* resp. time is optional, so we don't care about the return code. */
2853 (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2854 (void *)&response_lifetime, NULL);
2856 if (!OCSP_check_validity(thisupd, nextupd, 300,
2857 response_lifetime)) {
2858 ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2859 goto end;
2862 #ifdef DEBUG
2863 printf("Successfully verify the time.\n");
2864 #endif /* DEBUG */
2866 end:
2867 if (derbio != NULL)
2868 (void) BIO_free(derbio);
2870 if (resp != NULL)
2871 OCSP_RESPONSE_free(resp);
2873 if (bs != NULL)
2874 OCSP_BASICRESP_free(bs);
2876 if (id != NULL)
2877 OCSP_CERTID_free(id);
2879 return (ret);
2882 static KMF_RETURN
2883 fetch_key(KMF_HANDLE_T handle, char *path,
2884 KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2886 KMF_RETURN rv = KMF_OK;
2887 EVP_PKEY *pkey = NULL;
2888 KMF_RAW_SYM_KEY *rkey = NULL;
2890 if (keyclass == KMF_ASYM_PRI ||
2891 keyclass == KMF_ASYM_PUB) {
2892 pkey = openssl_load_key(handle, path);
2893 if (pkey == NULL) {
2894 return (KMF_ERR_KEY_NOT_FOUND);
2896 if (key != NULL) {
2897 if (EVP_PKEY_get0_RSA(pkey) != NULL)
2898 key->keyalg = KMF_RSA;
2899 else if (EVP_PKEY_get0_DSA(pkey) != NULL)
2900 key->keyalg = KMF_DSA;
2902 key->kstype = KMF_KEYSTORE_OPENSSL;
2903 key->keyclass = keyclass;
2904 key->keyp = (void *)pkey;
2905 key->israw = FALSE;
2906 if (path != NULL &&
2907 ((key->keylabel = strdup(path)) == NULL)) {
2908 EVP_PKEY_free(pkey);
2909 return (KMF_ERR_MEMORY);
2911 } else {
2912 EVP_PKEY_free(pkey);
2913 pkey = NULL;
2915 } else if (keyclass == KMF_SYMMETRIC) {
2916 KMF_ENCODE_FORMAT fmt;
2918 * If the file is a recognized format,
2919 * then it is NOT a symmetric key.
2921 rv = kmf_get_file_format(path, &fmt);
2922 if (rv == KMF_OK || fmt != 0) {
2923 return (KMF_ERR_KEY_NOT_FOUND);
2924 } else if (rv == KMF_ERR_ENCODING) {
2926 * If we don't know the encoding,
2927 * it is probably a symmetric key.
2929 rv = KMF_OK;
2930 } else if (rv == KMF_ERR_OPEN_FILE) {
2931 return (KMF_ERR_KEY_NOT_FOUND);
2934 if (key != NULL) {
2935 KMF_DATA keyvalue;
2936 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2937 if (rkey == NULL) {
2938 rv = KMF_ERR_MEMORY;
2939 goto out;
2942 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2943 rv = kmf_read_input_file(handle, path, &keyvalue);
2944 if (rv != KMF_OK)
2945 goto out;
2947 rkey->keydata.len = keyvalue.Length;
2948 rkey->keydata.val = keyvalue.Data;
2950 key->kstype = KMF_KEYSTORE_OPENSSL;
2951 key->keyclass = keyclass;
2952 key->israw = TRUE;
2953 key->keyp = (void *)rkey;
2954 if (path != NULL &&
2955 ((key->keylabel = strdup(path)) == NULL)) {
2956 rv = KMF_ERR_MEMORY;
2960 out:
2961 if (rv != KMF_OK) {
2962 if (rkey != NULL) {
2963 kmf_free_raw_sym_key(rkey);
2965 if (pkey != NULL)
2966 EVP_PKEY_free(pkey);
2968 if (key != NULL) {
2969 key->keyalg = KMF_KEYALG_NONE;
2970 key->keyclass = KMF_KEYCLASS_NONE;
2971 key->keyp = NULL;
2975 return (rv);
2978 KMF_RETURN
2979 OpenSSL_FindKey(KMF_HANDLE_T handle,
2980 int numattr, KMF_ATTRIBUTE *attrlist)
2982 KMF_RETURN rv = KMF_OK;
2983 char *fullpath = NULL;
2984 uint32_t maxkeys;
2985 KMF_KEY_HANDLE *key;
2986 uint32_t *numkeys;
2987 KMF_KEY_CLASS keyclass;
2988 KMF_RAW_KEY_DATA *rawkey;
2989 char *dirpath;
2990 char *keyfile;
2992 if (handle == NULL)
2993 return (KMF_ERR_BAD_PARAMETER);
2995 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2996 if (numkeys == NULL)
2997 return (KMF_ERR_BAD_PARAMETER);
2999 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
3000 (void *)&keyclass, NULL);
3001 if (rv != KMF_OK)
3002 return (KMF_ERR_BAD_PARAMETER);
3004 if (keyclass != KMF_ASYM_PUB &&
3005 keyclass != KMF_ASYM_PRI &&
3006 keyclass != KMF_SYMMETRIC)
3007 return (KMF_ERR_BAD_KEY_CLASS);
3009 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3010 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3012 fullpath = get_fullpath(dirpath, keyfile);
3014 if (fullpath == NULL)
3015 return (KMF_ERR_BAD_PARAMETER);
3017 maxkeys = *numkeys;
3018 if (maxkeys == 0)
3019 maxkeys = 0xFFFFFFFF;
3020 *numkeys = 0;
3022 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
3023 /* it is okay to have "keys" contains NULL */
3026 * The caller may want a list of the raw key data as well.
3027 * Useful for importing keys from a file into other keystores.
3029 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
3031 if (isdir(fullpath)) {
3032 DIR *dirp;
3033 struct dirent *dp;
3034 int n = 0;
3036 /* open all files in the directory and attempt to read them */
3037 if ((dirp = opendir(fullpath)) == NULL) {
3038 return (KMF_ERR_BAD_PARAMETER);
3040 rewinddir(dirp);
3041 while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
3042 if (strcmp(dp->d_name, ".") &&
3043 strcmp(dp->d_name, "..")) {
3044 char *fname;
3046 fname = get_fullpath(fullpath,
3047 (char *)&dp->d_name);
3049 rv = fetch_key(handle, fname,
3050 keyclass, key ? &key[n] : NULL);
3052 if (rv == KMF_OK) {
3053 if (key != NULL && rawkey != NULL)
3054 rv = convertToRawKey(
3055 key[n].keyp, &rawkey[n]);
3056 n++;
3059 if (rv != KMF_OK || key == NULL)
3060 free(fname);
3063 (void) closedir(dirp);
3064 free(fullpath);
3065 (*numkeys) = n;
3066 } else {
3067 rv = fetch_key(handle, fullpath, keyclass, key);
3068 if (rv == KMF_OK)
3069 (*numkeys) = 1;
3071 if (rv != KMF_OK || key == NULL)
3072 free(fullpath);
3074 if (rv == KMF_OK && key != NULL && rawkey != NULL) {
3075 rv = convertToRawKey(key->keyp, rawkey);
3079 if (rv == KMF_OK && (*numkeys) == 0)
3080 rv = KMF_ERR_KEY_NOT_FOUND;
3081 else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
3082 rv = KMF_OK;
3084 return (rv);
3087 #define HANDLE_PK12_ERROR { \
3088 SET_ERROR(kmfh, ERR_get_error()); \
3089 rv = KMF_ERR_ENCODING; \
3090 goto out; \
3093 static int
3094 add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3096 unsigned char *alias;
3097 int len;
3099 if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
3100 if (PKCS12_add_friendlyname_asc(bag,
3101 (const char *)alias, len) == 0)
3102 return (0);
3104 return (1);
3107 static PKCS7 *
3108 add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3109 uchar_t *keyid, unsigned int keyidlen)
3111 PKCS12_SAFEBAG *bag = NULL;
3112 PKCS7 *cert_authsafe = NULL;
3113 STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3115 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3116 if (bag_stack == NULL)
3117 return (NULL);
3119 /* Convert cert from X509 struct to PKCS#12 bag */
3120 bag = PKCS12_SAFEBAG_create_cert(sslcert);
3121 if (bag == NULL) {
3122 goto out;
3125 /* Add the key id to the certificate bag. */
3126 if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3127 goto out;
3130 if (!add_alias_to_bag(bag, sslcert))
3131 goto out;
3133 /* Pile it on the bag_stack. */
3134 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3135 goto out;
3137 /* Turn bag_stack of certs into encrypted authsafe. */
3138 cert_authsafe = PKCS12_pack_p7encdata(
3139 NID_pbe_WithSHA1And40BitRC2_CBC,
3140 cred->cred, cred->credlen, NULL, 0,
3141 PKCS12_DEFAULT_ITER, bag_stack);
3143 out:
3144 if (bag_stack != NULL)
3145 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3147 return (cert_authsafe);
3150 static PKCS7 *
3151 add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3152 uchar_t *keyid, unsigned int keyidlen,
3153 char *label, int label_len)
3155 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3156 STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3157 PKCS12_SAFEBAG *bag = NULL;
3158 PKCS7 *key_authsafe = NULL;
3160 p8 = EVP_PKEY2PKCS8(pkey);
3161 if (p8 == NULL) {
3162 return (NULL);
3164 /* Put the shrouded key into a PKCS#12 bag. */
3165 bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
3166 NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3167 cred->cred, cred->credlen,
3168 NULL, 0, PKCS12_DEFAULT_ITER, p8);
3170 /* Clean up the PKCS#8 shrouded key, don't need it now. */
3171 PKCS8_PRIV_KEY_INFO_free(p8);
3172 p8 = NULL;
3174 if (bag == NULL) {
3175 return (NULL);
3177 if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3178 goto out;
3179 if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3180 goto out;
3182 /* Start a PKCS#12 safebag container for the private key. */
3183 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3184 if (bag_stack == NULL)
3185 goto out;
3187 /* Pile on the private key on the bag_stack. */
3188 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3189 goto out;
3191 key_authsafe = PKCS12_pack_p7data(bag_stack);
3193 out:
3194 if (bag_stack != NULL)
3195 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3196 bag_stack = NULL;
3197 return (key_authsafe);
3200 static EVP_PKEY *
3201 ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3203 RSA *rsa = NULL;
3204 EVP_PKEY *newkey = NULL;
3205 BIGNUM *n = NULL, *e = NULL, *d = NULL,
3206 *p = NULL, *q = NULL,
3207 *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
3209 if ((rsa = RSA_new()) == NULL)
3210 goto cleanup;
3212 if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3213 goto cleanup;
3215 if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3216 goto cleanup;
3218 if (key->priexp.val != NULL &&
3219 (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3220 goto cleanup;
3222 if (key->prime1.val != NULL &&
3223 (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3224 goto cleanup;
3226 if (key->prime2.val != NULL &&
3227 (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3228 goto cleanup;
3230 if (key->exp1.val != NULL &&
3231 (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3232 goto cleanup;
3234 if (key->exp2.val != NULL &&
3235 (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3236 goto cleanup;
3238 if (key->coef.val != NULL &&
3239 (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3240 goto cleanup;
3242 if (RSA_set0_key(rsa, n, e, d) == 0)
3243 goto cleanup;
3244 n = e = d = NULL;
3245 if (RSA_set0_factors(rsa, p, q) == 0)
3246 goto cleanup;
3247 p = q = NULL;
3248 if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3249 goto cleanup;
3250 dmp1 = dmq1 = iqmp = NULL;
3252 if ((newkey = EVP_PKEY_new()) == NULL)
3253 goto cleanup;
3255 (void) EVP_PKEY_set1_RSA(newkey, rsa);
3257 cleanup:
3258 /* The original key must be freed once here or it leaks memory */
3259 if (rsa)
3260 RSA_free(rsa);
3261 BN_free(n);
3262 BN_free(e);
3263 BN_free(d);
3264 BN_free(p);
3265 BN_free(q);
3266 BN_free(dmp1);
3267 BN_free(dmq1);
3268 BN_free(iqmp);
3270 return (newkey);
3273 static EVP_PKEY *
3274 ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3276 DSA *dsa = NULL;
3277 EVP_PKEY *newkey = NULL;
3278 BIGNUM *p = NULL, *q = NULL, *g = NULL,
3279 *priv_key = NULL, *pub_key = NULL;
3281 if ((dsa = DSA_new()) == NULL)
3282 goto cleanup;
3284 if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3285 goto cleanup;
3287 if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3288 goto cleanup;
3290 if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3291 goto cleanup;
3293 if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3294 NULL)) == NULL)
3295 goto cleanup;
3297 if (key->pubvalue.val != NULL && (pub_key =
3298 BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3299 goto cleanup;
3301 if (DSA_set0_pqg(dsa, p, q, g) == 0)
3302 goto cleanup;
3303 p = q = g = NULL;
3304 if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3305 goto cleanup;
3306 pub_key = priv_key = 0;
3308 if ((newkey = EVP_PKEY_new()) == NULL)
3309 goto cleanup;
3311 (void) EVP_PKEY_set1_DSA(newkey, dsa);
3313 cleanup:
3314 /* The original key must be freed once here or it leaks memory */
3315 if (dsa)
3316 DSA_free(dsa);
3317 BN_free(p);
3318 BN_free(q);
3319 BN_free(g);
3320 BN_free(priv_key);
3321 BN_free(pub_key);
3323 return (newkey);
3326 static EVP_PKEY *
3327 raw_key_to_pkey(KMF_KEY_HANDLE *key)
3329 EVP_PKEY *pkey = NULL;
3330 KMF_RAW_KEY_DATA *rawkey;
3331 ASN1_TYPE *attr = NULL;
3332 KMF_RETURN ret;
3334 if (key == NULL || !key->israw)
3335 return (NULL);
3337 rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3338 if (rawkey->keytype == KMF_RSA) {
3339 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3340 } else if (rawkey->keytype == KMF_DSA) {
3341 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3342 } else if (rawkey->keytype == KMF_ECDSA) {
3344 * OpenSSL in Solaris does not support EC for
3345 * legal reasons
3347 return (NULL);
3348 } else {
3349 /* wrong kind of key */
3350 return (NULL);
3353 if (rawkey->label != NULL) {
3354 if ((attr = ASN1_TYPE_new()) == NULL) {
3355 EVP_PKEY_free(pkey);
3356 return (NULL);
3358 attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3359 (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3360 strlen(rawkey->label));
3361 attr->type = V_ASN1_BMPSTRING;
3362 attr->value.ptr = (char *)attr->value.bmpstring;
3363 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3364 if (ret != KMF_OK) {
3365 EVP_PKEY_free(pkey);
3366 ASN1_TYPE_free(attr);
3367 return (NULL);
3370 if (rawkey->id.Data != NULL) {
3371 if ((attr = ASN1_TYPE_new()) == NULL) {
3372 EVP_PKEY_free(pkey);
3373 return (NULL);
3375 attr->value.octet_string =
3376 ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3377 attr->type = V_ASN1_OCTET_STRING;
3378 (void) ASN1_STRING_set(attr->value.octet_string,
3379 rawkey->id.Data, rawkey->id.Length);
3380 attr->value.ptr = (char *)attr->value.octet_string;
3381 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3382 if (ret != KMF_OK) {
3383 EVP_PKEY_free(pkey);
3384 ASN1_TYPE_free(attr);
3385 return (NULL);
3388 return (pkey);
3392 * Search a list of private keys to find one that goes with the certificate.
3394 static EVP_PKEY *
3395 find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3397 int i;
3398 EVP_PKEY *pkey = NULL;
3400 if (numkeys == 0 || keylist == NULL || xcert == NULL)
3401 return (NULL);
3402 for (i = 0; i < numkeys; i++) {
3403 if (keylist[i].israw)
3404 pkey = raw_key_to_pkey(&keylist[i]);
3405 else
3406 pkey = (EVP_PKEY *)keylist[i].keyp;
3407 if (pkey != NULL) {
3408 if (X509_check_private_key(xcert, pkey)) {
3409 return (pkey);
3410 } else {
3411 EVP_PKEY_free(pkey);
3412 pkey = NULL;
3416 return (pkey);
3419 static KMF_RETURN
3420 local_export_pk12(KMF_HANDLE_T handle,
3421 KMF_CREDENTIAL *cred,
3422 int numcerts, KMF_X509_DER_CERT *certlist,
3423 int numkeys, KMF_KEY_HANDLE *keylist,
3424 char *filename)
3426 KMF_RETURN rv = KMF_OK;
3427 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3428 BIO *bio = NULL;
3429 PKCS7 *cert_authsafe = NULL;
3430 PKCS7 *key_authsafe = NULL;
3431 STACK_OF(PKCS7) *authsafe_stack = NULL;
3432 PKCS12 *p12_elem = NULL;
3433 int i;
3435 if (numcerts == 0 && numkeys == 0)
3436 return (KMF_ERR_BAD_PARAMETER);
3439 * Open the output file.
3441 if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3442 SET_ERROR(kmfh, ERR_get_error());
3443 rv = KMF_ERR_OPEN_FILE;
3444 goto cleanup;
3447 /* Start a PKCS#7 stack. */
3448 authsafe_stack = sk_PKCS7_new_null();
3449 if (authsafe_stack == NULL) {
3450 rv = KMF_ERR_MEMORY;
3451 goto cleanup;
3453 if (numcerts > 0) {
3454 for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3455 const uchar_t *p = certlist[i].certificate.Data;
3456 long len = certlist[i].certificate.Length;
3457 X509 *xcert = NULL;
3458 EVP_PKEY *pkey = NULL;
3459 unsigned char keyid[EVP_MAX_MD_SIZE];
3460 unsigned int keyidlen = 0;
3462 xcert = d2i_X509(NULL, &p, len);
3463 if (xcert == NULL) {
3464 SET_ERROR(kmfh, ERR_get_error());
3465 rv = KMF_ERR_ENCODING;
3467 if (certlist[i].kmf_private.label != NULL) {
3468 /* Set alias attribute */
3469 (void) X509_alias_set1(xcert,
3470 (uchar_t *)certlist[i].kmf_private.label,
3471 strlen(certlist[i].kmf_private.label));
3473 /* Check if there is a key corresponding to this cert */
3474 pkey = find_matching_key(xcert, numkeys, keylist);
3477 * If key is found, get fingerprint and create a
3478 * safebag.
3480 if (pkey != NULL) {
3481 (void) X509_digest(xcert, EVP_sha1(),
3482 keyid, &keyidlen);
3483 key_authsafe = add_key_to_safe(pkey, cred,
3484 keyid, keyidlen,
3485 certlist[i].kmf_private.label,
3486 (certlist[i].kmf_private.label ?
3487 strlen(certlist[i].kmf_private.label) : 0));
3489 if (key_authsafe == NULL) {
3490 X509_free(xcert);
3491 EVP_PKEY_free(pkey);
3492 goto cleanup;
3494 /* Put the key safe into the Auth Safe */
3495 if (!sk_PKCS7_push(authsafe_stack,
3496 key_authsafe)) {
3497 X509_free(xcert);
3498 EVP_PKEY_free(pkey);
3499 goto cleanup;
3503 /* create a certificate safebag */
3504 cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3505 keyidlen);
3506 if (cert_authsafe == NULL) {
3507 X509_free(xcert);
3508 EVP_PKEY_free(pkey);
3509 goto cleanup;
3511 if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3512 X509_free(xcert);
3513 EVP_PKEY_free(pkey);
3514 goto cleanup;
3517 X509_free(xcert);
3518 if (pkey)
3519 EVP_PKEY_free(pkey);
3521 } else if (numcerts == 0 && numkeys > 0) {
3523 * If only adding keys to the file.
3525 for (i = 0; i < numkeys; i++) {
3526 EVP_PKEY *pkey = NULL;
3528 if (keylist[i].israw)
3529 pkey = raw_key_to_pkey(&keylist[i]);
3530 else
3531 pkey = (EVP_PKEY *)keylist[i].keyp;
3533 if (pkey == NULL)
3534 continue;
3536 key_authsafe = add_key_to_safe(pkey, cred,
3537 NULL, 0, NULL, 0);
3539 if (key_authsafe == NULL) {
3540 EVP_PKEY_free(pkey);
3541 goto cleanup;
3543 if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3544 EVP_PKEY_free(pkey);
3545 goto cleanup;
3549 p12_elem = PKCS12_init(NID_pkcs7_data);
3550 if (p12_elem == NULL) {
3551 goto cleanup;
3554 /* Put the PKCS#7 stack into the PKCS#12 element. */
3555 if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3556 goto cleanup;
3559 /* Set the integrity MAC on the PKCS#12 element. */
3560 if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3561 NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3562 goto cleanup;
3565 /* Write the PKCS#12 element to the export file. */
3566 if (!i2d_PKCS12_bio(bio, p12_elem)) {
3567 goto cleanup;
3569 PKCS12_free(p12_elem);
3571 cleanup:
3572 /* Clear away the PKCS#7 stack, we're done with it. */
3573 if (authsafe_stack)
3574 sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3576 if (bio != NULL)
3577 (void) BIO_free_all(bio);
3579 return (rv);
3582 KMF_RETURN
3583 openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3584 KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3585 KMF_CREDENTIAL *p12cred, char *filename)
3587 KMF_RETURN rv;
3589 if (certlist == NULL && keylist == NULL)
3590 return (KMF_ERR_BAD_PARAMETER);
3592 rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3593 numkeys, keylist, filename);
3595 return (rv);
3598 KMF_RETURN
3599 OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3601 KMF_RETURN rv;
3602 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3603 char *fullpath = NULL;
3604 char *dirpath = NULL;
3605 char *certfile = NULL;
3606 char *keyfile = NULL;
3607 char *filename = NULL;
3608 KMF_CREDENTIAL *p12cred = NULL;
3609 KMF_X509_DER_CERT certdata;
3610 KMF_KEY_HANDLE key;
3611 int gotkey = 0;
3612 int gotcert = 0;
3614 if (handle == NULL)
3615 return (KMF_ERR_BAD_PARAMETER);
3618 * First, find the certificate.
3620 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3621 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3622 if (certfile != NULL) {
3623 fullpath = get_fullpath(dirpath, certfile);
3624 if (fullpath == NULL)
3625 return (KMF_ERR_BAD_PARAMETER);
3627 if (isdir(fullpath)) {
3628 free(fullpath);
3629 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3632 (void) memset(&certdata, 0, sizeof (certdata));
3633 rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3634 fullpath, &certdata.certificate);
3635 if (rv != KMF_OK)
3636 goto end;
3638 gotcert++;
3639 certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3640 free(fullpath);
3644 * Now find the private key.
3646 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3647 if (keyfile != NULL) {
3648 fullpath = get_fullpath(dirpath, keyfile);
3649 if (fullpath == NULL)
3650 return (KMF_ERR_BAD_PARAMETER);
3652 if (isdir(fullpath)) {
3653 free(fullpath);
3654 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3657 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3658 rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3659 if (rv != KMF_OK)
3660 goto end;
3661 gotkey++;
3665 * Open the output file.
3667 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3668 numattr);
3669 if (filename == NULL) {
3670 rv = KMF_ERR_BAD_PARAMETER;
3671 goto end;
3674 /* Stick the key and the cert into a PKCS#12 file */
3675 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3676 if (p12cred == NULL) {
3677 rv = KMF_ERR_BAD_PARAMETER;
3678 goto end;
3681 rv = local_export_pk12(handle, p12cred, 1, &certdata,
3682 1, &key, filename);
3684 end:
3685 if (fullpath)
3686 free(fullpath);
3688 if (gotcert)
3689 kmf_free_kmf_cert(handle, &certdata);
3690 if (gotkey)
3691 kmf_free_kmf_key(handle, &key);
3692 return (rv);
3696 * Helper function to extract keys and certificates from
3697 * a single PEM file. Typically the file should contain a
3698 * private key and an associated public key wrapped in an x509 cert.
3699 * However, the file may be just a list of X509 certs with no keys.
3701 static KMF_RETURN
3702 extract_pem(KMF_HANDLE *kmfh,
3703 char *issuer, char *subject, KMF_BIGINT *serial,
3704 char *filename, CK_UTF8CHAR *pin,
3705 CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3706 int *numcerts)
3707 /* ARGSUSED6 */
3709 KMF_RETURN rv = KMF_OK;
3710 FILE *fp;
3711 STACK_OF(X509_INFO) *x509_info_stack = NULL;
3712 int i, ncerts = 0, matchcerts = 0;
3713 EVP_PKEY *pkey = NULL;
3714 X509_INFO *info;
3715 X509 *x;
3716 X509_INFO **cert_infos = NULL;
3717 KMF_DATA *certlist = NULL;
3719 if (priv_key)
3720 *priv_key = NULL;
3721 if (certs)
3722 *certs = NULL;
3723 fp = fopen(filename, "r");
3724 if (fp == NULL)
3725 return (KMF_ERR_OPEN_FILE);
3727 x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3728 if (x509_info_stack == NULL) {
3729 (void) fclose(fp);
3730 return (KMF_ERR_ENCODING);
3732 cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3733 sizeof (X509_INFO *));
3734 if (cert_infos == NULL) {
3735 (void) fclose(fp);
3736 rv = KMF_ERR_MEMORY;
3737 goto err;
3740 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3741 /* LINTED E_BAD_PTR_CAST_ALIGN */
3742 cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
3743 ncerts++;
3746 if (ncerts == 0) {
3747 (void) fclose(fp);
3748 rv = KMF_ERR_CERT_NOT_FOUND;
3749 goto err;
3752 if (priv_key != NULL) {
3753 rewind(fp);
3754 pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
3756 (void) fclose(fp);
3758 x = cert_infos[ncerts - 1]->x509;
3760 * Make sure the private key matchs the last cert in the file.
3762 if (pkey != NULL && !X509_check_private_key(x, pkey)) {
3763 EVP_PKEY_free(pkey);
3764 rv = KMF_ERR_KEY_MISMATCH;
3765 goto err;
3768 certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
3769 if (certlist == NULL) {
3770 if (pkey != NULL)
3771 EVP_PKEY_free(pkey);
3772 rv = KMF_ERR_MEMORY;
3773 goto err;
3777 * Convert all of the certs to DER format.
3779 matchcerts = 0;
3780 for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
3781 boolean_t match = FALSE;
3782 info = cert_infos[ncerts - 1 - i];
3784 rv = check_cert(info->x509, issuer, subject, serial, &match);
3785 if (rv != KMF_OK || match != TRUE) {
3786 rv = KMF_OK;
3787 continue;
3790 rv = ssl_cert2KMFDATA(kmfh, info->x509,
3791 &certlist[matchcerts++]);
3793 if (rv != KMF_OK) {
3794 int j;
3795 for (j = 0; j < matchcerts; j++)
3796 kmf_free_data(&certlist[j]);
3797 free(certlist);
3798 certlist = NULL;
3799 ncerts = matchcerts = 0;
3803 if (numcerts != NULL)
3804 *numcerts = matchcerts;
3806 if (certs != NULL)
3807 *certs = certlist;
3808 else if (certlist != NULL) {
3809 for (i = 0; i < ncerts; i++)
3810 kmf_free_data(&certlist[i]);
3811 free(certlist);
3812 certlist = NULL;
3815 if (priv_key == NULL && pkey != NULL)
3816 EVP_PKEY_free(pkey);
3817 else if (priv_key != NULL && pkey != NULL)
3818 *priv_key = pkey;
3820 err:
3821 /* Cleanup the stack of X509 info records */
3822 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3823 /* LINTED E_BAD_PTR_CAST_ALIGN */
3824 info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3825 X509_INFO_free(info);
3827 if (x509_info_stack)
3828 sk_X509_INFO_free(x509_info_stack);
3830 if (cert_infos != NULL)
3831 free(cert_infos);
3833 return (rv);
3836 static KMF_RETURN
3837 openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3838 STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3840 KMF_RETURN ret;
3841 int i;
3843 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3844 /* LINTED E_BAD_PTR_CAST_ALIGN */
3845 PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3846 ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3847 keys, certs);
3849 if (ret != KMF_OK)
3850 return (ret);
3853 return (ret);
3856 static KMF_RETURN
3857 set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3859 X509_ATTRIBUTE *attr = NULL;
3861 if (pkey == NULL || attrib == NULL)
3862 return (KMF_ERR_BAD_PARAMETER);
3864 attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3865 if (attr != NULL) {
3866 int i;
3868 if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3869 (void) EVP_PKEY_delete_attr(pkey, i);
3870 if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
3871 X509_ATTRIBUTE_free(attr);
3872 return (KMF_ERR_MEMORY);
3874 } else {
3875 return (KMF_ERR_MEMORY);
3878 return (KMF_OK);
3881 static KMF_RETURN
3882 openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3883 STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3885 KMF_RETURN ret = KMF_OK;
3886 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3887 EVP_PKEY *pkey = NULL;
3888 X509 *xcert = NULL;
3889 const ASN1_TYPE *keyid = NULL;
3890 const ASN1_TYPE *fname = NULL;
3891 uchar_t *data = NULL;
3893 keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3894 fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
3896 switch (PKCS12_SAFEBAG_get_nid(bag)) {
3897 case NID_keyBag:
3898 if (keylist == NULL)
3899 goto end;
3900 pkey = EVP_PKCS82PKEY(
3901 PKCS12_SAFEBAG_get0_p8inf(bag));
3902 if (pkey == NULL)
3903 ret = KMF_ERR_PKCS12_FORMAT;
3905 break;
3906 case NID_pkcs8ShroudedKeyBag:
3907 if (keylist == NULL)
3908 goto end;
3909 p8 = PKCS12_decrypt_skey(bag, pass, passlen);
3910 if (p8 == NULL)
3911 return (KMF_ERR_AUTH_FAILED);
3912 pkey = EVP_PKCS82PKEY(p8);
3913 PKCS8_PRIV_KEY_INFO_free(p8);
3914 if (pkey == NULL)
3915 ret = KMF_ERR_PKCS12_FORMAT;
3916 break;
3917 case NID_certBag:
3918 if (certlist == NULL)
3919 goto end;
3920 if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3921 NID_x509Certificate)
3922 return (KMF_ERR_PKCS12_FORMAT);
3923 xcert = PKCS12_SAFEBAG_get1_cert(bag);
3924 if (xcert == NULL) {
3925 ret = KMF_ERR_PKCS12_FORMAT;
3926 goto end;
3928 if (keyid != NULL) {
3929 if (X509_keyid_set1(xcert,
3930 keyid->value.octet_string->data,
3931 keyid->value.octet_string->length) == 0) {
3932 ret = KMF_ERR_PKCS12_FORMAT;
3933 goto end;
3936 if (fname != NULL) {
3937 int len, r;
3938 len = ASN1_STRING_to_UTF8(&data,
3939 fname->value.asn1_string);
3940 if (len > 0 && data != NULL) {
3941 r = X509_alias_set1(xcert, data, len);
3942 if (r == NULL) {
3943 ret = KMF_ERR_PKCS12_FORMAT;
3944 goto end;
3946 } else {
3947 ret = KMF_ERR_PKCS12_FORMAT;
3948 goto end;
3951 if (sk_X509_push(certlist, xcert) == 0)
3952 ret = KMF_ERR_MEMORY;
3953 else
3954 xcert = NULL;
3955 break;
3956 case NID_safeContentsBag:
3957 return (openssl_parse_bags(
3958 PKCS12_SAFEBAG_get0_safes(bag),
3959 pass, keylist, certlist));
3960 default:
3961 ret = KMF_ERR_PKCS12_FORMAT;
3962 break;
3966 * Set the ID and/or FriendlyName attributes on the key.
3967 * If converting to PKCS11 objects, these can translate to CKA_ID
3968 * and CKA_LABEL values.
3970 if (pkey != NULL && ret == KMF_OK) {
3971 ASN1_TYPE *attr = NULL;
3972 if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3973 if ((attr = ASN1_TYPE_new()) == NULL)
3974 return (KMF_ERR_MEMORY);
3975 attr->value.octet_string =
3976 ASN1_STRING_dup(keyid->value.octet_string);
3977 attr->type = V_ASN1_OCTET_STRING;
3978 attr->value.ptr = (char *)attr->value.octet_string;
3979 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3980 OPENSSL_free(attr);
3983 if (ret == KMF_OK && fname != NULL &&
3984 fname->type == V_ASN1_BMPSTRING) {
3985 if ((attr = ASN1_TYPE_new()) == NULL)
3986 return (KMF_ERR_MEMORY);
3987 attr->value.bmpstring =
3988 ASN1_STRING_dup(fname->value.bmpstring);
3989 attr->type = V_ASN1_BMPSTRING;
3990 attr->value.ptr = (char *)attr->value.bmpstring;
3991 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3992 OPENSSL_free(attr);
3995 if (ret == KMF_OK && keylist != NULL &&
3996 sk_EVP_PKEY_push(keylist, pkey) == 0)
3997 ret = KMF_ERR_MEMORY;
3999 if (ret == KMF_OK && keylist != NULL)
4000 pkey = NULL;
4001 end:
4002 if (pkey != NULL)
4003 EVP_PKEY_free(pkey);
4004 if (xcert != NULL)
4005 X509_free(xcert);
4006 if (data != NULL)
4007 OPENSSL_free(data);
4009 return (ret);
4012 static KMF_RETURN
4013 openssl_pkcs12_parse(PKCS12 *p12, char *pin,
4014 STACK_OF(EVP_PKEY) *keys,
4015 STACK_OF(X509) *certs,
4016 STACK_OF(X509) *ca)
4017 /* ARGSUSED3 */
4019 KMF_RETURN ret = KMF_OK;
4020 STACK_OF(PKCS7) *asafes = NULL;
4021 STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
4022 int i, bagnid;
4023 PKCS7 *p7;
4025 if (p12 == NULL || (keys == NULL && certs == NULL))
4026 return (KMF_ERR_BAD_PARAMETER);
4028 if (pin == NULL || *pin == NULL) {
4029 if (PKCS12_verify_mac(p12, NULL, 0)) {
4030 pin = NULL;
4031 } else if (PKCS12_verify_mac(p12, "", 0)) {
4032 pin = "";
4033 } else {
4034 return (KMF_ERR_AUTH_FAILED);
4036 } else if (!PKCS12_verify_mac(p12, pin, -1)) {
4037 return (KMF_ERR_AUTH_FAILED);
4040 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
4041 return (KMF_ERR_PKCS12_FORMAT);
4043 for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
4044 bags = NULL;
4045 /* LINTED E_BAD_PTR_CAST_ALIGN */
4046 p7 = sk_PKCS7_value(asafes, i);
4047 bagnid = OBJ_obj2nid(p7->type);
4049 if (bagnid == NID_pkcs7_data) {
4050 bags = PKCS12_unpack_p7data(p7);
4051 } else if (bagnid == NID_pkcs7_encrypted) {
4052 bags = PKCS12_unpack_p7encdata(p7, pin,
4053 (pin ? strlen(pin) : 0));
4054 } else {
4055 continue;
4057 if (bags == NULL) {
4058 ret = KMF_ERR_PKCS12_FORMAT;
4059 goto out;
4062 if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
4063 ret = KMF_ERR_PKCS12_FORMAT;
4065 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
4067 out:
4068 if (asafes != NULL)
4069 sk_PKCS7_pop_free(asafes, PKCS7_free);
4071 return (ret);
4075 * Helper function to decrypt and parse PKCS#12 import file.
4077 static KMF_RETURN
4078 extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
4079 STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
4080 STACK_OF(X509) **ca)
4081 /* ARGSUSED2 */
4083 PKCS12 *pk12, *pk12_tmp;
4084 STACK_OF(EVP_PKEY) *pkeylist = NULL;
4085 STACK_OF(X509) *xcertlist = NULL;
4086 STACK_OF(X509) *cacertlist = NULL;
4088 if ((pk12 = PKCS12_new()) == NULL) {
4089 return (KMF_ERR_MEMORY);
4092 if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
4093 /* This is ok; it seems to mean there is no more to read. */
4094 if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
4095 ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
4096 goto end_extract_pkcs12;
4098 PKCS12_free(pk12);
4099 return (KMF_ERR_PKCS12_FORMAT);
4101 pk12 = pk12_tmp;
4103 xcertlist = sk_X509_new_null();
4104 if (xcertlist == NULL) {
4105 PKCS12_free(pk12);
4106 return (KMF_ERR_MEMORY);
4108 pkeylist = sk_EVP_PKEY_new_null();
4109 if (pkeylist == NULL) {
4110 sk_X509_pop_free(xcertlist, X509_free);
4111 PKCS12_free(pk12);
4112 return (KMF_ERR_MEMORY);
4115 if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4116 cacertlist) != KMF_OK) {
4117 sk_X509_pop_free(xcertlist, X509_free);
4118 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4119 PKCS12_free(pk12);
4120 return (KMF_ERR_PKCS12_FORMAT);
4123 if (priv_key && pkeylist)
4124 *priv_key = pkeylist;
4125 else if (pkeylist)
4126 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4127 if (certs && xcertlist)
4128 *certs = xcertlist;
4129 else if (xcertlist)
4130 sk_X509_pop_free(xcertlist, X509_free);
4131 if (ca && cacertlist)
4132 *ca = cacertlist;
4133 else if (cacertlist)
4134 sk_X509_pop_free(cacertlist, X509_free);
4136 end_extract_pkcs12:
4138 PKCS12_free(pk12);
4139 return (KMF_OK);
4142 static KMF_RETURN
4143 sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4145 KMF_RETURN rv = KMF_OK;
4146 uint32_t sz;
4148 sz = BN_num_bytes(from);
4149 to->val = (uchar_t *)malloc(sz);
4150 if (to->val == NULL)
4151 return (KMF_ERR_MEMORY);
4153 if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4154 free(to->val);
4155 to->val = NULL;
4156 to->len = 0;
4157 rv = KMF_ERR_MEMORY;
4160 return (rv);
4163 static KMF_RETURN
4164 exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4166 KMF_RETURN rv;
4167 KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4169 const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4171 RSA_get0_key(rsa, &n, &e, &d);
4172 RSA_get0_factors(rsa, &p, &q);
4173 RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4175 (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4176 if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
4177 goto cleanup;
4179 if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
4180 goto cleanup;
4182 if (d != NULL)
4183 if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
4184 goto cleanup;
4186 if (p != NULL)
4187 if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
4188 goto cleanup;
4190 if (q != NULL)
4191 if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
4192 goto cleanup;
4194 if (dmp1 != NULL)
4195 if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
4196 goto cleanup;
4198 if (dmpq != NULL)
4199 if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
4200 goto cleanup;
4202 if (iqmp != NULL)
4203 if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
4204 goto cleanup;
4205 cleanup:
4206 if (rv != KMF_OK)
4207 kmf_free_raw_key(key);
4208 else
4209 key->keytype = KMF_RSA;
4212 * Free the reference to this key, SSL will not actually free
4213 * the memory until the refcount == 0, so this is safe.
4215 RSA_free(rsa);
4217 return (rv);
4220 static KMF_RETURN
4221 exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4223 KMF_RETURN rv;
4224 KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4225 const BIGNUM *p, *q, *g, *priv_key;
4227 DSA_get0_pqg(dsa, &p, &q, &g);
4228 DSA_get0_key(dsa, NULL, &priv_key);
4230 (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4231 if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
4232 goto cleanup;
4234 if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
4235 goto cleanup;
4237 if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
4238 goto cleanup;
4240 if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
4241 goto cleanup;
4243 cleanup:
4244 if (rv != KMF_OK)
4245 kmf_free_raw_key(key);
4246 else
4247 key->keytype = KMF_DSA;
4250 * Free the reference to this key, SSL will not actually free
4251 * the memory until the refcount == 0, so this is safe.
4253 DSA_free(dsa);
4255 return (rv);
4258 static KMF_RETURN
4259 add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4260 KMF_X509_DER_CERT **certlist, int *ncerts)
4262 KMF_RETURN rv = KMF_OK;
4263 KMF_X509_DER_CERT *list = (*certlist);
4264 KMF_X509_DER_CERT cert;
4265 int n = (*ncerts);
4267 if (list == NULL) {
4268 list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4269 } else {
4270 list = (KMF_X509_DER_CERT *)realloc(list,
4271 sizeof (KMF_X509_DER_CERT) * (n + 1));
4274 if (list == NULL)
4275 return (KMF_ERR_MEMORY);
4277 (void) memset(&cert, 0, sizeof (cert));
4278 rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4279 if (rv == KMF_OK) {
4280 int len = 0;
4281 /* Get the alias name for the cert if there is one */
4282 char *a = (char *)X509_alias_get0(sslcert, &len);
4283 if (a != NULL)
4284 cert.kmf_private.label = strdup(a);
4285 cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4287 list[n] = cert;
4288 (*ncerts) = n + 1;
4290 *certlist = list;
4291 } else {
4292 free(list);
4295 return (rv);
4298 static KMF_RETURN
4299 add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4300 KMF_RAW_KEY_DATA *newkey, int *nkeys)
4302 KMF_RAW_KEY_DATA *list = (*keylist);
4303 int n = (*nkeys);
4305 if (list == NULL) {
4306 list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4307 } else {
4308 list = (KMF_RAW_KEY_DATA *)realloc(list,
4309 sizeof (KMF_RAW_KEY_DATA) * (n + 1));
4312 if (list == NULL)
4313 return (KMF_ERR_MEMORY);
4315 list[n] = *newkey;
4316 (*nkeys) = n + 1;
4318 *keylist = list;
4320 return (KMF_OK);
4323 static KMF_RETURN
4324 convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4326 KMF_RETURN rv = KMF_OK;
4327 X509_ATTRIBUTE *attr;
4328 RSA *rsa;
4329 DSA *dsa;
4330 int loc;
4332 if (pkey == NULL || key == NULL)
4333 return (KMF_ERR_BAD_PARAMETER);
4334 /* Convert SSL key to raw key */
4335 if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4336 rv = exportRawRSAKey(rsa, key);
4337 if (rv != KMF_OK)
4338 return (rv);
4339 } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4340 rv = exportRawDSAKey(dsa, key);
4341 if (rv != KMF_OK)
4342 return (rv);
4343 } else
4344 return (KMF_ERR_BAD_PARAMETER);
4347 * If friendlyName, add it to record.
4350 if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4351 NID_friendlyName, -1)) != -1 &&
4352 (attr = EVP_PKEY_get_attr(pkey, loc))) {
4353 ASN1_TYPE *ty = NULL;
4354 int numattr = X509_ATTRIBUTE_count(attr);
4355 if (numattr > 0) {
4356 ty = X509_ATTRIBUTE_get0_type(attr, 0);
4358 if (ty != NULL) {
4359 key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4360 ty->value.bmpstring->length);
4362 } else {
4363 key->label = NULL;
4367 * If KeyID, add it to record as a KMF_DATA object.
4369 if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4370 NID_localKeyID, -1)) != -1 &&
4371 (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
4372 ASN1_TYPE *ty = NULL;
4373 int numattr = X509_ATTRIBUTE_count(attr);
4374 if (numattr > 0)
4375 ty = X509_ATTRIBUTE_get0_type(attr, 0);
4376 key->id.Data = (uchar_t *)malloc(
4377 ty->value.octet_string->length);
4378 if (key->id.Data == NULL)
4379 return (KMF_ERR_MEMORY);
4380 (void) memcpy(key->id.Data, ty->value.octet_string->data,
4381 ty->value.octet_string->length);
4382 key->id.Length = ty->value.octet_string->length;
4383 } else {
4384 (void) memset(&key->id, 0, sizeof (KMF_DATA));
4387 return (rv);
4390 static KMF_RETURN
4391 convertPK12Objects(
4392 KMF_HANDLE *kmfh,
4393 STACK_OF(EVP_PKEY) *sslkeys,
4394 STACK_OF(X509) *sslcert,
4395 STACK_OF(X509) *sslcacerts,
4396 KMF_RAW_KEY_DATA **keylist, int *nkeys,
4397 KMF_X509_DER_CERT **certlist, int *ncerts)
4399 KMF_RETURN rv = KMF_OK;
4400 KMF_RAW_KEY_DATA key;
4401 int i;
4403 for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4404 /* LINTED E_BAD_PTR_CAST_ALIGN */
4405 EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4406 rv = convertToRawKey(pkey, &key);
4407 if (rv == KMF_OK)
4408 rv = add_key_to_list(keylist, &key, nkeys);
4410 if (rv != KMF_OK)
4411 return (rv);
4414 /* Now add the certificate to the certlist */
4415 for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4416 /* LINTED E_BAD_PTR_CAST_ALIGN */
4417 X509 *cert = sk_X509_value(sslcert, i);
4418 rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4419 if (rv != KMF_OK)
4420 return (rv);
4423 /* Also add any included CA certs to the list */
4424 for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4425 X509 *c;
4427 * sk_X509_value() is macro that embeds a cast to (X509 *).
4428 * Here it translates into ((X509 *)sk_value((ca), (i))).
4429 * Lint is complaining about the embedded casting, and
4430 * to fix it, you need to fix openssl header files.
4432 /* LINTED E_BAD_PTR_CAST_ALIGN */
4433 c = sk_X509_value(sslcacerts, i);
4435 /* Now add the ca cert to the certlist */
4436 rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4437 if (rv != KMF_OK)
4438 return (rv);
4440 return (rv);
4443 KMF_RETURN
4444 openssl_import_objects(KMF_HANDLE *kmfh,
4445 char *filename, KMF_CREDENTIAL *cred,
4446 KMF_X509_DER_CERT **certlist, int *ncerts,
4447 KMF_RAW_KEY_DATA **keylist, int *nkeys)
4449 KMF_RETURN rv = KMF_OK;
4450 KMF_ENCODE_FORMAT format;
4451 BIO *bio = NULL;
4452 STACK_OF(EVP_PKEY) *privkeys = NULL;
4453 STACK_OF(X509) *certs = NULL;
4454 STACK_OF(X509) *cacerts = NULL;
4457 * auto-detect the file format, regardless of what
4458 * the 'format' parameters in the params say.
4460 rv = kmf_get_file_format(filename, &format);
4461 if (rv != KMF_OK) {
4462 return (rv);
4465 /* This function only works for PEM or PKCS#12 files */
4466 if (format != KMF_FORMAT_PEM &&
4467 format != KMF_FORMAT_PEM_KEYPAIR &&
4468 format != KMF_FORMAT_PKCS12)
4469 return (KMF_ERR_ENCODING);
4471 *certlist = NULL;
4472 *keylist = NULL;
4473 *ncerts = 0;
4474 *nkeys = 0;
4476 if (format == KMF_FORMAT_PKCS12) {
4477 bio = BIO_new_file(filename, "rb");
4478 if (bio == NULL) {
4479 SET_ERROR(kmfh, ERR_get_error());
4480 rv = KMF_ERR_OPEN_FILE;
4481 goto end;
4484 rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4485 (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4487 if (rv == KMF_OK)
4488 /* Convert keys and certs to exportable format */
4489 rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4490 keylist, nkeys, certlist, ncerts);
4491 } else {
4492 EVP_PKEY *pkey;
4493 KMF_DATA *certdata = NULL;
4494 KMF_X509_DER_CERT *kmfcerts = NULL;
4495 int i;
4496 rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4497 (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4498 &pkey, &certdata, ncerts);
4500 /* Reached end of import file? */
4501 if (rv == KMF_OK && pkey != NULL) {
4502 privkeys = sk_EVP_PKEY_new_null();
4503 if (privkeys == NULL) {
4504 rv = KMF_ERR_MEMORY;
4505 goto end;
4507 (void) sk_EVP_PKEY_push(privkeys, pkey);
4508 /* convert the certificate list here */
4509 if (*ncerts > 0 && certlist != NULL) {
4510 kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4511 sizeof (KMF_X509_DER_CERT));
4512 if (kmfcerts == NULL) {
4513 rv = KMF_ERR_MEMORY;
4514 goto end;
4516 for (i = 0; i < *ncerts; i++) {
4517 kmfcerts[i].certificate = certdata[i];
4518 kmfcerts[i].kmf_private.keystore_type =
4519 KMF_KEYSTORE_OPENSSL;
4521 *certlist = kmfcerts;
4524 * Convert keys to exportable format, the certs
4525 * are already OK.
4527 rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4528 keylist, nkeys, NULL, NULL);
4531 end:
4532 if (bio != NULL)
4533 (void) BIO_free(bio);
4535 if (privkeys)
4536 sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4537 if (certs)
4538 sk_X509_pop_free(certs, X509_free);
4539 if (cacerts)
4540 sk_X509_pop_free(cacerts, X509_free);
4542 return (rv);
4545 static KMF_RETURN
4546 create_deskey(DES_cblock **deskey)
4548 DES_cblock *key;
4550 key = (DES_cblock *) malloc(sizeof (DES_cblock));
4551 if (key == NULL) {
4552 return (KMF_ERR_MEMORY);
4555 if (DES_random_key(key) == 0) {
4556 free(key);
4557 return (KMF_ERR_KEYGEN_FAILED);
4560 *deskey = key;
4561 return (KMF_OK);
4564 #define KEYGEN_RETRY 3
4565 #define DES3_KEY_SIZE 24
4567 static KMF_RETURN
4568 create_des3key(unsigned char **des3key)
4570 KMF_RETURN ret = KMF_OK;
4571 DES_cblock *deskey1 = NULL;
4572 DES_cblock *deskey2 = NULL;
4573 DES_cblock *deskey3 = NULL;
4574 unsigned char *newkey = NULL;
4575 int retry;
4577 if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4578 return (KMF_ERR_MEMORY);
4581 /* create the 1st DES key */
4582 if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4583 goto out;
4587 * Create the 2nd DES key and make sure its value is different
4588 * from the 1st DES key.
4590 retry = 0;
4591 do {
4592 if (deskey2 != NULL) {
4593 free(deskey2);
4594 deskey2 = NULL;
4597 if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4598 goto out;
4601 if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4602 == 0) {
4603 ret = KMF_ERR_KEYGEN_FAILED;
4604 retry++;
4606 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4608 if (ret != KMF_OK) {
4609 goto out;
4613 * Create the 3rd DES key and make sure its value is different
4614 * from the 2nd DES key.
4616 retry = 0;
4617 do {
4618 if (deskey3 != NULL) {
4619 free(deskey3);
4620 deskey3 = NULL;
4623 if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4624 goto out;
4627 if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4628 == 0) {
4629 ret = KMF_ERR_KEYGEN_FAILED;
4630 retry++;
4632 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4634 if (ret != KMF_OK) {
4635 goto out;
4638 /* Concatenate 3 DES keys into a DES3 key */
4639 (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4640 (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4641 (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4642 *des3key = newkey;
4644 out:
4645 if (deskey1 != NULL)
4646 free(deskey1);
4648 if (deskey2 != NULL)
4649 free(deskey2);
4651 if (deskey3 != NULL)
4652 free(deskey3);
4654 if (ret != KMF_OK && newkey != NULL)
4655 free(newkey);
4657 return (ret);
4660 KMF_RETURN
4661 OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4662 int numattr, KMF_ATTRIBUTE *attrlist)
4664 KMF_RETURN ret = KMF_OK;
4665 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4666 char *fullpath = NULL;
4667 KMF_RAW_SYM_KEY *rkey = NULL;
4668 DES_cblock *deskey = NULL;
4669 unsigned char *des3key = NULL;
4670 unsigned char *random = NULL;
4671 int fd = -1;
4672 KMF_KEY_HANDLE *symkey;
4673 KMF_KEY_ALG keytype;
4674 uint32_t keylen;
4675 uint32_t keylen_size = sizeof (keylen);
4676 char *dirpath;
4677 char *keyfile;
4679 if (kmfh == NULL)
4680 return (KMF_ERR_UNINITIALIZED);
4682 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4683 if (symkey == NULL)
4684 return (KMF_ERR_BAD_PARAMETER);
4686 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4688 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4689 if (keyfile == NULL)
4690 return (KMF_ERR_BAD_PARAMETER);
4692 ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4693 (void *)&keytype, NULL);
4694 if (ret != KMF_OK)
4695 return (KMF_ERR_BAD_PARAMETER);
4697 ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4698 &keylen, &keylen_size);
4699 if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4700 (keytype == KMF_DES || keytype == KMF_DES3))
4701 /* keylength is not required for DES and 3DES */
4702 ret = KMF_OK;
4703 if (ret != KMF_OK)
4704 return (KMF_ERR_BAD_PARAMETER);
4706 fullpath = get_fullpath(dirpath, keyfile);
4707 if (fullpath == NULL)
4708 return (KMF_ERR_BAD_PARAMETER);
4710 /* If the requested file exists, return an error */
4711 if (test_for_file(fullpath, 0400) == 1) {
4712 free(fullpath);
4713 return (KMF_ERR_DUPLICATE_KEYFILE);
4716 fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4717 if (fd == -1) {
4718 ret = KMF_ERR_OPEN_FILE;
4719 goto out;
4722 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4723 if (rkey == NULL) {
4724 ret = KMF_ERR_MEMORY;
4725 goto out;
4727 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4729 if (keytype == KMF_DES) {
4730 if ((ret = create_deskey(&deskey)) != KMF_OK) {
4731 goto out;
4733 rkey->keydata.val = (uchar_t *)deskey;
4734 rkey->keydata.len = 8;
4736 symkey->keyalg = KMF_DES;
4738 } else if (keytype == KMF_DES3) {
4739 if ((ret = create_des3key(&des3key)) != KMF_OK) {
4740 goto out;
4742 rkey->keydata.val = (uchar_t *)des3key;
4743 rkey->keydata.len = DES3_KEY_SIZE;
4744 symkey->keyalg = KMF_DES3;
4746 } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4747 keytype == KMF_GENERIC_SECRET) {
4748 int bytes;
4750 if (keylen % 8 != 0) {
4751 ret = KMF_ERR_BAD_KEY_SIZE;
4752 goto out;
4755 if (keytype == KMF_AES) {
4756 if (keylen != 128 &&
4757 keylen != 192 &&
4758 keylen != 256) {
4759 ret = KMF_ERR_BAD_KEY_SIZE;
4760 goto out;
4764 bytes = keylen/8;
4765 random = malloc(bytes);
4766 if (random == NULL) {
4767 ret = KMF_ERR_MEMORY;
4768 goto out;
4770 if (RAND_bytes(random, bytes) != 1) {
4771 ret = KMF_ERR_KEYGEN_FAILED;
4772 goto out;
4775 rkey->keydata.val = (uchar_t *)random;
4776 rkey->keydata.len = bytes;
4777 symkey->keyalg = keytype;
4779 } else {
4780 ret = KMF_ERR_BAD_KEY_TYPE;
4781 goto out;
4784 (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4786 symkey->kstype = KMF_KEYSTORE_OPENSSL;
4787 symkey->keyclass = KMF_SYMMETRIC;
4788 symkey->keylabel = (char *)fullpath;
4789 symkey->israw = TRUE;
4790 symkey->keyp = rkey;
4792 out:
4793 if (fd != -1)
4794 (void) close(fd);
4796 if (ret != KMF_OK && fullpath != NULL) {
4797 free(fullpath);
4799 if (ret != KMF_OK) {
4800 kmf_free_raw_sym_key(rkey);
4801 symkey->keyp = NULL;
4802 symkey->keyalg = KMF_KEYALG_NONE;
4805 return (ret);
4809 * Check a file to see if it is a CRL file with PEM or DER format.
4810 * If success, return its format in the "pformat" argument.
4812 KMF_RETURN
4813 OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4815 KMF_RETURN ret = KMF_OK;
4816 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4817 BIO *bio = NULL;
4818 X509_CRL *xcrl = NULL;
4820 if (filename == NULL) {
4821 return (KMF_ERR_BAD_PARAMETER);
4824 bio = BIO_new_file(filename, "rb");
4825 if (bio == NULL) {
4826 SET_ERROR(kmfh, ERR_get_error());
4827 ret = KMF_ERR_OPEN_FILE;
4828 goto out;
4831 if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4832 *pformat = KMF_FORMAT_PEM;
4833 goto out;
4835 (void) BIO_free(bio);
4838 * Now try to read it as raw DER data.
4840 bio = BIO_new_file(filename, "rb");
4841 if (bio == NULL) {
4842 SET_ERROR(kmfh, ERR_get_error());
4843 ret = KMF_ERR_OPEN_FILE;
4844 goto out;
4847 if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4848 *pformat = KMF_FORMAT_ASN1;
4849 } else {
4850 ret = KMF_ERR_BAD_CRLFILE;
4853 out:
4854 if (bio != NULL)
4855 (void) BIO_free(bio);
4857 if (xcrl != NULL)
4858 X509_CRL_free(xcrl);
4860 return (ret);
4863 KMF_RETURN
4864 OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4865 KMF_RAW_SYM_KEY *rkey)
4867 KMF_RETURN rv = KMF_OK;
4868 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4869 KMF_DATA keyvalue;
4871 if (kmfh == NULL)
4872 return (KMF_ERR_UNINITIALIZED);
4874 if (symkey == NULL || rkey == NULL)
4875 return (KMF_ERR_BAD_PARAMETER);
4876 else if (symkey->keyclass != KMF_SYMMETRIC)
4877 return (KMF_ERR_BAD_KEY_CLASS);
4879 if (symkey->israw) {
4880 KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4882 if (rawkey == NULL ||
4883 rawkey->keydata.val == NULL ||
4884 rawkey->keydata.len == 0)
4885 return (KMF_ERR_BAD_KEYHANDLE);
4887 rkey->keydata.len = rawkey->keydata.len;
4888 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4889 return (KMF_ERR_MEMORY);
4890 (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4891 rkey->keydata.len);
4892 } else {
4893 rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4894 if (rv != KMF_OK)
4895 return (rv);
4896 rkey->keydata.len = keyvalue.Length;
4897 rkey->keydata.val = keyvalue.Data;
4900 return (rv);
4904 * substitute for the unsafe access(2) function.
4905 * If the file in question already exists, return 1.
4906 * else 0. If an error occurs during testing (other
4907 * than EEXIST), return -1.
4909 static int
4910 test_for_file(char *filename, mode_t mode)
4912 int fd;
4915 * Try to create the file with the EXCL flag.
4916 * The call should fail if the file exists.
4918 fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4919 if (fd == -1 && errno == EEXIST)
4920 return (1);
4921 else if (fd == -1) /* some other error */
4922 return (-1);
4924 /* The file did NOT exist. Delete the testcase. */
4925 (void) close(fd);
4926 (void) unlink(filename);
4927 return (0);
4930 KMF_RETURN
4931 OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4932 KMF_ATTRIBUTE *attrlist)
4934 KMF_RETURN rv = KMF_OK;
4935 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4936 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4937 KMF_RAW_KEY_DATA *rawkey;
4938 EVP_PKEY *pkey = NULL;
4939 KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4940 KMF_CREDENTIAL cred = { NULL, 0 };
4941 BIO *out = NULL;
4942 int keys = 0;
4943 char *fullpath = NULL;
4944 char *keyfile = NULL;
4945 char *dirpath = NULL;
4947 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4948 if (pubkey != NULL)
4949 keys++;
4951 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4952 if (prikey != NULL)
4953 keys++;
4955 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4956 if (rawkey != NULL)
4957 keys++;
4960 * Exactly 1 type of key must be passed to this function.
4962 if (keys != 1)
4963 return (KMF_ERR_BAD_PARAMETER);
4965 keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4966 numattr);
4967 if (keyfile == NULL)
4968 return (KMF_ERR_BAD_PARAMETER);
4970 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4972 fullpath = get_fullpath(dirpath, keyfile);
4974 /* Once we have the full path, we don't need the pieces */
4975 if (fullpath == NULL)
4976 return (KMF_ERR_BAD_PARAMETER);
4978 /* If the requested file exists, return an error */
4979 if (test_for_file(fullpath, 0400) == 1) {
4980 free(fullpath);
4981 return (KMF_ERR_DUPLICATE_KEYFILE);
4984 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4985 &format, NULL);
4986 if (rv != KMF_OK)
4987 /* format is optional. */
4988 rv = KMF_OK;
4990 /* CRED is not required for OpenSSL files */
4991 (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4992 &cred, NULL);
4994 /* Store the private key to the keyfile */
4995 out = BIO_new_file(fullpath, "wb");
4996 if (out == NULL) {
4997 SET_ERROR(kmfh, ERR_get_error());
4998 rv = KMF_ERR_OPEN_FILE;
4999 goto end;
5002 if (prikey != NULL && prikey->keyp != NULL) {
5003 if (prikey->keyalg == KMF_RSA ||
5004 prikey->keyalg == KMF_DSA) {
5005 pkey = (EVP_PKEY *)prikey->keyp;
5007 rv = ssl_write_key(kmfh, format,
5008 out, &cred, pkey, TRUE);
5010 if (rv == KMF_OK && prikey->keylabel == NULL) {
5011 prikey->keylabel = strdup(fullpath);
5012 if (prikey->keylabel == NULL)
5013 rv = KMF_ERR_MEMORY;
5016 } else if (pubkey != NULL && pubkey->keyp != NULL) {
5017 if (pubkey->keyalg == KMF_RSA ||
5018 pubkey->keyalg == KMF_DSA) {
5019 pkey = (EVP_PKEY *)pubkey->keyp;
5021 rv = ssl_write_key(kmfh, format,
5022 out, &cred, pkey, FALSE);
5024 if (rv == KMF_OK && pubkey->keylabel == NULL) {
5025 pubkey->keylabel = strdup(fullpath);
5026 if (pubkey->keylabel == NULL)
5027 rv = KMF_ERR_MEMORY;
5030 } else if (rawkey != NULL) {
5031 if (rawkey->keytype == KMF_RSA) {
5032 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
5033 } else if (rawkey->keytype == KMF_DSA) {
5034 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
5035 } else {
5036 rv = KMF_ERR_BAD_PARAMETER;
5038 if (pkey != NULL) {
5039 KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
5041 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
5042 (void *)&kclass, NULL);
5043 if (rv != KMF_OK)
5044 rv = KMF_OK;
5045 rv = ssl_write_key(kmfh, format, out,
5046 &cred, pkey, (kclass == KMF_ASYM_PRI));
5047 EVP_PKEY_free(pkey);
5051 end:
5053 if (out)
5054 (void) BIO_free(out);
5057 if (rv == KMF_OK)
5058 (void) chmod(fullpath, 0400);
5060 free(fullpath);
5061 return (rv);
5064 KMF_RETURN
5065 OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5067 KMF_RETURN ret = KMF_OK;
5068 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5069 X509_CRL *xcrl = NULL;
5070 X509 *xcert = NULL;
5071 EVP_PKEY *pkey;
5072 KMF_ENCODE_FORMAT format;
5073 BIO *in = NULL, *out = NULL;
5074 int openssl_ret = 0;
5075 KMF_ENCODE_FORMAT outformat;
5076 boolean_t crlcheck = FALSE;
5077 char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
5079 if (numattr == 0 || attrlist == NULL) {
5080 return (KMF_ERR_BAD_PARAMETER);
5083 /* CRL check is optional */
5084 (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
5085 &crlcheck, NULL);
5087 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5088 if (crlcheck == B_TRUE && certfile == NULL) {
5089 return (KMF_ERR_BAD_CERTFILE);
5092 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5093 incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5094 outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5096 crlfile = get_fullpath(dirpath, incrl);
5098 if (crlfile == NULL)
5099 return (KMF_ERR_BAD_CRLFILE);
5101 outcrlfile = get_fullpath(dirpath, outcrl);
5102 if (outcrlfile == NULL)
5103 return (KMF_ERR_BAD_CRLFILE);
5105 if (isdir(outcrlfile)) {
5106 free(outcrlfile);
5107 return (KMF_ERR_BAD_CRLFILE);
5110 ret = kmf_is_crl_file(handle, crlfile, &format);
5111 if (ret != KMF_OK) {
5112 free(outcrlfile);
5113 return (ret);
5116 in = BIO_new_file(crlfile, "rb");
5117 if (in == NULL) {
5118 SET_ERROR(kmfh, ERR_get_error());
5119 ret = KMF_ERR_OPEN_FILE;
5120 goto end;
5123 if (format == KMF_FORMAT_ASN1) {
5124 xcrl = d2i_X509_CRL_bio(in, NULL);
5125 } else if (format == KMF_FORMAT_PEM) {
5126 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5129 if (xcrl == NULL) {
5130 SET_ERROR(kmfh, ERR_get_error());
5131 ret = KMF_ERR_BAD_CRLFILE;
5132 goto end;
5135 /* If bypasscheck is specified, no need to verify. */
5136 if (crlcheck == B_FALSE)
5137 goto output;
5139 ret = kmf_is_cert_file(handle, certfile, &format);
5140 if (ret != KMF_OK)
5141 goto end;
5143 /* Read in the CA cert file and convert to X509 */
5144 if (BIO_read_filename(in, certfile) <= 0) {
5145 SET_ERROR(kmfh, ERR_get_error());
5146 ret = KMF_ERR_OPEN_FILE;
5147 goto end;
5150 if (format == KMF_FORMAT_ASN1) {
5151 xcert = d2i_X509_bio(in, NULL);
5152 } else if (format == KMF_FORMAT_PEM) {
5153 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5154 } else {
5155 ret = KMF_ERR_BAD_CERT_FORMAT;
5156 goto end;
5159 if (xcert == NULL) {
5160 SET_ERROR(kmfh, ERR_get_error());
5161 ret = KMF_ERR_BAD_CERT_FORMAT;
5162 goto end;
5164 /* Now get the public key from the CA cert */
5165 pkey = X509_get_pubkey(xcert);
5166 if (pkey == NULL) {
5167 SET_ERROR(kmfh, ERR_get_error());
5168 ret = KMF_ERR_BAD_CERTFILE;
5169 goto end;
5172 /* Verify the CRL with the CA's public key */
5173 openssl_ret = X509_CRL_verify(xcrl, pkey);
5174 EVP_PKEY_free(pkey);
5175 if (openssl_ret > 0) {
5176 ret = KMF_OK; /* verify succeed */
5177 } else {
5178 SET_ERROR(kmfh, openssl_ret);
5179 ret = KMF_ERR_BAD_CRLFILE;
5182 output:
5183 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5184 &outformat, NULL);
5185 if (ret != KMF_OK) {
5186 ret = KMF_OK;
5187 outformat = KMF_FORMAT_PEM;
5190 out = BIO_new_file(outcrlfile, "wb");
5191 if (out == NULL) {
5192 SET_ERROR(kmfh, ERR_get_error());
5193 ret = KMF_ERR_OPEN_FILE;
5194 goto end;
5197 if (outformat == KMF_FORMAT_ASN1) {
5198 openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5199 } else if (outformat == KMF_FORMAT_PEM) {
5200 openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5201 } else {
5202 ret = KMF_ERR_BAD_PARAMETER;
5203 goto end;
5206 if (openssl_ret <= 0) {
5207 SET_ERROR(kmfh, ERR_get_error());
5208 ret = KMF_ERR_WRITE_FILE;
5209 } else {
5210 ret = KMF_OK;
5213 end:
5214 if (xcrl != NULL)
5215 X509_CRL_free(xcrl);
5217 if (xcert != NULL)
5218 X509_free(xcert);
5220 if (in != NULL)
5221 (void) BIO_free(in);
5223 if (out != NULL)
5224 (void) BIO_free(out);
5226 if (outcrlfile != NULL)
5227 free(outcrlfile);
5229 return (ret);
5232 KMF_RETURN
5233 OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5235 KMF_RETURN ret = KMF_OK;
5236 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5237 X509_CRL *x = NULL;
5238 KMF_ENCODE_FORMAT format;
5239 char *crlfile = NULL;
5240 BIO *in = NULL;
5241 BIO *mem = NULL;
5242 long len;
5243 char *memptr;
5244 char *data = NULL;
5245 char **crldata;
5246 char *crlfilename, *dirpath;
5248 if (numattr == 0 || attrlist == NULL) {
5249 return (KMF_ERR_BAD_PARAMETER);
5251 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5252 attrlist, numattr);
5253 if (crlfilename == NULL)
5254 return (KMF_ERR_BAD_CRLFILE);
5256 crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5257 attrlist, numattr);
5259 if (crldata == NULL)
5260 return (KMF_ERR_BAD_PARAMETER);
5262 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5264 crlfile = get_fullpath(dirpath, crlfilename);
5266 if (crlfile == NULL)
5267 return (KMF_ERR_BAD_CRLFILE);
5269 if (isdir(crlfile)) {
5270 free(crlfile);
5271 return (KMF_ERR_BAD_CRLFILE);
5274 ret = kmf_is_crl_file(handle, crlfile, &format);
5275 if (ret != KMF_OK) {
5276 free(crlfile);
5277 return (ret);
5280 if (bio_err == NULL)
5281 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5283 in = BIO_new_file(crlfile, "rb");
5284 if (in == NULL) {
5285 SET_ERROR(kmfh, ERR_get_error());
5286 ret = KMF_ERR_OPEN_FILE;
5287 goto end;
5290 if (format == KMF_FORMAT_ASN1) {
5291 x = d2i_X509_CRL_bio(in, NULL);
5292 } else if (format == KMF_FORMAT_PEM) {
5293 x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5296 if (x == NULL) { /* should not happen */
5297 SET_ERROR(kmfh, ERR_get_error());
5298 ret = KMF_ERR_OPEN_FILE;
5299 goto end;
5302 mem = BIO_new(BIO_s_mem());
5303 if (mem == NULL) {
5304 SET_ERROR(kmfh, ERR_get_error());
5305 ret = KMF_ERR_MEMORY;
5306 goto end;
5309 (void) X509_CRL_print(mem, x);
5310 len = BIO_get_mem_data(mem, &memptr);
5311 if (len <= 0) {
5312 SET_ERROR(kmfh, ERR_get_error());
5313 ret = KMF_ERR_MEMORY;
5314 goto end;
5317 data = malloc(len + 1);
5318 if (data == NULL) {
5319 ret = KMF_ERR_MEMORY;
5320 goto end;
5323 (void) memcpy(data, memptr, len);
5324 data[len] = '\0';
5325 *crldata = data;
5327 end:
5328 if (x != NULL)
5329 X509_CRL_free(x);
5331 if (crlfile != NULL)
5332 free(crlfile);
5334 if (in != NULL)
5335 (void) BIO_free(in);
5337 if (mem != NULL)
5338 (void) BIO_free(mem);
5340 return (ret);
5343 KMF_RETURN
5344 OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5346 KMF_RETURN ret = KMF_OK;
5347 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5348 KMF_ENCODE_FORMAT format;
5349 char *crlfile = NULL;
5350 BIO *in = NULL;
5351 char *crlfilename, *dirpath;
5353 if (numattr == 0 || attrlist == NULL) {
5354 return (KMF_ERR_BAD_PARAMETER);
5357 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5358 attrlist, numattr);
5360 if (crlfilename == NULL)
5361 return (KMF_ERR_BAD_CRLFILE);
5363 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5365 crlfile = get_fullpath(dirpath, crlfilename);
5367 if (crlfile == NULL)
5368 return (KMF_ERR_BAD_CRLFILE);
5370 if (isdir(crlfile)) {
5371 ret = KMF_ERR_BAD_CRLFILE;
5372 goto end;
5375 ret = kmf_is_crl_file(handle, crlfile, &format);
5376 if (ret != KMF_OK)
5377 goto end;
5379 if (unlink(crlfile) != 0) {
5380 SET_SYS_ERROR(kmfh, errno);
5381 ret = KMF_ERR_INTERNAL;
5382 goto end;
5385 end:
5386 if (in != NULL)
5387 (void) BIO_free(in);
5388 if (crlfile != NULL)
5389 free(crlfile);
5391 return (ret);
5394 KMF_RETURN
5395 OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5397 KMF_RETURN ret = KMF_OK;
5398 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5399 KMF_ENCODE_FORMAT format;
5400 BIO *in = NULL;
5401 X509 *xcert = NULL;
5402 X509_CRL *xcrl = NULL;
5403 STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5404 X509_REVOKED *revoke;
5405 int i;
5406 char *crlfilename, *crlfile, *dirpath, *certfile;
5408 if (numattr == 0 || attrlist == NULL) {
5409 return (KMF_ERR_BAD_PARAMETER);
5412 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5413 attrlist, numattr);
5415 if (crlfilename == NULL)
5416 return (KMF_ERR_BAD_CRLFILE);
5418 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5419 if (certfile == NULL)
5420 return (KMF_ERR_BAD_CRLFILE);
5422 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5424 crlfile = get_fullpath(dirpath, crlfilename);
5426 if (crlfile == NULL)
5427 return (KMF_ERR_BAD_CRLFILE);
5429 if (isdir(crlfile)) {
5430 ret = KMF_ERR_BAD_CRLFILE;
5431 goto end;
5434 ret = kmf_is_crl_file(handle, crlfile, &format);
5435 if (ret != KMF_OK)
5436 goto end;
5438 /* Read the CRL file and load it into a X509_CRL structure */
5439 in = BIO_new_file(crlfilename, "rb");
5440 if (in == NULL) {
5441 SET_ERROR(kmfh, ERR_get_error());
5442 ret = KMF_ERR_OPEN_FILE;
5443 goto end;
5446 if (format == KMF_FORMAT_ASN1) {
5447 xcrl = d2i_X509_CRL_bio(in, NULL);
5448 } else if (format == KMF_FORMAT_PEM) {
5449 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5452 if (xcrl == NULL) {
5453 SET_ERROR(kmfh, ERR_get_error());
5454 ret = KMF_ERR_BAD_CRLFILE;
5455 goto end;
5457 (void) BIO_free(in);
5459 /* Read the Certificate file and load it into a X509 structure */
5460 ret = kmf_is_cert_file(handle, certfile, &format);
5461 if (ret != KMF_OK)
5462 goto end;
5464 in = BIO_new_file(certfile, "rb");
5465 if (in == NULL) {
5466 SET_ERROR(kmfh, ERR_get_error());
5467 ret = KMF_ERR_OPEN_FILE;
5468 goto end;
5471 if (format == KMF_FORMAT_ASN1) {
5472 xcert = d2i_X509_bio(in, NULL);
5473 } else if (format == KMF_FORMAT_PEM) {
5474 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5477 if (xcert == NULL) {
5478 SET_ERROR(kmfh, ERR_get_error());
5479 ret = KMF_ERR_BAD_CERTFILE;
5480 goto end;
5483 /* Check if the certificate and the CRL have same issuer */
5484 if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5485 X509_CRL_get_issuer(xcrl)) != 0) {
5486 ret = KMF_ERR_ISSUER;
5487 goto end;
5490 /* Check to see if the certificate serial number is revoked */
5491 revoke_stack = X509_CRL_get_REVOKED(xcrl);
5492 if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5493 /* No revoked certificates in the CRL file */
5494 SET_ERROR(kmfh, ERR_get_error());
5495 ret = KMF_ERR_EMPTY_CRL;
5496 goto end;
5499 for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5500 /* LINTED E_BAD_PTR_CAST_ALIGN */
5501 revoke = sk_X509_REVOKED_value(revoke_stack, i);
5502 if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5503 X509_REVOKED_get0_serialNumber(revoke)) == 0) {
5504 break;
5508 if (i < sk_X509_REVOKED_num(revoke_stack)) {
5509 ret = KMF_OK;
5510 } else {
5511 ret = KMF_ERR_NOT_REVOKED;
5514 end:
5515 if (in != NULL)
5516 (void) BIO_free(in);
5517 if (xcrl != NULL)
5518 X509_CRL_free(xcrl);
5519 if (xcert != NULL)
5520 X509_free(xcert);
5522 return (ret);
5525 KMF_RETURN
5526 OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5528 KMF_RETURN ret = KMF_OK;
5529 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5530 BIO *bcrl = NULL;
5531 X509_CRL *xcrl = NULL;
5532 X509 *xcert = NULL;
5533 EVP_PKEY *pkey;
5534 int sslret;
5535 KMF_ENCODE_FORMAT crl_format;
5536 unsigned char *p;
5537 long len;
5539 if (handle == NULL || crlname == NULL || tacert == NULL) {
5540 return (KMF_ERR_BAD_PARAMETER);
5543 ret = kmf_get_file_format(crlname, &crl_format);
5544 if (ret != KMF_OK)
5545 return (ret);
5547 bcrl = BIO_new_file(crlname, "rb");
5548 if (bcrl == NULL) {
5549 SET_ERROR(kmfh, ERR_get_error());
5550 ret = KMF_ERR_OPEN_FILE;
5551 goto cleanup;
5554 if (crl_format == KMF_FORMAT_ASN1) {
5555 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5556 } else if (crl_format == KMF_FORMAT_PEM) {
5557 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5558 } else {
5559 ret = KMF_ERR_BAD_PARAMETER;
5560 goto cleanup;
5563 if (xcrl == NULL) {
5564 SET_ERROR(kmfh, ERR_get_error());
5565 ret = KMF_ERR_BAD_CRLFILE;
5566 goto cleanup;
5569 p = tacert->Data;
5570 len = tacert->Length;
5571 xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5573 if (xcert == NULL) {
5574 SET_ERROR(kmfh, ERR_get_error());
5575 ret = KMF_ERR_BAD_CERTFILE;
5576 goto cleanup;
5579 /* Get issuer certificate public key */
5580 pkey = X509_get_pubkey(xcert);
5581 if (pkey == NULL) {
5582 SET_ERROR(kmfh, ERR_get_error());
5583 ret = KMF_ERR_BAD_CERT_FORMAT;
5584 goto cleanup;
5587 /* Verify CRL signature */
5588 sslret = X509_CRL_verify(xcrl, pkey);
5589 EVP_PKEY_free(pkey);
5590 if (sslret > 0) {
5591 ret = KMF_OK;
5592 } else {
5593 SET_ERROR(kmfh, sslret);
5594 ret = KMF_ERR_BAD_CRLFILE;
5597 cleanup:
5598 if (bcrl != NULL)
5599 (void) BIO_free(bcrl);
5601 if (xcrl != NULL)
5602 X509_CRL_free(xcrl);
5604 if (xcert != NULL)
5605 X509_free(xcert);
5607 return (ret);
5611 KMF_RETURN
5612 OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5614 KMF_RETURN ret = KMF_OK;
5615 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5616 KMF_ENCODE_FORMAT crl_format;
5617 BIO *bcrl = NULL;
5618 X509_CRL *xcrl = NULL;
5619 int i;
5621 if (handle == NULL || crlname == NULL) {
5622 return (KMF_ERR_BAD_PARAMETER);
5625 ret = kmf_is_crl_file(handle, crlname, &crl_format);
5626 if (ret != KMF_OK)
5627 return (ret);
5629 bcrl = BIO_new_file(crlname, "rb");
5630 if (bcrl == NULL) {
5631 SET_ERROR(kmfh, ERR_get_error());
5632 ret = KMF_ERR_OPEN_FILE;
5633 goto cleanup;
5636 if (crl_format == KMF_FORMAT_ASN1)
5637 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5638 else if (crl_format == KMF_FORMAT_PEM)
5639 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5641 if (xcrl == NULL) {
5642 SET_ERROR(kmfh, ERR_get_error());
5643 ret = KMF_ERR_BAD_CRLFILE;
5644 goto cleanup;
5646 i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
5647 if (i >= 0) {
5648 ret = KMF_ERR_VALIDITY_PERIOD;
5649 goto cleanup;
5651 if (X509_CRL_get0_nextUpdate(xcrl)) {
5652 i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
5654 if (i <= 0) {
5655 ret = KMF_ERR_VALIDITY_PERIOD;
5656 goto cleanup;
5660 ret = KMF_OK;
5662 cleanup:
5663 if (bcrl != NULL)
5664 (void) BIO_free(bcrl);
5666 if (xcrl != NULL)
5667 X509_CRL_free(xcrl);
5669 return (ret);