8982 Support building with OpenSSL 1.1
[unleashed.git] / usr / src / lib / libkmf / plugins / kmf_openssl / common / openssl_spi.c
blob3ca328ff0567c595f446d31b276d9e72c87bb080
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 */
11 * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
12 * project 2000.
15 * ====================================================================
16 * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
30 * 3. All advertising materials mentioning features or use of this
31 * software must display the following acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
35 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
36 * endorse or promote products derived from this software without
37 * prior written permission. For written permission, please contact
38 * licensing@OpenSSL.org.
40 * 5. Products derived from this software may not be called "OpenSSL"
41 * nor may "OpenSSL" appear in their names without prior written
42 * permission of the OpenSSL Project.
44 * 6. Redistributions of any form whatsoever must retain the following
45 * acknowledgment:
46 * "This product includes software developed by the OpenSSL Project
47 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
49 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
50 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
53 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
60 * OF THE POSSIBILITY OF SUCH DAMAGE.
61 * ====================================================================
63 * This product includes cryptographic software written by Eric Young
64 * (eay@cryptsoft.com). This product includes software written by Tim
65 * Hudson (tjh@cryptsoft.com).
69 #include <stdlib.h>
70 #include <kmfapiP.h>
71 #include <ber_der.h>
72 #include <fcntl.h>
73 #include <sys/stat.h>
74 #include <dirent.h>
75 #include <cryptoutil.h>
76 #include <synch.h>
77 #include <thread.h>
79 /* OPENSSL related headers */
80 #include <openssl/bio.h>
81 #include <openssl/bn.h>
82 #include <openssl/asn1.h>
83 #include <openssl/err.h>
84 #include <openssl/x509.h>
85 #include <openssl/rsa.h>
86 #include <openssl/dsa.h>
87 #include <openssl/x509v3.h>
88 #include <openssl/objects.h>
89 #include <openssl/pem.h>
90 #include <openssl/pkcs12.h>
91 #include <openssl/ocsp.h>
92 #include <openssl/des.h>
93 #include <openssl/rand.h>
94 #include "compat.h"
96 #define PRINT_ANY_EXTENSION (\
97 KMF_X509_EXT_KEY_USAGE |\
98 KMF_X509_EXT_CERT_POLICIES |\
99 KMF_X509_EXT_SUBJALTNAME |\
100 KMF_X509_EXT_BASIC_CONSTRAINTS |\
101 KMF_X509_EXT_NAME_CONSTRAINTS |\
102 KMF_X509_EXT_POLICY_CONSTRAINTS |\
103 KMF_X509_EXT_EXT_KEY_USAGE |\
104 KMF_X509_EXT_INHIBIT_ANY_POLICY |\
105 KMF_X509_EXT_AUTH_KEY_ID |\
106 KMF_X509_EXT_SUBJ_KEY_ID |\
107 KMF_X509_EXT_POLICY_MAPPING)
109 static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
110 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
111 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
112 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
113 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
114 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
115 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
116 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
117 0x91 };
119 static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
120 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
121 0x8e, 0xda, 0xce, 0x91, 0x5f };
123 static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
124 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
125 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
126 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
127 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
128 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
129 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
130 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
131 0x02 };
133 #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
134 h->lasterr.errcode = c;
136 #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
139 * Declare some new macros for managing stacks of EVP_PKEYS.
141 #if OPENSSL_VERSION_NUMBER < 0x10100000L
142 DECLARE_STACK_OF(EVP_PKEY)
144 #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
145 #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
146 #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
147 #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
148 #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
149 #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
150 (free_func))
152 #else
153 /* LINTED E_STATIC_UNUSED */
154 DEFINE_STACK_OF(EVP_PKEY)
155 #endif
157 mutex_t init_lock = DEFAULTMUTEX;
158 static int ssl_initialized = 0;
159 static BIO *bio_err = NULL;
161 static int
162 test_for_file(char *, mode_t);
163 static KMF_RETURN
164 openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
165 STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
167 static KMF_RETURN
168 local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
169 int, KMF_KEY_HANDLE *, char *);
171 static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
173 static KMF_RETURN
174 extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
175 CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
177 static KMF_RETURN
178 kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
179 char *, KMF_DATA *);
181 static KMF_RETURN
182 load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
183 char *, KMF_DATA **, uint32_t *);
185 static KMF_RETURN
186 sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
188 static EVP_PKEY *
189 ImportRawRSAKey(KMF_RAW_RSA_KEY *);
191 static KMF_RETURN
192 convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
194 KMF_RETURN
195 OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
197 void
198 OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
200 KMF_RETURN
201 OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
203 KMF_RETURN
204 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
206 KMF_RETURN
207 OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
209 KMF_RETURN
210 OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
212 KMF_RETURN
213 OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
215 KMF_RETURN
216 OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
217 KMF_DATA *, KMF_DATA *);
219 KMF_RETURN
220 OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
222 KMF_RETURN
223 OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
225 KMF_RETURN
226 OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
228 KMF_RETURN
229 OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
231 KMF_RETURN
232 OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
234 KMF_RETURN
235 OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
236 KMF_PRINTABLE_ITEM, char *);
238 KMF_RETURN
239 OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
241 KMF_RETURN
242 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
244 KMF_RETURN
245 OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
246 KMF_DATA *, KMF_DATA *);
248 KMF_RETURN
249 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
251 KMF_RETURN
252 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
254 KMF_RETURN
255 OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
257 KMF_RETURN
258 OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
260 KMF_RETURN
261 OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
263 KMF_RETURN
264 OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
266 KMF_RETURN
267 OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
269 KMF_RETURN
270 OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
272 static
273 KMF_PLUGIN_FUNCLIST openssl_plugin_table =
275 1, /* Version */
276 NULL, /* ConfigureKeystore */
277 OpenSSL_FindCert,
278 OpenSSL_FreeKMFCert,
279 OpenSSL_StoreCert,
280 NULL, /* ImportCert */
281 OpenSSL_ImportCRL,
282 OpenSSL_DeleteCert,
283 OpenSSL_DeleteCRL,
284 OpenSSL_CreateKeypair,
285 OpenSSL_FindKey,
286 OpenSSL_EncodePubKeyData,
287 OpenSSL_SignData,
288 OpenSSL_DeleteKey,
289 OpenSSL_ListCRL,
290 NULL, /* FindCRL */
291 OpenSSL_FindCertInCRL,
292 OpenSSL_GetErrorString,
293 OpenSSL_FindPrikeyByCert,
294 OpenSSL_DecryptData,
295 OpenSSL_ExportPK12,
296 OpenSSL_CreateSymKey,
297 OpenSSL_GetSymKeyValue,
298 NULL, /* SetTokenPin */
299 OpenSSL_StoreKey,
300 NULL /* Finalize */
303 #if OPENSSL_VERSION_NUMBER < 0x10100000L
304 static mutex_t *lock_cs;
305 static long *lock_count;
307 static void
308 /* ARGSUSED1 */
309 locking_cb(int mode, int type, char *file, int line)
311 if (mode & CRYPTO_LOCK) {
312 (void) mutex_lock(&(lock_cs[type]));
313 lock_count[type]++;
314 } else {
315 (void) mutex_unlock(&(lock_cs[type]));
319 static unsigned long
320 thread_id()
322 return ((unsigned long)thr_self());
324 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
326 KMF_PLUGIN_FUNCLIST *
327 KMF_Plugin_Initialize()
329 #if OPENSSL_VERSION_NUMBER < 0x10100000L
330 int i;
331 #endif
333 (void) mutex_lock(&init_lock);
334 if (!ssl_initialized) {
336 * Add support for extension OIDs that are not yet in the
337 * openssl default set.
339 (void) OBJ_create("2.5.29.30", "nameConstraints",
340 "X509v3 Name Constraints");
341 (void) OBJ_create("2.5.29.33", "policyMappings",
342 "X509v3 Policy Mappings");
343 (void) OBJ_create("2.5.29.36", "policyConstraints",
344 "X509v3 Policy Constraints");
345 (void) OBJ_create("2.5.29.46", "freshestCRL",
346 "X509v3 Freshest CRL");
347 (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
348 "X509v3 Inhibit Any-Policy");
350 #if OPENSSL_VERSION_NUMBER < 0x10100000L
352 * Set up for thread-safe operation.
353 * This is not required for OpenSSL 1.1
355 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
356 if (lock_cs == NULL) {
357 (void) mutex_unlock(&init_lock);
358 return (NULL);
361 lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
362 if (lock_count == NULL) {
363 OPENSSL_free(lock_cs);
364 (void) mutex_unlock(&init_lock);
365 return (NULL);
368 for (i = 0; i < CRYPTO_num_locks(); i++) {
369 lock_count[i] = 0;
370 (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
373 CRYPTO_set_id_callback((unsigned long (*)())thread_id);
374 if (CRYPTO_get_locking_callback() == NULL)
375 CRYPTO_set_locking_callback((void (*)())locking_cb);
377 (void) OpenSSL_add_all_algorithms();
379 /* Enable error strings for reporting */
380 (void) ERR_load_crypto_strings();
381 #endif
383 ssl_initialized = 1;
385 (void) mutex_unlock(&init_lock);
387 return (&openssl_plugin_table);
391 * Convert an SSL DN to a KMF DN.
393 static KMF_RETURN
394 get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
396 KMF_DATA derdata;
397 KMF_RETURN rv = KMF_OK;
398 uchar_t *tmp;
400 /* Convert to raw DER format */
401 derdata.Length = i2d_X509_NAME(sslDN, NULL);
402 if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
403 == NULL) {
404 return (KMF_ERR_MEMORY);
406 (void) i2d_X509_NAME(sslDN, &tmp);
408 /* Decode to KMF format */
409 rv = DerDecodeName(&derdata, kmfDN);
410 if (rv != KMF_OK) {
411 rv = KMF_ERR_BAD_CERT_FORMAT;
413 OPENSSL_free(derdata.Data);
415 return (rv);
419 isdir(char *path)
421 struct stat s;
423 if (stat(path, &s) == -1)
424 return (0);
426 return ((s.st_mode & S_IFMT) == S_IFDIR);
429 static KMF_RETURN
430 ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
432 KMF_RETURN rv = KMF_OK;
433 unsigned char *buf = NULL, *p;
434 int len;
437 * Convert the X509 internal struct to DER encoded data
439 if ((len = i2d_X509(x509cert, NULL)) < 0) {
440 SET_ERROR(kmfh, ERR_get_error());
441 rv = KMF_ERR_BAD_CERT_FORMAT;
442 goto cleanup;
444 if ((buf = malloc(len)) == NULL) {
445 SET_SYS_ERROR(kmfh, errno);
446 rv = KMF_ERR_MEMORY;
447 goto cleanup;
451 * i2d_X509 will increment the buf pointer so that we need to
452 * save it.
454 p = buf;
455 if ((len = i2d_X509(x509cert, &p)) < 0) {
456 SET_ERROR(kmfh, ERR_get_error());
457 free(buf);
458 rv = KMF_ERR_BAD_CERT_FORMAT;
459 goto cleanup;
462 /* caller's responsibility to free it */
463 cert->Data = buf;
464 cert->Length = len;
466 cleanup:
467 if (rv != KMF_OK) {
468 if (buf)
469 free(buf);
470 cert->Data = NULL;
471 cert->Length = 0;
474 return (rv);
478 static KMF_RETURN
479 check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
480 boolean_t *match)
482 KMF_RETURN rv = KMF_OK;
483 boolean_t findIssuer = FALSE;
484 boolean_t findSubject = FALSE;
485 boolean_t findSerial = FALSE;
486 KMF_X509_NAME issuerDN, subjectDN;
487 KMF_X509_NAME certIssuerDN, certSubjectDN;
489 *match = FALSE;
490 if (xcert == NULL) {
491 return (KMF_ERR_BAD_PARAMETER);
494 (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
495 (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
496 (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
497 (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
499 if (issuer != NULL && strlen(issuer)) {
500 rv = kmf_dn_parser(issuer, &issuerDN);
501 if (rv != KMF_OK)
502 return (KMF_ERR_BAD_PARAMETER);
504 rv = get_x509_dn(X509_get_issuer_name(xcert), &certIssuerDN);
505 if (rv != KMF_OK) {
506 kmf_free_dn(&issuerDN);
507 return (KMF_ERR_BAD_PARAMETER);
510 findIssuer = TRUE;
512 if (subject != NULL && strlen(subject)) {
513 rv = kmf_dn_parser(subject, &subjectDN);
514 if (rv != KMF_OK) {
515 rv = KMF_ERR_BAD_PARAMETER;
516 goto cleanup;
519 rv = get_x509_dn(X509_get_subject_name(xcert), &certSubjectDN);
520 if (rv != KMF_OK) {
521 rv = KMF_ERR_BAD_PARAMETER;
522 goto cleanup;
524 findSubject = TRUE;
526 if (serial != NULL && serial->val != NULL)
527 findSerial = TRUE;
529 if (findSerial) {
530 BIGNUM *bn;
532 /* Comparing BIGNUMs is a pain! */
533 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(xcert), NULL);
534 if (bn != NULL) {
535 int bnlen = BN_num_bytes(bn);
537 if (bnlen == serial->len) {
538 uchar_t *a = malloc(bnlen);
539 if (a == NULL) {
540 rv = KMF_ERR_MEMORY;
541 BN_free(bn);
542 goto cleanup;
544 bnlen = BN_bn2bin(bn, a);
545 *match = (memcmp(a, serial->val, serial->len) ==
547 rv = KMF_OK;
548 free(a);
550 BN_free(bn);
551 if (!(*match))
552 goto cleanup;
553 } else {
554 rv = KMF_OK;
555 goto cleanup;
558 if (findIssuer) {
559 *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
560 if ((*match) == B_FALSE) {
561 /* stop checking and bail */
562 rv = KMF_OK;
563 goto cleanup;
566 if (findSubject) {
567 *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
568 if ((*match) == B_FALSE) {
569 /* stop checking and bail */
570 rv = KMF_OK;
571 goto cleanup;
575 *match = TRUE;
576 cleanup:
577 if (findIssuer) {
578 kmf_free_dn(&issuerDN);
579 kmf_free_dn(&certIssuerDN);
581 if (findSubject) {
582 kmf_free_dn(&subjectDN);
583 kmf_free_dn(&certSubjectDN);
586 return (rv);
591 * This function loads a certificate file into an X509 data structure, and
592 * checks if its issuer, subject or the serial number matches with those
593 * values. If it matches, then return the X509 data structure.
595 static KMF_RETURN
596 load_X509cert(KMF_HANDLE *kmfh,
597 char *issuer, char *subject, KMF_BIGINT *serial,
598 char *pathname, X509 **outcert)
600 KMF_RETURN rv = KMF_OK;
601 X509 *xcert = NULL;
602 BIO *bcert = NULL;
603 boolean_t match = FALSE;
604 KMF_ENCODE_FORMAT format;
607 * auto-detect the file format, regardless of what
608 * the 'format' parameters in the params say.
610 rv = kmf_get_file_format(pathname, &format);
611 if (rv != KMF_OK) {
612 if (rv == KMF_ERR_OPEN_FILE)
613 rv = KMF_ERR_CERT_NOT_FOUND;
614 return (rv);
617 /* Not ASN1(DER) format */
618 if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
619 SET_ERROR(kmfh, ERR_get_error());
620 rv = KMF_ERR_OPEN_FILE;
621 goto cleanup;
624 if (format == KMF_FORMAT_PEM)
625 xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
626 else if (format == KMF_FORMAT_ASN1)
627 xcert = d2i_X509_bio(bcert, NULL);
628 else if (format == KMF_FORMAT_PKCS12) {
629 PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
630 if (p12 != NULL) {
631 (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
632 PKCS12_free(p12);
633 p12 = NULL;
634 } else {
635 SET_ERROR(kmfh, ERR_get_error());
636 rv = KMF_ERR_BAD_CERT_FORMAT;
638 } else {
639 rv = KMF_ERR_BAD_PARAMETER;
640 goto cleanup;
643 if (xcert == NULL) {
644 SET_ERROR(kmfh, ERR_get_error());
645 rv = KMF_ERR_BAD_CERT_FORMAT;
646 goto cleanup;
649 if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
650 match == FALSE) {
651 rv = KMF_ERR_CERT_NOT_FOUND;
652 goto cleanup;
655 if (outcert != NULL) {
656 *outcert = xcert;
659 cleanup:
660 if (bcert != NULL) (void) BIO_free(bcert);
661 if (rv != KMF_OK && xcert != NULL)
662 X509_free(xcert);
664 return (rv);
667 static int
668 datacmp(const void *a, const void *b)
670 KMF_DATA *adata = (KMF_DATA *)a;
671 KMF_DATA *bdata = (KMF_DATA *)b;
672 if (adata->Length > bdata->Length)
673 return (-1);
674 if (adata->Length < bdata->Length)
675 return (1);
676 return (0);
679 static KMF_RETURN
680 load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
681 KMF_CERT_VALIDITY validity, char *pathname,
682 KMF_DATA **certlist, uint32_t *numcerts)
684 KMF_RETURN rv = KMF_OK;
685 int i;
686 KMF_DATA *certs = NULL;
687 int nc = 0;
688 int hits = 0;
689 KMF_ENCODE_FORMAT format;
691 rv = kmf_get_file_format(pathname, &format);
692 if (rv != KMF_OK) {
693 if (rv == KMF_ERR_OPEN_FILE)
694 rv = KMF_ERR_CERT_NOT_FOUND;
695 return (rv);
697 if (format == KMF_FORMAT_ASN1) {
698 /* load a single certificate */
699 certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
700 if (certs == NULL)
701 return (KMF_ERR_MEMORY);
702 certs->Data = NULL;
703 certs->Length = 0;
704 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
705 pathname, certs);
706 if (rv == KMF_OK) {
707 *certlist = certs;
708 *numcerts = 1;
709 } else {
710 kmf_free_data(certs);
711 free(certs);
712 certs = NULL;
714 return (rv);
715 } else if (format == KMF_FORMAT_PKCS12) {
716 /* We need a credential to access a PKCS#12 file */
717 rv = KMF_ERR_BAD_CERT_FORMAT;
718 } else if (format == KMF_FORMAT_PEM ||
719 format != KMF_FORMAT_PEM_KEYPAIR) {
721 /* This function only works on PEM files */
722 rv = extract_pem(kmfh, issuer, subject, serial, pathname,
723 (uchar_t *)NULL, 0, NULL, &certs, &nc);
724 } else {
725 return (KMF_ERR_ENCODING);
728 if (rv != KMF_OK)
729 return (rv);
731 for (i = 0; i < nc; i++) {
732 if (validity == KMF_NONEXPIRED_CERTS) {
733 rv = kmf_check_cert_date(kmfh, &certs[i]);
734 } else if (validity == KMF_EXPIRED_CERTS) {
735 rv = kmf_check_cert_date(kmfh, &certs[i]);
736 if (rv == KMF_OK)
737 rv = KMF_ERR_CERT_NOT_FOUND;
738 if (rv == KMF_ERR_VALIDITY_PERIOD)
739 rv = KMF_OK;
741 if (rv != KMF_OK) {
742 /* Remove this cert from the list by clearing it. */
743 kmf_free_data(&certs[i]);
744 } else {
745 hits++; /* count valid certs found */
747 rv = KMF_OK;
749 if (rv == KMF_OK && hits > 0) {
751 * Sort the list of certs by length to put the cleared ones
752 * at the end so they don't get accessed by the caller.
754 qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
755 *certlist = certs;
757 /* since we sorted the list, just return the number of hits */
758 *numcerts = hits;
759 } else {
760 if (rv == KMF_OK && hits == 0)
761 rv = KMF_ERR_CERT_NOT_FOUND;
762 if (certs != NULL) {
763 free(certs);
764 certs = NULL;
767 return (rv);
770 static KMF_RETURN
771 kmf_load_cert(KMF_HANDLE *kmfh,
772 char *issuer, char *subject, KMF_BIGINT *serial,
773 KMF_CERT_VALIDITY validity,
774 char *pathname,
775 KMF_DATA *cert)
777 KMF_RETURN rv = KMF_OK;
778 X509 *x509cert = NULL;
780 rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
781 if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
782 rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
783 if (rv != KMF_OK) {
784 goto cleanup;
786 if (validity == KMF_NONEXPIRED_CERTS) {
787 rv = kmf_check_cert_date(kmfh, cert);
788 } else if (validity == KMF_EXPIRED_CERTS) {
789 rv = kmf_check_cert_date(kmfh, cert);
790 if (rv == KMF_OK) {
792 * This is a valid cert so skip it.
794 rv = KMF_ERR_CERT_NOT_FOUND;
796 if (rv == KMF_ERR_VALIDITY_PERIOD) {
798 * We want to return success when we
799 * find an invalid cert.
801 rv = KMF_OK;
802 goto cleanup;
806 cleanup:
807 if (x509cert != NULL)
808 X509_free(x509cert);
810 return (rv);
813 static KMF_RETURN
814 readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
816 KMF_RETURN ret = KMF_OK;
817 KMF_RAW_RSA_KEY rsa;
818 BerElement *asn1 = NULL;
819 BerValue filebuf;
820 BerValue OID = { NULL, 0 };
821 BerValue *Mod = NULL, *PubExp = NULL;
822 BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
823 BerValue *Coef = NULL;
824 BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
825 BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
826 BIGNUM *qminus1 = NULL;
827 BN_CTX *ctx = NULL;
829 *pkey = NULL;
831 filebuf.bv_val = (char *)filedata->Data;
832 filebuf.bv_len = filedata->Length;
834 asn1 = kmfder_init(&filebuf);
835 if (asn1 == NULL) {
836 ret = KMF_ERR_MEMORY;
837 goto out;
840 if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
841 &OID, &Mod, &PubExp, &PriExp, &Prime1,
842 &Prime2, &Coef) == -1) {
843 ret = KMF_ERR_ENCODING;
844 goto out;
848 * We have to derive the 2 Exponents using Bignumber math.
849 * Exp1 = PriExp mod (Prime1 - 1)
850 * Exp2 = PriExp mod (Prime2 - 1)
853 /* D = PrivateExponent */
854 D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
855 if (D == NULL) {
856 ret = KMF_ERR_MEMORY;
857 goto out;
860 /* P = Prime1 (first prime factor of Modulus) */
861 P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
862 if (D == NULL) {
863 ret = KMF_ERR_MEMORY;
864 goto out;
867 /* Q = Prime2 (second prime factor of Modulus) */
868 Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
870 if ((ctx = BN_CTX_new()) == NULL) {
871 ret = KMF_ERR_MEMORY;
872 goto out;
875 /* Compute (P - 1) */
876 pminus1 = BN_new();
877 (void) BN_sub(pminus1, P, BN_value_one());
879 /* Exponent1 = D mod (P - 1) */
880 Exp1 = BN_new();
881 (void) BN_mod(Exp1, D, pminus1, ctx);
883 /* Compute (Q - 1) */
884 qminus1 = BN_new();
885 (void) BN_sub(qminus1, Q, BN_value_one());
887 /* Exponent2 = D mod (Q - 1) */
888 Exp2 = BN_new();
889 (void) BN_mod(Exp2, D, qminus1, ctx);
891 /* Coef = (Inverse Q) mod P */
892 COEF = BN_new();
893 (void) BN_mod_inverse(COEF, Q, P, ctx);
895 /* Convert back to KMF format */
896 (void) memset(&rsa, 0, sizeof (rsa));
898 if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
899 goto out;
900 if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
901 goto out;
902 if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
903 goto out;
905 rsa.mod.val = (uchar_t *)Mod->bv_val;
906 rsa.mod.len = Mod->bv_len;
908 rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
909 rsa.pubexp.len = PubExp->bv_len;
911 rsa.priexp.val = (uchar_t *)PriExp->bv_val;
912 rsa.priexp.len = PriExp->bv_len;
914 rsa.prime1.val = (uchar_t *)Prime1->bv_val;
915 rsa.prime1.len = Prime1->bv_len;
917 rsa.prime2.val = (uchar_t *)Prime2->bv_val;
918 rsa.prime2.len = Prime2->bv_len;
920 *pkey = ImportRawRSAKey(&rsa);
921 out:
922 if (asn1 != NULL)
923 kmfber_free(asn1, 1);
925 if (OID.bv_val) {
926 free(OID.bv_val);
928 if (PriExp)
929 free(PriExp);
931 if (Mod)
932 free(Mod);
934 if (PubExp)
935 free(PubExp);
937 if (Coef) {
938 (void) memset(Coef->bv_val, 0, Coef->bv_len);
939 free(Coef->bv_val);
940 free(Coef);
942 if (Prime1)
943 free(Prime1);
944 if (Prime2)
945 free(Prime2);
947 if (ctx != NULL)
948 BN_CTX_free(ctx);
950 if (D)
951 BN_clear_free(D);
952 if (P)
953 BN_clear_free(P);
954 if (Q)
955 BN_clear_free(Q);
956 if (pminus1)
957 BN_clear_free(pminus1);
958 if (qminus1)
959 BN_clear_free(qminus1);
960 if (Exp1)
961 BN_clear_free(Exp1);
962 if (Exp2)
963 BN_clear_free(Exp2);
965 return (ret);
969 static EVP_PKEY *
970 openssl_load_key(KMF_HANDLE_T handle, const char *file)
972 BIO *keyfile = NULL;
973 EVP_PKEY *pkey = NULL;
974 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
975 KMF_ENCODE_FORMAT format;
976 KMF_RETURN rv;
977 KMF_DATA filedata;
979 if (file == NULL) {
980 return (NULL);
983 if (kmf_get_file_format((char *)file, &format) != KMF_OK)
984 return (NULL);
986 keyfile = BIO_new_file(file, "rb");
987 if (keyfile == NULL) {
988 goto end;
991 if (format == KMF_FORMAT_ASN1) {
992 pkey = d2i_PrivateKey_bio(keyfile, NULL);
993 if (pkey == NULL) {
995 (void) BIO_free(keyfile);
996 keyfile = NULL;
997 /* Try odd ASN.1 variations */
998 rv = kmf_read_input_file(kmfh, (char *)file,
999 &filedata);
1000 if (rv == KMF_OK) {
1001 (void) readAltFormatPrivateKey(&filedata,
1002 &pkey);
1003 kmf_free_data(&filedata);
1006 } else if (format == KMF_FORMAT_PEM ||
1007 format == KMF_FORMAT_PEM_KEYPAIR) {
1008 pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
1009 if (pkey == NULL) {
1010 KMF_DATA derdata;
1012 * Check if this is the alt. format
1013 * RSA private key file.
1015 rv = kmf_read_input_file(kmfh, (char *)file,
1016 &filedata);
1017 if (rv == KMF_OK) {
1018 uchar_t *d = NULL;
1019 int len;
1020 rv = kmf_pem_to_der(filedata.Data,
1021 filedata.Length, &d, &len);
1022 if (rv == KMF_OK && d != NULL) {
1023 derdata.Data = d;
1024 derdata.Length = (size_t)len;
1025 (void) readAltFormatPrivateKey(
1026 &derdata, &pkey);
1027 free(d);
1029 kmf_free_data(&filedata);
1034 end:
1035 if (pkey == NULL)
1036 SET_ERROR(kmfh, ERR_get_error());
1038 if (keyfile != NULL)
1039 (void) BIO_free(keyfile);
1041 return (pkey);
1044 KMF_RETURN
1045 OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1047 KMF_RETURN rv = KMF_OK;
1048 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1049 int i, n;
1050 uint32_t maxcerts = 0;
1051 uint32_t *num_certs;
1052 KMF_X509_DER_CERT *kmf_cert = NULL;
1053 char *dirpath = NULL;
1054 char *filename = NULL;
1055 char *fullpath = NULL;
1056 char *issuer = NULL;
1057 char *subject = NULL;
1058 KMF_BIGINT *serial = NULL;
1059 KMF_CERT_VALIDITY validity;
1061 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1062 if (num_certs == NULL)
1063 return (KMF_ERR_BAD_PARAMETER);
1065 /* num_certs should reference the size of kmf_cert */
1066 maxcerts = *num_certs;
1067 if (maxcerts == 0)
1068 maxcerts = 0xFFFFFFFF;
1069 *num_certs = 0;
1071 /* Get the optional returned certificate list */
1072 kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1073 numattr);
1076 * The dirpath attribute and the filename attribute can not be NULL
1077 * at the same time.
1079 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1080 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1081 numattr);
1083 fullpath = get_fullpath(dirpath, filename);
1084 if (fullpath == NULL)
1085 return (KMF_ERR_BAD_PARAMETER);
1087 /* Get optional search criteria attributes */
1088 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1089 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1090 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1091 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1092 &validity, NULL);
1093 if (rv != KMF_OK) {
1094 validity = KMF_ALL_CERTS;
1095 rv = KMF_OK;
1098 if (isdir(fullpath)) {
1099 DIR *dirp;
1100 struct dirent *dp;
1102 n = 0;
1103 /* open all files in the directory and attempt to read them */
1104 if ((dirp = opendir(fullpath)) == NULL) {
1105 return (KMF_ERR_BAD_PARAMETER);
1107 while ((dp = readdir(dirp)) != NULL) {
1108 char *fname;
1109 KMF_DATA *certlist = NULL;
1110 uint32_t loaded_certs = 0;
1112 if (strcmp(dp->d_name, ".") == 0 ||
1113 strcmp(dp->d_name, "..") == 0)
1114 continue;
1116 fname = get_fullpath(fullpath, (char *)&dp->d_name);
1118 rv = load_certs(kmfh, issuer, subject, serial,
1119 validity, fname, &certlist, &loaded_certs);
1121 if (rv != KMF_OK) {
1122 free(fname);
1123 if (certlist != NULL) {
1124 for (i = 0; i < loaded_certs; i++)
1125 kmf_free_data(&certlist[i]);
1126 free(certlist);
1128 continue;
1131 /* If load succeeds, add certdata to the list */
1132 if (kmf_cert != NULL) {
1133 for (i = 0; i < loaded_certs &&
1134 n < maxcerts; i++) {
1135 kmf_cert[n].certificate.Data =
1136 certlist[i].Data;
1137 kmf_cert[n].certificate.Length =
1138 certlist[i].Length;
1140 kmf_cert[n].kmf_private.keystore_type =
1141 KMF_KEYSTORE_OPENSSL;
1142 kmf_cert[n].kmf_private.flags =
1143 KMF_FLAG_CERT_VALID;
1144 kmf_cert[n].kmf_private.label =
1145 strdup(fname);
1146 n++;
1149 * If maxcerts < loaded_certs, clean up the
1150 * certs that were not used.
1152 for (; i < loaded_certs; i++)
1153 kmf_free_data(&certlist[i]);
1154 } else {
1155 for (i = 0; i < loaded_certs; i++)
1156 kmf_free_data(&certlist[i]);
1157 n += loaded_certs;
1159 free(certlist);
1160 free(fname);
1162 (*num_certs) = n;
1163 if (*num_certs == 0)
1164 rv = KMF_ERR_CERT_NOT_FOUND;
1165 if (*num_certs > 0)
1166 rv = KMF_OK;
1167 exit:
1168 (void) closedir(dirp);
1169 } else {
1170 KMF_DATA *certlist = NULL;
1171 uint32_t loaded_certs = 0;
1173 rv = load_certs(kmfh, issuer, subject, serial, validity,
1174 fullpath, &certlist, &loaded_certs);
1175 if (rv != KMF_OK) {
1176 free(fullpath);
1177 return (rv);
1180 n = 0;
1181 if (kmf_cert != NULL && certlist != NULL) {
1182 for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1183 kmf_cert[n].certificate.Data =
1184 certlist[i].Data;
1185 kmf_cert[n].certificate.Length =
1186 certlist[i].Length;
1187 kmf_cert[n].kmf_private.keystore_type =
1188 KMF_KEYSTORE_OPENSSL;
1189 kmf_cert[n].kmf_private.flags =
1190 KMF_FLAG_CERT_VALID;
1191 kmf_cert[n].kmf_private.label =
1192 strdup(fullpath);
1193 n++;
1195 /* If maxcerts < loaded_certs, clean up */
1196 for (; i < loaded_certs; i++)
1197 kmf_free_data(&certlist[i]);
1198 } else if (certlist != NULL) {
1199 for (i = 0; i < loaded_certs; i++)
1200 kmf_free_data(&certlist[i]);
1201 n = loaded_certs;
1203 if (certlist != NULL)
1204 free(certlist);
1205 *num_certs = n;
1208 free(fullpath);
1210 return (rv);
1213 void
1214 /*ARGSUSED*/
1215 OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
1216 KMF_X509_DER_CERT *kmf_cert)
1218 if (kmf_cert != NULL) {
1219 if (kmf_cert->certificate.Data != NULL) {
1220 kmf_free_data(&kmf_cert->certificate);
1222 if (kmf_cert->kmf_private.label)
1223 free(kmf_cert->kmf_private.label);
1227 /*ARGSUSED*/
1228 KMF_RETURN
1229 OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1231 KMF_RETURN ret = KMF_OK;
1232 KMF_DATA *cert = NULL;
1233 char *outfilename = NULL;
1234 char *dirpath = NULL;
1235 char *fullpath = NULL;
1236 KMF_ENCODE_FORMAT format;
1238 /* Get the cert data */
1239 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1240 if (cert == NULL || cert->Data == NULL)
1241 return (KMF_ERR_BAD_PARAMETER);
1243 /* Check the output filename and directory attributes. */
1244 outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1245 numattr);
1246 if (outfilename == NULL)
1247 return (KMF_ERR_BAD_PARAMETER);
1249 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1250 fullpath = get_fullpath(dirpath, outfilename);
1251 if (fullpath == NULL)
1252 return (KMF_ERR_BAD_CERTFILE);
1254 /* Check the optional format attribute */
1255 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1256 &format, NULL);
1257 if (ret != KMF_OK) {
1258 /* If there is no format attribute, then default to PEM */
1259 format = KMF_FORMAT_PEM;
1260 ret = KMF_OK;
1261 } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1262 ret = KMF_ERR_BAD_CERT_FORMAT;
1263 goto out;
1266 /* Store the certificate in the file with the specified format */
1267 ret = kmf_create_cert_file(cert, format, fullpath);
1269 out:
1270 if (fullpath != NULL)
1271 free(fullpath);
1273 return (ret);
1277 KMF_RETURN
1278 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1280 KMF_RETURN rv;
1281 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1282 KMF_DATA certdata = { 0, NULL };
1283 char *dirpath = NULL;
1284 char *filename = NULL;
1285 char *fullpath = NULL;
1286 char *issuer = NULL;
1287 char *subject = NULL;
1288 KMF_BIGINT *serial = NULL;
1289 KMF_CERT_VALIDITY validity;
1292 * Get the DIRPATH and CERT_FILENAME attributes. They can not be
1293 * NULL at the same time.
1295 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1296 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1297 numattr);
1298 fullpath = get_fullpath(dirpath, filename);
1299 if (fullpath == NULL)
1300 return (KMF_ERR_BAD_PARAMETER);
1302 /* Get optional search criteria attributes */
1303 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1304 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1305 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1306 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1307 &validity, NULL);
1308 if (rv != KMF_OK) {
1309 validity = KMF_ALL_CERTS;
1310 rv = KMF_OK;
1313 if (isdir(fullpath)) {
1314 DIR *dirp;
1315 struct dirent *dp;
1317 /* open all files in the directory and attempt to read them */
1318 if ((dirp = opendir(fullpath)) == NULL) {
1319 return (KMF_ERR_BAD_PARAMETER);
1322 while ((dp = readdir(dirp)) != NULL) {
1323 if (strcmp(dp->d_name, ".") != 0 &&
1324 strcmp(dp->d_name, "..") != 0) {
1325 char *fname;
1327 fname = get_fullpath(fullpath,
1328 (char *)&dp->d_name);
1330 if (fname == NULL) {
1331 rv = KMF_ERR_MEMORY;
1332 break;
1335 rv = kmf_load_cert(kmfh, issuer, subject,
1336 serial, validity, fname, &certdata);
1338 if (rv == KMF_ERR_CERT_NOT_FOUND) {
1339 free(fname);
1340 kmf_free_data(&certdata);
1341 rv = KMF_OK;
1342 continue;
1343 } else if (rv != KMF_OK) {
1344 free(fname);
1345 break;
1348 if (unlink(fname) != 0) {
1349 SET_SYS_ERROR(kmfh, errno);
1350 rv = KMF_ERR_INTERNAL;
1351 free(fname);
1352 break;
1354 free(fname);
1355 kmf_free_data(&certdata);
1358 (void) closedir(dirp);
1359 } else {
1360 /* Just try to load a single certificate */
1361 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1362 fullpath, &certdata);
1363 if (rv == KMF_OK) {
1364 if (unlink(fullpath) != 0) {
1365 SET_SYS_ERROR(kmfh, errno);
1366 rv = KMF_ERR_INTERNAL;
1371 out:
1372 if (fullpath != NULL)
1373 free(fullpath);
1375 kmf_free_data(&certdata);
1377 return (rv);
1380 KMF_RETURN
1381 OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1382 KMF_DATA *keydata)
1384 KMF_RETURN rv = KMF_OK;
1385 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1386 int n;
1388 if (key == NULL || keydata == NULL ||
1389 key->keyp == NULL)
1390 return (KMF_ERR_BAD_PARAMETER);
1392 if (key->keyalg == KMF_RSA) {
1393 RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
1395 if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
1396 SET_ERROR(kmfh, ERR_get_error());
1397 return (KMF_ERR_ENCODING);
1399 RSA_free(pubkey);
1400 } else if (key->keyalg == KMF_DSA) {
1401 DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
1403 if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
1404 SET_ERROR(kmfh, ERR_get_error());
1405 return (KMF_ERR_ENCODING);
1407 DSA_free(pubkey);
1408 } else {
1409 return (KMF_ERR_BAD_PARAMETER);
1411 keydata->Length = n;
1413 cleanup:
1414 if (rv != KMF_OK) {
1415 if (keydata->Data)
1416 free(keydata->Data);
1417 keydata->Data = NULL;
1418 keydata->Length = 0;
1421 return (rv);
1424 static KMF_RETURN
1425 ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1426 KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
1428 int rv = 0;
1429 RSA *rsa;
1430 DSA *dsa;
1432 if (pkey == NULL || out == NULL)
1433 return (KMF_ERR_BAD_PARAMETER);
1435 switch (format) {
1436 case KMF_FORMAT_RAWKEY:
1437 /* same as ASN.1 */
1438 case KMF_FORMAT_ASN1:
1439 if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
1440 if (private)
1441 rv = i2d_RSAPrivateKey_bio(out, rsa);
1442 else
1443 rv = i2d_RSAPublicKey_bio(out, rsa);
1444 } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
1445 rv = i2d_DSAPrivateKey_bio(out, dsa);
1447 if (rv == 1) {
1448 rv = KMF_OK;
1449 } else {
1450 SET_ERROR(kmfh, rv);
1452 break;
1453 case KMF_FORMAT_PEM:
1454 if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
1455 if (private)
1456 rv = PEM_write_bio_RSAPrivateKey(out,
1457 rsa, NULL, NULL, 0, NULL,
1458 (cred != NULL ? cred->cred : NULL));
1459 else
1460 rv = PEM_write_bio_RSAPublicKey(out,
1461 rsa);
1462 } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
1463 rv = PEM_write_bio_DSAPrivateKey(out,
1464 dsa, NULL, NULL, 0, NULL,
1465 (cred != NULL ? cred->cred : NULL));
1468 if (rv == 1) {
1469 rv = KMF_OK;
1470 } else {
1471 SET_ERROR(kmfh, rv);
1473 break;
1475 default:
1476 rv = KMF_ERR_BAD_PARAMETER;
1479 return (rv);
1482 KMF_RETURN
1483 OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1484 KMF_ATTRIBUTE *attrlist)
1486 KMF_RETURN rv = KMF_OK;
1487 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1488 uint32_t eValue = RSA_F4;
1489 BIGNUM *eValue_bn = NULL;
1490 RSA *sslPrivKey = NULL;
1491 DSA *sslDSAKey = NULL;
1492 EVP_PKEY *eprikey = NULL;
1493 EVP_PKEY *epubkey = NULL;
1494 BIO *out = NULL;
1495 KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1496 uint32_t keylen = 1024;
1497 uint32_t keylen_size = sizeof (uint32_t);
1498 boolean_t storekey = TRUE;
1499 KMF_KEY_ALG keytype = KMF_RSA;
1501 eValue_bn = BN_new();
1502 if (eValue_bn == NULL)
1503 return (KMF_ERR_MEMORY);
1504 if (BN_set_word(eValue_bn, eValue) == 0) {
1505 rv = KMF_ERR_KEYGEN_FAILED;
1506 goto cleanup;
1509 rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1510 &storekey, NULL);
1511 if (rv != KMF_OK) {
1512 /* "storekey" is optional. Default is TRUE */
1513 rv = KMF_OK;
1516 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1517 (void *)&keytype, NULL);
1518 if (rv != KMF_OK)
1519 /* keytype is optional. KMF_RSA is default */
1520 rv = KMF_OK;
1522 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1523 if (pubkey == NULL) {
1524 rv = KMF_ERR_BAD_PARAMETER;
1525 goto cleanup;
1528 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1529 if (privkey == NULL) {
1530 rv = KMF_ERR_BAD_PARAMETER;
1531 goto cleanup;
1534 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1535 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1537 eprikey = EVP_PKEY_new();
1538 if (eprikey == NULL) {
1539 SET_ERROR(kmfh, ERR_get_error());
1540 rv = KMF_ERR_KEYGEN_FAILED;
1541 goto cleanup;
1543 epubkey = EVP_PKEY_new();
1544 if (epubkey == NULL) {
1545 SET_ERROR(kmfh, ERR_get_error());
1546 rv = KMF_ERR_KEYGEN_FAILED;
1547 goto cleanup;
1549 if (keytype == KMF_RSA) {
1550 KMF_BIGINT *rsaexp = NULL;
1552 rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1553 if (rsaexp != NULL) {
1554 if (rsaexp->len > 0 &&
1555 rsaexp->len <= sizeof (eValue) &&
1556 rsaexp->val != NULL) {
1557 /* LINTED E_BAD_PTR_CAST_ALIGN */
1558 eValue = *(uint32_t *)rsaexp->val;
1559 if (BN_set_word(eValue_bn, eValue) == 0) {
1560 rv = KMF_ERR_BAD_PARAMETER;
1561 goto cleanup;
1563 } else {
1564 rv = KMF_ERR_BAD_PARAMETER;
1565 goto cleanup;
1567 } else {
1568 /* RSA Exponent is optional. Default is 0x10001 */
1569 rv = KMF_OK;
1572 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1573 &keylen, &keylen_size);
1574 if (rv == KMF_ERR_ATTR_NOT_FOUND)
1575 /* keylen is optional, default is 1024 */
1576 rv = KMF_OK;
1577 if (rv != KMF_OK) {
1578 rv = KMF_ERR_BAD_PARAMETER;
1579 goto cleanup;
1582 sslPrivKey = RSA_new();
1583 if (sslPrivKey == NULL ||
1584 RSA_generate_key_ex(sslPrivKey, keylen, eValue_bn, NULL)
1585 == 0) {
1586 SET_ERROR(kmfh, ERR_get_error());
1587 rv = KMF_ERR_KEYGEN_FAILED;
1588 } else {
1589 (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
1590 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1591 privkey->keyalg = KMF_RSA;
1592 privkey->keyclass = KMF_ASYM_PRI;
1593 privkey->israw = FALSE;
1594 privkey->keyp = (void *)eprikey;
1596 /* OpenSSL derives the public key from the private */
1597 (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
1598 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1599 pubkey->keyalg = KMF_RSA;
1600 pubkey->israw = FALSE;
1601 pubkey->keyclass = KMF_ASYM_PUB;
1602 pubkey->keyp = (void *)epubkey;
1604 } else if (keytype == KMF_DSA) {
1605 BIGNUM *p, *q, *g;
1607 sslDSAKey = DSA_new();
1608 if (sslDSAKey == NULL) {
1609 SET_ERROR(kmfh, ERR_get_error());
1610 return (KMF_ERR_MEMORY);
1613 p = BN_bin2bn(P, sizeof (P), NULL);
1614 q = BN_bin2bn(Q, sizeof (Q), NULL);
1615 g = BN_bin2bn(G, sizeof (G), NULL);
1616 if (p == NULL || q == NULL || g == NULL) {
1617 BN_free(p);
1618 BN_free(q);
1619 BN_free(g);
1620 SET_ERROR(kmfh, ERR_get_error());
1621 rv = KMF_ERR_KEYGEN_FAILED;
1622 goto cleanup;
1625 if (DSA_set0_pqg(sslDSAKey, p, q, g) == 0) {
1626 SET_ERROR(kmfh, ERR_get_error());
1627 rv = KMF_ERR_KEYGEN_FAILED;
1628 goto cleanup;
1631 if (!DSA_generate_key(sslDSAKey)) {
1632 SET_ERROR(kmfh, ERR_get_error());
1633 rv = KMF_ERR_KEYGEN_FAILED;
1634 goto cleanup;
1637 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1638 privkey->keyalg = KMF_DSA;
1639 privkey->keyclass = KMF_ASYM_PRI;
1640 privkey->israw = FALSE;
1641 if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1642 privkey->keyp = (void *)eprikey;
1643 } else {
1644 SET_ERROR(kmfh, ERR_get_error());
1645 rv = KMF_ERR_KEYGEN_FAILED;
1646 goto cleanup;
1649 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1650 pubkey->keyalg = KMF_DSA;
1651 pubkey->keyclass = KMF_ASYM_PUB;
1652 pubkey->israw = FALSE;
1654 if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1655 pubkey->keyp = (void *)epubkey;
1656 } else {
1657 SET_ERROR(kmfh, ERR_get_error());
1658 rv = KMF_ERR_KEYGEN_FAILED;
1659 goto cleanup;
1663 if (rv != KMF_OK) {
1664 goto cleanup;
1667 if (storekey) {
1668 KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1669 int i = 0;
1670 char *keyfile = NULL, *dirpath = NULL;
1671 KMF_ENCODE_FORMAT format;
1673 * Construct a new attribute arrray and call openssl_store_key
1675 kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1676 privkey, sizeof (privkey));
1677 i++;
1679 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1680 if (dirpath != NULL) {
1681 storeattrs[i].type = KMF_DIRPATH_ATTR;
1682 storeattrs[i].pValue = dirpath;
1683 storeattrs[i].valueLen = strlen(dirpath);
1684 i++;
1685 } else {
1686 rv = KMF_OK; /* DIRPATH is optional */
1688 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1689 attrlist, numattr);
1690 if (keyfile != NULL) {
1691 storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1692 storeattrs[i].pValue = keyfile;
1693 storeattrs[i].valueLen = strlen(keyfile);
1694 i++;
1695 } else {
1696 goto cleanup; /* KEYFILE is required */
1698 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1699 (void *)&format, NULL);
1700 if (rv == KMF_OK) {
1701 storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1702 storeattrs[i].pValue = &format;
1703 storeattrs[i].valueLen = sizeof (format);
1704 i++;
1707 rv = OpenSSL_StoreKey(handle, i, storeattrs);
1710 cleanup:
1711 if (eValue_bn != NULL)
1712 BN_free(eValue_bn);
1714 if (rv != KMF_OK) {
1715 if (eprikey != NULL)
1716 EVP_PKEY_free(eprikey);
1718 if (epubkey != NULL)
1719 EVP_PKEY_free(epubkey);
1721 if (pubkey->keylabel) {
1722 free(pubkey->keylabel);
1723 pubkey->keylabel = NULL;
1726 if (privkey->keylabel) {
1727 free(privkey->keylabel);
1728 privkey->keylabel = NULL;
1731 pubkey->keyp = NULL;
1732 privkey->keyp = NULL;
1735 if (sslPrivKey)
1736 RSA_free(sslPrivKey);
1738 if (sslDSAKey)
1739 DSA_free(sslDSAKey);
1741 if (out != NULL)
1742 (void) BIO_free(out);
1744 return (rv);
1748 * Make sure the BN conversion is properly padded with 0x00
1749 * bytes. If not, signature verification for DSA signatures
1750 * may fail in the case where the bignum value does not use
1751 * all of the bits.
1753 static int
1754 fixbnlen(const BIGNUM *bn, unsigned char *buf, int len) {
1755 int bytes = len - BN_num_bytes(bn);
1757 /* prepend with leading 0x00 if necessary */
1758 while (bytes-- > 0)
1759 *buf++ = 0;
1761 (void) BN_bn2bin(bn, buf);
1763 * Return the desired length since we prepended it
1764 * with the necessary 0x00 padding.
1766 return (len);
1769 KMF_RETURN
1770 OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1771 KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1773 KMF_RETURN ret = KMF_OK;
1774 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1775 KMF_ALGORITHM_INDEX AlgId;
1776 EVP_MD_CTX *ctx;
1777 const EVP_MD *md;
1779 if (key == NULL || AlgOID == NULL ||
1780 tobesigned == NULL || output == NULL ||
1781 tobesigned->Data == NULL ||
1782 output->Data == NULL)
1783 return (KMF_ERR_BAD_PARAMETER);
1785 /* Map the OID to an OpenSSL algorithm */
1786 AlgId = x509_algoid_to_algid(AlgOID);
1787 if (AlgId == KMF_ALGID_NONE)
1788 return (KMF_ERR_BAD_ALGORITHM);
1790 if (key->keyalg == KMF_RSA) {
1791 EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1792 uchar_t *p;
1793 int len;
1794 if (AlgId == KMF_ALGID_MD5WithRSA)
1795 md = EVP_md5();
1796 else if (AlgId == KMF_ALGID_SHA1WithRSA)
1797 md = EVP_sha1();
1798 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1799 md = EVP_sha256();
1800 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1801 md = EVP_sha384();
1802 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1803 md = EVP_sha512();
1804 else if (AlgId == KMF_ALGID_RSA)
1805 md = NULL;
1806 else
1807 return (KMF_ERR_BAD_ALGORITHM);
1809 if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1810 RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1812 p = output->Data;
1813 if ((len = RSA_private_encrypt(tobesigned->Length,
1814 tobesigned->Data, p, rsa,
1815 RSA_PKCS1_PADDING)) <= 0) {
1816 SET_ERROR(kmfh, ERR_get_error());
1817 ret = KMF_ERR_INTERNAL;
1819 output->Length = len;
1820 } else {
1821 if ((ctx = EVP_MD_CTX_new()) == NULL)
1822 return (KMF_ERR_MEMORY);
1823 (void) EVP_SignInit_ex(ctx, md, NULL);
1824 (void) EVP_SignUpdate(ctx, tobesigned->Data,
1825 (uint32_t)tobesigned->Length);
1826 len = (uint32_t)output->Length;
1827 p = output->Data;
1828 if (!EVP_SignFinal(ctx, p, (uint32_t *)&len, pkey)) {
1829 SET_ERROR(kmfh, ERR_get_error());
1830 len = 0;
1831 ret = KMF_ERR_INTERNAL;
1833 output->Length = len;
1834 EVP_MD_CTX_free(ctx);
1836 } else if (key->keyalg == KMF_DSA) {
1837 DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1839 uchar_t hash[EVP_MAX_MD_SIZE];
1840 uint32_t hashlen;
1841 DSA_SIG *dsasig;
1843 if (AlgId == KMF_ALGID_DSA ||
1844 AlgId == KMF_ALGID_SHA1WithDSA)
1845 md = EVP_sha1();
1846 else if (AlgId == KMF_ALGID_SHA256WithDSA)
1847 md = EVP_sha256();
1848 else /* Bad algorithm */
1849 return (KMF_ERR_BAD_ALGORITHM);
1852 * OpenSSL EVP_Sign operation automatically converts to
1853 * ASN.1 output so we do the operations separately so we
1854 * are assured of NOT getting ASN.1 output returned.
1855 * KMF does not want ASN.1 encoded results because
1856 * not all mechanisms return ASN.1 encodings (PKCS#11
1857 * and NSS return raw signature data).
1859 if ((ctx = EVP_MD_CTX_new()) == NULL)
1860 return (KMF_ERR_MEMORY);
1861 (void) EVP_DigestInit_ex(ctx, md, NULL);
1862 (void) EVP_DigestUpdate(ctx, tobesigned->Data,
1863 tobesigned->Length);
1864 (void) EVP_DigestFinal_ex(ctx, hash, &hashlen);
1866 /* Only sign first 20 bytes for SHA2 */
1867 if (AlgId == KMF_ALGID_SHA256WithDSA)
1868 hashlen = 20;
1869 dsasig = DSA_do_sign(hash, hashlen, dsa);
1870 if (dsasig != NULL) {
1871 int i;
1872 const BIGNUM *r, *s;
1874 DSA_SIG_get0(dsasig, &r, &s);
1875 output->Length = i = fixbnlen(r, output->Data,
1876 hashlen);
1878 output->Length += fixbnlen(s, &output->Data[i],
1879 hashlen);
1881 DSA_SIG_free(dsasig);
1882 } else {
1883 SET_ERROR(kmfh, ERR_get_error());
1885 EVP_MD_CTX_free(ctx);
1886 } else {
1887 return (KMF_ERR_BAD_PARAMETER);
1889 cleanup:
1890 return (ret);
1893 KMF_RETURN
1894 /*ARGSUSED*/
1895 OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1896 int numattr, KMF_ATTRIBUTE *attrlist)
1898 KMF_RETURN rv = KMF_OK;
1899 KMF_KEY_HANDLE *key;
1900 boolean_t destroy = B_TRUE;
1902 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1903 if (key == NULL || key->keyp == NULL)
1904 return (KMF_ERR_BAD_PARAMETER);
1906 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1907 (void *)&destroy, NULL);
1908 if (rv != KMF_OK) {
1909 /* "destroy" is optional. Default is TRUE */
1910 rv = KMF_OK;
1913 if (key->keyclass != KMF_ASYM_PUB &&
1914 key->keyclass != KMF_ASYM_PRI &&
1915 key->keyclass != KMF_SYMMETRIC)
1916 return (KMF_ERR_BAD_KEY_CLASS);
1918 if (key->keyclass == KMF_SYMMETRIC) {
1919 kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1920 key->keyp = NULL;
1921 } else {
1922 if (key->keyp != NULL) {
1923 EVP_PKEY_free(key->keyp);
1924 key->keyp = NULL;
1928 if (key->keylabel != NULL) {
1929 EVP_PKEY *pkey = NULL;
1930 /* If the file exists, make sure it is a proper key. */
1931 pkey = openssl_load_key(handle, key->keylabel);
1932 if (pkey == NULL) {
1933 if (key->keylabel != NULL) {
1934 free(key->keylabel);
1935 key->keylabel = NULL;
1937 return (KMF_ERR_KEY_NOT_FOUND);
1939 EVP_PKEY_free(pkey);
1941 if (destroy) {
1942 if (unlink(key->keylabel) != 0) {
1943 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1944 SET_SYS_ERROR(kmfh, errno);
1945 rv = KMF_ERR_INTERNAL;
1948 if (key->keylabel != NULL) {
1949 free(key->keylabel);
1950 key->keylabel = NULL;
1953 return (rv);
1956 KMF_RETURN
1957 OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1959 KMF_RETURN ret = KMF_OK;
1960 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1961 char str[256]; /* OpenSSL needs at least 120 byte buffer */
1963 ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1964 if (strlen(str)) {
1965 *msgstr = (char *)strdup(str);
1966 if ((*msgstr) == NULL)
1967 ret = KMF_ERR_MEMORY;
1968 } else {
1969 *msgstr = NULL;
1972 return (ret);
1975 static int
1976 ext2NID(int kmfext)
1978 switch (kmfext) {
1979 case KMF_X509_EXT_KEY_USAGE:
1980 return (NID_key_usage);
1981 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1982 return (NID_private_key_usage_period);
1983 case KMF_X509_EXT_CERT_POLICIES:
1984 return (NID_certificate_policies);
1985 case KMF_X509_EXT_SUBJ_ALTNAME:
1986 return (NID_subject_alt_name);
1987 case KMF_X509_EXT_ISSUER_ALTNAME:
1988 return (NID_issuer_alt_name);
1989 case KMF_X509_EXT_BASIC_CONSTRAINTS:
1990 return (NID_basic_constraints);
1991 case KMF_X509_EXT_EXT_KEY_USAGE:
1992 return (NID_ext_key_usage);
1993 case KMF_X509_EXT_AUTH_KEY_ID:
1994 return (NID_authority_key_identifier);
1995 case KMF_X509_EXT_CRL_DIST_POINTS:
1996 return (NID_crl_distribution_points);
1997 case KMF_X509_EXT_SUBJ_KEY_ID:
1998 return (NID_subject_key_identifier);
1999 case KMF_X509_EXT_POLICY_MAPPINGS:
2000 return (OBJ_sn2nid("policyMappings"));
2001 case KMF_X509_EXT_NAME_CONSTRAINTS:
2002 return (OBJ_sn2nid("nameConstraints"));
2003 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2004 return (OBJ_sn2nid("policyConstraints"));
2005 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2006 return (OBJ_sn2nid("inhibitAnyPolicy"));
2007 case KMF_X509_EXT_FRESHEST_CRL:
2008 return (OBJ_sn2nid("freshestCRL"));
2009 default:
2010 return (NID_undef);
2014 KMF_RETURN
2015 OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2016 KMF_PRINTABLE_ITEM flag, char *resultStr)
2018 KMF_RETURN ret = KMF_OK;
2019 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2020 X509 *xcert = NULL;
2021 unsigned char *outbuf = NULL;
2022 unsigned char *outbuf_p;
2023 int j;
2024 int ext_index, nid, len;
2025 BIO *mem = NULL;
2026 STACK_OF(OPENSSL_STRING) *emlst = NULL;
2027 X509_EXTENSION *ex;
2029 if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2030 return (KMF_ERR_BAD_PARAMETER);
2033 /* copy cert data to outbuf */
2034 outbuf = malloc(pcert->Length);
2035 if (outbuf == NULL) {
2036 return (KMF_ERR_MEMORY);
2038 (void) memcpy(outbuf, pcert->Data, pcert->Length);
2040 outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2041 xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2042 if (xcert == NULL) {
2043 SET_ERROR(kmfh, ERR_get_error());
2044 ret = KMF_ERR_ENCODING;
2045 goto out;
2048 mem = BIO_new(BIO_s_mem());
2049 if (mem == NULL) {
2050 SET_ERROR(kmfh, ERR_get_error());
2051 ret = KMF_ERR_MEMORY;
2052 goto out;
2055 switch (flag) {
2056 case KMF_CERT_ISSUER:
2057 (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2058 XN_FLAG_SEP_CPLUS_SPC);
2059 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2060 break;
2062 case KMF_CERT_SUBJECT:
2063 (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2064 XN_FLAG_SEP_CPLUS_SPC);
2065 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2066 break;
2068 case KMF_CERT_VERSION:
2069 (void) snprintf(resultStr, KMF_CERT_PRINTABLE_LEN,
2070 "%ld", X509_get_version(xcert));
2071 len = strlen(resultStr);
2072 break;
2074 case KMF_CERT_SERIALNUM:
2075 if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2076 (void) strcpy(resultStr, "0x");
2077 len = BIO_gets(mem, &resultStr[2],
2078 KMF_CERT_PRINTABLE_LEN - 2);
2080 break;
2082 case KMF_CERT_NOTBEFORE:
2083 (void) ASN1_TIME_print(mem, X509_getm_notBefore(xcert));
2084 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2085 break;
2087 case KMF_CERT_NOTAFTER:
2088 (void) ASN1_TIME_print(mem, X509_getm_notAfter(xcert));
2089 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2090 break;
2092 case KMF_CERT_PUBKEY_DATA:
2094 RSA *rsa;
2095 DSA *dsa;
2097 EVP_PKEY *pkey = X509_get_pubkey(xcert);
2098 if (pkey == NULL) {
2099 SET_ERROR(kmfh, ERR_get_error());
2100 ret = KMF_ERR_ENCODING;
2101 goto out;
2104 if ((rsa = EVP_PKEY_get0_RSA(pkey)) != NULL) {
2105 (void) BIO_printf(mem,
2106 "RSA Public Key: (%d bit)\n",
2107 RSA_bits(rsa));
2108 (void) RSA_print(mem, rsa, 0);
2110 } else if ((dsa = EVP_PKEY_get0_DSA(pkey)) != NULL) {
2111 (void) BIO_printf(mem,
2112 "%12sDSA Public Key:\n", "");
2113 (void) DSA_print(mem, dsa, 0);
2114 } else {
2115 (void) BIO_printf(mem,
2116 "%12sUnknown Public Key:\n", "");
2118 (void) BIO_printf(mem, "\n");
2119 EVP_PKEY_free(pkey);
2121 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2122 break;
2123 case KMF_CERT_SIGNATURE_ALG:
2124 case KMF_CERT_PUBKEY_ALG:
2126 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2127 ASN1_OBJECT *alg = NULL;
2128 #else
2129 const ASN1_OBJECT *alg = NULL;
2130 #endif
2132 if (flag == KMF_CERT_SIGNATURE_ALG) {
2133 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2134 alg = xcert->sig_alg->algorithm;
2135 #else
2136 const X509_ALGOR *sig_alg = NULL;
2138 X509_get0_signature(NULL, &sig_alg, xcert);
2139 if (sig_alg != NULL)
2140 X509_ALGOR_get0(&alg, NULL, NULL,
2141 sig_alg);
2142 #endif
2143 } else {
2144 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2145 alg = xcert->cert_info->key->algor->algorithm;
2146 #else
2147 X509_PUBKEY *key = X509_get_X509_PUBKEY(xcert);
2149 if (key != NULL)
2150 (void) X509_PUBKEY_get0_param(
2151 (ASN1_OBJECT **)&alg, NULL, 0,
2152 NULL, key);
2153 #endif
2156 if (alg == NULL)
2157 len = -1;
2158 else if ((len = i2a_ASN1_OBJECT(mem, alg)) > 0)
2159 len = BIO_read(mem, resultStr,
2160 KMF_CERT_PRINTABLE_LEN);
2162 break;
2164 case KMF_CERT_EMAIL:
2165 emlst = X509_get1_email(xcert);
2166 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2167 (void) BIO_printf(mem, "%s\n",
2168 sk_OPENSSL_STRING_value(emlst, j));
2170 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2171 X509_email_free(emlst);
2172 break;
2173 case KMF_X509_EXT_ISSUER_ALTNAME:
2174 case KMF_X509_EXT_SUBJ_ALTNAME:
2175 case KMF_X509_EXT_KEY_USAGE:
2176 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2177 case KMF_X509_EXT_CERT_POLICIES:
2178 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2179 case KMF_X509_EXT_NAME_CONSTRAINTS:
2180 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2181 case KMF_X509_EXT_EXT_KEY_USAGE:
2182 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2183 case KMF_X509_EXT_AUTH_KEY_ID:
2184 case KMF_X509_EXT_SUBJ_KEY_ID:
2185 case KMF_X509_EXT_POLICY_MAPPINGS:
2186 case KMF_X509_EXT_CRL_DIST_POINTS:
2187 case KMF_X509_EXT_FRESHEST_CRL:
2188 nid = ext2NID(flag);
2189 if (nid == NID_undef) {
2190 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2191 goto out;
2194 ext_index = X509_get_ext_by_NID(xcert, nid, -1);
2195 if (ext_index == -1) {
2196 SET_ERROR(kmfh, ERR_get_error());
2198 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2199 goto out;
2201 ex = X509_get_ext(xcert, ext_index);
2203 (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2205 if (BIO_printf(mem, ": %s\n",
2206 X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2207 SET_ERROR(kmfh, ERR_get_error());
2208 ret = KMF_ERR_ENCODING;
2209 goto out;
2211 if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2212 (void) BIO_printf(mem, "%*s", 4, "");
2213 (void) ASN1_STRING_print(mem,
2214 X509_EXTENSION_get_data(ex));
2216 if (BIO_write(mem, "\n", 1) <= 0) {
2217 SET_ERROR(kmfh, ERR_get_error());
2218 ret = KMF_ERR_ENCODING;
2219 goto out;
2221 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2223 if (len <= 0) {
2224 SET_ERROR(kmfh, ERR_get_error());
2225 ret = KMF_ERR_ENCODING;
2228 out:
2229 if (outbuf != NULL) {
2230 free(outbuf);
2233 if (xcert != NULL) {
2234 X509_free(xcert);
2237 if (mem != NULL) {
2238 (void) BIO_free(mem);
2241 return (ret);
2244 KMF_RETURN
2245 /*ARGSUSED*/
2246 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2247 KMF_ATTRIBUTE *attrlist)
2249 KMF_RETURN rv = KMF_OK;
2250 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2251 KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2252 KMF_KEY_HANDLE *key = NULL;
2253 uint32_t numkeys = 1; /* 1 key only */
2254 char *dirpath = NULL;
2255 char *keyfile = NULL;
2256 KMF_ATTRIBUTE new_attrlist[16];
2257 int i = 0;
2260 * This is really just a FindKey operation, reuse the
2261 * FindKey function.
2263 kmf_set_attr_at_index(new_attrlist, i,
2264 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2265 i++;
2267 kmf_set_attr_at_index(new_attrlist, i,
2268 KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2269 i++;
2271 kmf_set_attr_at_index(new_attrlist, i,
2272 KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2273 i++;
2275 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2276 if (key == NULL) {
2277 return (KMF_ERR_BAD_PARAMETER);
2278 } else {
2279 kmf_set_attr_at_index(new_attrlist, i,
2280 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2281 i++;
2284 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2285 if (dirpath != NULL) {
2286 kmf_set_attr_at_index(new_attrlist, i,
2287 KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2288 i++;
2291 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2292 if (keyfile == NULL)
2293 return (KMF_ERR_BAD_PARAMETER);
2294 else {
2295 kmf_set_attr_at_index(new_attrlist, i,
2296 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2297 i++;
2300 rv = OpenSSL_FindKey(handle, i, new_attrlist);
2301 return (rv);
2304 KMF_RETURN
2305 /*ARGSUSED*/
2306 OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2307 KMF_OID *AlgOID, KMF_DATA *ciphertext,
2308 KMF_DATA *output)
2310 KMF_RETURN ret = KMF_OK;
2311 RSA *rsa = NULL;
2312 unsigned int in_len = 0, out_len = 0;
2313 unsigned int total_decrypted = 0, modulus_len = 0;
2314 uint8_t *in_data, *out_data;
2315 int i, blocks;
2317 if (key == NULL || AlgOID == NULL ||
2318 ciphertext == NULL || output == NULL ||
2319 ciphertext->Data == NULL ||
2320 output->Data == NULL)
2321 return (KMF_ERR_BAD_PARAMETER);
2323 if (key->keyalg == KMF_RSA) {
2324 rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2325 modulus_len = RSA_size(rsa);
2326 } else {
2327 return (KMF_ERR_BAD_PARAMETER);
2330 blocks = ciphertext->Length/modulus_len;
2331 out_data = output->Data;
2332 in_data = ciphertext->Data;
2333 out_len = modulus_len - 11;
2334 in_len = modulus_len;
2336 for (i = 0; i < blocks; i++) {
2337 out_len = RSA_private_decrypt(in_len,
2338 in_data, out_data, rsa, RSA_PKCS1_PADDING);
2340 if (out_len == 0) {
2341 ret = KMF_ERR_INTERNAL;
2342 goto cleanup;
2345 out_data += out_len;
2346 total_decrypted += out_len;
2347 in_data += in_len;
2350 output->Length = total_decrypted;
2352 cleanup:
2353 RSA_free(rsa);
2354 if (ret != KMF_OK)
2355 output->Length = 0;
2357 return (ret);
2362 * This function will create a certid from issuer_cert and user_cert.
2363 * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2364 * certid memory after use.
2366 static KMF_RETURN
2367 create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2368 const KMF_DATA *user_cert, OCSP_CERTID **certid)
2370 KMF_RETURN ret = KMF_OK;
2371 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2372 X509 *issuer = NULL;
2373 X509 *cert = NULL;
2374 unsigned char *ptmp;
2376 if (issuer_cert == NULL || user_cert == NULL) {
2377 return (KMF_ERR_BAD_PARAMETER);
2380 /* convert the DER-encoded issuer cert to an internal X509 */
2381 ptmp = issuer_cert->Data;
2382 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2383 issuer_cert->Length);
2384 if (issuer == NULL) {
2385 SET_ERROR(kmfh, ERR_get_error());
2386 ret = KMF_ERR_OCSP_BAD_ISSUER;
2387 goto end;
2390 /* convert the DER-encoded user cert to an internal X509 */
2391 ptmp = user_cert->Data;
2392 cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2393 user_cert->Length);
2394 if (cert == NULL) {
2395 SET_ERROR(kmfh, ERR_get_error());
2397 ret = KMF_ERR_OCSP_BAD_CERT;
2398 goto end;
2401 /* create a CERTID */
2402 *certid = OCSP_cert_to_id(NULL, cert, issuer);
2403 if (*certid == NULL) {
2404 SET_ERROR(kmfh, ERR_get_error());
2405 ret = KMF_ERR_OCSP_CERTID;
2406 goto end;
2409 end:
2410 if (issuer != NULL) {
2411 X509_free(issuer);
2414 if (cert != NULL) {
2415 X509_free(cert);
2418 return (ret);
2421 KMF_RETURN
2422 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2423 int numattr, KMF_ATTRIBUTE *attrlist)
2425 KMF_RETURN ret = KMF_OK;
2426 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2427 OCSP_CERTID *id = NULL;
2428 OCSP_REQUEST *req = NULL;
2429 BIO *derbio = NULL;
2430 char *reqfile;
2431 KMF_DATA *issuer_cert;
2432 KMF_DATA *user_cert;
2434 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2435 attrlist, numattr);
2436 if (user_cert == NULL)
2437 return (KMF_ERR_BAD_PARAMETER);
2439 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2440 attrlist, numattr);
2441 if (issuer_cert == NULL)
2442 return (KMF_ERR_BAD_PARAMETER);
2444 reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2445 attrlist, numattr);
2446 if (reqfile == NULL)
2447 return (KMF_ERR_BAD_PARAMETER);
2449 ret = create_certid(handle, issuer_cert, user_cert, &id);
2450 if (ret != KMF_OK) {
2451 return (ret);
2454 /* Create an OCSP request */
2455 req = OCSP_REQUEST_new();
2456 if (req == NULL) {
2457 SET_ERROR(kmfh, ERR_get_error());
2458 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2459 goto end;
2462 if (!OCSP_request_add0_id(req, id)) {
2463 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2464 goto end;
2467 /* Write the request to the output file with DER encoding */
2468 derbio = BIO_new_file(reqfile, "wb");
2469 if (!derbio) {
2470 SET_ERROR(kmfh, ERR_get_error());
2471 ret = KMF_ERR_OPEN_FILE;
2472 goto end;
2474 if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2475 ret = KMF_ERR_ENCODING;
2478 end:
2480 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2481 * will also deallocate certid's space.
2483 if (req != NULL) {
2484 OCSP_REQUEST_free(req);
2487 if (derbio != NULL) {
2488 (void) BIO_free(derbio);
2491 return (ret);
2494 /* ocsp_find_signer_sk() is copied from openssl source */
2495 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_BASICRESP *bs)
2497 int i;
2498 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2499 const ASN1_OCTET_STRING *pid;
2501 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2502 OCSP_RESPID *id = bs->tbsResponseData->responderId;
2504 if (id->type == V_OCSP_RESPID_NAME)
2505 return (X509_find_by_subject(certs, id->value.byName));
2507 pid = id->value.byKey;
2508 #else
2509 const X509_NAME *pname;
2511 if (OCSP_resp_get0_id(bs, &pid, &pname) == 0)
2512 return (NULL);
2514 if (pname != NULL)
2515 return (X509_find_by_subject(certs, (X509_NAME *)pname));
2516 #endif
2518 /* Lookup by key hash */
2520 /* If key hash isn't SHA1 length then forget it */
2521 if (pid->length != SHA_DIGEST_LENGTH)
2522 return (NULL);
2524 keyhash = pid->data;
2525 /* Calculate hash of each key and compare */
2526 for (i = 0; i < sk_X509_num(certs); i++) {
2527 /* LINTED E_BAD_PTR_CAST_ALIGN */
2528 X509 *x = sk_X509_value(certs, i);
2529 /* Use pubkey_digest to get the key ID value */
2530 (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2531 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2532 return (x);
2534 return (NULL);
2537 /* ocsp_find_signer() is copied from openssl source */
2538 /* ARGSUSED2 */
2539 static int
2540 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2541 X509_STORE *st, unsigned long flags)
2543 X509 *signer;
2544 if ((signer = ocsp_find_signer_sk(certs, bs))) {
2545 *psigner = signer;
2546 return (2);
2549 if (!(flags & OCSP_NOINTERN) &&
2550 (signer = ocsp_find_signer_sk(
2551 (STACK_OF(X509) *)OCSP_resp_get0_certs(bs), bs))) {
2552 *psigner = signer;
2553 return (1);
2555 /* Maybe lookup from store if by subject name */
2557 *psigner = NULL;
2558 return (0);
2562 * This function will verify the signature of a basic response, using
2563 * the public key from the OCSP responder certificate.
2565 static KMF_RETURN
2566 check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2567 KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2569 KMF_RETURN ret = KMF_OK;
2570 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2571 STACK_OF(X509) *cert_stack = NULL;
2572 X509 *signer = NULL;
2573 X509 *issuer = NULL;
2574 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2575 EVP_PKEY *skey = NULL;
2576 #else
2577 STACK_OF(X509) *cert_stack2 = NULL;
2578 #endif
2579 unsigned char *ptmp;
2581 if (bs == NULL || issuer_cert == NULL)
2582 return (KMF_ERR_BAD_PARAMETER);
2585 * Find the certificate that signed the basic response.
2587 * If signer_cert is not NULL, we will use that as the signer cert.
2588 * Otherwise, we will check if the issuer cert is actually the signer.
2589 * If we still do not find a signer, we will look for it from the
2590 * certificate list came with the response file.
2592 if (signer_cert != NULL) {
2593 ptmp = signer_cert->Data;
2594 signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2595 signer_cert->Length);
2596 if (signer == NULL) {
2597 SET_ERROR(kmfh, ERR_get_error());
2598 ret = KMF_ERR_OCSP_BAD_SIGNER;
2599 goto end;
2601 } else {
2603 * Convert the issuer cert into X509 and push it into a
2604 * stack to be used by ocsp_find_signer().
2606 ptmp = issuer_cert->Data;
2607 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2608 issuer_cert->Length);
2609 if (issuer == NULL) {
2610 SET_ERROR(kmfh, ERR_get_error());
2611 ret = KMF_ERR_OCSP_BAD_ISSUER;
2612 goto end;
2615 if ((cert_stack = sk_X509_new_null()) == NULL) {
2616 ret = KMF_ERR_INTERNAL;
2617 goto end;
2620 if (sk_X509_push(cert_stack, issuer) == NULL) {
2621 ret = KMF_ERR_INTERNAL;
2622 goto end;
2625 ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2626 if (!ret) {
2627 /* can not find the signer */
2628 ret = KMF_ERR_OCSP_BAD_SIGNER;
2629 goto end;
2633 /* Verify the signature of the response */
2634 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2635 skey = X509_get_pubkey(signer);
2636 if (skey == NULL) {
2637 ret = KMF_ERR_OCSP_BAD_SIGNER;
2638 goto end;
2641 ret = OCSP_BASICRESP_verify(bs, skey, 0);
2642 #else
2644 * Technique based on
2645 * https://mta.openssl.org/pipermail/openssl-users/
2646 * 2017-October/006814.html
2648 if ((cert_stack2 = sk_X509_new_null()) == NULL) {
2649 ret = KMF_ERR_INTERNAL;
2650 goto end;
2653 if (sk_X509_push(cert_stack2, signer) == NULL) {
2654 ret = KMF_ERR_INTERNAL;
2655 goto end;
2658 ret = OCSP_basic_verify(bs, cert_stack2, NULL, OCSP_NOVERIFY);
2659 #endif
2661 if (ret == 0) {
2662 ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2663 goto end;
2666 end:
2667 if (issuer != NULL) {
2668 X509_free(issuer);
2671 if (signer != NULL) {
2672 X509_free(signer);
2675 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2676 if (skey != NULL) {
2677 EVP_PKEY_free(skey);
2679 #else
2680 if (cert_stack2 != NULL) {
2681 sk_X509_free(cert_stack2);
2683 #endif
2685 if (cert_stack != NULL) {
2686 sk_X509_free(cert_stack);
2689 return (ret);
2692 KMF_RETURN
2693 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2694 int numattr, KMF_ATTRIBUTE *attrlist)
2696 KMF_RETURN ret = KMF_OK;
2697 BIO *derbio = NULL;
2698 OCSP_RESPONSE *resp = NULL;
2699 OCSP_BASICRESP *bs = NULL;
2700 OCSP_CERTID *id = NULL;
2701 OCSP_SINGLERESP *single = NULL;
2702 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2703 int index, status, reason;
2704 KMF_DATA *issuer_cert;
2705 KMF_DATA *user_cert;
2706 KMF_DATA *signer_cert;
2707 KMF_DATA *response;
2708 int *response_reason, *response_status, *cert_status;
2709 boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
2710 uint32_t response_lifetime;
2712 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2713 attrlist, numattr);
2714 if (issuer_cert == NULL)
2715 return (KMF_ERR_BAD_PARAMETER);
2717 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2718 attrlist, numattr);
2719 if (user_cert == NULL)
2720 return (KMF_ERR_BAD_PARAMETER);
2722 response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2723 attrlist, numattr);
2724 if (response == NULL)
2725 return (KMF_ERR_BAD_PARAMETER);
2727 response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2728 attrlist, numattr);
2729 if (response_status == NULL)
2730 return (KMF_ERR_BAD_PARAMETER);
2732 response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2733 attrlist, numattr);
2734 if (response_reason == NULL)
2735 return (KMF_ERR_BAD_PARAMETER);
2737 cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2738 attrlist, numattr);
2739 if (cert_status == NULL)
2740 return (KMF_ERR_BAD_PARAMETER);
2742 /* Read in the response */
2743 derbio = BIO_new_mem_buf(response->Data, response->Length);
2744 if (!derbio) {
2745 ret = KMF_ERR_MEMORY;
2746 return (ret);
2749 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2750 if (resp == NULL) {
2751 ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2752 goto end;
2755 /* Check the response status */
2756 status = OCSP_response_status(resp);
2757 *response_status = status;
2758 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2759 ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2760 goto end;
2763 #ifdef DEBUG
2764 printf("Successfully checked the response file status.\n");
2765 #endif /* DEBUG */
2767 /* Extract basic response */
2768 bs = OCSP_response_get1_basic(resp);
2769 if (bs == NULL) {
2770 ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2771 goto end;
2774 #ifdef DEBUG
2775 printf("Successfully retrieved the basic response.\n");
2776 #endif /* DEBUG */
2778 /* Check the basic response signature if required */
2779 ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2780 (void *)&ignore_response_sign, NULL);
2781 if (ret != KMF_OK)
2782 ret = KMF_OK;
2784 signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2785 attrlist, numattr);
2787 if (ignore_response_sign == B_FALSE) {
2788 ret = check_response_signature(handle, bs,
2789 signer_cert, issuer_cert);
2790 if (ret != KMF_OK)
2791 goto end;
2794 #ifdef DEBUG
2795 printf("Successfully verified the response signature.\n");
2796 #endif /* DEBUG */
2798 /* Create a certid for the certificate in question */
2799 ret = create_certid(handle, issuer_cert, user_cert, &id);
2800 if (ret != KMF_OK) {
2801 ret = KMF_ERR_OCSP_CERTID;
2802 goto end;
2805 #ifdef DEBUG
2806 printf("successfully created a certid for the cert.\n");
2807 #endif /* DEBUG */
2809 /* Find the index of the single response for the certid */
2810 index = OCSP_resp_find(bs, id, -1);
2811 if (index < 0) {
2812 /* cound not find this certificate in the response */
2813 ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2814 goto end;
2817 #ifdef DEBUG
2818 printf("Successfully found the single response index for the cert.\n");
2819 #endif /* DEBUG */
2821 /* Retrieve the single response and get the cert status */
2822 single = OCSP_resp_get0(bs, index);
2823 status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2824 &nextupd);
2825 if (status == V_OCSP_CERTSTATUS_GOOD) {
2826 *cert_status = OCSP_GOOD;
2827 } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2828 *cert_status = OCSP_UNKNOWN;
2829 } else { /* revoked */
2830 *cert_status = OCSP_REVOKED;
2831 *response_reason = reason;
2833 ret = KMF_OK;
2835 /* resp. time is optional, so we don't care about the return code. */
2836 (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2837 (void *)&response_lifetime, NULL);
2839 if (!OCSP_check_validity(thisupd, nextupd, 300,
2840 response_lifetime)) {
2841 ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2842 goto end;
2845 #ifdef DEBUG
2846 printf("Successfully verify the time.\n");
2847 #endif /* DEBUG */
2849 end:
2850 if (derbio != NULL)
2851 (void) BIO_free(derbio);
2853 if (resp != NULL)
2854 OCSP_RESPONSE_free(resp);
2856 if (bs != NULL)
2857 OCSP_BASICRESP_free(bs);
2859 if (id != NULL)
2860 OCSP_CERTID_free(id);
2862 return (ret);
2865 static KMF_RETURN
2866 fetch_key(KMF_HANDLE_T handle, char *path,
2867 KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2869 KMF_RETURN rv = KMF_OK;
2870 EVP_PKEY *pkey = NULL;
2871 KMF_RAW_SYM_KEY *rkey = NULL;
2873 if (keyclass == KMF_ASYM_PRI ||
2874 keyclass == KMF_ASYM_PUB) {
2875 pkey = openssl_load_key(handle, path);
2876 if (pkey == NULL) {
2877 return (KMF_ERR_KEY_NOT_FOUND);
2879 if (key != NULL) {
2880 if (EVP_PKEY_get0_RSA(pkey) != NULL)
2881 key->keyalg = KMF_RSA;
2882 else if (EVP_PKEY_get0_DSA(pkey) != NULL)
2883 key->keyalg = KMF_DSA;
2885 key->kstype = KMF_KEYSTORE_OPENSSL;
2886 key->keyclass = keyclass;
2887 key->keyp = (void *)pkey;
2888 key->israw = FALSE;
2889 if (path != NULL &&
2890 ((key->keylabel = strdup(path)) == NULL)) {
2891 EVP_PKEY_free(pkey);
2892 return (KMF_ERR_MEMORY);
2894 } else {
2895 EVP_PKEY_free(pkey);
2896 pkey = NULL;
2898 } else if (keyclass == KMF_SYMMETRIC) {
2899 KMF_ENCODE_FORMAT fmt;
2901 * If the file is a recognized format,
2902 * then it is NOT a symmetric key.
2904 rv = kmf_get_file_format(path, &fmt);
2905 if (rv == KMF_OK || fmt != 0) {
2906 return (KMF_ERR_KEY_NOT_FOUND);
2907 } else if (rv == KMF_ERR_ENCODING) {
2909 * If we don't know the encoding,
2910 * it is probably a symmetric key.
2912 rv = KMF_OK;
2913 } else if (rv == KMF_ERR_OPEN_FILE) {
2914 return (KMF_ERR_KEY_NOT_FOUND);
2917 if (key != NULL) {
2918 KMF_DATA keyvalue;
2919 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2920 if (rkey == NULL) {
2921 rv = KMF_ERR_MEMORY;
2922 goto out;
2925 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2926 rv = kmf_read_input_file(handle, path, &keyvalue);
2927 if (rv != KMF_OK)
2928 goto out;
2930 rkey->keydata.len = keyvalue.Length;
2931 rkey->keydata.val = keyvalue.Data;
2933 key->kstype = KMF_KEYSTORE_OPENSSL;
2934 key->keyclass = keyclass;
2935 key->israw = TRUE;
2936 key->keyp = (void *)rkey;
2937 if (path != NULL &&
2938 ((key->keylabel = strdup(path)) == NULL)) {
2939 rv = KMF_ERR_MEMORY;
2943 out:
2944 if (rv != KMF_OK) {
2945 if (rkey != NULL) {
2946 kmf_free_raw_sym_key(rkey);
2948 if (pkey != NULL)
2949 EVP_PKEY_free(pkey);
2951 if (key != NULL) {
2952 key->keyalg = KMF_KEYALG_NONE;
2953 key->keyclass = KMF_KEYCLASS_NONE;
2954 key->keyp = NULL;
2958 return (rv);
2961 KMF_RETURN
2962 OpenSSL_FindKey(KMF_HANDLE_T handle,
2963 int numattr, KMF_ATTRIBUTE *attrlist)
2965 KMF_RETURN rv = KMF_OK;
2966 char *fullpath = NULL;
2967 uint32_t maxkeys;
2968 KMF_KEY_HANDLE *key;
2969 uint32_t *numkeys;
2970 KMF_KEY_CLASS keyclass;
2971 KMF_RAW_KEY_DATA *rawkey;
2972 char *dirpath;
2973 char *keyfile;
2975 if (handle == NULL)
2976 return (KMF_ERR_BAD_PARAMETER);
2978 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2979 if (numkeys == NULL)
2980 return (KMF_ERR_BAD_PARAMETER);
2982 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2983 (void *)&keyclass, NULL);
2984 if (rv != KMF_OK)
2985 return (KMF_ERR_BAD_PARAMETER);
2987 if (keyclass != KMF_ASYM_PUB &&
2988 keyclass != KMF_ASYM_PRI &&
2989 keyclass != KMF_SYMMETRIC)
2990 return (KMF_ERR_BAD_KEY_CLASS);
2992 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2993 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2995 fullpath = get_fullpath(dirpath, keyfile);
2997 if (fullpath == NULL)
2998 return (KMF_ERR_BAD_PARAMETER);
3000 maxkeys = *numkeys;
3001 if (maxkeys == 0)
3002 maxkeys = 0xFFFFFFFF;
3003 *numkeys = 0;
3005 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
3006 /* it is okay to have "keys" contains NULL */
3009 * The caller may want a list of the raw key data as well.
3010 * Useful for importing keys from a file into other keystores.
3012 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
3014 if (isdir(fullpath)) {
3015 DIR *dirp;
3016 struct dirent *dp;
3017 int n = 0;
3019 /* open all files in the directory and attempt to read them */
3020 if ((dirp = opendir(fullpath)) == NULL) {
3021 return (KMF_ERR_BAD_PARAMETER);
3023 rewinddir(dirp);
3024 while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
3025 if (strcmp(dp->d_name, ".") &&
3026 strcmp(dp->d_name, "..")) {
3027 char *fname;
3029 fname = get_fullpath(fullpath,
3030 (char *)&dp->d_name);
3032 rv = fetch_key(handle, fname,
3033 keyclass, key ? &key[n] : NULL);
3035 if (rv == KMF_OK) {
3036 if (key != NULL && rawkey != NULL)
3037 rv = convertToRawKey(
3038 key[n].keyp, &rawkey[n]);
3039 n++;
3042 if (rv != KMF_OK || key == NULL)
3043 free(fname);
3046 (void) closedir(dirp);
3047 free(fullpath);
3048 (*numkeys) = n;
3049 } else {
3050 rv = fetch_key(handle, fullpath, keyclass, key);
3051 if (rv == KMF_OK)
3052 (*numkeys) = 1;
3054 if (rv != KMF_OK || key == NULL)
3055 free(fullpath);
3057 if (rv == KMF_OK && key != NULL && rawkey != NULL) {
3058 rv = convertToRawKey(key->keyp, rawkey);
3062 if (rv == KMF_OK && (*numkeys) == 0)
3063 rv = KMF_ERR_KEY_NOT_FOUND;
3064 else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
3065 rv = KMF_OK;
3067 return (rv);
3070 #define HANDLE_PK12_ERROR { \
3071 SET_ERROR(kmfh, ERR_get_error()); \
3072 rv = KMF_ERR_ENCODING; \
3073 goto out; \
3076 static int
3077 add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3079 unsigned char *alias;
3080 int len;
3082 if (xcert != NULL && (alias = X509_alias_get0(xcert, &len)) != NULL) {
3083 if (PKCS12_add_friendlyname_asc(bag,
3084 (const char *)alias, len) == 0)
3085 return (0);
3087 return (1);
3090 static PKCS7 *
3091 add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3092 uchar_t *keyid, unsigned int keyidlen)
3094 PKCS12_SAFEBAG *bag = NULL;
3095 PKCS7 *cert_authsafe = NULL;
3096 STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3098 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3099 if (bag_stack == NULL)
3100 return (NULL);
3102 /* Convert cert from X509 struct to PKCS#12 bag */
3103 bag = PKCS12_SAFEBAG_create_cert(sslcert);
3104 if (bag == NULL) {
3105 goto out;
3108 /* Add the key id to the certificate bag. */
3109 if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3110 goto out;
3113 if (!add_alias_to_bag(bag, sslcert))
3114 goto out;
3116 /* Pile it on the bag_stack. */
3117 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3118 goto out;
3120 /* Turn bag_stack of certs into encrypted authsafe. */
3121 cert_authsafe = PKCS12_pack_p7encdata(
3122 NID_pbe_WithSHA1And40BitRC2_CBC,
3123 cred->cred, cred->credlen, NULL, 0,
3124 PKCS12_DEFAULT_ITER, bag_stack);
3126 out:
3127 if (bag_stack != NULL)
3128 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3130 return (cert_authsafe);
3133 static PKCS7 *
3134 add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3135 uchar_t *keyid, unsigned int keyidlen,
3136 char *label, int label_len)
3138 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3139 STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3140 PKCS12_SAFEBAG *bag = NULL;
3141 PKCS7 *key_authsafe = NULL;
3143 p8 = EVP_PKEY2PKCS8(pkey);
3144 if (p8 == NULL) {
3145 return (NULL);
3147 /* Put the shrouded key into a PKCS#12 bag. */
3148 bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(
3149 NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3150 cred->cred, cred->credlen,
3151 NULL, 0, PKCS12_DEFAULT_ITER, p8);
3153 /* Clean up the PKCS#8 shrouded key, don't need it now. */
3154 PKCS8_PRIV_KEY_INFO_free(p8);
3155 p8 = NULL;
3157 if (bag == NULL) {
3158 return (NULL);
3160 if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3161 goto out;
3162 if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3163 goto out;
3165 /* Start a PKCS#12 safebag container for the private key. */
3166 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3167 if (bag_stack == NULL)
3168 goto out;
3170 /* Pile on the private key on the bag_stack. */
3171 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3172 goto out;
3174 key_authsafe = PKCS12_pack_p7data(bag_stack);
3176 out:
3177 if (bag_stack != NULL)
3178 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3179 bag_stack = NULL;
3180 return (key_authsafe);
3183 static EVP_PKEY *
3184 ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3186 RSA *rsa = NULL;
3187 EVP_PKEY *newkey = NULL;
3188 BIGNUM *n = NULL, *e = NULL, *d = NULL,
3189 *p = NULL, *q = NULL,
3190 *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
3192 if ((rsa = RSA_new()) == NULL)
3193 goto cleanup;
3195 if ((n = BN_bin2bn(key->mod.val, key->mod.len, NULL)) == NULL)
3196 goto cleanup;
3198 if ((e = BN_bin2bn(key->pubexp.val, key->pubexp.len, NULL)) == NULL)
3199 goto cleanup;
3201 if (key->priexp.val != NULL &&
3202 (d = BN_bin2bn(key->priexp.val, key->priexp.len, NULL)) == NULL)
3203 goto cleanup;
3205 if (key->prime1.val != NULL &&
3206 (p = BN_bin2bn(key->prime1.val, key->prime1.len, NULL)) == NULL)
3207 goto cleanup;
3209 if (key->prime2.val != NULL &&
3210 (q = BN_bin2bn(key->prime2.val, key->prime2.len, NULL)) == NULL)
3211 goto cleanup;
3213 if (key->exp1.val != NULL &&
3214 (dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len, NULL)) == NULL)
3215 goto cleanup;
3217 if (key->exp2.val != NULL &&
3218 (dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len, NULL)) == NULL)
3219 goto cleanup;
3221 if (key->coef.val != NULL &&
3222 (iqmp = BN_bin2bn(key->coef.val, key->coef.len, NULL)) == NULL)
3223 goto cleanup;
3225 if (RSA_set0_key(rsa, n, e, d) == 0)
3226 goto cleanup;
3227 n = e = d = NULL;
3228 if (RSA_set0_factors(rsa, p, q) == 0)
3229 goto cleanup;
3230 p = q = NULL;
3231 if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)
3232 goto cleanup;
3233 dmp1 = dmq1 = iqmp = NULL;
3235 if ((newkey = EVP_PKEY_new()) == NULL)
3236 goto cleanup;
3238 (void) EVP_PKEY_set1_RSA(newkey, rsa);
3240 cleanup:
3241 /* The original key must be freed once here or it leaks memory */
3242 if (rsa)
3243 RSA_free(rsa);
3244 BN_free(n);
3245 BN_free(e);
3246 BN_free(d);
3247 BN_free(p);
3248 BN_free(q);
3249 BN_free(dmp1);
3250 BN_free(dmq1);
3251 BN_free(iqmp);
3253 return (newkey);
3256 static EVP_PKEY *
3257 ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3259 DSA *dsa = NULL;
3260 EVP_PKEY *newkey = NULL;
3261 BIGNUM *p = NULL, *q = NULL, *g = NULL,
3262 *priv_key = NULL, *pub_key = NULL;
3264 if ((dsa = DSA_new()) == NULL)
3265 goto cleanup;
3267 if ((p = BN_bin2bn(key->prime.val, key->prime.len, NULL)) == NULL)
3268 goto cleanup;
3270 if ((q = BN_bin2bn(key->subprime.val, key->subprime.len, NULL)) == NULL)
3271 goto cleanup;
3273 if ((g = BN_bin2bn(key->base.val, key->base.len, NULL)) == NULL)
3274 goto cleanup;
3276 if ((priv_key = BN_bin2bn(key->value.val, key->value.len,
3277 NULL)) == NULL)
3278 goto cleanup;
3280 if (key->pubvalue.val != NULL && (pub_key =
3281 BN_bin2bn(key->pubvalue.val, key->pubvalue.len, NULL)) == NULL)
3282 goto cleanup;
3284 if (DSA_set0_pqg(dsa, p, q, g) == 0)
3285 goto cleanup;
3286 p = q = g = NULL;
3287 if (DSA_set0_key(dsa, pub_key, priv_key) == 0)
3288 goto cleanup;
3289 pub_key = priv_key = 0;
3291 if ((newkey = EVP_PKEY_new()) == NULL)
3292 goto cleanup;
3294 (void) EVP_PKEY_set1_DSA(newkey, dsa);
3296 cleanup:
3297 /* The original key must be freed once here or it leaks memory */
3298 if (dsa)
3299 DSA_free(dsa);
3300 BN_free(p);
3301 BN_free(q);
3302 BN_free(g);
3303 BN_free(priv_key);
3304 BN_free(pub_key);
3306 return (newkey);
3309 static EVP_PKEY *
3310 raw_key_to_pkey(KMF_KEY_HANDLE *key)
3312 EVP_PKEY *pkey = NULL;
3313 KMF_RAW_KEY_DATA *rawkey;
3314 ASN1_TYPE *attr = NULL;
3315 KMF_RETURN ret;
3317 if (key == NULL || !key->israw)
3318 return (NULL);
3320 rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3321 if (rawkey->keytype == KMF_RSA) {
3322 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3323 } else if (rawkey->keytype == KMF_DSA) {
3324 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3325 } else if (rawkey->keytype == KMF_ECDSA) {
3327 * OpenSSL in Solaris does not support EC for
3328 * legal reasons
3330 return (NULL);
3331 } else {
3332 /* wrong kind of key */
3333 return (NULL);
3336 if (rawkey->label != NULL) {
3337 if ((attr = ASN1_TYPE_new()) == NULL) {
3338 EVP_PKEY_free(pkey);
3339 return (NULL);
3341 attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3342 (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3343 strlen(rawkey->label));
3344 attr->type = V_ASN1_BMPSTRING;
3345 attr->value.ptr = (char *)attr->value.bmpstring;
3346 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3347 if (ret != KMF_OK) {
3348 EVP_PKEY_free(pkey);
3349 ASN1_TYPE_free(attr);
3350 return (NULL);
3353 if (rawkey->id.Data != NULL) {
3354 if ((attr = ASN1_TYPE_new()) == NULL) {
3355 EVP_PKEY_free(pkey);
3356 return (NULL);
3358 attr->value.octet_string =
3359 ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3360 attr->type = V_ASN1_OCTET_STRING;
3361 (void) ASN1_STRING_set(attr->value.octet_string,
3362 rawkey->id.Data, rawkey->id.Length);
3363 attr->value.ptr = (char *)attr->value.octet_string;
3364 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3365 if (ret != KMF_OK) {
3366 EVP_PKEY_free(pkey);
3367 ASN1_TYPE_free(attr);
3368 return (NULL);
3371 return (pkey);
3375 * Search a list of private keys to find one that goes with the certificate.
3377 static EVP_PKEY *
3378 find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3380 int i;
3381 EVP_PKEY *pkey = NULL;
3383 if (numkeys == 0 || keylist == NULL || xcert == NULL)
3384 return (NULL);
3385 for (i = 0; i < numkeys; i++) {
3386 if (keylist[i].israw)
3387 pkey = raw_key_to_pkey(&keylist[i]);
3388 else
3389 pkey = (EVP_PKEY *)keylist[i].keyp;
3390 if (pkey != NULL) {
3391 if (X509_check_private_key(xcert, pkey)) {
3392 return (pkey);
3393 } else {
3394 EVP_PKEY_free(pkey);
3395 pkey = NULL;
3399 return (pkey);
3402 static KMF_RETURN
3403 local_export_pk12(KMF_HANDLE_T handle,
3404 KMF_CREDENTIAL *cred,
3405 int numcerts, KMF_X509_DER_CERT *certlist,
3406 int numkeys, KMF_KEY_HANDLE *keylist,
3407 char *filename)
3409 KMF_RETURN rv = KMF_OK;
3410 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3411 BIO *bio = NULL;
3412 PKCS7 *cert_authsafe = NULL;
3413 PKCS7 *key_authsafe = NULL;
3414 STACK_OF(PKCS7) *authsafe_stack = NULL;
3415 PKCS12 *p12_elem = NULL;
3416 int i;
3418 if (numcerts == 0 && numkeys == 0)
3419 return (KMF_ERR_BAD_PARAMETER);
3422 * Open the output file.
3424 if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3425 SET_ERROR(kmfh, ERR_get_error());
3426 rv = KMF_ERR_OPEN_FILE;
3427 goto cleanup;
3430 /* Start a PKCS#7 stack. */
3431 authsafe_stack = sk_PKCS7_new_null();
3432 if (authsafe_stack == NULL) {
3433 rv = KMF_ERR_MEMORY;
3434 goto cleanup;
3436 if (numcerts > 0) {
3437 for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3438 const uchar_t *p = certlist[i].certificate.Data;
3439 long len = certlist[i].certificate.Length;
3440 X509 *xcert = NULL;
3441 EVP_PKEY *pkey = NULL;
3442 unsigned char keyid[EVP_MAX_MD_SIZE];
3443 unsigned int keyidlen = 0;
3445 xcert = d2i_X509(NULL, &p, len);
3446 if (xcert == NULL) {
3447 SET_ERROR(kmfh, ERR_get_error());
3448 rv = KMF_ERR_ENCODING;
3450 if (certlist[i].kmf_private.label != NULL) {
3451 /* Set alias attribute */
3452 (void) X509_alias_set1(xcert,
3453 (uchar_t *)certlist[i].kmf_private.label,
3454 strlen(certlist[i].kmf_private.label));
3456 /* Check if there is a key corresponding to this cert */
3457 pkey = find_matching_key(xcert, numkeys, keylist);
3460 * If key is found, get fingerprint and create a
3461 * safebag.
3463 if (pkey != NULL) {
3464 (void) X509_digest(xcert, EVP_sha1(),
3465 keyid, &keyidlen);
3466 key_authsafe = add_key_to_safe(pkey, cred,
3467 keyid, keyidlen,
3468 certlist[i].kmf_private.label,
3469 (certlist[i].kmf_private.label ?
3470 strlen(certlist[i].kmf_private.label) : 0));
3472 if (key_authsafe == NULL) {
3473 X509_free(xcert);
3474 EVP_PKEY_free(pkey);
3475 goto cleanup;
3477 /* Put the key safe into the Auth Safe */
3478 if (!sk_PKCS7_push(authsafe_stack,
3479 key_authsafe)) {
3480 X509_free(xcert);
3481 EVP_PKEY_free(pkey);
3482 goto cleanup;
3486 /* create a certificate safebag */
3487 cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3488 keyidlen);
3489 if (cert_authsafe == NULL) {
3490 X509_free(xcert);
3491 EVP_PKEY_free(pkey);
3492 goto cleanup;
3494 if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3495 X509_free(xcert);
3496 EVP_PKEY_free(pkey);
3497 goto cleanup;
3500 X509_free(xcert);
3501 if (pkey)
3502 EVP_PKEY_free(pkey);
3504 } else if (numcerts == 0 && numkeys > 0) {
3506 * If only adding keys to the file.
3508 for (i = 0; i < numkeys; i++) {
3509 EVP_PKEY *pkey = NULL;
3511 if (keylist[i].israw)
3512 pkey = raw_key_to_pkey(&keylist[i]);
3513 else
3514 pkey = (EVP_PKEY *)keylist[i].keyp;
3516 if (pkey == NULL)
3517 continue;
3519 key_authsafe = add_key_to_safe(pkey, cred,
3520 NULL, 0, NULL, 0);
3522 if (key_authsafe == NULL) {
3523 EVP_PKEY_free(pkey);
3524 goto cleanup;
3526 if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3527 EVP_PKEY_free(pkey);
3528 goto cleanup;
3532 p12_elem = PKCS12_init(NID_pkcs7_data);
3533 if (p12_elem == NULL) {
3534 goto cleanup;
3537 /* Put the PKCS#7 stack into the PKCS#12 element. */
3538 if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3539 goto cleanup;
3542 /* Set the integrity MAC on the PKCS#12 element. */
3543 if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3544 NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3545 goto cleanup;
3548 /* Write the PKCS#12 element to the export file. */
3549 if (!i2d_PKCS12_bio(bio, p12_elem)) {
3550 goto cleanup;
3552 PKCS12_free(p12_elem);
3554 cleanup:
3555 /* Clear away the PKCS#7 stack, we're done with it. */
3556 if (authsafe_stack)
3557 sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3559 if (bio != NULL)
3560 (void) BIO_free_all(bio);
3562 return (rv);
3565 KMF_RETURN
3566 openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3567 KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3568 KMF_CREDENTIAL *p12cred, char *filename)
3570 KMF_RETURN rv;
3572 if (certlist == NULL && keylist == NULL)
3573 return (KMF_ERR_BAD_PARAMETER);
3575 rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3576 numkeys, keylist, filename);
3578 return (rv);
3581 KMF_RETURN
3582 OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3584 KMF_RETURN rv;
3585 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3586 char *fullpath = NULL;
3587 char *dirpath = NULL;
3588 char *certfile = NULL;
3589 char *keyfile = NULL;
3590 char *filename = NULL;
3591 KMF_CREDENTIAL *p12cred = NULL;
3592 KMF_X509_DER_CERT certdata;
3593 KMF_KEY_HANDLE key;
3594 int gotkey = 0;
3595 int gotcert = 0;
3597 if (handle == NULL)
3598 return (KMF_ERR_BAD_PARAMETER);
3601 * First, find the certificate.
3603 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3604 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3605 if (certfile != NULL) {
3606 fullpath = get_fullpath(dirpath, certfile);
3607 if (fullpath == NULL)
3608 return (KMF_ERR_BAD_PARAMETER);
3610 if (isdir(fullpath)) {
3611 free(fullpath);
3612 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3615 (void) memset(&certdata, 0, sizeof (certdata));
3616 rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3617 fullpath, &certdata.certificate);
3618 if (rv != KMF_OK)
3619 goto end;
3621 gotcert++;
3622 certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3623 free(fullpath);
3627 * Now find the private key.
3629 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3630 if (keyfile != NULL) {
3631 fullpath = get_fullpath(dirpath, keyfile);
3632 if (fullpath == NULL)
3633 return (KMF_ERR_BAD_PARAMETER);
3635 if (isdir(fullpath)) {
3636 free(fullpath);
3637 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3640 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3641 rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3642 if (rv != KMF_OK)
3643 goto end;
3644 gotkey++;
3648 * Open the output file.
3650 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3651 numattr);
3652 if (filename == NULL) {
3653 rv = KMF_ERR_BAD_PARAMETER;
3654 goto end;
3657 /* Stick the key and the cert into a PKCS#12 file */
3658 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3659 if (p12cred == NULL) {
3660 rv = KMF_ERR_BAD_PARAMETER;
3661 goto end;
3664 rv = local_export_pk12(handle, p12cred, 1, &certdata,
3665 1, &key, filename);
3667 end:
3668 if (fullpath)
3669 free(fullpath);
3671 if (gotcert)
3672 kmf_free_kmf_cert(handle, &certdata);
3673 if (gotkey)
3674 kmf_free_kmf_key(handle, &key);
3675 return (rv);
3679 * Helper function to extract keys and certificates from
3680 * a single PEM file. Typically the file should contain a
3681 * private key and an associated public key wrapped in an x509 cert.
3682 * However, the file may be just a list of X509 certs with no keys.
3684 static KMF_RETURN
3685 extract_pem(KMF_HANDLE *kmfh,
3686 char *issuer, char *subject, KMF_BIGINT *serial,
3687 char *filename, CK_UTF8CHAR *pin,
3688 CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3689 int *numcerts)
3690 /* ARGSUSED6 */
3692 KMF_RETURN rv = KMF_OK;
3693 FILE *fp;
3694 STACK_OF(X509_INFO) *x509_info_stack = NULL;
3695 int i, ncerts = 0, matchcerts = 0;
3696 EVP_PKEY *pkey = NULL;
3697 X509_INFO *info;
3698 X509 *x;
3699 X509_INFO **cert_infos = NULL;
3700 KMF_DATA *certlist = NULL;
3702 if (priv_key)
3703 *priv_key = NULL;
3704 if (certs)
3705 *certs = NULL;
3706 fp = fopen(filename, "r");
3707 if (fp == NULL)
3708 return (KMF_ERR_OPEN_FILE);
3710 x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3711 if (x509_info_stack == NULL) {
3712 (void) fclose(fp);
3713 return (KMF_ERR_ENCODING);
3715 cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3716 sizeof (X509_INFO *));
3717 if (cert_infos == NULL) {
3718 (void) fclose(fp);
3719 rv = KMF_ERR_MEMORY;
3720 goto err;
3723 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3724 /* LINTED E_BAD_PTR_CAST_ALIGN */
3725 cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
3726 ncerts++;
3729 if (ncerts == 0) {
3730 (void) fclose(fp);
3731 rv = KMF_ERR_CERT_NOT_FOUND;
3732 goto err;
3735 if (priv_key != NULL) {
3736 rewind(fp);
3737 pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
3739 (void) fclose(fp);
3741 x = cert_infos[ncerts - 1]->x509;
3743 * Make sure the private key matchs the last cert in the file.
3745 if (pkey != NULL && !X509_check_private_key(x, pkey)) {
3746 EVP_PKEY_free(pkey);
3747 rv = KMF_ERR_KEY_MISMATCH;
3748 goto err;
3751 certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
3752 if (certlist == NULL) {
3753 if (pkey != NULL)
3754 EVP_PKEY_free(pkey);
3755 rv = KMF_ERR_MEMORY;
3756 goto err;
3760 * Convert all of the certs to DER format.
3762 matchcerts = 0;
3763 for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
3764 boolean_t match = FALSE;
3765 info = cert_infos[ncerts - 1 - i];
3767 rv = check_cert(info->x509, issuer, subject, serial, &match);
3768 if (rv != KMF_OK || match != TRUE) {
3769 rv = KMF_OK;
3770 continue;
3773 rv = ssl_cert2KMFDATA(kmfh, info->x509,
3774 &certlist[matchcerts++]);
3776 if (rv != KMF_OK) {
3777 int j;
3778 for (j = 0; j < matchcerts; j++)
3779 kmf_free_data(&certlist[j]);
3780 free(certlist);
3781 certlist = NULL;
3782 ncerts = matchcerts = 0;
3786 if (numcerts != NULL)
3787 *numcerts = matchcerts;
3789 if (certs != NULL)
3790 *certs = certlist;
3791 else if (certlist != NULL) {
3792 for (i = 0; i < ncerts; i++)
3793 kmf_free_data(&certlist[i]);
3794 free(certlist);
3795 certlist = NULL;
3798 if (priv_key == NULL && pkey != NULL)
3799 EVP_PKEY_free(pkey);
3800 else if (priv_key != NULL && pkey != NULL)
3801 *priv_key = pkey;
3803 err:
3804 /* Cleanup the stack of X509 info records */
3805 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3806 /* LINTED E_BAD_PTR_CAST_ALIGN */
3807 info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3808 X509_INFO_free(info);
3810 if (x509_info_stack)
3811 sk_X509_INFO_free(x509_info_stack);
3813 if (cert_infos != NULL)
3814 free(cert_infos);
3816 return (rv);
3819 static KMF_RETURN
3820 openssl_parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3821 STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3823 KMF_RETURN ret;
3824 int i;
3826 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3827 /* LINTED E_BAD_PTR_CAST_ALIGN */
3828 PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3829 ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3830 keys, certs);
3832 if (ret != KMF_OK)
3833 return (ret);
3836 return (ret);
3839 static KMF_RETURN
3840 set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3842 X509_ATTRIBUTE *attr = NULL;
3844 if (pkey == NULL || attrib == NULL)
3845 return (KMF_ERR_BAD_PARAMETER);
3847 attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3848 if (attr != NULL) {
3849 int i;
3851 if ((i = EVP_PKEY_get_attr_by_NID(pkey, nid, -1)) != -1)
3852 (void) EVP_PKEY_delete_attr(pkey, i);
3853 if (EVP_PKEY_add1_attr(pkey, attr) == 0) {
3854 X509_ATTRIBUTE_free(attr);
3855 return (KMF_ERR_MEMORY);
3857 } else {
3858 return (KMF_ERR_MEMORY);
3861 return (KMF_OK);
3864 static KMF_RETURN
3865 openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3866 STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3868 KMF_RETURN ret = KMF_OK;
3869 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3870 EVP_PKEY *pkey = NULL;
3871 X509 *xcert = NULL;
3872 const ASN1_TYPE *keyid = NULL;
3873 const ASN1_TYPE *fname = NULL;
3874 uchar_t *data = NULL;
3876 keyid = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID);
3877 fname = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName);
3879 switch (PKCS12_SAFEBAG_get_nid(bag)) {
3880 case NID_keyBag:
3881 if (keylist == NULL)
3882 goto end;
3883 pkey = EVP_PKCS82PKEY(
3884 PKCS12_SAFEBAG_get0_p8inf(bag));
3885 if (pkey == NULL)
3886 ret = KMF_ERR_PKCS12_FORMAT;
3888 break;
3889 case NID_pkcs8ShroudedKeyBag:
3890 if (keylist == NULL)
3891 goto end;
3892 p8 = PKCS12_decrypt_skey(bag, pass, passlen);
3893 if (p8 == NULL)
3894 return (KMF_ERR_AUTH_FAILED);
3895 pkey = EVP_PKCS82PKEY(p8);
3896 PKCS8_PRIV_KEY_INFO_free(p8);
3897 if (pkey == NULL)
3898 ret = KMF_ERR_PKCS12_FORMAT;
3899 break;
3900 case NID_certBag:
3901 if (certlist == NULL)
3902 goto end;
3903 if (PKCS12_SAFEBAG_get_bag_nid(bag) !=
3904 NID_x509Certificate)
3905 return (KMF_ERR_PKCS12_FORMAT);
3906 xcert = PKCS12_SAFEBAG_get1_cert(bag);
3907 if (xcert == NULL) {
3908 ret = KMF_ERR_PKCS12_FORMAT;
3909 goto end;
3911 if (keyid != NULL) {
3912 if (X509_keyid_set1(xcert,
3913 keyid->value.octet_string->data,
3914 keyid->value.octet_string->length) == 0) {
3915 ret = KMF_ERR_PKCS12_FORMAT;
3916 goto end;
3919 if (fname != NULL) {
3920 int len, r;
3921 len = ASN1_STRING_to_UTF8(&data,
3922 fname->value.asn1_string);
3923 if (len > 0 && data != NULL) {
3924 r = X509_alias_set1(xcert, data, len);
3925 if (r == NULL) {
3926 ret = KMF_ERR_PKCS12_FORMAT;
3927 goto end;
3929 } else {
3930 ret = KMF_ERR_PKCS12_FORMAT;
3931 goto end;
3934 if (sk_X509_push(certlist, xcert) == 0)
3935 ret = KMF_ERR_MEMORY;
3936 else
3937 xcert = NULL;
3938 break;
3939 case NID_safeContentsBag:
3940 return (openssl_parse_bags(
3941 PKCS12_SAFEBAG_get0_safes(bag),
3942 pass, keylist, certlist));
3943 default:
3944 ret = KMF_ERR_PKCS12_FORMAT;
3945 break;
3949 * Set the ID and/or FriendlyName attributes on the key.
3950 * If converting to PKCS11 objects, these can translate to CKA_ID
3951 * and CKA_LABEL values.
3953 if (pkey != NULL && ret == KMF_OK) {
3954 ASN1_TYPE *attr = NULL;
3955 if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3956 if ((attr = ASN1_TYPE_new()) == NULL)
3957 return (KMF_ERR_MEMORY);
3958 attr->value.octet_string =
3959 ASN1_STRING_dup(keyid->value.octet_string);
3960 attr->type = V_ASN1_OCTET_STRING;
3961 attr->value.ptr = (char *)attr->value.octet_string;
3962 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3963 OPENSSL_free(attr);
3966 if (ret == KMF_OK && fname != NULL &&
3967 fname->type == V_ASN1_BMPSTRING) {
3968 if ((attr = ASN1_TYPE_new()) == NULL)
3969 return (KMF_ERR_MEMORY);
3970 attr->value.bmpstring =
3971 ASN1_STRING_dup(fname->value.bmpstring);
3972 attr->type = V_ASN1_BMPSTRING;
3973 attr->value.ptr = (char *)attr->value.bmpstring;
3974 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3975 OPENSSL_free(attr);
3978 if (ret == KMF_OK && keylist != NULL &&
3979 sk_EVP_PKEY_push(keylist, pkey) == 0)
3980 ret = KMF_ERR_MEMORY;
3982 if (ret == KMF_OK && keylist != NULL)
3983 pkey = NULL;
3984 end:
3985 if (pkey != NULL)
3986 EVP_PKEY_free(pkey);
3987 if (xcert != NULL)
3988 X509_free(xcert);
3989 if (data != NULL)
3990 OPENSSL_free(data);
3992 return (ret);
3995 static KMF_RETURN
3996 openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3997 STACK_OF(EVP_PKEY) *keys,
3998 STACK_OF(X509) *certs,
3999 STACK_OF(X509) *ca)
4000 /* ARGSUSED3 */
4002 KMF_RETURN ret = KMF_OK;
4003 STACK_OF(PKCS7) *asafes = NULL;
4004 STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
4005 int i, bagnid;
4006 PKCS7 *p7;
4008 if (p12 == NULL || (keys == NULL && certs == NULL))
4009 return (KMF_ERR_BAD_PARAMETER);
4011 if (pin == NULL || *pin == NULL) {
4012 if (PKCS12_verify_mac(p12, NULL, 0)) {
4013 pin = NULL;
4014 } else if (PKCS12_verify_mac(p12, "", 0)) {
4015 pin = "";
4016 } else {
4017 return (KMF_ERR_AUTH_FAILED);
4019 } else if (!PKCS12_verify_mac(p12, pin, -1)) {
4020 return (KMF_ERR_AUTH_FAILED);
4023 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
4024 return (KMF_ERR_PKCS12_FORMAT);
4026 for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
4027 bags = NULL;
4028 /* LINTED E_BAD_PTR_CAST_ALIGN */
4029 p7 = sk_PKCS7_value(asafes, i);
4030 bagnid = OBJ_obj2nid(p7->type);
4032 if (bagnid == NID_pkcs7_data) {
4033 bags = PKCS12_unpack_p7data(p7);
4034 } else if (bagnid == NID_pkcs7_encrypted) {
4035 bags = PKCS12_unpack_p7encdata(p7, pin,
4036 (pin ? strlen(pin) : 0));
4037 } else {
4038 continue;
4040 if (bags == NULL) {
4041 ret = KMF_ERR_PKCS12_FORMAT;
4042 goto out;
4045 if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
4046 ret = KMF_ERR_PKCS12_FORMAT;
4048 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
4050 out:
4051 if (asafes != NULL)
4052 sk_PKCS7_pop_free(asafes, PKCS7_free);
4054 return (ret);
4058 * Helper function to decrypt and parse PKCS#12 import file.
4060 static KMF_RETURN
4061 extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
4062 STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
4063 STACK_OF(X509) **ca)
4064 /* ARGSUSED2 */
4066 PKCS12 *pk12, *pk12_tmp;
4067 STACK_OF(EVP_PKEY) *pkeylist = NULL;
4068 STACK_OF(X509) *xcertlist = NULL;
4069 STACK_OF(X509) *cacertlist = NULL;
4071 if ((pk12 = PKCS12_new()) == NULL) {
4072 return (KMF_ERR_MEMORY);
4075 if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
4076 /* This is ok; it seems to mean there is no more to read. */
4077 if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
4078 ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
4079 goto end_extract_pkcs12;
4081 PKCS12_free(pk12);
4082 return (KMF_ERR_PKCS12_FORMAT);
4084 pk12 = pk12_tmp;
4086 xcertlist = sk_X509_new_null();
4087 if (xcertlist == NULL) {
4088 PKCS12_free(pk12);
4089 return (KMF_ERR_MEMORY);
4091 pkeylist = sk_EVP_PKEY_new_null();
4092 if (pkeylist == NULL) {
4093 sk_X509_pop_free(xcertlist, X509_free);
4094 PKCS12_free(pk12);
4095 return (KMF_ERR_MEMORY);
4098 if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4099 cacertlist) != KMF_OK) {
4100 sk_X509_pop_free(xcertlist, X509_free);
4101 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4102 PKCS12_free(pk12);
4103 return (KMF_ERR_PKCS12_FORMAT);
4106 if (priv_key && pkeylist)
4107 *priv_key = pkeylist;
4108 else if (pkeylist)
4109 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4110 if (certs && xcertlist)
4111 *certs = xcertlist;
4112 else if (xcertlist)
4113 sk_X509_pop_free(xcertlist, X509_free);
4114 if (ca && cacertlist)
4115 *ca = cacertlist;
4116 else if (cacertlist)
4117 sk_X509_pop_free(cacertlist, X509_free);
4119 end_extract_pkcs12:
4121 PKCS12_free(pk12);
4122 return (KMF_OK);
4125 static KMF_RETURN
4126 sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4128 KMF_RETURN rv = KMF_OK;
4129 uint32_t sz;
4131 sz = BN_num_bytes(from);
4132 to->val = (uchar_t *)malloc(sz);
4133 if (to->val == NULL)
4134 return (KMF_ERR_MEMORY);
4136 if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4137 free(to->val);
4138 to->val = NULL;
4139 to->len = 0;
4140 rv = KMF_ERR_MEMORY;
4143 return (rv);
4146 static KMF_RETURN
4147 exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4149 KMF_RETURN rv;
4150 KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4152 const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmpq, *iqmp;
4154 RSA_get0_key(rsa, &n, &e, &d);
4155 RSA_get0_factors(rsa, &p, &q);
4156 RSA_get0_crt_params(rsa, &dmp1, &dmpq, &iqmp);
4158 (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4159 if ((rv = sslBN2KMFBN((BIGNUM *)n, &kmfkey->mod)) != KMF_OK)
4160 goto cleanup;
4162 if ((rv = sslBN2KMFBN((BIGNUM *)e, &kmfkey->pubexp)) != KMF_OK)
4163 goto cleanup;
4165 if (d != NULL)
4166 if ((rv = sslBN2KMFBN((BIGNUM *)d, &kmfkey->priexp)) != KMF_OK)
4167 goto cleanup;
4169 if (p != NULL)
4170 if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime1)) != KMF_OK)
4171 goto cleanup;
4173 if (q != NULL)
4174 if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->prime2)) != KMF_OK)
4175 goto cleanup;
4177 if (dmp1 != NULL)
4178 if ((rv = sslBN2KMFBN((BIGNUM *)dmp1, &kmfkey->exp1)) != KMF_OK)
4179 goto cleanup;
4181 if (dmpq != NULL)
4182 if ((rv = sslBN2KMFBN((BIGNUM *)dmpq, &kmfkey->exp2)) != KMF_OK)
4183 goto cleanup;
4185 if (iqmp != NULL)
4186 if ((rv = sslBN2KMFBN((BIGNUM *)iqmp, &kmfkey->coef)) != KMF_OK)
4187 goto cleanup;
4188 cleanup:
4189 if (rv != KMF_OK)
4190 kmf_free_raw_key(key);
4191 else
4192 key->keytype = KMF_RSA;
4195 * Free the reference to this key, SSL will not actually free
4196 * the memory until the refcount == 0, so this is safe.
4198 RSA_free(rsa);
4200 return (rv);
4203 static KMF_RETURN
4204 exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4206 KMF_RETURN rv;
4207 KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4208 const BIGNUM *p, *q, *g, *priv_key;
4210 DSA_get0_pqg(dsa, &p, &q, &g);
4211 DSA_get0_key(dsa, NULL, &priv_key);
4213 (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4214 if ((rv = sslBN2KMFBN((BIGNUM *)p, &kmfkey->prime)) != KMF_OK)
4215 goto cleanup;
4217 if ((rv = sslBN2KMFBN((BIGNUM *)q, &kmfkey->subprime)) != KMF_OK)
4218 goto cleanup;
4220 if ((rv = sslBN2KMFBN((BIGNUM *)g, &kmfkey->base)) != KMF_OK)
4221 goto cleanup;
4223 if ((rv = sslBN2KMFBN((BIGNUM *)priv_key, &kmfkey->value)) != KMF_OK)
4224 goto cleanup;
4226 cleanup:
4227 if (rv != KMF_OK)
4228 kmf_free_raw_key(key);
4229 else
4230 key->keytype = KMF_DSA;
4233 * Free the reference to this key, SSL will not actually free
4234 * the memory until the refcount == 0, so this is safe.
4236 DSA_free(dsa);
4238 return (rv);
4241 static KMF_RETURN
4242 add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4243 KMF_X509_DER_CERT **certlist, int *ncerts)
4245 KMF_RETURN rv = KMF_OK;
4246 KMF_X509_DER_CERT *list = (*certlist);
4247 KMF_X509_DER_CERT cert;
4248 int n = (*ncerts);
4250 if (list == NULL) {
4251 list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4252 } else {
4253 list = (KMF_X509_DER_CERT *)realloc(list,
4254 sizeof (KMF_X509_DER_CERT) * (n + 1));
4257 if (list == NULL)
4258 return (KMF_ERR_MEMORY);
4260 (void) memset(&cert, 0, sizeof (cert));
4261 rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4262 if (rv == KMF_OK) {
4263 int len = 0;
4264 /* Get the alias name for the cert if there is one */
4265 char *a = (char *)X509_alias_get0(sslcert, &len);
4266 if (a != NULL)
4267 cert.kmf_private.label = strdup(a);
4268 cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4270 list[n] = cert;
4271 (*ncerts) = n + 1;
4273 *certlist = list;
4274 } else {
4275 free(list);
4278 return (rv);
4281 static KMF_RETURN
4282 add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4283 KMF_RAW_KEY_DATA *newkey, int *nkeys)
4285 KMF_RAW_KEY_DATA *list = (*keylist);
4286 int n = (*nkeys);
4288 if (list == NULL) {
4289 list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4290 } else {
4291 list = (KMF_RAW_KEY_DATA *)realloc(list,
4292 sizeof (KMF_RAW_KEY_DATA) * (n + 1));
4295 if (list == NULL)
4296 return (KMF_ERR_MEMORY);
4298 list[n] = *newkey;
4299 (*nkeys) = n + 1;
4301 *keylist = list;
4303 return (KMF_OK);
4306 static KMF_RETURN
4307 convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4309 KMF_RETURN rv = KMF_OK;
4310 X509_ATTRIBUTE *attr;
4311 RSA *rsa;
4312 DSA *dsa;
4313 int loc;
4315 if (pkey == NULL || key == NULL)
4316 return (KMF_ERR_BAD_PARAMETER);
4317 /* Convert SSL key to raw key */
4318 if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
4319 rv = exportRawRSAKey(rsa, key);
4320 if (rv != KMF_OK)
4321 return (rv);
4322 } else if ((dsa = EVP_PKEY_get1_DSA(pkey)) != NULL) {
4323 rv = exportRawDSAKey(dsa, key);
4324 if (rv != KMF_OK)
4325 return (rv);
4326 } else
4327 return (KMF_ERR_BAD_PARAMETER);
4330 * If friendlyName, add it to record.
4333 if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4334 NID_friendlyName, -1)) != -1 &&
4335 (attr = EVP_PKEY_get_attr(pkey, loc))) {
4336 ASN1_TYPE *ty = NULL;
4337 int numattr = X509_ATTRIBUTE_count(attr);
4338 if (numattr > 0) {
4339 ty = X509_ATTRIBUTE_get0_type(attr, 0);
4341 if (ty != NULL) {
4342 key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4343 ty->value.bmpstring->length);
4345 } else {
4346 key->label = NULL;
4350 * If KeyID, add it to record as a KMF_DATA object.
4352 if ((loc = EVP_PKEY_get_attr_by_NID(pkey,
4353 NID_localKeyID, -1)) != -1 &&
4354 (attr = EVP_PKEY_get_attr(pkey, loc)) != NULL) {
4355 ASN1_TYPE *ty = NULL;
4356 int numattr = X509_ATTRIBUTE_count(attr);
4357 if (numattr > 0)
4358 ty = X509_ATTRIBUTE_get0_type(attr, 0);
4359 key->id.Data = (uchar_t *)malloc(
4360 ty->value.octet_string->length);
4361 if (key->id.Data == NULL)
4362 return (KMF_ERR_MEMORY);
4363 (void) memcpy(key->id.Data, ty->value.octet_string->data,
4364 ty->value.octet_string->length);
4365 key->id.Length = ty->value.octet_string->length;
4366 } else {
4367 (void) memset(&key->id, 0, sizeof (KMF_DATA));
4370 return (rv);
4373 static KMF_RETURN
4374 convertPK12Objects(
4375 KMF_HANDLE *kmfh,
4376 STACK_OF(EVP_PKEY) *sslkeys,
4377 STACK_OF(X509) *sslcert,
4378 STACK_OF(X509) *sslcacerts,
4379 KMF_RAW_KEY_DATA **keylist, int *nkeys,
4380 KMF_X509_DER_CERT **certlist, int *ncerts)
4382 KMF_RETURN rv = KMF_OK;
4383 KMF_RAW_KEY_DATA key;
4384 int i;
4386 for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4387 /* LINTED E_BAD_PTR_CAST_ALIGN */
4388 EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4389 rv = convertToRawKey(pkey, &key);
4390 if (rv == KMF_OK)
4391 rv = add_key_to_list(keylist, &key, nkeys);
4393 if (rv != KMF_OK)
4394 return (rv);
4397 /* Now add the certificate to the certlist */
4398 for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4399 /* LINTED E_BAD_PTR_CAST_ALIGN */
4400 X509 *cert = sk_X509_value(sslcert, i);
4401 rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4402 if (rv != KMF_OK)
4403 return (rv);
4406 /* Also add any included CA certs to the list */
4407 for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4408 X509 *c;
4410 * sk_X509_value() is macro that embeds a cast to (X509 *).
4411 * Here it translates into ((X509 *)sk_value((ca), (i))).
4412 * Lint is complaining about the embedded casting, and
4413 * to fix it, you need to fix openssl header files.
4415 /* LINTED E_BAD_PTR_CAST_ALIGN */
4416 c = sk_X509_value(sslcacerts, i);
4418 /* Now add the ca cert to the certlist */
4419 rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4420 if (rv != KMF_OK)
4421 return (rv);
4423 return (rv);
4426 KMF_RETURN
4427 openssl_import_objects(KMF_HANDLE *kmfh,
4428 char *filename, KMF_CREDENTIAL *cred,
4429 KMF_X509_DER_CERT **certlist, int *ncerts,
4430 KMF_RAW_KEY_DATA **keylist, int *nkeys)
4432 KMF_RETURN rv = KMF_OK;
4433 KMF_ENCODE_FORMAT format;
4434 BIO *bio = NULL;
4435 STACK_OF(EVP_PKEY) *privkeys = NULL;
4436 STACK_OF(X509) *certs = NULL;
4437 STACK_OF(X509) *cacerts = NULL;
4440 * auto-detect the file format, regardless of what
4441 * the 'format' parameters in the params say.
4443 rv = kmf_get_file_format(filename, &format);
4444 if (rv != KMF_OK) {
4445 return (rv);
4448 /* This function only works for PEM or PKCS#12 files */
4449 if (format != KMF_FORMAT_PEM &&
4450 format != KMF_FORMAT_PEM_KEYPAIR &&
4451 format != KMF_FORMAT_PKCS12)
4452 return (KMF_ERR_ENCODING);
4454 *certlist = NULL;
4455 *keylist = NULL;
4456 *ncerts = 0;
4457 *nkeys = 0;
4459 if (format == KMF_FORMAT_PKCS12) {
4460 bio = BIO_new_file(filename, "rb");
4461 if (bio == NULL) {
4462 SET_ERROR(kmfh, ERR_get_error());
4463 rv = KMF_ERR_OPEN_FILE;
4464 goto end;
4467 rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4468 (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4470 if (rv == KMF_OK)
4471 /* Convert keys and certs to exportable format */
4472 rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4473 keylist, nkeys, certlist, ncerts);
4474 } else {
4475 EVP_PKEY *pkey;
4476 KMF_DATA *certdata = NULL;
4477 KMF_X509_DER_CERT *kmfcerts = NULL;
4478 int i;
4479 rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4480 (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4481 &pkey, &certdata, ncerts);
4483 /* Reached end of import file? */
4484 if (rv == KMF_OK && pkey != NULL) {
4485 privkeys = sk_EVP_PKEY_new_null();
4486 if (privkeys == NULL) {
4487 rv = KMF_ERR_MEMORY;
4488 goto end;
4490 (void) sk_EVP_PKEY_push(privkeys, pkey);
4491 /* convert the certificate list here */
4492 if (*ncerts > 0 && certlist != NULL) {
4493 kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4494 sizeof (KMF_X509_DER_CERT));
4495 if (kmfcerts == NULL) {
4496 rv = KMF_ERR_MEMORY;
4497 goto end;
4499 for (i = 0; i < *ncerts; i++) {
4500 kmfcerts[i].certificate = certdata[i];
4501 kmfcerts[i].kmf_private.keystore_type =
4502 KMF_KEYSTORE_OPENSSL;
4504 *certlist = kmfcerts;
4507 * Convert keys to exportable format, the certs
4508 * are already OK.
4510 rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4511 keylist, nkeys, NULL, NULL);
4514 end:
4515 if (bio != NULL)
4516 (void) BIO_free(bio);
4518 if (privkeys)
4519 sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4520 if (certs)
4521 sk_X509_pop_free(certs, X509_free);
4522 if (cacerts)
4523 sk_X509_pop_free(cacerts, X509_free);
4525 return (rv);
4528 static KMF_RETURN
4529 create_deskey(DES_cblock **deskey)
4531 DES_cblock *key;
4533 key = (DES_cblock *) malloc(sizeof (DES_cblock));
4534 if (key == NULL) {
4535 return (KMF_ERR_MEMORY);
4538 if (DES_random_key(key) == 0) {
4539 free(key);
4540 return (KMF_ERR_KEYGEN_FAILED);
4543 *deskey = key;
4544 return (KMF_OK);
4547 #define KEYGEN_RETRY 3
4548 #define DES3_KEY_SIZE 24
4550 static KMF_RETURN
4551 create_des3key(unsigned char **des3key)
4553 KMF_RETURN ret = KMF_OK;
4554 DES_cblock *deskey1 = NULL;
4555 DES_cblock *deskey2 = NULL;
4556 DES_cblock *deskey3 = NULL;
4557 unsigned char *newkey = NULL;
4558 int retry;
4560 if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4561 return (KMF_ERR_MEMORY);
4564 /* create the 1st DES key */
4565 if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4566 goto out;
4570 * Create the 2nd DES key and make sure its value is different
4571 * from the 1st DES key.
4573 retry = 0;
4574 do {
4575 if (deskey2 != NULL) {
4576 free(deskey2);
4577 deskey2 = NULL;
4580 if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4581 goto out;
4584 if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4585 == 0) {
4586 ret = KMF_ERR_KEYGEN_FAILED;
4587 retry++;
4589 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4591 if (ret != KMF_OK) {
4592 goto out;
4596 * Create the 3rd DES key and make sure its value is different
4597 * from the 2nd DES key.
4599 retry = 0;
4600 do {
4601 if (deskey3 != NULL) {
4602 free(deskey3);
4603 deskey3 = NULL;
4606 if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4607 goto out;
4610 if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4611 == 0) {
4612 ret = KMF_ERR_KEYGEN_FAILED;
4613 retry++;
4615 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4617 if (ret != KMF_OK) {
4618 goto out;
4621 /* Concatenate 3 DES keys into a DES3 key */
4622 (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4623 (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4624 (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4625 *des3key = newkey;
4627 out:
4628 if (deskey1 != NULL)
4629 free(deskey1);
4631 if (deskey2 != NULL)
4632 free(deskey2);
4634 if (deskey3 != NULL)
4635 free(deskey3);
4637 if (ret != KMF_OK && newkey != NULL)
4638 free(newkey);
4640 return (ret);
4643 KMF_RETURN
4644 OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4645 int numattr, KMF_ATTRIBUTE *attrlist)
4647 KMF_RETURN ret = KMF_OK;
4648 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4649 char *fullpath = NULL;
4650 KMF_RAW_SYM_KEY *rkey = NULL;
4651 DES_cblock *deskey = NULL;
4652 unsigned char *des3key = NULL;
4653 unsigned char *random = NULL;
4654 int fd = -1;
4655 KMF_KEY_HANDLE *symkey;
4656 KMF_KEY_ALG keytype;
4657 uint32_t keylen;
4658 uint32_t keylen_size = sizeof (keylen);
4659 char *dirpath;
4660 char *keyfile;
4662 if (kmfh == NULL)
4663 return (KMF_ERR_UNINITIALIZED);
4665 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4666 if (symkey == NULL)
4667 return (KMF_ERR_BAD_PARAMETER);
4669 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4671 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4672 if (keyfile == NULL)
4673 return (KMF_ERR_BAD_PARAMETER);
4675 ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4676 (void *)&keytype, NULL);
4677 if (ret != KMF_OK)
4678 return (KMF_ERR_BAD_PARAMETER);
4680 ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4681 &keylen, &keylen_size);
4682 if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4683 (keytype == KMF_DES || keytype == KMF_DES3))
4684 /* keylength is not required for DES and 3DES */
4685 ret = KMF_OK;
4686 if (ret != KMF_OK)
4687 return (KMF_ERR_BAD_PARAMETER);
4689 fullpath = get_fullpath(dirpath, keyfile);
4690 if (fullpath == NULL)
4691 return (KMF_ERR_BAD_PARAMETER);
4693 /* If the requested file exists, return an error */
4694 if (test_for_file(fullpath, 0400) == 1) {
4695 free(fullpath);
4696 return (KMF_ERR_DUPLICATE_KEYFILE);
4699 fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4700 if (fd == -1) {
4701 ret = KMF_ERR_OPEN_FILE;
4702 goto out;
4705 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4706 if (rkey == NULL) {
4707 ret = KMF_ERR_MEMORY;
4708 goto out;
4710 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4712 if (keytype == KMF_DES) {
4713 if ((ret = create_deskey(&deskey)) != KMF_OK) {
4714 goto out;
4716 rkey->keydata.val = (uchar_t *)deskey;
4717 rkey->keydata.len = 8;
4719 symkey->keyalg = KMF_DES;
4721 } else if (keytype == KMF_DES3) {
4722 if ((ret = create_des3key(&des3key)) != KMF_OK) {
4723 goto out;
4725 rkey->keydata.val = (uchar_t *)des3key;
4726 rkey->keydata.len = DES3_KEY_SIZE;
4727 symkey->keyalg = KMF_DES3;
4729 } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4730 keytype == KMF_GENERIC_SECRET) {
4731 int bytes;
4733 if (keylen % 8 != 0) {
4734 ret = KMF_ERR_BAD_KEY_SIZE;
4735 goto out;
4738 if (keytype == KMF_AES) {
4739 if (keylen != 128 &&
4740 keylen != 192 &&
4741 keylen != 256) {
4742 ret = KMF_ERR_BAD_KEY_SIZE;
4743 goto out;
4747 bytes = keylen/8;
4748 random = malloc(bytes);
4749 if (random == NULL) {
4750 ret = KMF_ERR_MEMORY;
4751 goto out;
4753 if (RAND_bytes(random, bytes) != 1) {
4754 ret = KMF_ERR_KEYGEN_FAILED;
4755 goto out;
4758 rkey->keydata.val = (uchar_t *)random;
4759 rkey->keydata.len = bytes;
4760 symkey->keyalg = keytype;
4762 } else {
4763 ret = KMF_ERR_BAD_KEY_TYPE;
4764 goto out;
4767 (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4769 symkey->kstype = KMF_KEYSTORE_OPENSSL;
4770 symkey->keyclass = KMF_SYMMETRIC;
4771 symkey->keylabel = (char *)fullpath;
4772 symkey->israw = TRUE;
4773 symkey->keyp = rkey;
4775 out:
4776 if (fd != -1)
4777 (void) close(fd);
4779 if (ret != KMF_OK && fullpath != NULL) {
4780 free(fullpath);
4782 if (ret != KMF_OK) {
4783 kmf_free_raw_sym_key(rkey);
4784 symkey->keyp = NULL;
4785 symkey->keyalg = KMF_KEYALG_NONE;
4788 return (ret);
4792 * Check a file to see if it is a CRL file with PEM or DER format.
4793 * If success, return its format in the "pformat" argument.
4795 KMF_RETURN
4796 OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4798 KMF_RETURN ret = KMF_OK;
4799 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4800 BIO *bio = NULL;
4801 X509_CRL *xcrl = NULL;
4803 if (filename == NULL) {
4804 return (KMF_ERR_BAD_PARAMETER);
4807 bio = BIO_new_file(filename, "rb");
4808 if (bio == NULL) {
4809 SET_ERROR(kmfh, ERR_get_error());
4810 ret = KMF_ERR_OPEN_FILE;
4811 goto out;
4814 if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4815 *pformat = KMF_FORMAT_PEM;
4816 goto out;
4818 (void) BIO_free(bio);
4821 * Now try to read it as raw DER data.
4823 bio = BIO_new_file(filename, "rb");
4824 if (bio == NULL) {
4825 SET_ERROR(kmfh, ERR_get_error());
4826 ret = KMF_ERR_OPEN_FILE;
4827 goto out;
4830 if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4831 *pformat = KMF_FORMAT_ASN1;
4832 } else {
4833 ret = KMF_ERR_BAD_CRLFILE;
4836 out:
4837 if (bio != NULL)
4838 (void) BIO_free(bio);
4840 if (xcrl != NULL)
4841 X509_CRL_free(xcrl);
4843 return (ret);
4846 KMF_RETURN
4847 OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4848 KMF_RAW_SYM_KEY *rkey)
4850 KMF_RETURN rv = KMF_OK;
4851 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4852 KMF_DATA keyvalue;
4854 if (kmfh == NULL)
4855 return (KMF_ERR_UNINITIALIZED);
4857 if (symkey == NULL || rkey == NULL)
4858 return (KMF_ERR_BAD_PARAMETER);
4859 else if (symkey->keyclass != KMF_SYMMETRIC)
4860 return (KMF_ERR_BAD_KEY_CLASS);
4862 if (symkey->israw) {
4863 KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4865 if (rawkey == NULL ||
4866 rawkey->keydata.val == NULL ||
4867 rawkey->keydata.len == 0)
4868 return (KMF_ERR_BAD_KEYHANDLE);
4870 rkey->keydata.len = rawkey->keydata.len;
4871 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4872 return (KMF_ERR_MEMORY);
4873 (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4874 rkey->keydata.len);
4875 } else {
4876 rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4877 if (rv != KMF_OK)
4878 return (rv);
4879 rkey->keydata.len = keyvalue.Length;
4880 rkey->keydata.val = keyvalue.Data;
4883 return (rv);
4887 * substitute for the unsafe access(2) function.
4888 * If the file in question already exists, return 1.
4889 * else 0. If an error occurs during testing (other
4890 * than EEXIST), return -1.
4892 static int
4893 test_for_file(char *filename, mode_t mode)
4895 int fd;
4898 * Try to create the file with the EXCL flag.
4899 * The call should fail if the file exists.
4901 fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4902 if (fd == -1 && errno == EEXIST)
4903 return (1);
4904 else if (fd == -1) /* some other error */
4905 return (-1);
4907 /* The file did NOT exist. Delete the testcase. */
4908 (void) close(fd);
4909 (void) unlink(filename);
4910 return (0);
4913 KMF_RETURN
4914 OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4915 KMF_ATTRIBUTE *attrlist)
4917 KMF_RETURN rv = KMF_OK;
4918 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4919 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4920 KMF_RAW_KEY_DATA *rawkey;
4921 EVP_PKEY *pkey = NULL;
4922 KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4923 KMF_CREDENTIAL cred = { NULL, 0 };
4924 BIO *out = NULL;
4925 int keys = 0;
4926 char *fullpath = NULL;
4927 char *keyfile = NULL;
4928 char *dirpath = NULL;
4930 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4931 if (pubkey != NULL)
4932 keys++;
4934 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4935 if (prikey != NULL)
4936 keys++;
4938 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4939 if (rawkey != NULL)
4940 keys++;
4943 * Exactly 1 type of key must be passed to this function.
4945 if (keys != 1)
4946 return (KMF_ERR_BAD_PARAMETER);
4948 keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4949 numattr);
4950 if (keyfile == NULL)
4951 return (KMF_ERR_BAD_PARAMETER);
4953 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4955 fullpath = get_fullpath(dirpath, keyfile);
4957 /* Once we have the full path, we don't need the pieces */
4958 if (fullpath == NULL)
4959 return (KMF_ERR_BAD_PARAMETER);
4961 /* If the requested file exists, return an error */
4962 if (test_for_file(fullpath, 0400) == 1) {
4963 free(fullpath);
4964 return (KMF_ERR_DUPLICATE_KEYFILE);
4967 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4968 &format, NULL);
4969 if (rv != KMF_OK)
4970 /* format is optional. */
4971 rv = KMF_OK;
4973 /* CRED is not required for OpenSSL files */
4974 (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4975 &cred, NULL);
4977 /* Store the private key to the keyfile */
4978 out = BIO_new_file(fullpath, "wb");
4979 if (out == NULL) {
4980 SET_ERROR(kmfh, ERR_get_error());
4981 rv = KMF_ERR_OPEN_FILE;
4982 goto end;
4985 if (prikey != NULL && prikey->keyp != NULL) {
4986 if (prikey->keyalg == KMF_RSA ||
4987 prikey->keyalg == KMF_DSA) {
4988 pkey = (EVP_PKEY *)prikey->keyp;
4990 rv = ssl_write_key(kmfh, format,
4991 out, &cred, pkey, TRUE);
4993 if (rv == KMF_OK && prikey->keylabel == NULL) {
4994 prikey->keylabel = strdup(fullpath);
4995 if (prikey->keylabel == NULL)
4996 rv = KMF_ERR_MEMORY;
4999 } else if (pubkey != NULL && pubkey->keyp != NULL) {
5000 if (pubkey->keyalg == KMF_RSA ||
5001 pubkey->keyalg == KMF_DSA) {
5002 pkey = (EVP_PKEY *)pubkey->keyp;
5004 rv = ssl_write_key(kmfh, format,
5005 out, &cred, pkey, FALSE);
5007 if (rv == KMF_OK && pubkey->keylabel == NULL) {
5008 pubkey->keylabel = strdup(fullpath);
5009 if (pubkey->keylabel == NULL)
5010 rv = KMF_ERR_MEMORY;
5013 } else if (rawkey != NULL) {
5014 if (rawkey->keytype == KMF_RSA) {
5015 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
5016 } else if (rawkey->keytype == KMF_DSA) {
5017 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
5018 } else {
5019 rv = KMF_ERR_BAD_PARAMETER;
5021 if (pkey != NULL) {
5022 KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
5024 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
5025 (void *)&kclass, NULL);
5026 if (rv != KMF_OK)
5027 rv = KMF_OK;
5028 rv = ssl_write_key(kmfh, format, out,
5029 &cred, pkey, (kclass == KMF_ASYM_PRI));
5030 EVP_PKEY_free(pkey);
5034 end:
5036 if (out)
5037 (void) BIO_free(out);
5040 if (rv == KMF_OK)
5041 (void) chmod(fullpath, 0400);
5043 free(fullpath);
5044 return (rv);
5047 KMF_RETURN
5048 OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5050 KMF_RETURN ret = KMF_OK;
5051 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5052 X509_CRL *xcrl = NULL;
5053 X509 *xcert = NULL;
5054 EVP_PKEY *pkey;
5055 KMF_ENCODE_FORMAT format;
5056 BIO *in = NULL, *out = NULL;
5057 int openssl_ret = 0;
5058 KMF_ENCODE_FORMAT outformat;
5059 boolean_t crlcheck = FALSE;
5060 char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
5062 if (numattr == 0 || attrlist == NULL) {
5063 return (KMF_ERR_BAD_PARAMETER);
5066 /* CRL check is optional */
5067 (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
5068 &crlcheck, NULL);
5070 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5071 if (crlcheck == B_TRUE && certfile == NULL) {
5072 return (KMF_ERR_BAD_CERTFILE);
5075 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5076 incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5077 outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5079 crlfile = get_fullpath(dirpath, incrl);
5081 if (crlfile == NULL)
5082 return (KMF_ERR_BAD_CRLFILE);
5084 outcrlfile = get_fullpath(dirpath, outcrl);
5085 if (outcrlfile == NULL)
5086 return (KMF_ERR_BAD_CRLFILE);
5088 if (isdir(outcrlfile)) {
5089 free(outcrlfile);
5090 return (KMF_ERR_BAD_CRLFILE);
5093 ret = kmf_is_crl_file(handle, crlfile, &format);
5094 if (ret != KMF_OK) {
5095 free(outcrlfile);
5096 return (ret);
5099 in = BIO_new_file(crlfile, "rb");
5100 if (in == NULL) {
5101 SET_ERROR(kmfh, ERR_get_error());
5102 ret = KMF_ERR_OPEN_FILE;
5103 goto end;
5106 if (format == KMF_FORMAT_ASN1) {
5107 xcrl = d2i_X509_CRL_bio(in, NULL);
5108 } else if (format == KMF_FORMAT_PEM) {
5109 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5112 if (xcrl == NULL) {
5113 SET_ERROR(kmfh, ERR_get_error());
5114 ret = KMF_ERR_BAD_CRLFILE;
5115 goto end;
5118 /* If bypasscheck is specified, no need to verify. */
5119 if (crlcheck == B_FALSE)
5120 goto output;
5122 ret = kmf_is_cert_file(handle, certfile, &format);
5123 if (ret != KMF_OK)
5124 goto end;
5126 /* Read in the CA cert file and convert to X509 */
5127 if (BIO_read_filename(in, certfile) <= 0) {
5128 SET_ERROR(kmfh, ERR_get_error());
5129 ret = KMF_ERR_OPEN_FILE;
5130 goto end;
5133 if (format == KMF_FORMAT_ASN1) {
5134 xcert = d2i_X509_bio(in, NULL);
5135 } else if (format == KMF_FORMAT_PEM) {
5136 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5137 } else {
5138 ret = KMF_ERR_BAD_CERT_FORMAT;
5139 goto end;
5142 if (xcert == NULL) {
5143 SET_ERROR(kmfh, ERR_get_error());
5144 ret = KMF_ERR_BAD_CERT_FORMAT;
5145 goto end;
5147 /* Now get the public key from the CA cert */
5148 pkey = X509_get_pubkey(xcert);
5149 if (pkey == NULL) {
5150 SET_ERROR(kmfh, ERR_get_error());
5151 ret = KMF_ERR_BAD_CERTFILE;
5152 goto end;
5155 /* Verify the CRL with the CA's public key */
5156 openssl_ret = X509_CRL_verify(xcrl, pkey);
5157 EVP_PKEY_free(pkey);
5158 if (openssl_ret > 0) {
5159 ret = KMF_OK; /* verify succeed */
5160 } else {
5161 SET_ERROR(kmfh, openssl_ret);
5162 ret = KMF_ERR_BAD_CRLFILE;
5165 output:
5166 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5167 &outformat, NULL);
5168 if (ret != KMF_OK) {
5169 ret = KMF_OK;
5170 outformat = KMF_FORMAT_PEM;
5173 out = BIO_new_file(outcrlfile, "wb");
5174 if (out == NULL) {
5175 SET_ERROR(kmfh, ERR_get_error());
5176 ret = KMF_ERR_OPEN_FILE;
5177 goto end;
5180 if (outformat == KMF_FORMAT_ASN1) {
5181 openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5182 } else if (outformat == KMF_FORMAT_PEM) {
5183 openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5184 } else {
5185 ret = KMF_ERR_BAD_PARAMETER;
5186 goto end;
5189 if (openssl_ret <= 0) {
5190 SET_ERROR(kmfh, ERR_get_error());
5191 ret = KMF_ERR_WRITE_FILE;
5192 } else {
5193 ret = KMF_OK;
5196 end:
5197 if (xcrl != NULL)
5198 X509_CRL_free(xcrl);
5200 if (xcert != NULL)
5201 X509_free(xcert);
5203 if (in != NULL)
5204 (void) BIO_free(in);
5206 if (out != NULL)
5207 (void) BIO_free(out);
5209 if (outcrlfile != NULL)
5210 free(outcrlfile);
5212 return (ret);
5215 KMF_RETURN
5216 OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5218 KMF_RETURN ret = KMF_OK;
5219 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5220 X509_CRL *x = NULL;
5221 KMF_ENCODE_FORMAT format;
5222 char *crlfile = NULL;
5223 BIO *in = NULL;
5224 BIO *mem = NULL;
5225 long len;
5226 char *memptr;
5227 char *data = NULL;
5228 char **crldata;
5229 char *crlfilename, *dirpath;
5231 if (numattr == 0 || attrlist == NULL) {
5232 return (KMF_ERR_BAD_PARAMETER);
5234 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5235 attrlist, numattr);
5236 if (crlfilename == NULL)
5237 return (KMF_ERR_BAD_CRLFILE);
5239 crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5240 attrlist, numattr);
5242 if (crldata == NULL)
5243 return (KMF_ERR_BAD_PARAMETER);
5245 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5247 crlfile = get_fullpath(dirpath, crlfilename);
5249 if (crlfile == NULL)
5250 return (KMF_ERR_BAD_CRLFILE);
5252 if (isdir(crlfile)) {
5253 free(crlfile);
5254 return (KMF_ERR_BAD_CRLFILE);
5257 ret = kmf_is_crl_file(handle, crlfile, &format);
5258 if (ret != KMF_OK) {
5259 free(crlfile);
5260 return (ret);
5263 if (bio_err == NULL)
5264 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5266 in = BIO_new_file(crlfile, "rb");
5267 if (in == NULL) {
5268 SET_ERROR(kmfh, ERR_get_error());
5269 ret = KMF_ERR_OPEN_FILE;
5270 goto end;
5273 if (format == KMF_FORMAT_ASN1) {
5274 x = d2i_X509_CRL_bio(in, NULL);
5275 } else if (format == KMF_FORMAT_PEM) {
5276 x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5279 if (x == NULL) { /* should not happen */
5280 SET_ERROR(kmfh, ERR_get_error());
5281 ret = KMF_ERR_OPEN_FILE;
5282 goto end;
5285 mem = BIO_new(BIO_s_mem());
5286 if (mem == NULL) {
5287 SET_ERROR(kmfh, ERR_get_error());
5288 ret = KMF_ERR_MEMORY;
5289 goto end;
5292 (void) X509_CRL_print(mem, x);
5293 len = BIO_get_mem_data(mem, &memptr);
5294 if (len <= 0) {
5295 SET_ERROR(kmfh, ERR_get_error());
5296 ret = KMF_ERR_MEMORY;
5297 goto end;
5300 data = malloc(len + 1);
5301 if (data == NULL) {
5302 ret = KMF_ERR_MEMORY;
5303 goto end;
5306 (void) memcpy(data, memptr, len);
5307 data[len] = '\0';
5308 *crldata = data;
5310 end:
5311 if (x != NULL)
5312 X509_CRL_free(x);
5314 if (crlfile != NULL)
5315 free(crlfile);
5317 if (in != NULL)
5318 (void) BIO_free(in);
5320 if (mem != NULL)
5321 (void) BIO_free(mem);
5323 return (ret);
5326 KMF_RETURN
5327 OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5329 KMF_RETURN ret = KMF_OK;
5330 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5331 KMF_ENCODE_FORMAT format;
5332 char *crlfile = NULL;
5333 BIO *in = NULL;
5334 char *crlfilename, *dirpath;
5336 if (numattr == 0 || attrlist == NULL) {
5337 return (KMF_ERR_BAD_PARAMETER);
5340 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5341 attrlist, numattr);
5343 if (crlfilename == NULL)
5344 return (KMF_ERR_BAD_CRLFILE);
5346 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5348 crlfile = get_fullpath(dirpath, crlfilename);
5350 if (crlfile == NULL)
5351 return (KMF_ERR_BAD_CRLFILE);
5353 if (isdir(crlfile)) {
5354 ret = KMF_ERR_BAD_CRLFILE;
5355 goto end;
5358 ret = kmf_is_crl_file(handle, crlfile, &format);
5359 if (ret != KMF_OK)
5360 goto end;
5362 if (unlink(crlfile) != 0) {
5363 SET_SYS_ERROR(kmfh, errno);
5364 ret = KMF_ERR_INTERNAL;
5365 goto end;
5368 end:
5369 if (in != NULL)
5370 (void) BIO_free(in);
5371 if (crlfile != NULL)
5372 free(crlfile);
5374 return (ret);
5377 KMF_RETURN
5378 OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5380 KMF_RETURN ret = KMF_OK;
5381 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5382 KMF_ENCODE_FORMAT format;
5383 BIO *in = NULL;
5384 X509 *xcert = NULL;
5385 X509_CRL *xcrl = NULL;
5386 STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5387 X509_REVOKED *revoke;
5388 int i;
5389 char *crlfilename, *crlfile, *dirpath, *certfile;
5391 if (numattr == 0 || attrlist == NULL) {
5392 return (KMF_ERR_BAD_PARAMETER);
5395 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5396 attrlist, numattr);
5398 if (crlfilename == NULL)
5399 return (KMF_ERR_BAD_CRLFILE);
5401 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5402 if (certfile == NULL)
5403 return (KMF_ERR_BAD_CRLFILE);
5405 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5407 crlfile = get_fullpath(dirpath, crlfilename);
5409 if (crlfile == NULL)
5410 return (KMF_ERR_BAD_CRLFILE);
5412 if (isdir(crlfile)) {
5413 ret = KMF_ERR_BAD_CRLFILE;
5414 goto end;
5417 ret = kmf_is_crl_file(handle, crlfile, &format);
5418 if (ret != KMF_OK)
5419 goto end;
5421 /* Read the CRL file and load it into a X509_CRL structure */
5422 in = BIO_new_file(crlfilename, "rb");
5423 if (in == NULL) {
5424 SET_ERROR(kmfh, ERR_get_error());
5425 ret = KMF_ERR_OPEN_FILE;
5426 goto end;
5429 if (format == KMF_FORMAT_ASN1) {
5430 xcrl = d2i_X509_CRL_bio(in, NULL);
5431 } else if (format == KMF_FORMAT_PEM) {
5432 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5435 if (xcrl == NULL) {
5436 SET_ERROR(kmfh, ERR_get_error());
5437 ret = KMF_ERR_BAD_CRLFILE;
5438 goto end;
5440 (void) BIO_free(in);
5442 /* Read the Certificate file and load it into a X509 structure */
5443 ret = kmf_is_cert_file(handle, certfile, &format);
5444 if (ret != KMF_OK)
5445 goto end;
5447 in = BIO_new_file(certfile, "rb");
5448 if (in == NULL) {
5449 SET_ERROR(kmfh, ERR_get_error());
5450 ret = KMF_ERR_OPEN_FILE;
5451 goto end;
5454 if (format == KMF_FORMAT_ASN1) {
5455 xcert = d2i_X509_bio(in, NULL);
5456 } else if (format == KMF_FORMAT_PEM) {
5457 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5460 if (xcert == NULL) {
5461 SET_ERROR(kmfh, ERR_get_error());
5462 ret = KMF_ERR_BAD_CERTFILE;
5463 goto end;
5466 /* Check if the certificate and the CRL have same issuer */
5467 if (X509_NAME_cmp(X509_get_issuer_name(xcert),
5468 X509_CRL_get_issuer(xcrl)) != 0) {
5469 ret = KMF_ERR_ISSUER;
5470 goto end;
5473 /* Check to see if the certificate serial number is revoked */
5474 revoke_stack = X509_CRL_get_REVOKED(xcrl);
5475 if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5476 /* No revoked certificates in the CRL file */
5477 SET_ERROR(kmfh, ERR_get_error());
5478 ret = KMF_ERR_EMPTY_CRL;
5479 goto end;
5482 for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5483 /* LINTED E_BAD_PTR_CAST_ALIGN */
5484 revoke = sk_X509_REVOKED_value(revoke_stack, i);
5485 if (ASN1_INTEGER_cmp(X509_get_serialNumber(xcert),
5486 X509_REVOKED_get0_serialNumber(revoke)) == 0) {
5487 break;
5491 if (i < sk_X509_REVOKED_num(revoke_stack)) {
5492 ret = KMF_OK;
5493 } else {
5494 ret = KMF_ERR_NOT_REVOKED;
5497 end:
5498 if (in != NULL)
5499 (void) BIO_free(in);
5500 if (xcrl != NULL)
5501 X509_CRL_free(xcrl);
5502 if (xcert != NULL)
5503 X509_free(xcert);
5505 return (ret);
5508 KMF_RETURN
5509 OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5511 KMF_RETURN ret = KMF_OK;
5512 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5513 BIO *bcrl = NULL;
5514 X509_CRL *xcrl = NULL;
5515 X509 *xcert = NULL;
5516 EVP_PKEY *pkey;
5517 int sslret;
5518 KMF_ENCODE_FORMAT crl_format;
5519 unsigned char *p;
5520 long len;
5522 if (handle == NULL || crlname == NULL || tacert == NULL) {
5523 return (KMF_ERR_BAD_PARAMETER);
5526 ret = kmf_get_file_format(crlname, &crl_format);
5527 if (ret != KMF_OK)
5528 return (ret);
5530 bcrl = BIO_new_file(crlname, "rb");
5531 if (bcrl == NULL) {
5532 SET_ERROR(kmfh, ERR_get_error());
5533 ret = KMF_ERR_OPEN_FILE;
5534 goto cleanup;
5537 if (crl_format == KMF_FORMAT_ASN1) {
5538 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5539 } else if (crl_format == KMF_FORMAT_PEM) {
5540 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5541 } else {
5542 ret = KMF_ERR_BAD_PARAMETER;
5543 goto cleanup;
5546 if (xcrl == NULL) {
5547 SET_ERROR(kmfh, ERR_get_error());
5548 ret = KMF_ERR_BAD_CRLFILE;
5549 goto cleanup;
5552 p = tacert->Data;
5553 len = tacert->Length;
5554 xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5556 if (xcert == NULL) {
5557 SET_ERROR(kmfh, ERR_get_error());
5558 ret = KMF_ERR_BAD_CERTFILE;
5559 goto cleanup;
5562 /* Get issuer certificate public key */
5563 pkey = X509_get_pubkey(xcert);
5564 if (pkey == NULL) {
5565 SET_ERROR(kmfh, ERR_get_error());
5566 ret = KMF_ERR_BAD_CERT_FORMAT;
5567 goto cleanup;
5570 /* Verify CRL signature */
5571 sslret = X509_CRL_verify(xcrl, pkey);
5572 EVP_PKEY_free(pkey);
5573 if (sslret > 0) {
5574 ret = KMF_OK;
5575 } else {
5576 SET_ERROR(kmfh, sslret);
5577 ret = KMF_ERR_BAD_CRLFILE;
5580 cleanup:
5581 if (bcrl != NULL)
5582 (void) BIO_free(bcrl);
5584 if (xcrl != NULL)
5585 X509_CRL_free(xcrl);
5587 if (xcert != NULL)
5588 X509_free(xcert);
5590 return (ret);
5594 KMF_RETURN
5595 OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5597 KMF_RETURN ret = KMF_OK;
5598 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5599 KMF_ENCODE_FORMAT crl_format;
5600 BIO *bcrl = NULL;
5601 X509_CRL *xcrl = NULL;
5602 int i;
5604 if (handle == NULL || crlname == NULL) {
5605 return (KMF_ERR_BAD_PARAMETER);
5608 ret = kmf_is_crl_file(handle, crlname, &crl_format);
5609 if (ret != KMF_OK)
5610 return (ret);
5612 bcrl = BIO_new_file(crlname, "rb");
5613 if (bcrl == NULL) {
5614 SET_ERROR(kmfh, ERR_get_error());
5615 ret = KMF_ERR_OPEN_FILE;
5616 goto cleanup;
5619 if (crl_format == KMF_FORMAT_ASN1)
5620 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5621 else if (crl_format == KMF_FORMAT_PEM)
5622 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5624 if (xcrl == NULL) {
5625 SET_ERROR(kmfh, ERR_get_error());
5626 ret = KMF_ERR_BAD_CRLFILE;
5627 goto cleanup;
5629 i = X509_cmp_time(X509_CRL_get0_lastUpdate(xcrl), NULL);
5630 if (i >= 0) {
5631 ret = KMF_ERR_VALIDITY_PERIOD;
5632 goto cleanup;
5634 if (X509_CRL_get0_nextUpdate(xcrl)) {
5635 i = X509_cmp_time(X509_CRL_get0_nextUpdate(xcrl), NULL);
5637 if (i <= 0) {
5638 ret = KMF_ERR_VALIDITY_PERIOD;
5639 goto cleanup;
5643 ret = KMF_OK;
5645 cleanup:
5646 if (bcrl != NULL)
5647 (void) BIO_free(bcrl);
5649 if (xcrl != NULL)
5650 X509_CRL_free(xcrl);
5652 return (ret);