9070 Remove wanboot from gate
[unleashed.git] / usr / src / lib / libkmf / plugins / kmf_openssl / common / openssl_spi.c
blob46aea6a2aa74b41473bbec908e4cf08579ac1715
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 */
9 /*
10 * Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
11 * project 2000.
14 * ====================================================================
15 * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in
26 * the documentation and/or other materials provided with the
27 * distribution.
29 * 3. All advertising materials mentioning features or use of this
30 * software must display the following acknowledgment:
31 * "This product includes software developed by the OpenSSL Project
32 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
34 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
35 * endorse or promote products derived from this software without
36 * prior written permission. For written permission, please contact
37 * licensing@OpenSSL.org.
39 * 5. Products derived from this software may not be called "OpenSSL"
40 * nor may "OpenSSL" appear in their names without prior written
41 * permission of the OpenSSL Project.
43 * 6. Redistributions of any form whatsoever must retain the following
44 * acknowledgment:
45 * "This product includes software developed by the OpenSSL Project
46 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
48 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
49 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
52 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
57 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
59 * OF THE POSSIBILITY OF SUCH DAMAGE.
60 * ====================================================================
62 * This product includes cryptographic software written by Eric Young
63 * (eay@cryptsoft.com). This product includes software written by Tim
64 * Hudson (tjh@cryptsoft.com).
68 #include <stdlib.h>
69 #include <kmfapiP.h>
70 #include <ber_der.h>
71 #include <fcntl.h>
72 #include <sys/stat.h>
73 #include <dirent.h>
74 #include <cryptoutil.h>
75 #include <synch.h>
76 #include <thread.h>
78 /* OPENSSL related headers */
79 #include <openssl/bio.h>
80 #include <openssl/bn.h>
81 #include <openssl/asn1.h>
82 #include <openssl/err.h>
83 #include <openssl/bn.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>
95 #define PRINT_ANY_EXTENSION (\
96 KMF_X509_EXT_KEY_USAGE |\
97 KMF_X509_EXT_CERT_POLICIES |\
98 KMF_X509_EXT_SUBJALTNAME |\
99 KMF_X509_EXT_BASIC_CONSTRAINTS |\
100 KMF_X509_EXT_NAME_CONSTRAINTS |\
101 KMF_X509_EXT_POLICY_CONSTRAINTS |\
102 KMF_X509_EXT_EXT_KEY_USAGE |\
103 KMF_X509_EXT_INHIBIT_ANY_POLICY |\
104 KMF_X509_EXT_AUTH_KEY_ID |\
105 KMF_X509_EXT_SUBJ_KEY_ID |\
106 KMF_X509_EXT_POLICY_MAPPING)
108 static uchar_t P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
109 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
110 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
111 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
112 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
113 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
114 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
115 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
116 0x91 };
118 static uchar_t Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
119 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
120 0x8e, 0xda, 0xce, 0x91, 0x5f };
122 static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
123 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
124 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
125 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
126 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
127 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
128 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
129 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
130 0x02 };
132 #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_OPENSSL; \
133 h->lasterr.errcode = c;
135 #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c;
138 * Declare some new macros for managing stacks of EVP_PKEYS.
140 DECLARE_STACK_OF(EVP_PKEY)
142 #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
143 #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
144 #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
145 #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
146 #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
147 #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
148 (free_func))
150 mutex_t init_lock = DEFAULTMUTEX;
151 static int ssl_initialized = 0;
152 static BIO *bio_err = NULL;
154 static int
155 test_for_file(char *, mode_t);
156 static KMF_RETURN
157 openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
158 STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
160 static KMF_RETURN
161 local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
162 int, KMF_KEY_HANDLE *, char *);
164 static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
166 static KMF_RETURN
167 extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
168 CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
170 static KMF_RETURN
171 kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
172 char *, KMF_DATA *);
174 static KMF_RETURN
175 load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
176 char *, KMF_DATA **, uint32_t *);
178 static KMF_RETURN
179 sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
181 static EVP_PKEY *
182 ImportRawRSAKey(KMF_RAW_RSA_KEY *);
184 static KMF_RETURN
185 convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
187 KMF_RETURN
188 OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
190 void
191 OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
193 KMF_RETURN
194 OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
196 KMF_RETURN
197 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
199 KMF_RETURN
200 OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
202 KMF_RETURN
203 OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
205 KMF_RETURN
206 OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
208 KMF_RETURN
209 OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
210 KMF_DATA *, KMF_DATA *);
212 KMF_RETURN
213 OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
215 KMF_RETURN
216 OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
218 KMF_RETURN
219 OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
221 KMF_RETURN
222 OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
224 KMF_RETURN
225 OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
227 KMF_RETURN
228 OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
229 KMF_PRINTABLE_ITEM, char *);
231 KMF_RETURN
232 OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
234 KMF_RETURN
235 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
237 KMF_RETURN
238 OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
239 KMF_DATA *, KMF_DATA *);
241 KMF_RETURN
242 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
244 KMF_RETURN
245 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
247 KMF_RETURN
248 OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
250 KMF_RETURN
251 OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
253 KMF_RETURN
254 OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
256 KMF_RETURN
257 OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
259 KMF_RETURN
260 OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
262 KMF_RETURN
263 OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
265 static
266 KMF_PLUGIN_FUNCLIST openssl_plugin_table =
268 1, /* Version */
269 NULL, /* ConfigureKeystore */
270 OpenSSL_FindCert,
271 OpenSSL_FreeKMFCert,
272 OpenSSL_StoreCert,
273 NULL, /* ImportCert */
274 OpenSSL_ImportCRL,
275 OpenSSL_DeleteCert,
276 OpenSSL_DeleteCRL,
277 OpenSSL_CreateKeypair,
278 OpenSSL_FindKey,
279 OpenSSL_EncodePubKeyData,
280 OpenSSL_SignData,
281 OpenSSL_DeleteKey,
282 OpenSSL_ListCRL,
283 NULL, /* FindCRL */
284 OpenSSL_FindCertInCRL,
285 OpenSSL_GetErrorString,
286 OpenSSL_FindPrikeyByCert,
287 OpenSSL_DecryptData,
288 OpenSSL_ExportPK12,
289 OpenSSL_CreateSymKey,
290 OpenSSL_GetSymKeyValue,
291 NULL, /* SetTokenPin */
292 OpenSSL_StoreKey,
293 NULL /* Finalize */
296 static mutex_t *lock_cs;
297 static long *lock_count;
299 static void
300 /* ARGSUSED1 */
301 locking_cb(int mode, int type, char *file, int line)
303 if (mode & CRYPTO_LOCK) {
304 (void) mutex_lock(&(lock_cs[type]));
305 lock_count[type]++;
306 } else {
307 (void) mutex_unlock(&(lock_cs[type]));
311 static unsigned long
312 thread_id()
314 return ((unsigned long)thr_self());
317 KMF_PLUGIN_FUNCLIST *
318 KMF_Plugin_Initialize()
320 int i;
322 (void) mutex_lock(&init_lock);
323 if (!ssl_initialized) {
325 * Add support for extension OIDs that are not yet in the
326 * openssl default set.
328 (void) OBJ_create("2.5.29.30", "nameConstraints",
329 "X509v3 Name Constraints");
330 (void) OBJ_create("2.5.29.33", "policyMappings",
331 "X509v3 Policy Mappings");
332 (void) OBJ_create("2.5.29.36", "policyConstraints",
333 "X509v3 Policy Constraints");
334 (void) OBJ_create("2.5.29.46", "freshestCRL",
335 "X509v3 Freshest CRL");
336 (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
337 "X509v3 Inhibit Any-Policy");
339 * Set up for thread-safe operation.
341 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
342 if (lock_cs == NULL) {
343 (void) mutex_unlock(&init_lock);
344 return (NULL);
347 lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
348 if (lock_count == NULL) {
349 OPENSSL_free(lock_cs);
350 (void) mutex_unlock(&init_lock);
351 return (NULL);
354 for (i = 0; i < CRYPTO_num_locks(); i++) {
355 lock_count[i] = 0;
356 (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
359 CRYPTO_set_id_callback((unsigned long (*)())thread_id);
360 if (CRYPTO_get_locking_callback() == NULL)
361 CRYPTO_set_locking_callback((void (*)())locking_cb);
363 OpenSSL_add_all_algorithms();
365 /* Enable error strings for reporting */
366 ERR_load_crypto_strings();
368 ssl_initialized = 1;
370 (void) mutex_unlock(&init_lock);
372 return (&openssl_plugin_table);
375 * Convert an SSL DN to a KMF DN.
377 static KMF_RETURN
378 get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
380 KMF_DATA derdata;
381 KMF_RETURN rv = KMF_OK;
382 uchar_t *tmp;
384 /* Convert to raw DER format */
385 derdata.Length = i2d_X509_NAME(sslDN, NULL);
386 if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
387 == NULL) {
388 return (KMF_ERR_MEMORY);
390 (void) i2d_X509_NAME(sslDN, &tmp);
392 /* Decode to KMF format */
393 rv = DerDecodeName(&derdata, kmfDN);
394 if (rv != KMF_OK) {
395 rv = KMF_ERR_BAD_CERT_FORMAT;
397 OPENSSL_free(derdata.Data);
399 return (rv);
403 isdir(char *path)
405 struct stat s;
407 if (stat(path, &s) == -1)
408 return (0);
410 return ((s.st_mode & S_IFMT) == S_IFDIR);
413 static KMF_RETURN
414 ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
416 KMF_RETURN rv = KMF_OK;
417 unsigned char *buf = NULL, *p;
418 int len;
421 * Convert the X509 internal struct to DER encoded data
423 if ((len = i2d_X509(x509cert, NULL)) < 0) {
424 SET_ERROR(kmfh, ERR_get_error());
425 rv = KMF_ERR_BAD_CERT_FORMAT;
426 goto cleanup;
428 if ((buf = malloc(len)) == NULL) {
429 SET_SYS_ERROR(kmfh, errno);
430 rv = KMF_ERR_MEMORY;
431 goto cleanup;
435 * i2d_X509 will increment the buf pointer so that we need to
436 * save it.
438 p = buf;
439 if ((len = i2d_X509(x509cert, &p)) < 0) {
440 SET_ERROR(kmfh, ERR_get_error());
441 free(buf);
442 rv = KMF_ERR_BAD_CERT_FORMAT;
443 goto cleanup;
446 /* caller's responsibility to free it */
447 cert->Data = buf;
448 cert->Length = len;
450 cleanup:
451 if (rv != KMF_OK) {
452 if (buf)
453 free(buf);
454 cert->Data = NULL;
455 cert->Length = 0;
458 return (rv);
462 static KMF_RETURN
463 check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
464 boolean_t *match)
466 KMF_RETURN rv = KMF_OK;
467 boolean_t findIssuer = FALSE;
468 boolean_t findSubject = FALSE;
469 boolean_t findSerial = FALSE;
470 KMF_X509_NAME issuerDN, subjectDN;
471 KMF_X509_NAME certIssuerDN, certSubjectDN;
473 *match = FALSE;
474 if (xcert == NULL) {
475 return (KMF_ERR_BAD_PARAMETER);
478 (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
479 (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
480 (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
481 (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
483 if (issuer != NULL && strlen(issuer)) {
484 rv = kmf_dn_parser(issuer, &issuerDN);
485 if (rv != KMF_OK)
486 return (KMF_ERR_BAD_PARAMETER);
488 rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
489 if (rv != KMF_OK) {
490 kmf_free_dn(&issuerDN);
491 return (KMF_ERR_BAD_PARAMETER);
494 findIssuer = TRUE;
496 if (subject != NULL && strlen(subject)) {
497 rv = kmf_dn_parser(subject, &subjectDN);
498 if (rv != KMF_OK) {
499 rv = KMF_ERR_BAD_PARAMETER;
500 goto cleanup;
503 rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
504 if (rv != KMF_OK) {
505 rv = KMF_ERR_BAD_PARAMETER;
506 goto cleanup;
508 findSubject = TRUE;
510 if (serial != NULL && serial->val != NULL)
511 findSerial = TRUE;
513 if (findSerial) {
514 BIGNUM *bn;
516 /* Comparing BIGNUMs is a pain! */
517 bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
518 if (bn != NULL) {
519 int bnlen = BN_num_bytes(bn);
521 if (bnlen == serial->len) {
522 uchar_t *a = malloc(bnlen);
523 if (a == NULL) {
524 rv = KMF_ERR_MEMORY;
525 BN_free(bn);
526 goto cleanup;
528 bnlen = BN_bn2bin(bn, a);
529 *match = (memcmp(a, serial->val, serial->len) ==
531 rv = KMF_OK;
532 free(a);
534 BN_free(bn);
535 if (!(*match))
536 goto cleanup;
537 } else {
538 rv = KMF_OK;
539 goto cleanup;
542 if (findIssuer) {
543 *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
544 if ((*match) == B_FALSE) {
545 /* stop checking and bail */
546 rv = KMF_OK;
547 goto cleanup;
550 if (findSubject) {
551 *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
552 if ((*match) == B_FALSE) {
553 /* stop checking and bail */
554 rv = KMF_OK;
555 goto cleanup;
559 *match = TRUE;
560 cleanup:
561 if (findIssuer) {
562 kmf_free_dn(&issuerDN);
563 kmf_free_dn(&certIssuerDN);
565 if (findSubject) {
566 kmf_free_dn(&subjectDN);
567 kmf_free_dn(&certSubjectDN);
570 return (rv);
575 * This function loads a certificate file into an X509 data structure, and
576 * checks if its issuer, subject or the serial number matches with those
577 * values. If it matches, then return the X509 data structure.
579 static KMF_RETURN
580 load_X509cert(KMF_HANDLE *kmfh,
581 char *issuer, char *subject, KMF_BIGINT *serial,
582 char *pathname, X509 **outcert)
584 KMF_RETURN rv = KMF_OK;
585 X509 *xcert = NULL;
586 BIO *bcert = NULL;
587 boolean_t match = FALSE;
588 KMF_ENCODE_FORMAT format;
591 * auto-detect the file format, regardless of what
592 * the 'format' parameters in the params say.
594 rv = kmf_get_file_format(pathname, &format);
595 if (rv != KMF_OK) {
596 if (rv == KMF_ERR_OPEN_FILE)
597 rv = KMF_ERR_CERT_NOT_FOUND;
598 return (rv);
601 /* Not ASN1(DER) format */
602 if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
603 SET_ERROR(kmfh, ERR_get_error());
604 rv = KMF_ERR_OPEN_FILE;
605 goto cleanup;
608 if (format == KMF_FORMAT_PEM)
609 xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
610 else if (format == KMF_FORMAT_ASN1)
611 xcert = d2i_X509_bio(bcert, NULL);
612 else if (format == KMF_FORMAT_PKCS12) {
613 PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
614 if (p12 != NULL) {
615 (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
616 PKCS12_free(p12);
617 p12 = NULL;
618 } else {
619 SET_ERROR(kmfh, ERR_get_error());
620 rv = KMF_ERR_BAD_CERT_FORMAT;
622 } else {
623 rv = KMF_ERR_BAD_PARAMETER;
624 goto cleanup;
627 if (xcert == NULL) {
628 SET_ERROR(kmfh, ERR_get_error());
629 rv = KMF_ERR_BAD_CERT_FORMAT;
630 goto cleanup;
633 if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
634 match == FALSE) {
635 rv = KMF_ERR_CERT_NOT_FOUND;
636 goto cleanup;
639 if (outcert != NULL) {
640 *outcert = xcert;
643 cleanup:
644 if (bcert != NULL) (void) BIO_free(bcert);
645 if (rv != KMF_OK && xcert != NULL)
646 X509_free(xcert);
648 return (rv);
651 static int
652 datacmp(const void *a, const void *b)
654 KMF_DATA *adata = (KMF_DATA *)a;
655 KMF_DATA *bdata = (KMF_DATA *)b;
656 if (adata->Length > bdata->Length)
657 return (-1);
658 if (adata->Length < bdata->Length)
659 return (1);
660 return (0);
663 static KMF_RETURN
664 load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
665 KMF_CERT_VALIDITY validity, char *pathname,
666 KMF_DATA **certlist, uint32_t *numcerts)
668 KMF_RETURN rv = KMF_OK;
669 int i;
670 KMF_DATA *certs = NULL;
671 int nc = 0;
672 int hits = 0;
673 KMF_ENCODE_FORMAT format;
675 rv = kmf_get_file_format(pathname, &format);
676 if (rv != KMF_OK) {
677 if (rv == KMF_ERR_OPEN_FILE)
678 rv = KMF_ERR_CERT_NOT_FOUND;
679 return (rv);
681 if (format == KMF_FORMAT_ASN1) {
682 /* load a single certificate */
683 certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
684 if (certs == NULL)
685 return (KMF_ERR_MEMORY);
686 certs->Data = NULL;
687 certs->Length = 0;
688 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
689 pathname, certs);
690 if (rv == KMF_OK) {
691 *certlist = certs;
692 *numcerts = 1;
693 } else {
694 kmf_free_data(certs);
695 free(certs);
696 certs = NULL;
698 return (rv);
699 } else if (format == KMF_FORMAT_PKCS12) {
700 /* We need a credential to access a PKCS#12 file */
701 rv = KMF_ERR_BAD_CERT_FORMAT;
702 } else if (format == KMF_FORMAT_PEM ||
703 format != KMF_FORMAT_PEM_KEYPAIR) {
705 /* This function only works on PEM files */
706 rv = extract_pem(kmfh, issuer, subject, serial, pathname,
707 (uchar_t *)NULL, 0, NULL, &certs, &nc);
708 } else {
709 return (KMF_ERR_ENCODING);
712 if (rv != KMF_OK)
713 return (rv);
715 for (i = 0; i < nc; i++) {
716 if (validity == KMF_NONEXPIRED_CERTS) {
717 rv = kmf_check_cert_date(kmfh, &certs[i]);
718 } else if (validity == KMF_EXPIRED_CERTS) {
719 rv = kmf_check_cert_date(kmfh, &certs[i]);
720 if (rv == KMF_OK)
721 rv = KMF_ERR_CERT_NOT_FOUND;
722 if (rv == KMF_ERR_VALIDITY_PERIOD)
723 rv = KMF_OK;
725 if (rv != KMF_OK) {
726 /* Remove this cert from the list by clearing it. */
727 kmf_free_data(&certs[i]);
728 } else {
729 hits++; /* count valid certs found */
731 rv = KMF_OK;
733 if (rv == KMF_OK && hits > 0) {
735 * Sort the list of certs by length to put the cleared ones
736 * at the end so they don't get accessed by the caller.
738 qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
739 *certlist = certs;
741 /* since we sorted the list, just return the number of hits */
742 *numcerts = hits;
743 } else {
744 if (rv == KMF_OK && hits == 0)
745 rv = KMF_ERR_CERT_NOT_FOUND;
746 if (certs != NULL) {
747 free(certs);
748 certs = NULL;
751 return (rv);
754 static KMF_RETURN
755 kmf_load_cert(KMF_HANDLE *kmfh,
756 char *issuer, char *subject, KMF_BIGINT *serial,
757 KMF_CERT_VALIDITY validity,
758 char *pathname,
759 KMF_DATA *cert)
761 KMF_RETURN rv = KMF_OK;
762 X509 *x509cert = NULL;
764 rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
765 if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
766 rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
767 if (rv != KMF_OK) {
768 goto cleanup;
770 if (validity == KMF_NONEXPIRED_CERTS) {
771 rv = kmf_check_cert_date(kmfh, cert);
772 } else if (validity == KMF_EXPIRED_CERTS) {
773 rv = kmf_check_cert_date(kmfh, cert);
774 if (rv == KMF_OK) {
776 * This is a valid cert so skip it.
778 rv = KMF_ERR_CERT_NOT_FOUND;
780 if (rv == KMF_ERR_VALIDITY_PERIOD) {
782 * We want to return success when we
783 * find an invalid cert.
785 rv = KMF_OK;
786 goto cleanup;
790 cleanup:
791 if (x509cert != NULL)
792 X509_free(x509cert);
794 return (rv);
797 static KMF_RETURN
798 readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
800 KMF_RETURN ret = KMF_OK;
801 KMF_RAW_RSA_KEY rsa;
802 BerElement *asn1 = NULL;
803 BerValue filebuf;
804 BerValue OID = { NULL, 0 };
805 BerValue *Mod = NULL, *PubExp = NULL;
806 BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
807 BerValue *Coef = NULL;
808 BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
809 BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
810 BIGNUM *qminus1 = NULL;
811 BN_CTX *ctx = NULL;
813 *pkey = NULL;
815 filebuf.bv_val = (char *)filedata->Data;
816 filebuf.bv_len = filedata->Length;
818 asn1 = kmfder_init(&filebuf);
819 if (asn1 == NULL) {
820 ret = KMF_ERR_MEMORY;
821 goto out;
824 if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
825 &OID, &Mod, &PubExp, &PriExp, &Prime1,
826 &Prime2, &Coef) == -1) {
827 ret = KMF_ERR_ENCODING;
828 goto out;
832 * We have to derive the 2 Exponents using Bignumber math.
833 * Exp1 = PriExp mod (Prime1 - 1)
834 * Exp2 = PriExp mod (Prime2 - 1)
837 /* D = PrivateExponent */
838 D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
839 if (D == NULL) {
840 ret = KMF_ERR_MEMORY;
841 goto out;
844 /* P = Prime1 (first prime factor of Modulus) */
845 P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
846 if (D == NULL) {
847 ret = KMF_ERR_MEMORY;
848 goto out;
851 /* Q = Prime2 (second prime factor of Modulus) */
852 Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
854 if ((ctx = BN_CTX_new()) == NULL) {
855 ret = KMF_ERR_MEMORY;
856 goto out;
859 /* Compute (P - 1) */
860 pminus1 = BN_new();
861 (void) BN_sub(pminus1, P, BN_value_one());
863 /* Exponent1 = D mod (P - 1) */
864 Exp1 = BN_new();
865 (void) BN_mod(Exp1, D, pminus1, ctx);
867 /* Compute (Q - 1) */
868 qminus1 = BN_new();
869 (void) BN_sub(qminus1, Q, BN_value_one());
871 /* Exponent2 = D mod (Q - 1) */
872 Exp2 = BN_new();
873 (void) BN_mod(Exp2, D, qminus1, ctx);
875 /* Coef = (Inverse Q) mod P */
876 COEF = BN_new();
877 (void) BN_mod_inverse(COEF, Q, P, ctx);
879 /* Convert back to KMF format */
880 (void) memset(&rsa, 0, sizeof (rsa));
882 if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
883 goto out;
884 if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
885 goto out;
886 if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
887 goto out;
889 rsa.mod.val = (uchar_t *)Mod->bv_val;
890 rsa.mod.len = Mod->bv_len;
892 rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
893 rsa.pubexp.len = PubExp->bv_len;
895 rsa.priexp.val = (uchar_t *)PriExp->bv_val;
896 rsa.priexp.len = PriExp->bv_len;
898 rsa.prime1.val = (uchar_t *)Prime1->bv_val;
899 rsa.prime1.len = Prime1->bv_len;
901 rsa.prime2.val = (uchar_t *)Prime2->bv_val;
902 rsa.prime2.len = Prime2->bv_len;
904 *pkey = ImportRawRSAKey(&rsa);
905 out:
906 if (asn1 != NULL)
907 kmfber_free(asn1, 1);
909 if (OID.bv_val) {
910 free(OID.bv_val);
912 if (PriExp)
913 free(PriExp);
915 if (Mod)
916 free(Mod);
918 if (PubExp)
919 free(PubExp);
921 if (Coef) {
922 (void) memset(Coef->bv_val, 0, Coef->bv_len);
923 free(Coef->bv_val);
924 free(Coef);
926 if (Prime1)
927 free(Prime1);
928 if (Prime2)
929 free(Prime2);
931 if (ctx != NULL)
932 BN_CTX_free(ctx);
934 if (D)
935 BN_clear_free(D);
936 if (P)
937 BN_clear_free(P);
938 if (Q)
939 BN_clear_free(Q);
940 if (pminus1)
941 BN_clear_free(pminus1);
942 if (qminus1)
943 BN_clear_free(qminus1);
944 if (Exp1)
945 BN_clear_free(Exp1);
946 if (Exp2)
947 BN_clear_free(Exp2);
949 return (ret);
953 static EVP_PKEY *
954 openssl_load_key(KMF_HANDLE_T handle, const char *file)
956 BIO *keyfile = NULL;
957 EVP_PKEY *pkey = NULL;
958 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
959 KMF_ENCODE_FORMAT format;
960 KMF_RETURN rv;
961 KMF_DATA filedata;
963 if (file == NULL) {
964 return (NULL);
967 if (kmf_get_file_format((char *)file, &format) != KMF_OK)
968 return (NULL);
970 keyfile = BIO_new_file(file, "rb");
971 if (keyfile == NULL) {
972 goto end;
975 if (format == KMF_FORMAT_ASN1) {
976 pkey = d2i_PrivateKey_bio(keyfile, NULL);
977 if (pkey == NULL) {
979 (void) BIO_free(keyfile);
980 keyfile = NULL;
981 /* Try odd ASN.1 variations */
982 rv = kmf_read_input_file(kmfh, (char *)file,
983 &filedata);
984 if (rv == KMF_OK) {
985 (void) readAltFormatPrivateKey(&filedata,
986 &pkey);
987 kmf_free_data(&filedata);
990 } else if (format == KMF_FORMAT_PEM ||
991 format == KMF_FORMAT_PEM_KEYPAIR) {
992 pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
993 if (pkey == NULL) {
994 KMF_DATA derdata;
996 * Check if this is the alt. format
997 * RSA private key file.
999 rv = kmf_read_input_file(kmfh, (char *)file,
1000 &filedata);
1001 if (rv == KMF_OK) {
1002 uchar_t *d = NULL;
1003 int len;
1004 rv = kmf_pem_to_der(filedata.Data,
1005 filedata.Length, &d, &len);
1006 if (rv == KMF_OK && d != NULL) {
1007 derdata.Data = d;
1008 derdata.Length = (size_t)len;
1009 (void) readAltFormatPrivateKey(
1010 &derdata, &pkey);
1011 free(d);
1013 kmf_free_data(&filedata);
1018 end:
1019 if (pkey == NULL)
1020 SET_ERROR(kmfh, ERR_get_error());
1022 if (keyfile != NULL)
1023 (void) BIO_free(keyfile);
1025 return (pkey);
1028 KMF_RETURN
1029 OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1031 KMF_RETURN rv = KMF_OK;
1032 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1033 int i, n;
1034 uint32_t maxcerts = 0;
1035 uint32_t *num_certs;
1036 KMF_X509_DER_CERT *kmf_cert = NULL;
1037 char *dirpath = NULL;
1038 char *filename = NULL;
1039 char *fullpath = NULL;
1040 char *issuer = NULL;
1041 char *subject = NULL;
1042 KMF_BIGINT *serial = NULL;
1043 KMF_CERT_VALIDITY validity;
1045 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1046 if (num_certs == NULL)
1047 return (KMF_ERR_BAD_PARAMETER);
1049 /* num_certs should reference the size of kmf_cert */
1050 maxcerts = *num_certs;
1051 if (maxcerts == 0)
1052 maxcerts = 0xFFFFFFFF;
1053 *num_certs = 0;
1055 /* Get the optional returned certificate list */
1056 kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1057 numattr);
1060 * The dirpath attribute and the filename attribute can not be NULL
1061 * at the same time.
1063 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1064 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1065 numattr);
1067 fullpath = get_fullpath(dirpath, filename);
1068 if (fullpath == NULL)
1069 return (KMF_ERR_BAD_PARAMETER);
1071 /* Get optional search criteria attributes */
1072 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1073 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1074 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1075 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1076 &validity, NULL);
1077 if (rv != KMF_OK) {
1078 validity = KMF_ALL_CERTS;
1079 rv = KMF_OK;
1082 if (isdir(fullpath)) {
1083 DIR *dirp;
1084 struct dirent *dp;
1086 n = 0;
1087 /* open all files in the directory and attempt to read them */
1088 if ((dirp = opendir(fullpath)) == NULL) {
1089 return (KMF_ERR_BAD_PARAMETER);
1091 while ((dp = readdir(dirp)) != NULL) {
1092 char *fname;
1093 KMF_DATA *certlist = NULL;
1094 uint32_t loaded_certs = 0;
1096 if (strcmp(dp->d_name, ".") == 0 ||
1097 strcmp(dp->d_name, "..") == 0)
1098 continue;
1100 fname = get_fullpath(fullpath, (char *)&dp->d_name);
1102 rv = load_certs(kmfh, issuer, subject, serial,
1103 validity, fname, &certlist, &loaded_certs);
1105 if (rv != KMF_OK) {
1106 free(fname);
1107 if (certlist != NULL) {
1108 for (i = 0; i < loaded_certs; i++)
1109 kmf_free_data(&certlist[i]);
1110 free(certlist);
1112 continue;
1115 /* If load succeeds, add certdata to the list */
1116 if (kmf_cert != NULL) {
1117 for (i = 0; i < loaded_certs &&
1118 n < maxcerts; i++) {
1119 kmf_cert[n].certificate.Data =
1120 certlist[i].Data;
1121 kmf_cert[n].certificate.Length =
1122 certlist[i].Length;
1124 kmf_cert[n].kmf_private.keystore_type =
1125 KMF_KEYSTORE_OPENSSL;
1126 kmf_cert[n].kmf_private.flags =
1127 KMF_FLAG_CERT_VALID;
1128 kmf_cert[n].kmf_private.label =
1129 strdup(fname);
1130 n++;
1133 * If maxcerts < loaded_certs, clean up the
1134 * certs that were not used.
1136 for (; i < loaded_certs; i++)
1137 kmf_free_data(&certlist[i]);
1138 } else {
1139 for (i = 0; i < loaded_certs; i++)
1140 kmf_free_data(&certlist[i]);
1141 n += loaded_certs;
1143 free(certlist);
1144 free(fname);
1146 (*num_certs) = n;
1147 if (*num_certs == 0)
1148 rv = KMF_ERR_CERT_NOT_FOUND;
1149 if (*num_certs > 0)
1150 rv = KMF_OK;
1151 exit:
1152 (void) closedir(dirp);
1153 } else {
1154 KMF_DATA *certlist = NULL;
1155 uint32_t loaded_certs = 0;
1157 rv = load_certs(kmfh, issuer, subject, serial, validity,
1158 fullpath, &certlist, &loaded_certs);
1159 if (rv != KMF_OK) {
1160 free(fullpath);
1161 return (rv);
1164 n = 0;
1165 if (kmf_cert != NULL && certlist != NULL) {
1166 for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1167 kmf_cert[n].certificate.Data =
1168 certlist[i].Data;
1169 kmf_cert[n].certificate.Length =
1170 certlist[i].Length;
1171 kmf_cert[n].kmf_private.keystore_type =
1172 KMF_KEYSTORE_OPENSSL;
1173 kmf_cert[n].kmf_private.flags =
1174 KMF_FLAG_CERT_VALID;
1175 kmf_cert[n].kmf_private.label =
1176 strdup(fullpath);
1177 n++;
1179 /* If maxcerts < loaded_certs, clean up */
1180 for (; i < loaded_certs; i++)
1181 kmf_free_data(&certlist[i]);
1182 } else if (certlist != NULL) {
1183 for (i = 0; i < loaded_certs; i++)
1184 kmf_free_data(&certlist[i]);
1185 n = loaded_certs;
1187 if (certlist != NULL)
1188 free(certlist);
1189 *num_certs = n;
1192 free(fullpath);
1194 return (rv);
1197 void
1198 /*ARGSUSED*/
1199 OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
1200 KMF_X509_DER_CERT *kmf_cert)
1202 if (kmf_cert != NULL) {
1203 if (kmf_cert->certificate.Data != NULL) {
1204 kmf_free_data(&kmf_cert->certificate);
1206 if (kmf_cert->kmf_private.label)
1207 free(kmf_cert->kmf_private.label);
1211 /*ARGSUSED*/
1212 KMF_RETURN
1213 OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1215 KMF_RETURN ret = KMF_OK;
1216 KMF_DATA *cert = NULL;
1217 char *outfilename = NULL;
1218 char *dirpath = NULL;
1219 char *fullpath = NULL;
1220 KMF_ENCODE_FORMAT format;
1222 /* Get the cert data */
1223 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1224 if (cert == NULL || cert->Data == NULL)
1225 return (KMF_ERR_BAD_PARAMETER);
1227 /* Check the output filename and directory attributes. */
1228 outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1229 numattr);
1230 if (outfilename == NULL)
1231 return (KMF_ERR_BAD_PARAMETER);
1233 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1234 fullpath = get_fullpath(dirpath, outfilename);
1235 if (fullpath == NULL)
1236 return (KMF_ERR_BAD_CERTFILE);
1238 /* Check the optional format attribute */
1239 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1240 &format, NULL);
1241 if (ret != KMF_OK) {
1242 /* If there is no format attribute, then default to PEM */
1243 format = KMF_FORMAT_PEM;
1244 ret = KMF_OK;
1245 } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1246 ret = KMF_ERR_BAD_CERT_FORMAT;
1247 goto out;
1250 /* Store the certificate in the file with the specified format */
1251 ret = kmf_create_cert_file(cert, format, fullpath);
1253 out:
1254 if (fullpath != NULL)
1255 free(fullpath);
1257 return (ret);
1261 KMF_RETURN
1262 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1264 KMF_RETURN rv;
1265 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1266 KMF_DATA certdata = { 0, NULL };
1267 char *dirpath = NULL;
1268 char *filename = NULL;
1269 char *fullpath = NULL;
1270 char *issuer = NULL;
1271 char *subject = NULL;
1272 KMF_BIGINT *serial = NULL;
1273 KMF_CERT_VALIDITY validity;
1276 * Get the DIRPATH and CERT_FILENAME attributes. They can not be
1277 * NULL at the same time.
1279 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1280 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1281 numattr);
1282 fullpath = get_fullpath(dirpath, filename);
1283 if (fullpath == NULL)
1284 return (KMF_ERR_BAD_PARAMETER);
1286 /* Get optional search criteria attributes */
1287 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1288 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1289 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1290 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1291 &validity, NULL);
1292 if (rv != KMF_OK) {
1293 validity = KMF_ALL_CERTS;
1294 rv = KMF_OK;
1297 if (isdir(fullpath)) {
1298 DIR *dirp;
1299 struct dirent *dp;
1301 /* open all files in the directory and attempt to read them */
1302 if ((dirp = opendir(fullpath)) == NULL) {
1303 return (KMF_ERR_BAD_PARAMETER);
1306 while ((dp = readdir(dirp)) != NULL) {
1307 if (strcmp(dp->d_name, ".") != 0 &&
1308 strcmp(dp->d_name, "..") != 0) {
1309 char *fname;
1311 fname = get_fullpath(fullpath,
1312 (char *)&dp->d_name);
1314 if (fname == NULL) {
1315 rv = KMF_ERR_MEMORY;
1316 break;
1319 rv = kmf_load_cert(kmfh, issuer, subject,
1320 serial, validity, fname, &certdata);
1322 if (rv == KMF_ERR_CERT_NOT_FOUND) {
1323 free(fname);
1324 kmf_free_data(&certdata);
1325 rv = KMF_OK;
1326 continue;
1327 } else if (rv != KMF_OK) {
1328 free(fname);
1329 break;
1332 if (unlink(fname) != 0) {
1333 SET_SYS_ERROR(kmfh, errno);
1334 rv = KMF_ERR_INTERNAL;
1335 free(fname);
1336 break;
1338 free(fname);
1339 kmf_free_data(&certdata);
1342 (void) closedir(dirp);
1343 } else {
1344 /* Just try to load a single certificate */
1345 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1346 fullpath, &certdata);
1347 if (rv == KMF_OK) {
1348 if (unlink(fullpath) != 0) {
1349 SET_SYS_ERROR(kmfh, errno);
1350 rv = KMF_ERR_INTERNAL;
1355 out:
1356 if (fullpath != NULL)
1357 free(fullpath);
1359 kmf_free_data(&certdata);
1361 return (rv);
1364 KMF_RETURN
1365 OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1366 KMF_DATA *keydata)
1368 KMF_RETURN rv = KMF_OK;
1369 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1370 int n;
1372 if (key == NULL || keydata == NULL ||
1373 key->keyp == NULL)
1374 return (KMF_ERR_BAD_PARAMETER);
1376 if (key->keyalg == KMF_RSA) {
1377 RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
1379 if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
1380 SET_ERROR(kmfh, ERR_get_error());
1381 return (KMF_ERR_ENCODING);
1383 RSA_free(pubkey);
1384 } else if (key->keyalg == KMF_DSA) {
1385 DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
1387 if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
1388 SET_ERROR(kmfh, ERR_get_error());
1389 return (KMF_ERR_ENCODING);
1391 DSA_free(pubkey);
1392 } else {
1393 return (KMF_ERR_BAD_PARAMETER);
1395 keydata->Length = n;
1397 cleanup:
1398 if (rv != KMF_OK) {
1399 if (keydata->Data)
1400 free(keydata->Data);
1401 keydata->Data = NULL;
1402 keydata->Length = 0;
1405 return (rv);
1408 static KMF_RETURN
1409 ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1410 KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
1412 int rv = 0;
1413 RSA *rsa;
1414 DSA *dsa;
1416 if (pkey == NULL || out == NULL)
1417 return (KMF_ERR_BAD_PARAMETER);
1419 switch (format) {
1420 case KMF_FORMAT_RAWKEY:
1421 /* same as ASN.1 */
1422 case KMF_FORMAT_ASN1:
1423 if (pkey->type == EVP_PKEY_RSA) {
1424 rsa = EVP_PKEY_get1_RSA(pkey);
1425 if (private)
1426 rv = i2d_RSAPrivateKey_bio(out, rsa);
1427 else
1428 rv = i2d_RSAPublicKey_bio(out, rsa);
1429 RSA_free(rsa);
1430 } else if (pkey->type == EVP_PKEY_DSA) {
1431 dsa = EVP_PKEY_get1_DSA(pkey);
1432 rv = i2d_DSAPrivateKey_bio(out, dsa);
1433 DSA_free(dsa);
1435 if (rv == 1) {
1436 rv = KMF_OK;
1437 } else {
1438 SET_ERROR(kmfh, rv);
1440 break;
1441 case KMF_FORMAT_PEM:
1442 if (pkey->type == EVP_PKEY_RSA) {
1443 rsa = EVP_PKEY_get1_RSA(pkey);
1444 if (private)
1445 rv = PEM_write_bio_RSAPrivateKey(out,
1446 rsa, NULL, NULL, 0, NULL,
1447 (cred != NULL ? cred->cred : NULL));
1448 else
1449 rv = PEM_write_bio_RSAPublicKey(out,
1450 rsa);
1451 RSA_free(rsa);
1452 } else if (pkey->type == EVP_PKEY_DSA) {
1453 dsa = EVP_PKEY_get1_DSA(pkey);
1454 rv = PEM_write_bio_DSAPrivateKey(out,
1455 dsa, NULL, NULL, 0, NULL,
1456 (cred != NULL ? cred->cred : NULL));
1457 DSA_free(dsa);
1460 if (rv == 1) {
1461 rv = KMF_OK;
1462 } else {
1463 SET_ERROR(kmfh, rv);
1465 break;
1467 default:
1468 rv = KMF_ERR_BAD_PARAMETER;
1471 return (rv);
1474 KMF_RETURN
1475 OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1476 KMF_ATTRIBUTE *attrlist)
1478 KMF_RETURN rv = KMF_OK;
1479 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1480 uint32_t eValue = 0x010001;
1481 RSA *sslPrivKey = NULL;
1482 DSA *sslDSAKey = NULL;
1483 EVP_PKEY *eprikey = NULL;
1484 EVP_PKEY *epubkey = NULL;
1485 BIO *out = NULL;
1486 KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1487 uint32_t keylen = 1024;
1488 uint32_t keylen_size = sizeof (uint32_t);
1489 boolean_t storekey = TRUE;
1490 KMF_KEY_ALG keytype = KMF_RSA;
1492 rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1493 &storekey, NULL);
1494 if (rv != KMF_OK) {
1495 /* "storekey" is optional. Default is TRUE */
1496 rv = KMF_OK;
1499 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1500 (void *)&keytype, NULL);
1501 if (rv != KMF_OK)
1502 /* keytype is optional. KMF_RSA is default */
1503 rv = KMF_OK;
1505 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1506 if (pubkey == NULL)
1507 return (KMF_ERR_BAD_PARAMETER);
1509 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1510 if (privkey == NULL)
1511 return (KMF_ERR_BAD_PARAMETER);
1513 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1514 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1516 eprikey = EVP_PKEY_new();
1517 if (eprikey == NULL) {
1518 SET_ERROR(kmfh, ERR_get_error());
1519 rv = KMF_ERR_KEYGEN_FAILED;
1520 goto cleanup;
1522 epubkey = EVP_PKEY_new();
1523 if (epubkey == NULL) {
1524 SET_ERROR(kmfh, ERR_get_error());
1525 rv = KMF_ERR_KEYGEN_FAILED;
1526 goto cleanup;
1528 if (keytype == KMF_RSA) {
1529 KMF_BIGINT *rsaexp = NULL;
1531 rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1532 if (rsaexp != NULL) {
1533 if (rsaexp->len > 0 &&
1534 rsaexp->len <= sizeof (eValue) &&
1535 rsaexp->val != NULL) {
1536 /* LINTED E_BAD_PTR_CAST_ALIGN */
1537 eValue = *(uint32_t *)rsaexp->val;
1538 } else {
1539 rv = KMF_ERR_BAD_PARAMETER;
1540 goto cleanup;
1542 } else {
1543 /* RSA Exponent is optional. Default is 0x10001 */
1544 rv = KMF_OK;
1547 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1548 &keylen, &keylen_size);
1549 if (rv == KMF_ERR_ATTR_NOT_FOUND)
1550 /* keylen is optional, default is 1024 */
1551 rv = KMF_OK;
1552 if (rv != KMF_OK) {
1553 rv = KMF_ERR_BAD_PARAMETER;
1554 goto cleanup;
1557 sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
1558 if (sslPrivKey == NULL) {
1559 SET_ERROR(kmfh, ERR_get_error());
1560 rv = KMF_ERR_KEYGEN_FAILED;
1561 } else {
1562 (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
1563 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1564 privkey->keyalg = KMF_RSA;
1565 privkey->keyclass = KMF_ASYM_PRI;
1566 privkey->israw = FALSE;
1567 privkey->keyp = (void *)eprikey;
1569 /* OpenSSL derives the public key from the private */
1570 (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
1571 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1572 pubkey->keyalg = KMF_RSA;
1573 pubkey->israw = FALSE;
1574 pubkey->keyclass = KMF_ASYM_PUB;
1575 pubkey->keyp = (void *)epubkey;
1577 } else if (keytype == KMF_DSA) {
1578 DSA *dp;
1579 sslDSAKey = DSA_new();
1580 if (sslDSAKey == NULL) {
1581 SET_ERROR(kmfh, ERR_get_error());
1582 return (KMF_ERR_MEMORY);
1585 if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
1586 NULL) {
1587 SET_ERROR(kmfh, ERR_get_error());
1588 rv = KMF_ERR_KEYGEN_FAILED;
1589 goto cleanup;
1591 if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
1592 NULL) {
1593 SET_ERROR(kmfh, ERR_get_error());
1594 rv = KMF_ERR_KEYGEN_FAILED;
1595 goto cleanup;
1597 if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
1598 NULL) {
1599 SET_ERROR(kmfh, ERR_get_error());
1600 rv = KMF_ERR_KEYGEN_FAILED;
1601 goto cleanup;
1604 if (!DSA_generate_key(sslDSAKey)) {
1605 SET_ERROR(kmfh, ERR_get_error());
1606 rv = KMF_ERR_KEYGEN_FAILED;
1607 goto cleanup;
1610 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1611 privkey->keyalg = KMF_DSA;
1612 privkey->keyclass = KMF_ASYM_PRI;
1613 privkey->israw = FALSE;
1614 if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1615 privkey->keyp = (void *)eprikey;
1616 } else {
1617 SET_ERROR(kmfh, ERR_get_error());
1618 rv = KMF_ERR_KEYGEN_FAILED;
1619 goto cleanup;
1621 dp = DSA_new();
1622 /* Make a copy for the public key */
1623 if (dp != NULL) {
1624 if ((dp->p = BN_new()) == NULL) {
1625 SET_ERROR(kmfh, ERR_get_error());
1626 rv = KMF_ERR_MEMORY;
1627 DSA_free(dp);
1628 goto cleanup;
1630 if ((dp->q = BN_new()) == NULL) {
1631 SET_ERROR(kmfh, ERR_get_error());
1632 rv = KMF_ERR_MEMORY;
1633 BN_free(dp->p);
1634 DSA_free(dp);
1635 goto cleanup;
1637 if ((dp->g = BN_new()) == NULL) {
1638 SET_ERROR(kmfh, ERR_get_error());
1639 rv = KMF_ERR_MEMORY;
1640 BN_free(dp->q);
1641 BN_free(dp->p);
1642 DSA_free(dp);
1643 goto cleanup;
1645 if ((dp->pub_key = BN_new()) == NULL) {
1646 SET_ERROR(kmfh, ERR_get_error());
1647 rv = KMF_ERR_MEMORY;
1648 BN_free(dp->q);
1649 BN_free(dp->p);
1650 BN_free(dp->g);
1651 DSA_free(dp);
1652 goto cleanup;
1654 (void) BN_copy(dp->p, sslDSAKey->p);
1655 (void) BN_copy(dp->q, sslDSAKey->q);
1656 (void) BN_copy(dp->g, sslDSAKey->g);
1657 (void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
1659 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1660 pubkey->keyalg = KMF_DSA;
1661 pubkey->keyclass = KMF_ASYM_PUB;
1662 pubkey->israw = FALSE;
1664 if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1665 pubkey->keyp = (void *)epubkey;
1666 } else {
1667 SET_ERROR(kmfh, ERR_get_error());
1668 rv = KMF_ERR_KEYGEN_FAILED;
1669 goto cleanup;
1674 if (rv != KMF_OK) {
1675 goto cleanup;
1678 if (storekey) {
1679 KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1680 int i = 0;
1681 char *keyfile = NULL, *dirpath = NULL;
1682 KMF_ENCODE_FORMAT format;
1684 * Construct a new attribute arrray and call openssl_store_key
1686 kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1687 privkey, sizeof (privkey));
1688 i++;
1690 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1691 if (dirpath != NULL) {
1692 storeattrs[i].type = KMF_DIRPATH_ATTR;
1693 storeattrs[i].pValue = dirpath;
1694 storeattrs[i].valueLen = strlen(dirpath);
1695 i++;
1696 } else {
1697 rv = KMF_OK; /* DIRPATH is optional */
1699 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1700 attrlist, numattr);
1701 if (keyfile != NULL) {
1702 storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1703 storeattrs[i].pValue = keyfile;
1704 storeattrs[i].valueLen = strlen(keyfile);
1705 i++;
1706 } else {
1707 goto cleanup; /* KEYFILE is required */
1709 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1710 (void *)&format, NULL);
1711 if (rv == KMF_OK) {
1712 storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1713 storeattrs[i].pValue = &format;
1714 storeattrs[i].valueLen = sizeof (format);
1715 i++;
1718 rv = OpenSSL_StoreKey(handle, i, storeattrs);
1721 cleanup:
1722 if (rv != KMF_OK) {
1723 if (eprikey != NULL)
1724 EVP_PKEY_free(eprikey);
1726 if (epubkey != NULL)
1727 EVP_PKEY_free(epubkey);
1729 if (pubkey->keylabel) {
1730 free(pubkey->keylabel);
1731 pubkey->keylabel = NULL;
1734 if (privkey->keylabel) {
1735 free(privkey->keylabel);
1736 privkey->keylabel = NULL;
1739 pubkey->keyp = NULL;
1740 privkey->keyp = NULL;
1743 if (sslPrivKey)
1744 RSA_free(sslPrivKey);
1746 if (sslDSAKey)
1747 DSA_free(sslDSAKey);
1749 if (out != NULL)
1750 (void) BIO_free(out);
1752 return (rv);
1756 * Make sure the BN conversion is properly padded with 0x00
1757 * bytes. If not, signature verification for DSA signatures
1758 * may fail in the case where the bignum value does not use
1759 * all of the bits.
1761 static int
1762 fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1763 int bytes = len - BN_num_bytes(bn);
1765 /* prepend with leading 0x00 if necessary */
1766 while (bytes-- > 0)
1767 *buf++ = 0;
1769 (void) BN_bn2bin(bn, buf);
1771 * Return the desired length since we prepended it
1772 * with the necessary 0x00 padding.
1774 return (len);
1777 KMF_RETURN
1778 OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1779 KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1781 KMF_RETURN ret = KMF_OK;
1782 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1783 KMF_ALGORITHM_INDEX AlgId;
1784 EVP_MD_CTX ctx;
1785 const EVP_MD *md;
1787 if (key == NULL || AlgOID == NULL ||
1788 tobesigned == NULL || output == NULL ||
1789 tobesigned->Data == NULL ||
1790 output->Data == NULL)
1791 return (KMF_ERR_BAD_PARAMETER);
1793 /* Map the OID to an OpenSSL algorithm */
1794 AlgId = x509_algoid_to_algid(AlgOID);
1795 if (AlgId == KMF_ALGID_NONE)
1796 return (KMF_ERR_BAD_ALGORITHM);
1798 if (key->keyalg == KMF_RSA) {
1799 EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1800 uchar_t *p;
1801 int len;
1802 if (AlgId == KMF_ALGID_MD5WithRSA)
1803 md = EVP_md5();
1804 else if (AlgId == KMF_ALGID_SHA1WithRSA)
1805 md = EVP_sha1();
1806 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1807 md = EVP_sha256();
1808 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1809 md = EVP_sha384();
1810 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1811 md = EVP_sha512();
1812 else if (AlgId == KMF_ALGID_RSA)
1813 md = NULL;
1814 else
1815 return (KMF_ERR_BAD_ALGORITHM);
1817 if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1818 RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1820 p = output->Data;
1821 if ((len = RSA_private_encrypt(tobesigned->Length,
1822 tobesigned->Data, p, rsa,
1823 RSA_PKCS1_PADDING)) <= 0) {
1824 SET_ERROR(kmfh, ERR_get_error());
1825 ret = KMF_ERR_INTERNAL;
1827 output->Length = len;
1828 } else {
1829 (void) EVP_MD_CTX_init(&ctx);
1830 (void) EVP_SignInit_ex(&ctx, md, NULL);
1831 (void) EVP_SignUpdate(&ctx, tobesigned->Data,
1832 (uint32_t)tobesigned->Length);
1833 len = (uint32_t)output->Length;
1834 p = output->Data;
1835 if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
1836 SET_ERROR(kmfh, ERR_get_error());
1837 len = 0;
1838 ret = KMF_ERR_INTERNAL;
1840 output->Length = len;
1841 (void) EVP_MD_CTX_cleanup(&ctx);
1843 } else if (key->keyalg == KMF_DSA) {
1844 DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1846 uchar_t hash[EVP_MAX_MD_SIZE];
1847 uint32_t hashlen;
1848 DSA_SIG *dsasig;
1850 if (AlgId == KMF_ALGID_DSA ||
1851 AlgId == KMF_ALGID_SHA1WithDSA)
1852 md = EVP_sha1();
1853 else if (AlgId == KMF_ALGID_SHA256WithDSA)
1854 md = EVP_sha256();
1855 else /* Bad algorithm */
1856 return (KMF_ERR_BAD_ALGORITHM);
1859 * OpenSSL EVP_Sign operation automatically converts to
1860 * ASN.1 output so we do the operations separately so we
1861 * are assured of NOT getting ASN.1 output returned.
1862 * KMF does not want ASN.1 encoded results because
1863 * not all mechanisms return ASN.1 encodings (PKCS#11
1864 * and NSS return raw signature data).
1866 EVP_MD_CTX_init(&ctx);
1867 (void) EVP_DigestInit_ex(&ctx, md, NULL);
1868 (void) EVP_DigestUpdate(&ctx, tobesigned->Data,
1869 tobesigned->Length);
1870 (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
1872 /* Only sign first 20 bytes for SHA2 */
1873 if (AlgId == KMF_ALGID_SHA256WithDSA)
1874 hashlen = 20;
1875 dsasig = DSA_do_sign(hash, hashlen, dsa);
1876 if (dsasig != NULL) {
1877 int i;
1878 output->Length = i = fixbnlen(dsasig->r, output->Data,
1879 hashlen);
1881 output->Length += fixbnlen(dsasig->s, &output->Data[i],
1882 hashlen);
1884 DSA_SIG_free(dsasig);
1885 } else {
1886 SET_ERROR(kmfh, ERR_get_error());
1888 (void) EVP_MD_CTX_cleanup(&ctx);
1889 } else {
1890 return (KMF_ERR_BAD_PARAMETER);
1892 cleanup:
1893 return (ret);
1896 KMF_RETURN
1897 /*ARGSUSED*/
1898 OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1899 int numattr, KMF_ATTRIBUTE *attrlist)
1901 KMF_RETURN rv = KMF_OK;
1902 KMF_KEY_HANDLE *key;
1903 boolean_t destroy = B_TRUE;
1905 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1906 if (key == NULL || key->keyp == NULL)
1907 return (KMF_ERR_BAD_PARAMETER);
1909 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1910 (void *)&destroy, NULL);
1911 if (rv != KMF_OK) {
1912 /* "destroy" is optional. Default is TRUE */
1913 rv = KMF_OK;
1916 if (key->keyclass != KMF_ASYM_PUB &&
1917 key->keyclass != KMF_ASYM_PRI &&
1918 key->keyclass != KMF_SYMMETRIC)
1919 return (KMF_ERR_BAD_KEY_CLASS);
1921 if (key->keyclass == KMF_SYMMETRIC) {
1922 kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1923 key->keyp = NULL;
1924 } else {
1925 if (key->keyp != NULL) {
1926 EVP_PKEY_free(key->keyp);
1927 key->keyp = NULL;
1931 if (key->keylabel != NULL) {
1932 EVP_PKEY *pkey = NULL;
1933 /* If the file exists, make sure it is a proper key. */
1934 pkey = openssl_load_key(handle, key->keylabel);
1935 if (pkey == NULL) {
1936 if (key->keylabel != NULL) {
1937 free(key->keylabel);
1938 key->keylabel = NULL;
1940 return (KMF_ERR_KEY_NOT_FOUND);
1942 EVP_PKEY_free(pkey);
1944 if (destroy) {
1945 if (unlink(key->keylabel) != 0) {
1946 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1947 SET_SYS_ERROR(kmfh, errno);
1948 rv = KMF_ERR_INTERNAL;
1951 if (key->keylabel != NULL) {
1952 free(key->keylabel);
1953 key->keylabel = NULL;
1956 return (rv);
1959 KMF_RETURN
1960 OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1962 KMF_RETURN ret = KMF_OK;
1963 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1964 char str[256]; /* OpenSSL needs at least 120 byte buffer */
1966 ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1967 if (strlen(str)) {
1968 *msgstr = (char *)strdup(str);
1969 if ((*msgstr) == NULL)
1970 ret = KMF_ERR_MEMORY;
1971 } else {
1972 *msgstr = NULL;
1975 return (ret);
1978 static int
1979 ext2NID(int kmfext)
1981 switch (kmfext) {
1982 case KMF_X509_EXT_KEY_USAGE:
1983 return (NID_key_usage);
1984 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1985 return (NID_private_key_usage_period);
1986 case KMF_X509_EXT_CERT_POLICIES:
1987 return (NID_certificate_policies);
1988 case KMF_X509_EXT_SUBJ_ALTNAME:
1989 return (NID_subject_alt_name);
1990 case KMF_X509_EXT_ISSUER_ALTNAME:
1991 return (NID_issuer_alt_name);
1992 case KMF_X509_EXT_BASIC_CONSTRAINTS:
1993 return (NID_basic_constraints);
1994 case KMF_X509_EXT_EXT_KEY_USAGE:
1995 return (NID_ext_key_usage);
1996 case KMF_X509_EXT_AUTH_KEY_ID:
1997 return (NID_authority_key_identifier);
1998 case KMF_X509_EXT_CRL_DIST_POINTS:
1999 return (NID_crl_distribution_points);
2000 case KMF_X509_EXT_SUBJ_KEY_ID:
2001 return (NID_subject_key_identifier);
2002 case KMF_X509_EXT_POLICY_MAPPINGS:
2003 return (OBJ_sn2nid("policyMappings"));
2004 case KMF_X509_EXT_NAME_CONSTRAINTS:
2005 return (OBJ_sn2nid("nameConstraints"));
2006 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2007 return (OBJ_sn2nid("policyConstraints"));
2008 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2009 return (OBJ_sn2nid("inhibitAnyPolicy"));
2010 case KMF_X509_EXT_FRESHEST_CRL:
2011 return (OBJ_sn2nid("freshestCRL"));
2012 default:
2013 return (NID_undef);
2017 KMF_RETURN
2018 OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2019 KMF_PRINTABLE_ITEM flag, char *resultStr)
2021 KMF_RETURN ret = KMF_OK;
2022 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2023 X509 *xcert = NULL;
2024 unsigned char *outbuf = NULL;
2025 unsigned char *outbuf_p;
2026 char *tmpstr = NULL;
2027 int j;
2028 int ext_index, nid, len;
2029 BIO *mem = NULL;
2030 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2031 STACK *emlst = NULL;
2032 #else
2033 STACK_OF(OPENSSL_STRING) *emlst = NULL;
2034 #endif
2035 X509_EXTENSION *ex;
2036 X509_CINF *ci;
2038 if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2039 return (KMF_ERR_BAD_PARAMETER);
2042 /* copy cert data to outbuf */
2043 outbuf = malloc(pcert->Length);
2044 if (outbuf == NULL) {
2045 return (KMF_ERR_MEMORY);
2047 (void) memcpy(outbuf, pcert->Data, pcert->Length);
2049 outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2050 xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2051 if (xcert == NULL) {
2052 SET_ERROR(kmfh, ERR_get_error());
2053 ret = KMF_ERR_ENCODING;
2054 goto out;
2057 mem = BIO_new(BIO_s_mem());
2058 if (mem == NULL) {
2059 SET_ERROR(kmfh, ERR_get_error());
2060 ret = KMF_ERR_MEMORY;
2061 goto out;
2064 switch (flag) {
2065 case KMF_CERT_ISSUER:
2066 (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2067 XN_FLAG_SEP_CPLUS_SPC);
2068 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2069 break;
2071 case KMF_CERT_SUBJECT:
2072 (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2073 XN_FLAG_SEP_CPLUS_SPC);
2074 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2075 break;
2077 case KMF_CERT_VERSION:
2078 tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
2079 (void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
2080 OPENSSL_free(tmpstr);
2081 len = strlen(resultStr);
2082 break;
2084 case KMF_CERT_SERIALNUM:
2085 if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2086 (void) strcpy(resultStr, "0x");
2087 len = BIO_gets(mem, &resultStr[2],
2088 KMF_CERT_PRINTABLE_LEN - 2);
2090 break;
2092 case KMF_CERT_NOTBEFORE:
2093 (void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
2094 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2095 break;
2097 case KMF_CERT_NOTAFTER:
2098 (void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
2099 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2100 break;
2102 case KMF_CERT_PUBKEY_DATA:
2104 EVP_PKEY *pkey = X509_get_pubkey(xcert);
2105 if (pkey == NULL) {
2106 SET_ERROR(kmfh, ERR_get_error());
2107 ret = KMF_ERR_ENCODING;
2108 goto out;
2111 if (pkey->type == EVP_PKEY_RSA) {
2112 (void) BIO_printf(mem,
2113 "RSA Public Key: (%d bit)\n",
2114 BN_num_bits(pkey->pkey.rsa->n));
2115 (void) RSA_print(mem, pkey->pkey.rsa, 0);
2116 } else if (pkey->type == EVP_PKEY_DSA) {
2117 (void) BIO_printf(mem,
2118 "%12sDSA Public Key:\n", "");
2119 (void) DSA_print(mem, pkey->pkey.dsa, 0);
2120 } else {
2121 (void) BIO_printf(mem,
2122 "%12sUnknown Public Key:\n", "");
2124 (void) BIO_printf(mem, "\n");
2125 EVP_PKEY_free(pkey);
2127 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2128 break;
2129 case KMF_CERT_SIGNATURE_ALG:
2130 case KMF_CERT_PUBKEY_ALG:
2131 if (flag == KMF_CERT_SIGNATURE_ALG) {
2132 len = i2a_ASN1_OBJECT(mem,
2133 xcert->sig_alg->algorithm);
2134 } else {
2135 len = i2a_ASN1_OBJECT(mem,
2136 xcert->cert_info->key->algor->algorithm);
2139 if (len > 0) {
2140 len = BIO_read(mem, resultStr,
2141 KMF_CERT_PRINTABLE_LEN);
2143 break;
2145 case KMF_CERT_EMAIL:
2146 emlst = X509_get1_email(xcert);
2147 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2148 for (j = 0; j < sk_num(emlst); j++)
2149 (void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2150 #else
2151 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2152 (void) BIO_printf(mem, "%s\n",
2153 sk_OPENSSL_STRING_value(emlst, j));
2154 #endif
2156 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2157 X509_email_free(emlst);
2158 break;
2159 case KMF_X509_EXT_ISSUER_ALTNAME:
2160 case KMF_X509_EXT_SUBJ_ALTNAME:
2161 case KMF_X509_EXT_KEY_USAGE:
2162 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2163 case KMF_X509_EXT_CERT_POLICIES:
2164 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2165 case KMF_X509_EXT_NAME_CONSTRAINTS:
2166 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2167 case KMF_X509_EXT_EXT_KEY_USAGE:
2168 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2169 case KMF_X509_EXT_AUTH_KEY_ID:
2170 case KMF_X509_EXT_SUBJ_KEY_ID:
2171 case KMF_X509_EXT_POLICY_MAPPINGS:
2172 case KMF_X509_EXT_CRL_DIST_POINTS:
2173 case KMF_X509_EXT_FRESHEST_CRL:
2174 nid = ext2NID(flag);
2175 if (nid == NID_undef) {
2176 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2177 goto out;
2179 ci = xcert->cert_info;
2181 ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
2182 if (ext_index == -1) {
2183 SET_ERROR(kmfh, ERR_get_error());
2185 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2186 goto out;
2188 ex = X509v3_get_ext(ci->extensions, ext_index);
2190 (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2192 if (BIO_printf(mem, ": %s\n",
2193 X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2194 SET_ERROR(kmfh, ERR_get_error());
2195 ret = KMF_ERR_ENCODING;
2196 goto out;
2198 if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2199 (void) BIO_printf(mem, "%*s", 4, "");
2200 (void) M_ASN1_OCTET_STRING_print(mem, ex->value);
2202 if (BIO_write(mem, "\n", 1) <= 0) {
2203 SET_ERROR(kmfh, ERR_get_error());
2204 ret = KMF_ERR_ENCODING;
2205 goto out;
2207 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2209 if (len <= 0) {
2210 SET_ERROR(kmfh, ERR_get_error());
2211 ret = KMF_ERR_ENCODING;
2214 out:
2215 if (outbuf != NULL) {
2216 free(outbuf);
2219 if (xcert != NULL) {
2220 X509_free(xcert);
2223 if (mem != NULL) {
2224 (void) BIO_free(mem);
2227 return (ret);
2230 KMF_RETURN
2231 /*ARGSUSED*/
2232 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2233 KMF_ATTRIBUTE *attrlist)
2235 KMF_RETURN rv = KMF_OK;
2236 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2237 KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2238 KMF_KEY_HANDLE *key = NULL;
2239 uint32_t numkeys = 1; /* 1 key only */
2240 char *dirpath = NULL;
2241 char *keyfile = NULL;
2242 KMF_ATTRIBUTE new_attrlist[16];
2243 int i = 0;
2246 * This is really just a FindKey operation, reuse the
2247 * FindKey function.
2249 kmf_set_attr_at_index(new_attrlist, i,
2250 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2251 i++;
2253 kmf_set_attr_at_index(new_attrlist, i,
2254 KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2255 i++;
2257 kmf_set_attr_at_index(new_attrlist, i,
2258 KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2259 i++;
2261 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2262 if (key == NULL) {
2263 return (KMF_ERR_BAD_PARAMETER);
2264 } else {
2265 kmf_set_attr_at_index(new_attrlist, i,
2266 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2267 i++;
2270 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2271 if (dirpath != NULL) {
2272 kmf_set_attr_at_index(new_attrlist, i,
2273 KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2274 i++;
2277 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2278 if (keyfile == NULL)
2279 return (KMF_ERR_BAD_PARAMETER);
2280 else {
2281 kmf_set_attr_at_index(new_attrlist, i,
2282 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2283 i++;
2286 rv = OpenSSL_FindKey(handle, i, new_attrlist);
2287 return (rv);
2290 KMF_RETURN
2291 /*ARGSUSED*/
2292 OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2293 KMF_OID *AlgOID, KMF_DATA *ciphertext,
2294 KMF_DATA *output)
2296 KMF_RETURN ret = KMF_OK;
2297 RSA *rsa = NULL;
2298 unsigned int in_len = 0, out_len = 0;
2299 unsigned int total_decrypted = 0, modulus_len = 0;
2300 uint8_t *in_data, *out_data;
2301 int i, blocks;
2303 if (key == NULL || AlgOID == NULL ||
2304 ciphertext == NULL || output == NULL ||
2305 ciphertext->Data == NULL ||
2306 output->Data == NULL)
2307 return (KMF_ERR_BAD_PARAMETER);
2309 if (key->keyalg == KMF_RSA) {
2310 rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2311 modulus_len = RSA_size(rsa);
2312 } else {
2313 return (KMF_ERR_BAD_PARAMETER);
2316 blocks = ciphertext->Length/modulus_len;
2317 out_data = output->Data;
2318 in_data = ciphertext->Data;
2319 out_len = modulus_len - 11;
2320 in_len = modulus_len;
2322 for (i = 0; i < blocks; i++) {
2323 out_len = RSA_private_decrypt(in_len,
2324 in_data, out_data, rsa, RSA_PKCS1_PADDING);
2326 if (out_len == 0) {
2327 ret = KMF_ERR_INTERNAL;
2328 goto cleanup;
2331 out_data += out_len;
2332 total_decrypted += out_len;
2333 in_data += in_len;
2336 output->Length = total_decrypted;
2338 cleanup:
2339 RSA_free(rsa);
2340 if (ret != KMF_OK)
2341 output->Length = 0;
2343 return (ret);
2348 * This function will create a certid from issuer_cert and user_cert.
2349 * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2350 * certid memory after use.
2352 static KMF_RETURN
2353 create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2354 const KMF_DATA *user_cert, OCSP_CERTID **certid)
2356 KMF_RETURN ret = KMF_OK;
2357 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2358 X509 *issuer = NULL;
2359 X509 *cert = NULL;
2360 unsigned char *ptmp;
2362 if (issuer_cert == NULL || user_cert == NULL) {
2363 return (KMF_ERR_BAD_PARAMETER);
2366 /* convert the DER-encoded issuer cert to an internal X509 */
2367 ptmp = issuer_cert->Data;
2368 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2369 issuer_cert->Length);
2370 if (issuer == NULL) {
2371 SET_ERROR(kmfh, ERR_get_error());
2372 ret = KMF_ERR_OCSP_BAD_ISSUER;
2373 goto end;
2376 /* convert the DER-encoded user cert to an internal X509 */
2377 ptmp = user_cert->Data;
2378 cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2379 user_cert->Length);
2380 if (cert == NULL) {
2381 SET_ERROR(kmfh, ERR_get_error());
2383 ret = KMF_ERR_OCSP_BAD_CERT;
2384 goto end;
2387 /* create a CERTID */
2388 *certid = OCSP_cert_to_id(NULL, cert, issuer);
2389 if (*certid == NULL) {
2390 SET_ERROR(kmfh, ERR_get_error());
2391 ret = KMF_ERR_OCSP_CERTID;
2392 goto end;
2395 end:
2396 if (issuer != NULL) {
2397 X509_free(issuer);
2400 if (cert != NULL) {
2401 X509_free(cert);
2404 return (ret);
2407 KMF_RETURN
2408 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2409 int numattr, KMF_ATTRIBUTE *attrlist)
2411 KMF_RETURN ret = KMF_OK;
2412 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2413 OCSP_CERTID *id = NULL;
2414 OCSP_REQUEST *req = NULL;
2415 BIO *derbio = NULL;
2416 char *reqfile;
2417 KMF_DATA *issuer_cert;
2418 KMF_DATA *user_cert;
2420 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2421 attrlist, numattr);
2422 if (user_cert == NULL)
2423 return (KMF_ERR_BAD_PARAMETER);
2425 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2426 attrlist, numattr);
2427 if (issuer_cert == NULL)
2428 return (KMF_ERR_BAD_PARAMETER);
2430 reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2431 attrlist, numattr);
2432 if (reqfile == NULL)
2433 return (KMF_ERR_BAD_PARAMETER);
2435 ret = create_certid(handle, issuer_cert, user_cert, &id);
2436 if (ret != KMF_OK) {
2437 return (ret);
2440 /* Create an OCSP request */
2441 req = OCSP_REQUEST_new();
2442 if (req == NULL) {
2443 SET_ERROR(kmfh, ERR_get_error());
2444 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2445 goto end;
2448 if (!OCSP_request_add0_id(req, id)) {
2449 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2450 goto end;
2453 /* Write the request to the output file with DER encoding */
2454 derbio = BIO_new_file(reqfile, "wb");
2455 if (!derbio) {
2456 SET_ERROR(kmfh, ERR_get_error());
2457 ret = KMF_ERR_OPEN_FILE;
2458 goto end;
2460 if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2461 ret = KMF_ERR_ENCODING;
2464 end:
2466 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2467 * will also deallocate certid's space.
2469 if (req != NULL) {
2470 OCSP_REQUEST_free(req);
2473 if (derbio != NULL) {
2474 (void) BIO_free(derbio);
2477 return (ret);
2480 /* ocsp_find_signer_sk() is copied from openssl source */
2481 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
2483 int i;
2484 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2486 /* Easy if lookup by name */
2487 if (id->type == V_OCSP_RESPID_NAME)
2488 return (X509_find_by_subject(certs, id->value.byName));
2490 /* Lookup by key hash */
2492 /* If key hash isn't SHA1 length then forget it */
2493 if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2494 return (NULL);
2496 keyhash = id->value.byKey->data;
2497 /* Calculate hash of each key and compare */
2498 for (i = 0; i < sk_X509_num(certs); i++) {
2499 /* LINTED E_BAD_PTR_CAST_ALIGN */
2500 X509 *x = sk_X509_value(certs, i);
2501 /* Use pubkey_digest to get the key ID value */
2502 (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2503 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2504 return (x);
2506 return (NULL);
2509 /* ocsp_find_signer() is copied from openssl source */
2510 /* ARGSUSED2 */
2511 static int
2512 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2513 X509_STORE *st, unsigned long flags)
2515 X509 *signer;
2516 OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2517 if ((signer = ocsp_find_signer_sk(certs, rid))) {
2518 *psigner = signer;
2519 return (2);
2521 if (!(flags & OCSP_NOINTERN) &&
2522 (signer = ocsp_find_signer_sk(bs->certs, rid))) {
2523 *psigner = signer;
2524 return (1);
2526 /* Maybe lookup from store if by subject name */
2528 *psigner = NULL;
2529 return (0);
2533 * This function will verify the signature of a basic response, using
2534 * the public key from the OCSP responder certificate.
2536 static KMF_RETURN
2537 check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2538 KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2540 KMF_RETURN ret = KMF_OK;
2541 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2542 STACK_OF(X509) *cert_stack = NULL;
2543 X509 *signer = NULL;
2544 X509 *issuer = NULL;
2545 EVP_PKEY *skey = NULL;
2546 unsigned char *ptmp;
2549 if (bs == NULL || issuer_cert == NULL)
2550 return (KMF_ERR_BAD_PARAMETER);
2553 * Find the certificate that signed the basic response.
2555 * If signer_cert is not NULL, we will use that as the signer cert.
2556 * Otherwise, we will check if the issuer cert is actually the signer.
2557 * If we still do not find a signer, we will look for it from the
2558 * certificate list came with the response file.
2560 if (signer_cert != NULL) {
2561 ptmp = signer_cert->Data;
2562 signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2563 signer_cert->Length);
2564 if (signer == NULL) {
2565 SET_ERROR(kmfh, ERR_get_error());
2566 ret = KMF_ERR_OCSP_BAD_SIGNER;
2567 goto end;
2569 } else {
2571 * Convert the issuer cert into X509 and push it into a
2572 * stack to be used by ocsp_find_signer().
2574 ptmp = issuer_cert->Data;
2575 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2576 issuer_cert->Length);
2577 if (issuer == NULL) {
2578 SET_ERROR(kmfh, ERR_get_error());
2579 ret = KMF_ERR_OCSP_BAD_ISSUER;
2580 goto end;
2583 if ((cert_stack = sk_X509_new_null()) == NULL) {
2584 ret = KMF_ERR_INTERNAL;
2585 goto end;
2588 if (sk_X509_push(cert_stack, issuer) == NULL) {
2589 ret = KMF_ERR_INTERNAL;
2590 goto end;
2593 ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2594 if (!ret) {
2595 /* can not find the signer */
2596 ret = KMF_ERR_OCSP_BAD_SIGNER;
2597 goto end;
2601 /* Verify the signature of the response */
2602 skey = X509_get_pubkey(signer);
2603 if (skey == NULL) {
2604 ret = KMF_ERR_OCSP_BAD_SIGNER;
2605 goto end;
2608 ret = OCSP_BASICRESP_verify(bs, skey, 0);
2609 if (ret == 0) {
2610 ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2611 goto end;
2614 end:
2615 if (issuer != NULL) {
2616 X509_free(issuer);
2619 if (signer != NULL) {
2620 X509_free(signer);
2623 if (skey != NULL) {
2624 EVP_PKEY_free(skey);
2627 if (cert_stack != NULL) {
2628 sk_X509_free(cert_stack);
2631 return (ret);
2636 KMF_RETURN
2637 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2638 int numattr, KMF_ATTRIBUTE *attrlist)
2640 KMF_RETURN ret = KMF_OK;
2641 BIO *derbio = NULL;
2642 OCSP_RESPONSE *resp = NULL;
2643 OCSP_BASICRESP *bs = NULL;
2644 OCSP_CERTID *id = NULL;
2645 OCSP_SINGLERESP *single = NULL;
2646 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2647 int index, status, reason;
2648 KMF_DATA *issuer_cert;
2649 KMF_DATA *user_cert;
2650 KMF_DATA *signer_cert;
2651 KMF_DATA *response;
2652 int *response_reason, *response_status, *cert_status;
2653 boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
2654 uint32_t response_lifetime;
2656 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2657 attrlist, numattr);
2658 if (issuer_cert == NULL)
2659 return (KMF_ERR_BAD_PARAMETER);
2661 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2662 attrlist, numattr);
2663 if (user_cert == NULL)
2664 return (KMF_ERR_BAD_PARAMETER);
2666 response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2667 attrlist, numattr);
2668 if (response == NULL)
2669 return (KMF_ERR_BAD_PARAMETER);
2671 response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2672 attrlist, numattr);
2673 if (response_status == NULL)
2674 return (KMF_ERR_BAD_PARAMETER);
2676 response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2677 attrlist, numattr);
2678 if (response_reason == NULL)
2679 return (KMF_ERR_BAD_PARAMETER);
2681 cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2682 attrlist, numattr);
2683 if (cert_status == NULL)
2684 return (KMF_ERR_BAD_PARAMETER);
2686 /* Read in the response */
2687 derbio = BIO_new_mem_buf(response->Data, response->Length);
2688 if (!derbio) {
2689 ret = KMF_ERR_MEMORY;
2690 return (ret);
2693 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2694 if (resp == NULL) {
2695 ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2696 goto end;
2699 /* Check the response status */
2700 status = OCSP_response_status(resp);
2701 *response_status = status;
2702 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2703 ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2704 goto end;
2707 #ifdef DEBUG
2708 printf("Successfully checked the response file status.\n");
2709 #endif /* DEBUG */
2711 /* Extract basic response */
2712 bs = OCSP_response_get1_basic(resp);
2713 if (bs == NULL) {
2714 ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2715 goto end;
2718 #ifdef DEBUG
2719 printf("Successfully retrieved the basic response.\n");
2720 #endif /* DEBUG */
2722 /* Check the basic response signature if required */
2723 ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2724 (void *)&ignore_response_sign, NULL);
2725 if (ret != KMF_OK)
2726 ret = KMF_OK;
2728 signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2729 attrlist, numattr);
2731 if (ignore_response_sign == B_FALSE) {
2732 ret = check_response_signature(handle, bs,
2733 signer_cert, issuer_cert);
2734 if (ret != KMF_OK)
2735 goto end;
2738 #ifdef DEBUG
2739 printf("Successfully verified the response signature.\n");
2740 #endif /* DEBUG */
2742 /* Create a certid for the certificate in question */
2743 ret = create_certid(handle, issuer_cert, user_cert, &id);
2744 if (ret != KMF_OK) {
2745 ret = KMF_ERR_OCSP_CERTID;
2746 goto end;
2749 #ifdef DEBUG
2750 printf("successfully created a certid for the cert.\n");
2751 #endif /* DEBUG */
2753 /* Find the index of the single response for the certid */
2754 index = OCSP_resp_find(bs, id, -1);
2755 if (index < 0) {
2756 /* cound not find this certificate in the response */
2757 ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2758 goto end;
2761 #ifdef DEBUG
2762 printf("Successfully found the single response index for the cert.\n");
2763 #endif /* DEBUG */
2765 /* Retrieve the single response and get the cert status */
2766 single = OCSP_resp_get0(bs, index);
2767 status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2768 &nextupd);
2769 if (status == V_OCSP_CERTSTATUS_GOOD) {
2770 *cert_status = OCSP_GOOD;
2771 } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2772 *cert_status = OCSP_UNKNOWN;
2773 } else { /* revoked */
2774 *cert_status = OCSP_REVOKED;
2775 *response_reason = reason;
2777 ret = KMF_OK;
2779 /* resp. time is optional, so we don't care about the return code. */
2780 (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2781 (void *)&response_lifetime, NULL);
2783 if (!OCSP_check_validity(thisupd, nextupd, 300,
2784 response_lifetime)) {
2785 ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2786 goto end;
2789 #ifdef DEBUG
2790 printf("Successfully verify the time.\n");
2791 #endif /* DEBUG */
2793 end:
2794 if (derbio != NULL)
2795 (void) BIO_free(derbio);
2797 if (resp != NULL)
2798 OCSP_RESPONSE_free(resp);
2800 if (bs != NULL)
2801 OCSP_BASICRESP_free(bs);
2803 if (id != NULL)
2804 OCSP_CERTID_free(id);
2806 return (ret);
2809 static KMF_RETURN
2810 fetch_key(KMF_HANDLE_T handle, char *path,
2811 KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2813 KMF_RETURN rv = KMF_OK;
2814 EVP_PKEY *pkey = NULL;
2815 KMF_RAW_SYM_KEY *rkey = NULL;
2817 if (keyclass == KMF_ASYM_PRI ||
2818 keyclass == KMF_ASYM_PUB) {
2819 pkey = openssl_load_key(handle, path);
2820 if (pkey == NULL) {
2821 return (KMF_ERR_KEY_NOT_FOUND);
2823 if (key != NULL) {
2824 if (pkey->type == EVP_PKEY_RSA)
2825 key->keyalg = KMF_RSA;
2826 else if (pkey->type == EVP_PKEY_DSA)
2827 key->keyalg = KMF_DSA;
2829 key->kstype = KMF_KEYSTORE_OPENSSL;
2830 key->keyclass = keyclass;
2831 key->keyp = (void *)pkey;
2832 key->israw = FALSE;
2833 if (path != NULL &&
2834 ((key->keylabel = strdup(path)) == NULL)) {
2835 EVP_PKEY_free(pkey);
2836 return (KMF_ERR_MEMORY);
2838 } else {
2839 EVP_PKEY_free(pkey);
2840 pkey = NULL;
2842 } else if (keyclass == KMF_SYMMETRIC) {
2843 KMF_ENCODE_FORMAT fmt;
2845 * If the file is a recognized format,
2846 * then it is NOT a symmetric key.
2848 rv = kmf_get_file_format(path, &fmt);
2849 if (rv == KMF_OK || fmt != 0) {
2850 return (KMF_ERR_KEY_NOT_FOUND);
2851 } else if (rv == KMF_ERR_ENCODING) {
2853 * If we don't know the encoding,
2854 * it is probably a symmetric key.
2856 rv = KMF_OK;
2857 } else if (rv == KMF_ERR_OPEN_FILE) {
2858 return (KMF_ERR_KEY_NOT_FOUND);
2861 if (key != NULL) {
2862 KMF_DATA keyvalue;
2863 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2864 if (rkey == NULL) {
2865 rv = KMF_ERR_MEMORY;
2866 goto out;
2869 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2870 rv = kmf_read_input_file(handle, path, &keyvalue);
2871 if (rv != KMF_OK)
2872 goto out;
2874 rkey->keydata.len = keyvalue.Length;
2875 rkey->keydata.val = keyvalue.Data;
2877 key->kstype = KMF_KEYSTORE_OPENSSL;
2878 key->keyclass = keyclass;
2879 key->israw = TRUE;
2880 key->keyp = (void *)rkey;
2881 if (path != NULL &&
2882 ((key->keylabel = strdup(path)) == NULL)) {
2883 rv = KMF_ERR_MEMORY;
2887 out:
2888 if (rv != KMF_OK) {
2889 if (rkey != NULL) {
2890 kmf_free_raw_sym_key(rkey);
2892 if (pkey != NULL)
2893 EVP_PKEY_free(pkey);
2895 if (key != NULL) {
2896 key->keyalg = KMF_KEYALG_NONE;
2897 key->keyclass = KMF_KEYCLASS_NONE;
2898 key->keyp = NULL;
2902 return (rv);
2905 KMF_RETURN
2906 OpenSSL_FindKey(KMF_HANDLE_T handle,
2907 int numattr, KMF_ATTRIBUTE *attrlist)
2909 KMF_RETURN rv = KMF_OK;
2910 char *fullpath = NULL;
2911 uint32_t maxkeys;
2912 KMF_KEY_HANDLE *key;
2913 uint32_t *numkeys;
2914 KMF_KEY_CLASS keyclass;
2915 KMF_RAW_KEY_DATA *rawkey;
2916 char *dirpath;
2917 char *keyfile;
2919 if (handle == NULL)
2920 return (KMF_ERR_BAD_PARAMETER);
2922 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2923 if (numkeys == NULL)
2924 return (KMF_ERR_BAD_PARAMETER);
2926 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2927 (void *)&keyclass, NULL);
2928 if (rv != KMF_OK)
2929 return (KMF_ERR_BAD_PARAMETER);
2931 if (keyclass != KMF_ASYM_PUB &&
2932 keyclass != KMF_ASYM_PRI &&
2933 keyclass != KMF_SYMMETRIC)
2934 return (KMF_ERR_BAD_KEY_CLASS);
2936 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2937 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2939 fullpath = get_fullpath(dirpath, keyfile);
2941 if (fullpath == NULL)
2942 return (KMF_ERR_BAD_PARAMETER);
2944 maxkeys = *numkeys;
2945 if (maxkeys == 0)
2946 maxkeys = 0xFFFFFFFF;
2947 *numkeys = 0;
2949 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2950 /* it is okay to have "keys" contains NULL */
2953 * The caller may want a list of the raw key data as well.
2954 * Useful for importing keys from a file into other keystores.
2956 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
2958 if (isdir(fullpath)) {
2959 DIR *dirp;
2960 struct dirent *dp;
2961 int n = 0;
2963 /* open all files in the directory and attempt to read them */
2964 if ((dirp = opendir(fullpath)) == NULL) {
2965 return (KMF_ERR_BAD_PARAMETER);
2967 rewinddir(dirp);
2968 while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
2969 if (strcmp(dp->d_name, ".") &&
2970 strcmp(dp->d_name, "..")) {
2971 char *fname;
2973 fname = get_fullpath(fullpath,
2974 (char *)&dp->d_name);
2976 rv = fetch_key(handle, fname,
2977 keyclass, key ? &key[n] : NULL);
2979 if (rv == KMF_OK) {
2980 if (key != NULL && rawkey != NULL)
2981 rv = convertToRawKey(
2982 key[n].keyp, &rawkey[n]);
2983 n++;
2986 if (rv != KMF_OK || key == NULL)
2987 free(fname);
2990 (void) closedir(dirp);
2991 free(fullpath);
2992 (*numkeys) = n;
2993 } else {
2994 rv = fetch_key(handle, fullpath, keyclass, key);
2995 if (rv == KMF_OK)
2996 (*numkeys) = 1;
2998 if (rv != KMF_OK || key == NULL)
2999 free(fullpath);
3001 if (rv == KMF_OK && key != NULL && rawkey != NULL) {
3002 rv = convertToRawKey(key->keyp, rawkey);
3006 if (rv == KMF_OK && (*numkeys) == 0)
3007 rv = KMF_ERR_KEY_NOT_FOUND;
3008 else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
3009 rv = KMF_OK;
3011 return (rv);
3014 #define HANDLE_PK12_ERROR { \
3015 SET_ERROR(kmfh, ERR_get_error()); \
3016 rv = KMF_ERR_ENCODING; \
3017 goto out; \
3020 static int
3021 add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3023 if (xcert != NULL && xcert->aux != NULL &&
3024 xcert->aux->alias != NULL) {
3025 if (PKCS12_add_friendlyname_asc(bag,
3026 (const char *)xcert->aux->alias->data,
3027 xcert->aux->alias->length) == 0)
3028 return (0);
3030 return (1);
3033 static PKCS7 *
3034 add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3035 uchar_t *keyid, unsigned int keyidlen)
3037 PKCS12_SAFEBAG *bag = NULL;
3038 PKCS7 *cert_authsafe = NULL;
3039 STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3041 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3042 if (bag_stack == NULL)
3043 return (NULL);
3045 /* Convert cert from X509 struct to PKCS#12 bag */
3046 bag = PKCS12_x5092certbag(sslcert);
3047 if (bag == NULL) {
3048 goto out;
3051 /* Add the key id to the certificate bag. */
3052 if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3053 goto out;
3056 if (!add_alias_to_bag(bag, sslcert))
3057 goto out;
3059 /* Pile it on the bag_stack. */
3060 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3061 goto out;
3063 /* Turn bag_stack of certs into encrypted authsafe. */
3064 cert_authsafe = PKCS12_pack_p7encdata(
3065 NID_pbe_WithSHA1And40BitRC2_CBC,
3066 cred->cred, cred->credlen, NULL, 0,
3067 PKCS12_DEFAULT_ITER, bag_stack);
3069 out:
3070 if (bag_stack != NULL)
3071 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3073 return (cert_authsafe);
3076 static PKCS7 *
3077 add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3078 uchar_t *keyid, unsigned int keyidlen,
3079 char *label, int label_len)
3081 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3082 STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3083 PKCS12_SAFEBAG *bag = NULL;
3084 PKCS7 *key_authsafe = NULL;
3086 p8 = EVP_PKEY2PKCS8(pkey);
3087 if (p8 == NULL) {
3088 return (NULL);
3090 /* Put the shrouded key into a PKCS#12 bag. */
3091 bag = PKCS12_MAKE_SHKEYBAG(
3092 NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3093 cred->cred, cred->credlen,
3094 NULL, 0, PKCS12_DEFAULT_ITER, p8);
3096 /* Clean up the PKCS#8 shrouded key, don't need it now. */
3097 PKCS8_PRIV_KEY_INFO_free(p8);
3098 p8 = NULL;
3100 if (bag == NULL) {
3101 return (NULL);
3103 if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3104 goto out;
3105 if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3106 goto out;
3108 /* Start a PKCS#12 safebag container for the private key. */
3109 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3110 if (bag_stack == NULL)
3111 goto out;
3113 /* Pile on the private key on the bag_stack. */
3114 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3115 goto out;
3117 key_authsafe = PKCS12_pack_p7data(bag_stack);
3119 out:
3120 if (bag_stack != NULL)
3121 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3122 bag_stack = NULL;
3123 return (key_authsafe);
3126 static EVP_PKEY *
3127 ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3129 RSA *rsa = NULL;
3130 EVP_PKEY *newkey = NULL;
3132 if ((rsa = RSA_new()) == NULL)
3133 return (NULL);
3135 if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
3136 return (NULL);
3138 if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
3139 NULL)
3140 return (NULL);
3142 if (key->priexp.val != NULL)
3143 if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
3144 rsa->d)) == NULL)
3145 return (NULL);
3147 if (key->prime1.val != NULL)
3148 if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
3149 rsa->p)) == NULL)
3150 return (NULL);
3152 if (key->prime2.val != NULL)
3153 if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
3154 rsa->q)) == NULL)
3155 return (NULL);
3157 if (key->exp1.val != NULL)
3158 if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
3159 rsa->dmp1)) == NULL)
3160 return (NULL);
3162 if (key->exp2.val != NULL)
3163 if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
3164 rsa->dmq1)) == NULL)
3165 return (NULL);
3167 if (key->coef.val != NULL)
3168 if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
3169 rsa->iqmp)) == NULL)
3170 return (NULL);
3172 if ((newkey = EVP_PKEY_new()) == NULL)
3173 return (NULL);
3175 (void) EVP_PKEY_set1_RSA(newkey, rsa);
3177 /* The original key must be freed once here or it leaks memory */
3178 RSA_free(rsa);
3180 return (newkey);
3183 static EVP_PKEY *
3184 ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3186 DSA *dsa = NULL;
3187 EVP_PKEY *newkey = NULL;
3189 if ((dsa = DSA_new()) == NULL)
3190 return (NULL);
3192 if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
3193 dsa->p)) == NULL)
3194 return (NULL);
3196 if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
3197 dsa->q)) == NULL)
3198 return (NULL);
3200 if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
3201 dsa->g)) == NULL)
3202 return (NULL);
3204 if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
3205 dsa->priv_key)) == NULL)
3206 return (NULL);
3208 if (key->pubvalue.val != NULL) {
3209 if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
3210 key->pubvalue.len, dsa->pub_key)) == NULL)
3211 return (NULL);
3214 if ((newkey = EVP_PKEY_new()) == NULL)
3215 return (NULL);
3217 (void) EVP_PKEY_set1_DSA(newkey, dsa);
3219 /* The original key must be freed once here or it leaks memory */
3220 DSA_free(dsa);
3221 return (newkey);
3224 static EVP_PKEY *
3225 raw_key_to_pkey(KMF_KEY_HANDLE *key)
3227 EVP_PKEY *pkey = NULL;
3228 KMF_RAW_KEY_DATA *rawkey;
3229 ASN1_TYPE *attr = NULL;
3230 KMF_RETURN ret;
3232 if (key == NULL || !key->israw)
3233 return (NULL);
3235 rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3236 if (rawkey->keytype == KMF_RSA) {
3237 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3238 } else if (rawkey->keytype == KMF_DSA) {
3239 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3240 } else if (rawkey->keytype == KMF_ECDSA) {
3242 * OpenSSL in Solaris does not support EC for
3243 * legal reasons
3245 return (NULL);
3246 } else {
3247 /* wrong kind of key */
3248 return (NULL);
3251 if (rawkey->label != NULL) {
3252 if ((attr = ASN1_TYPE_new()) == NULL) {
3253 EVP_PKEY_free(pkey);
3254 return (NULL);
3256 attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3257 (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3258 strlen(rawkey->label));
3259 attr->type = V_ASN1_BMPSTRING;
3260 attr->value.ptr = (char *)attr->value.bmpstring;
3261 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3262 if (ret != KMF_OK) {
3263 EVP_PKEY_free(pkey);
3264 ASN1_TYPE_free(attr);
3265 return (NULL);
3268 if (rawkey->id.Data != NULL) {
3269 if ((attr = ASN1_TYPE_new()) == NULL) {
3270 EVP_PKEY_free(pkey);
3271 return (NULL);
3273 attr->value.octet_string =
3274 ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3275 attr->type = V_ASN1_OCTET_STRING;
3276 (void) ASN1_STRING_set(attr->value.octet_string,
3277 rawkey->id.Data, rawkey->id.Length);
3278 attr->value.ptr = (char *)attr->value.octet_string;
3279 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3280 if (ret != KMF_OK) {
3281 EVP_PKEY_free(pkey);
3282 ASN1_TYPE_free(attr);
3283 return (NULL);
3286 return (pkey);
3290 * Search a list of private keys to find one that goes with the certificate.
3292 static EVP_PKEY *
3293 find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3295 int i;
3296 EVP_PKEY *pkey = NULL;
3298 if (numkeys == 0 || keylist == NULL || xcert == NULL)
3299 return (NULL);
3300 for (i = 0; i < numkeys; i++) {
3301 if (keylist[i].israw)
3302 pkey = raw_key_to_pkey(&keylist[i]);
3303 else
3304 pkey = (EVP_PKEY *)keylist[i].keyp;
3305 if (pkey != NULL) {
3306 if (X509_check_private_key(xcert, pkey)) {
3307 return (pkey);
3308 } else {
3309 EVP_PKEY_free(pkey);
3310 pkey = NULL;
3314 return (pkey);
3317 static KMF_RETURN
3318 local_export_pk12(KMF_HANDLE_T handle,
3319 KMF_CREDENTIAL *cred,
3320 int numcerts, KMF_X509_DER_CERT *certlist,
3321 int numkeys, KMF_KEY_HANDLE *keylist,
3322 char *filename)
3324 KMF_RETURN rv = KMF_OK;
3325 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3326 BIO *bio = NULL;
3327 PKCS7 *cert_authsafe = NULL;
3328 PKCS7 *key_authsafe = NULL;
3329 STACK_OF(PKCS7) *authsafe_stack = NULL;
3330 PKCS12 *p12_elem = NULL;
3331 int i;
3333 if (numcerts == 0 && numkeys == 0)
3334 return (KMF_ERR_BAD_PARAMETER);
3337 * Open the output file.
3339 if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3340 SET_ERROR(kmfh, ERR_get_error());
3341 rv = KMF_ERR_OPEN_FILE;
3342 goto cleanup;
3345 /* Start a PKCS#7 stack. */
3346 authsafe_stack = sk_PKCS7_new_null();
3347 if (authsafe_stack == NULL) {
3348 rv = KMF_ERR_MEMORY;
3349 goto cleanup;
3351 if (numcerts > 0) {
3352 for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3353 const uchar_t *p = certlist[i].certificate.Data;
3354 long len = certlist[i].certificate.Length;
3355 X509 *xcert = NULL;
3356 EVP_PKEY *pkey = NULL;
3357 unsigned char keyid[EVP_MAX_MD_SIZE];
3358 unsigned int keyidlen = 0;
3360 xcert = d2i_X509(NULL, &p, len);
3361 if (xcert == NULL) {
3362 SET_ERROR(kmfh, ERR_get_error());
3363 rv = KMF_ERR_ENCODING;
3365 if (certlist[i].kmf_private.label != NULL) {
3366 /* Set alias attribute */
3367 (void) X509_alias_set1(xcert,
3368 (uchar_t *)certlist[i].kmf_private.label,
3369 strlen(certlist[i].kmf_private.label));
3371 /* Check if there is a key corresponding to this cert */
3372 pkey = find_matching_key(xcert, numkeys, keylist);
3375 * If key is found, get fingerprint and create a
3376 * safebag.
3378 if (pkey != NULL) {
3379 (void) X509_digest(xcert, EVP_sha1(),
3380 keyid, &keyidlen);
3381 key_authsafe = add_key_to_safe(pkey, cred,
3382 keyid, keyidlen,
3383 certlist[i].kmf_private.label,
3384 (certlist[i].kmf_private.label ?
3385 strlen(certlist[i].kmf_private.label) : 0));
3387 if (key_authsafe == NULL) {
3388 X509_free(xcert);
3389 EVP_PKEY_free(pkey);
3390 goto cleanup;
3392 /* Put the key safe into the Auth Safe */
3393 if (!sk_PKCS7_push(authsafe_stack,
3394 key_authsafe)) {
3395 X509_free(xcert);
3396 EVP_PKEY_free(pkey);
3397 goto cleanup;
3401 /* create a certificate safebag */
3402 cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3403 keyidlen);
3404 if (cert_authsafe == NULL) {
3405 X509_free(xcert);
3406 EVP_PKEY_free(pkey);
3407 goto cleanup;
3409 if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3410 X509_free(xcert);
3411 EVP_PKEY_free(pkey);
3412 goto cleanup;
3415 X509_free(xcert);
3416 if (pkey)
3417 EVP_PKEY_free(pkey);
3419 } else if (numcerts == 0 && numkeys > 0) {
3421 * If only adding keys to the file.
3423 for (i = 0; i < numkeys; i++) {
3424 EVP_PKEY *pkey = NULL;
3426 if (keylist[i].israw)
3427 pkey = raw_key_to_pkey(&keylist[i]);
3428 else
3429 pkey = (EVP_PKEY *)keylist[i].keyp;
3431 if (pkey == NULL)
3432 continue;
3434 key_authsafe = add_key_to_safe(pkey, cred,
3435 NULL, 0, NULL, 0);
3437 if (key_authsafe == NULL) {
3438 EVP_PKEY_free(pkey);
3439 goto cleanup;
3441 if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3442 EVP_PKEY_free(pkey);
3443 goto cleanup;
3447 p12_elem = PKCS12_init(NID_pkcs7_data);
3448 if (p12_elem == NULL) {
3449 goto cleanup;
3452 /* Put the PKCS#7 stack into the PKCS#12 element. */
3453 if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3454 goto cleanup;
3457 /* Set the integrity MAC on the PKCS#12 element. */
3458 if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3459 NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3460 goto cleanup;
3463 /* Write the PKCS#12 element to the export file. */
3464 if (!i2d_PKCS12_bio(bio, p12_elem)) {
3465 goto cleanup;
3467 PKCS12_free(p12_elem);
3469 cleanup:
3470 /* Clear away the PKCS#7 stack, we're done with it. */
3471 if (authsafe_stack)
3472 sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3474 if (bio != NULL)
3475 (void) BIO_free_all(bio);
3477 return (rv);
3480 KMF_RETURN
3481 openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3482 KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3483 KMF_CREDENTIAL *p12cred, char *filename)
3485 KMF_RETURN rv;
3487 if (certlist == NULL && keylist == NULL)
3488 return (KMF_ERR_BAD_PARAMETER);
3490 rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3491 numkeys, keylist, filename);
3493 return (rv);
3496 KMF_RETURN
3497 OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3499 KMF_RETURN rv;
3500 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3501 char *fullpath = NULL;
3502 char *dirpath = NULL;
3503 char *certfile = NULL;
3504 char *keyfile = NULL;
3505 char *filename = NULL;
3506 KMF_CREDENTIAL *p12cred = NULL;
3507 KMF_X509_DER_CERT certdata;
3508 KMF_KEY_HANDLE key;
3509 int gotkey = 0;
3510 int gotcert = 0;
3512 if (handle == NULL)
3513 return (KMF_ERR_BAD_PARAMETER);
3516 * First, find the certificate.
3518 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3519 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3520 if (certfile != NULL) {
3521 fullpath = get_fullpath(dirpath, certfile);
3522 if (fullpath == NULL)
3523 return (KMF_ERR_BAD_PARAMETER);
3525 if (isdir(fullpath)) {
3526 free(fullpath);
3527 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3530 (void) memset(&certdata, 0, sizeof (certdata));
3531 rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3532 fullpath, &certdata.certificate);
3533 if (rv != KMF_OK)
3534 goto end;
3536 gotcert++;
3537 certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3538 free(fullpath);
3542 * Now find the private key.
3544 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3545 if (keyfile != NULL) {
3546 fullpath = get_fullpath(dirpath, keyfile);
3547 if (fullpath == NULL)
3548 return (KMF_ERR_BAD_PARAMETER);
3550 if (isdir(fullpath)) {
3551 free(fullpath);
3552 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3555 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3556 rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3557 if (rv != KMF_OK)
3558 goto end;
3559 gotkey++;
3563 * Open the output file.
3565 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3566 numattr);
3567 if (filename == NULL) {
3568 rv = KMF_ERR_BAD_PARAMETER;
3569 goto end;
3572 /* Stick the key and the cert into a PKCS#12 file */
3573 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3574 if (p12cred == NULL) {
3575 rv = KMF_ERR_BAD_PARAMETER;
3576 goto end;
3579 rv = local_export_pk12(handle, p12cred, 1, &certdata,
3580 1, &key, filename);
3582 end:
3583 if (fullpath)
3584 free(fullpath);
3586 if (gotcert)
3587 kmf_free_kmf_cert(handle, &certdata);
3588 if (gotkey)
3589 kmf_free_kmf_key(handle, &key);
3590 return (rv);
3594 * Helper function to extract keys and certificates from
3595 * a single PEM file. Typically the file should contain a
3596 * private key and an associated public key wrapped in an x509 cert.
3597 * However, the file may be just a list of X509 certs with no keys.
3599 static KMF_RETURN
3600 extract_pem(KMF_HANDLE *kmfh,
3601 char *issuer, char *subject, KMF_BIGINT *serial,
3602 char *filename, CK_UTF8CHAR *pin,
3603 CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3604 int *numcerts)
3605 /* ARGSUSED6 */
3607 KMF_RETURN rv = KMF_OK;
3608 FILE *fp;
3609 STACK_OF(X509_INFO) *x509_info_stack = NULL;
3610 int i, ncerts = 0, matchcerts = 0;
3611 EVP_PKEY *pkey = NULL;
3612 X509_INFO *info;
3613 X509 *x;
3614 X509_INFO **cert_infos = NULL;
3615 KMF_DATA *certlist = NULL;
3617 if (priv_key)
3618 *priv_key = NULL;
3619 if (certs)
3620 *certs = NULL;
3621 fp = fopen(filename, "r");
3622 if (fp == NULL)
3623 return (KMF_ERR_OPEN_FILE);
3625 x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3626 if (x509_info_stack == NULL) {
3627 (void) fclose(fp);
3628 return (KMF_ERR_ENCODING);
3630 cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3631 sizeof (X509_INFO *));
3632 if (cert_infos == NULL) {
3633 (void) fclose(fp);
3634 rv = KMF_ERR_MEMORY;
3635 goto err;
3638 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3639 /* LINTED E_BAD_PTR_CAST_ALIGN */
3640 cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
3641 ncerts++;
3644 if (ncerts == 0) {
3645 (void) fclose(fp);
3646 rv = KMF_ERR_CERT_NOT_FOUND;
3647 goto err;
3650 if (priv_key != NULL) {
3651 rewind(fp);
3652 pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
3654 (void) fclose(fp);
3656 x = cert_infos[ncerts - 1]->x509;
3658 * Make sure the private key matchs the last cert in the file.
3660 if (pkey != NULL && !X509_check_private_key(x, pkey)) {
3661 EVP_PKEY_free(pkey);
3662 rv = KMF_ERR_KEY_MISMATCH;
3663 goto err;
3666 certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
3667 if (certlist == NULL) {
3668 if (pkey != NULL)
3669 EVP_PKEY_free(pkey);
3670 rv = KMF_ERR_MEMORY;
3671 goto err;
3675 * Convert all of the certs to DER format.
3677 matchcerts = 0;
3678 for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
3679 boolean_t match = FALSE;
3680 info = cert_infos[ncerts - 1 - i];
3682 rv = check_cert(info->x509, issuer, subject, serial, &match);
3683 if (rv != KMF_OK || match != TRUE) {
3684 rv = KMF_OK;
3685 continue;
3688 rv = ssl_cert2KMFDATA(kmfh, info->x509,
3689 &certlist[matchcerts++]);
3691 if (rv != KMF_OK) {
3692 int j;
3693 for (j = 0; j < matchcerts; j++)
3694 kmf_free_data(&certlist[j]);
3695 free(certlist);
3696 certlist = NULL;
3697 ncerts = matchcerts = 0;
3701 if (numcerts != NULL)
3702 *numcerts = matchcerts;
3704 if (certs != NULL)
3705 *certs = certlist;
3706 else if (certlist != NULL) {
3707 for (i = 0; i < ncerts; i++)
3708 kmf_free_data(&certlist[i]);
3709 free(certlist);
3710 certlist = NULL;
3713 if (priv_key == NULL && pkey != NULL)
3714 EVP_PKEY_free(pkey);
3715 else if (priv_key != NULL && pkey != NULL)
3716 *priv_key = pkey;
3718 err:
3719 /* Cleanup the stack of X509 info records */
3720 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3721 /* LINTED E_BAD_PTR_CAST_ALIGN */
3722 info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3723 X509_INFO_free(info);
3725 if (x509_info_stack)
3726 sk_X509_INFO_free(x509_info_stack);
3728 if (cert_infos != NULL)
3729 free(cert_infos);
3731 return (rv);
3734 static KMF_RETURN
3735 openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3736 STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3738 KMF_RETURN ret;
3739 int i;
3741 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3742 /* LINTED E_BAD_PTR_CAST_ALIGN */
3743 PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3744 ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3745 keys, certs);
3747 if (ret != KMF_OK)
3748 return (ret);
3751 return (ret);
3754 static KMF_RETURN
3755 set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3757 X509_ATTRIBUTE *attr = NULL;
3759 if (pkey == NULL || attrib == NULL)
3760 return (KMF_ERR_BAD_PARAMETER);
3762 if (pkey->attributes == NULL) {
3763 pkey->attributes = sk_X509_ATTRIBUTE_new_null();
3764 if (pkey->attributes == NULL)
3765 return (KMF_ERR_MEMORY);
3767 attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3768 if (attr != NULL) {
3769 int i;
3770 X509_ATTRIBUTE *a;
3771 for (i = 0;
3772 i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3773 /* LINTED E_BAD_PTR_CASE_ALIGN */
3774 a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
3775 if (OBJ_obj2nid(a->object) == nid) {
3776 X509_ATTRIBUTE_free(a);
3777 /* LINTED E_BAD_PTR_CAST_ALIGN */
3778 (void) sk_X509_ATTRIBUTE_set(pkey->attributes,
3779 i, attr);
3780 return (KMF_OK);
3783 if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
3784 X509_ATTRIBUTE_free(attr);
3785 return (KMF_ERR_MEMORY);
3787 } else {
3788 return (KMF_ERR_MEMORY);
3791 return (KMF_OK);
3794 static KMF_RETURN
3795 openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3796 STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3798 KMF_RETURN ret = KMF_OK;
3799 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3800 EVP_PKEY *pkey = NULL;
3801 X509 *xcert = NULL;
3802 ASN1_TYPE *keyid = NULL;
3803 ASN1_TYPE *fname = NULL;
3804 uchar_t *data = NULL;
3806 keyid = PKCS12_get_attr(bag, NID_localKeyID);
3807 fname = PKCS12_get_attr(bag, NID_friendlyName);
3809 switch (M_PKCS12_bag_type(bag)) {
3810 case NID_keyBag:
3811 if (keylist == NULL)
3812 goto end;
3813 pkey = EVP_PKCS82PKEY(bag->value.keybag);
3814 if (pkey == NULL)
3815 ret = KMF_ERR_PKCS12_FORMAT;
3817 break;
3818 case NID_pkcs8ShroudedKeyBag:
3819 if (keylist == NULL)
3820 goto end;
3821 p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
3822 if (p8 == NULL)
3823 return (KMF_ERR_AUTH_FAILED);
3824 pkey = EVP_PKCS82PKEY(p8);
3825 PKCS8_PRIV_KEY_INFO_free(p8);
3826 if (pkey == NULL)
3827 ret = KMF_ERR_PKCS12_FORMAT;
3828 break;
3829 case NID_certBag:
3830 if (certlist == NULL)
3831 goto end;
3832 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
3833 return (KMF_ERR_PKCS12_FORMAT);
3834 xcert = M_PKCS12_certbag2x509(bag);
3835 if (xcert == NULL) {
3836 ret = KMF_ERR_PKCS12_FORMAT;
3837 goto end;
3839 if (keyid != NULL) {
3840 if (X509_keyid_set1(xcert,
3841 keyid->value.octet_string->data,
3842 keyid->value.octet_string->length) == 0) {
3843 ret = KMF_ERR_PKCS12_FORMAT;
3844 goto end;
3847 if (fname != NULL) {
3848 int len, r;
3849 len = ASN1_STRING_to_UTF8(&data,
3850 fname->value.asn1_string);
3851 if (len > 0 && data != NULL) {
3852 r = X509_alias_set1(xcert, data, len);
3853 if (r == NULL) {
3854 ret = KMF_ERR_PKCS12_FORMAT;
3855 goto end;
3857 } else {
3858 ret = KMF_ERR_PKCS12_FORMAT;
3859 goto end;
3862 if (sk_X509_push(certlist, xcert) == 0)
3863 ret = KMF_ERR_MEMORY;
3864 else
3865 xcert = NULL;
3866 break;
3867 case NID_safeContentsBag:
3868 return (openssl_parse_bags(bag->value.safes, pass,
3869 keylist, certlist));
3870 default:
3871 ret = KMF_ERR_PKCS12_FORMAT;
3872 break;
3876 * Set the ID and/or FriendlyName attributes on the key.
3877 * If converting to PKCS11 objects, these can translate to CKA_ID
3878 * and CKA_LABEL values.
3880 if (pkey != NULL && ret == KMF_OK) {
3881 ASN1_TYPE *attr = NULL;
3882 if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3883 if ((attr = ASN1_TYPE_new()) == NULL)
3884 return (KMF_ERR_MEMORY);
3885 attr->value.octet_string =
3886 ASN1_STRING_dup(keyid->value.octet_string);
3887 attr->type = V_ASN1_OCTET_STRING;
3888 attr->value.ptr = (char *)attr->value.octet_string;
3889 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3890 OPENSSL_free(attr);
3893 if (ret == KMF_OK && fname != NULL &&
3894 fname->type == V_ASN1_BMPSTRING) {
3895 if ((attr = ASN1_TYPE_new()) == NULL)
3896 return (KMF_ERR_MEMORY);
3897 attr->value.bmpstring =
3898 ASN1_STRING_dup(fname->value.bmpstring);
3899 attr->type = V_ASN1_BMPSTRING;
3900 attr->value.ptr = (char *)attr->value.bmpstring;
3901 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3902 OPENSSL_free(attr);
3905 if (ret == KMF_OK && keylist != NULL &&
3906 sk_EVP_PKEY_push(keylist, pkey) == 0)
3907 ret = KMF_ERR_MEMORY;
3909 if (ret == KMF_OK && keylist != NULL)
3910 pkey = NULL;
3911 end:
3912 if (pkey != NULL)
3913 EVP_PKEY_free(pkey);
3914 if (xcert != NULL)
3915 X509_free(xcert);
3916 if (data != NULL)
3917 OPENSSL_free(data);
3919 return (ret);
3922 static KMF_RETURN
3923 openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3924 STACK_OF(EVP_PKEY) *keys,
3925 STACK_OF(X509) *certs,
3926 STACK_OF(X509) *ca)
3927 /* ARGSUSED3 */
3929 KMF_RETURN ret = KMF_OK;
3930 STACK_OF(PKCS7) *asafes = NULL;
3931 STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
3932 int i, bagnid;
3933 PKCS7 *p7;
3935 if (p12 == NULL || (keys == NULL && certs == NULL))
3936 return (KMF_ERR_BAD_PARAMETER);
3938 if (pin == NULL || *pin == NULL) {
3939 if (PKCS12_verify_mac(p12, NULL, 0)) {
3940 pin = NULL;
3941 } else if (PKCS12_verify_mac(p12, "", 0)) {
3942 pin = "";
3943 } else {
3944 return (KMF_ERR_AUTH_FAILED);
3946 } else if (!PKCS12_verify_mac(p12, pin, -1)) {
3947 return (KMF_ERR_AUTH_FAILED);
3950 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
3951 return (KMF_ERR_PKCS12_FORMAT);
3953 for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
3954 bags = NULL;
3955 /* LINTED E_BAD_PTR_CAST_ALIGN */
3956 p7 = sk_PKCS7_value(asafes, i);
3957 bagnid = OBJ_obj2nid(p7->type);
3959 if (bagnid == NID_pkcs7_data) {
3960 bags = PKCS12_unpack_p7data(p7);
3961 } else if (bagnid == NID_pkcs7_encrypted) {
3962 bags = PKCS12_unpack_p7encdata(p7, pin,
3963 (pin ? strlen(pin) : 0));
3964 } else {
3965 continue;
3967 if (bags == NULL) {
3968 ret = KMF_ERR_PKCS12_FORMAT;
3969 goto out;
3972 if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
3973 ret = KMF_ERR_PKCS12_FORMAT;
3975 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
3977 out:
3978 if (asafes != NULL)
3979 sk_PKCS7_pop_free(asafes, PKCS7_free);
3981 return (ret);
3985 * Helper function to decrypt and parse PKCS#12 import file.
3987 static KMF_RETURN
3988 extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3989 STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
3990 STACK_OF(X509) **ca)
3991 /* ARGSUSED2 */
3993 PKCS12 *pk12, *pk12_tmp;
3994 STACK_OF(EVP_PKEY) *pkeylist = NULL;
3995 STACK_OF(X509) *xcertlist = NULL;
3996 STACK_OF(X509) *cacertlist = NULL;
3998 if ((pk12 = PKCS12_new()) == NULL) {
3999 return (KMF_ERR_MEMORY);
4002 if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
4003 /* This is ok; it seems to mean there is no more to read. */
4004 if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
4005 ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
4006 goto end_extract_pkcs12;
4008 PKCS12_free(pk12);
4009 return (KMF_ERR_PKCS12_FORMAT);
4011 pk12 = pk12_tmp;
4013 xcertlist = sk_X509_new_null();
4014 if (xcertlist == NULL) {
4015 PKCS12_free(pk12);
4016 return (KMF_ERR_MEMORY);
4018 pkeylist = sk_EVP_PKEY_new_null();
4019 if (pkeylist == NULL) {
4020 sk_X509_pop_free(xcertlist, X509_free);
4021 PKCS12_free(pk12);
4022 return (KMF_ERR_MEMORY);
4025 if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4026 cacertlist) != KMF_OK) {
4027 sk_X509_pop_free(xcertlist, X509_free);
4028 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4029 PKCS12_free(pk12);
4030 return (KMF_ERR_PKCS12_FORMAT);
4033 if (priv_key && pkeylist)
4034 *priv_key = pkeylist;
4035 else if (pkeylist)
4036 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4037 if (certs && xcertlist)
4038 *certs = xcertlist;
4039 else if (xcertlist)
4040 sk_X509_pop_free(xcertlist, X509_free);
4041 if (ca && cacertlist)
4042 *ca = cacertlist;
4043 else if (cacertlist)
4044 sk_X509_pop_free(cacertlist, X509_free);
4046 end_extract_pkcs12:
4048 PKCS12_free(pk12);
4049 return (KMF_OK);
4052 static KMF_RETURN
4053 sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4055 KMF_RETURN rv = KMF_OK;
4056 uint32_t sz;
4058 sz = BN_num_bytes(from);
4059 to->val = (uchar_t *)malloc(sz);
4060 if (to->val == NULL)
4061 return (KMF_ERR_MEMORY);
4063 if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4064 free(to->val);
4065 to->val = NULL;
4066 to->len = 0;
4067 rv = KMF_ERR_MEMORY;
4070 return (rv);
4073 static KMF_RETURN
4074 exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4076 KMF_RETURN rv;
4077 KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4079 (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4080 if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
4081 goto cleanup;
4083 if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
4084 goto cleanup;
4086 if (rsa->d != NULL)
4087 if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
4088 goto cleanup;
4090 if (rsa->p != NULL)
4091 if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
4092 goto cleanup;
4094 if (rsa->q != NULL)
4095 if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
4096 goto cleanup;
4098 if (rsa->dmp1 != NULL)
4099 if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
4100 goto cleanup;
4102 if (rsa->dmq1 != NULL)
4103 if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
4104 goto cleanup;
4106 if (rsa->iqmp != NULL)
4107 if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
4108 goto cleanup;
4109 cleanup:
4110 if (rv != KMF_OK)
4111 kmf_free_raw_key(key);
4112 else
4113 key->keytype = KMF_RSA;
4116 * Free the reference to this key, SSL will not actually free
4117 * the memory until the refcount == 0, so this is safe.
4119 RSA_free(rsa);
4121 return (rv);
4124 static KMF_RETURN
4125 exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4127 KMF_RETURN rv;
4128 KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4130 (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4131 if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
4132 goto cleanup;
4134 if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
4135 goto cleanup;
4137 if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
4138 goto cleanup;
4140 if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
4141 goto cleanup;
4143 cleanup:
4144 if (rv != KMF_OK)
4145 kmf_free_raw_key(key);
4146 else
4147 key->keytype = KMF_DSA;
4150 * Free the reference to this key, SSL will not actually free
4151 * the memory until the refcount == 0, so this is safe.
4153 DSA_free(dsa);
4155 return (rv);
4158 static KMF_RETURN
4159 add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4160 KMF_X509_DER_CERT **certlist, int *ncerts)
4162 KMF_RETURN rv = KMF_OK;
4163 KMF_X509_DER_CERT *list = (*certlist);
4164 KMF_X509_DER_CERT cert;
4165 int n = (*ncerts);
4167 if (list == NULL) {
4168 list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4169 } else {
4170 list = (KMF_X509_DER_CERT *)realloc(list,
4171 sizeof (KMF_X509_DER_CERT) * (n + 1));
4174 if (list == NULL)
4175 return (KMF_ERR_MEMORY);
4177 (void) memset(&cert, 0, sizeof (cert));
4178 rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4179 if (rv == KMF_OK) {
4180 int len = 0;
4181 /* Get the alias name for the cert if there is one */
4182 char *a = (char *)X509_alias_get0(sslcert, &len);
4183 if (a != NULL)
4184 cert.kmf_private.label = strdup(a);
4185 cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4187 list[n] = cert;
4188 (*ncerts) = n + 1;
4190 *certlist = list;
4191 } else {
4192 free(list);
4195 return (rv);
4198 static KMF_RETURN
4199 add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4200 KMF_RAW_KEY_DATA *newkey, int *nkeys)
4202 KMF_RAW_KEY_DATA *list = (*keylist);
4203 int n = (*nkeys);
4205 if (list == NULL) {
4206 list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4207 } else {
4208 list = (KMF_RAW_KEY_DATA *)realloc(list,
4209 sizeof (KMF_RAW_KEY_DATA) * (n + 1));
4212 if (list == NULL)
4213 return (KMF_ERR_MEMORY);
4215 list[n] = *newkey;
4216 (*nkeys) = n + 1;
4218 *keylist = list;
4220 return (KMF_OK);
4223 static X509_ATTRIBUTE *
4224 find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4226 X509_ATTRIBUTE *a;
4227 int i;
4229 if (attrs == NULL)
4230 return (NULL);
4232 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4233 /* LINTED E_BAD_PTR_CAST_ALIGN */
4234 a = sk_X509_ATTRIBUTE_value(attrs, i);
4235 if (OBJ_obj2nid(a->object) == nid)
4236 return (a);
4238 return (NULL);
4241 static KMF_RETURN
4242 convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4244 KMF_RETURN rv = KMF_OK;
4245 X509_ATTRIBUTE *attr;
4247 if (pkey == NULL || key == NULL)
4248 return (KMF_ERR_BAD_PARAMETER);
4249 /* Convert SSL key to raw key */
4250 switch (pkey->type) {
4251 case EVP_PKEY_RSA:
4252 rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
4253 key);
4254 if (rv != KMF_OK)
4255 return (rv);
4256 break;
4257 case EVP_PKEY_DSA:
4258 rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
4259 key);
4260 if (rv != KMF_OK)
4261 return (rv);
4262 break;
4263 default:
4264 return (KMF_ERR_BAD_PARAMETER);
4267 * If friendlyName, add it to record.
4269 attr = find_attr(pkey->attributes, NID_friendlyName);
4270 if (attr != NULL) {
4271 ASN1_TYPE *ty = NULL;
4272 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4273 if (attr->single == 0 && numattr > 0) {
4274 /* LINTED E_BAD_PTR_CAST_ALIGN */
4275 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4277 if (ty != NULL) {
4278 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4279 key->label = uni2asc(ty->value.bmpstring->data,
4280 ty->value.bmpstring->length);
4281 #else
4282 key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4283 ty->value.bmpstring->length);
4284 #endif
4286 } else {
4287 key->label = NULL;
4291 * If KeyID, add it to record as a KMF_DATA object.
4293 attr = find_attr(pkey->attributes, NID_localKeyID);
4294 if (attr != NULL) {
4295 ASN1_TYPE *ty = NULL;
4296 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4297 if (attr->single == 0 && numattr > 0) {
4298 /* LINTED E_BAD_PTR_CAST_ALIGN */
4299 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4301 key->id.Data = (uchar_t *)malloc(
4302 ty->value.octet_string->length);
4303 if (key->id.Data == NULL)
4304 return (KMF_ERR_MEMORY);
4305 (void) memcpy(key->id.Data, ty->value.octet_string->data,
4306 ty->value.octet_string->length);
4307 key->id.Length = ty->value.octet_string->length;
4308 } else {
4309 (void) memset(&key->id, 0, sizeof (KMF_DATA));
4312 return (rv);
4315 static KMF_RETURN
4316 convertPK12Objects(
4317 KMF_HANDLE *kmfh,
4318 STACK_OF(EVP_PKEY) *sslkeys,
4319 STACK_OF(X509) *sslcert,
4320 STACK_OF(X509) *sslcacerts,
4321 KMF_RAW_KEY_DATA **keylist, int *nkeys,
4322 KMF_X509_DER_CERT **certlist, int *ncerts)
4324 KMF_RETURN rv = KMF_OK;
4325 KMF_RAW_KEY_DATA key;
4326 int i;
4328 for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4329 /* LINTED E_BAD_PTR_CAST_ALIGN */
4330 EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4331 rv = convertToRawKey(pkey, &key);
4332 if (rv == KMF_OK)
4333 rv = add_key_to_list(keylist, &key, nkeys);
4335 if (rv != KMF_OK)
4336 return (rv);
4339 /* Now add the certificate to the certlist */
4340 for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4341 /* LINTED E_BAD_PTR_CAST_ALIGN */
4342 X509 *cert = sk_X509_value(sslcert, i);
4343 rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4344 if (rv != KMF_OK)
4345 return (rv);
4348 /* Also add any included CA certs to the list */
4349 for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4350 X509 *c;
4352 * sk_X509_value() is macro that embeds a cast to (X509 *).
4353 * Here it translates into ((X509 *)sk_value((ca), (i))).
4354 * Lint is complaining about the embedded casting, and
4355 * to fix it, you need to fix openssl header files.
4357 /* LINTED E_BAD_PTR_CAST_ALIGN */
4358 c = sk_X509_value(sslcacerts, i);
4360 /* Now add the ca cert to the certlist */
4361 rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4362 if (rv != KMF_OK)
4363 return (rv);
4365 return (rv);
4368 KMF_RETURN
4369 openssl_import_objects(KMF_HANDLE *kmfh,
4370 char *filename, KMF_CREDENTIAL *cred,
4371 KMF_X509_DER_CERT **certlist, int *ncerts,
4372 KMF_RAW_KEY_DATA **keylist, int *nkeys)
4374 KMF_RETURN rv = KMF_OK;
4375 KMF_ENCODE_FORMAT format;
4376 BIO *bio = NULL;
4377 STACK_OF(EVP_PKEY) *privkeys = NULL;
4378 STACK_OF(X509) *certs = NULL;
4379 STACK_OF(X509) *cacerts = NULL;
4382 * auto-detect the file format, regardless of what
4383 * the 'format' parameters in the params say.
4385 rv = kmf_get_file_format(filename, &format);
4386 if (rv != KMF_OK) {
4387 return (rv);
4390 /* This function only works for PEM or PKCS#12 files */
4391 if (format != KMF_FORMAT_PEM &&
4392 format != KMF_FORMAT_PEM_KEYPAIR &&
4393 format != KMF_FORMAT_PKCS12)
4394 return (KMF_ERR_ENCODING);
4396 *certlist = NULL;
4397 *keylist = NULL;
4398 *ncerts = 0;
4399 *nkeys = 0;
4401 if (format == KMF_FORMAT_PKCS12) {
4402 bio = BIO_new_file(filename, "rb");
4403 if (bio == NULL) {
4404 SET_ERROR(kmfh, ERR_get_error());
4405 rv = KMF_ERR_OPEN_FILE;
4406 goto end;
4409 rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4410 (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4412 if (rv == KMF_OK)
4413 /* Convert keys and certs to exportable format */
4414 rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4415 keylist, nkeys, certlist, ncerts);
4416 } else {
4417 EVP_PKEY *pkey;
4418 KMF_DATA *certdata = NULL;
4419 KMF_X509_DER_CERT *kmfcerts = NULL;
4420 int i;
4421 rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4422 (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4423 &pkey, &certdata, ncerts);
4425 /* Reached end of import file? */
4426 if (rv == KMF_OK && pkey != NULL) {
4427 privkeys = sk_EVP_PKEY_new_null();
4428 if (privkeys == NULL) {
4429 rv = KMF_ERR_MEMORY;
4430 goto end;
4432 (void) sk_EVP_PKEY_push(privkeys, pkey);
4433 /* convert the certificate list here */
4434 if (*ncerts > 0 && certlist != NULL) {
4435 kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4436 sizeof (KMF_X509_DER_CERT));
4437 if (kmfcerts == NULL) {
4438 rv = KMF_ERR_MEMORY;
4439 goto end;
4441 for (i = 0; i < *ncerts; i++) {
4442 kmfcerts[i].certificate = certdata[i];
4443 kmfcerts[i].kmf_private.keystore_type =
4444 KMF_KEYSTORE_OPENSSL;
4446 *certlist = kmfcerts;
4449 * Convert keys to exportable format, the certs
4450 * are already OK.
4452 rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4453 keylist, nkeys, NULL, NULL);
4456 end:
4457 if (bio != NULL)
4458 (void) BIO_free(bio);
4460 if (privkeys)
4461 sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4462 if (certs)
4463 sk_X509_pop_free(certs, X509_free);
4464 if (cacerts)
4465 sk_X509_pop_free(cacerts, X509_free);
4467 return (rv);
4470 static KMF_RETURN
4471 create_deskey(DES_cblock **deskey)
4473 DES_cblock *key;
4475 key = (DES_cblock *) malloc(sizeof (DES_cblock));
4476 if (key == NULL) {
4477 return (KMF_ERR_MEMORY);
4480 if (DES_random_key(key) == 0) {
4481 free(key);
4482 return (KMF_ERR_KEYGEN_FAILED);
4485 *deskey = key;
4486 return (KMF_OK);
4489 #define KEYGEN_RETRY 3
4490 #define DES3_KEY_SIZE 24
4492 static KMF_RETURN
4493 create_des3key(unsigned char **des3key)
4495 KMF_RETURN ret = KMF_OK;
4496 DES_cblock *deskey1 = NULL;
4497 DES_cblock *deskey2 = NULL;
4498 DES_cblock *deskey3 = NULL;
4499 unsigned char *newkey = NULL;
4500 int retry;
4502 if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4503 return (KMF_ERR_MEMORY);
4506 /* create the 1st DES key */
4507 if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4508 goto out;
4512 * Create the 2nd DES key and make sure its value is different
4513 * from the 1st DES key.
4515 retry = 0;
4516 do {
4517 if (deskey2 != NULL) {
4518 free(deskey2);
4519 deskey2 = NULL;
4522 if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4523 goto out;
4526 if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4527 == 0) {
4528 ret = KMF_ERR_KEYGEN_FAILED;
4529 retry++;
4531 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4533 if (ret != KMF_OK) {
4534 goto out;
4538 * Create the 3rd DES key and make sure its value is different
4539 * from the 2nd DES key.
4541 retry = 0;
4542 do {
4543 if (deskey3 != NULL) {
4544 free(deskey3);
4545 deskey3 = NULL;
4548 if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4549 goto out;
4552 if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4553 == 0) {
4554 ret = KMF_ERR_KEYGEN_FAILED;
4555 retry++;
4557 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4559 if (ret != KMF_OK) {
4560 goto out;
4563 /* Concatenate 3 DES keys into a DES3 key */
4564 (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4565 (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4566 (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4567 *des3key = newkey;
4569 out:
4570 if (deskey1 != NULL)
4571 free(deskey1);
4573 if (deskey2 != NULL)
4574 free(deskey2);
4576 if (deskey3 != NULL)
4577 free(deskey3);
4579 if (ret != KMF_OK && newkey != NULL)
4580 free(newkey);
4582 return (ret);
4585 KMF_RETURN
4586 OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4587 int numattr, KMF_ATTRIBUTE *attrlist)
4589 KMF_RETURN ret = KMF_OK;
4590 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4591 char *fullpath = NULL;
4592 KMF_RAW_SYM_KEY *rkey = NULL;
4593 DES_cblock *deskey = NULL;
4594 unsigned char *des3key = NULL;
4595 unsigned char *random = NULL;
4596 int fd = -1;
4597 KMF_KEY_HANDLE *symkey;
4598 KMF_KEY_ALG keytype;
4599 uint32_t keylen;
4600 uint32_t keylen_size = sizeof (keylen);
4601 char *dirpath;
4602 char *keyfile;
4604 if (kmfh == NULL)
4605 return (KMF_ERR_UNINITIALIZED);
4607 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4608 if (symkey == NULL)
4609 return (KMF_ERR_BAD_PARAMETER);
4611 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4613 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4614 if (keyfile == NULL)
4615 return (KMF_ERR_BAD_PARAMETER);
4617 ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4618 (void *)&keytype, NULL);
4619 if (ret != KMF_OK)
4620 return (KMF_ERR_BAD_PARAMETER);
4622 ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4623 &keylen, &keylen_size);
4624 if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4625 (keytype == KMF_DES || keytype == KMF_DES3))
4626 /* keylength is not required for DES and 3DES */
4627 ret = KMF_OK;
4628 if (ret != KMF_OK)
4629 return (KMF_ERR_BAD_PARAMETER);
4631 fullpath = get_fullpath(dirpath, keyfile);
4632 if (fullpath == NULL)
4633 return (KMF_ERR_BAD_PARAMETER);
4635 /* If the requested file exists, return an error */
4636 if (test_for_file(fullpath, 0400) == 1) {
4637 free(fullpath);
4638 return (KMF_ERR_DUPLICATE_KEYFILE);
4641 fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4642 if (fd == -1) {
4643 ret = KMF_ERR_OPEN_FILE;
4644 goto out;
4647 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4648 if (rkey == NULL) {
4649 ret = KMF_ERR_MEMORY;
4650 goto out;
4652 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4654 if (keytype == KMF_DES) {
4655 if ((ret = create_deskey(&deskey)) != KMF_OK) {
4656 goto out;
4658 rkey->keydata.val = (uchar_t *)deskey;
4659 rkey->keydata.len = 8;
4661 symkey->keyalg = KMF_DES;
4663 } else if (keytype == KMF_DES3) {
4664 if ((ret = create_des3key(&des3key)) != KMF_OK) {
4665 goto out;
4667 rkey->keydata.val = (uchar_t *)des3key;
4668 rkey->keydata.len = DES3_KEY_SIZE;
4669 symkey->keyalg = KMF_DES3;
4671 } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4672 keytype == KMF_GENERIC_SECRET) {
4673 int bytes;
4675 if (keylen % 8 != 0) {
4676 ret = KMF_ERR_BAD_KEY_SIZE;
4677 goto out;
4680 if (keytype == KMF_AES) {
4681 if (keylen != 128 &&
4682 keylen != 192 &&
4683 keylen != 256) {
4684 ret = KMF_ERR_BAD_KEY_SIZE;
4685 goto out;
4689 bytes = keylen/8;
4690 random = malloc(bytes);
4691 if (random == NULL) {
4692 ret = KMF_ERR_MEMORY;
4693 goto out;
4695 if (RAND_bytes(random, bytes) != 1) {
4696 ret = KMF_ERR_KEYGEN_FAILED;
4697 goto out;
4700 rkey->keydata.val = (uchar_t *)random;
4701 rkey->keydata.len = bytes;
4702 symkey->keyalg = keytype;
4704 } else {
4705 ret = KMF_ERR_BAD_KEY_TYPE;
4706 goto out;
4709 (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4711 symkey->kstype = KMF_KEYSTORE_OPENSSL;
4712 symkey->keyclass = KMF_SYMMETRIC;
4713 symkey->keylabel = (char *)fullpath;
4714 symkey->israw = TRUE;
4715 symkey->keyp = rkey;
4717 out:
4718 if (fd != -1)
4719 (void) close(fd);
4721 if (ret != KMF_OK && fullpath != NULL) {
4722 free(fullpath);
4724 if (ret != KMF_OK) {
4725 kmf_free_raw_sym_key(rkey);
4726 symkey->keyp = NULL;
4727 symkey->keyalg = KMF_KEYALG_NONE;
4730 return (ret);
4734 * Check a file to see if it is a CRL file with PEM or DER format.
4735 * If success, return its format in the "pformat" argument.
4737 KMF_RETURN
4738 OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4740 KMF_RETURN ret = KMF_OK;
4741 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4742 BIO *bio = NULL;
4743 X509_CRL *xcrl = NULL;
4745 if (filename == NULL) {
4746 return (KMF_ERR_BAD_PARAMETER);
4749 bio = BIO_new_file(filename, "rb");
4750 if (bio == NULL) {
4751 SET_ERROR(kmfh, ERR_get_error());
4752 ret = KMF_ERR_OPEN_FILE;
4753 goto out;
4756 if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4757 *pformat = KMF_FORMAT_PEM;
4758 goto out;
4760 (void) BIO_free(bio);
4763 * Now try to read it as raw DER data.
4765 bio = BIO_new_file(filename, "rb");
4766 if (bio == NULL) {
4767 SET_ERROR(kmfh, ERR_get_error());
4768 ret = KMF_ERR_OPEN_FILE;
4769 goto out;
4772 if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4773 *pformat = KMF_FORMAT_ASN1;
4774 } else {
4775 ret = KMF_ERR_BAD_CRLFILE;
4778 out:
4779 if (bio != NULL)
4780 (void) BIO_free(bio);
4782 if (xcrl != NULL)
4783 X509_CRL_free(xcrl);
4785 return (ret);
4788 KMF_RETURN
4789 OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4790 KMF_RAW_SYM_KEY *rkey)
4792 KMF_RETURN rv = KMF_OK;
4793 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4794 KMF_DATA keyvalue;
4796 if (kmfh == NULL)
4797 return (KMF_ERR_UNINITIALIZED);
4799 if (symkey == NULL || rkey == NULL)
4800 return (KMF_ERR_BAD_PARAMETER);
4801 else if (symkey->keyclass != KMF_SYMMETRIC)
4802 return (KMF_ERR_BAD_KEY_CLASS);
4804 if (symkey->israw) {
4805 KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4807 if (rawkey == NULL ||
4808 rawkey->keydata.val == NULL ||
4809 rawkey->keydata.len == 0)
4810 return (KMF_ERR_BAD_KEYHANDLE);
4812 rkey->keydata.len = rawkey->keydata.len;
4813 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4814 return (KMF_ERR_MEMORY);
4815 (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4816 rkey->keydata.len);
4817 } else {
4818 rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4819 if (rv != KMF_OK)
4820 return (rv);
4821 rkey->keydata.len = keyvalue.Length;
4822 rkey->keydata.val = keyvalue.Data;
4825 return (rv);
4829 * substitute for the unsafe access(2) function.
4830 * If the file in question already exists, return 1.
4831 * else 0. If an error occurs during testing (other
4832 * than EEXIST), return -1.
4834 static int
4835 test_for_file(char *filename, mode_t mode)
4837 int fd;
4840 * Try to create the file with the EXCL flag.
4841 * The call should fail if the file exists.
4843 fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4844 if (fd == -1 && errno == EEXIST)
4845 return (1);
4846 else if (fd == -1) /* some other error */
4847 return (-1);
4849 /* The file did NOT exist. Delete the testcase. */
4850 (void) close(fd);
4851 (void) unlink(filename);
4852 return (0);
4855 KMF_RETURN
4856 OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4857 KMF_ATTRIBUTE *attrlist)
4859 KMF_RETURN rv = KMF_OK;
4860 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4861 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4862 KMF_RAW_KEY_DATA *rawkey;
4863 EVP_PKEY *pkey = NULL;
4864 KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4865 KMF_CREDENTIAL cred = { NULL, 0 };
4866 BIO *out = NULL;
4867 int keys = 0;
4868 char *fullpath = NULL;
4869 char *keyfile = NULL;
4870 char *dirpath = NULL;
4872 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4873 if (pubkey != NULL)
4874 keys++;
4876 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4877 if (prikey != NULL)
4878 keys++;
4880 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4881 if (rawkey != NULL)
4882 keys++;
4885 * Exactly 1 type of key must be passed to this function.
4887 if (keys != 1)
4888 return (KMF_ERR_BAD_PARAMETER);
4890 keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4891 numattr);
4892 if (keyfile == NULL)
4893 return (KMF_ERR_BAD_PARAMETER);
4895 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4897 fullpath = get_fullpath(dirpath, keyfile);
4899 /* Once we have the full path, we don't need the pieces */
4900 if (fullpath == NULL)
4901 return (KMF_ERR_BAD_PARAMETER);
4903 /* If the requested file exists, return an error */
4904 if (test_for_file(fullpath, 0400) == 1) {
4905 free(fullpath);
4906 return (KMF_ERR_DUPLICATE_KEYFILE);
4909 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4910 &format, NULL);
4911 if (rv != KMF_OK)
4912 /* format is optional. */
4913 rv = KMF_OK;
4915 /* CRED is not required for OpenSSL files */
4916 (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4917 &cred, NULL);
4919 /* Store the private key to the keyfile */
4920 out = BIO_new_file(fullpath, "wb");
4921 if (out == NULL) {
4922 SET_ERROR(kmfh, ERR_get_error());
4923 rv = KMF_ERR_OPEN_FILE;
4924 goto end;
4927 if (prikey != NULL && prikey->keyp != NULL) {
4928 if (prikey->keyalg == KMF_RSA ||
4929 prikey->keyalg == KMF_DSA) {
4930 pkey = (EVP_PKEY *)prikey->keyp;
4932 rv = ssl_write_key(kmfh, format,
4933 out, &cred, pkey, TRUE);
4935 if (rv == KMF_OK && prikey->keylabel == NULL) {
4936 prikey->keylabel = strdup(fullpath);
4937 if (prikey->keylabel == NULL)
4938 rv = KMF_ERR_MEMORY;
4941 } else if (pubkey != NULL && pubkey->keyp != NULL) {
4942 if (pubkey->keyalg == KMF_RSA ||
4943 pubkey->keyalg == KMF_DSA) {
4944 pkey = (EVP_PKEY *)pubkey->keyp;
4946 rv = ssl_write_key(kmfh, format,
4947 out, &cred, pkey, FALSE);
4949 if (rv == KMF_OK && pubkey->keylabel == NULL) {
4950 pubkey->keylabel = strdup(fullpath);
4951 if (pubkey->keylabel == NULL)
4952 rv = KMF_ERR_MEMORY;
4955 } else if (rawkey != NULL) {
4956 if (rawkey->keytype == KMF_RSA) {
4957 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
4958 } else if (rawkey->keytype == KMF_DSA) {
4959 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
4960 } else {
4961 rv = KMF_ERR_BAD_PARAMETER;
4963 if (pkey != NULL) {
4964 KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
4966 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
4967 (void *)&kclass, NULL);
4968 if (rv != KMF_OK)
4969 rv = KMF_OK;
4970 rv = ssl_write_key(kmfh, format, out,
4971 &cred, pkey, (kclass == KMF_ASYM_PRI));
4972 EVP_PKEY_free(pkey);
4976 end:
4978 if (out)
4979 (void) BIO_free(out);
4982 if (rv == KMF_OK)
4983 (void) chmod(fullpath, 0400);
4985 free(fullpath);
4986 return (rv);
4989 KMF_RETURN
4990 OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4992 KMF_RETURN ret = KMF_OK;
4993 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4994 X509_CRL *xcrl = NULL;
4995 X509 *xcert = NULL;
4996 EVP_PKEY *pkey;
4997 KMF_ENCODE_FORMAT format;
4998 BIO *in = NULL, *out = NULL;
4999 int openssl_ret = 0;
5000 KMF_ENCODE_FORMAT outformat;
5001 boolean_t crlcheck = FALSE;
5002 char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
5004 if (numattr == 0 || attrlist == NULL) {
5005 return (KMF_ERR_BAD_PARAMETER);
5008 /* CRL check is optional */
5009 (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
5010 &crlcheck, NULL);
5012 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5013 if (crlcheck == B_TRUE && certfile == NULL) {
5014 return (KMF_ERR_BAD_CERTFILE);
5017 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5018 incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5019 outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5021 crlfile = get_fullpath(dirpath, incrl);
5023 if (crlfile == NULL)
5024 return (KMF_ERR_BAD_CRLFILE);
5026 outcrlfile = get_fullpath(dirpath, outcrl);
5027 if (outcrlfile == NULL)
5028 return (KMF_ERR_BAD_CRLFILE);
5030 if (isdir(outcrlfile)) {
5031 free(outcrlfile);
5032 return (KMF_ERR_BAD_CRLFILE);
5035 ret = kmf_is_crl_file(handle, crlfile, &format);
5036 if (ret != KMF_OK) {
5037 free(outcrlfile);
5038 return (ret);
5041 in = BIO_new_file(crlfile, "rb");
5042 if (in == NULL) {
5043 SET_ERROR(kmfh, ERR_get_error());
5044 ret = KMF_ERR_OPEN_FILE;
5045 goto end;
5048 if (format == KMF_FORMAT_ASN1) {
5049 xcrl = d2i_X509_CRL_bio(in, NULL);
5050 } else if (format == KMF_FORMAT_PEM) {
5051 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5054 if (xcrl == NULL) {
5055 SET_ERROR(kmfh, ERR_get_error());
5056 ret = KMF_ERR_BAD_CRLFILE;
5057 goto end;
5060 /* If bypasscheck is specified, no need to verify. */
5061 if (crlcheck == B_FALSE)
5062 goto output;
5064 ret = kmf_is_cert_file(handle, certfile, &format);
5065 if (ret != KMF_OK)
5066 goto end;
5068 /* Read in the CA cert file and convert to X509 */
5069 if (BIO_read_filename(in, certfile) <= 0) {
5070 SET_ERROR(kmfh, ERR_get_error());
5071 ret = KMF_ERR_OPEN_FILE;
5072 goto end;
5075 if (format == KMF_FORMAT_ASN1) {
5076 xcert = d2i_X509_bio(in, NULL);
5077 } else if (format == KMF_FORMAT_PEM) {
5078 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5079 } else {
5080 ret = KMF_ERR_BAD_CERT_FORMAT;
5081 goto end;
5084 if (xcert == NULL) {
5085 SET_ERROR(kmfh, ERR_get_error());
5086 ret = KMF_ERR_BAD_CERT_FORMAT;
5087 goto end;
5089 /* Now get the public key from the CA cert */
5090 pkey = X509_get_pubkey(xcert);
5091 if (pkey == NULL) {
5092 SET_ERROR(kmfh, ERR_get_error());
5093 ret = KMF_ERR_BAD_CERTFILE;
5094 goto end;
5097 /* Verify the CRL with the CA's public key */
5098 openssl_ret = X509_CRL_verify(xcrl, pkey);
5099 EVP_PKEY_free(pkey);
5100 if (openssl_ret > 0) {
5101 ret = KMF_OK; /* verify succeed */
5102 } else {
5103 SET_ERROR(kmfh, openssl_ret);
5104 ret = KMF_ERR_BAD_CRLFILE;
5107 output:
5108 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5109 &outformat, NULL);
5110 if (ret != KMF_OK) {
5111 ret = KMF_OK;
5112 outformat = KMF_FORMAT_PEM;
5115 out = BIO_new_file(outcrlfile, "wb");
5116 if (out == NULL) {
5117 SET_ERROR(kmfh, ERR_get_error());
5118 ret = KMF_ERR_OPEN_FILE;
5119 goto end;
5122 if (outformat == KMF_FORMAT_ASN1) {
5123 openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5124 } else if (outformat == KMF_FORMAT_PEM) {
5125 openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5126 } else {
5127 ret = KMF_ERR_BAD_PARAMETER;
5128 goto end;
5131 if (openssl_ret <= 0) {
5132 SET_ERROR(kmfh, ERR_get_error());
5133 ret = KMF_ERR_WRITE_FILE;
5134 } else {
5135 ret = KMF_OK;
5138 end:
5139 if (xcrl != NULL)
5140 X509_CRL_free(xcrl);
5142 if (xcert != NULL)
5143 X509_free(xcert);
5145 if (in != NULL)
5146 (void) BIO_free(in);
5148 if (out != NULL)
5149 (void) BIO_free(out);
5151 if (outcrlfile != NULL)
5152 free(outcrlfile);
5154 return (ret);
5157 KMF_RETURN
5158 OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5160 KMF_RETURN ret = KMF_OK;
5161 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5162 X509_CRL *x = NULL;
5163 KMF_ENCODE_FORMAT format;
5164 char *crlfile = NULL;
5165 BIO *in = NULL;
5166 BIO *mem = NULL;
5167 long len;
5168 char *memptr;
5169 char *data = NULL;
5170 char **crldata;
5171 char *crlfilename, *dirpath;
5173 if (numattr == 0 || attrlist == NULL) {
5174 return (KMF_ERR_BAD_PARAMETER);
5176 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5177 attrlist, numattr);
5178 if (crlfilename == NULL)
5179 return (KMF_ERR_BAD_CRLFILE);
5181 crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5182 attrlist, numattr);
5184 if (crldata == NULL)
5185 return (KMF_ERR_BAD_PARAMETER);
5187 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5189 crlfile = get_fullpath(dirpath, crlfilename);
5191 if (crlfile == NULL)
5192 return (KMF_ERR_BAD_CRLFILE);
5194 if (isdir(crlfile)) {
5195 free(crlfile);
5196 return (KMF_ERR_BAD_CRLFILE);
5199 ret = kmf_is_crl_file(handle, crlfile, &format);
5200 if (ret != KMF_OK) {
5201 free(crlfile);
5202 return (ret);
5205 if (bio_err == NULL)
5206 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5208 in = BIO_new_file(crlfile, "rb");
5209 if (in == NULL) {
5210 SET_ERROR(kmfh, ERR_get_error());
5211 ret = KMF_ERR_OPEN_FILE;
5212 goto end;
5215 if (format == KMF_FORMAT_ASN1) {
5216 x = d2i_X509_CRL_bio(in, NULL);
5217 } else if (format == KMF_FORMAT_PEM) {
5218 x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5221 if (x == NULL) { /* should not happen */
5222 SET_ERROR(kmfh, ERR_get_error());
5223 ret = KMF_ERR_OPEN_FILE;
5224 goto end;
5227 mem = BIO_new(BIO_s_mem());
5228 if (mem == NULL) {
5229 SET_ERROR(kmfh, ERR_get_error());
5230 ret = KMF_ERR_MEMORY;
5231 goto end;
5234 (void) X509_CRL_print(mem, x);
5235 len = BIO_get_mem_data(mem, &memptr);
5236 if (len <= 0) {
5237 SET_ERROR(kmfh, ERR_get_error());
5238 ret = KMF_ERR_MEMORY;
5239 goto end;
5242 data = malloc(len + 1);
5243 if (data == NULL) {
5244 ret = KMF_ERR_MEMORY;
5245 goto end;
5248 (void) memcpy(data, memptr, len);
5249 data[len] = '\0';
5250 *crldata = data;
5252 end:
5253 if (x != NULL)
5254 X509_CRL_free(x);
5256 if (crlfile != NULL)
5257 free(crlfile);
5259 if (in != NULL)
5260 (void) BIO_free(in);
5262 if (mem != NULL)
5263 (void) BIO_free(mem);
5265 return (ret);
5268 KMF_RETURN
5269 OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5271 KMF_RETURN ret = KMF_OK;
5272 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5273 KMF_ENCODE_FORMAT format;
5274 char *crlfile = NULL;
5275 BIO *in = NULL;
5276 char *crlfilename, *dirpath;
5278 if (numattr == 0 || attrlist == NULL) {
5279 return (KMF_ERR_BAD_PARAMETER);
5282 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5283 attrlist, numattr);
5285 if (crlfilename == NULL)
5286 return (KMF_ERR_BAD_CRLFILE);
5288 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5290 crlfile = get_fullpath(dirpath, crlfilename);
5292 if (crlfile == NULL)
5293 return (KMF_ERR_BAD_CRLFILE);
5295 if (isdir(crlfile)) {
5296 ret = KMF_ERR_BAD_CRLFILE;
5297 goto end;
5300 ret = kmf_is_crl_file(handle, crlfile, &format);
5301 if (ret != KMF_OK)
5302 goto end;
5304 if (unlink(crlfile) != 0) {
5305 SET_SYS_ERROR(kmfh, errno);
5306 ret = KMF_ERR_INTERNAL;
5307 goto end;
5310 end:
5311 if (in != NULL)
5312 (void) BIO_free(in);
5313 if (crlfile != NULL)
5314 free(crlfile);
5316 return (ret);
5319 KMF_RETURN
5320 OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5322 KMF_RETURN ret = KMF_OK;
5323 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5324 KMF_ENCODE_FORMAT format;
5325 BIO *in = NULL;
5326 X509 *xcert = NULL;
5327 X509_CRL *xcrl = NULL;
5328 STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5329 X509_REVOKED *revoke;
5330 int i;
5331 char *crlfilename, *crlfile, *dirpath, *certfile;
5333 if (numattr == 0 || attrlist == NULL) {
5334 return (KMF_ERR_BAD_PARAMETER);
5337 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5338 attrlist, numattr);
5340 if (crlfilename == NULL)
5341 return (KMF_ERR_BAD_CRLFILE);
5343 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5344 if (certfile == NULL)
5345 return (KMF_ERR_BAD_CRLFILE);
5347 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5349 crlfile = get_fullpath(dirpath, crlfilename);
5351 if (crlfile == NULL)
5352 return (KMF_ERR_BAD_CRLFILE);
5354 if (isdir(crlfile)) {
5355 ret = KMF_ERR_BAD_CRLFILE;
5356 goto end;
5359 ret = kmf_is_crl_file(handle, crlfile, &format);
5360 if (ret != KMF_OK)
5361 goto end;
5363 /* Read the CRL file and load it into a X509_CRL structure */
5364 in = BIO_new_file(crlfilename, "rb");
5365 if (in == NULL) {
5366 SET_ERROR(kmfh, ERR_get_error());
5367 ret = KMF_ERR_OPEN_FILE;
5368 goto end;
5371 if (format == KMF_FORMAT_ASN1) {
5372 xcrl = d2i_X509_CRL_bio(in, NULL);
5373 } else if (format == KMF_FORMAT_PEM) {
5374 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5377 if (xcrl == NULL) {
5378 SET_ERROR(kmfh, ERR_get_error());
5379 ret = KMF_ERR_BAD_CRLFILE;
5380 goto end;
5382 (void) BIO_free(in);
5384 /* Read the Certificate file and load it into a X509 structure */
5385 ret = kmf_is_cert_file(handle, certfile, &format);
5386 if (ret != KMF_OK)
5387 goto end;
5389 in = BIO_new_file(certfile, "rb");
5390 if (in == NULL) {
5391 SET_ERROR(kmfh, ERR_get_error());
5392 ret = KMF_ERR_OPEN_FILE;
5393 goto end;
5396 if (format == KMF_FORMAT_ASN1) {
5397 xcert = d2i_X509_bio(in, NULL);
5398 } else if (format == KMF_FORMAT_PEM) {
5399 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5402 if (xcert == NULL) {
5403 SET_ERROR(kmfh, ERR_get_error());
5404 ret = KMF_ERR_BAD_CERTFILE;
5405 goto end;
5408 /* Check if the certificate and the CRL have same issuer */
5409 if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
5410 ret = KMF_ERR_ISSUER;
5411 goto end;
5414 /* Check to see if the certificate serial number is revoked */
5415 revoke_stack = X509_CRL_get_REVOKED(xcrl);
5416 if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5417 /* No revoked certificates in the CRL file */
5418 SET_ERROR(kmfh, ERR_get_error());
5419 ret = KMF_ERR_EMPTY_CRL;
5420 goto end;
5423 for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5424 /* LINTED E_BAD_PTR_CAST_ALIGN */
5425 revoke = sk_X509_REVOKED_value(revoke_stack, i);
5426 if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
5427 revoke->serialNumber) == 0) {
5428 break;
5432 if (i < sk_X509_REVOKED_num(revoke_stack)) {
5433 ret = KMF_OK;
5434 } else {
5435 ret = KMF_ERR_NOT_REVOKED;
5438 end:
5439 if (in != NULL)
5440 (void) BIO_free(in);
5441 if (xcrl != NULL)
5442 X509_CRL_free(xcrl);
5443 if (xcert != NULL)
5444 X509_free(xcert);
5446 return (ret);
5449 KMF_RETURN
5450 OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5452 KMF_RETURN ret = KMF_OK;
5453 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5454 BIO *bcrl = NULL;
5455 X509_CRL *xcrl = NULL;
5456 X509 *xcert = NULL;
5457 EVP_PKEY *pkey;
5458 int sslret;
5459 KMF_ENCODE_FORMAT crl_format;
5460 unsigned char *p;
5461 long len;
5463 if (handle == NULL || crlname == NULL || tacert == NULL) {
5464 return (KMF_ERR_BAD_PARAMETER);
5467 ret = kmf_get_file_format(crlname, &crl_format);
5468 if (ret != KMF_OK)
5469 return (ret);
5471 bcrl = BIO_new_file(crlname, "rb");
5472 if (bcrl == NULL) {
5473 SET_ERROR(kmfh, ERR_get_error());
5474 ret = KMF_ERR_OPEN_FILE;
5475 goto cleanup;
5478 if (crl_format == KMF_FORMAT_ASN1) {
5479 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5480 } else if (crl_format == KMF_FORMAT_PEM) {
5481 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5482 } else {
5483 ret = KMF_ERR_BAD_PARAMETER;
5484 goto cleanup;
5487 if (xcrl == NULL) {
5488 SET_ERROR(kmfh, ERR_get_error());
5489 ret = KMF_ERR_BAD_CRLFILE;
5490 goto cleanup;
5493 p = tacert->Data;
5494 len = tacert->Length;
5495 xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5497 if (xcert == NULL) {
5498 SET_ERROR(kmfh, ERR_get_error());
5499 ret = KMF_ERR_BAD_CERTFILE;
5500 goto cleanup;
5503 /* Get issuer certificate public key */
5504 pkey = X509_get_pubkey(xcert);
5505 if (pkey == NULL) {
5506 SET_ERROR(kmfh, ERR_get_error());
5507 ret = KMF_ERR_BAD_CERT_FORMAT;
5508 goto cleanup;
5511 /* Verify CRL signature */
5512 sslret = X509_CRL_verify(xcrl, pkey);
5513 EVP_PKEY_free(pkey);
5514 if (sslret > 0) {
5515 ret = KMF_OK;
5516 } else {
5517 SET_ERROR(kmfh, sslret);
5518 ret = KMF_ERR_BAD_CRLFILE;
5521 cleanup:
5522 if (bcrl != NULL)
5523 (void) BIO_free(bcrl);
5525 if (xcrl != NULL)
5526 X509_CRL_free(xcrl);
5528 if (xcert != NULL)
5529 X509_free(xcert);
5531 return (ret);
5535 KMF_RETURN
5536 OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5538 KMF_RETURN ret = KMF_OK;
5539 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5540 KMF_ENCODE_FORMAT crl_format;
5541 BIO *bcrl = NULL;
5542 X509_CRL *xcrl = NULL;
5543 int i;
5545 if (handle == NULL || crlname == NULL) {
5546 return (KMF_ERR_BAD_PARAMETER);
5549 ret = kmf_is_crl_file(handle, crlname, &crl_format);
5550 if (ret != KMF_OK)
5551 return (ret);
5553 bcrl = BIO_new_file(crlname, "rb");
5554 if (bcrl == NULL) {
5555 SET_ERROR(kmfh, ERR_get_error());
5556 ret = KMF_ERR_OPEN_FILE;
5557 goto cleanup;
5560 if (crl_format == KMF_FORMAT_ASN1)
5561 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5562 else if (crl_format == KMF_FORMAT_PEM)
5563 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5565 if (xcrl == NULL) {
5566 SET_ERROR(kmfh, ERR_get_error());
5567 ret = KMF_ERR_BAD_CRLFILE;
5568 goto cleanup;
5570 i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
5571 if (i >= 0) {
5572 ret = KMF_ERR_VALIDITY_PERIOD;
5573 goto cleanup;
5575 if (X509_CRL_get_nextUpdate(xcrl)) {
5576 i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
5578 if (i <= 0) {
5579 ret = KMF_ERR_VALIDITY_PERIOD;
5580 goto cleanup;
5584 ret = KMF_OK;
5586 cleanup:
5587 if (bcrl != NULL)
5588 (void) BIO_free(bcrl);
5590 if (xcrl != NULL)
5591 X509_CRL_free(xcrl);
5593 return (ret);