4853 illumos-gate is not lint-clean when built with openssl 1.0
[unleashed.git] / usr / src / lib / libkmf / plugins / kmf_openssl / common / openssl_spi.c
blob19d757df904b55e8f2e64910154894c018c0a64f
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, similar to
139 * what wanboot did.
141 DECLARE_STACK_OF(EVP_PKEY)
143 #define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY)
144 #define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st))
145 #define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st))
146 #define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i))
147 #define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val))
148 #define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \
149 (free_func))
151 mutex_t init_lock = DEFAULTMUTEX;
152 static int ssl_initialized = 0;
153 static BIO *bio_err = NULL;
155 static int
156 test_for_file(char *, mode_t);
157 static KMF_RETURN
158 openssl_parse_bag(PKCS12_SAFEBAG *, char *, int,
159 STACK_OF(EVP_PKEY) *, STACK_OF(X509) *);
161 static KMF_RETURN
162 local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *,
163 int, KMF_KEY_HANDLE *, char *);
165 static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int);
167 static KMF_RETURN
168 extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *,
169 CK_UTF8CHAR *, CK_ULONG, EVP_PKEY **, KMF_DATA **, int *);
171 static KMF_RETURN
172 kmf_load_cert(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
173 char *, KMF_DATA *);
175 static KMF_RETURN
176 load_certs(KMF_HANDLE *, char *, char *, KMF_BIGINT *, KMF_CERT_VALIDITY,
177 char *, KMF_DATA **, uint32_t *);
179 static KMF_RETURN
180 sslBN2KMFBN(BIGNUM *, KMF_BIGINT *);
182 static EVP_PKEY *
183 ImportRawRSAKey(KMF_RAW_RSA_KEY *);
185 static KMF_RETURN
186 convertToRawKey(EVP_PKEY *, KMF_RAW_KEY_DATA *);
188 KMF_RETURN
189 OpenSSL_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
191 void
192 OpenSSL_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
194 KMF_RETURN
195 OpenSSL_StoreCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
197 KMF_RETURN
198 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int, KMF_ATTRIBUTE *);
200 KMF_RETURN
201 OpenSSL_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
203 KMF_RETURN
204 OpenSSL_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
206 KMF_RETURN
207 OpenSSL_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
209 KMF_RETURN
210 OpenSSL_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
211 KMF_DATA *, KMF_DATA *);
213 KMF_RETURN
214 OpenSSL_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
216 KMF_RETURN
217 OpenSSL_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
219 KMF_RETURN
220 OpenSSL_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
222 KMF_RETURN
223 OpenSSL_ListCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
225 KMF_RETURN
226 OpenSSL_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
228 KMF_RETURN
229 OpenSSL_CertGetPrintable(KMF_HANDLE_T, const KMF_DATA *,
230 KMF_PRINTABLE_ITEM, char *);
232 KMF_RETURN
233 OpenSSL_GetErrorString(KMF_HANDLE_T, char **);
235 KMF_RETURN
236 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
238 KMF_RETURN
239 OpenSSL_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
240 KMF_DATA *, KMF_DATA *);
242 KMF_RETURN
243 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
245 KMF_RETURN
246 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
248 KMF_RETURN
249 OpenSSL_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
251 KMF_RETURN
252 OpenSSL_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
254 KMF_RETURN
255 OpenSSL_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
257 KMF_RETURN
258 OpenSSL_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
260 KMF_RETURN
261 OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
263 KMF_RETURN
264 OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
266 static
267 KMF_PLUGIN_FUNCLIST openssl_plugin_table =
269 1, /* Version */
270 NULL, /* ConfigureKeystore */
271 OpenSSL_FindCert,
272 OpenSSL_FreeKMFCert,
273 OpenSSL_StoreCert,
274 NULL, /* ImportCert */
275 OpenSSL_ImportCRL,
276 OpenSSL_DeleteCert,
277 OpenSSL_DeleteCRL,
278 OpenSSL_CreateKeypair,
279 OpenSSL_FindKey,
280 OpenSSL_EncodePubKeyData,
281 OpenSSL_SignData,
282 OpenSSL_DeleteKey,
283 OpenSSL_ListCRL,
284 NULL, /* FindCRL */
285 OpenSSL_FindCertInCRL,
286 OpenSSL_GetErrorString,
287 OpenSSL_FindPrikeyByCert,
288 OpenSSL_DecryptData,
289 OpenSSL_ExportPK12,
290 OpenSSL_CreateSymKey,
291 OpenSSL_GetSymKeyValue,
292 NULL, /* SetTokenPin */
293 OpenSSL_StoreKey,
294 NULL /* Finalize */
297 static mutex_t *lock_cs;
298 static long *lock_count;
300 static void
301 /* ARGSUSED1 */
302 locking_cb(int mode, int type, char *file, int line)
304 if (mode & CRYPTO_LOCK) {
305 (void) mutex_lock(&(lock_cs[type]));
306 lock_count[type]++;
307 } else {
308 (void) mutex_unlock(&(lock_cs[type]));
312 static unsigned long
313 thread_id()
315 return ((unsigned long)thr_self());
318 KMF_PLUGIN_FUNCLIST *
319 KMF_Plugin_Initialize()
321 int i;
323 (void) mutex_lock(&init_lock);
324 if (!ssl_initialized) {
326 * Add support for extension OIDs that are not yet in the
327 * openssl default set.
329 (void) OBJ_create("2.5.29.30", "nameConstraints",
330 "X509v3 Name Constraints");
331 (void) OBJ_create("2.5.29.33", "policyMappings",
332 "X509v3 Policy Mappings");
333 (void) OBJ_create("2.5.29.36", "policyConstraints",
334 "X509v3 Policy Constraints");
335 (void) OBJ_create("2.5.29.46", "freshestCRL",
336 "X509v3 Freshest CRL");
337 (void) OBJ_create("2.5.29.54", "inhibitAnyPolicy",
338 "X509v3 Inhibit Any-Policy");
340 * Set up for thread-safe operation.
342 lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (mutex_t));
343 if (lock_cs == NULL) {
344 (void) mutex_unlock(&init_lock);
345 return (NULL);
348 lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (long));
349 if (lock_count == NULL) {
350 OPENSSL_free(lock_cs);
351 (void) mutex_unlock(&init_lock);
352 return (NULL);
355 for (i = 0; i < CRYPTO_num_locks(); i++) {
356 lock_count[i] = 0;
357 (void) mutex_init(&lock_cs[i], USYNC_THREAD, NULL);
360 CRYPTO_set_id_callback((unsigned long (*)())thread_id);
361 if (CRYPTO_get_locking_callback() == NULL)
362 CRYPTO_set_locking_callback((void (*)())locking_cb);
364 OpenSSL_add_all_algorithms();
366 /* Enable error strings for reporting */
367 ERR_load_crypto_strings();
369 ssl_initialized = 1;
371 (void) mutex_unlock(&init_lock);
373 return (&openssl_plugin_table);
376 * Convert an SSL DN to a KMF DN.
378 static KMF_RETURN
379 get_x509_dn(X509_NAME *sslDN, KMF_X509_NAME *kmfDN)
381 KMF_DATA derdata;
382 KMF_RETURN rv = KMF_OK;
383 uchar_t *tmp;
385 /* Convert to raw DER format */
386 derdata.Length = i2d_X509_NAME(sslDN, NULL);
387 if ((tmp = derdata.Data = (uchar_t *)OPENSSL_malloc(derdata.Length))
388 == NULL) {
389 return (KMF_ERR_MEMORY);
391 (void) i2d_X509_NAME(sslDN, &tmp);
393 /* Decode to KMF format */
394 rv = DerDecodeName(&derdata, kmfDN);
395 if (rv != KMF_OK) {
396 rv = KMF_ERR_BAD_CERT_FORMAT;
398 OPENSSL_free(derdata.Data);
400 return (rv);
404 isdir(char *path)
406 struct stat s;
408 if (stat(path, &s) == -1)
409 return (0);
411 return ((s.st_mode & S_IFMT) == S_IFDIR);
414 static KMF_RETURN
415 ssl_cert2KMFDATA(KMF_HANDLE *kmfh, X509 *x509cert, KMF_DATA *cert)
417 KMF_RETURN rv = KMF_OK;
418 unsigned char *buf = NULL, *p;
419 int len;
422 * Convert the X509 internal struct to DER encoded data
424 if ((len = i2d_X509(x509cert, NULL)) < 0) {
425 SET_ERROR(kmfh, ERR_get_error());
426 rv = KMF_ERR_BAD_CERT_FORMAT;
427 goto cleanup;
429 if ((buf = malloc(len)) == NULL) {
430 SET_SYS_ERROR(kmfh, errno);
431 rv = KMF_ERR_MEMORY;
432 goto cleanup;
436 * i2d_X509 will increment the buf pointer so that we need to
437 * save it.
439 p = buf;
440 if ((len = i2d_X509(x509cert, &p)) < 0) {
441 SET_ERROR(kmfh, ERR_get_error());
442 free(buf);
443 rv = KMF_ERR_BAD_CERT_FORMAT;
444 goto cleanup;
447 /* caller's responsibility to free it */
448 cert->Data = buf;
449 cert->Length = len;
451 cleanup:
452 if (rv != KMF_OK) {
453 if (buf)
454 free(buf);
455 cert->Data = NULL;
456 cert->Length = 0;
459 return (rv);
463 static KMF_RETURN
464 check_cert(X509 *xcert, char *issuer, char *subject, KMF_BIGINT *serial,
465 boolean_t *match)
467 KMF_RETURN rv = KMF_OK;
468 boolean_t findIssuer = FALSE;
469 boolean_t findSubject = FALSE;
470 boolean_t findSerial = FALSE;
471 KMF_X509_NAME issuerDN, subjectDN;
472 KMF_X509_NAME certIssuerDN, certSubjectDN;
474 *match = FALSE;
475 if (xcert == NULL) {
476 return (KMF_ERR_BAD_PARAMETER);
479 (void) memset(&issuerDN, 0, sizeof (KMF_X509_NAME));
480 (void) memset(&subjectDN, 0, sizeof (KMF_X509_NAME));
481 (void) memset(&certIssuerDN, 0, sizeof (KMF_X509_NAME));
482 (void) memset(&certSubjectDN, 0, sizeof (KMF_X509_NAME));
484 if (issuer != NULL && strlen(issuer)) {
485 rv = kmf_dn_parser(issuer, &issuerDN);
486 if (rv != KMF_OK)
487 return (KMF_ERR_BAD_PARAMETER);
489 rv = get_x509_dn(xcert->cert_info->issuer, &certIssuerDN);
490 if (rv != KMF_OK) {
491 kmf_free_dn(&issuerDN);
492 return (KMF_ERR_BAD_PARAMETER);
495 findIssuer = TRUE;
497 if (subject != NULL && strlen(subject)) {
498 rv = kmf_dn_parser(subject, &subjectDN);
499 if (rv != KMF_OK) {
500 rv = KMF_ERR_BAD_PARAMETER;
501 goto cleanup;
504 rv = get_x509_dn(xcert->cert_info->subject, &certSubjectDN);
505 if (rv != KMF_OK) {
506 rv = KMF_ERR_BAD_PARAMETER;
507 goto cleanup;
509 findSubject = TRUE;
511 if (serial != NULL && serial->val != NULL)
512 findSerial = TRUE;
514 if (findSerial) {
515 BIGNUM *bn;
517 /* Comparing BIGNUMs is a pain! */
518 bn = ASN1_INTEGER_to_BN(xcert->cert_info->serialNumber, NULL);
519 if (bn != NULL) {
520 int bnlen = BN_num_bytes(bn);
522 if (bnlen == serial->len) {
523 uchar_t *a = malloc(bnlen);
524 if (a == NULL) {
525 rv = KMF_ERR_MEMORY;
526 BN_free(bn);
527 goto cleanup;
529 bnlen = BN_bn2bin(bn, a);
530 *match = (memcmp(a, serial->val, serial->len) ==
532 rv = KMF_OK;
533 free(a);
535 BN_free(bn);
536 if (!(*match))
537 goto cleanup;
538 } else {
539 rv = KMF_OK;
540 goto cleanup;
543 if (findIssuer) {
544 *match = (kmf_compare_rdns(&issuerDN, &certIssuerDN) == 0);
545 if ((*match) == B_FALSE) {
546 /* stop checking and bail */
547 rv = KMF_OK;
548 goto cleanup;
551 if (findSubject) {
552 *match = (kmf_compare_rdns(&subjectDN, &certSubjectDN) == 0);
553 if ((*match) == B_FALSE) {
554 /* stop checking and bail */
555 rv = KMF_OK;
556 goto cleanup;
560 *match = TRUE;
561 cleanup:
562 if (findIssuer) {
563 kmf_free_dn(&issuerDN);
564 kmf_free_dn(&certIssuerDN);
566 if (findSubject) {
567 kmf_free_dn(&subjectDN);
568 kmf_free_dn(&certSubjectDN);
571 return (rv);
576 * This function loads a certificate file into an X509 data structure, and
577 * checks if its issuer, subject or the serial number matches with those
578 * values. If it matches, then return the X509 data structure.
580 static KMF_RETURN
581 load_X509cert(KMF_HANDLE *kmfh,
582 char *issuer, char *subject, KMF_BIGINT *serial,
583 char *pathname, X509 **outcert)
585 KMF_RETURN rv = KMF_OK;
586 X509 *xcert = NULL;
587 BIO *bcert = NULL;
588 boolean_t match = FALSE;
589 KMF_ENCODE_FORMAT format;
592 * auto-detect the file format, regardless of what
593 * the 'format' parameters in the params say.
595 rv = kmf_get_file_format(pathname, &format);
596 if (rv != KMF_OK) {
597 if (rv == KMF_ERR_OPEN_FILE)
598 rv = KMF_ERR_CERT_NOT_FOUND;
599 return (rv);
602 /* Not ASN1(DER) format */
603 if ((bcert = BIO_new_file(pathname, "rb")) == NULL) {
604 SET_ERROR(kmfh, ERR_get_error());
605 rv = KMF_ERR_OPEN_FILE;
606 goto cleanup;
609 if (format == KMF_FORMAT_PEM)
610 xcert = PEM_read_bio_X509_AUX(bcert, NULL, NULL, NULL);
611 else if (format == KMF_FORMAT_ASN1)
612 xcert = d2i_X509_bio(bcert, NULL);
613 else if (format == KMF_FORMAT_PKCS12) {
614 PKCS12 *p12 = d2i_PKCS12_bio(bcert, NULL);
615 if (p12 != NULL) {
616 (void) PKCS12_parse(p12, NULL, NULL, &xcert, NULL);
617 PKCS12_free(p12);
618 p12 = NULL;
619 } else {
620 SET_ERROR(kmfh, ERR_get_error());
621 rv = KMF_ERR_BAD_CERT_FORMAT;
623 } else {
624 rv = KMF_ERR_BAD_PARAMETER;
625 goto cleanup;
628 if (xcert == NULL) {
629 SET_ERROR(kmfh, ERR_get_error());
630 rv = KMF_ERR_BAD_CERT_FORMAT;
631 goto cleanup;
634 if (check_cert(xcert, issuer, subject, serial, &match) != KMF_OK ||
635 match == FALSE) {
636 rv = KMF_ERR_CERT_NOT_FOUND;
637 goto cleanup;
640 if (outcert != NULL) {
641 *outcert = xcert;
644 cleanup:
645 if (bcert != NULL) (void) BIO_free(bcert);
646 if (rv != KMF_OK && xcert != NULL)
647 X509_free(xcert);
649 return (rv);
652 static int
653 datacmp(const void *a, const void *b)
655 KMF_DATA *adata = (KMF_DATA *)a;
656 KMF_DATA *bdata = (KMF_DATA *)b;
657 if (adata->Length > bdata->Length)
658 return (-1);
659 if (adata->Length < bdata->Length)
660 return (1);
661 return (0);
664 static KMF_RETURN
665 load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
666 KMF_CERT_VALIDITY validity, char *pathname,
667 KMF_DATA **certlist, uint32_t *numcerts)
669 KMF_RETURN rv = KMF_OK;
670 int i;
671 KMF_DATA *certs = NULL;
672 int nc = 0;
673 int hits = 0;
674 KMF_ENCODE_FORMAT format;
676 rv = kmf_get_file_format(pathname, &format);
677 if (rv != KMF_OK) {
678 if (rv == KMF_ERR_OPEN_FILE)
679 rv = KMF_ERR_CERT_NOT_FOUND;
680 return (rv);
682 if (format == KMF_FORMAT_ASN1) {
683 /* load a single certificate */
684 certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
685 if (certs == NULL)
686 return (KMF_ERR_MEMORY);
687 certs->Data = NULL;
688 certs->Length = 0;
689 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
690 pathname, certs);
691 if (rv == KMF_OK) {
692 *certlist = certs;
693 *numcerts = 1;
694 } else {
695 kmf_free_data(certs);
696 free(certs);
697 certs = NULL;
699 return (rv);
700 } else if (format == KMF_FORMAT_PKCS12) {
701 /* We need a credential to access a PKCS#12 file */
702 rv = KMF_ERR_BAD_CERT_FORMAT;
703 } else if (format == KMF_FORMAT_PEM ||
704 format != KMF_FORMAT_PEM_KEYPAIR) {
706 /* This function only works on PEM files */
707 rv = extract_pem(kmfh, issuer, subject, serial, pathname,
708 (uchar_t *)NULL, 0, NULL, &certs, &nc);
709 } else {
710 return (KMF_ERR_ENCODING);
713 if (rv != KMF_OK)
714 return (rv);
716 for (i = 0; i < nc; i++) {
717 if (validity == KMF_NONEXPIRED_CERTS) {
718 rv = kmf_check_cert_date(kmfh, &certs[i]);
719 } else if (validity == KMF_EXPIRED_CERTS) {
720 rv = kmf_check_cert_date(kmfh, &certs[i]);
721 if (rv == KMF_OK)
722 rv = KMF_ERR_CERT_NOT_FOUND;
723 if (rv == KMF_ERR_VALIDITY_PERIOD)
724 rv = KMF_OK;
726 if (rv != KMF_OK) {
727 /* Remove this cert from the list by clearing it. */
728 kmf_free_data(&certs[i]);
729 } else {
730 hits++; /* count valid certs found */
732 rv = KMF_OK;
734 if (rv == KMF_OK && hits > 0) {
736 * Sort the list of certs by length to put the cleared ones
737 * at the end so they don't get accessed by the caller.
739 qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
740 *certlist = certs;
742 /* since we sorted the list, just return the number of hits */
743 *numcerts = hits;
744 } else {
745 if (rv == KMF_OK && hits == 0)
746 rv = KMF_ERR_CERT_NOT_FOUND;
747 if (certs != NULL) {
748 free(certs);
749 certs = NULL;
752 return (rv);
755 static KMF_RETURN
756 kmf_load_cert(KMF_HANDLE *kmfh,
757 char *issuer, char *subject, KMF_BIGINT *serial,
758 KMF_CERT_VALIDITY validity,
759 char *pathname,
760 KMF_DATA *cert)
762 KMF_RETURN rv = KMF_OK;
763 X509 *x509cert = NULL;
765 rv = load_X509cert(kmfh, issuer, subject, serial, pathname, &x509cert);
766 if (rv == KMF_OK && x509cert != NULL && cert != NULL) {
767 rv = ssl_cert2KMFDATA(kmfh, x509cert, cert);
768 if (rv != KMF_OK) {
769 goto cleanup;
771 if (validity == KMF_NONEXPIRED_CERTS) {
772 rv = kmf_check_cert_date(kmfh, cert);
773 } else if (validity == KMF_EXPIRED_CERTS) {
774 rv = kmf_check_cert_date(kmfh, cert);
775 if (rv == KMF_OK) {
777 * This is a valid cert so skip it.
779 rv = KMF_ERR_CERT_NOT_FOUND;
781 if (rv == KMF_ERR_VALIDITY_PERIOD) {
783 * We want to return success when we
784 * find an invalid cert.
786 rv = KMF_OK;
787 goto cleanup;
791 cleanup:
792 if (x509cert != NULL)
793 X509_free(x509cert);
795 return (rv);
798 static KMF_RETURN
799 readAltFormatPrivateKey(KMF_DATA *filedata, EVP_PKEY **pkey)
801 KMF_RETURN ret = KMF_OK;
802 KMF_RAW_RSA_KEY rsa;
803 BerElement *asn1 = NULL;
804 BerValue filebuf;
805 BerValue OID = { NULL, 0 };
806 BerValue *Mod = NULL, *PubExp = NULL;
807 BerValue *PriExp = NULL, *Prime1 = NULL, *Prime2 = NULL;
808 BerValue *Coef = NULL;
809 BIGNUM *D = NULL, *P = NULL, *Q = NULL, *COEF = NULL;
810 BIGNUM *Exp1 = NULL, *Exp2 = NULL, *pminus1 = NULL;
811 BIGNUM *qminus1 = NULL;
812 BN_CTX *ctx = NULL;
814 *pkey = NULL;
816 filebuf.bv_val = (char *)filedata->Data;
817 filebuf.bv_len = filedata->Length;
819 asn1 = kmfder_init(&filebuf);
820 if (asn1 == NULL) {
821 ret = KMF_ERR_MEMORY;
822 goto out;
825 if (kmfber_scanf(asn1, "{{Dn{IIIIII}}}",
826 &OID, &Mod, &PubExp, &PriExp, &Prime1,
827 &Prime2, &Coef) == -1) {
828 ret = KMF_ERR_ENCODING;
829 goto out;
833 * We have to derive the 2 Exponents using Bignumber math.
834 * Exp1 = PriExp mod (Prime1 - 1)
835 * Exp2 = PriExp mod (Prime2 - 1)
838 /* D = PrivateExponent */
839 D = BN_bin2bn((const uchar_t *)PriExp->bv_val, PriExp->bv_len, D);
840 if (D == NULL) {
841 ret = KMF_ERR_MEMORY;
842 goto out;
845 /* P = Prime1 (first prime factor of Modulus) */
846 P = BN_bin2bn((const uchar_t *)Prime1->bv_val, Prime1->bv_len, P);
847 if (D == NULL) {
848 ret = KMF_ERR_MEMORY;
849 goto out;
852 /* Q = Prime2 (second prime factor of Modulus) */
853 Q = BN_bin2bn((const uchar_t *)Prime2->bv_val, Prime2->bv_len, Q);
855 if ((ctx = BN_CTX_new()) == NULL) {
856 ret = KMF_ERR_MEMORY;
857 goto out;
860 /* Compute (P - 1) */
861 pminus1 = BN_new();
862 (void) BN_sub(pminus1, P, BN_value_one());
864 /* Exponent1 = D mod (P - 1) */
865 Exp1 = BN_new();
866 (void) BN_mod(Exp1, D, pminus1, ctx);
868 /* Compute (Q - 1) */
869 qminus1 = BN_new();
870 (void) BN_sub(qminus1, Q, BN_value_one());
872 /* Exponent2 = D mod (Q - 1) */
873 Exp2 = BN_new();
874 (void) BN_mod(Exp2, D, qminus1, ctx);
876 /* Coef = (Inverse Q) mod P */
877 COEF = BN_new();
878 (void) BN_mod_inverse(COEF, Q, P, ctx);
880 /* Convert back to KMF format */
881 (void) memset(&rsa, 0, sizeof (rsa));
883 if ((ret = sslBN2KMFBN(Exp1, &rsa.exp1)) != KMF_OK)
884 goto out;
885 if ((ret = sslBN2KMFBN(Exp2, &rsa.exp2)) != KMF_OK)
886 goto out;
887 if ((ret = sslBN2KMFBN(COEF, &rsa.coef)) != KMF_OK)
888 goto out;
890 rsa.mod.val = (uchar_t *)Mod->bv_val;
891 rsa.mod.len = Mod->bv_len;
893 rsa.pubexp.val = (uchar_t *)PubExp->bv_val;
894 rsa.pubexp.len = PubExp->bv_len;
896 rsa.priexp.val = (uchar_t *)PriExp->bv_val;
897 rsa.priexp.len = PriExp->bv_len;
899 rsa.prime1.val = (uchar_t *)Prime1->bv_val;
900 rsa.prime1.len = Prime1->bv_len;
902 rsa.prime2.val = (uchar_t *)Prime2->bv_val;
903 rsa.prime2.len = Prime2->bv_len;
905 *pkey = ImportRawRSAKey(&rsa);
906 out:
907 if (asn1 != NULL)
908 kmfber_free(asn1, 1);
910 if (OID.bv_val) {
911 free(OID.bv_val);
913 if (PriExp)
914 free(PriExp);
916 if (Mod)
917 free(Mod);
919 if (PubExp)
920 free(PubExp);
922 if (Coef) {
923 (void) memset(Coef->bv_val, 0, Coef->bv_len);
924 free(Coef->bv_val);
925 free(Coef);
927 if (Prime1)
928 free(Prime1);
929 if (Prime2)
930 free(Prime2);
932 if (ctx != NULL)
933 BN_CTX_free(ctx);
935 if (D)
936 BN_clear_free(D);
937 if (P)
938 BN_clear_free(P);
939 if (Q)
940 BN_clear_free(Q);
941 if (pminus1)
942 BN_clear_free(pminus1);
943 if (qminus1)
944 BN_clear_free(qminus1);
945 if (Exp1)
946 BN_clear_free(Exp1);
947 if (Exp2)
948 BN_clear_free(Exp2);
950 return (ret);
954 static EVP_PKEY *
955 openssl_load_key(KMF_HANDLE_T handle, const char *file)
957 BIO *keyfile = NULL;
958 EVP_PKEY *pkey = NULL;
959 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
960 KMF_ENCODE_FORMAT format;
961 KMF_RETURN rv;
962 KMF_DATA filedata;
964 if (file == NULL) {
965 return (NULL);
968 if (kmf_get_file_format((char *)file, &format) != KMF_OK)
969 return (NULL);
971 keyfile = BIO_new_file(file, "rb");
972 if (keyfile == NULL) {
973 goto end;
976 if (format == KMF_FORMAT_ASN1) {
977 pkey = d2i_PrivateKey_bio(keyfile, NULL);
978 if (pkey == NULL) {
980 (void) BIO_free(keyfile);
981 keyfile = NULL;
982 /* Try odd ASN.1 variations */
983 rv = kmf_read_input_file(kmfh, (char *)file,
984 &filedata);
985 if (rv == KMF_OK) {
986 (void) readAltFormatPrivateKey(&filedata,
987 &pkey);
988 kmf_free_data(&filedata);
991 } else if (format == KMF_FORMAT_PEM ||
992 format == KMF_FORMAT_PEM_KEYPAIR) {
993 pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
994 if (pkey == NULL) {
995 KMF_DATA derdata;
997 * Check if this is the alt. format
998 * RSA private key file.
1000 rv = kmf_read_input_file(kmfh, (char *)file,
1001 &filedata);
1002 if (rv == KMF_OK) {
1003 uchar_t *d = NULL;
1004 int len;
1005 rv = kmf_pem_to_der(filedata.Data,
1006 filedata.Length, &d, &len);
1007 if (rv == KMF_OK && d != NULL) {
1008 derdata.Data = d;
1009 derdata.Length = (size_t)len;
1010 (void) readAltFormatPrivateKey(
1011 &derdata, &pkey);
1012 free(d);
1014 kmf_free_data(&filedata);
1019 end:
1020 if (pkey == NULL)
1021 SET_ERROR(kmfh, ERR_get_error());
1023 if (keyfile != NULL)
1024 (void) BIO_free(keyfile);
1026 return (pkey);
1029 KMF_RETURN
1030 OpenSSL_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1032 KMF_RETURN rv = KMF_OK;
1033 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1034 int i, n;
1035 uint32_t maxcerts = 0;
1036 uint32_t *num_certs;
1037 KMF_X509_DER_CERT *kmf_cert = NULL;
1038 char *dirpath = NULL;
1039 char *filename = NULL;
1040 char *fullpath = NULL;
1041 char *issuer = NULL;
1042 char *subject = NULL;
1043 KMF_BIGINT *serial = NULL;
1044 KMF_CERT_VALIDITY validity;
1046 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1047 if (num_certs == NULL)
1048 return (KMF_ERR_BAD_PARAMETER);
1050 /* num_certs should reference the size of kmf_cert */
1051 maxcerts = *num_certs;
1052 if (maxcerts == 0)
1053 maxcerts = 0xFFFFFFFF;
1054 *num_certs = 0;
1056 /* Get the optional returned certificate list */
1057 kmf_cert = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist,
1058 numattr);
1061 * The dirpath attribute and the filename attribute can not be NULL
1062 * at the same time.
1064 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1065 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1066 numattr);
1068 fullpath = get_fullpath(dirpath, filename);
1069 if (fullpath == NULL)
1070 return (KMF_ERR_BAD_PARAMETER);
1072 /* Get optional search criteria attributes */
1073 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1074 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1075 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1076 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1077 &validity, NULL);
1078 if (rv != KMF_OK) {
1079 validity = KMF_ALL_CERTS;
1080 rv = KMF_OK;
1083 if (isdir(fullpath)) {
1084 DIR *dirp;
1085 struct dirent *dp;
1087 n = 0;
1088 /* open all files in the directory and attempt to read them */
1089 if ((dirp = opendir(fullpath)) == NULL) {
1090 return (KMF_ERR_BAD_PARAMETER);
1092 while ((dp = readdir(dirp)) != NULL) {
1093 char *fname;
1094 KMF_DATA *certlist = NULL;
1095 uint32_t loaded_certs = 0;
1097 if (strcmp(dp->d_name, ".") == 0 ||
1098 strcmp(dp->d_name, "..") == 0)
1099 continue;
1101 fname = get_fullpath(fullpath, (char *)&dp->d_name);
1103 rv = load_certs(kmfh, issuer, subject, serial,
1104 validity, fname, &certlist, &loaded_certs);
1106 if (rv != KMF_OK) {
1107 free(fname);
1108 if (certlist != NULL) {
1109 for (i = 0; i < loaded_certs; i++)
1110 kmf_free_data(&certlist[i]);
1111 free(certlist);
1113 continue;
1116 /* If load succeeds, add certdata to the list */
1117 if (kmf_cert != NULL) {
1118 for (i = 0; i < loaded_certs &&
1119 n < maxcerts; i++) {
1120 kmf_cert[n].certificate.Data =
1121 certlist[i].Data;
1122 kmf_cert[n].certificate.Length =
1123 certlist[i].Length;
1125 kmf_cert[n].kmf_private.keystore_type =
1126 KMF_KEYSTORE_OPENSSL;
1127 kmf_cert[n].kmf_private.flags =
1128 KMF_FLAG_CERT_VALID;
1129 kmf_cert[n].kmf_private.label =
1130 strdup(fname);
1131 n++;
1134 * If maxcerts < loaded_certs, clean up the
1135 * certs that were not used.
1137 for (; i < loaded_certs; i++)
1138 kmf_free_data(&certlist[i]);
1139 } else {
1140 for (i = 0; i < loaded_certs; i++)
1141 kmf_free_data(&certlist[i]);
1142 n += loaded_certs;
1144 free(certlist);
1145 free(fname);
1147 (*num_certs) = n;
1148 if (*num_certs == 0)
1149 rv = KMF_ERR_CERT_NOT_FOUND;
1150 if (*num_certs > 0)
1151 rv = KMF_OK;
1152 exit:
1153 (void) closedir(dirp);
1154 } else {
1155 KMF_DATA *certlist = NULL;
1156 uint32_t loaded_certs = 0;
1158 rv = load_certs(kmfh, issuer, subject, serial, validity,
1159 fullpath, &certlist, &loaded_certs);
1160 if (rv != KMF_OK) {
1161 free(fullpath);
1162 return (rv);
1165 n = 0;
1166 if (kmf_cert != NULL && certlist != NULL) {
1167 for (i = 0; i < loaded_certs && i < maxcerts; i++) {
1168 kmf_cert[n].certificate.Data =
1169 certlist[i].Data;
1170 kmf_cert[n].certificate.Length =
1171 certlist[i].Length;
1172 kmf_cert[n].kmf_private.keystore_type =
1173 KMF_KEYSTORE_OPENSSL;
1174 kmf_cert[n].kmf_private.flags =
1175 KMF_FLAG_CERT_VALID;
1176 kmf_cert[n].kmf_private.label =
1177 strdup(fullpath);
1178 n++;
1180 /* If maxcerts < loaded_certs, clean up */
1181 for (; i < loaded_certs; i++)
1182 kmf_free_data(&certlist[i]);
1183 } else if (certlist != NULL) {
1184 for (i = 0; i < loaded_certs; i++)
1185 kmf_free_data(&certlist[i]);
1186 n = loaded_certs;
1188 if (certlist != NULL)
1189 free(certlist);
1190 *num_certs = n;
1193 free(fullpath);
1195 return (rv);
1198 void
1199 /*ARGSUSED*/
1200 OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
1201 KMF_X509_DER_CERT *kmf_cert)
1203 if (kmf_cert != NULL) {
1204 if (kmf_cert->certificate.Data != NULL) {
1205 kmf_free_data(&kmf_cert->certificate);
1207 if (kmf_cert->kmf_private.label)
1208 free(kmf_cert->kmf_private.label);
1212 /*ARGSUSED*/
1213 KMF_RETURN
1214 OpenSSL_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1216 KMF_RETURN ret = KMF_OK;
1217 KMF_DATA *cert = NULL;
1218 char *outfilename = NULL;
1219 char *dirpath = NULL;
1220 char *fullpath = NULL;
1221 KMF_ENCODE_FORMAT format;
1223 /* Get the cert data */
1224 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1225 if (cert == NULL || cert->Data == NULL)
1226 return (KMF_ERR_BAD_PARAMETER);
1228 /* Check the output filename and directory attributes. */
1229 outfilename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1230 numattr);
1231 if (outfilename == NULL)
1232 return (KMF_ERR_BAD_PARAMETER);
1234 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1235 fullpath = get_fullpath(dirpath, outfilename);
1236 if (fullpath == NULL)
1237 return (KMF_ERR_BAD_CERTFILE);
1239 /* Check the optional format attribute */
1240 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1241 &format, NULL);
1242 if (ret != KMF_OK) {
1243 /* If there is no format attribute, then default to PEM */
1244 format = KMF_FORMAT_PEM;
1245 ret = KMF_OK;
1246 } else if (format != KMF_FORMAT_ASN1 && format != KMF_FORMAT_PEM) {
1247 ret = KMF_ERR_BAD_CERT_FORMAT;
1248 goto out;
1251 /* Store the certificate in the file with the specified format */
1252 ret = kmf_create_cert_file(cert, format, fullpath);
1254 out:
1255 if (fullpath != NULL)
1256 free(fullpath);
1258 return (ret);
1262 KMF_RETURN
1263 OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1265 KMF_RETURN rv;
1266 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1267 KMF_DATA certdata = {NULL, 0};
1268 char *dirpath = NULL;
1269 char *filename = NULL;
1270 char *fullpath = NULL;
1271 char *issuer = NULL;
1272 char *subject = NULL;
1273 KMF_BIGINT *serial = NULL;
1274 KMF_CERT_VALIDITY validity;
1277 * Get the DIRPATH and CERT_FILENAME attributes. They can not be
1278 * NULL at the same time.
1280 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1281 filename = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist,
1282 numattr);
1283 fullpath = get_fullpath(dirpath, filename);
1284 if (fullpath == NULL)
1285 return (KMF_ERR_BAD_PARAMETER);
1287 /* Get optional search criteria attributes */
1288 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1289 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1290 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1291 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
1292 &validity, NULL);
1293 if (rv != KMF_OK) {
1294 validity = KMF_ALL_CERTS;
1295 rv = KMF_OK;
1298 if (isdir(fullpath)) {
1299 DIR *dirp;
1300 struct dirent *dp;
1302 /* open all files in the directory and attempt to read them */
1303 if ((dirp = opendir(fullpath)) == NULL) {
1304 return (KMF_ERR_BAD_PARAMETER);
1307 while ((dp = readdir(dirp)) != NULL) {
1308 if (strcmp(dp->d_name, ".") != 0 &&
1309 strcmp(dp->d_name, "..") != 0) {
1310 char *fname;
1312 fname = get_fullpath(fullpath,
1313 (char *)&dp->d_name);
1315 if (fname == NULL) {
1316 rv = KMF_ERR_MEMORY;
1317 break;
1320 rv = kmf_load_cert(kmfh, issuer, subject,
1321 serial, validity, fname, &certdata);
1323 if (rv == KMF_ERR_CERT_NOT_FOUND) {
1324 free(fname);
1325 kmf_free_data(&certdata);
1326 rv = KMF_OK;
1327 continue;
1328 } else if (rv != KMF_OK) {
1329 free(fname);
1330 break;
1333 if (unlink(fname) != 0) {
1334 SET_SYS_ERROR(kmfh, errno);
1335 rv = KMF_ERR_INTERNAL;
1336 free(fname);
1337 break;
1339 free(fname);
1340 kmf_free_data(&certdata);
1343 (void) closedir(dirp);
1344 } else {
1345 /* Just try to load a single certificate */
1346 rv = kmf_load_cert(kmfh, issuer, subject, serial, validity,
1347 fullpath, &certdata);
1348 if (rv == KMF_OK) {
1349 if (unlink(fullpath) != 0) {
1350 SET_SYS_ERROR(kmfh, errno);
1351 rv = KMF_ERR_INTERNAL;
1356 out:
1357 if (fullpath != NULL)
1358 free(fullpath);
1360 kmf_free_data(&certdata);
1362 return (rv);
1365 KMF_RETURN
1366 OpenSSL_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1367 KMF_DATA *keydata)
1369 KMF_RETURN rv = KMF_OK;
1370 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1371 int n;
1373 if (key == NULL || keydata == NULL ||
1374 key->keyp == NULL)
1375 return (KMF_ERR_BAD_PARAMETER);
1377 if (key->keyalg == KMF_RSA) {
1378 RSA *pubkey = EVP_PKEY_get1_RSA(key->keyp);
1380 if (!(n = i2d_RSA_PUBKEY(pubkey, &keydata->Data))) {
1381 SET_ERROR(kmfh, ERR_get_error());
1382 return (KMF_ERR_ENCODING);
1384 RSA_free(pubkey);
1385 } else if (key->keyalg == KMF_DSA) {
1386 DSA *pubkey = EVP_PKEY_get1_DSA(key->keyp);
1388 if (!(n = i2d_DSA_PUBKEY(pubkey, &keydata->Data))) {
1389 SET_ERROR(kmfh, ERR_get_error());
1390 return (KMF_ERR_ENCODING);
1392 DSA_free(pubkey);
1393 } else {
1394 return (KMF_ERR_BAD_PARAMETER);
1396 keydata->Length = n;
1398 cleanup:
1399 if (rv != KMF_OK) {
1400 if (keydata->Data)
1401 free(keydata->Data);
1402 keydata->Data = NULL;
1403 keydata->Length = 0;
1406 return (rv);
1409 static KMF_RETURN
1410 ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out,
1411 KMF_CREDENTIAL *cred, EVP_PKEY *pkey, boolean_t private)
1413 int rv = 0;
1414 RSA *rsa;
1415 DSA *dsa;
1417 if (pkey == NULL || out == NULL)
1418 return (KMF_ERR_BAD_PARAMETER);
1420 switch (format) {
1421 case KMF_FORMAT_RAWKEY:
1422 /* same as ASN.1 */
1423 case KMF_FORMAT_ASN1:
1424 if (pkey->type == EVP_PKEY_RSA) {
1425 rsa = EVP_PKEY_get1_RSA(pkey);
1426 if (private)
1427 rv = i2d_RSAPrivateKey_bio(out, rsa);
1428 else
1429 rv = i2d_RSAPublicKey_bio(out, rsa);
1430 RSA_free(rsa);
1431 } else if (pkey->type == EVP_PKEY_DSA) {
1432 dsa = EVP_PKEY_get1_DSA(pkey);
1433 rv = i2d_DSAPrivateKey_bio(out, dsa);
1434 DSA_free(dsa);
1436 if (rv == 1) {
1437 rv = KMF_OK;
1438 } else {
1439 SET_ERROR(kmfh, rv);
1441 break;
1442 case KMF_FORMAT_PEM:
1443 if (pkey->type == EVP_PKEY_RSA) {
1444 rsa = EVP_PKEY_get1_RSA(pkey);
1445 if (private)
1446 rv = PEM_write_bio_RSAPrivateKey(out,
1447 rsa, NULL, NULL, 0, NULL,
1448 (cred != NULL ? cred->cred : NULL));
1449 else
1450 rv = PEM_write_bio_RSAPublicKey(out,
1451 rsa);
1452 RSA_free(rsa);
1453 } else if (pkey->type == EVP_PKEY_DSA) {
1454 dsa = EVP_PKEY_get1_DSA(pkey);
1455 rv = PEM_write_bio_DSAPrivateKey(out,
1456 dsa, NULL, NULL, 0, NULL,
1457 (cred != NULL ? cred->cred : NULL));
1458 DSA_free(dsa);
1461 if (rv == 1) {
1462 rv = KMF_OK;
1463 } else {
1464 SET_ERROR(kmfh, rv);
1466 break;
1468 default:
1469 rv = KMF_ERR_BAD_PARAMETER;
1472 return (rv);
1475 KMF_RETURN
1476 OpenSSL_CreateKeypair(KMF_HANDLE_T handle, int numattr,
1477 KMF_ATTRIBUTE *attrlist)
1479 KMF_RETURN rv = KMF_OK;
1480 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1481 uint32_t eValue = 0x010001;
1482 RSA *sslPrivKey = NULL;
1483 DSA *sslDSAKey = NULL;
1484 EVP_PKEY *eprikey = NULL;
1485 EVP_PKEY *epubkey = NULL;
1486 BIO *out = NULL;
1487 KMF_KEY_HANDLE *pubkey = NULL, *privkey = NULL;
1488 uint32_t keylen = 1024;
1489 uint32_t keylen_size = sizeof (uint32_t);
1490 boolean_t storekey = TRUE;
1491 KMF_KEY_ALG keytype = KMF_RSA;
1493 rv = kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
1494 &storekey, NULL);
1495 if (rv != KMF_OK) {
1496 /* "storekey" is optional. Default is TRUE */
1497 rv = KMF_OK;
1500 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1501 (void *)&keytype, NULL);
1502 if (rv != KMF_OK)
1503 /* keytype is optional. KMF_RSA is default */
1504 rv = KMF_OK;
1506 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
1507 if (pubkey == NULL)
1508 return (KMF_ERR_BAD_PARAMETER);
1510 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
1511 if (privkey == NULL)
1512 return (KMF_ERR_BAD_PARAMETER);
1514 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
1515 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
1517 eprikey = EVP_PKEY_new();
1518 if (eprikey == NULL) {
1519 SET_ERROR(kmfh, ERR_get_error());
1520 rv = KMF_ERR_KEYGEN_FAILED;
1521 goto cleanup;
1523 epubkey = EVP_PKEY_new();
1524 if (epubkey == NULL) {
1525 SET_ERROR(kmfh, ERR_get_error());
1526 rv = KMF_ERR_KEYGEN_FAILED;
1527 goto cleanup;
1529 if (keytype == KMF_RSA) {
1530 KMF_BIGINT *rsaexp = NULL;
1532 rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attrlist, numattr);
1533 if (rsaexp != NULL) {
1534 if (rsaexp->len > 0 &&
1535 rsaexp->len <= sizeof (eValue) &&
1536 rsaexp->val != NULL) {
1537 /* LINTED E_BAD_PTR_CAST_ALIGN */
1538 eValue = *(uint32_t *)rsaexp->val;
1539 } else {
1540 rv = KMF_ERR_BAD_PARAMETER;
1541 goto cleanup;
1543 } else {
1544 /* RSA Exponent is optional. Default is 0x10001 */
1545 rv = KMF_OK;
1548 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
1549 &keylen, &keylen_size);
1550 if (rv == KMF_ERR_ATTR_NOT_FOUND)
1551 /* keylen is optional, default is 1024 */
1552 rv = KMF_OK;
1553 if (rv != KMF_OK) {
1554 rv = KMF_ERR_BAD_PARAMETER;
1555 goto cleanup;
1558 sslPrivKey = RSA_generate_key(keylen, eValue, NULL, NULL);
1559 if (sslPrivKey == NULL) {
1560 SET_ERROR(kmfh, ERR_get_error());
1561 rv = KMF_ERR_KEYGEN_FAILED;
1562 } else {
1563 (void) EVP_PKEY_set1_RSA(eprikey, sslPrivKey);
1564 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1565 privkey->keyalg = KMF_RSA;
1566 privkey->keyclass = KMF_ASYM_PRI;
1567 privkey->israw = FALSE;
1568 privkey->keyp = (void *)eprikey;
1570 /* OpenSSL derives the public key from the private */
1571 (void) EVP_PKEY_set1_RSA(epubkey, sslPrivKey);
1572 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1573 pubkey->keyalg = KMF_RSA;
1574 pubkey->israw = FALSE;
1575 pubkey->keyclass = KMF_ASYM_PUB;
1576 pubkey->keyp = (void *)epubkey;
1578 } else if (keytype == KMF_DSA) {
1579 DSA *dp;
1580 sslDSAKey = DSA_new();
1581 if (sslDSAKey == NULL) {
1582 SET_ERROR(kmfh, ERR_get_error());
1583 return (KMF_ERR_MEMORY);
1586 if ((sslDSAKey->p = BN_bin2bn(P, sizeof (P), sslDSAKey->p)) ==
1587 NULL) {
1588 SET_ERROR(kmfh, ERR_get_error());
1589 rv = KMF_ERR_KEYGEN_FAILED;
1590 goto cleanup;
1592 if ((sslDSAKey->q = BN_bin2bn(Q, sizeof (Q), sslDSAKey->q)) ==
1593 NULL) {
1594 SET_ERROR(kmfh, ERR_get_error());
1595 rv = KMF_ERR_KEYGEN_FAILED;
1596 goto cleanup;
1598 if ((sslDSAKey->g = BN_bin2bn(G, sizeof (G), sslDSAKey->g)) ==
1599 NULL) {
1600 SET_ERROR(kmfh, ERR_get_error());
1601 rv = KMF_ERR_KEYGEN_FAILED;
1602 goto cleanup;
1605 if (!DSA_generate_key(sslDSAKey)) {
1606 SET_ERROR(kmfh, ERR_get_error());
1607 rv = KMF_ERR_KEYGEN_FAILED;
1608 goto cleanup;
1611 privkey->kstype = KMF_KEYSTORE_OPENSSL;
1612 privkey->keyalg = KMF_DSA;
1613 privkey->keyclass = KMF_ASYM_PRI;
1614 privkey->israw = FALSE;
1615 if (EVP_PKEY_set1_DSA(eprikey, sslDSAKey)) {
1616 privkey->keyp = (void *)eprikey;
1617 } else {
1618 SET_ERROR(kmfh, ERR_get_error());
1619 rv = KMF_ERR_KEYGEN_FAILED;
1620 goto cleanup;
1622 dp = DSA_new();
1623 /* Make a copy for the public key */
1624 if (dp != NULL) {
1625 if ((dp->p = BN_new()) == NULL) {
1626 SET_ERROR(kmfh, ERR_get_error());
1627 rv = KMF_ERR_MEMORY;
1628 DSA_free(dp);
1629 goto cleanup;
1631 if ((dp->q = BN_new()) == NULL) {
1632 SET_ERROR(kmfh, ERR_get_error());
1633 rv = KMF_ERR_MEMORY;
1634 BN_free(dp->p);
1635 DSA_free(dp);
1636 goto cleanup;
1638 if ((dp->g = BN_new()) == NULL) {
1639 SET_ERROR(kmfh, ERR_get_error());
1640 rv = KMF_ERR_MEMORY;
1641 BN_free(dp->q);
1642 BN_free(dp->p);
1643 DSA_free(dp);
1644 goto cleanup;
1646 if ((dp->pub_key = BN_new()) == NULL) {
1647 SET_ERROR(kmfh, ERR_get_error());
1648 rv = KMF_ERR_MEMORY;
1649 BN_free(dp->q);
1650 BN_free(dp->p);
1651 BN_free(dp->g);
1652 DSA_free(dp);
1653 goto cleanup;
1655 (void) BN_copy(dp->p, sslDSAKey->p);
1656 (void) BN_copy(dp->q, sslDSAKey->q);
1657 (void) BN_copy(dp->g, sslDSAKey->g);
1658 (void) BN_copy(dp->pub_key, sslDSAKey->pub_key);
1660 pubkey->kstype = KMF_KEYSTORE_OPENSSL;
1661 pubkey->keyalg = KMF_DSA;
1662 pubkey->keyclass = KMF_ASYM_PUB;
1663 pubkey->israw = FALSE;
1665 if (EVP_PKEY_set1_DSA(epubkey, sslDSAKey)) {
1666 pubkey->keyp = (void *)epubkey;
1667 } else {
1668 SET_ERROR(kmfh, ERR_get_error());
1669 rv = KMF_ERR_KEYGEN_FAILED;
1670 goto cleanup;
1675 if (rv != KMF_OK) {
1676 goto cleanup;
1679 if (storekey) {
1680 KMF_ATTRIBUTE storeattrs[4]; /* max. 4 attributes needed */
1681 int i = 0;
1682 char *keyfile = NULL, *dirpath = NULL;
1683 KMF_ENCODE_FORMAT format;
1685 * Construct a new attribute arrray and call openssl_store_key
1687 kmf_set_attr_at_index(storeattrs, i, KMF_PRIVKEY_HANDLE_ATTR,
1688 privkey, sizeof (privkey));
1689 i++;
1691 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
1692 if (dirpath != NULL) {
1693 storeattrs[i].type = KMF_DIRPATH_ATTR;
1694 storeattrs[i].pValue = dirpath;
1695 storeattrs[i].valueLen = strlen(dirpath);
1696 i++;
1697 } else {
1698 rv = KMF_OK; /* DIRPATH is optional */
1700 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR,
1701 attrlist, numattr);
1702 if (keyfile != NULL) {
1703 storeattrs[i].type = KMF_KEY_FILENAME_ATTR;
1704 storeattrs[i].pValue = keyfile;
1705 storeattrs[i].valueLen = strlen(keyfile);
1706 i++;
1707 } else {
1708 goto cleanup; /* KEYFILE is required */
1710 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
1711 (void *)&format, NULL);
1712 if (rv == KMF_OK) {
1713 storeattrs[i].type = KMF_ENCODE_FORMAT_ATTR;
1714 storeattrs[i].pValue = &format;
1715 storeattrs[i].valueLen = sizeof (format);
1716 i++;
1719 rv = OpenSSL_StoreKey(handle, i, storeattrs);
1722 cleanup:
1723 if (rv != KMF_OK) {
1724 if (eprikey != NULL)
1725 EVP_PKEY_free(eprikey);
1727 if (epubkey != NULL)
1728 EVP_PKEY_free(epubkey);
1730 if (pubkey->keylabel) {
1731 free(pubkey->keylabel);
1732 pubkey->keylabel = NULL;
1735 if (privkey->keylabel) {
1736 free(privkey->keylabel);
1737 privkey->keylabel = NULL;
1740 pubkey->keyp = NULL;
1741 privkey->keyp = NULL;
1744 if (sslPrivKey)
1745 RSA_free(sslPrivKey);
1747 if (sslDSAKey)
1748 DSA_free(sslDSAKey);
1750 if (out != NULL)
1751 (void) BIO_free(out);
1753 return (rv);
1757 * Make sure the BN conversion is properly padded with 0x00
1758 * bytes. If not, signature verification for DSA signatures
1759 * may fail in the case where the bignum value does not use
1760 * all of the bits.
1762 static int
1763 fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
1764 int bytes = len - BN_num_bytes(bn);
1766 /* prepend with leading 0x00 if necessary */
1767 while (bytes-- > 0)
1768 *buf++ = 0;
1770 (void) BN_bn2bin(bn, buf);
1772 * Return the desired length since we prepended it
1773 * with the necessary 0x00 padding.
1775 return (len);
1778 KMF_RETURN
1779 OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1780 KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
1782 KMF_RETURN ret = KMF_OK;
1783 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1784 KMF_ALGORITHM_INDEX AlgId;
1785 EVP_MD_CTX ctx;
1786 const EVP_MD *md;
1788 if (key == NULL || AlgOID == NULL ||
1789 tobesigned == NULL || output == NULL ||
1790 tobesigned->Data == NULL ||
1791 output->Data == NULL)
1792 return (KMF_ERR_BAD_PARAMETER);
1794 /* Map the OID to an OpenSSL algorithm */
1795 AlgId = x509_algoid_to_algid(AlgOID);
1796 if (AlgId == KMF_ALGID_NONE)
1797 return (KMF_ERR_BAD_ALGORITHM);
1799 if (key->keyalg == KMF_RSA) {
1800 EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
1801 uchar_t *p;
1802 int len;
1803 if (AlgId == KMF_ALGID_MD5WithRSA)
1804 md = EVP_md5();
1805 else if (AlgId == KMF_ALGID_MD2WithRSA)
1806 md = EVP_md2();
1807 else if (AlgId == KMF_ALGID_SHA1WithRSA)
1808 md = EVP_sha1();
1809 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1810 md = EVP_sha256();
1811 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1812 md = EVP_sha384();
1813 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1814 md = EVP_sha512();
1815 else if (AlgId == KMF_ALGID_RSA)
1816 md = NULL;
1817 else
1818 return (KMF_ERR_BAD_ALGORITHM);
1820 if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1821 RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1823 p = output->Data;
1824 if ((len = RSA_private_encrypt(tobesigned->Length,
1825 tobesigned->Data, p, rsa,
1826 RSA_PKCS1_PADDING)) <= 0) {
1827 SET_ERROR(kmfh, ERR_get_error());
1828 ret = KMF_ERR_INTERNAL;
1830 output->Length = len;
1831 } else {
1832 (void) EVP_MD_CTX_init(&ctx);
1833 (void) EVP_SignInit_ex(&ctx, md, NULL);
1834 (void) EVP_SignUpdate(&ctx, tobesigned->Data,
1835 (uint32_t)tobesigned->Length);
1836 len = (uint32_t)output->Length;
1837 p = output->Data;
1838 if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
1839 SET_ERROR(kmfh, ERR_get_error());
1840 len = 0;
1841 ret = KMF_ERR_INTERNAL;
1843 output->Length = len;
1844 (void) EVP_MD_CTX_cleanup(&ctx);
1846 } else if (key->keyalg == KMF_DSA) {
1847 DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1849 uchar_t hash[EVP_MAX_MD_SIZE];
1850 uint32_t hashlen;
1851 DSA_SIG *dsasig;
1853 if (AlgId == KMF_ALGID_DSA ||
1854 AlgId == KMF_ALGID_SHA1WithDSA)
1855 md = EVP_sha1();
1856 else if (AlgId == KMF_ALGID_SHA256WithDSA)
1857 md = EVP_sha256();
1858 else /* Bad algorithm */
1859 return (KMF_ERR_BAD_ALGORITHM);
1862 * OpenSSL EVP_Sign operation automatically converts to
1863 * ASN.1 output so we do the operations separately so we
1864 * are assured of NOT getting ASN.1 output returned.
1865 * KMF does not want ASN.1 encoded results because
1866 * not all mechanisms return ASN.1 encodings (PKCS#11
1867 * and NSS return raw signature data).
1869 EVP_MD_CTX_init(&ctx);
1870 (void) EVP_DigestInit_ex(&ctx, md, NULL);
1871 (void) EVP_DigestUpdate(&ctx, tobesigned->Data,
1872 tobesigned->Length);
1873 (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
1875 /* Only sign first 20 bytes for SHA2 */
1876 if (AlgId == KMF_ALGID_SHA256WithDSA)
1877 hashlen = 20;
1878 dsasig = DSA_do_sign(hash, hashlen, dsa);
1879 if (dsasig != NULL) {
1880 int i;
1881 output->Length = i = fixbnlen(dsasig->r, output->Data,
1882 hashlen);
1884 output->Length += fixbnlen(dsasig->s, &output->Data[i],
1885 hashlen);
1887 DSA_SIG_free(dsasig);
1888 } else {
1889 SET_ERROR(kmfh, ERR_get_error());
1891 (void) EVP_MD_CTX_cleanup(&ctx);
1892 } else {
1893 return (KMF_ERR_BAD_PARAMETER);
1895 cleanup:
1896 return (ret);
1899 KMF_RETURN
1900 /*ARGSUSED*/
1901 OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1902 int numattr, KMF_ATTRIBUTE *attrlist)
1904 KMF_RETURN rv = KMF_OK;
1905 KMF_KEY_HANDLE *key;
1906 boolean_t destroy = B_TRUE;
1908 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1909 if (key == NULL || key->keyp == NULL)
1910 return (KMF_ERR_BAD_PARAMETER);
1912 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1913 (void *)&destroy, NULL);
1914 if (rv != KMF_OK) {
1915 /* "destroy" is optional. Default is TRUE */
1916 rv = KMF_OK;
1919 if (key->keyclass != KMF_ASYM_PUB &&
1920 key->keyclass != KMF_ASYM_PRI &&
1921 key->keyclass != KMF_SYMMETRIC)
1922 return (KMF_ERR_BAD_KEY_CLASS);
1924 if (key->keyclass == KMF_SYMMETRIC) {
1925 kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1926 key->keyp = NULL;
1927 } else {
1928 if (key->keyp != NULL) {
1929 EVP_PKEY_free(key->keyp);
1930 key->keyp = NULL;
1934 if (key->keylabel != NULL) {
1935 EVP_PKEY *pkey = NULL;
1936 /* If the file exists, make sure it is a proper key. */
1937 pkey = openssl_load_key(handle, key->keylabel);
1938 if (pkey == NULL) {
1939 if (key->keylabel != NULL) {
1940 free(key->keylabel);
1941 key->keylabel = NULL;
1943 return (KMF_ERR_KEY_NOT_FOUND);
1945 EVP_PKEY_free(pkey);
1947 if (destroy) {
1948 if (unlink(key->keylabel) != 0) {
1949 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1950 SET_SYS_ERROR(kmfh, errno);
1951 rv = KMF_ERR_INTERNAL;
1954 if (key->keylabel != NULL) {
1955 free(key->keylabel);
1956 key->keylabel = NULL;
1959 return (rv);
1962 KMF_RETURN
1963 OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1965 KMF_RETURN ret = KMF_OK;
1966 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1967 char str[256]; /* OpenSSL needs at least 120 byte buffer */
1969 ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1970 if (strlen(str)) {
1971 *msgstr = (char *)strdup(str);
1972 if ((*msgstr) == NULL)
1973 ret = KMF_ERR_MEMORY;
1974 } else {
1975 *msgstr = NULL;
1978 return (ret);
1981 static int
1982 ext2NID(int kmfext)
1984 switch (kmfext) {
1985 case KMF_X509_EXT_KEY_USAGE:
1986 return (NID_key_usage);
1987 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1988 return (NID_private_key_usage_period);
1989 case KMF_X509_EXT_CERT_POLICIES:
1990 return (NID_certificate_policies);
1991 case KMF_X509_EXT_SUBJ_ALTNAME:
1992 return (NID_subject_alt_name);
1993 case KMF_X509_EXT_ISSUER_ALTNAME:
1994 return (NID_issuer_alt_name);
1995 case KMF_X509_EXT_BASIC_CONSTRAINTS:
1996 return (NID_basic_constraints);
1997 case KMF_X509_EXT_EXT_KEY_USAGE:
1998 return (NID_ext_key_usage);
1999 case KMF_X509_EXT_AUTH_KEY_ID:
2000 return (NID_authority_key_identifier);
2001 case KMF_X509_EXT_CRL_DIST_POINTS:
2002 return (NID_crl_distribution_points);
2003 case KMF_X509_EXT_SUBJ_KEY_ID:
2004 return (NID_subject_key_identifier);
2005 case KMF_X509_EXT_POLICY_MAPPINGS:
2006 return (OBJ_sn2nid("policyMappings"));
2007 case KMF_X509_EXT_NAME_CONSTRAINTS:
2008 return (OBJ_sn2nid("nameConstraints"));
2009 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2010 return (OBJ_sn2nid("policyConstraints"));
2011 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2012 return (OBJ_sn2nid("inhibitAnyPolicy"));
2013 case KMF_X509_EXT_FRESHEST_CRL:
2014 return (OBJ_sn2nid("freshestCRL"));
2015 default:
2016 return (NID_undef);
2020 KMF_RETURN
2021 OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2022 KMF_PRINTABLE_ITEM flag, char *resultStr)
2024 KMF_RETURN ret = KMF_OK;
2025 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2026 X509 *xcert = NULL;
2027 unsigned char *outbuf = NULL;
2028 unsigned char *outbuf_p;
2029 char *tmpstr = NULL;
2030 int j;
2031 int ext_index, nid, len;
2032 BIO *mem = NULL;
2033 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2034 STACK *emlst = NULL;
2035 #else
2036 STACK_OF(OPENSSL_STRING) *emlst = NULL;
2037 #endif
2038 X509_EXTENSION *ex;
2039 X509_CINF *ci;
2041 if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2042 return (KMF_ERR_BAD_PARAMETER);
2045 /* copy cert data to outbuf */
2046 outbuf = malloc(pcert->Length);
2047 if (outbuf == NULL) {
2048 return (KMF_ERR_MEMORY);
2050 (void) memcpy(outbuf, pcert->Data, pcert->Length);
2052 outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2053 xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2054 if (xcert == NULL) {
2055 SET_ERROR(kmfh, ERR_get_error());
2056 ret = KMF_ERR_ENCODING;
2057 goto out;
2060 mem = BIO_new(BIO_s_mem());
2061 if (mem == NULL) {
2062 SET_ERROR(kmfh, ERR_get_error());
2063 ret = KMF_ERR_MEMORY;
2064 goto out;
2067 switch (flag) {
2068 case KMF_CERT_ISSUER:
2069 (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2070 XN_FLAG_SEP_CPLUS_SPC);
2071 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2072 break;
2074 case KMF_CERT_SUBJECT:
2075 (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2076 XN_FLAG_SEP_CPLUS_SPC);
2077 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2078 break;
2080 case KMF_CERT_VERSION:
2081 tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
2082 (void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
2083 OPENSSL_free(tmpstr);
2084 len = strlen(resultStr);
2085 break;
2087 case KMF_CERT_SERIALNUM:
2088 if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2089 (void) strcpy(resultStr, "0x");
2090 len = BIO_gets(mem, &resultStr[2],
2091 KMF_CERT_PRINTABLE_LEN - 2);
2093 break;
2095 case KMF_CERT_NOTBEFORE:
2096 (void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
2097 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2098 break;
2100 case KMF_CERT_NOTAFTER:
2101 (void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
2102 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2103 break;
2105 case KMF_CERT_PUBKEY_DATA:
2107 EVP_PKEY *pkey = X509_get_pubkey(xcert);
2108 if (pkey == NULL) {
2109 SET_ERROR(kmfh, ERR_get_error());
2110 ret = KMF_ERR_ENCODING;
2111 goto out;
2114 if (pkey->type == EVP_PKEY_RSA) {
2115 (void) BIO_printf(mem,
2116 "RSA Public Key: (%d bit)\n",
2117 BN_num_bits(pkey->pkey.rsa->n));
2118 (void) RSA_print(mem, pkey->pkey.rsa, 0);
2119 } else if (pkey->type == EVP_PKEY_DSA) {
2120 (void) BIO_printf(mem,
2121 "%12sDSA Public Key:\n", "");
2122 (void) DSA_print(mem, pkey->pkey.dsa, 0);
2123 } else {
2124 (void) BIO_printf(mem,
2125 "%12sUnknown Public Key:\n", "");
2127 (void) BIO_printf(mem, "\n");
2128 EVP_PKEY_free(pkey);
2130 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2131 break;
2132 case KMF_CERT_SIGNATURE_ALG:
2133 case KMF_CERT_PUBKEY_ALG:
2134 if (flag == KMF_CERT_SIGNATURE_ALG) {
2135 len = i2a_ASN1_OBJECT(mem,
2136 xcert->sig_alg->algorithm);
2137 } else {
2138 len = i2a_ASN1_OBJECT(mem,
2139 xcert->cert_info->key->algor->algorithm);
2142 if (len > 0) {
2143 len = BIO_read(mem, resultStr,
2144 KMF_CERT_PRINTABLE_LEN);
2146 break;
2148 case KMF_CERT_EMAIL:
2149 emlst = X509_get1_email(xcert);
2150 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2151 for (j = 0; j < sk_num(emlst); j++)
2152 (void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2153 #else
2154 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2155 (void) BIO_printf(mem, "%s\n",
2156 sk_OPENSSL_STRING_value(emlst, j));
2157 #endif
2159 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2160 X509_email_free(emlst);
2161 break;
2162 case KMF_X509_EXT_ISSUER_ALTNAME:
2163 case KMF_X509_EXT_SUBJ_ALTNAME:
2164 case KMF_X509_EXT_KEY_USAGE:
2165 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2166 case KMF_X509_EXT_CERT_POLICIES:
2167 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2168 case KMF_X509_EXT_NAME_CONSTRAINTS:
2169 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2170 case KMF_X509_EXT_EXT_KEY_USAGE:
2171 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2172 case KMF_X509_EXT_AUTH_KEY_ID:
2173 case KMF_X509_EXT_SUBJ_KEY_ID:
2174 case KMF_X509_EXT_POLICY_MAPPINGS:
2175 case KMF_X509_EXT_CRL_DIST_POINTS:
2176 case KMF_X509_EXT_FRESHEST_CRL:
2177 nid = ext2NID(flag);
2178 if (nid == NID_undef) {
2179 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2180 goto out;
2182 ci = xcert->cert_info;
2184 ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
2185 if (ext_index == -1) {
2186 SET_ERROR(kmfh, ERR_get_error());
2188 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2189 goto out;
2191 ex = X509v3_get_ext(ci->extensions, ext_index);
2193 (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2195 if (BIO_printf(mem, ": %s\n",
2196 X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2197 SET_ERROR(kmfh, ERR_get_error());
2198 ret = KMF_ERR_ENCODING;
2199 goto out;
2201 if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2202 (void) BIO_printf(mem, "%*s", 4, "");
2203 (void) M_ASN1_OCTET_STRING_print(mem, ex->value);
2205 if (BIO_write(mem, "\n", 1) <= 0) {
2206 SET_ERROR(kmfh, ERR_get_error());
2207 ret = KMF_ERR_ENCODING;
2208 goto out;
2210 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2212 if (len <= 0) {
2213 SET_ERROR(kmfh, ERR_get_error());
2214 ret = KMF_ERR_ENCODING;
2217 out:
2218 if (outbuf != NULL) {
2219 free(outbuf);
2222 if (xcert != NULL) {
2223 X509_free(xcert);
2226 if (mem != NULL) {
2227 (void) BIO_free(mem);
2230 return (ret);
2233 KMF_RETURN
2234 /*ARGSUSED*/
2235 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2236 KMF_ATTRIBUTE *attrlist)
2238 KMF_RETURN rv = KMF_OK;
2239 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2240 KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2241 KMF_KEY_HANDLE *key = NULL;
2242 uint32_t numkeys = 1; /* 1 key only */
2243 char *dirpath = NULL;
2244 char *keyfile = NULL;
2245 KMF_ATTRIBUTE new_attrlist[16];
2246 int i = 0;
2249 * This is really just a FindKey operation, reuse the
2250 * FindKey function.
2252 kmf_set_attr_at_index(new_attrlist, i,
2253 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2254 i++;
2256 kmf_set_attr_at_index(new_attrlist, i,
2257 KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2258 i++;
2260 kmf_set_attr_at_index(new_attrlist, i,
2261 KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2262 i++;
2264 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2265 if (key == NULL) {
2266 return (KMF_ERR_BAD_PARAMETER);
2267 } else {
2268 kmf_set_attr_at_index(new_attrlist, i,
2269 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2270 i++;
2273 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2274 if (dirpath != NULL) {
2275 kmf_set_attr_at_index(new_attrlist, i,
2276 KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2277 i++;
2280 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2281 if (keyfile == NULL)
2282 return (KMF_ERR_BAD_PARAMETER);
2283 else {
2284 kmf_set_attr_at_index(new_attrlist, i,
2285 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2286 i++;
2289 rv = OpenSSL_FindKey(handle, i, new_attrlist);
2290 return (rv);
2293 KMF_RETURN
2294 /*ARGSUSED*/
2295 OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2296 KMF_OID *AlgOID, KMF_DATA *ciphertext,
2297 KMF_DATA *output)
2299 KMF_RETURN ret = KMF_OK;
2300 RSA *rsa = NULL;
2301 unsigned int in_len = 0, out_len = 0;
2302 unsigned int total_decrypted = 0, modulus_len = 0;
2303 uint8_t *in_data, *out_data;
2304 int i, blocks;
2306 if (key == NULL || AlgOID == NULL ||
2307 ciphertext == NULL || output == NULL ||
2308 ciphertext->Data == NULL ||
2309 output->Data == NULL)
2310 return (KMF_ERR_BAD_PARAMETER);
2312 if (key->keyalg == KMF_RSA) {
2313 rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2314 modulus_len = RSA_size(rsa);
2315 } else {
2316 return (KMF_ERR_BAD_PARAMETER);
2319 blocks = ciphertext->Length/modulus_len;
2320 out_data = output->Data;
2321 in_data = ciphertext->Data;
2322 out_len = modulus_len - 11;
2323 in_len = modulus_len;
2325 for (i = 0; i < blocks; i++) {
2326 out_len = RSA_private_decrypt(in_len,
2327 in_data, out_data, rsa, RSA_PKCS1_PADDING);
2329 if (out_len == 0) {
2330 ret = KMF_ERR_INTERNAL;
2331 goto cleanup;
2334 out_data += out_len;
2335 total_decrypted += out_len;
2336 in_data += in_len;
2339 output->Length = total_decrypted;
2341 cleanup:
2342 RSA_free(rsa);
2343 if (ret != KMF_OK)
2344 output->Length = 0;
2346 return (ret);
2351 * This function will create a certid from issuer_cert and user_cert.
2352 * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2353 * certid memory after use.
2355 static KMF_RETURN
2356 create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2357 const KMF_DATA *user_cert, OCSP_CERTID **certid)
2359 KMF_RETURN ret = KMF_OK;
2360 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2361 X509 *issuer = NULL;
2362 X509 *cert = NULL;
2363 unsigned char *ptmp;
2365 if (issuer_cert == NULL || user_cert == NULL) {
2366 return (KMF_ERR_BAD_PARAMETER);
2369 /* convert the DER-encoded issuer cert to an internal X509 */
2370 ptmp = issuer_cert->Data;
2371 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2372 issuer_cert->Length);
2373 if (issuer == NULL) {
2374 SET_ERROR(kmfh, ERR_get_error());
2375 ret = KMF_ERR_OCSP_BAD_ISSUER;
2376 goto end;
2379 /* convert the DER-encoded user cert to an internal X509 */
2380 ptmp = user_cert->Data;
2381 cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2382 user_cert->Length);
2383 if (cert == NULL) {
2384 SET_ERROR(kmfh, ERR_get_error());
2386 ret = KMF_ERR_OCSP_BAD_CERT;
2387 goto end;
2390 /* create a CERTID */
2391 *certid = OCSP_cert_to_id(NULL, cert, issuer);
2392 if (*certid == NULL) {
2393 SET_ERROR(kmfh, ERR_get_error());
2394 ret = KMF_ERR_OCSP_CERTID;
2395 goto end;
2398 end:
2399 if (issuer != NULL) {
2400 X509_free(issuer);
2403 if (cert != NULL) {
2404 X509_free(cert);
2407 return (ret);
2410 KMF_RETURN
2411 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2412 int numattr, KMF_ATTRIBUTE *attrlist)
2414 KMF_RETURN ret = KMF_OK;
2415 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2416 OCSP_CERTID *id = NULL;
2417 OCSP_REQUEST *req = NULL;
2418 BIO *derbio = NULL;
2419 char *reqfile;
2420 KMF_DATA *issuer_cert;
2421 KMF_DATA *user_cert;
2423 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2424 attrlist, numattr);
2425 if (user_cert == NULL)
2426 return (KMF_ERR_BAD_PARAMETER);
2428 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2429 attrlist, numattr);
2430 if (issuer_cert == NULL)
2431 return (KMF_ERR_BAD_PARAMETER);
2433 reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2434 attrlist, numattr);
2435 if (reqfile == NULL)
2436 return (KMF_ERR_BAD_PARAMETER);
2438 ret = create_certid(handle, issuer_cert, user_cert, &id);
2439 if (ret != KMF_OK) {
2440 return (ret);
2443 /* Create an OCSP request */
2444 req = OCSP_REQUEST_new();
2445 if (req == NULL) {
2446 SET_ERROR(kmfh, ERR_get_error());
2447 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2448 goto end;
2451 if (!OCSP_request_add0_id(req, id)) {
2452 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2453 goto end;
2456 /* Write the request to the output file with DER encoding */
2457 derbio = BIO_new_file(reqfile, "wb");
2458 if (!derbio) {
2459 SET_ERROR(kmfh, ERR_get_error());
2460 ret = KMF_ERR_OPEN_FILE;
2461 goto end;
2463 if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2464 ret = KMF_ERR_ENCODING;
2467 end:
2469 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2470 * will also deallocate certid's space.
2472 if (req != NULL) {
2473 OCSP_REQUEST_free(req);
2476 if (derbio != NULL) {
2477 (void) BIO_free(derbio);
2480 return (ret);
2483 /* ocsp_find_signer_sk() is copied from openssl source */
2484 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
2486 int i;
2487 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2489 /* Easy if lookup by name */
2490 if (id->type == V_OCSP_RESPID_NAME)
2491 return (X509_find_by_subject(certs, id->value.byName));
2493 /* Lookup by key hash */
2495 /* If key hash isn't SHA1 length then forget it */
2496 if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2497 return (NULL);
2499 keyhash = id->value.byKey->data;
2500 /* Calculate hash of each key and compare */
2501 for (i = 0; i < sk_X509_num(certs); i++) {
2502 X509 *x = sk_X509_value(certs, i);
2503 /* Use pubkey_digest to get the key ID value */
2504 (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2505 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2506 return (x);
2508 return (NULL);
2511 /* ocsp_find_signer() is copied from openssl source */
2512 /* ARGSUSED2 */
2513 static int
2514 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2515 X509_STORE *st, unsigned long flags)
2517 X509 *signer;
2518 OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2519 if ((signer = ocsp_find_signer_sk(certs, rid))) {
2520 *psigner = signer;
2521 return (2);
2523 if (!(flags & OCSP_NOINTERN) &&
2524 (signer = ocsp_find_signer_sk(bs->certs, rid))) {
2525 *psigner = signer;
2526 return (1);
2528 /* Maybe lookup from store if by subject name */
2530 *psigner = NULL;
2531 return (0);
2535 * This function will verify the signature of a basic response, using
2536 * the public key from the OCSP responder certificate.
2538 static KMF_RETURN
2539 check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2540 KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2542 KMF_RETURN ret = KMF_OK;
2543 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2544 STACK_OF(X509) *cert_stack = NULL;
2545 X509 *signer = NULL;
2546 X509 *issuer = NULL;
2547 EVP_PKEY *skey = NULL;
2548 unsigned char *ptmp;
2551 if (bs == NULL || issuer_cert == NULL)
2552 return (KMF_ERR_BAD_PARAMETER);
2555 * Find the certificate that signed the basic response.
2557 * If signer_cert is not NULL, we will use that as the signer cert.
2558 * Otherwise, we will check if the issuer cert is actually the signer.
2559 * If we still do not find a signer, we will look for it from the
2560 * certificate list came with the response file.
2562 if (signer_cert != NULL) {
2563 ptmp = signer_cert->Data;
2564 signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2565 signer_cert->Length);
2566 if (signer == NULL) {
2567 SET_ERROR(kmfh, ERR_get_error());
2568 ret = KMF_ERR_OCSP_BAD_SIGNER;
2569 goto end;
2571 } else {
2573 * Convert the issuer cert into X509 and push it into a
2574 * stack to be used by ocsp_find_signer().
2576 ptmp = issuer_cert->Data;
2577 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2578 issuer_cert->Length);
2579 if (issuer == NULL) {
2580 SET_ERROR(kmfh, ERR_get_error());
2581 ret = KMF_ERR_OCSP_BAD_ISSUER;
2582 goto end;
2585 if ((cert_stack = sk_X509_new_null()) == NULL) {
2586 ret = KMF_ERR_INTERNAL;
2587 goto end;
2590 if (sk_X509_push(cert_stack, issuer) == NULL) {
2591 ret = KMF_ERR_INTERNAL;
2592 goto end;
2595 ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2596 if (!ret) {
2597 /* can not find the signer */
2598 ret = KMF_ERR_OCSP_BAD_SIGNER;
2599 goto end;
2603 /* Verify the signature of the response */
2604 skey = X509_get_pubkey(signer);
2605 if (skey == NULL) {
2606 ret = KMF_ERR_OCSP_BAD_SIGNER;
2607 goto end;
2610 ret = OCSP_BASICRESP_verify(bs, skey, 0);
2611 if (ret == 0) {
2612 ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2613 goto end;
2616 end:
2617 if (issuer != NULL) {
2618 X509_free(issuer);
2621 if (signer != NULL) {
2622 X509_free(signer);
2625 if (skey != NULL) {
2626 EVP_PKEY_free(skey);
2629 if (cert_stack != NULL) {
2630 sk_X509_free(cert_stack);
2633 return (ret);
2638 KMF_RETURN
2639 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2640 int numattr, KMF_ATTRIBUTE *attrlist)
2642 KMF_RETURN ret = KMF_OK;
2643 BIO *derbio = NULL;
2644 OCSP_RESPONSE *resp = NULL;
2645 OCSP_BASICRESP *bs = NULL;
2646 OCSP_CERTID *id = NULL;
2647 OCSP_SINGLERESP *single = NULL;
2648 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2649 int index, status, reason;
2650 KMF_DATA *issuer_cert;
2651 KMF_DATA *user_cert;
2652 KMF_DATA *signer_cert;
2653 KMF_DATA *response;
2654 int *response_reason, *response_status, *cert_status;
2655 boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
2656 uint32_t response_lifetime;
2658 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2659 attrlist, numattr);
2660 if (issuer_cert == NULL)
2661 return (KMF_ERR_BAD_PARAMETER);
2663 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2664 attrlist, numattr);
2665 if (user_cert == NULL)
2666 return (KMF_ERR_BAD_PARAMETER);
2668 response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2669 attrlist, numattr);
2670 if (response == NULL)
2671 return (KMF_ERR_BAD_PARAMETER);
2673 response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2674 attrlist, numattr);
2675 if (response_status == NULL)
2676 return (KMF_ERR_BAD_PARAMETER);
2678 response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2679 attrlist, numattr);
2680 if (response_reason == NULL)
2681 return (KMF_ERR_BAD_PARAMETER);
2683 cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2684 attrlist, numattr);
2685 if (cert_status == NULL)
2686 return (KMF_ERR_BAD_PARAMETER);
2688 /* Read in the response */
2689 derbio = BIO_new_mem_buf(response->Data, response->Length);
2690 if (!derbio) {
2691 ret = KMF_ERR_MEMORY;
2692 return (ret);
2695 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2696 if (resp == NULL) {
2697 ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2698 goto end;
2701 /* Check the response status */
2702 status = OCSP_response_status(resp);
2703 *response_status = status;
2704 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2705 ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2706 goto end;
2709 #ifdef DEBUG
2710 printf("Successfully checked the response file status.\n");
2711 #endif /* DEBUG */
2713 /* Extract basic response */
2714 bs = OCSP_response_get1_basic(resp);
2715 if (bs == NULL) {
2716 ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2717 goto end;
2720 #ifdef DEBUG
2721 printf("Successfully retrieved the basic response.\n");
2722 #endif /* DEBUG */
2724 /* Check the basic response signature if required */
2725 ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2726 (void *)&ignore_response_sign, NULL);
2727 if (ret != KMF_OK)
2728 ret = KMF_OK;
2730 signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2731 attrlist, numattr);
2733 if (ignore_response_sign == B_FALSE) {
2734 ret = check_response_signature(handle, bs,
2735 signer_cert, issuer_cert);
2736 if (ret != KMF_OK)
2737 goto end;
2740 #ifdef DEBUG
2741 printf("Successfully verified the response signature.\n");
2742 #endif /* DEBUG */
2744 /* Create a certid for the certificate in question */
2745 ret = create_certid(handle, issuer_cert, user_cert, &id);
2746 if (ret != KMF_OK) {
2747 ret = KMF_ERR_OCSP_CERTID;
2748 goto end;
2751 #ifdef DEBUG
2752 printf("successfully created a certid for the cert.\n");
2753 #endif /* DEBUG */
2755 /* Find the index of the single response for the certid */
2756 index = OCSP_resp_find(bs, id, -1);
2757 if (index < 0) {
2758 /* cound not find this certificate in the response */
2759 ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2760 goto end;
2763 #ifdef DEBUG
2764 printf("Successfully found the single response index for the cert.\n");
2765 #endif /* DEBUG */
2767 /* Retrieve the single response and get the cert status */
2768 single = OCSP_resp_get0(bs, index);
2769 status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2770 &nextupd);
2771 if (status == V_OCSP_CERTSTATUS_GOOD) {
2772 *cert_status = OCSP_GOOD;
2773 } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2774 *cert_status = OCSP_UNKNOWN;
2775 } else { /* revoked */
2776 *cert_status = OCSP_REVOKED;
2777 *response_reason = reason;
2779 ret = KMF_OK;
2781 /* resp. time is optional, so we don't care about the return code. */
2782 (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2783 (void *)&response_lifetime, NULL);
2785 if (!OCSP_check_validity(thisupd, nextupd, 300,
2786 response_lifetime)) {
2787 ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2788 goto end;
2791 #ifdef DEBUG
2792 printf("Successfully verify the time.\n");
2793 #endif /* DEBUG */
2795 end:
2796 if (derbio != NULL)
2797 (void) BIO_free(derbio);
2799 if (resp != NULL)
2800 OCSP_RESPONSE_free(resp);
2802 if (bs != NULL)
2803 OCSP_BASICRESP_free(bs);
2805 if (id != NULL)
2806 OCSP_CERTID_free(id);
2808 return (ret);
2811 static KMF_RETURN
2812 fetch_key(KMF_HANDLE_T handle, char *path,
2813 KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2815 KMF_RETURN rv = KMF_OK;
2816 EVP_PKEY *pkey = NULL;
2817 KMF_RAW_SYM_KEY *rkey = NULL;
2819 if (keyclass == KMF_ASYM_PRI ||
2820 keyclass == KMF_ASYM_PUB) {
2821 pkey = openssl_load_key(handle, path);
2822 if (pkey == NULL) {
2823 return (KMF_ERR_KEY_NOT_FOUND);
2825 if (key != NULL) {
2826 if (pkey->type == EVP_PKEY_RSA)
2827 key->keyalg = KMF_RSA;
2828 else if (pkey->type == EVP_PKEY_DSA)
2829 key->keyalg = KMF_DSA;
2831 key->kstype = KMF_KEYSTORE_OPENSSL;
2832 key->keyclass = keyclass;
2833 key->keyp = (void *)pkey;
2834 key->israw = FALSE;
2835 if (path != NULL &&
2836 ((key->keylabel = strdup(path)) == NULL)) {
2837 EVP_PKEY_free(pkey);
2838 return (KMF_ERR_MEMORY);
2840 } else {
2841 EVP_PKEY_free(pkey);
2842 pkey = NULL;
2844 } else if (keyclass == KMF_SYMMETRIC) {
2845 KMF_ENCODE_FORMAT fmt;
2847 * If the file is a recognized format,
2848 * then it is NOT a symmetric key.
2850 rv = kmf_get_file_format(path, &fmt);
2851 if (rv == KMF_OK || fmt != 0) {
2852 return (KMF_ERR_KEY_NOT_FOUND);
2853 } else if (rv == KMF_ERR_ENCODING) {
2855 * If we don't know the encoding,
2856 * it is probably a symmetric key.
2858 rv = KMF_OK;
2859 } else if (rv == KMF_ERR_OPEN_FILE) {
2860 return (KMF_ERR_KEY_NOT_FOUND);
2863 if (key != NULL) {
2864 KMF_DATA keyvalue;
2865 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2866 if (rkey == NULL) {
2867 rv = KMF_ERR_MEMORY;
2868 goto out;
2871 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2872 rv = kmf_read_input_file(handle, path, &keyvalue);
2873 if (rv != KMF_OK)
2874 goto out;
2876 rkey->keydata.len = keyvalue.Length;
2877 rkey->keydata.val = keyvalue.Data;
2879 key->kstype = KMF_KEYSTORE_OPENSSL;
2880 key->keyclass = keyclass;
2881 key->israw = TRUE;
2882 key->keyp = (void *)rkey;
2883 if (path != NULL &&
2884 ((key->keylabel = strdup(path)) == NULL)) {
2885 rv = KMF_ERR_MEMORY;
2889 out:
2890 if (rv != KMF_OK) {
2891 if (rkey != NULL) {
2892 kmf_free_raw_sym_key(rkey);
2894 if (pkey != NULL)
2895 EVP_PKEY_free(pkey);
2897 if (key != NULL) {
2898 key->keyalg = KMF_KEYALG_NONE;
2899 key->keyclass = KMF_KEYCLASS_NONE;
2900 key->keyp = NULL;
2904 return (rv);
2907 KMF_RETURN
2908 OpenSSL_FindKey(KMF_HANDLE_T handle,
2909 int numattr, KMF_ATTRIBUTE *attrlist)
2911 KMF_RETURN rv = KMF_OK;
2912 char *fullpath = NULL;
2913 uint32_t maxkeys;
2914 KMF_KEY_HANDLE *key;
2915 uint32_t *numkeys;
2916 KMF_KEY_CLASS keyclass;
2917 KMF_RAW_KEY_DATA *rawkey;
2918 char *dirpath;
2919 char *keyfile;
2921 if (handle == NULL)
2922 return (KMF_ERR_BAD_PARAMETER);
2924 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2925 if (numkeys == NULL)
2926 return (KMF_ERR_BAD_PARAMETER);
2928 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2929 (void *)&keyclass, NULL);
2930 if (rv != KMF_OK)
2931 return (KMF_ERR_BAD_PARAMETER);
2933 if (keyclass != KMF_ASYM_PUB &&
2934 keyclass != KMF_ASYM_PRI &&
2935 keyclass != KMF_SYMMETRIC)
2936 return (KMF_ERR_BAD_KEY_CLASS);
2938 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2939 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2941 fullpath = get_fullpath(dirpath, keyfile);
2943 if (fullpath == NULL)
2944 return (KMF_ERR_BAD_PARAMETER);
2946 maxkeys = *numkeys;
2947 if (maxkeys == 0)
2948 maxkeys = 0xFFFFFFFF;
2949 *numkeys = 0;
2951 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2952 /* it is okay to have "keys" contains NULL */
2955 * The caller may want a list of the raw key data as well.
2956 * Useful for importing keys from a file into other keystores.
2958 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
2960 if (isdir(fullpath)) {
2961 DIR *dirp;
2962 struct dirent *dp;
2963 int n = 0;
2965 /* open all files in the directory and attempt to read them */
2966 if ((dirp = opendir(fullpath)) == NULL) {
2967 return (KMF_ERR_BAD_PARAMETER);
2969 rewinddir(dirp);
2970 while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
2971 if (strcmp(dp->d_name, ".") &&
2972 strcmp(dp->d_name, "..")) {
2973 char *fname;
2975 fname = get_fullpath(fullpath,
2976 (char *)&dp->d_name);
2978 rv = fetch_key(handle, fname,
2979 keyclass, key ? &key[n] : NULL);
2981 if (rv == KMF_OK) {
2982 if (key != NULL && rawkey != NULL)
2983 rv = convertToRawKey(
2984 key[n].keyp, &rawkey[n]);
2985 n++;
2988 if (rv != KMF_OK || key == NULL)
2989 free(fname);
2992 (void) closedir(dirp);
2993 free(fullpath);
2994 (*numkeys) = n;
2995 } else {
2996 rv = fetch_key(handle, fullpath, keyclass, key);
2997 if (rv == KMF_OK)
2998 (*numkeys) = 1;
3000 if (rv != KMF_OK || key == NULL)
3001 free(fullpath);
3003 if (rv == KMF_OK && key != NULL && rawkey != NULL) {
3004 rv = convertToRawKey(key->keyp, rawkey);
3008 if (rv == KMF_OK && (*numkeys) == 0)
3009 rv = KMF_ERR_KEY_NOT_FOUND;
3010 else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
3011 rv = KMF_OK;
3013 return (rv);
3016 #define HANDLE_PK12_ERROR { \
3017 SET_ERROR(kmfh, ERR_get_error()); \
3018 rv = KMF_ERR_ENCODING; \
3019 goto out; \
3022 static int
3023 add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3025 if (xcert != NULL && xcert->aux != NULL &&
3026 xcert->aux->alias != NULL) {
3027 if (PKCS12_add_friendlyname_asc(bag,
3028 (const char *)xcert->aux->alias->data,
3029 xcert->aux->alias->length) == 0)
3030 return (0);
3032 return (1);
3035 static PKCS7 *
3036 add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3037 uchar_t *keyid, unsigned int keyidlen)
3039 PKCS12_SAFEBAG *bag = NULL;
3040 PKCS7 *cert_authsafe = NULL;
3041 STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3043 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3044 if (bag_stack == NULL)
3045 return (NULL);
3047 /* Convert cert from X509 struct to PKCS#12 bag */
3048 bag = PKCS12_x5092certbag(sslcert);
3049 if (bag == NULL) {
3050 goto out;
3053 /* Add the key id to the certificate bag. */
3054 if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3055 goto out;
3058 if (!add_alias_to_bag(bag, sslcert))
3059 goto out;
3061 /* Pile it on the bag_stack. */
3062 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3063 goto out;
3065 /* Turn bag_stack of certs into encrypted authsafe. */
3066 cert_authsafe = PKCS12_pack_p7encdata(
3067 NID_pbe_WithSHA1And40BitRC2_CBC,
3068 cred->cred, cred->credlen, NULL, 0,
3069 PKCS12_DEFAULT_ITER, bag_stack);
3071 out:
3072 if (bag_stack != NULL)
3073 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3075 return (cert_authsafe);
3078 static PKCS7 *
3079 add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3080 uchar_t *keyid, unsigned int keyidlen,
3081 char *label, int label_len)
3083 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3084 STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3085 PKCS12_SAFEBAG *bag = NULL;
3086 PKCS7 *key_authsafe = NULL;
3088 p8 = EVP_PKEY2PKCS8(pkey);
3089 if (p8 == NULL) {
3090 return (NULL);
3092 /* Put the shrouded key into a PKCS#12 bag. */
3093 bag = PKCS12_MAKE_SHKEYBAG(
3094 NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3095 cred->cred, cred->credlen,
3096 NULL, 0, PKCS12_DEFAULT_ITER, p8);
3098 /* Clean up the PKCS#8 shrouded key, don't need it now. */
3099 PKCS8_PRIV_KEY_INFO_free(p8);
3100 p8 = NULL;
3102 if (bag == NULL) {
3103 return (NULL);
3105 if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3106 goto out;
3107 if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3108 goto out;
3110 /* Start a PKCS#12 safebag container for the private key. */
3111 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3112 if (bag_stack == NULL)
3113 goto out;
3115 /* Pile on the private key on the bag_stack. */
3116 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3117 goto out;
3119 key_authsafe = PKCS12_pack_p7data(bag_stack);
3121 out:
3122 if (bag_stack != NULL)
3123 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3124 bag_stack = NULL;
3125 return (key_authsafe);
3128 static EVP_PKEY *
3129 ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3131 RSA *rsa = NULL;
3132 EVP_PKEY *newkey = NULL;
3134 if ((rsa = RSA_new()) == NULL)
3135 return (NULL);
3137 if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
3138 return (NULL);
3140 if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
3141 NULL)
3142 return (NULL);
3144 if (key->priexp.val != NULL)
3145 if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
3146 rsa->d)) == NULL)
3147 return (NULL);
3149 if (key->prime1.val != NULL)
3150 if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
3151 rsa->p)) == NULL)
3152 return (NULL);
3154 if (key->prime2.val != NULL)
3155 if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
3156 rsa->q)) == NULL)
3157 return (NULL);
3159 if (key->exp1.val != NULL)
3160 if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
3161 rsa->dmp1)) == NULL)
3162 return (NULL);
3164 if (key->exp2.val != NULL)
3165 if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
3166 rsa->dmq1)) == NULL)
3167 return (NULL);
3169 if (key->coef.val != NULL)
3170 if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
3171 rsa->iqmp)) == NULL)
3172 return (NULL);
3174 if ((newkey = EVP_PKEY_new()) == NULL)
3175 return (NULL);
3177 (void) EVP_PKEY_set1_RSA(newkey, rsa);
3179 /* The original key must be freed once here or it leaks memory */
3180 RSA_free(rsa);
3182 return (newkey);
3185 static EVP_PKEY *
3186 ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3188 DSA *dsa = NULL;
3189 EVP_PKEY *newkey = NULL;
3191 if ((dsa = DSA_new()) == NULL)
3192 return (NULL);
3194 if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
3195 dsa->p)) == NULL)
3196 return (NULL);
3198 if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
3199 dsa->q)) == NULL)
3200 return (NULL);
3202 if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
3203 dsa->g)) == NULL)
3204 return (NULL);
3206 if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
3207 dsa->priv_key)) == NULL)
3208 return (NULL);
3210 if (key->pubvalue.val != NULL) {
3211 if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
3212 key->pubvalue.len, dsa->pub_key)) == NULL)
3213 return (NULL);
3216 if ((newkey = EVP_PKEY_new()) == NULL)
3217 return (NULL);
3219 (void) EVP_PKEY_set1_DSA(newkey, dsa);
3221 /* The original key must be freed once here or it leaks memory */
3222 DSA_free(dsa);
3223 return (newkey);
3226 static EVP_PKEY *
3227 raw_key_to_pkey(KMF_KEY_HANDLE *key)
3229 EVP_PKEY *pkey = NULL;
3230 KMF_RAW_KEY_DATA *rawkey;
3231 ASN1_TYPE *attr = NULL;
3232 KMF_RETURN ret;
3234 if (key == NULL || !key->israw)
3235 return (NULL);
3237 rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3238 if (rawkey->keytype == KMF_RSA) {
3239 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3240 } else if (rawkey->keytype == KMF_DSA) {
3241 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3242 } else if (rawkey->keytype == KMF_ECDSA) {
3244 * OpenSSL in Solaris does not support EC for
3245 * legal reasons
3247 return (NULL);
3248 } else {
3249 /* wrong kind of key */
3250 return (NULL);
3253 if (rawkey->label != NULL) {
3254 if ((attr = ASN1_TYPE_new()) == NULL) {
3255 EVP_PKEY_free(pkey);
3256 return (NULL);
3258 attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3259 (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3260 strlen(rawkey->label));
3261 attr->type = V_ASN1_BMPSTRING;
3262 attr->value.ptr = (char *)attr->value.bmpstring;
3263 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3264 if (ret != KMF_OK) {
3265 EVP_PKEY_free(pkey);
3266 ASN1_TYPE_free(attr);
3267 return (NULL);
3270 if (rawkey->id.Data != NULL) {
3271 if ((attr = ASN1_TYPE_new()) == NULL) {
3272 EVP_PKEY_free(pkey);
3273 return (NULL);
3275 attr->value.octet_string =
3276 ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3277 attr->type = V_ASN1_OCTET_STRING;
3278 (void) ASN1_STRING_set(attr->value.octet_string,
3279 rawkey->id.Data, rawkey->id.Length);
3280 attr->value.ptr = (char *)attr->value.octet_string;
3281 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3282 if (ret != KMF_OK) {
3283 EVP_PKEY_free(pkey);
3284 ASN1_TYPE_free(attr);
3285 return (NULL);
3288 return (pkey);
3292 * Search a list of private keys to find one that goes with the certificate.
3294 static EVP_PKEY *
3295 find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3297 int i;
3298 EVP_PKEY *pkey = NULL;
3300 if (numkeys == 0 || keylist == NULL || xcert == NULL)
3301 return (NULL);
3302 for (i = 0; i < numkeys; i++) {
3303 if (keylist[i].israw)
3304 pkey = raw_key_to_pkey(&keylist[i]);
3305 else
3306 pkey = (EVP_PKEY *)keylist[i].keyp;
3307 if (pkey != NULL) {
3308 if (X509_check_private_key(xcert, pkey)) {
3309 return (pkey);
3310 } else {
3311 EVP_PKEY_free(pkey);
3312 pkey = NULL;
3316 return (pkey);
3319 static KMF_RETURN
3320 local_export_pk12(KMF_HANDLE_T handle,
3321 KMF_CREDENTIAL *cred,
3322 int numcerts, KMF_X509_DER_CERT *certlist,
3323 int numkeys, KMF_KEY_HANDLE *keylist,
3324 char *filename)
3326 KMF_RETURN rv = KMF_OK;
3327 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3328 BIO *bio = NULL;
3329 PKCS7 *cert_authsafe = NULL;
3330 PKCS7 *key_authsafe = NULL;
3331 STACK_OF(PKCS7) *authsafe_stack = NULL;
3332 PKCS12 *p12_elem = NULL;
3333 int i;
3335 if (numcerts == 0 && numkeys == 0)
3336 return (KMF_ERR_BAD_PARAMETER);
3339 * Open the output file.
3341 if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3342 SET_ERROR(kmfh, ERR_get_error());
3343 rv = KMF_ERR_OPEN_FILE;
3344 goto cleanup;
3347 /* Start a PKCS#7 stack. */
3348 authsafe_stack = sk_PKCS7_new_null();
3349 if (authsafe_stack == NULL) {
3350 rv = KMF_ERR_MEMORY;
3351 goto cleanup;
3353 if (numcerts > 0) {
3354 for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3355 const uchar_t *p = certlist[i].certificate.Data;
3356 long len = certlist[i].certificate.Length;
3357 X509 *xcert = NULL;
3358 EVP_PKEY *pkey = NULL;
3359 unsigned char keyid[EVP_MAX_MD_SIZE];
3360 unsigned int keyidlen = 0;
3362 xcert = d2i_X509(NULL, &p, len);
3363 if (xcert == NULL) {
3364 SET_ERROR(kmfh, ERR_get_error());
3365 rv = KMF_ERR_ENCODING;
3367 if (certlist[i].kmf_private.label != NULL) {
3368 /* Set alias attribute */
3369 (void) X509_alias_set1(xcert,
3370 (uchar_t *)certlist[i].kmf_private.label,
3371 strlen(certlist[i].kmf_private.label));
3373 /* Check if there is a key corresponding to this cert */
3374 pkey = find_matching_key(xcert, numkeys, keylist);
3377 * If key is found, get fingerprint and create a
3378 * safebag.
3380 if (pkey != NULL) {
3381 (void) X509_digest(xcert, EVP_sha1(),
3382 keyid, &keyidlen);
3383 key_authsafe = add_key_to_safe(pkey, cred,
3384 keyid, keyidlen,
3385 certlist[i].kmf_private.label,
3386 (certlist[i].kmf_private.label ?
3387 strlen(certlist[i].kmf_private.label) : 0));
3389 if (key_authsafe == NULL) {
3390 X509_free(xcert);
3391 EVP_PKEY_free(pkey);
3392 goto cleanup;
3394 /* Put the key safe into the Auth Safe */
3395 if (!sk_PKCS7_push(authsafe_stack,
3396 key_authsafe)) {
3397 X509_free(xcert);
3398 EVP_PKEY_free(pkey);
3399 goto cleanup;
3403 /* create a certificate safebag */
3404 cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3405 keyidlen);
3406 if (cert_authsafe == NULL) {
3407 X509_free(xcert);
3408 EVP_PKEY_free(pkey);
3409 goto cleanup;
3411 if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3412 X509_free(xcert);
3413 EVP_PKEY_free(pkey);
3414 goto cleanup;
3417 X509_free(xcert);
3418 if (pkey)
3419 EVP_PKEY_free(pkey);
3421 } else if (numcerts == 0 && numkeys > 0) {
3423 * If only adding keys to the file.
3425 for (i = 0; i < numkeys; i++) {
3426 EVP_PKEY *pkey = NULL;
3428 if (keylist[i].israw)
3429 pkey = raw_key_to_pkey(&keylist[i]);
3430 else
3431 pkey = (EVP_PKEY *)keylist[i].keyp;
3433 if (pkey == NULL)
3434 continue;
3436 key_authsafe = add_key_to_safe(pkey, cred,
3437 NULL, 0, NULL, 0);
3439 if (key_authsafe == NULL) {
3440 EVP_PKEY_free(pkey);
3441 goto cleanup;
3443 if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3444 EVP_PKEY_free(pkey);
3445 goto cleanup;
3449 p12_elem = PKCS12_init(NID_pkcs7_data);
3450 if (p12_elem == NULL) {
3451 goto cleanup;
3454 /* Put the PKCS#7 stack into the PKCS#12 element. */
3455 if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3456 goto cleanup;
3459 /* Set the integrity MAC on the PKCS#12 element. */
3460 if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3461 NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3462 goto cleanup;
3465 /* Write the PKCS#12 element to the export file. */
3466 if (!i2d_PKCS12_bio(bio, p12_elem)) {
3467 goto cleanup;
3469 PKCS12_free(p12_elem);
3471 cleanup:
3472 /* Clear away the PKCS#7 stack, we're done with it. */
3473 if (authsafe_stack)
3474 sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3476 if (bio != NULL)
3477 (void) BIO_free_all(bio);
3479 return (rv);
3482 KMF_RETURN
3483 openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3484 KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3485 KMF_CREDENTIAL *p12cred, char *filename)
3487 KMF_RETURN rv;
3489 if (certlist == NULL && keylist == NULL)
3490 return (KMF_ERR_BAD_PARAMETER);
3492 rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3493 numkeys, keylist, filename);
3495 return (rv);
3498 KMF_RETURN
3499 OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3501 KMF_RETURN rv;
3502 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3503 char *fullpath = NULL;
3504 char *dirpath = NULL;
3505 char *certfile = NULL;
3506 char *keyfile = NULL;
3507 char *filename = NULL;
3508 KMF_CREDENTIAL *p12cred = NULL;
3509 KMF_X509_DER_CERT certdata;
3510 KMF_KEY_HANDLE key;
3511 int gotkey = 0;
3512 int gotcert = 0;
3514 if (handle == NULL)
3515 return (KMF_ERR_BAD_PARAMETER);
3518 * First, find the certificate.
3520 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3521 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3522 if (certfile != NULL) {
3523 fullpath = get_fullpath(dirpath, certfile);
3524 if (fullpath == NULL)
3525 return (KMF_ERR_BAD_PARAMETER);
3527 if (isdir(fullpath)) {
3528 free(fullpath);
3529 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3532 (void) memset(&certdata, 0, sizeof (certdata));
3533 rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3534 fullpath, &certdata.certificate);
3535 if (rv != KMF_OK)
3536 goto end;
3538 gotcert++;
3539 certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3540 free(fullpath);
3544 * Now find the private key.
3546 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3547 if (keyfile != NULL) {
3548 fullpath = get_fullpath(dirpath, keyfile);
3549 if (fullpath == NULL)
3550 return (KMF_ERR_BAD_PARAMETER);
3552 if (isdir(fullpath)) {
3553 free(fullpath);
3554 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3557 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3558 rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3559 if (rv != KMF_OK)
3560 goto end;
3561 gotkey++;
3565 * Open the output file.
3567 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3568 numattr);
3569 if (filename == NULL) {
3570 rv = KMF_ERR_BAD_PARAMETER;
3571 goto end;
3574 /* Stick the key and the cert into a PKCS#12 file */
3575 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3576 if (p12cred == NULL) {
3577 rv = KMF_ERR_BAD_PARAMETER;
3578 goto end;
3581 rv = local_export_pk12(handle, p12cred, 1, &certdata,
3582 1, &key, filename);
3584 end:
3585 if (fullpath)
3586 free(fullpath);
3588 if (gotcert)
3589 kmf_free_kmf_cert(handle, &certdata);
3590 if (gotkey)
3591 kmf_free_kmf_key(handle, &key);
3592 return (rv);
3596 * Helper function to extract keys and certificates from
3597 * a single PEM file. Typically the file should contain a
3598 * private key and an associated public key wrapped in an x509 cert.
3599 * However, the file may be just a list of X509 certs with no keys.
3601 static KMF_RETURN
3602 extract_pem(KMF_HANDLE *kmfh,
3603 char *issuer, char *subject, KMF_BIGINT *serial,
3604 char *filename, CK_UTF8CHAR *pin,
3605 CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3606 int *numcerts)
3607 /* ARGSUSED6 */
3609 KMF_RETURN rv = KMF_OK;
3610 FILE *fp;
3611 STACK_OF(X509_INFO) *x509_info_stack = NULL;
3612 int i, ncerts = 0, matchcerts = 0;
3613 EVP_PKEY *pkey = NULL;
3614 X509_INFO *info;
3615 X509 *x;
3616 X509_INFO **cert_infos = NULL;
3617 KMF_DATA *certlist = NULL;
3619 if (priv_key)
3620 *priv_key = NULL;
3621 if (certs)
3622 *certs = NULL;
3623 fp = fopen(filename, "r");
3624 if (fp == NULL)
3625 return (KMF_ERR_OPEN_FILE);
3627 x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3628 if (x509_info_stack == NULL) {
3629 (void) fclose(fp);
3630 return (KMF_ERR_ENCODING);
3632 cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3633 sizeof (X509_INFO *));
3634 if (cert_infos == NULL) {
3635 (void) fclose(fp);
3636 rv = KMF_ERR_MEMORY;
3637 goto err;
3640 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3641 cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i);
3642 ncerts++;
3645 if (ncerts == 0) {
3646 (void) fclose(fp);
3647 rv = KMF_ERR_CERT_NOT_FOUND;
3648 goto err;
3651 if (priv_key != NULL) {
3652 rewind(fp);
3653 pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
3655 (void) fclose(fp);
3657 x = cert_infos[ncerts - 1]->x509;
3659 * Make sure the private key matchs the last cert in the file.
3661 if (pkey != NULL && !X509_check_private_key(x, pkey)) {
3662 EVP_PKEY_free(pkey);
3663 rv = KMF_ERR_KEY_MISMATCH;
3664 goto err;
3667 certlist = (KMF_DATA *)calloc(ncerts, sizeof (KMF_DATA));
3668 if (certlist == NULL) {
3669 if (pkey != NULL)
3670 EVP_PKEY_free(pkey);
3671 rv = KMF_ERR_MEMORY;
3672 goto err;
3676 * Convert all of the certs to DER format.
3678 matchcerts = 0;
3679 for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
3680 boolean_t match = FALSE;
3681 info = cert_infos[ncerts - 1 - i];
3683 rv = check_cert(info->x509, issuer, subject, serial, &match);
3684 if (rv != KMF_OK || match != TRUE) {
3685 rv = KMF_OK;
3686 continue;
3689 rv = ssl_cert2KMFDATA(kmfh, info->x509,
3690 &certlist[matchcerts++]);
3692 if (rv != KMF_OK) {
3693 int j;
3694 for (j = 0; j < matchcerts; j++)
3695 kmf_free_data(&certlist[j]);
3696 free(certlist);
3697 certlist = NULL;
3698 ncerts = matchcerts = 0;
3702 if (numcerts != NULL)
3703 *numcerts = matchcerts;
3705 if (certs != NULL)
3706 *certs = certlist;
3707 else if (certlist != NULL) {
3708 for (i = 0; i < ncerts; i++)
3709 kmf_free_data(&certlist[i]);
3710 free(certlist);
3711 certlist = NULL;
3714 if (priv_key == NULL && pkey != NULL)
3715 EVP_PKEY_free(pkey);
3716 else if (priv_key != NULL && pkey != NULL)
3717 *priv_key = pkey;
3719 err:
3720 /* Cleanup the stack of X509 info records */
3721 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3722 info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3723 X509_INFO_free(info);
3725 if (x509_info_stack)
3726 sk_X509_INFO_free(x509_info_stack);
3728 if (cert_infos != NULL)
3729 free(cert_infos);
3731 return (rv);
3734 static KMF_RETURN
3735 openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3736 STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3738 KMF_RETURN ret;
3739 int i;
3741 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3742 PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3743 ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3744 keys, certs);
3746 if (ret != KMF_OK)
3747 return (ret);
3750 return (ret);
3753 static KMF_RETURN
3754 set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3756 X509_ATTRIBUTE *attr = NULL;
3758 if (pkey == NULL || attrib == NULL)
3759 return (KMF_ERR_BAD_PARAMETER);
3761 if (pkey->attributes == NULL) {
3762 pkey->attributes = sk_X509_ATTRIBUTE_new_null();
3763 if (pkey->attributes == NULL)
3764 return (KMF_ERR_MEMORY);
3766 attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3767 if (attr != NULL) {
3768 int i;
3769 X509_ATTRIBUTE *a;
3770 for (i = 0;
3771 i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3772 a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
3773 if (OBJ_obj2nid(a->object) == nid) {
3774 X509_ATTRIBUTE_free(a);
3775 (void) sk_X509_ATTRIBUTE_set(pkey->attributes,
3776 i, attr);
3777 return (KMF_OK);
3780 if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
3781 X509_ATTRIBUTE_free(attr);
3782 return (KMF_ERR_MEMORY);
3784 } else {
3785 return (KMF_ERR_MEMORY);
3788 return (KMF_OK);
3791 static KMF_RETURN
3792 openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3793 STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3795 KMF_RETURN ret = KMF_OK;
3796 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3797 EVP_PKEY *pkey = NULL;
3798 X509 *xcert = NULL;
3799 ASN1_TYPE *keyid = NULL;
3800 ASN1_TYPE *fname = NULL;
3801 uchar_t *data = NULL;
3803 keyid = PKCS12_get_attr(bag, NID_localKeyID);
3804 fname = PKCS12_get_attr(bag, NID_friendlyName);
3806 switch (M_PKCS12_bag_type(bag)) {
3807 case NID_keyBag:
3808 if (keylist == NULL)
3809 goto end;
3810 pkey = EVP_PKCS82PKEY(bag->value.keybag);
3811 if (pkey == NULL)
3812 ret = KMF_ERR_PKCS12_FORMAT;
3814 break;
3815 case NID_pkcs8ShroudedKeyBag:
3816 if (keylist == NULL)
3817 goto end;
3818 p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
3819 if (p8 == NULL)
3820 return (KMF_ERR_AUTH_FAILED);
3821 pkey = EVP_PKCS82PKEY(p8);
3822 PKCS8_PRIV_KEY_INFO_free(p8);
3823 if (pkey == NULL)
3824 ret = KMF_ERR_PKCS12_FORMAT;
3825 break;
3826 case NID_certBag:
3827 if (certlist == NULL)
3828 goto end;
3829 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
3830 return (KMF_ERR_PKCS12_FORMAT);
3831 xcert = M_PKCS12_certbag2x509(bag);
3832 if (xcert == NULL) {
3833 ret = KMF_ERR_PKCS12_FORMAT;
3834 goto end;
3836 if (keyid != NULL) {
3837 if (X509_keyid_set1(xcert,
3838 keyid->value.octet_string->data,
3839 keyid->value.octet_string->length) == 0) {
3840 ret = KMF_ERR_PKCS12_FORMAT;
3841 goto end;
3844 if (fname != NULL) {
3845 int len, r;
3846 len = ASN1_STRING_to_UTF8(&data,
3847 fname->value.asn1_string);
3848 if (len > 0 && data != NULL) {
3849 r = X509_alias_set1(xcert, data, len);
3850 if (r == NULL) {
3851 ret = KMF_ERR_PKCS12_FORMAT;
3852 goto end;
3854 } else {
3855 ret = KMF_ERR_PKCS12_FORMAT;
3856 goto end;
3859 if (sk_X509_push(certlist, xcert) == 0)
3860 ret = KMF_ERR_MEMORY;
3861 else
3862 xcert = NULL;
3863 break;
3864 case NID_safeContentsBag:
3865 return (openssl_parse_bags(bag->value.safes, pass,
3866 keylist, certlist));
3867 default:
3868 ret = KMF_ERR_PKCS12_FORMAT;
3869 break;
3873 * Set the ID and/or FriendlyName attributes on the key.
3874 * If converting to PKCS11 objects, these can translate to CKA_ID
3875 * and CKA_LABEL values.
3877 if (pkey != NULL && ret == KMF_OK) {
3878 ASN1_TYPE *attr = NULL;
3879 if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3880 if ((attr = ASN1_TYPE_new()) == NULL)
3881 return (KMF_ERR_MEMORY);
3882 attr->value.octet_string =
3883 ASN1_STRING_dup(keyid->value.octet_string);
3884 attr->type = V_ASN1_OCTET_STRING;
3885 attr->value.ptr = (char *)attr->value.octet_string;
3886 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3887 OPENSSL_free(attr);
3890 if (ret == KMF_OK && fname != NULL &&
3891 fname->type == V_ASN1_BMPSTRING) {
3892 if ((attr = ASN1_TYPE_new()) == NULL)
3893 return (KMF_ERR_MEMORY);
3894 attr->value.bmpstring =
3895 ASN1_STRING_dup(fname->value.bmpstring);
3896 attr->type = V_ASN1_BMPSTRING;
3897 attr->value.ptr = (char *)attr->value.bmpstring;
3898 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3899 OPENSSL_free(attr);
3902 if (ret == KMF_OK && keylist != NULL &&
3903 sk_EVP_PKEY_push(keylist, pkey) == 0)
3904 ret = KMF_ERR_MEMORY;
3906 if (ret == KMF_OK && keylist != NULL)
3907 pkey = NULL;
3908 end:
3909 if (pkey != NULL)
3910 EVP_PKEY_free(pkey);
3911 if (xcert != NULL)
3912 X509_free(xcert);
3913 if (data != NULL)
3914 OPENSSL_free(data);
3916 return (ret);
3919 static KMF_RETURN
3920 openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3921 STACK_OF(EVP_PKEY) *keys,
3922 STACK_OF(X509) *certs,
3923 STACK_OF(X509) *ca)
3924 /* ARGSUSED3 */
3926 KMF_RETURN ret = KMF_OK;
3927 STACK_OF(PKCS7) *asafes = NULL;
3928 STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
3929 int i, bagnid;
3930 PKCS7 *p7;
3932 if (p12 == NULL || (keys == NULL && certs == NULL))
3933 return (KMF_ERR_BAD_PARAMETER);
3935 if (pin == NULL || *pin == NULL) {
3936 if (PKCS12_verify_mac(p12, NULL, 0)) {
3937 pin = NULL;
3938 } else if (PKCS12_verify_mac(p12, "", 0)) {
3939 pin = "";
3940 } else {
3941 return (KMF_ERR_AUTH_FAILED);
3943 } else if (!PKCS12_verify_mac(p12, pin, -1)) {
3944 return (KMF_ERR_AUTH_FAILED);
3947 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
3948 return (KMF_ERR_PKCS12_FORMAT);
3950 for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
3951 bags = NULL;
3952 p7 = sk_PKCS7_value(asafes, i);
3953 bagnid = OBJ_obj2nid(p7->type);
3955 if (bagnid == NID_pkcs7_data) {
3956 bags = PKCS12_unpack_p7data(p7);
3957 } else if (bagnid == NID_pkcs7_encrypted) {
3958 bags = PKCS12_unpack_p7encdata(p7, pin,
3959 (pin ? strlen(pin) : 0));
3960 } else {
3961 continue;
3963 if (bags == NULL) {
3964 ret = KMF_ERR_PKCS12_FORMAT;
3965 goto out;
3968 if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
3969 ret = KMF_ERR_PKCS12_FORMAT;
3971 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
3973 out:
3974 if (asafes != NULL)
3975 sk_PKCS7_pop_free(asafes, PKCS7_free);
3977 return (ret);
3981 * Helper function to decrypt and parse PKCS#12 import file.
3983 static KMF_RETURN
3984 extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3985 STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
3986 STACK_OF(X509) **ca)
3987 /* ARGSUSED2 */
3989 PKCS12 *pk12, *pk12_tmp;
3990 STACK_OF(EVP_PKEY) *pkeylist = NULL;
3991 STACK_OF(X509) *xcertlist = NULL;
3992 STACK_OF(X509) *cacertlist = NULL;
3994 if ((pk12 = PKCS12_new()) == NULL) {
3995 return (KMF_ERR_MEMORY);
3998 if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
3999 /* This is ok; it seems to mean there is no more to read. */
4000 if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
4001 ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
4002 goto end_extract_pkcs12;
4004 PKCS12_free(pk12);
4005 return (KMF_ERR_PKCS12_FORMAT);
4007 pk12 = pk12_tmp;
4009 xcertlist = sk_X509_new_null();
4010 if (xcertlist == NULL) {
4011 PKCS12_free(pk12);
4012 return (KMF_ERR_MEMORY);
4014 pkeylist = sk_EVP_PKEY_new_null();
4015 if (pkeylist == NULL) {
4016 sk_X509_pop_free(xcertlist, X509_free);
4017 PKCS12_free(pk12);
4018 return (KMF_ERR_MEMORY);
4021 if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4022 cacertlist) != KMF_OK) {
4023 sk_X509_pop_free(xcertlist, X509_free);
4024 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4025 PKCS12_free(pk12);
4026 return (KMF_ERR_PKCS12_FORMAT);
4029 if (priv_key && pkeylist)
4030 *priv_key = pkeylist;
4031 else if (pkeylist)
4032 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4033 if (certs && xcertlist)
4034 *certs = xcertlist;
4035 else if (xcertlist)
4036 sk_X509_pop_free(xcertlist, X509_free);
4037 if (ca && cacertlist)
4038 *ca = cacertlist;
4039 else if (cacertlist)
4040 sk_X509_pop_free(cacertlist, X509_free);
4042 end_extract_pkcs12:
4044 PKCS12_free(pk12);
4045 return (KMF_OK);
4048 static KMF_RETURN
4049 sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4051 KMF_RETURN rv = KMF_OK;
4052 uint32_t sz;
4054 sz = BN_num_bytes(from);
4055 to->val = (uchar_t *)malloc(sz);
4056 if (to->val == NULL)
4057 return (KMF_ERR_MEMORY);
4059 if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4060 free(to->val);
4061 to->val = NULL;
4062 to->len = 0;
4063 rv = KMF_ERR_MEMORY;
4066 return (rv);
4069 static KMF_RETURN
4070 exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4072 KMF_RETURN rv;
4073 KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4075 (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4076 if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
4077 goto cleanup;
4079 if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
4080 goto cleanup;
4082 if (rsa->d != NULL)
4083 if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
4084 goto cleanup;
4086 if (rsa->p != NULL)
4087 if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
4088 goto cleanup;
4090 if (rsa->q != NULL)
4091 if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
4092 goto cleanup;
4094 if (rsa->dmp1 != NULL)
4095 if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
4096 goto cleanup;
4098 if (rsa->dmq1 != NULL)
4099 if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
4100 goto cleanup;
4102 if (rsa->iqmp != NULL)
4103 if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
4104 goto cleanup;
4105 cleanup:
4106 if (rv != KMF_OK)
4107 kmf_free_raw_key(key);
4108 else
4109 key->keytype = KMF_RSA;
4112 * Free the reference to this key, SSL will not actually free
4113 * the memory until the refcount == 0, so this is safe.
4115 RSA_free(rsa);
4117 return (rv);
4120 static KMF_RETURN
4121 exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4123 KMF_RETURN rv;
4124 KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4126 (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4127 if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
4128 goto cleanup;
4130 if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
4131 goto cleanup;
4133 if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
4134 goto cleanup;
4136 if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
4137 goto cleanup;
4139 cleanup:
4140 if (rv != KMF_OK)
4141 kmf_free_raw_key(key);
4142 else
4143 key->keytype = KMF_DSA;
4146 * Free the reference to this key, SSL will not actually free
4147 * the memory until the refcount == 0, so this is safe.
4149 DSA_free(dsa);
4151 return (rv);
4154 static KMF_RETURN
4155 add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4156 KMF_X509_DER_CERT **certlist, int *ncerts)
4158 KMF_RETURN rv = KMF_OK;
4159 KMF_X509_DER_CERT *list = (*certlist);
4160 KMF_X509_DER_CERT cert;
4161 int n = (*ncerts);
4163 if (list == NULL) {
4164 list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4165 } else {
4166 list = (KMF_X509_DER_CERT *)realloc(list,
4167 sizeof (KMF_X509_DER_CERT) * (n + 1));
4170 if (list == NULL)
4171 return (KMF_ERR_MEMORY);
4173 (void) memset(&cert, 0, sizeof (cert));
4174 rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4175 if (rv == KMF_OK) {
4176 int len = 0;
4177 /* Get the alias name for the cert if there is one */
4178 char *a = (char *)X509_alias_get0(sslcert, &len);
4179 if (a != NULL)
4180 cert.kmf_private.label = strdup(a);
4181 cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4183 list[n] = cert;
4184 (*ncerts) = n + 1;
4186 *certlist = list;
4187 } else {
4188 free(list);
4191 return (rv);
4194 static KMF_RETURN
4195 add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4196 KMF_RAW_KEY_DATA *newkey, int *nkeys)
4198 KMF_RAW_KEY_DATA *list = (*keylist);
4199 int n = (*nkeys);
4201 if (list == NULL) {
4202 list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4203 } else {
4204 list = (KMF_RAW_KEY_DATA *)realloc(list,
4205 sizeof (KMF_RAW_KEY_DATA) * (n + 1));
4208 if (list == NULL)
4209 return (KMF_ERR_MEMORY);
4211 list[n] = *newkey;
4212 (*nkeys) = n + 1;
4214 *keylist = list;
4216 return (KMF_OK);
4219 static X509_ATTRIBUTE *
4220 find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4222 X509_ATTRIBUTE *a;
4223 int i;
4225 if (attrs == NULL)
4226 return (NULL);
4228 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4229 a = sk_X509_ATTRIBUTE_value(attrs, i);
4230 if (OBJ_obj2nid(a->object) == nid)
4231 return (a);
4233 return (NULL);
4236 static KMF_RETURN
4237 convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4239 KMF_RETURN rv = KMF_OK;
4240 X509_ATTRIBUTE *attr;
4242 if (pkey == NULL || key == NULL)
4243 return (KMF_ERR_BAD_PARAMETER);
4244 /* Convert SSL key to raw key */
4245 switch (pkey->type) {
4246 case EVP_PKEY_RSA:
4247 rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
4248 key);
4249 if (rv != KMF_OK)
4250 return (rv);
4251 break;
4252 case EVP_PKEY_DSA:
4253 rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
4254 key);
4255 if (rv != KMF_OK)
4256 return (rv);
4257 break;
4258 default:
4259 return (KMF_ERR_BAD_PARAMETER);
4262 * If friendlyName, add it to record.
4264 attr = find_attr(pkey->attributes, NID_friendlyName);
4265 if (attr != NULL) {
4266 ASN1_TYPE *ty = NULL;
4267 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4268 if (attr->single == 0 && numattr > 0) {
4269 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4271 if (ty != NULL) {
4272 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4273 key->label = uni2asc(ty->value.bmpstring->data,
4274 ty->value.bmpstring->length);
4275 #else
4276 key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4277 ty->value.bmpstring->length);
4278 #endif
4280 } else {
4281 key->label = NULL;
4285 * If KeyID, add it to record as a KMF_DATA object.
4287 attr = find_attr(pkey->attributes, NID_localKeyID);
4288 if (attr != NULL) {
4289 ASN1_TYPE *ty = NULL;
4290 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4291 if (attr->single == 0 && numattr > 0) {
4292 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4294 key->id.Data = (uchar_t *)malloc(
4295 ty->value.octet_string->length);
4296 if (key->id.Data == NULL)
4297 return (KMF_ERR_MEMORY);
4298 (void) memcpy(key->id.Data, ty->value.octet_string->data,
4299 ty->value.octet_string->length);
4300 key->id.Length = ty->value.octet_string->length;
4301 } else {
4302 (void) memset(&key->id, 0, sizeof (KMF_DATA));
4305 return (rv);
4308 static KMF_RETURN
4309 convertPK12Objects(
4310 KMF_HANDLE *kmfh,
4311 STACK_OF(EVP_PKEY) *sslkeys,
4312 STACK_OF(X509) *sslcert,
4313 STACK_OF(X509) *sslcacerts,
4314 KMF_RAW_KEY_DATA **keylist, int *nkeys,
4315 KMF_X509_DER_CERT **certlist, int *ncerts)
4317 KMF_RETURN rv = KMF_OK;
4318 KMF_RAW_KEY_DATA key;
4319 int i;
4321 for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4322 EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4323 rv = convertToRawKey(pkey, &key);
4324 if (rv == KMF_OK)
4325 rv = add_key_to_list(keylist, &key, nkeys);
4327 if (rv != KMF_OK)
4328 return (rv);
4331 /* Now add the certificate to the certlist */
4332 for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4333 X509 *cert = sk_X509_value(sslcert, i);
4334 rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4335 if (rv != KMF_OK)
4336 return (rv);
4339 /* Also add any included CA certs to the list */
4340 for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4341 X509 *c;
4343 * sk_X509_value() is macro that embeds a cast to (X509 *).
4344 * Here it translates into ((X509 *)sk_value((ca), (i))).
4345 * Lint is complaining about the embedded casting, and
4346 * to fix it, you need to fix openssl header files.
4348 c = sk_X509_value(sslcacerts, i);
4350 /* Now add the ca cert to the certlist */
4351 rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4352 if (rv != KMF_OK)
4353 return (rv);
4355 return (rv);
4358 KMF_RETURN
4359 openssl_import_objects(KMF_HANDLE *kmfh,
4360 char *filename, KMF_CREDENTIAL *cred,
4361 KMF_X509_DER_CERT **certlist, int *ncerts,
4362 KMF_RAW_KEY_DATA **keylist, int *nkeys)
4364 KMF_RETURN rv = KMF_OK;
4365 KMF_ENCODE_FORMAT format;
4366 BIO *bio = NULL;
4367 STACK_OF(EVP_PKEY) *privkeys = NULL;
4368 STACK_OF(X509) *certs = NULL;
4369 STACK_OF(X509) *cacerts = NULL;
4372 * auto-detect the file format, regardless of what
4373 * the 'format' parameters in the params say.
4375 rv = kmf_get_file_format(filename, &format);
4376 if (rv != KMF_OK) {
4377 return (rv);
4380 /* This function only works for PEM or PKCS#12 files */
4381 if (format != KMF_FORMAT_PEM &&
4382 format != KMF_FORMAT_PEM_KEYPAIR &&
4383 format != KMF_FORMAT_PKCS12)
4384 return (KMF_ERR_ENCODING);
4386 *certlist = NULL;
4387 *keylist = NULL;
4388 *ncerts = 0;
4389 *nkeys = 0;
4391 if (format == KMF_FORMAT_PKCS12) {
4392 bio = BIO_new_file(filename, "rb");
4393 if (bio == NULL) {
4394 SET_ERROR(kmfh, ERR_get_error());
4395 rv = KMF_ERR_OPEN_FILE;
4396 goto end;
4399 rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4400 (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4402 if (rv == KMF_OK)
4403 /* Convert keys and certs to exportable format */
4404 rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4405 keylist, nkeys, certlist, ncerts);
4406 } else {
4407 EVP_PKEY *pkey;
4408 KMF_DATA *certdata = NULL;
4409 KMF_X509_DER_CERT *kmfcerts = NULL;
4410 int i;
4411 rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4412 (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4413 &pkey, &certdata, ncerts);
4415 /* Reached end of import file? */
4416 if (rv == KMF_OK && pkey != NULL) {
4417 privkeys = sk_EVP_PKEY_new_null();
4418 if (privkeys == NULL) {
4419 rv = KMF_ERR_MEMORY;
4420 goto end;
4422 (void) sk_EVP_PKEY_push(privkeys, pkey);
4423 /* convert the certificate list here */
4424 if (*ncerts > 0 && certlist != NULL) {
4425 kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4426 sizeof (KMF_X509_DER_CERT));
4427 if (kmfcerts == NULL) {
4428 rv = KMF_ERR_MEMORY;
4429 goto end;
4431 for (i = 0; i < *ncerts; i++) {
4432 kmfcerts[i].certificate = certdata[i];
4433 kmfcerts[i].kmf_private.keystore_type =
4434 KMF_KEYSTORE_OPENSSL;
4436 *certlist = kmfcerts;
4439 * Convert keys to exportable format, the certs
4440 * are already OK.
4442 rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4443 keylist, nkeys, NULL, NULL);
4446 end:
4447 if (bio != NULL)
4448 (void) BIO_free(bio);
4450 if (privkeys)
4451 sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4452 if (certs)
4453 sk_X509_pop_free(certs, X509_free);
4454 if (cacerts)
4455 sk_X509_pop_free(cacerts, X509_free);
4457 return (rv);
4460 static KMF_RETURN
4461 create_deskey(DES_cblock **deskey)
4463 DES_cblock *key;
4465 key = (DES_cblock *) malloc(sizeof (DES_cblock));
4466 if (key == NULL) {
4467 return (KMF_ERR_MEMORY);
4470 if (DES_random_key(key) == 0) {
4471 free(key);
4472 return (KMF_ERR_KEYGEN_FAILED);
4475 *deskey = key;
4476 return (KMF_OK);
4479 #define KEYGEN_RETRY 3
4480 #define DES3_KEY_SIZE 24
4482 static KMF_RETURN
4483 create_des3key(unsigned char **des3key)
4485 KMF_RETURN ret = KMF_OK;
4486 DES_cblock *deskey1 = NULL;
4487 DES_cblock *deskey2 = NULL;
4488 DES_cblock *deskey3 = NULL;
4489 unsigned char *newkey = NULL;
4490 int retry;
4492 if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4493 return (KMF_ERR_MEMORY);
4496 /* create the 1st DES key */
4497 if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4498 goto out;
4502 * Create the 2nd DES key and make sure its value is different
4503 * from the 1st DES key.
4505 retry = 0;
4506 do {
4507 if (deskey2 != NULL) {
4508 free(deskey2);
4509 deskey2 = NULL;
4512 if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4513 goto out;
4516 if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4517 == 0) {
4518 ret = KMF_ERR_KEYGEN_FAILED;
4519 retry++;
4521 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4523 if (ret != KMF_OK) {
4524 goto out;
4528 * Create the 3rd DES key and make sure its value is different
4529 * from the 2nd DES key.
4531 retry = 0;
4532 do {
4533 if (deskey3 != NULL) {
4534 free(deskey3);
4535 deskey3 = NULL;
4538 if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4539 goto out;
4542 if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4543 == 0) {
4544 ret = KMF_ERR_KEYGEN_FAILED;
4545 retry++;
4547 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4549 if (ret != KMF_OK) {
4550 goto out;
4553 /* Concatenate 3 DES keys into a DES3 key */
4554 (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4555 (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4556 (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4557 *des3key = newkey;
4559 out:
4560 if (deskey1 != NULL)
4561 free(deskey1);
4563 if (deskey2 != NULL)
4564 free(deskey2);
4566 if (deskey3 != NULL)
4567 free(deskey3);
4569 if (ret != KMF_OK && newkey != NULL)
4570 free(newkey);
4572 return (ret);
4575 KMF_RETURN
4576 OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4577 int numattr, KMF_ATTRIBUTE *attrlist)
4579 KMF_RETURN ret = KMF_OK;
4580 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4581 char *fullpath = NULL;
4582 KMF_RAW_SYM_KEY *rkey = NULL;
4583 DES_cblock *deskey = NULL;
4584 unsigned char *des3key = NULL;
4585 unsigned char *random = NULL;
4586 int fd = -1;
4587 KMF_KEY_HANDLE *symkey;
4588 KMF_KEY_ALG keytype;
4589 uint32_t keylen;
4590 uint32_t keylen_size = sizeof (keylen);
4591 char *dirpath;
4592 char *keyfile;
4594 if (kmfh == NULL)
4595 return (KMF_ERR_UNINITIALIZED);
4597 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4598 if (symkey == NULL)
4599 return (KMF_ERR_BAD_PARAMETER);
4601 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4603 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4604 if (keyfile == NULL)
4605 return (KMF_ERR_BAD_PARAMETER);
4607 ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4608 (void *)&keytype, NULL);
4609 if (ret != KMF_OK)
4610 return (KMF_ERR_BAD_PARAMETER);
4612 ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4613 &keylen, &keylen_size);
4614 if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4615 (keytype == KMF_DES || keytype == KMF_DES3))
4616 /* keylength is not required for DES and 3DES */
4617 ret = KMF_OK;
4618 if (ret != KMF_OK)
4619 return (KMF_ERR_BAD_PARAMETER);
4621 fullpath = get_fullpath(dirpath, keyfile);
4622 if (fullpath == NULL)
4623 return (KMF_ERR_BAD_PARAMETER);
4625 /* If the requested file exists, return an error */
4626 if (test_for_file(fullpath, 0400) == 1) {
4627 free(fullpath);
4628 return (KMF_ERR_DUPLICATE_KEYFILE);
4631 fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4632 if (fd == -1) {
4633 ret = KMF_ERR_OPEN_FILE;
4634 goto out;
4637 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4638 if (rkey == NULL) {
4639 ret = KMF_ERR_MEMORY;
4640 goto out;
4642 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4644 if (keytype == KMF_DES) {
4645 if ((ret = create_deskey(&deskey)) != KMF_OK) {
4646 goto out;
4648 rkey->keydata.val = (uchar_t *)deskey;
4649 rkey->keydata.len = 8;
4651 symkey->keyalg = KMF_DES;
4653 } else if (keytype == KMF_DES3) {
4654 if ((ret = create_des3key(&des3key)) != KMF_OK) {
4655 goto out;
4657 rkey->keydata.val = (uchar_t *)des3key;
4658 rkey->keydata.len = DES3_KEY_SIZE;
4659 symkey->keyalg = KMF_DES3;
4661 } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4662 keytype == KMF_GENERIC_SECRET) {
4663 int bytes;
4665 if (keylen % 8 != 0) {
4666 ret = KMF_ERR_BAD_KEY_SIZE;
4667 goto out;
4670 if (keytype == KMF_AES) {
4671 if (keylen != 128 &&
4672 keylen != 192 &&
4673 keylen != 256) {
4674 ret = KMF_ERR_BAD_KEY_SIZE;
4675 goto out;
4679 bytes = keylen/8;
4680 random = malloc(bytes);
4681 if (random == NULL) {
4682 ret = KMF_ERR_MEMORY;
4683 goto out;
4685 if (RAND_bytes(random, bytes) != 1) {
4686 ret = KMF_ERR_KEYGEN_FAILED;
4687 goto out;
4690 rkey->keydata.val = (uchar_t *)random;
4691 rkey->keydata.len = bytes;
4692 symkey->keyalg = keytype;
4694 } else {
4695 ret = KMF_ERR_BAD_KEY_TYPE;
4696 goto out;
4699 (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4701 symkey->kstype = KMF_KEYSTORE_OPENSSL;
4702 symkey->keyclass = KMF_SYMMETRIC;
4703 symkey->keylabel = (char *)fullpath;
4704 symkey->israw = TRUE;
4705 symkey->keyp = rkey;
4707 out:
4708 if (fd != -1)
4709 (void) close(fd);
4711 if (ret != KMF_OK && fullpath != NULL) {
4712 free(fullpath);
4714 if (ret != KMF_OK) {
4715 kmf_free_raw_sym_key(rkey);
4716 symkey->keyp = NULL;
4717 symkey->keyalg = KMF_KEYALG_NONE;
4720 return (ret);
4724 * Check a file to see if it is a CRL file with PEM or DER format.
4725 * If success, return its format in the "pformat" argument.
4727 KMF_RETURN
4728 OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4730 KMF_RETURN ret = KMF_OK;
4731 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4732 BIO *bio = NULL;
4733 X509_CRL *xcrl = NULL;
4735 if (filename == NULL) {
4736 return (KMF_ERR_BAD_PARAMETER);
4739 bio = BIO_new_file(filename, "rb");
4740 if (bio == NULL) {
4741 SET_ERROR(kmfh, ERR_get_error());
4742 ret = KMF_ERR_OPEN_FILE;
4743 goto out;
4746 if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4747 *pformat = KMF_FORMAT_PEM;
4748 goto out;
4750 (void) BIO_free(bio);
4753 * Now try to read it as raw DER data.
4755 bio = BIO_new_file(filename, "rb");
4756 if (bio == NULL) {
4757 SET_ERROR(kmfh, ERR_get_error());
4758 ret = KMF_ERR_OPEN_FILE;
4759 goto out;
4762 if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4763 *pformat = KMF_FORMAT_ASN1;
4764 } else {
4765 ret = KMF_ERR_BAD_CRLFILE;
4768 out:
4769 if (bio != NULL)
4770 (void) BIO_free(bio);
4772 if (xcrl != NULL)
4773 X509_CRL_free(xcrl);
4775 return (ret);
4778 KMF_RETURN
4779 OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4780 KMF_RAW_SYM_KEY *rkey)
4782 KMF_RETURN rv = KMF_OK;
4783 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4784 KMF_DATA keyvalue;
4786 if (kmfh == NULL)
4787 return (KMF_ERR_UNINITIALIZED);
4789 if (symkey == NULL || rkey == NULL)
4790 return (KMF_ERR_BAD_PARAMETER);
4791 else if (symkey->keyclass != KMF_SYMMETRIC)
4792 return (KMF_ERR_BAD_KEY_CLASS);
4794 if (symkey->israw) {
4795 KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4797 if (rawkey == NULL ||
4798 rawkey->keydata.val == NULL ||
4799 rawkey->keydata.len == 0)
4800 return (KMF_ERR_BAD_KEYHANDLE);
4802 rkey->keydata.len = rawkey->keydata.len;
4803 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4804 return (KMF_ERR_MEMORY);
4805 (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4806 rkey->keydata.len);
4807 } else {
4808 rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4809 if (rv != KMF_OK)
4810 return (rv);
4811 rkey->keydata.len = keyvalue.Length;
4812 rkey->keydata.val = keyvalue.Data;
4815 return (rv);
4819 * substitute for the unsafe access(2) function.
4820 * If the file in question already exists, return 1.
4821 * else 0. If an error occurs during testing (other
4822 * than EEXIST), return -1.
4824 static int
4825 test_for_file(char *filename, mode_t mode)
4827 int fd;
4830 * Try to create the file with the EXCL flag.
4831 * The call should fail if the file exists.
4833 fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4834 if (fd == -1 && errno == EEXIST)
4835 return (1);
4836 else if (fd == -1) /* some other error */
4837 return (-1);
4839 /* The file did NOT exist. Delete the testcase. */
4840 (void) close(fd);
4841 (void) unlink(filename);
4842 return (0);
4845 KMF_RETURN
4846 OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4847 KMF_ATTRIBUTE *attrlist)
4849 KMF_RETURN rv = KMF_OK;
4850 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4851 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4852 KMF_RAW_KEY_DATA *rawkey;
4853 EVP_PKEY *pkey = NULL;
4854 KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4855 KMF_CREDENTIAL cred = {NULL, 0};
4856 BIO *out = NULL;
4857 int keys = 0;
4858 char *fullpath = NULL;
4859 char *keyfile = NULL;
4860 char *dirpath = NULL;
4862 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4863 if (pubkey != NULL)
4864 keys++;
4866 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4867 if (prikey != NULL)
4868 keys++;
4870 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4871 if (rawkey != NULL)
4872 keys++;
4875 * Exactly 1 type of key must be passed to this function.
4877 if (keys != 1)
4878 return (KMF_ERR_BAD_PARAMETER);
4880 keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4881 numattr);
4882 if (keyfile == NULL)
4883 return (KMF_ERR_BAD_PARAMETER);
4885 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4887 fullpath = get_fullpath(dirpath, keyfile);
4889 /* Once we have the full path, we don't need the pieces */
4890 if (fullpath == NULL)
4891 return (KMF_ERR_BAD_PARAMETER);
4893 /* If the requested file exists, return an error */
4894 if (test_for_file(fullpath, 0400) == 1) {
4895 free(fullpath);
4896 return (KMF_ERR_DUPLICATE_KEYFILE);
4899 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4900 &format, NULL);
4901 if (rv != KMF_OK)
4902 /* format is optional. */
4903 rv = KMF_OK;
4905 /* CRED is not required for OpenSSL files */
4906 (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4907 &cred, NULL);
4909 /* Store the private key to the keyfile */
4910 out = BIO_new_file(fullpath, "wb");
4911 if (out == NULL) {
4912 SET_ERROR(kmfh, ERR_get_error());
4913 rv = KMF_ERR_OPEN_FILE;
4914 goto end;
4917 if (prikey != NULL && prikey->keyp != NULL) {
4918 if (prikey->keyalg == KMF_RSA ||
4919 prikey->keyalg == KMF_DSA) {
4920 pkey = (EVP_PKEY *)prikey->keyp;
4922 rv = ssl_write_key(kmfh, format,
4923 out, &cred, pkey, TRUE);
4925 if (rv == KMF_OK && prikey->keylabel == NULL) {
4926 prikey->keylabel = strdup(fullpath);
4927 if (prikey->keylabel == NULL)
4928 rv = KMF_ERR_MEMORY;
4931 } else if (pubkey != NULL && pubkey->keyp != NULL) {
4932 if (pubkey->keyalg == KMF_RSA ||
4933 pubkey->keyalg == KMF_DSA) {
4934 pkey = (EVP_PKEY *)pubkey->keyp;
4936 rv = ssl_write_key(kmfh, format,
4937 out, &cred, pkey, FALSE);
4939 if (rv == KMF_OK && pubkey->keylabel == NULL) {
4940 pubkey->keylabel = strdup(fullpath);
4941 if (pubkey->keylabel == NULL)
4942 rv = KMF_ERR_MEMORY;
4945 } else if (rawkey != NULL) {
4946 if (rawkey->keytype == KMF_RSA) {
4947 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
4948 } else if (rawkey->keytype == KMF_DSA) {
4949 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
4950 } else {
4951 rv = KMF_ERR_BAD_PARAMETER;
4953 if (pkey != NULL) {
4954 KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
4956 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
4957 (void *)&kclass, NULL);
4958 if (rv != KMF_OK)
4959 rv = KMF_OK;
4960 rv = ssl_write_key(kmfh, format, out,
4961 &cred, pkey, (kclass == KMF_ASYM_PRI));
4962 EVP_PKEY_free(pkey);
4966 end:
4968 if (out)
4969 (void) BIO_free(out);
4972 if (rv == KMF_OK)
4973 (void) chmod(fullpath, 0400);
4975 free(fullpath);
4976 return (rv);
4979 KMF_RETURN
4980 OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4982 KMF_RETURN ret = KMF_OK;
4983 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4984 X509_CRL *xcrl = NULL;
4985 X509 *xcert = NULL;
4986 EVP_PKEY *pkey;
4987 KMF_ENCODE_FORMAT format;
4988 BIO *in = NULL, *out = NULL;
4989 int openssl_ret = 0;
4990 KMF_ENCODE_FORMAT outformat;
4991 boolean_t crlcheck = FALSE;
4992 char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
4994 if (numattr == 0 || attrlist == NULL) {
4995 return (KMF_ERR_BAD_PARAMETER);
4998 /* CRL check is optional */
4999 (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
5000 &crlcheck, NULL);
5002 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5003 if (crlcheck == B_TRUE && certfile == NULL) {
5004 return (KMF_ERR_BAD_CERTFILE);
5007 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5008 incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5009 outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5011 crlfile = get_fullpath(dirpath, incrl);
5013 if (crlfile == NULL)
5014 return (KMF_ERR_BAD_CRLFILE);
5016 outcrlfile = get_fullpath(dirpath, outcrl);
5017 if (outcrlfile == NULL)
5018 return (KMF_ERR_BAD_CRLFILE);
5020 if (isdir(outcrlfile)) {
5021 free(outcrlfile);
5022 return (KMF_ERR_BAD_CRLFILE);
5025 ret = kmf_is_crl_file(handle, crlfile, &format);
5026 if (ret != KMF_OK) {
5027 free(outcrlfile);
5028 return (ret);
5031 in = BIO_new_file(crlfile, "rb");
5032 if (in == NULL) {
5033 SET_ERROR(kmfh, ERR_get_error());
5034 ret = KMF_ERR_OPEN_FILE;
5035 goto end;
5038 if (format == KMF_FORMAT_ASN1) {
5039 xcrl = d2i_X509_CRL_bio(in, NULL);
5040 } else if (format == KMF_FORMAT_PEM) {
5041 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5044 if (xcrl == NULL) {
5045 SET_ERROR(kmfh, ERR_get_error());
5046 ret = KMF_ERR_BAD_CRLFILE;
5047 goto end;
5050 /* If bypasscheck is specified, no need to verify. */
5051 if (crlcheck == B_FALSE)
5052 goto output;
5054 ret = kmf_is_cert_file(handle, certfile, &format);
5055 if (ret != KMF_OK)
5056 goto end;
5058 /* Read in the CA cert file and convert to X509 */
5059 if (BIO_read_filename(in, certfile) <= 0) {
5060 SET_ERROR(kmfh, ERR_get_error());
5061 ret = KMF_ERR_OPEN_FILE;
5062 goto end;
5065 if (format == KMF_FORMAT_ASN1) {
5066 xcert = d2i_X509_bio(in, NULL);
5067 } else if (format == KMF_FORMAT_PEM) {
5068 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5069 } else {
5070 ret = KMF_ERR_BAD_CERT_FORMAT;
5071 goto end;
5074 if (xcert == NULL) {
5075 SET_ERROR(kmfh, ERR_get_error());
5076 ret = KMF_ERR_BAD_CERT_FORMAT;
5077 goto end;
5079 /* Now get the public key from the CA cert */
5080 pkey = X509_get_pubkey(xcert);
5081 if (pkey == NULL) {
5082 SET_ERROR(kmfh, ERR_get_error());
5083 ret = KMF_ERR_BAD_CERTFILE;
5084 goto end;
5087 /* Verify the CRL with the CA's public key */
5088 openssl_ret = X509_CRL_verify(xcrl, pkey);
5089 EVP_PKEY_free(pkey);
5090 if (openssl_ret > 0) {
5091 ret = KMF_OK; /* verify succeed */
5092 } else {
5093 SET_ERROR(kmfh, openssl_ret);
5094 ret = KMF_ERR_BAD_CRLFILE;
5097 output:
5098 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5099 &outformat, NULL);
5100 if (ret != KMF_OK) {
5101 ret = KMF_OK;
5102 outformat = KMF_FORMAT_PEM;
5105 out = BIO_new_file(outcrlfile, "wb");
5106 if (out == NULL) {
5107 SET_ERROR(kmfh, ERR_get_error());
5108 ret = KMF_ERR_OPEN_FILE;
5109 goto end;
5112 if (outformat == KMF_FORMAT_ASN1) {
5113 openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5114 } else if (outformat == KMF_FORMAT_PEM) {
5115 openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5116 } else {
5117 ret = KMF_ERR_BAD_PARAMETER;
5118 goto end;
5121 if (openssl_ret <= 0) {
5122 SET_ERROR(kmfh, ERR_get_error());
5123 ret = KMF_ERR_WRITE_FILE;
5124 } else {
5125 ret = KMF_OK;
5128 end:
5129 if (xcrl != NULL)
5130 X509_CRL_free(xcrl);
5132 if (xcert != NULL)
5133 X509_free(xcert);
5135 if (in != NULL)
5136 (void) BIO_free(in);
5138 if (out != NULL)
5139 (void) BIO_free(out);
5141 if (outcrlfile != NULL)
5142 free(outcrlfile);
5144 return (ret);
5147 KMF_RETURN
5148 OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5150 KMF_RETURN ret = KMF_OK;
5151 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5152 X509_CRL *x = NULL;
5153 KMF_ENCODE_FORMAT format;
5154 char *crlfile = NULL;
5155 BIO *in = NULL;
5156 BIO *mem = NULL;
5157 long len;
5158 char *memptr;
5159 char *data = NULL;
5160 char **crldata;
5161 char *crlfilename, *dirpath;
5163 if (numattr == 0 || attrlist == NULL) {
5164 return (KMF_ERR_BAD_PARAMETER);
5166 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5167 attrlist, numattr);
5168 if (crlfilename == NULL)
5169 return (KMF_ERR_BAD_CRLFILE);
5171 crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5172 attrlist, numattr);
5174 if (crldata == NULL)
5175 return (KMF_ERR_BAD_PARAMETER);
5177 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5179 crlfile = get_fullpath(dirpath, crlfilename);
5181 if (crlfile == NULL)
5182 return (KMF_ERR_BAD_CRLFILE);
5184 if (isdir(crlfile)) {
5185 free(crlfile);
5186 return (KMF_ERR_BAD_CRLFILE);
5189 ret = kmf_is_crl_file(handle, crlfile, &format);
5190 if (ret != KMF_OK) {
5191 free(crlfile);
5192 return (ret);
5195 if (bio_err == NULL)
5196 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5198 in = BIO_new_file(crlfile, "rb");
5199 if (in == NULL) {
5200 SET_ERROR(kmfh, ERR_get_error());
5201 ret = KMF_ERR_OPEN_FILE;
5202 goto end;
5205 if (format == KMF_FORMAT_ASN1) {
5206 x = d2i_X509_CRL_bio(in, NULL);
5207 } else if (format == KMF_FORMAT_PEM) {
5208 x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5211 if (x == NULL) { /* should not happen */
5212 SET_ERROR(kmfh, ERR_get_error());
5213 ret = KMF_ERR_OPEN_FILE;
5214 goto end;
5217 mem = BIO_new(BIO_s_mem());
5218 if (mem == NULL) {
5219 SET_ERROR(kmfh, ERR_get_error());
5220 ret = KMF_ERR_MEMORY;
5221 goto end;
5224 (void) X509_CRL_print(mem, x);
5225 len = BIO_get_mem_data(mem, &memptr);
5226 if (len <= 0) {
5227 SET_ERROR(kmfh, ERR_get_error());
5228 ret = KMF_ERR_MEMORY;
5229 goto end;
5232 data = malloc(len + 1);
5233 if (data == NULL) {
5234 ret = KMF_ERR_MEMORY;
5235 goto end;
5238 (void) memcpy(data, memptr, len);
5239 data[len] = '\0';
5240 *crldata = data;
5242 end:
5243 if (x != NULL)
5244 X509_CRL_free(x);
5246 if (crlfile != NULL)
5247 free(crlfile);
5249 if (in != NULL)
5250 (void) BIO_free(in);
5252 if (mem != NULL)
5253 (void) BIO_free(mem);
5255 return (ret);
5258 KMF_RETURN
5259 OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5261 KMF_RETURN ret = KMF_OK;
5262 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5263 KMF_ENCODE_FORMAT format;
5264 char *crlfile = NULL;
5265 BIO *in = NULL;
5266 char *crlfilename, *dirpath;
5268 if (numattr == 0 || attrlist == NULL) {
5269 return (KMF_ERR_BAD_PARAMETER);
5272 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5273 attrlist, numattr);
5275 if (crlfilename == NULL)
5276 return (KMF_ERR_BAD_CRLFILE);
5278 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5280 crlfile = get_fullpath(dirpath, crlfilename);
5282 if (crlfile == NULL)
5283 return (KMF_ERR_BAD_CRLFILE);
5285 if (isdir(crlfile)) {
5286 ret = KMF_ERR_BAD_CRLFILE;
5287 goto end;
5290 ret = kmf_is_crl_file(handle, crlfile, &format);
5291 if (ret != KMF_OK)
5292 goto end;
5294 if (unlink(crlfile) != 0) {
5295 SET_SYS_ERROR(kmfh, errno);
5296 ret = KMF_ERR_INTERNAL;
5297 goto end;
5300 end:
5301 if (in != NULL)
5302 (void) BIO_free(in);
5303 if (crlfile != NULL)
5304 free(crlfile);
5306 return (ret);
5309 KMF_RETURN
5310 OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5312 KMF_RETURN ret = KMF_OK;
5313 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5314 KMF_ENCODE_FORMAT format;
5315 BIO *in = NULL;
5316 X509 *xcert = NULL;
5317 X509_CRL *xcrl = NULL;
5318 STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5319 X509_REVOKED *revoke;
5320 int i;
5321 char *crlfilename, *crlfile, *dirpath, *certfile;
5323 if (numattr == 0 || attrlist == NULL) {
5324 return (KMF_ERR_BAD_PARAMETER);
5327 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5328 attrlist, numattr);
5330 if (crlfilename == NULL)
5331 return (KMF_ERR_BAD_CRLFILE);
5333 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5334 if (certfile == NULL)
5335 return (KMF_ERR_BAD_CRLFILE);
5337 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5339 crlfile = get_fullpath(dirpath, crlfilename);
5341 if (crlfile == NULL)
5342 return (KMF_ERR_BAD_CRLFILE);
5344 if (isdir(crlfile)) {
5345 ret = KMF_ERR_BAD_CRLFILE;
5346 goto end;
5349 ret = kmf_is_crl_file(handle, crlfile, &format);
5350 if (ret != KMF_OK)
5351 goto end;
5353 /* Read the CRL file and load it into a X509_CRL structure */
5354 in = BIO_new_file(crlfilename, "rb");
5355 if (in == NULL) {
5356 SET_ERROR(kmfh, ERR_get_error());
5357 ret = KMF_ERR_OPEN_FILE;
5358 goto end;
5361 if (format == KMF_FORMAT_ASN1) {
5362 xcrl = d2i_X509_CRL_bio(in, NULL);
5363 } else if (format == KMF_FORMAT_PEM) {
5364 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5367 if (xcrl == NULL) {
5368 SET_ERROR(kmfh, ERR_get_error());
5369 ret = KMF_ERR_BAD_CRLFILE;
5370 goto end;
5372 (void) BIO_free(in);
5374 /* Read the Certificate file and load it into a X509 structure */
5375 ret = kmf_is_cert_file(handle, certfile, &format);
5376 if (ret != KMF_OK)
5377 goto end;
5379 in = BIO_new_file(certfile, "rb");
5380 if (in == NULL) {
5381 SET_ERROR(kmfh, ERR_get_error());
5382 ret = KMF_ERR_OPEN_FILE;
5383 goto end;
5386 if (format == KMF_FORMAT_ASN1) {
5387 xcert = d2i_X509_bio(in, NULL);
5388 } else if (format == KMF_FORMAT_PEM) {
5389 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5392 if (xcert == NULL) {
5393 SET_ERROR(kmfh, ERR_get_error());
5394 ret = KMF_ERR_BAD_CERTFILE;
5395 goto end;
5398 /* Check if the certificate and the CRL have same issuer */
5399 if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
5400 ret = KMF_ERR_ISSUER;
5401 goto end;
5404 /* Check to see if the certificate serial number is revoked */
5405 revoke_stack = X509_CRL_get_REVOKED(xcrl);
5406 if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5407 /* No revoked certificates in the CRL file */
5408 SET_ERROR(kmfh, ERR_get_error());
5409 ret = KMF_ERR_EMPTY_CRL;
5410 goto end;
5413 for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5414 revoke = sk_X509_REVOKED_value(revoke_stack, i);
5415 if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
5416 revoke->serialNumber) == 0) {
5417 break;
5421 if (i < sk_X509_REVOKED_num(revoke_stack)) {
5422 ret = KMF_OK;
5423 } else {
5424 ret = KMF_ERR_NOT_REVOKED;
5427 end:
5428 if (in != NULL)
5429 (void) BIO_free(in);
5430 if (xcrl != NULL)
5431 X509_CRL_free(xcrl);
5432 if (xcert != NULL)
5433 X509_free(xcert);
5435 return (ret);
5438 KMF_RETURN
5439 OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5441 KMF_RETURN ret = KMF_OK;
5442 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5443 BIO *bcrl = NULL;
5444 X509_CRL *xcrl = NULL;
5445 X509 *xcert = NULL;
5446 EVP_PKEY *pkey;
5447 int sslret;
5448 KMF_ENCODE_FORMAT crl_format;
5449 unsigned char *p;
5450 long len;
5452 if (handle == NULL || crlname == NULL || tacert == NULL) {
5453 return (KMF_ERR_BAD_PARAMETER);
5456 ret = kmf_get_file_format(crlname, &crl_format);
5457 if (ret != KMF_OK)
5458 return (ret);
5460 bcrl = BIO_new_file(crlname, "rb");
5461 if (bcrl == NULL) {
5462 SET_ERROR(kmfh, ERR_get_error());
5463 ret = KMF_ERR_OPEN_FILE;
5464 goto cleanup;
5467 if (crl_format == KMF_FORMAT_ASN1) {
5468 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5469 } else if (crl_format == KMF_FORMAT_PEM) {
5470 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5471 } else {
5472 ret = KMF_ERR_BAD_PARAMETER;
5473 goto cleanup;
5476 if (xcrl == NULL) {
5477 SET_ERROR(kmfh, ERR_get_error());
5478 ret = KMF_ERR_BAD_CRLFILE;
5479 goto cleanup;
5482 p = tacert->Data;
5483 len = tacert->Length;
5484 xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5486 if (xcert == NULL) {
5487 SET_ERROR(kmfh, ERR_get_error());
5488 ret = KMF_ERR_BAD_CERTFILE;
5489 goto cleanup;
5492 /* Get issuer certificate public key */
5493 pkey = X509_get_pubkey(xcert);
5494 if (pkey == NULL) {
5495 SET_ERROR(kmfh, ERR_get_error());
5496 ret = KMF_ERR_BAD_CERT_FORMAT;
5497 goto cleanup;
5500 /* Verify CRL signature */
5501 sslret = X509_CRL_verify(xcrl, pkey);
5502 EVP_PKEY_free(pkey);
5503 if (sslret > 0) {
5504 ret = KMF_OK;
5505 } else {
5506 SET_ERROR(kmfh, sslret);
5507 ret = KMF_ERR_BAD_CRLFILE;
5510 cleanup:
5511 if (bcrl != NULL)
5512 (void) BIO_free(bcrl);
5514 if (xcrl != NULL)
5515 X509_CRL_free(xcrl);
5517 if (xcert != NULL)
5518 X509_free(xcert);
5520 return (ret);
5524 KMF_RETURN
5525 OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5527 KMF_RETURN ret = KMF_OK;
5528 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5529 KMF_ENCODE_FORMAT crl_format;
5530 BIO *bcrl = NULL;
5531 X509_CRL *xcrl = NULL;
5532 int i;
5534 if (handle == NULL || crlname == NULL) {
5535 return (KMF_ERR_BAD_PARAMETER);
5538 ret = kmf_is_crl_file(handle, crlname, &crl_format);
5539 if (ret != KMF_OK)
5540 return (ret);
5542 bcrl = BIO_new_file(crlname, "rb");
5543 if (bcrl == NULL) {
5544 SET_ERROR(kmfh, ERR_get_error());
5545 ret = KMF_ERR_OPEN_FILE;
5546 goto cleanup;
5549 if (crl_format == KMF_FORMAT_ASN1)
5550 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5551 else if (crl_format == KMF_FORMAT_PEM)
5552 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5554 if (xcrl == NULL) {
5555 SET_ERROR(kmfh, ERR_get_error());
5556 ret = KMF_ERR_BAD_CRLFILE;
5557 goto cleanup;
5559 i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
5560 if (i >= 0) {
5561 ret = KMF_ERR_VALIDITY_PERIOD;
5562 goto cleanup;
5564 if (X509_CRL_get_nextUpdate(xcrl)) {
5565 i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
5567 if (i <= 0) {
5568 ret = KMF_ERR_VALIDITY_PERIOD;
5569 goto cleanup;
5573 ret = KMF_OK;
5575 cleanup:
5576 if (bcrl != NULL)
5577 (void) BIO_free(bcrl);
5579 if (xcrl != NULL)
5580 X509_CRL_free(xcrl);
5582 return (ret);