dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libkmf / plugins / kmf_openssl / common / openssl_spi.c
blobf41d996f7800f8f3a77b175cca71a34c37b99c47
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 free(buf);
453 cert->Data = NULL;
454 cert->Length = 0;
457 return (rv);
461 static KMF_RETURN
462 check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
463 boolean_t *match)
465 KMF_RETURN rv = KMF_OK;
466 boolean_t findIssuer = FALSE;
467 boolean_t findSubject = FALSE;
468 boolean_t findSerial = FALSE;
469 KMF_X509_NAME issuerDN, subjectDN;
470 KMF_X509_NAME certIssuerDN, certSubjectDN;
472 *match = FALSE;
473 if (xcert == NULL) {
474 return (KMF_ERR_BAD_PARAMETER);
477 (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
478 (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
479 (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
480 (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
482 if (issuer != NULL && strlen(issuer)) {
483 rv = kmf_dn_parser(issuer, &issuerDN);
484 if (rv != KMF_OK)
485 return (KMF_ERR_BAD_PARAMETER);
487 rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
488 if (rv != KMF_OK) {
489 kmf_free_dn(&issuerDN);
490 return (KMF_ERR_BAD_PARAMETER);
493 findIssuer = TRUE;
495 if (subject != NULL && strlen(subject)) {
496 rv = kmf_dn_parser(subject, &subjectDN);
497 if (rv != KMF_OK) {
498 rv = KMF_ERR_BAD_PARAMETER;
499 goto cleanup;
502 rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
503 if (rv != KMF_OK) {
504 rv = KMF_ERR_BAD_PARAMETER;
505 goto cleanup;
507 findSubject = TRUE;
509 if (serial != NULL && serial->val != NULL)
510 findSerial = TRUE;
512 if (findSerial) {
513 BIGNUM *bn;
515 /* Comparing BIGNUMs is a pain! */
516 bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
517 if (bn != NULL) {
518 int bnlen = BN_num_bytes(bn);
520 if (bnlen == serial->len) {
521 uchar_t *a = malloc(bnlen);
522 if (a == NULL) {
523 rv = KMF_ERR_MEMORY;
524 BN_free(bn);
525 goto cleanup;
527 bnlen = BN_bn2bin(bn, a);
528 *match = (memcmp(a, serial->val, serial->len) ==
530 rv = KMF_OK;
531 free(a);
533 BN_free(bn);
534 if (!(*match))
535 goto cleanup;
536 } else {
537 rv = KMF_OK;
538 goto cleanup;
541 if (findIssuer) {
542 *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
543 if ((*match) == B_FALSE) {
544 /* stop checking and bail */
545 rv = KMF_OK;
546 goto cleanup;
549 if (findSubject) {
550 *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
551 if ((*match) == B_FALSE) {
552 /* stop checking and bail */
553 rv = KMF_OK;
554 goto cleanup;
558 *match = TRUE;
559 cleanup:
560 if (findIssuer) {
561 kmf_free_dn(&issuerDN);
562 kmf_free_dn(&certIssuerDN);
564 if (findSubject) {
565 kmf_free_dn(&subjectDN);
566 kmf_free_dn(&certSubjectDN);
569 return (rv);
574 * This function loads a certificate file into an X509 data structure, and
575 * checks if its issuer, subject or the serial number matches with those
576 * values. If it matches, then return the X509 data structure.
578 static KMF_RETURN
579 load_X509cert(KMF_HANDLE *kmfh,
580 char *issuer, char *subject, KMF_BIGINT *serial,
581 char *pathname, X509 **outcert)
583 KMF_RETURN rv = KMF_OK;
584 X509 *xcert = NULL;
585 BIO *bcert = NULL;
586 boolean_t match = FALSE;
587 KMF_ENCODE_FORMAT format;
590 * auto-detect the file format, regardless of what
591 * the 'format' parameters in the params say.
593 rv = kmf_get_file_format(pathname, &format);
594 if (rv != KMF_OK) {
595 if (rv == KMF_ERR_OPEN_FILE)
596 rv = KMF_ERR_CERT_NOT_FOUND;
597 return (rv);
600 /* Not ASN1(DER) format */
601 if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
602 SET_ERROR(kmfh, ERR_get_error());
603 rv = KMF_ERR_OPEN_FILE;
604 goto cleanup;
607 if (format == KMF_FORMAT_PEM)
608 xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
609 else if (format == KMF_FORMAT_ASN1)
610 xcert = d2i_X509_bio(bcert, NULL);
611 else if (format == KMF_FORMAT_PKCS12) {
612 PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
613 if (p12 != NULL) {
614 (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
615 PKCS12_free(p12);
616 p12 = NULL;
617 } else {
618 SET_ERROR(kmfh, ERR_get_error());
619 rv = KMF_ERR_BAD_CERT_FORMAT;
621 } else {
622 rv = KMF_ERR_BAD_PARAMETER;
623 goto cleanup;
626 if (xcert == NULL) {
627 SET_ERROR(kmfh, ERR_get_error());
628 rv = KMF_ERR_BAD_CERT_FORMAT;
629 goto cleanup;
632 if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
633 match == FALSE) {
634 rv = KMF_ERR_CERT_NOT_FOUND;
635 goto cleanup;
638 if (outcert != NULL) {
639 *outcert = xcert;
642 cleanup:
643 if (bcert != NULL) (void) BIO_free(bcert);
644 if (rv != KMF_OK && xcert != NULL)
645 X509_free(xcert);
647 return (rv);
650 static int
651 datacmp(const void *a, const void *b)
653 KMF_DATA *adata = (KMF_DATA *)a;
654 KMF_DATA *bdata = (KMF_DATA *)b;
655 if (adata->Length > bdata->Length)
656 return (-1);
657 if (adata->Length < bdata->Length)
658 return (1);
659 return (0);
662 static KMF_RETURN
663 load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
664 KMF_CERT_VALIDITY validity, char *pathname,
665 KMF_DATA **certlist, uint32_t *numcerts)
667 KMF_RETURN rv = KMF_OK;
668 int i;
669 KMF_DATA *certs = NULL;
670 int nc = 0;
671 int hits = 0;
672 KMF_ENCODE_FORMAT format;
674 rv = kmf_get_file_format(pathname, &format);
675 if (rv != KMF_OK) {
676 if (rv == KMF_ERR_OPEN_FILE)
677 rv = KMF_ERR_CERT_NOT_FOUND;
678 return (rv);
680 if (format == KMF_FORMAT_ASN1) {
681 /* load a single certificate */
682 certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
683 if (certs == NULL)
684 return (KMF_ERR_MEMORY);
685 certs->Data = NULL;
686 certs->Length = 0;
687 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
688 pathname, certs);
689 if (rv == KMF_OK) {
690 *certlist = certs;
691 *numcerts = 1;
692 } else {
693 kmf_free_data(certs);
694 free(certs);
695 certs = NULL;
697 return (rv);
698 } else if (format == KMF_FORMAT_PKCS12) {
699 /* We need a credential to access a PKCS#12 file */
700 rv = KMF_ERR_BAD_CERT_FORMAT;
701 } else if (format == KMF_FORMAT_PEM ||
702 format != KMF_FORMAT_PEM_KEYPAIR) {
704 /* This function only works on PEM files */
705 rv = extract_pem(kmfh, issuer, subject, serial, pathname,
706 NULL, 0, NULL, &certs, &nc);
707 } else {
708 return (KMF_ERR_ENCODING);
711 if (rv != KMF_OK)
712 return (rv);
714 for (i = 0; i < nc; i++) {
715 if (validity == KMF_NONEXPIRED_CERTS) {
716 rv = kmf_check_cert_date(kmfh, &certs[i]);
717 } else if (validity == KMF_EXPIRED_CERTS) {
718 rv = kmf_check_cert_date(kmfh, &certs[i]);
719 if (rv == KMF_OK)
720 rv = KMF_ERR_CERT_NOT_FOUND;
721 if (rv == KMF_ERR_VALIDITY_PERIOD)
722 rv = KMF_OK;
724 if (rv != KMF_OK) {
725 /* Remove this cert from the list by clearing it. */
726 kmf_free_data(&certs[i]);
727 } else {
728 hits++; /* count valid certs found */
730 rv = KMF_OK;
732 if (rv == KMF_OK && hits > 0) {
734 * Sort the list of certs by length to put the cleared ones
735 * at the end so they don't get accessed by the caller.
737 qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
738 *certlist = certs;
740 /* since we sorted the list, just return the number of hits */
741 *numcerts = hits;
742 } else {
743 if (rv == KMF_OK && hits == 0)
744 rv = KMF_ERR_CERT_NOT_FOUND;
745 if (certs != NULL) {
746 free(certs);
747 certs = NULL;
750 return (rv);
753 static KMF_RETURN
754 kmf_load_cert(KMF_HANDLE *kmfh,
755 char *issuer, char *subject, KMF_BIGINT *serial,
756 KMF_CERT_VALIDITY validity,
757 char *pathname,
758 KMF_DATA *cert)
760 KMF_RETURN rv = KMF_OK;
761 X509 *x509cert = NULL;
763 rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
764 if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
765 rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
766 if (rv != KMF_OK) {
767 goto cleanup;
769 if (validity == KMF_NONEXPIRED_CERTS) {
770 rv = kmf_check_cert_date(kmfh, cert);
771 } else if (validity == KMF_EXPIRED_CERTS) {
772 rv = kmf_check_cert_date(kmfh, cert);
773 if (rv == KMF_OK) {
775 * This is a valid cert so skip it.
777 rv = KMF_ERR_CERT_NOT_FOUND;
779 if (rv == KMF_ERR_VALIDITY_PERIOD) {
781 * We want to return success when we
782 * find an invalid cert.
784 rv = KMF_OK;
785 goto cleanup;
789 cleanup:
790 if (x509cert != NULL)
791 X509_free(x509cert);
793 return (rv);
796 static KMF_RETURN
797 readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
799 KMF_RETURN ret = KMF_OK;
800 KMF_RAW_RSA_KEY rsa;
801 BerElement *asn1 = NULL;
802 BerValue filebuf;
803 BerValue OID = { 0, NULL };
804 BerValue *Mod = NULL, *PubExp = NULL;
805 BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
806 BerValue *Coef = NULL;
807 BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
808 BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
809 BIGNUM *qminus1 = NULL;
810 BN_CTX *ctx = NULL;
812 *pkey = NULL;
814 filebuf.bv_val = (char *)filedata->Data;
815 filebuf.bv_len = filedata->Length;
817 asn1 = kmfder_init(&filebuf);
818 if (asn1 == NULL) {
819 ret = KMF_ERR_MEMORY;
820 goto out;
823 if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
824 &OID, &Mod, &PubExp, &PriExp, &Prime1,
825 &Prime2, &Coef) == -1) {
826 ret = KMF_ERR_ENCODING;
827 goto out;
831 * We have to derive the 2 Exponents using Bignumber math.
832 * Exp1 = PriExp mod (Prime1 - 1)
833 * Exp2 = PriExp mod (Prime2 - 1)
836 /* D = PrivateExponent */
837 D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
838 if (D == NULL) {
839 ret = KMF_ERR_MEMORY;
840 goto out;
843 /* P = Prime1 (first prime factor of Modulus) */
844 P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
845 if (D == NULL) {
846 ret = KMF_ERR_MEMORY;
847 goto out;
850 /* Q = Prime2 (second prime factor of Modulus) */
851 Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
853 if ((ctx = BN_CTX_new()) == NULL) {
854 ret = KMF_ERR_MEMORY;
855 goto out;
858 /* Compute (P - 1) */
859 pminus1 = BN_new();
860 (void) BN_sub(pminus1, P, BN_value_one());
862 /* Exponent1 = D mod (P - 1) */
863 Exp1 = BN_new();
864 (void) BN_mod(Exp1, D, pminus1, ctx);
866 /* Compute (Q - 1) */
867 qminus1 = BN_new();
868 (void) BN_sub(qminus1, Q, BN_value_one());
870 /* Exponent2 = D mod (Q - 1) */
871 Exp2 = BN_new();
872 (void) BN_mod(Exp2, D, qminus1, ctx);
874 /* Coef = (Inverse Q) mod P */
875 COEF = BN_new();
876 (void) BN_mod_inverse(COEF, Q, P, ctx);
878 /* Convert back to KMF format */
879 (void) memset(&rsa, 0, sizeof (rsa));
881 if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
882 goto out;
883 if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
884 goto out;
885 if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
886 goto out;
888 rsa.mod.val = (uchar_t *)Mod->bv_val;
889 rsa.mod.len = Mod->bv_len;
891 rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
892 rsa.pubexp.len = PubExp->bv_len;
894 rsa.priexp.val = (uchar_t *)PriExp->bv_val;
895 rsa.priexp.len = PriExp->bv_len;
897 rsa.prime1.val = (uchar_t *)Prime1->bv_val;
898 rsa.prime1.len = Prime1->bv_len;
900 rsa.prime2.val = (uchar_t *)Prime2->bv_val;
901 rsa.prime2.len = Prime2->bv_len;
903 *pkey = ImportRawRSAKey(&rsa);
904 out:
905 if (asn1 != NULL)
906 kmfber_free(asn1, 1);
908 if (OID.bv_val) {
909 free(OID.bv_val);
911 free(PriExp);
913 free(Mod);
915 free(PubExp);
917 if (Coef) {
918 (void) memset(Coef->bv_val, 0, Coef->bv_len);
919 free(Coef->bv_val);
920 free(Coef);
922 free(Prime1);
923 free(Prime2);
925 if (ctx != NULL)
926 BN_CTX_free(ctx);
928 if (D)
929 BN_clear_free(D);
930 if (P)
931 BN_clear_free(P);
932 if (Q)
933 BN_clear_free(Q);
934 if (pminus1)
935 BN_clear_free(pminus1);
936 if (qminus1)
937 BN_clear_free(qminus1);
938 if (Exp1)
939 BN_clear_free(Exp1);
940 if (Exp2)
941 BN_clear_free(Exp2);
943 return (ret);
947 static EVP_PKEY *
948 openssl_load_key(KMF_HANDLE_T handle, const char *file)
950 BIO *keyfile = NULL;
951 EVP_PKEY *pkey = NULL;
952 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
953 KMF_ENCODE_FORMAT format;
954 KMF_RETURN rv;
955 KMF_DATA filedata;
957 if (file == NULL) {
958 return (NULL);
961 if (kmf_get_file_format((char *)file, &format) != KMF_OK)
962 return (NULL);
964 keyfile = BIO_new_file(file, "rb");
965 if (keyfile == NULL) {
966 goto end;
969 if (format == KMF_FORMAT_ASN1) {
970 pkey = d2i_PrivateKey_bio(keyfile, NULL);
971 if (pkey == NULL) {
973 (void) BIO_free(keyfile);
974 keyfile = NULL;
975 /* Try odd ASN.1 variations */
976 rv = kmf_read_input_file(kmfh, (char *)file,
977 &filedata);
978 if (rv == KMF_OK) {
979 (void) readAltFormatPrivateKey(&filedata,
980 &pkey);
981 kmf_free_data(&filedata);
984 } else if (format == KMF_FORMAT_PEM ||
985 format == KMF_FORMAT_PEM_KEYPAIR) {
986 pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
987 if (pkey == NULL) {
988 KMF_DATA derdata;
990 * Check if this is the alt. format
991 * RSA private key file.
993 rv = kmf_read_input_file(kmfh, (char *)file,
994 &filedata);
995 if (rv == KMF_OK) {
996 uchar_t *d = NULL;
997 int len;
998 rv = kmf_pem_to_der(filedata.Data,
999 filedata.Length, &d, &len);
1000 if (rv == KMF_OK && d != NULL) {
1001 derdata.Data = d;
1002 derdata.Length = (size_t)len;
1003 (void) readAltFormatPrivateKey(
1004 &derdata, &pkey);
1005 free(d);
1007 kmf_free_data(&filedata);
1012 end:
1013 if (pkey == NULL)
1014 SET_ERROR(kmfh, ERR_get_error());
1016 if (keyfile != NULL)
1017 (void) BIO_free(keyfile);
1019 return (pkey);
1022 KMF_RETURN
1023 OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1025 KMF_RETURN rv = KMF_OK;
1026 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1027 int i, n;
1028 uint32_t maxcerts = 0;
1029 uint32_t *num_certs;
1030 KMF_X509_DER_CERT *kmf_cert = NULL;
1031 char *dirpath = NULL;
1032 char *filename = NULL;
1033 char *fullpath = NULL;
1034 char *issuer = NULL;
1035 char *subject = NULL;
1036 KMF_BIGINT *serial = NULL;
1037 KMF_CERT_VALIDITY validity;
1039 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1040 if (num_certs == NULL)
1041 return (KMF_ERR_BAD_PARAMETER);
1043 /* num_certs should reference the size of kmf_cert */
1044 maxcerts = *num_certs;
1045 if (maxcerts == 0)
1046 maxcerts = 0xFFFFFFFF;
1047 *num_certs = 0;
1049 /* Get the optional returned certificate list */
1050 kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1051 numattr);
1054 * The dirpath attribute and the filename attribute can not be NULL
1055 * at the same time.
1057 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1058 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1059 numattr);
1061 fullpath = get_fullpath(dirpath, filename);
1062 if (fullpath == NULL)
1063 return (KMF_ERR_BAD_PARAMETER);
1065 /* Get optional search criteria attributes */
1066 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1067 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1068 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1069 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1070 &validity, NULL);
1071 if (rv != KMF_OK) {
1072 validity = KMF_ALL_CERTS;
1073 rv = KMF_OK;
1076 if (isdir(fullpath)) {
1077 DIR *dirp;
1078 struct dirent *dp;
1080 n = 0;
1081 /* open all files in the directory and attempt to read them */
1082 if ((dirp = opendir(fullpath)) == NULL) {
1083 return (KMF_ERR_BAD_PARAMETER);
1085 while ((dp = readdir(dirp)) != NULL) {
1086 char *fname;
1087 KMF_DATA *certlist = NULL;
1088 uint32_t loaded_certs = 0;
1090 if (strcmp(dp->d_name, ".") == 0 ||
1091 strcmp(dp->d_name, "..") == 0)
1092 continue;
1094 fname = get_fullpath(fullpath, (char *)&dp->d_name);
1096 rv = load_certs(kmfh, issuer, subject, serial,
1097 validity, fname, &certlist, &loaded_certs);
1099 if (rv != KMF_OK) {
1100 free(fname);
1101 if (certlist != NULL) {
1102 for (i = 0; i < loaded_certs; i++)
1103 kmf_free_data(&certlist[i]);
1104 free(certlist);
1106 continue;
1109 /* If load succeeds, add certdata to the list */
1110 if (kmf_cert != NULL) {
1111 for (i = 0; i < loaded_certs &&
1112 n < maxcerts; i++) {
1113 kmf_cert[n].certificate.Data =
1114 certlist[i].Data;
1115 kmf_cert[n].certificate.Length =
1116 certlist[i].Length;
1118 kmf_cert[n].kmf_private.keystore_type =
1119 KMF_KEYSTORE_OPENSSL;
1120 kmf_cert[n].kmf_private.flags =
1121 KMF_FLAG_CERT_VALID;
1122 kmf_cert[n].kmf_private.label =
1123 strdup(fname);
1124 n++;
1127 * If maxcerts < loaded_certs, clean up the
1128 * certs that were not used.
1130 for (; i < loaded_certs; i++)
1131 kmf_free_data(&certlist[i]);
1132 } else {
1133 for (i = 0; i < loaded_certs; i++)
1134 kmf_free_data(&certlist[i]);
1135 n += loaded_certs;
1137 free(certlist);
1138 free(fname);
1140 (*num_certs) = n;
1141 if (*num_certs == 0)
1142 rv = KMF_ERR_CERT_NOT_FOUND;
1143 if (*num_certs > 0)
1144 rv = KMF_OK;
1145 exit:
1146 (void) closedir(dirp);
1147 } else {
1148 KMF_DATA *certlist = NULL;
1149 uint32_t loaded_certs = 0;
1151 rv = load_certs(kmfh, issuer, subject, serial, validity,
1152 fullpath, &certlist, &loaded_certs);
1153 if (rv != KMF_OK) {
1154 free(fullpath);
1155 return (rv);
1158 n = 0;
1159 if (kmf_cert != NULL && certlist != NULL) {
1160 for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1161 kmf_cert[n].certificate.Data =
1162 certlist[i].Data;
1163 kmf_cert[n].certificate.Length =
1164 certlist[i].Length;
1165 kmf_cert[n].kmf_private.keystore_type =
1166 KMF_KEYSTORE_OPENSSL;
1167 kmf_cert[n].kmf_private.flags =
1168 KMF_FLAG_CERT_VALID;
1169 kmf_cert[n].kmf_private.label =
1170 strdup(fullpath);
1171 n++;
1173 /* If maxcerts < loaded_certs, clean up */
1174 for (; i < loaded_certs; i++)
1175 kmf_free_data(&certlist[i]);
1176 } else if (certlist != NULL) {
1177 for (i = 0; i < loaded_certs; i++)
1178 kmf_free_data(&certlist[i]);
1179 n = loaded_certs;
1181 free(certlist);
1182 *num_certs = n;
1185 free(fullpath);
1187 return (rv);
1190 void
1191 /*ARGSUSED*/
1192 OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
1193 KMF_X509_DER_CERT *kmf_cert)
1195 if (kmf_cert != NULL) {
1196 if (kmf_cert->certificate.Data != NULL) {
1197 kmf_free_data(&kmf_cert->certificate);
1199 free(kmf_cert->kmf_private.label);
1203 /*ARGSUSED*/
1204 KMF_RETURN
1205 OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1207 KMF_RETURN ret = KMF_OK;
1208 KMF_DATA *cert = NULL;
1209 char *outfilename = NULL;
1210 char *dirpath = NULL;
1211 char *fullpath = NULL;
1212 KMF_ENCODE_FORMAT format;
1214 /* Get the cert data */
1215 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1216 if (cert == NULL || cert->Data == NULL)
1217 return (KMF_ERR_BAD_PARAMETER);
1219 /* Check the output filename and directory attributes. */
1220 outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1221 numattr);
1222 if (outfilename == NULL)
1223 return (KMF_ERR_BAD_PARAMETER);
1225 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1226 fullpath = get_fullpath(dirpath, outfilename);
1227 if (fullpath == NULL)
1228 return (KMF_ERR_BAD_CERTFILE);
1230 /* Check the optional format attribute */
1231 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1232 &format, NULL);
1233 if (ret != KMF_OK) {
1234 /* If there is no format attribute, then default to PEM */
1235 format = KMF_FORMAT_PEM;
1236 ret = KMF_OK;
1237 } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1238 ret = KMF_ERR_BAD_CERT_FORMAT;
1239 goto out;
1242 /* Store the certificate in the file with the specified format */
1243 ret = kmf_create_cert_file(cert, format, fullpath);
1245 out:
1246 free(fullpath);
1248 return (ret);
1252 KMF_RETURN
1253 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1255 KMF_RETURN rv;
1256 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1257 KMF_DATA certdata = { 0, NULL };
1258 char *dirpath = NULL;
1259 char *filename = NULL;
1260 char *fullpath = NULL;
1261 char *issuer = NULL;
1262 char *subject = NULL;
1263 KMF_BIGINT *serial = NULL;
1264 KMF_CERT_VALIDITY validity;
1267 * Get the DIRPATH and CERT_FILENAME attributes. They can not be
1268 * NULL at the same time.
1270 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1271 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1272 numattr);
1273 fullpath = get_fullpath(dirpath, filename);
1274 if (fullpath == NULL)
1275 return (KMF_ERR_BAD_PARAMETER);
1277 /* Get optional search criteria attributes */
1278 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1279 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1280 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1281 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1282 &validity, NULL);
1283 if (rv != KMF_OK) {
1284 validity = KMF_ALL_CERTS;
1285 rv = KMF_OK;
1288 if (isdir(fullpath)) {
1289 DIR *dirp;
1290 struct dirent *dp;
1292 /* open all files in the directory and attempt to read them */
1293 if ((dirp = opendir(fullpath)) == NULL) {
1294 return (KMF_ERR_BAD_PARAMETER);
1297 while ((dp = readdir(dirp)) != NULL) {
1298 if (strcmp(dp->d_name, ".") != 0 &&
1299 strcmp(dp->d_name, "..") != 0) {
1300 char *fname;
1302 fname = get_fullpath(fullpath,
1303 (char *)&dp->d_name);
1305 if (fname == NULL) {
1306 rv = KMF_ERR_MEMORY;
1307 break;
1310 rv = kmf_load_cert(kmfh, issuer, subject,
1311 serial, validity, fname, &certdata);
1313 if (rv == KMF_ERR_CERT_NOT_FOUND) {
1314 free(fname);
1315 kmf_free_data(&certdata);
1316 rv = KMF_OK;
1317 continue;
1318 } else if (rv != KMF_OK) {
1319 free(fname);
1320 break;
1323 if (unlink(fname) != 0) {
1324 SET_SYS_ERROR(kmfh, errno);
1325 rv = KMF_ERR_INTERNAL;
1326 free(fname);
1327 break;
1329 free(fname);
1330 kmf_free_data(&certdata);
1333 (void) closedir(dirp);
1334 } else {
1335 /* Just try to load a single certificate */
1336 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1337 fullpath, &certdata);
1338 if (rv == KMF_OK) {
1339 if (unlink(fullpath) != 0) {
1340 SET_SYS_ERROR(kmfh, errno);
1341 rv = KMF_ERR_INTERNAL;
1346 out:
1347 free(fullpath);
1349 kmf_free_data(&certdata);
1351 return (rv);
1354 KMF_RETURN
1355 OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1356 KMF_DATA *keydata)
1358 KMF_RETURN rv = KMF_OK;
1359 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1360 int n;
1362 if (key == NULL || keydata == NULL ||
1363 key->keyp == NULL)
1364 return (KMF_ERR_BAD_PARAMETER);
1366 if (key->keyalg == KMF_RSA) {
1367 RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
1369 if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
1370 SET_ERROR(kmfh, ERR_get_error());
1371 return (KMF_ERR_ENCODING);
1373 RSA_free(pubkey);
1374 } else if (key->keyalg == KMF_DSA) {
1375 DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
1377 if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
1378 SET_ERROR(kmfh, ERR_get_error());
1379 return (KMF_ERR_ENCODING);
1381 DSA_free(pubkey);
1382 } else {
1383 return (KMF_ERR_BAD_PARAMETER);
1385 keydata->Length = n;
1387 cleanup:
1388 if (rv != KMF_OK) {
1389 free(keydata->Data);
1390 keydata->Data = NULL;
1391 keydata->Length = 0;
1394 return (rv);
1397 static KMF_RETURN
1398 ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1399 KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
1401 int rv = 0;
1402 RSA *rsa;
1403 DSA *dsa;
1405 if (pkey == NULL || out == NULL)
1406 return (KMF_ERR_BAD_PARAMETER);
1408 switch (format) {
1409 case KMF_FORMAT_RAWKEY:
1410 /* same as ASN.1 */
1411 case KMF_FORMAT_ASN1:
1412 if (pkey->type == EVP_PKEY_RSA) {
1413 rsa = EVP_PKEY_get1_RSA(pkey);
1414 if (private)
1415 rv = i2d_RSAPrivateKey_bio(out, rsa);
1416 else
1417 rv = i2d_RSAPublicKey_bio(out, rsa);
1418 RSA_free(rsa);
1419 } else if (pkey->type == EVP_PKEY_DSA) {
1420 dsa = EVP_PKEY_get1_DSA(pkey);
1421 rv = i2d_DSAPrivateKey_bio(out, dsa);
1422 DSA_free(dsa);
1424 if (rv == 1) {
1425 rv = KMF_OK;
1426 } else {
1427 SET_ERROR(kmfh, rv);
1429 break;
1430 case KMF_FORMAT_PEM:
1431 if (pkey->type == EVP_PKEY_RSA) {
1432 rsa = EVP_PKEY_get1_RSA(pkey);
1433 if (private)
1434 rv = PEM_write_bio_RSAPrivateKey(out,
1435 rsa, NULL, NULL, 0, NULL,
1436 (cred != NULL ? cred->cred : NULL));
1437 else
1438 rv = PEM_write_bio_RSAPublicKey(out,
1439 rsa);
1440 RSA_free(rsa);
1441 } else if (pkey->type == EVP_PKEY_DSA) {
1442 dsa = EVP_PKEY_get1_DSA(pkey);
1443 rv = PEM_write_bio_DSAPrivateKey(out,
1444 dsa, NULL, NULL, 0, NULL,
1445 (cred != NULL ? cred->cred : NULL));
1446 DSA_free(dsa);
1449 if (rv == 1) {
1450 rv = KMF_OK;
1451 } else {
1452 SET_ERROR(kmfh, rv);
1454 break;
1456 default:
1457 rv = KMF_ERR_BAD_PARAMETER;
1460 return (rv);
1463 KMF_RETURN
1464 OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1465 KMF_ATTRIBUTE *attrlist)
1467 KMF_RETURN rv = KMF_OK;
1468 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1469 uint32_t eValue = 0x010001;
1470 RSA *sslPrivKey = NULL;
1471 DSA *sslDSAKey = NULL;
1472 EVP_PKEY *eprikey = NULL;
1473 EVP_PKEY *epubkey = NULL;
1474 BIO *out = NULL;
1475 KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1476 uint32_t keylen = 1024;
1477 uint32_t keylen_size = sizeof (uint32_t);
1478 boolean_t storekey = TRUE;
1479 KMF_KEY_ALG keytype = KMF_RSA;
1481 rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1482 &storekey, NULL);
1483 if (rv != KMF_OK) {
1484 /* "storekey" is optional. Default is TRUE */
1485 rv = KMF_OK;
1488 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1489 (void *)&keytype, NULL);
1490 if (rv != KMF_OK)
1491 /* keytype is optional. KMF_RSA is default */
1492 rv = KMF_OK;
1494 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1495 if (pubkey == NULL)
1496 return (KMF_ERR_BAD_PARAMETER);
1498 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1499 if (privkey == NULL)
1500 return (KMF_ERR_BAD_PARAMETER);
1502 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1503 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1505 eprikey = EVP_PKEY_new();
1506 if (eprikey == NULL) {
1507 SET_ERROR(kmfh, ERR_get_error());
1508 rv = KMF_ERR_KEYGEN_FAILED;
1509 goto cleanup;
1511 epubkey = EVP_PKEY_new();
1512 if (epubkey == NULL) {
1513 SET_ERROR(kmfh, ERR_get_error());
1514 rv = KMF_ERR_KEYGEN_FAILED;
1515 goto cleanup;
1517 if (keytype == KMF_RSA) {
1518 KMF_BIGINT *rsaexp = NULL;
1520 rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1521 if (rsaexp != NULL) {
1522 if (rsaexp->len > 0 &&
1523 rsaexp->len <= sizeof (eValue) &&
1524 rsaexp->val != NULL) {
1525 /* LINTED E_BAD_PTR_CAST_ALIGN */
1526 eValue = *(uint32_t *)rsaexp->val;
1527 } else {
1528 rv = KMF_ERR_BAD_PARAMETER;
1529 goto cleanup;
1531 } else {
1532 /* RSA Exponent is optional. Default is 0x10001 */
1533 rv = KMF_OK;
1536 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1537 &keylen, &keylen_size);
1538 if (rv == KMF_ERR_ATTR_NOT_FOUND)
1539 /* keylen is optional, default is 1024 */
1540 rv = KMF_OK;
1541 if (rv != KMF_OK) {
1542 rv = KMF_ERR_BAD_PARAMETER;
1543 goto cleanup;
1546 sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
1547 if (sslPrivKey == NULL) {
1548 SET_ERROR(kmfh, ERR_get_error());
1549 rv = KMF_ERR_KEYGEN_FAILED;
1550 } else {
1551 (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
1552 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1553 privkey->keyalg = KMF_RSA;
1554 privkey->keyclass = KMF_ASYM_PRI;
1555 privkey->israw = FALSE;
1556 privkey->keyp = (void *)eprikey;
1558 /* OpenSSL derives the public key from the private */
1559 (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
1560 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1561 pubkey->keyalg = KMF_RSA;
1562 pubkey->israw = FALSE;
1563 pubkey->keyclass = KMF_ASYM_PUB;
1564 pubkey->keyp = (void *)epubkey;
1566 } else if (keytype == KMF_DSA) {
1567 DSA *dp;
1568 sslDSAKey = DSA_new();
1569 if (sslDSAKey == NULL) {
1570 SET_ERROR(kmfh, ERR_get_error());
1571 return (KMF_ERR_MEMORY);
1574 if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
1575 NULL) {
1576 SET_ERROR(kmfh, ERR_get_error());
1577 rv = KMF_ERR_KEYGEN_FAILED;
1578 goto cleanup;
1580 if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
1581 NULL) {
1582 SET_ERROR(kmfh, ERR_get_error());
1583 rv = KMF_ERR_KEYGEN_FAILED;
1584 goto cleanup;
1586 if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
1587 NULL) {
1588 SET_ERROR(kmfh, ERR_get_error());
1589 rv = KMF_ERR_KEYGEN_FAILED;
1590 goto cleanup;
1593 if (!DSA_generate_key(sslDSAKey)) {
1594 SET_ERROR(kmfh, ERR_get_error());
1595 rv = KMF_ERR_KEYGEN_FAILED;
1596 goto cleanup;
1599 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1600 privkey->keyalg = KMF_DSA;
1601 privkey->keyclass = KMF_ASYM_PRI;
1602 privkey->israw = FALSE;
1603 if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1604 privkey->keyp = (void *)eprikey;
1605 } else {
1606 SET_ERROR(kmfh, ERR_get_error());
1607 rv = KMF_ERR_KEYGEN_FAILED;
1608 goto cleanup;
1610 dp = DSA_new();
1611 /* Make a copy for the public key */
1612 if (dp != NULL) {
1613 if ((dp->p = BN_new()) == NULL) {
1614 SET_ERROR(kmfh, ERR_get_error());
1615 rv = KMF_ERR_MEMORY;
1616 DSA_free(dp);
1617 goto cleanup;
1619 if ((dp->q = BN_new()) == NULL) {
1620 SET_ERROR(kmfh, ERR_get_error());
1621 rv = KMF_ERR_MEMORY;
1622 BN_free(dp->p);
1623 DSA_free(dp);
1624 goto cleanup;
1626 if ((dp->g = BN_new()) == NULL) {
1627 SET_ERROR(kmfh, ERR_get_error());
1628 rv = KMF_ERR_MEMORY;
1629 BN_free(dp->q);
1630 BN_free(dp->p);
1631 DSA_free(dp);
1632 goto cleanup;
1634 if ((dp->pub_key = BN_new()) == NULL) {
1635 SET_ERROR(kmfh, ERR_get_error());
1636 rv = KMF_ERR_MEMORY;
1637 BN_free(dp->q);
1638 BN_free(dp->p);
1639 BN_free(dp->g);
1640 DSA_free(dp);
1641 goto cleanup;
1643 (void) BN_copy(dp->p, sslDSAKey->p);
1644 (void) BN_copy(dp->q, sslDSAKey->q);
1645 (void) BN_copy(dp->g, sslDSAKey->g);
1646 (void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
1648 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1649 pubkey->keyalg = KMF_DSA;
1650 pubkey->keyclass = KMF_ASYM_PUB;
1651 pubkey->israw = FALSE;
1653 if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1654 pubkey->keyp = (void *)epubkey;
1655 } else {
1656 SET_ERROR(kmfh, ERR_get_error());
1657 rv = KMF_ERR_KEYGEN_FAILED;
1658 goto cleanup;
1663 if (rv != KMF_OK) {
1664 goto cleanup;
1667 if (storekey) {
1668 KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1669 int i = 0;
1670 char *keyfile = NULL, *dirpath = NULL;
1671 KMF_ENCODE_FORMAT format;
1673 * Construct a new attribute arrray and call openssl_store_key
1675 kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1676 privkey, sizeof (privkey));
1677 i++;
1679 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1680 if (dirpath != NULL) {
1681 storeattrs[i].type = KMF_DIRPATH_ATTR;
1682 storeattrs[i].pValue = dirpath;
1683 storeattrs[i].valueLen = strlen(dirpath);
1684 i++;
1685 } else {
1686 rv = KMF_OK; /* DIRPATH is optional */
1688 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1689 attrlist, numattr);
1690 if (keyfile != NULL) {
1691 storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1692 storeattrs[i].pValue = keyfile;
1693 storeattrs[i].valueLen = strlen(keyfile);
1694 i++;
1695 } else {
1696 goto cleanup; /* KEYFILE is required */
1698 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1699 (void *)&format, NULL);
1700 if (rv == KMF_OK) {
1701 storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1702 storeattrs[i].pValue = &format;
1703 storeattrs[i].valueLen = sizeof (format);
1704 i++;
1707 rv = OpenSSL_StoreKey(handle, i, storeattrs);
1710 cleanup:
1711 if (rv != KMF_OK) {
1712 if (eprikey != NULL)
1713 EVP_PKEY_free(eprikey);
1715 if (epubkey != NULL)
1716 EVP_PKEY_free(epubkey);
1718 if (pubkey->keylabel) {
1719 free(pubkey->keylabel);
1720 pubkey->keylabel = NULL;
1723 if (privkey->keylabel) {
1724 free(privkey->keylabel);
1725 privkey->keylabel = NULL;
1728 pubkey->keyp = NULL;
1729 privkey->keyp = NULL;
1732 if (sslPrivKey)
1733 RSA_free(sslPrivKey);
1735 if (sslDSAKey)
1736 DSA_free(sslDSAKey);
1738 if (out != NULL)
1739 (void) BIO_free(out);
1741 return (rv);
1745 * Make sure the BN conversion is properly padded with 0x00
1746 * bytes. If not, signature verification for DSA signatures
1747 * may fail in the case where the bignum value does not use
1748 * all of the bits.
1750 static int
1751 fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1752 int bytes = len - BN_num_bytes(bn);
1754 /* prepend with leading 0x00 if necessary */
1755 while (bytes-- > 0)
1756 *buf++ = 0;
1758 (void) BN_bn2bin(bn, buf);
1760 * Return the desired length since we prepended it
1761 * with the necessary 0x00 padding.
1763 return (len);
1766 KMF_RETURN
1767 OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1768 KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1770 KMF_RETURN ret = KMF_OK;
1771 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1772 KMF_ALGORITHM_INDEX AlgId;
1773 EVP_MD_CTX ctx;
1774 const EVP_MD *md;
1776 if (key == NULL || AlgOID == NULL ||
1777 tobesigned == NULL || output == NULL ||
1778 tobesigned->Data == NULL ||
1779 output->Data == NULL)
1780 return (KMF_ERR_BAD_PARAMETER);
1782 /* Map the OID to an OpenSSL algorithm */
1783 AlgId = x509_algoid_to_algid(AlgOID);
1784 if (AlgId == KMF_ALGID_NONE)
1785 return (KMF_ERR_BAD_ALGORITHM);
1787 if (key->keyalg == KMF_RSA) {
1788 EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1789 uchar_t *p;
1790 int len;
1791 if (AlgId == KMF_ALGID_MD5WithRSA)
1792 md = EVP_md5();
1793 else if (AlgId == KMF_ALGID_SHA1WithRSA)
1794 md = EVP_sha1();
1795 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1796 md = EVP_sha256();
1797 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1798 md = EVP_sha384();
1799 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1800 md = EVP_sha512();
1801 else if (AlgId == KMF_ALGID_RSA)
1802 md = NULL;
1803 else
1804 return (KMF_ERR_BAD_ALGORITHM);
1806 if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1807 RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1809 p = output->Data;
1810 if ((len = RSA_private_encrypt(tobesigned->Length,
1811 tobesigned->Data, p, rsa,
1812 RSA_PKCS1_PADDING)) <= 0) {
1813 SET_ERROR(kmfh, ERR_get_error());
1814 ret = KMF_ERR_INTERNAL;
1816 output->Length = len;
1817 } else {
1818 (void) EVP_MD_CTX_init(&ctx);
1819 (void) EVP_SignInit_ex(&ctx, md, NULL);
1820 (void) EVP_SignUpdate(&ctx, tobesigned->Data,
1821 (uint32_t)tobesigned->Length);
1822 len = (uint32_t)output->Length;
1823 p = output->Data;
1824 if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
1825 SET_ERROR(kmfh, ERR_get_error());
1826 len = 0;
1827 ret = KMF_ERR_INTERNAL;
1829 output->Length = len;
1830 (void) EVP_MD_CTX_cleanup(&ctx);
1832 } else if (key->keyalg == KMF_DSA) {
1833 DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1835 uchar_t hash[EVP_MAX_MD_SIZE];
1836 uint32_t hashlen;
1837 DSA_SIG *dsasig;
1839 if (AlgId == KMF_ALGID_DSA ||
1840 AlgId == KMF_ALGID_SHA1WithDSA)
1841 md = EVP_sha1();
1842 else if (AlgId == KMF_ALGID_SHA256WithDSA)
1843 md = EVP_sha256();
1844 else /* Bad algorithm */
1845 return (KMF_ERR_BAD_ALGORITHM);
1848 * OpenSSL EVP_Sign operation automatically converts to
1849 * ASN.1 output so we do the operations separately so we
1850 * are assured of NOT getting ASN.1 output returned.
1851 * KMF does not want ASN.1 encoded results because
1852 * not all mechanisms return ASN.1 encodings (PKCS#11
1853 * and NSS return raw signature data).
1855 EVP_MD_CTX_init(&ctx);
1856 (void) EVP_DigestInit_ex(&ctx, md, NULL);
1857 (void) EVP_DigestUpdate(&ctx, tobesigned->Data,
1858 tobesigned->Length);
1859 (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
1861 /* Only sign first 20 bytes for SHA2 */
1862 if (AlgId == KMF_ALGID_SHA256WithDSA)
1863 hashlen = 20;
1864 dsasig = DSA_do_sign(hash, hashlen, dsa);
1865 if (dsasig != NULL) {
1866 int i;
1867 output->Length = i = fixbnlen(dsasig->r, output->Data,
1868 hashlen);
1870 output->Length += fixbnlen(dsasig->s, &output->Data[i],
1871 hashlen);
1873 DSA_SIG_free(dsasig);
1874 } else {
1875 SET_ERROR(kmfh, ERR_get_error());
1877 (void) EVP_MD_CTX_cleanup(&ctx);
1878 } else {
1879 return (KMF_ERR_BAD_PARAMETER);
1881 cleanup:
1882 return (ret);
1885 KMF_RETURN
1886 /*ARGSUSED*/
1887 OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1888 int numattr, KMF_ATTRIBUTE *attrlist)
1890 KMF_RETURN rv = KMF_OK;
1891 KMF_KEY_HANDLE *key;
1892 boolean_t destroy = B_TRUE;
1894 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1895 if (key == NULL || key->keyp == NULL)
1896 return (KMF_ERR_BAD_PARAMETER);
1898 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1899 (void *)&destroy, NULL);
1900 if (rv != KMF_OK) {
1901 /* "destroy" is optional. Default is TRUE */
1902 rv = KMF_OK;
1905 if (key->keyclass != KMF_ASYM_PUB &&
1906 key->keyclass != KMF_ASYM_PRI &&
1907 key->keyclass != KMF_SYMMETRIC)
1908 return (KMF_ERR_BAD_KEY_CLASS);
1910 if (key->keyclass == KMF_SYMMETRIC) {
1911 kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1912 key->keyp = NULL;
1913 } else {
1914 if (key->keyp != NULL) {
1915 EVP_PKEY_free(key->keyp);
1916 key->keyp = NULL;
1920 if (key->keylabel != NULL) {
1921 EVP_PKEY *pkey = NULL;
1922 /* If the file exists, make sure it is a proper key. */
1923 pkey = openssl_load_key(handle, key->keylabel);
1924 if (pkey == NULL) {
1925 if (key->keylabel != NULL) {
1926 free(key->keylabel);
1927 key->keylabel = NULL;
1929 return (KMF_ERR_KEY_NOT_FOUND);
1931 EVP_PKEY_free(pkey);
1933 if (destroy) {
1934 if (unlink(key->keylabel) != 0) {
1935 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1936 SET_SYS_ERROR(kmfh, errno);
1937 rv = KMF_ERR_INTERNAL;
1940 if (key->keylabel != NULL) {
1941 free(key->keylabel);
1942 key->keylabel = NULL;
1945 return (rv);
1948 KMF_RETURN
1949 OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1951 KMF_RETURN ret = KMF_OK;
1952 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1953 char str[256]; /* OpenSSL needs at least 120 byte buffer */
1955 ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1956 if (strlen(str)) {
1957 *msgstr = (char *)strdup(str);
1958 if ((*msgstr) == NULL)
1959 ret = KMF_ERR_MEMORY;
1960 } else {
1961 *msgstr = NULL;
1964 return (ret);
1967 static int
1968 ext2NID(int kmfext)
1970 switch (kmfext) {
1971 case KMF_X509_EXT_KEY_USAGE:
1972 return (NID_key_usage);
1973 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1974 return (NID_private_key_usage_period);
1975 case KMF_X509_EXT_CERT_POLICIES:
1976 return (NID_certificate_policies);
1977 case KMF_X509_EXT_SUBJ_ALTNAME:
1978 return (NID_subject_alt_name);
1979 case KMF_X509_EXT_ISSUER_ALTNAME:
1980 return (NID_issuer_alt_name);
1981 case KMF_X509_EXT_BASIC_CONSTRAINTS:
1982 return (NID_basic_constraints);
1983 case KMF_X509_EXT_EXT_KEY_USAGE:
1984 return (NID_ext_key_usage);
1985 case KMF_X509_EXT_AUTH_KEY_ID:
1986 return (NID_authority_key_identifier);
1987 case KMF_X509_EXT_CRL_DIST_POINTS:
1988 return (NID_crl_distribution_points);
1989 case KMF_X509_EXT_SUBJ_KEY_ID:
1990 return (NID_subject_key_identifier);
1991 case KMF_X509_EXT_POLICY_MAPPINGS:
1992 return (OBJ_sn2nid("policyMappings"));
1993 case KMF_X509_EXT_NAME_CONSTRAINTS:
1994 return (OBJ_sn2nid("nameConstraints"));
1995 case KMF_X509_EXT_POLICY_CONSTRAINTS:
1996 return (OBJ_sn2nid("policyConstraints"));
1997 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
1998 return (OBJ_sn2nid("inhibitAnyPolicy"));
1999 case KMF_X509_EXT_FRESHEST_CRL:
2000 return (OBJ_sn2nid("freshestCRL"));
2001 default:
2002 return (NID_undef);
2006 KMF_RETURN
2007 OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2008 KMF_PRINTABLE_ITEM flag, char *resultStr)
2010 KMF_RETURN ret = KMF_OK;
2011 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2012 X509 *xcert = NULL;
2013 unsigned char *outbuf = NULL;
2014 unsigned char *outbuf_p;
2015 char *tmpstr = NULL;
2016 int j;
2017 int ext_index, nid, len;
2018 BIO *mem = NULL;
2019 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2020 STACK *emlst = NULL;
2021 #else
2022 STACK_OF(OPENSSL_STRING) *emlst = NULL;
2023 #endif
2024 X509_EXTENSION *ex;
2025 X509_CINF *ci;
2027 if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2028 return (KMF_ERR_BAD_PARAMETER);
2031 /* copy cert data to outbuf */
2032 outbuf = malloc(pcert->Length);
2033 if (outbuf == NULL) {
2034 return (KMF_ERR_MEMORY);
2036 (void) memcpy(outbuf, pcert->Data, pcert->Length);
2038 outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2039 xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2040 if (xcert == NULL) {
2041 SET_ERROR(kmfh, ERR_get_error());
2042 ret = KMF_ERR_ENCODING;
2043 goto out;
2046 mem = BIO_new(BIO_s_mem());
2047 if (mem == NULL) {
2048 SET_ERROR(kmfh, ERR_get_error());
2049 ret = KMF_ERR_MEMORY;
2050 goto out;
2053 switch (flag) {
2054 case KMF_CERT_ISSUER:
2055 (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2056 XN_FLAG_SEP_CPLUS_SPC);
2057 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2058 break;
2060 case KMF_CERT_SUBJECT:
2061 (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2062 XN_FLAG_SEP_CPLUS_SPC);
2063 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2064 break;
2066 case KMF_CERT_VERSION:
2067 tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
2068 (void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
2069 OPENSSL_free(tmpstr);
2070 len = strlen(resultStr);
2071 break;
2073 case KMF_CERT_SERIALNUM:
2074 if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2075 (void) strcpy(resultStr, "0x");
2076 len = BIO_gets(mem, &resultStr[2],
2077 KMF_CERT_PRINTABLE_LEN - 2);
2079 break;
2081 case KMF_CERT_NOTBEFORE:
2082 (void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
2083 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2084 break;
2086 case KMF_CERT_NOTAFTER:
2087 (void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
2088 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2089 break;
2091 case KMF_CERT_PUBKEY_DATA:
2093 EVP_PKEY *pkey = X509_get_pubkey(xcert);
2094 if (pkey == NULL) {
2095 SET_ERROR(kmfh, ERR_get_error());
2096 ret = KMF_ERR_ENCODING;
2097 goto out;
2100 if (pkey->type == EVP_PKEY_RSA) {
2101 (void) BIO_printf(mem,
2102 "RSA Public Key: (%d bit)\n",
2103 BN_num_bits(pkey->pkey.rsa->n));
2104 (void) RSA_print(mem, pkey->pkey.rsa, 0);
2105 } else if (pkey->type == EVP_PKEY_DSA) {
2106 (void) BIO_printf(mem,
2107 "%12sDSA Public Key:\n", "");
2108 (void) DSA_print(mem, pkey->pkey.dsa, 0);
2109 } else {
2110 (void) BIO_printf(mem,
2111 "%12sUnknown Public Key:\n", "");
2113 (void) BIO_printf(mem, "\n");
2114 EVP_PKEY_free(pkey);
2116 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2117 break;
2118 case KMF_CERT_SIGNATURE_ALG:
2119 case KMF_CERT_PUBKEY_ALG:
2120 if (flag == KMF_CERT_SIGNATURE_ALG) {
2121 len = i2a_ASN1_OBJECT(mem,
2122 xcert->sig_alg->algorithm);
2123 } else {
2124 len = i2a_ASN1_OBJECT(mem,
2125 xcert->cert_info->key->algor->algorithm);
2128 if (len > 0) {
2129 len = BIO_read(mem, resultStr,
2130 KMF_CERT_PRINTABLE_LEN);
2132 break;
2134 case KMF_CERT_EMAIL:
2135 emlst = X509_get1_email(xcert);
2136 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2137 for (j = 0; j < sk_num(emlst); j++)
2138 (void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2139 #else
2140 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2141 (void) BIO_printf(mem, "%s\n",
2142 sk_OPENSSL_STRING_value(emlst, j));
2143 #endif
2145 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2146 X509_email_free(emlst);
2147 break;
2148 case KMF_X509_EXT_ISSUER_ALTNAME:
2149 case KMF_X509_EXT_SUBJ_ALTNAME:
2150 case KMF_X509_EXT_KEY_USAGE:
2151 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2152 case KMF_X509_EXT_CERT_POLICIES:
2153 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2154 case KMF_X509_EXT_NAME_CONSTRAINTS:
2155 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2156 case KMF_X509_EXT_EXT_KEY_USAGE:
2157 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2158 case KMF_X509_EXT_AUTH_KEY_ID:
2159 case KMF_X509_EXT_SUBJ_KEY_ID:
2160 case KMF_X509_EXT_POLICY_MAPPINGS:
2161 case KMF_X509_EXT_CRL_DIST_POINTS:
2162 case KMF_X509_EXT_FRESHEST_CRL:
2163 nid = ext2NID(flag);
2164 if (nid == NID_undef) {
2165 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2166 goto out;
2168 ci = xcert->cert_info;
2170 ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
2171 if (ext_index == -1) {
2172 SET_ERROR(kmfh, ERR_get_error());
2174 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2175 goto out;
2177 ex = X509v3_get_ext(ci->extensions, ext_index);
2179 (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2181 if (BIO_printf(mem, ": %s\n",
2182 X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2183 SET_ERROR(kmfh, ERR_get_error());
2184 ret = KMF_ERR_ENCODING;
2185 goto out;
2187 if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2188 (void) BIO_printf(mem, "%*s", 4, "");
2189 (void) M_ASN1_OCTET_STRING_print(mem, ex->value);
2191 if (BIO_write(mem, "\n", 1) <= 0) {
2192 SET_ERROR(kmfh, ERR_get_error());
2193 ret = KMF_ERR_ENCODING;
2194 goto out;
2196 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2198 if (len <= 0) {
2199 SET_ERROR(kmfh, ERR_get_error());
2200 ret = KMF_ERR_ENCODING;
2203 out:
2204 if (outbuf != NULL) {
2205 free(outbuf);
2208 if (xcert != NULL) {
2209 X509_free(xcert);
2212 if (mem != NULL) {
2213 (void) BIO_free(mem);
2216 return (ret);
2219 KMF_RETURN
2220 /*ARGSUSED*/
2221 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2222 KMF_ATTRIBUTE *attrlist)
2224 KMF_RETURN rv = KMF_OK;
2225 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2226 KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2227 KMF_KEY_HANDLE *key = NULL;
2228 uint32_t numkeys = 1; /* 1 key only */
2229 char *dirpath = NULL;
2230 char *keyfile = NULL;
2231 KMF_ATTRIBUTE new_attrlist[16];
2232 int i = 0;
2235 * This is really just a FindKey operation, reuse the
2236 * FindKey function.
2238 kmf_set_attr_at_index(new_attrlist, i,
2239 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2240 i++;
2242 kmf_set_attr_at_index(new_attrlist, i,
2243 KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2244 i++;
2246 kmf_set_attr_at_index(new_attrlist, i,
2247 KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2248 i++;
2250 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2251 if (key == NULL) {
2252 return (KMF_ERR_BAD_PARAMETER);
2253 } else {
2254 kmf_set_attr_at_index(new_attrlist, i,
2255 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2256 i++;
2259 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2260 if (dirpath != NULL) {
2261 kmf_set_attr_at_index(new_attrlist, i,
2262 KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2263 i++;
2266 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2267 if (keyfile == NULL)
2268 return (KMF_ERR_BAD_PARAMETER);
2269 else {
2270 kmf_set_attr_at_index(new_attrlist, i,
2271 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2272 i++;
2275 rv = OpenSSL_FindKey(handle, i, new_attrlist);
2276 return (rv);
2279 KMF_RETURN
2280 /*ARGSUSED*/
2281 OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2282 KMF_OID *AlgOID, KMF_DATA *ciphertext,
2283 KMF_DATA *output)
2285 KMF_RETURN ret = KMF_OK;
2286 RSA *rsa = NULL;
2287 unsigned int in_len = 0, out_len = 0;
2288 unsigned int total_decrypted = 0, modulus_len = 0;
2289 uint8_t *in_data, *out_data;
2290 int i, blocks;
2292 if (key == NULL || AlgOID == NULL ||
2293 ciphertext == NULL || output == NULL ||
2294 ciphertext->Data == NULL ||
2295 output->Data == NULL)
2296 return (KMF_ERR_BAD_PARAMETER);
2298 if (key->keyalg == KMF_RSA) {
2299 rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2300 modulus_len = RSA_size(rsa);
2301 } else {
2302 return (KMF_ERR_BAD_PARAMETER);
2305 blocks = ciphertext->Length/modulus_len;
2306 out_data = output->Data;
2307 in_data = ciphertext->Data;
2308 out_len = modulus_len - 11;
2309 in_len = modulus_len;
2311 for (i = 0; i < blocks; i++) {
2312 out_len = RSA_private_decrypt(in_len,
2313 in_data, out_data, rsa, RSA_PKCS1_PADDING);
2315 if (out_len == 0) {
2316 ret = KMF_ERR_INTERNAL;
2317 goto cleanup;
2320 out_data += out_len;
2321 total_decrypted += out_len;
2322 in_data += in_len;
2325 output->Length = total_decrypted;
2327 cleanup:
2328 RSA_free(rsa);
2329 if (ret != KMF_OK)
2330 output->Length = 0;
2332 return (ret);
2337 * This function will create a certid from issuer_cert and user_cert.
2338 * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2339 * certid memory after use.
2341 static KMF_RETURN
2342 create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2343 const KMF_DATA *user_cert, OCSP_CERTID **certid)
2345 KMF_RETURN ret = KMF_OK;
2346 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2347 X509 *issuer = NULL;
2348 X509 *cert = NULL;
2349 unsigned char *ptmp;
2351 if (issuer_cert == NULL || user_cert == NULL) {
2352 return (KMF_ERR_BAD_PARAMETER);
2355 /* convert the DER-encoded issuer cert to an internal X509 */
2356 ptmp = issuer_cert->Data;
2357 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2358 issuer_cert->Length);
2359 if (issuer == NULL) {
2360 SET_ERROR(kmfh, ERR_get_error());
2361 ret = KMF_ERR_OCSP_BAD_ISSUER;
2362 goto end;
2365 /* convert the DER-encoded user cert to an internal X509 */
2366 ptmp = user_cert->Data;
2367 cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2368 user_cert->Length);
2369 if (cert == NULL) {
2370 SET_ERROR(kmfh, ERR_get_error());
2372 ret = KMF_ERR_OCSP_BAD_CERT;
2373 goto end;
2376 /* create a CERTID */
2377 *certid = OCSP_cert_to_id(NULL, cert, issuer);
2378 if (*certid == NULL) {
2379 SET_ERROR(kmfh, ERR_get_error());
2380 ret = KMF_ERR_OCSP_CERTID;
2381 goto end;
2384 end:
2385 if (issuer != NULL) {
2386 X509_free(issuer);
2389 if (cert != NULL) {
2390 X509_free(cert);
2393 return (ret);
2396 KMF_RETURN
2397 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2398 int numattr, KMF_ATTRIBUTE *attrlist)
2400 KMF_RETURN ret = KMF_OK;
2401 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2402 OCSP_CERTID *id = NULL;
2403 OCSP_REQUEST *req = NULL;
2404 BIO *derbio = NULL;
2405 char *reqfile;
2406 KMF_DATA *issuer_cert;
2407 KMF_DATA *user_cert;
2409 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2410 attrlist, numattr);
2411 if (user_cert == NULL)
2412 return (KMF_ERR_BAD_PARAMETER);
2414 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2415 attrlist, numattr);
2416 if (issuer_cert == NULL)
2417 return (KMF_ERR_BAD_PARAMETER);
2419 reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2420 attrlist, numattr);
2421 if (reqfile == NULL)
2422 return (KMF_ERR_BAD_PARAMETER);
2424 ret = create_certid(handle, issuer_cert, user_cert, &id);
2425 if (ret != KMF_OK) {
2426 return (ret);
2429 /* Create an OCSP request */
2430 req = OCSP_REQUEST_new();
2431 if (req == NULL) {
2432 SET_ERROR(kmfh, ERR_get_error());
2433 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2434 goto end;
2437 if (!OCSP_request_add0_id(req, id)) {
2438 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2439 goto end;
2442 /* Write the request to the output file with DER encoding */
2443 derbio = BIO_new_file(reqfile, "wb");
2444 if (!derbio) {
2445 SET_ERROR(kmfh, ERR_get_error());
2446 ret = KMF_ERR_OPEN_FILE;
2447 goto end;
2449 if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2450 ret = KMF_ERR_ENCODING;
2453 end:
2455 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2456 * will also deallocate certid's space.
2458 if (req != NULL) {
2459 OCSP_REQUEST_free(req);
2462 if (derbio != NULL) {
2463 (void) BIO_free(derbio);
2466 return (ret);
2469 /* ocsp_find_signer_sk() is copied from openssl source */
2470 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
2472 int i;
2473 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2475 /* Easy if lookup by name */
2476 if (id->type == V_OCSP_RESPID_NAME)
2477 return (X509_find_by_subject(certs, id->value.byName));
2479 /* Lookup by key hash */
2481 /* If key hash isn't SHA1 length then forget it */
2482 if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2483 return (NULL);
2485 keyhash = id->value.byKey->data;
2486 /* Calculate hash of each key and compare */
2487 for (i = 0; i < sk_X509_num(certs); i++) {
2488 /* LINTED E_BAD_PTR_CAST_ALIGN */
2489 X509 *x = sk_X509_value(certs, i);
2490 /* Use pubkey_digest to get the key ID value */
2491 (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2492 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2493 return (x);
2495 return (NULL);
2498 /* ocsp_find_signer() is copied from openssl source */
2499 /* ARGSUSED2 */
2500 static int
2501 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2502 X509_STORE *st, unsigned long flags)
2504 X509 *signer;
2505 OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2506 if ((signer = ocsp_find_signer_sk(certs, rid))) {
2507 *psigner = signer;
2508 return (2);
2510 if (!(flags & OCSP_NOINTERN) &&
2511 (signer = ocsp_find_signer_sk(bs->certs, rid))) {
2512 *psigner = signer;
2513 return (1);
2515 /* Maybe lookup from store if by subject name */
2517 *psigner = NULL;
2518 return (0);
2522 * This function will verify the signature of a basic response, using
2523 * the public key from the OCSP responder certificate.
2525 static KMF_RETURN
2526 check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2527 KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2529 KMF_RETURN ret = KMF_OK;
2530 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2531 STACK_OF(X509) *cert_stack = NULL;
2532 X509 *signer = NULL;
2533 X509 *issuer = NULL;
2534 EVP_PKEY *skey = NULL;
2535 unsigned char *ptmp;
2538 if (bs == NULL || issuer_cert == NULL)
2539 return (KMF_ERR_BAD_PARAMETER);
2542 * Find the certificate that signed the basic response.
2544 * If signer_cert is not NULL, we will use that as the signer cert.
2545 * Otherwise, we will check if the issuer cert is actually the signer.
2546 * If we still do not find a signer, we will look for it from the
2547 * certificate list came with the response file.
2549 if (signer_cert != NULL) {
2550 ptmp = signer_cert->Data;
2551 signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2552 signer_cert->Length);
2553 if (signer == NULL) {
2554 SET_ERROR(kmfh, ERR_get_error());
2555 ret = KMF_ERR_OCSP_BAD_SIGNER;
2556 goto end;
2558 } else {
2560 * Convert the issuer cert into X509 and push it into a
2561 * stack to be used by ocsp_find_signer().
2563 ptmp = issuer_cert->Data;
2564 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2565 issuer_cert->Length);
2566 if (issuer == NULL) {
2567 SET_ERROR(kmfh, ERR_get_error());
2568 ret = KMF_ERR_OCSP_BAD_ISSUER;
2569 goto end;
2572 if ((cert_stack = sk_X509_new_null()) == NULL) {
2573 ret = KMF_ERR_INTERNAL;
2574 goto end;
2577 if (sk_X509_push(cert_stack, issuer) == 0) {
2578 ret = KMF_ERR_INTERNAL;
2579 goto end;
2582 ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2583 if (!ret) {
2584 /* can not find the signer */
2585 ret = KMF_ERR_OCSP_BAD_SIGNER;
2586 goto end;
2590 /* Verify the signature of the response */
2591 skey = X509_get_pubkey(signer);
2592 if (skey == NULL) {
2593 ret = KMF_ERR_OCSP_BAD_SIGNER;
2594 goto end;
2597 ret = OCSP_BASICRESP_verify(bs, skey, 0);
2598 if (ret == 0) {
2599 ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2600 goto end;
2603 end:
2604 if (issuer != NULL) {
2605 X509_free(issuer);
2608 if (signer != NULL) {
2609 X509_free(signer);
2612 if (skey != NULL) {
2613 EVP_PKEY_free(skey);
2616 if (cert_stack != NULL) {
2617 sk_X509_free(cert_stack);
2620 return (ret);
2625 KMF_RETURN
2626 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2627 int numattr, KMF_ATTRIBUTE *attrlist)
2629 KMF_RETURN ret = KMF_OK;
2630 BIO *derbio = NULL;
2631 OCSP_RESPONSE *resp = NULL;
2632 OCSP_BASICRESP *bs = NULL;
2633 OCSP_CERTID *id = NULL;
2634 OCSP_SINGLERESP *single = NULL;
2635 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2636 int index, status, reason;
2637 KMF_DATA *issuer_cert;
2638 KMF_DATA *user_cert;
2639 KMF_DATA *signer_cert;
2640 KMF_DATA *response;
2641 int *response_reason, *response_status, *cert_status;
2642 boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
2643 uint32_t response_lifetime;
2645 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2646 attrlist, numattr);
2647 if (issuer_cert == NULL)
2648 return (KMF_ERR_BAD_PARAMETER);
2650 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2651 attrlist, numattr);
2652 if (user_cert == NULL)
2653 return (KMF_ERR_BAD_PARAMETER);
2655 response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2656 attrlist, numattr);
2657 if (response == NULL)
2658 return (KMF_ERR_BAD_PARAMETER);
2660 response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2661 attrlist, numattr);
2662 if (response_status == NULL)
2663 return (KMF_ERR_BAD_PARAMETER);
2665 response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2666 attrlist, numattr);
2667 if (response_reason == NULL)
2668 return (KMF_ERR_BAD_PARAMETER);
2670 cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2671 attrlist, numattr);
2672 if (cert_status == NULL)
2673 return (KMF_ERR_BAD_PARAMETER);
2675 /* Read in the response */
2676 derbio = BIO_new_mem_buf(response->Data, response->Length);
2677 if (!derbio) {
2678 ret = KMF_ERR_MEMORY;
2679 return (ret);
2682 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2683 if (resp == NULL) {
2684 ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2685 goto end;
2688 /* Check the response status */
2689 status = OCSP_response_status(resp);
2690 *response_status = status;
2691 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2692 ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2693 goto end;
2696 #ifdef DEBUG
2697 printf("Successfully checked the response file status.\n");
2698 #endif /* DEBUG */
2700 /* Extract basic response */
2701 bs = OCSP_response_get1_basic(resp);
2702 if (bs == NULL) {
2703 ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2704 goto end;
2707 #ifdef DEBUG
2708 printf("Successfully retrieved the basic response.\n");
2709 #endif /* DEBUG */
2711 /* Check the basic response signature if required */
2712 ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2713 (void *)&ignore_response_sign, NULL);
2714 if (ret != KMF_OK)
2715 ret = KMF_OK;
2717 signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2718 attrlist, numattr);
2720 if (ignore_response_sign == B_FALSE) {
2721 ret = check_response_signature(handle, bs,
2722 signer_cert, issuer_cert);
2723 if (ret != KMF_OK)
2724 goto end;
2727 #ifdef DEBUG
2728 printf("Successfully verified the response signature.\n");
2729 #endif /* DEBUG */
2731 /* Create a certid for the certificate in question */
2732 ret = create_certid(handle, issuer_cert, user_cert, &id);
2733 if (ret != KMF_OK) {
2734 ret = KMF_ERR_OCSP_CERTID;
2735 goto end;
2738 #ifdef DEBUG
2739 printf("successfully created a certid for the cert.\n");
2740 #endif /* DEBUG */
2742 /* Find the index of the single response for the certid */
2743 index = OCSP_resp_find(bs, id, -1);
2744 if (index < 0) {
2745 /* cound not find this certificate in the response */
2746 ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2747 goto end;
2750 #ifdef DEBUG
2751 printf("Successfully found the single response index for the cert.\n");
2752 #endif /* DEBUG */
2754 /* Retrieve the single response and get the cert status */
2755 single = OCSP_resp_get0(bs, index);
2756 status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2757 &nextupd);
2758 if (status == V_OCSP_CERTSTATUS_GOOD) {
2759 *cert_status = OCSP_GOOD;
2760 } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2761 *cert_status = OCSP_UNKNOWN;
2762 } else { /* revoked */
2763 *cert_status = OCSP_REVOKED;
2764 *response_reason = reason;
2766 ret = KMF_OK;
2768 /* resp. time is optional, so we don't care about the return code. */
2769 (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2770 (void *)&response_lifetime, NULL);
2772 if (!OCSP_check_validity(thisupd, nextupd, 300,
2773 response_lifetime)) {
2774 ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2775 goto end;
2778 #ifdef DEBUG
2779 printf("Successfully verify the time.\n");
2780 #endif /* DEBUG */
2782 end:
2783 if (derbio != NULL)
2784 (void) BIO_free(derbio);
2786 if (resp != NULL)
2787 OCSP_RESPONSE_free(resp);
2789 if (bs != NULL)
2790 OCSP_BASICRESP_free(bs);
2792 if (id != NULL)
2793 OCSP_CERTID_free(id);
2795 return (ret);
2798 static KMF_RETURN
2799 fetch_key(KMF_HANDLE_T handle, char *path,
2800 KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2802 KMF_RETURN rv = KMF_OK;
2803 EVP_PKEY *pkey = NULL;
2804 KMF_RAW_SYM_KEY *rkey = NULL;
2806 if (keyclass == KMF_ASYM_PRI ||
2807 keyclass == KMF_ASYM_PUB) {
2808 pkey = openssl_load_key(handle, path);
2809 if (pkey == NULL) {
2810 return (KMF_ERR_KEY_NOT_FOUND);
2812 if (key != NULL) {
2813 if (pkey->type == EVP_PKEY_RSA)
2814 key->keyalg = KMF_RSA;
2815 else if (pkey->type == EVP_PKEY_DSA)
2816 key->keyalg = KMF_DSA;
2818 key->kstype = KMF_KEYSTORE_OPENSSL;
2819 key->keyclass = keyclass;
2820 key->keyp = (void *)pkey;
2821 key->israw = FALSE;
2822 if (path != NULL &&
2823 ((key->keylabel = strdup(path)) == NULL)) {
2824 EVP_PKEY_free(pkey);
2825 return (KMF_ERR_MEMORY);
2827 } else {
2828 EVP_PKEY_free(pkey);
2829 pkey = NULL;
2831 } else if (keyclass == KMF_SYMMETRIC) {
2832 KMF_ENCODE_FORMAT fmt;
2834 * If the file is a recognized format,
2835 * then it is NOT a symmetric key.
2837 rv = kmf_get_file_format(path, &fmt);
2838 if (rv == KMF_OK || fmt != 0) {
2839 return (KMF_ERR_KEY_NOT_FOUND);
2840 } else if (rv == KMF_ERR_ENCODING) {
2842 * If we don't know the encoding,
2843 * it is probably a symmetric key.
2845 rv = KMF_OK;
2846 } else if (rv == KMF_ERR_OPEN_FILE) {
2847 return (KMF_ERR_KEY_NOT_FOUND);
2850 if (key != NULL) {
2851 KMF_DATA keyvalue;
2852 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2853 if (rkey == NULL) {
2854 rv = KMF_ERR_MEMORY;
2855 goto out;
2858 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2859 rv = kmf_read_input_file(handle, path, &keyvalue);
2860 if (rv != KMF_OK)
2861 goto out;
2863 rkey->keydata.len = keyvalue.Length;
2864 rkey->keydata.val = keyvalue.Data;
2866 key->kstype = KMF_KEYSTORE_OPENSSL;
2867 key->keyclass = keyclass;
2868 key->israw = TRUE;
2869 key->keyp = (void *)rkey;
2870 if (path != NULL &&
2871 ((key->keylabel = strdup(path)) == NULL)) {
2872 rv = KMF_ERR_MEMORY;
2876 out:
2877 if (rv != KMF_OK) {
2878 if (rkey != NULL) {
2879 kmf_free_raw_sym_key(rkey);
2881 if (pkey != NULL)
2882 EVP_PKEY_free(pkey);
2884 if (key != NULL) {
2885 key->keyalg = KMF_KEYALG_NONE;
2886 key->keyclass = KMF_KEYCLASS_NONE;
2887 key->keyp = NULL;
2891 return (rv);
2894 KMF_RETURN
2895 OpenSSL_FindKey(KMF_HANDLE_T handle,
2896 int numattr, KMF_ATTRIBUTE *attrlist)
2898 KMF_RETURN rv = KMF_OK;
2899 char *fullpath = NULL;
2900 uint32_t maxkeys;
2901 KMF_KEY_HANDLE *key;
2902 uint32_t *numkeys;
2903 KMF_KEY_CLASS keyclass;
2904 KMF_RAW_KEY_DATA *rawkey;
2905 char *dirpath;
2906 char *keyfile;
2908 if (handle == NULL)
2909 return (KMF_ERR_BAD_PARAMETER);
2911 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2912 if (numkeys == NULL)
2913 return (KMF_ERR_BAD_PARAMETER);
2915 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2916 (void *)&keyclass, NULL);
2917 if (rv != KMF_OK)
2918 return (KMF_ERR_BAD_PARAMETER);
2920 if (keyclass != KMF_ASYM_PUB &&
2921 keyclass != KMF_ASYM_PRI &&
2922 keyclass != KMF_SYMMETRIC)
2923 return (KMF_ERR_BAD_KEY_CLASS);
2925 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2926 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2928 fullpath = get_fullpath(dirpath, keyfile);
2930 if (fullpath == NULL)
2931 return (KMF_ERR_BAD_PARAMETER);
2933 maxkeys = *numkeys;
2934 if (maxkeys == 0)
2935 maxkeys = 0xFFFFFFFF;
2936 *numkeys = 0;
2938 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2939 /* it is okay to have "keys" contains NULL */
2942 * The caller may want a list of the raw key data as well.
2943 * Useful for importing keys from a file into other keystores.
2945 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
2947 if (isdir(fullpath)) {
2948 DIR *dirp;
2949 struct dirent *dp;
2950 int n = 0;
2952 /* open all files in the directory and attempt to read them */
2953 if ((dirp = opendir(fullpath)) == NULL) {
2954 return (KMF_ERR_BAD_PARAMETER);
2956 rewinddir(dirp);
2957 while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
2958 if (strcmp(dp->d_name, ".") &&
2959 strcmp(dp->d_name, "..")) {
2960 char *fname;
2962 fname = get_fullpath(fullpath,
2963 (char *)&dp->d_name);
2965 rv = fetch_key(handle, fname,
2966 keyclass, key ? &key[n] : NULL);
2968 if (rv == KMF_OK) {
2969 if (key != NULL && rawkey != NULL)
2970 rv = convertToRawKey(
2971 key[n].keyp, &rawkey[n]);
2972 n++;
2975 if (rv != KMF_OK || key == NULL)
2976 free(fname);
2979 (void) closedir(dirp);
2980 free(fullpath);
2981 (*numkeys) = n;
2982 } else {
2983 rv = fetch_key(handle, fullpath, keyclass, key);
2984 if (rv == KMF_OK)
2985 (*numkeys) = 1;
2987 if (rv != KMF_OK || key == NULL)
2988 free(fullpath);
2990 if (rv == KMF_OK && key != NULL && rawkey != NULL) {
2991 rv = convertToRawKey(key->keyp, rawkey);
2995 if (rv == KMF_OK && (*numkeys) == 0)
2996 rv = KMF_ERR_KEY_NOT_FOUND;
2997 else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
2998 rv = KMF_OK;
3000 return (rv);
3003 #define HANDLE_PK12_ERROR { \
3004 SET_ERROR(kmfh, ERR_get_error()); \
3005 rv = KMF_ERR_ENCODING; \
3006 goto out; \
3009 static int
3010 add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3012 if (xcert != NULL && xcert->aux != NULL &&
3013 xcert->aux->alias != NULL) {
3014 if (PKCS12_add_friendlyname_asc(bag,
3015 (const char *)xcert->aux->alias->data,
3016 xcert->aux->alias->length) == 0)
3017 return (0);
3019 return (1);
3022 static PKCS7 *
3023 add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3024 uchar_t *keyid, unsigned int keyidlen)
3026 PKCS12_SAFEBAG *bag = NULL;
3027 PKCS7 *cert_authsafe = NULL;
3028 STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3030 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3031 if (bag_stack == NULL)
3032 return (NULL);
3034 /* Convert cert from X509 struct to PKCS#12 bag */
3035 bag = PKCS12_x5092certbag(sslcert);
3036 if (bag == NULL) {
3037 goto out;
3040 /* Add the key id to the certificate bag. */
3041 if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3042 goto out;
3045 if (!add_alias_to_bag(bag, sslcert))
3046 goto out;
3048 /* Pile it on the bag_stack. */
3049 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3050 goto out;
3052 /* Turn bag_stack of certs into encrypted authsafe. */
3053 cert_authsafe = PKCS12_pack_p7encdata(
3054 NID_pbe_WithSHA1And40BitRC2_CBC,
3055 cred->cred, cred->credlen, NULL, 0,
3056 PKCS12_DEFAULT_ITER, bag_stack);
3058 out:
3059 if (bag_stack != NULL)
3060 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3062 return (cert_authsafe);
3065 static PKCS7 *
3066 add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3067 uchar_t *keyid, unsigned int keyidlen,
3068 char *label, int label_len)
3070 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3071 STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3072 PKCS12_SAFEBAG *bag = NULL;
3073 PKCS7 *key_authsafe = NULL;
3075 p8 = EVP_PKEY2PKCS8(pkey);
3076 if (p8 == NULL) {
3077 return (NULL);
3079 /* Put the shrouded key into a PKCS#12 bag. */
3080 bag = PKCS12_MAKE_SHKEYBAG(
3081 NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3082 cred->cred, cred->credlen,
3083 NULL, 0, PKCS12_DEFAULT_ITER, p8);
3085 /* Clean up the PKCS#8 shrouded key, don't need it now. */
3086 PKCS8_PRIV_KEY_INFO_free(p8);
3087 p8 = NULL;
3089 if (bag == NULL) {
3090 return (NULL);
3092 if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3093 goto out;
3094 if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3095 goto out;
3097 /* Start a PKCS#12 safebag container for the private key. */
3098 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3099 if (bag_stack == NULL)
3100 goto out;
3102 /* Pile on the private key on the bag_stack. */
3103 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3104 goto out;
3106 key_authsafe = PKCS12_pack_p7data(bag_stack);
3108 out:
3109 if (bag_stack != NULL)
3110 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3111 bag_stack = NULL;
3112 return (key_authsafe);
3115 static EVP_PKEY *
3116 ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3118 RSA *rsa = NULL;
3119 EVP_PKEY *newkey = NULL;
3121 if ((rsa = RSA_new()) == NULL)
3122 return (NULL);
3124 if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
3125 return (NULL);
3127 if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
3128 NULL)
3129 return (NULL);
3131 if (key->priexp.val != NULL)
3132 if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
3133 rsa->d)) == NULL)
3134 return (NULL);
3136 if (key->prime1.val != NULL)
3137 if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
3138 rsa->p)) == NULL)
3139 return (NULL);
3141 if (key->prime2.val != NULL)
3142 if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
3143 rsa->q)) == NULL)
3144 return (NULL);
3146 if (key->exp1.val != NULL)
3147 if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
3148 rsa->dmp1)) == NULL)
3149 return (NULL);
3151 if (key->exp2.val != NULL)
3152 if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
3153 rsa->dmq1)) == NULL)
3154 return (NULL);
3156 if (key->coef.val != NULL)
3157 if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
3158 rsa->iqmp)) == NULL)
3159 return (NULL);
3161 if ((newkey = EVP_PKEY_new()) == NULL)
3162 return (NULL);
3164 (void) EVP_PKEY_set1_RSA(newkey, rsa);
3166 /* The original key must be freed once here or it leaks memory */
3167 RSA_free(rsa);
3169 return (newkey);
3172 static EVP_PKEY *
3173 ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3175 DSA *dsa = NULL;
3176 EVP_PKEY *newkey = NULL;
3178 if ((dsa = DSA_new()) == NULL)
3179 return (NULL);
3181 if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
3182 dsa->p)) == NULL)
3183 return (NULL);
3185 if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
3186 dsa->q)) == NULL)
3187 return (NULL);
3189 if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
3190 dsa->g)) == NULL)
3191 return (NULL);
3193 if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
3194 dsa->priv_key)) == NULL)
3195 return (NULL);
3197 if (key->pubvalue.val != NULL) {
3198 if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
3199 key->pubvalue.len, dsa->pub_key)) == NULL)
3200 return (NULL);
3203 if ((newkey = EVP_PKEY_new()) == NULL)
3204 return (NULL);
3206 (void) EVP_PKEY_set1_DSA(newkey, dsa);
3208 /* The original key must be freed once here or it leaks memory */
3209 DSA_free(dsa);
3210 return (newkey);
3213 static EVP_PKEY *
3214 raw_key_to_pkey(KMF_KEY_HANDLE *key)
3216 EVP_PKEY *pkey = NULL;
3217 KMF_RAW_KEY_DATA *rawkey;
3218 ASN1_TYPE *attr = NULL;
3219 KMF_RETURN ret;
3221 if (key == NULL || !key->israw)
3222 return (NULL);
3224 rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3225 if (rawkey->keytype == KMF_RSA) {
3226 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3227 } else if (rawkey->keytype == KMF_DSA) {
3228 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3229 } else if (rawkey->keytype == KMF_ECDSA) {
3231 * OpenSSL in Solaris does not support EC for
3232 * legal reasons
3234 return (NULL);
3235 } else {
3236 /* wrong kind of key */
3237 return (NULL);
3240 if (rawkey->label != NULL) {
3241 if ((attr = ASN1_TYPE_new()) == NULL) {
3242 EVP_PKEY_free(pkey);
3243 return (NULL);
3245 attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3246 (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3247 strlen(rawkey->label));
3248 attr->type = V_ASN1_BMPSTRING;
3249 attr->value.ptr = (char *)attr->value.bmpstring;
3250 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3251 if (ret != KMF_OK) {
3252 EVP_PKEY_free(pkey);
3253 ASN1_TYPE_free(attr);
3254 return (NULL);
3257 if (rawkey->id.Data != NULL) {
3258 if ((attr = ASN1_TYPE_new()) == NULL) {
3259 EVP_PKEY_free(pkey);
3260 return (NULL);
3262 attr->value.octet_string =
3263 ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3264 attr->type = V_ASN1_OCTET_STRING;
3265 (void) ASN1_STRING_set(attr->value.octet_string,
3266 rawkey->id.Data, rawkey->id.Length);
3267 attr->value.ptr = (char *)attr->value.octet_string;
3268 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3269 if (ret != KMF_OK) {
3270 EVP_PKEY_free(pkey);
3271 ASN1_TYPE_free(attr);
3272 return (NULL);
3275 return (pkey);
3279 * Search a list of private keys to find one that goes with the certificate.
3281 static EVP_PKEY *
3282 find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3284 int i;
3285 EVP_PKEY *pkey = NULL;
3287 if (numkeys == 0 || keylist == NULL || xcert == NULL)
3288 return (NULL);
3289 for (i = 0; i < numkeys; i++) {
3290 if (keylist[i].israw)
3291 pkey = raw_key_to_pkey(&keylist[i]);
3292 else
3293 pkey = (EVP_PKEY *)keylist[i].keyp;
3294 if (pkey != NULL) {
3295 if (X509_check_private_key(xcert, pkey)) {
3296 return (pkey);
3297 } else {
3298 EVP_PKEY_free(pkey);
3299 pkey = NULL;
3303 return (pkey);
3306 static KMF_RETURN
3307 local_export_pk12(KMF_HANDLE_T handle,
3308 KMF_CREDENTIAL *cred,
3309 int numcerts, KMF_X509_DER_CERT *certlist,
3310 int numkeys, KMF_KEY_HANDLE *keylist,
3311 char *filename)
3313 KMF_RETURN rv = KMF_OK;
3314 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3315 BIO *bio = NULL;
3316 PKCS7 *cert_authsafe = NULL;
3317 PKCS7 *key_authsafe = NULL;
3318 STACK_OF(PKCS7) *authsafe_stack = NULL;
3319 PKCS12 *p12_elem = NULL;
3320 int i;
3322 if (numcerts == 0 && numkeys == 0)
3323 return (KMF_ERR_BAD_PARAMETER);
3326 * Open the output file.
3328 if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3329 SET_ERROR(kmfh, ERR_get_error());
3330 rv = KMF_ERR_OPEN_FILE;
3331 goto cleanup;
3334 /* Start a PKCS#7 stack. */
3335 authsafe_stack = sk_PKCS7_new_null();
3336 if (authsafe_stack == NULL) {
3337 rv = KMF_ERR_MEMORY;
3338 goto cleanup;
3340 if (numcerts > 0) {
3341 for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3342 const uchar_t *p = certlist[i].certificate.Data;
3343 long len = certlist[i].certificate.Length;
3344 X509 *xcert = NULL;
3345 EVP_PKEY *pkey = NULL;
3346 unsigned char keyid[EVP_MAX_MD_SIZE];
3347 unsigned int keyidlen = 0;
3349 xcert = d2i_X509(NULL, &p, len);
3350 if (xcert == NULL) {
3351 SET_ERROR(kmfh, ERR_get_error());
3352 rv = KMF_ERR_ENCODING;
3354 if (certlist[i].kmf_private.label != NULL) {
3355 /* Set alias attribute */
3356 (void) X509_alias_set1(xcert,
3357 (uchar_t *)certlist[i].kmf_private.label,
3358 strlen(certlist[i].kmf_private.label));
3360 /* Check if there is a key corresponding to this cert */
3361 pkey = find_matching_key(xcert, numkeys, keylist);
3364 * If key is found, get fingerprint and create a
3365 * safebag.
3367 if (pkey != NULL) {
3368 (void) X509_digest(xcert, EVP_sha1(),
3369 keyid, &keyidlen);
3370 key_authsafe = add_key_to_safe(pkey, cred,
3371 keyid, keyidlen,
3372 certlist[i].kmf_private.label,
3373 (certlist[i].kmf_private.label ?
3374 strlen(certlist[i].kmf_private.label) : 0));
3376 if (key_authsafe == NULL) {
3377 X509_free(xcert);
3378 EVP_PKEY_free(pkey);
3379 goto cleanup;
3381 /* Put the key safe into the Auth Safe */
3382 if (!sk_PKCS7_push(authsafe_stack,
3383 key_authsafe)) {
3384 X509_free(xcert);
3385 EVP_PKEY_free(pkey);
3386 goto cleanup;
3390 /* create a certificate safebag */
3391 cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3392 keyidlen);
3393 if (cert_authsafe == NULL) {
3394 X509_free(xcert);
3395 EVP_PKEY_free(pkey);
3396 goto cleanup;
3398 if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3399 X509_free(xcert);
3400 EVP_PKEY_free(pkey);
3401 goto cleanup;
3404 X509_free(xcert);
3405 if (pkey)
3406 EVP_PKEY_free(pkey);
3408 } else if (numcerts == 0 && numkeys > 0) {
3410 * If only adding keys to the file.
3412 for (i = 0; i < numkeys; i++) {
3413 EVP_PKEY *pkey = NULL;
3415 if (keylist[i].israw)
3416 pkey = raw_key_to_pkey(&keylist[i]);
3417 else
3418 pkey = (EVP_PKEY *)keylist[i].keyp;
3420 if (pkey == NULL)
3421 continue;
3423 key_authsafe = add_key_to_safe(pkey, cred,
3424 NULL, 0, NULL, 0);
3426 if (key_authsafe == NULL) {
3427 EVP_PKEY_free(pkey);
3428 goto cleanup;
3430 if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3431 EVP_PKEY_free(pkey);
3432 goto cleanup;
3436 p12_elem = PKCS12_init(NID_pkcs7_data);
3437 if (p12_elem == NULL) {
3438 goto cleanup;
3441 /* Put the PKCS#7 stack into the PKCS#12 element. */
3442 if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3443 goto cleanup;
3446 /* Set the integrity MAC on the PKCS#12 element. */
3447 if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3448 NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3449 goto cleanup;
3452 /* Write the PKCS#12 element to the export file. */
3453 if (!i2d_PKCS12_bio(bio, p12_elem)) {
3454 goto cleanup;
3456 PKCS12_free(p12_elem);
3458 cleanup:
3459 /* Clear away the PKCS#7 stack, we're done with it. */
3460 if (authsafe_stack)
3461 sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3463 if (bio != NULL)
3464 (void) BIO_free_all(bio);
3466 return (rv);
3469 KMF_RETURN
3470 openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3471 KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3472 KMF_CREDENTIAL *p12cred, char *filename)
3474 KMF_RETURN rv;
3476 if (certlist == NULL && keylist == NULL)
3477 return (KMF_ERR_BAD_PARAMETER);
3479 rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3480 numkeys, keylist, filename);
3482 return (rv);
3485 KMF_RETURN
3486 OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3488 KMF_RETURN rv;
3489 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3490 char *fullpath = NULL;
3491 char *dirpath = NULL;
3492 char *certfile = NULL;
3493 char *keyfile = NULL;
3494 char *filename = NULL;
3495 KMF_CREDENTIAL *p12cred = NULL;
3496 KMF_X509_DER_CERT certdata;
3497 KMF_KEY_HANDLE key;
3498 int gotkey = 0;
3499 int gotcert = 0;
3501 if (handle == NULL)
3502 return (KMF_ERR_BAD_PARAMETER);
3505 * First, find the certificate.
3507 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3508 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3509 if (certfile != NULL) {
3510 fullpath = get_fullpath(dirpath, certfile);
3511 if (fullpath == NULL)
3512 return (KMF_ERR_BAD_PARAMETER);
3514 if (isdir(fullpath)) {
3515 free(fullpath);
3516 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3519 (void) memset(&certdata, 0, sizeof (certdata));
3520 rv = kmf_load_cert(kmfh, NULL, NULL, NULL, KMF_ALL_CERTS,
3521 fullpath, &certdata.certificate);
3522 if (rv != KMF_OK)
3523 goto end;
3525 gotcert++;
3526 certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3527 free(fullpath);
3531 * Now find the private key.
3533 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3534 if (keyfile != NULL) {
3535 fullpath = get_fullpath(dirpath, keyfile);
3536 if (fullpath == NULL)
3537 return (KMF_ERR_BAD_PARAMETER);
3539 if (isdir(fullpath)) {
3540 free(fullpath);
3541 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3544 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3545 rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3546 if (rv != KMF_OK)
3547 goto end;
3548 gotkey++;
3552 * Open the output file.
3554 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3555 numattr);
3556 if (filename == NULL) {
3557 rv = KMF_ERR_BAD_PARAMETER;
3558 goto end;
3561 /* Stick the key and the cert into a PKCS#12 file */
3562 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3563 if (p12cred == NULL) {
3564 rv = KMF_ERR_BAD_PARAMETER;
3565 goto end;
3568 rv = local_export_pk12(handle, p12cred, 1, &certdata,
3569 1, &key, filename);
3571 end:
3572 free(fullpath);
3574 if (gotcert)
3575 kmf_free_kmf_cert(handle, &certdata);
3576 if (gotkey)
3577 kmf_free_kmf_key(handle, &key);
3578 return (rv);
3582 * Helper function to extract keys and certificates from
3583 * a single PEM file. Typically the file should contain a
3584 * private key and an associated public key wrapped in an x509 cert.
3585 * However, the file may be just a list of X509 certs with no keys.
3587 static KMF_RETURN
3588 extract_pem(KMF_HANDLE *kmfh,
3589 char *issuer, char *subject, KMF_BIGINT *serial,
3590 char *filename, CK_UTF8CHAR *pin,
3591 CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3592 int *numcerts)
3593 /* ARGSUSED6 */
3595 KMF_RETURN rv = KMF_OK;
3596 FILE *fp;
3597 STACK_OF(X509_INFO) *x509_info_stack = NULL;
3598 int i, ncerts = 0, matchcerts = 0;
3599 EVP_PKEY *pkey = NULL;
3600 X509_INFO *info;
3601 X509 *x;
3602 X509_INFO **cert_infos = NULL;
3603 KMF_DATA *certlist = NULL;
3605 if (priv_key)
3606 *priv_key = NULL;
3607 if (certs)
3608 *certs = NULL;
3609 fp = fopen(filename, "r");
3610 if (fp == NULL)
3611 return (KMF_ERR_OPEN_FILE);
3613 x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3614 if (x509_info_stack == NULL) {
3615 (void) fclose(fp);
3616 return (KMF_ERR_ENCODING);
3618 cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3619 sizeof (X509_INFO *));
3620 if (cert_infos == NULL) {
3621 (void) fclose(fp);
3622 rv = KMF_ERR_MEMORY;
3623 goto err;
3626 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3627 /* LINTED E_BAD_PTR_CAST_ALIGN */
3628 cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
3629 ncerts++;
3632 if (ncerts == 0) {
3633 (void) fclose(fp);
3634 rv = KMF_ERR_CERT_NOT_FOUND;
3635 goto err;
3638 if (priv_key != NULL) {
3639 rewind(fp);
3640 pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
3642 (void) fclose(fp);
3644 x = cert_infos[ncerts - 1]->x509;
3646 * Make sure the private key matchs the last cert in the file.
3648 if (pkey != NULL && !X509_check_private_key(x, pkey)) {
3649 EVP_PKEY_free(pkey);
3650 rv = KMF_ERR_KEY_MISMATCH;
3651 goto err;
3654 certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
3655 if (certlist == NULL) {
3656 if (pkey != NULL)
3657 EVP_PKEY_free(pkey);
3658 rv = KMF_ERR_MEMORY;
3659 goto err;
3663 * Convert all of the certs to DER format.
3665 matchcerts = 0;
3666 for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
3667 boolean_t match = FALSE;
3668 info = cert_infos[ncerts - 1 - i];
3670 rv = check_cert(info->x509, issuer, subject, serial, &match);
3671 if (rv != KMF_OK || match != TRUE) {
3672 rv = KMF_OK;
3673 continue;
3676 rv = ssl_cert2KMFDATA(kmfh, info->x509,
3677 &certlist[matchcerts++]);
3679 if (rv != KMF_OK) {
3680 int j;
3681 for (j = 0; j < matchcerts; j++)
3682 kmf_free_data(&certlist[j]);
3683 free(certlist);
3684 certlist = NULL;
3685 ncerts = matchcerts = 0;
3689 if (numcerts != NULL)
3690 *numcerts = matchcerts;
3692 if (certs != NULL)
3693 *certs = certlist;
3694 else if (certlist != NULL) {
3695 for (i = 0; i < ncerts; i++)
3696 kmf_free_data(&certlist[i]);
3697 free(certlist);
3698 certlist = NULL;
3701 if (priv_key == NULL && pkey != NULL)
3702 EVP_PKEY_free(pkey);
3703 else if (priv_key != NULL && pkey != NULL)
3704 *priv_key = pkey;
3706 err:
3707 /* Cleanup the stack of X509 info records */
3708 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3709 /* LINTED E_BAD_PTR_CAST_ALIGN */
3710 info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3711 X509_INFO_free(info);
3713 if (x509_info_stack)
3714 sk_X509_INFO_free(x509_info_stack);
3716 if (cert_infos != NULL)
3717 free(cert_infos);
3719 return (rv);
3722 static KMF_RETURN
3723 openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3724 STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3726 KMF_RETURN ret;
3727 int i;
3729 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3730 /* LINTED E_BAD_PTR_CAST_ALIGN */
3731 PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3732 ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3733 keys, certs);
3735 if (ret != KMF_OK)
3736 return (ret);
3739 return (ret);
3742 static KMF_RETURN
3743 set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3745 X509_ATTRIBUTE *attr = NULL;
3747 if (pkey == NULL || attrib == NULL)
3748 return (KMF_ERR_BAD_PARAMETER);
3750 if (pkey->attributes == NULL) {
3751 pkey->attributes = sk_X509_ATTRIBUTE_new_null();
3752 if (pkey->attributes == NULL)
3753 return (KMF_ERR_MEMORY);
3755 attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3756 if (attr != NULL) {
3757 int i;
3758 X509_ATTRIBUTE *a;
3759 for (i = 0;
3760 i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3761 /* LINTED E_BAD_PTR_CASE_ALIGN */
3762 a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
3763 if (OBJ_obj2nid(a->object) == nid) {
3764 X509_ATTRIBUTE_free(a);
3765 /* LINTED E_BAD_PTR_CAST_ALIGN */
3766 (void) sk_X509_ATTRIBUTE_set(pkey->attributes,
3767 i, attr);
3768 return (KMF_OK);
3771 if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == 0) {
3772 X509_ATTRIBUTE_free(attr);
3773 return (KMF_ERR_MEMORY);
3775 } else {
3776 return (KMF_ERR_MEMORY);
3779 return (KMF_OK);
3782 static KMF_RETURN
3783 openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3784 STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3786 KMF_RETURN ret = KMF_OK;
3787 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3788 EVP_PKEY *pkey = NULL;
3789 X509 *xcert = NULL;
3790 ASN1_TYPE *keyid = NULL;
3791 ASN1_TYPE *fname = NULL;
3792 uchar_t *data = NULL;
3794 keyid = PKCS12_get_attr(bag, NID_localKeyID);
3795 fname = PKCS12_get_attr(bag, NID_friendlyName);
3797 switch (M_PKCS12_bag_type(bag)) {
3798 case NID_keyBag:
3799 if (keylist == NULL)
3800 goto end;
3801 pkey = EVP_PKCS82PKEY(bag->value.keybag);
3802 if (pkey == NULL)
3803 ret = KMF_ERR_PKCS12_FORMAT;
3805 break;
3806 case NID_pkcs8ShroudedKeyBag:
3807 if (keylist == NULL)
3808 goto end;
3809 p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
3810 if (p8 == NULL)
3811 return (KMF_ERR_AUTH_FAILED);
3812 pkey = EVP_PKCS82PKEY(p8);
3813 PKCS8_PRIV_KEY_INFO_free(p8);
3814 if (pkey == NULL)
3815 ret = KMF_ERR_PKCS12_FORMAT;
3816 break;
3817 case NID_certBag:
3818 if (certlist == NULL)
3819 goto end;
3820 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
3821 return (KMF_ERR_PKCS12_FORMAT);
3822 xcert = M_PKCS12_certbag2x509(bag);
3823 if (xcert == NULL) {
3824 ret = KMF_ERR_PKCS12_FORMAT;
3825 goto end;
3827 if (keyid != NULL) {
3828 if (X509_keyid_set1(xcert,
3829 keyid->value.octet_string->data,
3830 keyid->value.octet_string->length) == 0) {
3831 ret = KMF_ERR_PKCS12_FORMAT;
3832 goto end;
3835 if (fname != NULL) {
3836 int len, r;
3837 len = ASN1_STRING_to_UTF8(&data,
3838 fname->value.asn1_string);
3839 if (len > 0 && data != NULL) {
3840 r = X509_alias_set1(xcert, data, len);
3841 if (r == 0) {
3842 ret = KMF_ERR_PKCS12_FORMAT;
3843 goto end;
3845 } else {
3846 ret = KMF_ERR_PKCS12_FORMAT;
3847 goto end;
3850 if (sk_X509_push(certlist, xcert) == 0)
3851 ret = KMF_ERR_MEMORY;
3852 else
3853 xcert = NULL;
3854 break;
3855 case NID_safeContentsBag:
3856 return (openssl_parse_bags(bag->value.safes, pass,
3857 keylist, certlist));
3858 default:
3859 ret = KMF_ERR_PKCS12_FORMAT;
3860 break;
3864 * Set the ID and/or FriendlyName attributes on the key.
3865 * If converting to PKCS11 objects, these can translate to CKA_ID
3866 * and CKA_LABEL values.
3868 if (pkey != NULL && ret == KMF_OK) {
3869 ASN1_TYPE *attr = NULL;
3870 if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3871 if ((attr = ASN1_TYPE_new()) == NULL)
3872 return (KMF_ERR_MEMORY);
3873 attr->value.octet_string =
3874 ASN1_STRING_dup(keyid->value.octet_string);
3875 attr->type = V_ASN1_OCTET_STRING;
3876 attr->value.ptr = (char *)attr->value.octet_string;
3877 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3878 OPENSSL_free(attr);
3881 if (ret == KMF_OK && fname != NULL &&
3882 fname->type == V_ASN1_BMPSTRING) {
3883 if ((attr = ASN1_TYPE_new()) == NULL)
3884 return (KMF_ERR_MEMORY);
3885 attr->value.bmpstring =
3886 ASN1_STRING_dup(fname->value.bmpstring);
3887 attr->type = V_ASN1_BMPSTRING;
3888 attr->value.ptr = (char *)attr->value.bmpstring;
3889 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3890 OPENSSL_free(attr);
3893 if (ret == KMF_OK && keylist != NULL &&
3894 sk_EVP_PKEY_push(keylist, pkey) == 0)
3895 ret = KMF_ERR_MEMORY;
3897 if (ret == KMF_OK && keylist != NULL)
3898 pkey = NULL;
3899 end:
3900 if (pkey != NULL)
3901 EVP_PKEY_free(pkey);
3902 if (xcert != NULL)
3903 X509_free(xcert);
3904 if (data != NULL)
3905 OPENSSL_free(data);
3907 return (ret);
3910 static KMF_RETURN
3911 openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3912 STACK_OF(EVP_PKEY) *keys,
3913 STACK_OF(X509) *certs,
3914 STACK_OF(X509) *ca)
3915 /* ARGSUSED3 */
3917 KMF_RETURN ret = KMF_OK;
3918 STACK_OF(PKCS7) *asafes = NULL;
3919 STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
3920 int i, bagnid;
3921 PKCS7 *p7;
3923 if (p12 == NULL || (keys == NULL && certs == NULL))
3924 return (KMF_ERR_BAD_PARAMETER);
3926 if (pin == NULL || *pin == '\0') {
3927 if (PKCS12_verify_mac(p12, NULL, 0)) {
3928 pin = NULL;
3929 } else if (PKCS12_verify_mac(p12, "", 0)) {
3930 pin = "";
3931 } else {
3932 return (KMF_ERR_AUTH_FAILED);
3934 } else if (!PKCS12_verify_mac(p12, pin, -1)) {
3935 return (KMF_ERR_AUTH_FAILED);
3938 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
3939 return (KMF_ERR_PKCS12_FORMAT);
3941 for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
3942 bags = NULL;
3943 /* LINTED E_BAD_PTR_CAST_ALIGN */
3944 p7 = sk_PKCS7_value(asafes, i);
3945 bagnid = OBJ_obj2nid(p7->type);
3947 if (bagnid == NID_pkcs7_data) {
3948 bags = PKCS12_unpack_p7data(p7);
3949 } else if (bagnid == NID_pkcs7_encrypted) {
3950 bags = PKCS12_unpack_p7encdata(p7, pin,
3951 (pin ? strlen(pin) : 0));
3952 } else {
3953 continue;
3955 if (bags == NULL) {
3956 ret = KMF_ERR_PKCS12_FORMAT;
3957 goto out;
3960 if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
3961 ret = KMF_ERR_PKCS12_FORMAT;
3963 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
3965 out:
3966 if (asafes != NULL)
3967 sk_PKCS7_pop_free(asafes, PKCS7_free);
3969 return (ret);
3973 * Helper function to decrypt and parse PKCS#12 import file.
3975 static KMF_RETURN
3976 extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3977 STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
3978 STACK_OF(X509) **ca)
3979 /* ARGSUSED2 */
3981 PKCS12 *pk12, *pk12_tmp;
3982 STACK_OF(EVP_PKEY) *pkeylist = NULL;
3983 STACK_OF(X509) *xcertlist = NULL;
3984 STACK_OF(X509) *cacertlist = NULL;
3986 if ((pk12 = PKCS12_new()) == NULL) {
3987 return (KMF_ERR_MEMORY);
3990 if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
3991 /* This is ok; it seems to mean there is no more to read. */
3992 if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
3993 ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
3994 goto end_extract_pkcs12;
3996 PKCS12_free(pk12);
3997 return (KMF_ERR_PKCS12_FORMAT);
3999 pk12 = pk12_tmp;
4001 xcertlist = sk_X509_new_null();
4002 if (xcertlist == NULL) {
4003 PKCS12_free(pk12);
4004 return (KMF_ERR_MEMORY);
4006 pkeylist = sk_EVP_PKEY_new_null();
4007 if (pkeylist == NULL) {
4008 sk_X509_pop_free(xcertlist, X509_free);
4009 PKCS12_free(pk12);
4010 return (KMF_ERR_MEMORY);
4013 if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4014 cacertlist) != KMF_OK) {
4015 sk_X509_pop_free(xcertlist, X509_free);
4016 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4017 PKCS12_free(pk12);
4018 return (KMF_ERR_PKCS12_FORMAT);
4021 if (priv_key && pkeylist)
4022 *priv_key = pkeylist;
4023 else if (pkeylist)
4024 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4025 if (certs && xcertlist)
4026 *certs = xcertlist;
4027 else if (xcertlist)
4028 sk_X509_pop_free(xcertlist, X509_free);
4029 if (ca && cacertlist)
4030 *ca = cacertlist;
4031 else if (cacertlist)
4032 sk_X509_pop_free(cacertlist, X509_free);
4034 end_extract_pkcs12:
4036 PKCS12_free(pk12);
4037 return (KMF_OK);
4040 static KMF_RETURN
4041 sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4043 KMF_RETURN rv = KMF_OK;
4044 uint32_t sz;
4046 sz = BN_num_bytes(from);
4047 to->val = (uchar_t *)malloc(sz);
4048 if (to->val == NULL)
4049 return (KMF_ERR_MEMORY);
4051 if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4052 free(to->val);
4053 to->val = NULL;
4054 to->len = 0;
4055 rv = KMF_ERR_MEMORY;
4058 return (rv);
4061 static KMF_RETURN
4062 exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4064 KMF_RETURN rv;
4065 KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4067 (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4068 if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
4069 goto cleanup;
4071 if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
4072 goto cleanup;
4074 if (rsa->d != NULL)
4075 if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
4076 goto cleanup;
4078 if (rsa->p != NULL)
4079 if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
4080 goto cleanup;
4082 if (rsa->q != NULL)
4083 if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
4084 goto cleanup;
4086 if (rsa->dmp1 != NULL)
4087 if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
4088 goto cleanup;
4090 if (rsa->dmq1 != NULL)
4091 if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
4092 goto cleanup;
4094 if (rsa->iqmp != NULL)
4095 if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
4096 goto cleanup;
4097 cleanup:
4098 if (rv != KMF_OK)
4099 kmf_free_raw_key(key);
4100 else
4101 key->keytype = KMF_RSA;
4104 * Free the reference to this key, SSL will not actually free
4105 * the memory until the refcount == 0, so this is safe.
4107 RSA_free(rsa);
4109 return (rv);
4112 static KMF_RETURN
4113 exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4115 KMF_RETURN rv;
4116 KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4118 (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4119 if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
4120 goto cleanup;
4122 if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
4123 goto cleanup;
4125 if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
4126 goto cleanup;
4128 if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
4129 goto cleanup;
4131 cleanup:
4132 if (rv != KMF_OK)
4133 kmf_free_raw_key(key);
4134 else
4135 key->keytype = KMF_DSA;
4138 * Free the reference to this key, SSL will not actually free
4139 * the memory until the refcount == 0, so this is safe.
4141 DSA_free(dsa);
4143 return (rv);
4146 static KMF_RETURN
4147 add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4148 KMF_X509_DER_CERT **certlist, int *ncerts)
4150 KMF_RETURN rv = KMF_OK;
4151 KMF_X509_DER_CERT *list = (*certlist);
4152 KMF_X509_DER_CERT cert;
4153 int n = (*ncerts);
4155 if (list == NULL) {
4156 list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4157 } else {
4158 list = reallocarray(list, n + 1, sizeof (KMF_X509_DER_CERT));
4161 if (list == NULL)
4162 return (KMF_ERR_MEMORY);
4164 (void) memset(&cert, 0, sizeof (cert));
4165 rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4166 if (rv == KMF_OK) {
4167 int len = 0;
4168 /* Get the alias name for the cert if there is one */
4169 char *a = (char *)X509_alias_get0(sslcert, &len);
4170 if (a != NULL)
4171 cert.kmf_private.label = strdup(a);
4172 cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4174 list[n] = cert;
4175 (*ncerts) = n + 1;
4177 *certlist = list;
4178 } else {
4179 free(list);
4182 return (rv);
4185 static KMF_RETURN
4186 add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4187 KMF_RAW_KEY_DATA *newkey, int *nkeys)
4189 KMF_RAW_KEY_DATA *list = (*keylist);
4190 int n = (*nkeys);
4192 if (list == NULL) {
4193 list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4194 } else {
4195 list = reallocarray(list, n + 1, sizeof (KMF_RAW_KEY_DATA));
4198 if (list == NULL)
4199 return (KMF_ERR_MEMORY);
4201 list[n] = *newkey;
4202 (*nkeys) = n + 1;
4204 *keylist = list;
4206 return (KMF_OK);
4209 static X509_ATTRIBUTE *
4210 find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4212 X509_ATTRIBUTE *a;
4213 int i;
4215 if (attrs == NULL)
4216 return (NULL);
4218 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4219 /* LINTED E_BAD_PTR_CAST_ALIGN */
4220 a = sk_X509_ATTRIBUTE_value(attrs, i);
4221 if (OBJ_obj2nid(a->object) == nid)
4222 return (a);
4224 return (NULL);
4227 static KMF_RETURN
4228 convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4230 KMF_RETURN rv = KMF_OK;
4231 X509_ATTRIBUTE *attr;
4233 if (pkey == NULL || key == NULL)
4234 return (KMF_ERR_BAD_PARAMETER);
4235 /* Convert SSL key to raw key */
4236 switch (pkey->type) {
4237 case EVP_PKEY_RSA:
4238 rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
4239 key);
4240 if (rv != KMF_OK)
4241 return (rv);
4242 break;
4243 case EVP_PKEY_DSA:
4244 rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
4245 key);
4246 if (rv != KMF_OK)
4247 return (rv);
4248 break;
4249 default:
4250 return (KMF_ERR_BAD_PARAMETER);
4253 * If friendlyName, add it to record.
4255 attr = find_attr(pkey->attributes, NID_friendlyName);
4256 if (attr != NULL) {
4257 ASN1_TYPE *ty = NULL;
4258 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4259 if (attr->single == 0 && numattr > 0) {
4260 /* LINTED E_BAD_PTR_CAST_ALIGN */
4261 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4263 if (ty != NULL) {
4264 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4265 key->label = uni2asc(ty->value.bmpstring->data,
4266 ty->value.bmpstring->length);
4267 #else
4268 key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4269 ty->value.bmpstring->length);
4270 #endif
4272 } else {
4273 key->label = NULL;
4277 * If KeyID, add it to record as a KMF_DATA object.
4279 attr = find_attr(pkey->attributes, NID_localKeyID);
4280 if (attr != NULL) {
4281 ASN1_TYPE *ty = NULL;
4282 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4283 if (attr->single == 0 && numattr > 0) {
4284 /* LINTED E_BAD_PTR_CAST_ALIGN */
4285 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4287 key->id.Data = (uchar_t *)malloc(
4288 ty->value.octet_string->length);
4289 if (key->id.Data == NULL)
4290 return (KMF_ERR_MEMORY);
4291 (void) memcpy(key->id.Data, ty->value.octet_string->data,
4292 ty->value.octet_string->length);
4293 key->id.Length = ty->value.octet_string->length;
4294 } else {
4295 (void) memset(&key->id, 0, sizeof (KMF_DATA));
4298 return (rv);
4301 static KMF_RETURN
4302 convertPK12Objects(
4303 KMF_HANDLE *kmfh,
4304 STACK_OF(EVP_PKEY) *sslkeys,
4305 STACK_OF(X509) *sslcert,
4306 STACK_OF(X509) *sslcacerts,
4307 KMF_RAW_KEY_DATA **keylist, int *nkeys,
4308 KMF_X509_DER_CERT **certlist, int *ncerts)
4310 KMF_RETURN rv = KMF_OK;
4311 KMF_RAW_KEY_DATA key;
4312 int i;
4314 for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4315 /* LINTED E_BAD_PTR_CAST_ALIGN */
4316 EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4317 rv = convertToRawKey(pkey, &key);
4318 if (rv == KMF_OK)
4319 rv = add_key_to_list(keylist, &key, nkeys);
4321 if (rv != KMF_OK)
4322 return (rv);
4325 /* Now add the certificate to the certlist */
4326 for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4327 /* LINTED E_BAD_PTR_CAST_ALIGN */
4328 X509 *cert = sk_X509_value(sslcert, i);
4329 rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4330 if (rv != KMF_OK)
4331 return (rv);
4334 /* Also add any included CA certs to the list */
4335 for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4336 X509 *c;
4338 * sk_X509_value() is macro that embeds a cast to (X509 *).
4339 * Here it translates into ((X509 *)sk_value((ca), (i))).
4340 * Lint is complaining about the embedded casting, and
4341 * to fix it, you need to fix openssl header files.
4343 /* LINTED E_BAD_PTR_CAST_ALIGN */
4344 c = sk_X509_value(sslcacerts, i);
4346 /* Now add the ca cert to the certlist */
4347 rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4348 if (rv != KMF_OK)
4349 return (rv);
4351 return (rv);
4354 KMF_RETURN
4355 openssl_import_objects(KMF_HANDLE *kmfh,
4356 char *filename, KMF_CREDENTIAL *cred,
4357 KMF_X509_DER_CERT **certlist, int *ncerts,
4358 KMF_RAW_KEY_DATA **keylist, int *nkeys)
4360 KMF_RETURN rv = KMF_OK;
4361 KMF_ENCODE_FORMAT format;
4362 BIO *bio = NULL;
4363 STACK_OF(EVP_PKEY) *privkeys = NULL;
4364 STACK_OF(X509) *certs = NULL;
4365 STACK_OF(X509) *cacerts = NULL;
4368 * auto-detect the file format, regardless of what
4369 * the 'format' parameters in the params say.
4371 rv = kmf_get_file_format(filename, &format);
4372 if (rv != KMF_OK) {
4373 return (rv);
4376 /* This function only works for PEM or PKCS#12 files */
4377 if (format != KMF_FORMAT_PEM &&
4378 format != KMF_FORMAT_PEM_KEYPAIR &&
4379 format != KMF_FORMAT_PKCS12)
4380 return (KMF_ERR_ENCODING);
4382 *certlist = NULL;
4383 *keylist = NULL;
4384 *ncerts = 0;
4385 *nkeys = 0;
4387 if (format == KMF_FORMAT_PKCS12) {
4388 bio = BIO_new_file(filename, "rb");
4389 if (bio == NULL) {
4390 SET_ERROR(kmfh, ERR_get_error());
4391 rv = KMF_ERR_OPEN_FILE;
4392 goto end;
4395 rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4396 (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4398 if (rv == KMF_OK)
4399 /* Convert keys and certs to exportable format */
4400 rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4401 keylist, nkeys, certlist, ncerts);
4402 } else {
4403 EVP_PKEY *pkey;
4404 KMF_DATA *certdata = NULL;
4405 KMF_X509_DER_CERT *kmfcerts = NULL;
4406 int i;
4407 rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4408 (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4409 &pkey, &certdata, ncerts);
4411 /* Reached end of import file? */
4412 if (rv == KMF_OK && pkey != NULL) {
4413 privkeys = sk_EVP_PKEY_new_null();
4414 if (privkeys == NULL) {
4415 rv = KMF_ERR_MEMORY;
4416 goto end;
4418 (void) sk_EVP_PKEY_push(privkeys, pkey);
4419 /* convert the certificate list here */
4420 if (*ncerts > 0 && certlist != NULL) {
4421 kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4422 sizeof (KMF_X509_DER_CERT));
4423 if (kmfcerts == NULL) {
4424 rv = KMF_ERR_MEMORY;
4425 goto end;
4427 for (i = 0; i < *ncerts; i++) {
4428 kmfcerts[i].certificate = certdata[i];
4429 kmfcerts[i].kmf_private.keystore_type =
4430 KMF_KEYSTORE_OPENSSL;
4432 *certlist = kmfcerts;
4435 * Convert keys to exportable format, the certs
4436 * are already OK.
4438 rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4439 keylist, nkeys, NULL, NULL);
4442 end:
4443 if (bio != NULL)
4444 (void) BIO_free(bio);
4446 if (privkeys)
4447 sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4448 if (certs)
4449 sk_X509_pop_free(certs, X509_free);
4450 if (cacerts)
4451 sk_X509_pop_free(cacerts, X509_free);
4453 return (rv);
4456 static KMF_RETURN
4457 create_deskey(DES_cblock **deskey)
4459 DES_cblock *key;
4461 key = (DES_cblock *) malloc(sizeof (DES_cblock));
4462 if (key == NULL) {
4463 return (KMF_ERR_MEMORY);
4466 if (DES_random_key(key) == 0) {
4467 free(key);
4468 return (KMF_ERR_KEYGEN_FAILED);
4471 *deskey = key;
4472 return (KMF_OK);
4475 #define KEYGEN_RETRY 3
4476 #define DES3_KEY_SIZE 24
4478 static KMF_RETURN
4479 create_des3key(unsigned char **des3key)
4481 KMF_RETURN ret = KMF_OK;
4482 DES_cblock *deskey1 = NULL;
4483 DES_cblock *deskey2 = NULL;
4484 DES_cblock *deskey3 = NULL;
4485 unsigned char *newkey = NULL;
4486 int retry;
4488 if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4489 return (KMF_ERR_MEMORY);
4492 /* create the 1st DES key */
4493 if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4494 goto out;
4498 * Create the 2nd DES key and make sure its value is different
4499 * from the 1st DES key.
4501 retry = 0;
4502 do {
4503 if (deskey2 != NULL) {
4504 free(deskey2);
4505 deskey2 = NULL;
4508 if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4509 goto out;
4512 if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4513 == 0) {
4514 ret = KMF_ERR_KEYGEN_FAILED;
4515 retry++;
4517 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4519 if (ret != KMF_OK) {
4520 goto out;
4524 * Create the 3rd DES key and make sure its value is different
4525 * from the 2nd DES key.
4527 retry = 0;
4528 do {
4529 if (deskey3 != NULL) {
4530 free(deskey3);
4531 deskey3 = NULL;
4534 if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4535 goto out;
4538 if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4539 == 0) {
4540 ret = KMF_ERR_KEYGEN_FAILED;
4541 retry++;
4543 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4545 if (ret != KMF_OK) {
4546 goto out;
4549 /* Concatenate 3 DES keys into a DES3 key */
4550 (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4551 (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4552 (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4553 *des3key = newkey;
4555 out:
4556 free(deskey1);
4558 free(deskey2);
4560 free(deskey3);
4562 if (ret != KMF_OK)
4563 free(newkey);
4565 return (ret);
4568 KMF_RETURN
4569 OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4570 int numattr, KMF_ATTRIBUTE *attrlist)
4572 KMF_RETURN ret = KMF_OK;
4573 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4574 char *fullpath = NULL;
4575 KMF_RAW_SYM_KEY *rkey = NULL;
4576 DES_cblock *deskey = NULL;
4577 unsigned char *des3key = NULL;
4578 unsigned char *random = NULL;
4579 int fd = -1;
4580 KMF_KEY_HANDLE *symkey;
4581 KMF_KEY_ALG keytype;
4582 uint32_t keylen;
4583 uint32_t keylen_size = sizeof (keylen);
4584 char *dirpath;
4585 char *keyfile;
4587 if (kmfh == NULL)
4588 return (KMF_ERR_UNINITIALIZED);
4590 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4591 if (symkey == NULL)
4592 return (KMF_ERR_BAD_PARAMETER);
4594 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4596 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4597 if (keyfile == NULL)
4598 return (KMF_ERR_BAD_PARAMETER);
4600 ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4601 (void *)&keytype, NULL);
4602 if (ret != KMF_OK)
4603 return (KMF_ERR_BAD_PARAMETER);
4605 ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4606 &keylen, &keylen_size);
4607 if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4608 (keytype == KMF_DES || keytype == KMF_DES3))
4609 /* keylength is not required for DES and 3DES */
4610 ret = KMF_OK;
4611 if (ret != KMF_OK)
4612 return (KMF_ERR_BAD_PARAMETER);
4614 fullpath = get_fullpath(dirpath, keyfile);
4615 if (fullpath == NULL)
4616 return (KMF_ERR_BAD_PARAMETER);
4618 /* If the requested file exists, return an error */
4619 if (test_for_file(fullpath, 0400) == 1) {
4620 free(fullpath);
4621 return (KMF_ERR_DUPLICATE_KEYFILE);
4624 fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4625 if (fd == -1) {
4626 ret = KMF_ERR_OPEN_FILE;
4627 goto out;
4630 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4631 if (rkey == NULL) {
4632 ret = KMF_ERR_MEMORY;
4633 goto out;
4635 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4637 if (keytype == KMF_DES) {
4638 if ((ret = create_deskey(&deskey)) != KMF_OK) {
4639 goto out;
4641 rkey->keydata.val = (uchar_t *)deskey;
4642 rkey->keydata.len = 8;
4644 symkey->keyalg = KMF_DES;
4646 } else if (keytype == KMF_DES3) {
4647 if ((ret = create_des3key(&des3key)) != KMF_OK) {
4648 goto out;
4650 rkey->keydata.val = (uchar_t *)des3key;
4651 rkey->keydata.len = DES3_KEY_SIZE;
4652 symkey->keyalg = KMF_DES3;
4654 } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4655 keytype == KMF_GENERIC_SECRET) {
4656 int bytes;
4658 if (keylen % 8 != 0) {
4659 ret = KMF_ERR_BAD_KEY_SIZE;
4660 goto out;
4663 if (keytype == KMF_AES) {
4664 if (keylen != 128 &&
4665 keylen != 192 &&
4666 keylen != 256) {
4667 ret = KMF_ERR_BAD_KEY_SIZE;
4668 goto out;
4672 bytes = keylen/8;
4673 random = malloc(bytes);
4674 if (random == NULL) {
4675 ret = KMF_ERR_MEMORY;
4676 goto out;
4678 if (RAND_bytes(random, bytes) != 1) {
4679 ret = KMF_ERR_KEYGEN_FAILED;
4680 goto out;
4683 rkey->keydata.val = (uchar_t *)random;
4684 rkey->keydata.len = bytes;
4685 symkey->keyalg = keytype;
4687 } else {
4688 ret = KMF_ERR_BAD_KEY_TYPE;
4689 goto out;
4692 (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4694 symkey->kstype = KMF_KEYSTORE_OPENSSL;
4695 symkey->keyclass = KMF_SYMMETRIC;
4696 symkey->keylabel = (char *)fullpath;
4697 symkey->israw = TRUE;
4698 symkey->keyp = rkey;
4700 out:
4701 if (fd != -1)
4702 (void) close(fd);
4704 if (ret != KMF_OK && fullpath != NULL) {
4705 free(fullpath);
4707 if (ret != KMF_OK) {
4708 kmf_free_raw_sym_key(rkey);
4709 symkey->keyp = NULL;
4710 symkey->keyalg = KMF_KEYALG_NONE;
4713 return (ret);
4717 * Check a file to see if it is a CRL file with PEM or DER format.
4718 * If success, return its format in the "pformat" argument.
4720 KMF_RETURN
4721 OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4723 KMF_RETURN ret = KMF_OK;
4724 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4725 BIO *bio = NULL;
4726 X509_CRL *xcrl = NULL;
4728 if (filename == NULL) {
4729 return (KMF_ERR_BAD_PARAMETER);
4732 bio = BIO_new_file(filename, "rb");
4733 if (bio == NULL) {
4734 SET_ERROR(kmfh, ERR_get_error());
4735 ret = KMF_ERR_OPEN_FILE;
4736 goto out;
4739 if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4740 *pformat = KMF_FORMAT_PEM;
4741 goto out;
4743 (void) BIO_free(bio);
4746 * Now try to read it as raw DER data.
4748 bio = BIO_new_file(filename, "rb");
4749 if (bio == NULL) {
4750 SET_ERROR(kmfh, ERR_get_error());
4751 ret = KMF_ERR_OPEN_FILE;
4752 goto out;
4755 if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4756 *pformat = KMF_FORMAT_ASN1;
4757 } else {
4758 ret = KMF_ERR_BAD_CRLFILE;
4761 out:
4762 if (bio != NULL)
4763 (void) BIO_free(bio);
4765 if (xcrl != NULL)
4766 X509_CRL_free(xcrl);
4768 return (ret);
4771 KMF_RETURN
4772 OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4773 KMF_RAW_SYM_KEY *rkey)
4775 KMF_RETURN rv = KMF_OK;
4776 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4777 KMF_DATA keyvalue;
4779 if (kmfh == NULL)
4780 return (KMF_ERR_UNINITIALIZED);
4782 if (symkey == NULL || rkey == NULL)
4783 return (KMF_ERR_BAD_PARAMETER);
4784 else if (symkey->keyclass != KMF_SYMMETRIC)
4785 return (KMF_ERR_BAD_KEY_CLASS);
4787 if (symkey->israw) {
4788 KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4790 if (rawkey == NULL ||
4791 rawkey->keydata.val == NULL ||
4792 rawkey->keydata.len == 0)
4793 return (KMF_ERR_BAD_KEYHANDLE);
4795 rkey->keydata.len = rawkey->keydata.len;
4796 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4797 return (KMF_ERR_MEMORY);
4798 (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4799 rkey->keydata.len);
4800 } else {
4801 rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4802 if (rv != KMF_OK)
4803 return (rv);
4804 rkey->keydata.len = keyvalue.Length;
4805 rkey->keydata.val = keyvalue.Data;
4808 return (rv);
4812 * substitute for the unsafe access(2) function.
4813 * If the file in question already exists, return 1.
4814 * else 0. If an error occurs during testing (other
4815 * than EEXIST), return -1.
4817 static int
4818 test_for_file(char *filename, mode_t mode)
4820 int fd;
4823 * Try to create the file with the EXCL flag.
4824 * The call should fail if the file exists.
4826 fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4827 if (fd == -1 && errno == EEXIST)
4828 return (1);
4829 else if (fd == -1) /* some other error */
4830 return (-1);
4832 /* The file did NOT exist. Delete the testcase. */
4833 (void) close(fd);
4834 (void) unlink(filename);
4835 return (0);
4838 KMF_RETURN
4839 OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4840 KMF_ATTRIBUTE *attrlist)
4842 KMF_RETURN rv = KMF_OK;
4843 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4844 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4845 KMF_RAW_KEY_DATA *rawkey;
4846 EVP_PKEY *pkey = NULL;
4847 KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4848 KMF_CREDENTIAL cred = { NULL, 0 };
4849 BIO *out = NULL;
4850 int keys = 0;
4851 char *fullpath = NULL;
4852 char *keyfile = NULL;
4853 char *dirpath = NULL;
4855 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4856 if (pubkey != NULL)
4857 keys++;
4859 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4860 if (prikey != NULL)
4861 keys++;
4863 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4864 if (rawkey != NULL)
4865 keys++;
4868 * Exactly 1 type of key must be passed to this function.
4870 if (keys != 1)
4871 return (KMF_ERR_BAD_PARAMETER);
4873 keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4874 numattr);
4875 if (keyfile == NULL)
4876 return (KMF_ERR_BAD_PARAMETER);
4878 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4880 fullpath = get_fullpath(dirpath, keyfile);
4882 /* Once we have the full path, we don't need the pieces */
4883 if (fullpath == NULL)
4884 return (KMF_ERR_BAD_PARAMETER);
4886 /* If the requested file exists, return an error */
4887 if (test_for_file(fullpath, 0400) == 1) {
4888 free(fullpath);
4889 return (KMF_ERR_DUPLICATE_KEYFILE);
4892 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4893 &format, NULL);
4894 if (rv != KMF_OK)
4895 /* format is optional. */
4896 rv = KMF_OK;
4898 /* CRED is not required for OpenSSL files */
4899 (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4900 &cred, NULL);
4902 /* Store the private key to the keyfile */
4903 out = BIO_new_file(fullpath, "wb");
4904 if (out == NULL) {
4905 SET_ERROR(kmfh, ERR_get_error());
4906 rv = KMF_ERR_OPEN_FILE;
4907 goto end;
4910 if (prikey != NULL && prikey->keyp != NULL) {
4911 if (prikey->keyalg == KMF_RSA ||
4912 prikey->keyalg == KMF_DSA) {
4913 pkey = (EVP_PKEY *)prikey->keyp;
4915 rv = ssl_write_key(kmfh, format,
4916 out, &cred, pkey, TRUE);
4918 if (rv == KMF_OK && prikey->keylabel == NULL) {
4919 prikey->keylabel = strdup(fullpath);
4920 if (prikey->keylabel == NULL)
4921 rv = KMF_ERR_MEMORY;
4924 } else if (pubkey != NULL && pubkey->keyp != NULL) {
4925 if (pubkey->keyalg == KMF_RSA ||
4926 pubkey->keyalg == KMF_DSA) {
4927 pkey = (EVP_PKEY *)pubkey->keyp;
4929 rv = ssl_write_key(kmfh, format,
4930 out, &cred, pkey, FALSE);
4932 if (rv == KMF_OK && pubkey->keylabel == NULL) {
4933 pubkey->keylabel = strdup(fullpath);
4934 if (pubkey->keylabel == NULL)
4935 rv = KMF_ERR_MEMORY;
4938 } else if (rawkey != NULL) {
4939 if (rawkey->keytype == KMF_RSA) {
4940 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
4941 } else if (rawkey->keytype == KMF_DSA) {
4942 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
4943 } else {
4944 rv = KMF_ERR_BAD_PARAMETER;
4946 if (pkey != NULL) {
4947 KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
4949 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
4950 (void *)&kclass, NULL);
4951 if (rv != KMF_OK)
4952 rv = KMF_OK;
4953 rv = ssl_write_key(kmfh, format, out,
4954 &cred, pkey, (kclass == KMF_ASYM_PRI));
4955 EVP_PKEY_free(pkey);
4959 end:
4961 if (out)
4962 (void) BIO_free(out);
4965 if (rv == KMF_OK)
4966 (void) chmod(fullpath, 0400);
4968 free(fullpath);
4969 return (rv);
4972 KMF_RETURN
4973 OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4975 KMF_RETURN ret = KMF_OK;
4976 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4977 X509_CRL *xcrl = NULL;
4978 X509 *xcert = NULL;
4979 EVP_PKEY *pkey;
4980 KMF_ENCODE_FORMAT format;
4981 BIO *in = NULL, *out = NULL;
4982 int openssl_ret = 0;
4983 KMF_ENCODE_FORMAT outformat;
4984 boolean_t crlcheck = FALSE;
4985 char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
4987 if (numattr == 0 || attrlist == NULL) {
4988 return (KMF_ERR_BAD_PARAMETER);
4991 /* CRL check is optional */
4992 (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
4993 &crlcheck, NULL);
4995 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
4996 if (crlcheck == B_TRUE && certfile == NULL) {
4997 return (KMF_ERR_BAD_CERTFILE);
5000 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5001 incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5002 outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5004 crlfile = get_fullpath(dirpath, incrl);
5006 if (crlfile == NULL)
5007 return (KMF_ERR_BAD_CRLFILE);
5009 outcrlfile = get_fullpath(dirpath, outcrl);
5010 if (outcrlfile == NULL)
5011 return (KMF_ERR_BAD_CRLFILE);
5013 if (isdir(outcrlfile)) {
5014 free(outcrlfile);
5015 return (KMF_ERR_BAD_CRLFILE);
5018 ret = kmf_is_crl_file(handle, crlfile, &format);
5019 if (ret != KMF_OK) {
5020 free(outcrlfile);
5021 return (ret);
5024 in = BIO_new_file(crlfile, "rb");
5025 if (in == NULL) {
5026 SET_ERROR(kmfh, ERR_get_error());
5027 ret = KMF_ERR_OPEN_FILE;
5028 goto end;
5031 if (format == KMF_FORMAT_ASN1) {
5032 xcrl = d2i_X509_CRL_bio(in, NULL);
5033 } else if (format == KMF_FORMAT_PEM) {
5034 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5037 if (xcrl == NULL) {
5038 SET_ERROR(kmfh, ERR_get_error());
5039 ret = KMF_ERR_BAD_CRLFILE;
5040 goto end;
5043 /* If bypasscheck is specified, no need to verify. */
5044 if (crlcheck == B_FALSE)
5045 goto output;
5047 ret = kmf_is_cert_file(handle, certfile, &format);
5048 if (ret != KMF_OK)
5049 goto end;
5051 /* Read in the CA cert file and convert to X509 */
5052 if (BIO_read_filename(in, certfile) <= 0) {
5053 SET_ERROR(kmfh, ERR_get_error());
5054 ret = KMF_ERR_OPEN_FILE;
5055 goto end;
5058 if (format == KMF_FORMAT_ASN1) {
5059 xcert = d2i_X509_bio(in, NULL);
5060 } else if (format == KMF_FORMAT_PEM) {
5061 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5062 } else {
5063 ret = KMF_ERR_BAD_CERT_FORMAT;
5064 goto end;
5067 if (xcert == NULL) {
5068 SET_ERROR(kmfh, ERR_get_error());
5069 ret = KMF_ERR_BAD_CERT_FORMAT;
5070 goto end;
5072 /* Now get the public key from the CA cert */
5073 pkey = X509_get_pubkey(xcert);
5074 if (pkey == NULL) {
5075 SET_ERROR(kmfh, ERR_get_error());
5076 ret = KMF_ERR_BAD_CERTFILE;
5077 goto end;
5080 /* Verify the CRL with the CA's public key */
5081 openssl_ret = X509_CRL_verify(xcrl, pkey);
5082 EVP_PKEY_free(pkey);
5083 if (openssl_ret > 0) {
5084 ret = KMF_OK; /* verify succeed */
5085 } else {
5086 SET_ERROR(kmfh, openssl_ret);
5087 ret = KMF_ERR_BAD_CRLFILE;
5090 output:
5091 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5092 &outformat, NULL);
5093 if (ret != KMF_OK) {
5094 ret = KMF_OK;
5095 outformat = KMF_FORMAT_PEM;
5098 out = BIO_new_file(outcrlfile, "wb");
5099 if (out == NULL) {
5100 SET_ERROR(kmfh, ERR_get_error());
5101 ret = KMF_ERR_OPEN_FILE;
5102 goto end;
5105 if (outformat == KMF_FORMAT_ASN1) {
5106 openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5107 } else if (outformat == KMF_FORMAT_PEM) {
5108 openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5109 } else {
5110 ret = KMF_ERR_BAD_PARAMETER;
5111 goto end;
5114 if (openssl_ret <= 0) {
5115 SET_ERROR(kmfh, ERR_get_error());
5116 ret = KMF_ERR_WRITE_FILE;
5117 } else {
5118 ret = KMF_OK;
5121 end:
5122 if (xcrl != NULL)
5123 X509_CRL_free(xcrl);
5125 if (xcert != NULL)
5126 X509_free(xcert);
5128 if (in != NULL)
5129 (void) BIO_free(in);
5131 if (out != NULL)
5132 (void) BIO_free(out);
5134 free(outcrlfile);
5136 return (ret);
5139 KMF_RETURN
5140 OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5142 KMF_RETURN ret = KMF_OK;
5143 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5144 X509_CRL *x = NULL;
5145 KMF_ENCODE_FORMAT format;
5146 char *crlfile = NULL;
5147 BIO *in = NULL;
5148 BIO *mem = NULL;
5149 long len;
5150 char *memptr;
5151 char *data = NULL;
5152 char **crldata;
5153 char *crlfilename, *dirpath;
5155 if (numattr == 0 || attrlist == NULL) {
5156 return (KMF_ERR_BAD_PARAMETER);
5158 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5159 attrlist, numattr);
5160 if (crlfilename == NULL)
5161 return (KMF_ERR_BAD_CRLFILE);
5163 crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5164 attrlist, numattr);
5166 if (crldata == NULL)
5167 return (KMF_ERR_BAD_PARAMETER);
5169 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5171 crlfile = get_fullpath(dirpath, crlfilename);
5173 if (crlfile == NULL)
5174 return (KMF_ERR_BAD_CRLFILE);
5176 if (isdir(crlfile)) {
5177 free(crlfile);
5178 return (KMF_ERR_BAD_CRLFILE);
5181 ret = kmf_is_crl_file(handle, crlfile, &format);
5182 if (ret != KMF_OK) {
5183 free(crlfile);
5184 return (ret);
5187 if (bio_err == NULL)
5188 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5190 in = BIO_new_file(crlfile, "rb");
5191 if (in == NULL) {
5192 SET_ERROR(kmfh, ERR_get_error());
5193 ret = KMF_ERR_OPEN_FILE;
5194 goto end;
5197 if (format == KMF_FORMAT_ASN1) {
5198 x = d2i_X509_CRL_bio(in, NULL);
5199 } else if (format == KMF_FORMAT_PEM) {
5200 x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5203 if (x == NULL) { /* should not happen */
5204 SET_ERROR(kmfh, ERR_get_error());
5205 ret = KMF_ERR_OPEN_FILE;
5206 goto end;
5209 mem = BIO_new(BIO_s_mem());
5210 if (mem == NULL) {
5211 SET_ERROR(kmfh, ERR_get_error());
5212 ret = KMF_ERR_MEMORY;
5213 goto end;
5216 (void) X509_CRL_print(mem, x);
5217 len = BIO_get_mem_data(mem, &memptr);
5218 if (len <= 0) {
5219 SET_ERROR(kmfh, ERR_get_error());
5220 ret = KMF_ERR_MEMORY;
5221 goto end;
5224 data = malloc(len + 1);
5225 if (data == NULL) {
5226 ret = KMF_ERR_MEMORY;
5227 goto end;
5230 (void) memcpy(data, memptr, len);
5231 data[len] = '\0';
5232 *crldata = data;
5234 end:
5235 if (x != NULL)
5236 X509_CRL_free(x);
5238 free(crlfile);
5240 if (in != NULL)
5241 (void) BIO_free(in);
5243 if (mem != NULL)
5244 (void) BIO_free(mem);
5246 return (ret);
5249 KMF_RETURN
5250 OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5252 KMF_RETURN ret = KMF_OK;
5253 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5254 KMF_ENCODE_FORMAT format;
5255 char *crlfile = NULL;
5256 BIO *in = NULL;
5257 char *crlfilename, *dirpath;
5259 if (numattr == 0 || attrlist == NULL) {
5260 return (KMF_ERR_BAD_PARAMETER);
5263 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5264 attrlist, numattr);
5266 if (crlfilename == NULL)
5267 return (KMF_ERR_BAD_CRLFILE);
5269 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5271 crlfile = get_fullpath(dirpath, crlfilename);
5273 if (crlfile == NULL)
5274 return (KMF_ERR_BAD_CRLFILE);
5276 if (isdir(crlfile)) {
5277 ret = KMF_ERR_BAD_CRLFILE;
5278 goto end;
5281 ret = kmf_is_crl_file(handle, crlfile, &format);
5282 if (ret != KMF_OK)
5283 goto end;
5285 if (unlink(crlfile) != 0) {
5286 SET_SYS_ERROR(kmfh, errno);
5287 ret = KMF_ERR_INTERNAL;
5288 goto end;
5291 end:
5292 if (in != NULL)
5293 (void) BIO_free(in);
5294 free(crlfile);
5296 return (ret);
5299 KMF_RETURN
5300 OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5302 KMF_RETURN ret = KMF_OK;
5303 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5304 KMF_ENCODE_FORMAT format;
5305 BIO *in = NULL;
5306 X509 *xcert = NULL;
5307 X509_CRL *xcrl = NULL;
5308 STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5309 X509_REVOKED *revoke;
5310 int i;
5311 char *crlfilename, *crlfile, *dirpath, *certfile;
5313 if (numattr == 0 || attrlist == NULL) {
5314 return (KMF_ERR_BAD_PARAMETER);
5317 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5318 attrlist, numattr);
5320 if (crlfilename == NULL)
5321 return (KMF_ERR_BAD_CRLFILE);
5323 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5324 if (certfile == NULL)
5325 return (KMF_ERR_BAD_CRLFILE);
5327 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5329 crlfile = get_fullpath(dirpath, crlfilename);
5331 if (crlfile == NULL)
5332 return (KMF_ERR_BAD_CRLFILE);
5334 if (isdir(crlfile)) {
5335 ret = KMF_ERR_BAD_CRLFILE;
5336 goto end;
5339 ret = kmf_is_crl_file(handle, crlfile, &format);
5340 if (ret != KMF_OK)
5341 goto end;
5343 /* Read the CRL file and load it into a X509_CRL structure */
5344 in = BIO_new_file(crlfilename, "rb");
5345 if (in == NULL) {
5346 SET_ERROR(kmfh, ERR_get_error());
5347 ret = KMF_ERR_OPEN_FILE;
5348 goto end;
5351 if (format == KMF_FORMAT_ASN1) {
5352 xcrl = d2i_X509_CRL_bio(in, NULL);
5353 } else if (format == KMF_FORMAT_PEM) {
5354 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5357 if (xcrl == NULL) {
5358 SET_ERROR(kmfh, ERR_get_error());
5359 ret = KMF_ERR_BAD_CRLFILE;
5360 goto end;
5362 (void) BIO_free(in);
5364 /* Read the Certificate file and load it into a X509 structure */
5365 ret = kmf_is_cert_file(handle, certfile, &format);
5366 if (ret != KMF_OK)
5367 goto end;
5369 in = BIO_new_file(certfile, "rb");
5370 if (in == NULL) {
5371 SET_ERROR(kmfh, ERR_get_error());
5372 ret = KMF_ERR_OPEN_FILE;
5373 goto end;
5376 if (format == KMF_FORMAT_ASN1) {
5377 xcert = d2i_X509_bio(in, NULL);
5378 } else if (format == KMF_FORMAT_PEM) {
5379 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5382 if (xcert == NULL) {
5383 SET_ERROR(kmfh, ERR_get_error());
5384 ret = KMF_ERR_BAD_CERTFILE;
5385 goto end;
5388 /* Check if the certificate and the CRL have same issuer */
5389 if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
5390 ret = KMF_ERR_ISSUER;
5391 goto end;
5394 /* Check to see if the certificate serial number is revoked */
5395 revoke_stack = X509_CRL_get_REVOKED(xcrl);
5396 if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5397 /* No revoked certificates in the CRL file */
5398 SET_ERROR(kmfh, ERR_get_error());
5399 ret = KMF_ERR_EMPTY_CRL;
5400 goto end;
5403 for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5404 /* LINTED E_BAD_PTR_CAST_ALIGN */
5405 revoke = sk_X509_REVOKED_value(revoke_stack, i);
5406 if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
5407 revoke->serialNumber) == 0) {
5408 break;
5412 if (i < sk_X509_REVOKED_num(revoke_stack)) {
5413 ret = KMF_OK;
5414 } else {
5415 ret = KMF_ERR_NOT_REVOKED;
5418 end:
5419 if (in != NULL)
5420 (void) BIO_free(in);
5421 if (xcrl != NULL)
5422 X509_CRL_free(xcrl);
5423 if (xcert != NULL)
5424 X509_free(xcert);
5426 return (ret);
5429 KMF_RETURN
5430 OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5432 KMF_RETURN ret = KMF_OK;
5433 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5434 BIO *bcrl = NULL;
5435 X509_CRL *xcrl = NULL;
5436 X509 *xcert = NULL;
5437 EVP_PKEY *pkey;
5438 int sslret;
5439 KMF_ENCODE_FORMAT crl_format;
5440 unsigned char *p;
5441 long len;
5443 if (handle == NULL || crlname == NULL || tacert == NULL) {
5444 return (KMF_ERR_BAD_PARAMETER);
5447 ret = kmf_get_file_format(crlname, &crl_format);
5448 if (ret != KMF_OK)
5449 return (ret);
5451 bcrl = BIO_new_file(crlname, "rb");
5452 if (bcrl == NULL) {
5453 SET_ERROR(kmfh, ERR_get_error());
5454 ret = KMF_ERR_OPEN_FILE;
5455 goto cleanup;
5458 if (crl_format == KMF_FORMAT_ASN1) {
5459 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5460 } else if (crl_format == KMF_FORMAT_PEM) {
5461 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5462 } else {
5463 ret = KMF_ERR_BAD_PARAMETER;
5464 goto cleanup;
5467 if (xcrl == NULL) {
5468 SET_ERROR(kmfh, ERR_get_error());
5469 ret = KMF_ERR_BAD_CRLFILE;
5470 goto cleanup;
5473 p = tacert->Data;
5474 len = tacert->Length;
5475 xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5477 if (xcert == NULL) {
5478 SET_ERROR(kmfh, ERR_get_error());
5479 ret = KMF_ERR_BAD_CERTFILE;
5480 goto cleanup;
5483 /* Get issuer certificate public key */
5484 pkey = X509_get_pubkey(xcert);
5485 if (pkey == NULL) {
5486 SET_ERROR(kmfh, ERR_get_error());
5487 ret = KMF_ERR_BAD_CERT_FORMAT;
5488 goto cleanup;
5491 /* Verify CRL signature */
5492 sslret = X509_CRL_verify(xcrl, pkey);
5493 EVP_PKEY_free(pkey);
5494 if (sslret > 0) {
5495 ret = KMF_OK;
5496 } else {
5497 SET_ERROR(kmfh, sslret);
5498 ret = KMF_ERR_BAD_CRLFILE;
5501 cleanup:
5502 if (bcrl != NULL)
5503 (void) BIO_free(bcrl);
5505 if (xcrl != NULL)
5506 X509_CRL_free(xcrl);
5508 if (xcert != NULL)
5509 X509_free(xcert);
5511 return (ret);
5515 KMF_RETURN
5516 OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5518 KMF_RETURN ret = KMF_OK;
5519 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5520 KMF_ENCODE_FORMAT crl_format;
5521 BIO *bcrl = NULL;
5522 X509_CRL *xcrl = NULL;
5523 int i;
5525 if (handle == NULL || crlname == NULL) {
5526 return (KMF_ERR_BAD_PARAMETER);
5529 ret = kmf_is_crl_file(handle, crlname, &crl_format);
5530 if (ret != KMF_OK)
5531 return (ret);
5533 bcrl = BIO_new_file(crlname, "rb");
5534 if (bcrl == NULL) {
5535 SET_ERROR(kmfh, ERR_get_error());
5536 ret = KMF_ERR_OPEN_FILE;
5537 goto cleanup;
5540 if (crl_format == KMF_FORMAT_ASN1)
5541 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5542 else if (crl_format == KMF_FORMAT_PEM)
5543 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5545 if (xcrl == NULL) {
5546 SET_ERROR(kmfh, ERR_get_error());
5547 ret = KMF_ERR_BAD_CRLFILE;
5548 goto cleanup;
5550 i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
5551 if (i >= 0) {
5552 ret = KMF_ERR_VALIDITY_PERIOD;
5553 goto cleanup;
5555 if (X509_CRL_get_nextUpdate(xcrl)) {
5556 i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
5558 if (i <= 0) {
5559 ret = KMF_ERR_VALIDITY_PERIOD;
5560 goto cleanup;
5564 ret = KMF_OK;
5566 cleanup:
5567 if (bcrl != NULL)
5568 (void) BIO_free(bcrl);
5570 if (xcrl != NULL)
5571 X509_CRL_free(xcrl);
5573 return (ret);