8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libkmf / plugins / kmf_openssl / common / openssl_spi.c
blob94225f846a25ef6063626ab10b9ae53ae3aacaa4
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 = { 0, NULL };
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_SHA1WithRSA)
1806 md = EVP_sha1();
1807 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1808 md = EVP_sha256();
1809 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1810 md = EVP_sha384();
1811 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1812 md = EVP_sha512();
1813 else if (AlgId == KMF_ALGID_RSA)
1814 md = NULL;
1815 else
1816 return (KMF_ERR_BAD_ALGORITHM);
1818 if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
1819 RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
1821 p = output->Data;
1822 if ((len = RSA_private_encrypt(tobesigned->Length,
1823 tobesigned->Data, p, rsa,
1824 RSA_PKCS1_PADDING)) <= 0) {
1825 SET_ERROR(kmfh, ERR_get_error());
1826 ret = KMF_ERR_INTERNAL;
1828 output->Length = len;
1829 } else {
1830 (void) EVP_MD_CTX_init(&ctx);
1831 (void) EVP_SignInit_ex(&ctx, md, NULL);
1832 (void) EVP_SignUpdate(&ctx, tobesigned->Data,
1833 (uint32_t)tobesigned->Length);
1834 len = (uint32_t)output->Length;
1835 p = output->Data;
1836 if (!EVP_SignFinal(&ctx, p, (uint32_t *)&len, pkey)) {
1837 SET_ERROR(kmfh, ERR_get_error());
1838 len = 0;
1839 ret = KMF_ERR_INTERNAL;
1841 output->Length = len;
1842 (void) EVP_MD_CTX_cleanup(&ctx);
1844 } else if (key->keyalg == KMF_DSA) {
1845 DSA *dsa = EVP_PKEY_get1_DSA(key->keyp);
1847 uchar_t hash[EVP_MAX_MD_SIZE];
1848 uint32_t hashlen;
1849 DSA_SIG *dsasig;
1851 if (AlgId == KMF_ALGID_DSA ||
1852 AlgId == KMF_ALGID_SHA1WithDSA)
1853 md = EVP_sha1();
1854 else if (AlgId == KMF_ALGID_SHA256WithDSA)
1855 md = EVP_sha256();
1856 else /* Bad algorithm */
1857 return (KMF_ERR_BAD_ALGORITHM);
1860 * OpenSSL EVP_Sign operation automatically converts to
1861 * ASN.1 output so we do the operations separately so we
1862 * are assured of NOT getting ASN.1 output returned.
1863 * KMF does not want ASN.1 encoded results because
1864 * not all mechanisms return ASN.1 encodings (PKCS#11
1865 * and NSS return raw signature data).
1867 EVP_MD_CTX_init(&ctx);
1868 (void) EVP_DigestInit_ex(&ctx, md, NULL);
1869 (void) EVP_DigestUpdate(&ctx, tobesigned->Data,
1870 tobesigned->Length);
1871 (void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
1873 /* Only sign first 20 bytes for SHA2 */
1874 if (AlgId == KMF_ALGID_SHA256WithDSA)
1875 hashlen = 20;
1876 dsasig = DSA_do_sign(hash, hashlen, dsa);
1877 if (dsasig != NULL) {
1878 int i;
1879 output->Length = i = fixbnlen(dsasig->r, output->Data,
1880 hashlen);
1882 output->Length += fixbnlen(dsasig->s, &output->Data[i],
1883 hashlen);
1885 DSA_SIG_free(dsasig);
1886 } else {
1887 SET_ERROR(kmfh, ERR_get_error());
1889 (void) EVP_MD_CTX_cleanup(&ctx);
1890 } else {
1891 return (KMF_ERR_BAD_PARAMETER);
1893 cleanup:
1894 return (ret);
1897 KMF_RETURN
1898 /*ARGSUSED*/
1899 OpenSSL_DeleteKey(KMF_HANDLE_T handle,
1900 int numattr, KMF_ATTRIBUTE *attrlist)
1902 KMF_RETURN rv = KMF_OK;
1903 KMF_KEY_HANDLE *key;
1904 boolean_t destroy = B_TRUE;
1906 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1907 if (key == NULL || key->keyp == NULL)
1908 return (KMF_ERR_BAD_PARAMETER);
1910 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1911 (void *)&destroy, NULL);
1912 if (rv != KMF_OK) {
1913 /* "destroy" is optional. Default is TRUE */
1914 rv = KMF_OK;
1917 if (key->keyclass != KMF_ASYM_PUB &&
1918 key->keyclass != KMF_ASYM_PRI &&
1919 key->keyclass != KMF_SYMMETRIC)
1920 return (KMF_ERR_BAD_KEY_CLASS);
1922 if (key->keyclass == KMF_SYMMETRIC) {
1923 kmf_free_raw_sym_key((KMF_RAW_SYM_KEY *)key->keyp);
1924 key->keyp = NULL;
1925 } else {
1926 if (key->keyp != NULL) {
1927 EVP_PKEY_free(key->keyp);
1928 key->keyp = NULL;
1932 if (key->keylabel != NULL) {
1933 EVP_PKEY *pkey = NULL;
1934 /* If the file exists, make sure it is a proper key. */
1935 pkey = openssl_load_key(handle, key->keylabel);
1936 if (pkey == NULL) {
1937 if (key->keylabel != NULL) {
1938 free(key->keylabel);
1939 key->keylabel = NULL;
1941 return (KMF_ERR_KEY_NOT_FOUND);
1943 EVP_PKEY_free(pkey);
1945 if (destroy) {
1946 if (unlink(key->keylabel) != 0) {
1947 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1948 SET_SYS_ERROR(kmfh, errno);
1949 rv = KMF_ERR_INTERNAL;
1952 if (key->keylabel != NULL) {
1953 free(key->keylabel);
1954 key->keylabel = NULL;
1957 return (rv);
1960 KMF_RETURN
1961 OpenSSL_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1963 KMF_RETURN ret = KMF_OK;
1964 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1965 char str[256]; /* OpenSSL needs at least 120 byte buffer */
1967 ERR_error_string_n(kmfh->lasterr.errcode, str, sizeof (str));
1968 if (strlen(str)) {
1969 *msgstr = (char *)strdup(str);
1970 if ((*msgstr) == NULL)
1971 ret = KMF_ERR_MEMORY;
1972 } else {
1973 *msgstr = NULL;
1976 return (ret);
1979 static int
1980 ext2NID(int kmfext)
1982 switch (kmfext) {
1983 case KMF_X509_EXT_KEY_USAGE:
1984 return (NID_key_usage);
1985 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
1986 return (NID_private_key_usage_period);
1987 case KMF_X509_EXT_CERT_POLICIES:
1988 return (NID_certificate_policies);
1989 case KMF_X509_EXT_SUBJ_ALTNAME:
1990 return (NID_subject_alt_name);
1991 case KMF_X509_EXT_ISSUER_ALTNAME:
1992 return (NID_issuer_alt_name);
1993 case KMF_X509_EXT_BASIC_CONSTRAINTS:
1994 return (NID_basic_constraints);
1995 case KMF_X509_EXT_EXT_KEY_USAGE:
1996 return (NID_ext_key_usage);
1997 case KMF_X509_EXT_AUTH_KEY_ID:
1998 return (NID_authority_key_identifier);
1999 case KMF_X509_EXT_CRL_DIST_POINTS:
2000 return (NID_crl_distribution_points);
2001 case KMF_X509_EXT_SUBJ_KEY_ID:
2002 return (NID_subject_key_identifier);
2003 case KMF_X509_EXT_POLICY_MAPPINGS:
2004 return (OBJ_sn2nid("policyMappings"));
2005 case KMF_X509_EXT_NAME_CONSTRAINTS:
2006 return (OBJ_sn2nid("nameConstraints"));
2007 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2008 return (OBJ_sn2nid("policyConstraints"));
2009 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2010 return (OBJ_sn2nid("inhibitAnyPolicy"));
2011 case KMF_X509_EXT_FRESHEST_CRL:
2012 return (OBJ_sn2nid("freshestCRL"));
2013 default:
2014 return (NID_undef);
2018 KMF_RETURN
2019 OpenSSL_CertGetPrintable(KMF_HANDLE_T handle, const KMF_DATA *pcert,
2020 KMF_PRINTABLE_ITEM flag, char *resultStr)
2022 KMF_RETURN ret = KMF_OK;
2023 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2024 X509 *xcert = NULL;
2025 unsigned char *outbuf = NULL;
2026 unsigned char *outbuf_p;
2027 char *tmpstr = NULL;
2028 int j;
2029 int ext_index, nid, len;
2030 BIO *mem = NULL;
2031 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2032 STACK *emlst = NULL;
2033 #else
2034 STACK_OF(OPENSSL_STRING) *emlst = NULL;
2035 #endif
2036 X509_EXTENSION *ex;
2037 X509_CINF *ci;
2039 if (pcert == NULL || pcert->Data == NULL || pcert->Length == 0) {
2040 return (KMF_ERR_BAD_PARAMETER);
2043 /* copy cert data to outbuf */
2044 outbuf = malloc(pcert->Length);
2045 if (outbuf == NULL) {
2046 return (KMF_ERR_MEMORY);
2048 (void) memcpy(outbuf, pcert->Data, pcert->Length);
2050 outbuf_p = outbuf; /* use a temp pointer; required by openssl */
2051 xcert = d2i_X509(NULL, (const uchar_t **)&outbuf_p, pcert->Length);
2052 if (xcert == NULL) {
2053 SET_ERROR(kmfh, ERR_get_error());
2054 ret = KMF_ERR_ENCODING;
2055 goto out;
2058 mem = BIO_new(BIO_s_mem());
2059 if (mem == NULL) {
2060 SET_ERROR(kmfh, ERR_get_error());
2061 ret = KMF_ERR_MEMORY;
2062 goto out;
2065 switch (flag) {
2066 case KMF_CERT_ISSUER:
2067 (void) X509_NAME_print_ex(mem, X509_get_issuer_name(xcert), 0,
2068 XN_FLAG_SEP_CPLUS_SPC);
2069 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2070 break;
2072 case KMF_CERT_SUBJECT:
2073 (void) X509_NAME_print_ex(mem, X509_get_subject_name(xcert), 0,
2074 XN_FLAG_SEP_CPLUS_SPC);
2075 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2076 break;
2078 case KMF_CERT_VERSION:
2079 tmpstr = i2s_ASN1_INTEGER(NULL, xcert->cert_info->version);
2080 (void) strncpy(resultStr, tmpstr, KMF_CERT_PRINTABLE_LEN);
2081 OPENSSL_free(tmpstr);
2082 len = strlen(resultStr);
2083 break;
2085 case KMF_CERT_SERIALNUM:
2086 if (i2a_ASN1_INTEGER(mem, X509_get_serialNumber(xcert)) > 0) {
2087 (void) strcpy(resultStr, "0x");
2088 len = BIO_gets(mem, &resultStr[2],
2089 KMF_CERT_PRINTABLE_LEN - 2);
2091 break;
2093 case KMF_CERT_NOTBEFORE:
2094 (void) ASN1_TIME_print(mem, X509_get_notBefore(xcert));
2095 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2096 break;
2098 case KMF_CERT_NOTAFTER:
2099 (void) ASN1_TIME_print(mem, X509_get_notAfter(xcert));
2100 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2101 break;
2103 case KMF_CERT_PUBKEY_DATA:
2105 EVP_PKEY *pkey = X509_get_pubkey(xcert);
2106 if (pkey == NULL) {
2107 SET_ERROR(kmfh, ERR_get_error());
2108 ret = KMF_ERR_ENCODING;
2109 goto out;
2112 if (pkey->type == EVP_PKEY_RSA) {
2113 (void) BIO_printf(mem,
2114 "RSA Public Key: (%d bit)\n",
2115 BN_num_bits(pkey->pkey.rsa->n));
2116 (void) RSA_print(mem, pkey->pkey.rsa, 0);
2117 } else if (pkey->type == EVP_PKEY_DSA) {
2118 (void) BIO_printf(mem,
2119 "%12sDSA Public Key:\n", "");
2120 (void) DSA_print(mem, pkey->pkey.dsa, 0);
2121 } else {
2122 (void) BIO_printf(mem,
2123 "%12sUnknown Public Key:\n", "");
2125 (void) BIO_printf(mem, "\n");
2126 EVP_PKEY_free(pkey);
2128 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2129 break;
2130 case KMF_CERT_SIGNATURE_ALG:
2131 case KMF_CERT_PUBKEY_ALG:
2132 if (flag == KMF_CERT_SIGNATURE_ALG) {
2133 len = i2a_ASN1_OBJECT(mem,
2134 xcert->sig_alg->algorithm);
2135 } else {
2136 len = i2a_ASN1_OBJECT(mem,
2137 xcert->cert_info->key->algor->algorithm);
2140 if (len > 0) {
2141 len = BIO_read(mem, resultStr,
2142 KMF_CERT_PRINTABLE_LEN);
2144 break;
2146 case KMF_CERT_EMAIL:
2147 emlst = X509_get1_email(xcert);
2148 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2149 for (j = 0; j < sk_num(emlst); j++)
2150 (void) BIO_printf(mem, "%s\n", sk_value(emlst, j));
2151 #else
2152 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
2153 (void) BIO_printf(mem, "%s\n",
2154 sk_OPENSSL_STRING_value(emlst, j));
2155 #endif
2157 len = BIO_gets(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2158 X509_email_free(emlst);
2159 break;
2160 case KMF_X509_EXT_ISSUER_ALTNAME:
2161 case KMF_X509_EXT_SUBJ_ALTNAME:
2162 case KMF_X509_EXT_KEY_USAGE:
2163 case KMF_X509_EXT_PRIV_KEY_USAGE_PERIOD:
2164 case KMF_X509_EXT_CERT_POLICIES:
2165 case KMF_X509_EXT_BASIC_CONSTRAINTS:
2166 case KMF_X509_EXT_NAME_CONSTRAINTS:
2167 case KMF_X509_EXT_POLICY_CONSTRAINTS:
2168 case KMF_X509_EXT_EXT_KEY_USAGE:
2169 case KMF_X509_EXT_INHIBIT_ANY_POLICY:
2170 case KMF_X509_EXT_AUTH_KEY_ID:
2171 case KMF_X509_EXT_SUBJ_KEY_ID:
2172 case KMF_X509_EXT_POLICY_MAPPINGS:
2173 case KMF_X509_EXT_CRL_DIST_POINTS:
2174 case KMF_X509_EXT_FRESHEST_CRL:
2175 nid = ext2NID(flag);
2176 if (nid == NID_undef) {
2177 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2178 goto out;
2180 ci = xcert->cert_info;
2182 ext_index = X509v3_get_ext_by_NID(ci->extensions, nid, -1);
2183 if (ext_index == -1) {
2184 SET_ERROR(kmfh, ERR_get_error());
2186 ret = KMF_ERR_EXTENSION_NOT_FOUND;
2187 goto out;
2189 ex = X509v3_get_ext(ci->extensions, ext_index);
2191 (void) i2a_ASN1_OBJECT(mem, X509_EXTENSION_get_object(ex));
2193 if (BIO_printf(mem, ": %s\n",
2194 X509_EXTENSION_get_critical(ex) ? "critical" : "") <= 0) {
2195 SET_ERROR(kmfh, ERR_get_error());
2196 ret = KMF_ERR_ENCODING;
2197 goto out;
2199 if (!X509V3_EXT_print(mem, ex, X509V3_EXT_DUMP_UNKNOWN, 4)) {
2200 (void) BIO_printf(mem, "%*s", 4, "");
2201 (void) M_ASN1_OCTET_STRING_print(mem, ex->value);
2203 if (BIO_write(mem, "\n", 1) <= 0) {
2204 SET_ERROR(kmfh, ERR_get_error());
2205 ret = KMF_ERR_ENCODING;
2206 goto out;
2208 len = BIO_read(mem, resultStr, KMF_CERT_PRINTABLE_LEN);
2210 if (len <= 0) {
2211 SET_ERROR(kmfh, ERR_get_error());
2212 ret = KMF_ERR_ENCODING;
2215 out:
2216 if (outbuf != NULL) {
2217 free(outbuf);
2220 if (xcert != NULL) {
2221 X509_free(xcert);
2224 if (mem != NULL) {
2225 (void) BIO_free(mem);
2228 return (ret);
2231 KMF_RETURN
2232 /*ARGSUSED*/
2233 OpenSSL_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
2234 KMF_ATTRIBUTE *attrlist)
2236 KMF_RETURN rv = KMF_OK;
2237 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2238 KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2239 KMF_KEY_HANDLE *key = NULL;
2240 uint32_t numkeys = 1; /* 1 key only */
2241 char *dirpath = NULL;
2242 char *keyfile = NULL;
2243 KMF_ATTRIBUTE new_attrlist[16];
2244 int i = 0;
2247 * This is really just a FindKey operation, reuse the
2248 * FindKey function.
2250 kmf_set_attr_at_index(new_attrlist, i,
2251 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
2252 i++;
2254 kmf_set_attr_at_index(new_attrlist, i,
2255 KMF_COUNT_ATTR, &numkeys, sizeof (uint32_t));
2256 i++;
2258 kmf_set_attr_at_index(new_attrlist, i,
2259 KMF_KEYCLASS_ATTR, &keyclass, sizeof (keyclass));
2260 i++;
2262 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2263 if (key == NULL) {
2264 return (KMF_ERR_BAD_PARAMETER);
2265 } else {
2266 kmf_set_attr_at_index(new_attrlist, i,
2267 KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
2268 i++;
2271 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2272 if (dirpath != NULL) {
2273 kmf_set_attr_at_index(new_attrlist, i,
2274 KMF_DIRPATH_ATTR, dirpath, strlen(dirpath));
2275 i++;
2278 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2279 if (keyfile == NULL)
2280 return (KMF_ERR_BAD_PARAMETER);
2281 else {
2282 kmf_set_attr_at_index(new_attrlist, i,
2283 KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
2284 i++;
2287 rv = OpenSSL_FindKey(handle, i, new_attrlist);
2288 return (rv);
2291 KMF_RETURN
2292 /*ARGSUSED*/
2293 OpenSSL_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
2294 KMF_OID *AlgOID, KMF_DATA *ciphertext,
2295 KMF_DATA *output)
2297 KMF_RETURN ret = KMF_OK;
2298 RSA *rsa = NULL;
2299 unsigned int in_len = 0, out_len = 0;
2300 unsigned int total_decrypted = 0, modulus_len = 0;
2301 uint8_t *in_data, *out_data;
2302 int i, blocks;
2304 if (key == NULL || AlgOID == NULL ||
2305 ciphertext == NULL || output == NULL ||
2306 ciphertext->Data == NULL ||
2307 output->Data == NULL)
2308 return (KMF_ERR_BAD_PARAMETER);
2310 if (key->keyalg == KMF_RSA) {
2311 rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)key->keyp);
2312 modulus_len = RSA_size(rsa);
2313 } else {
2314 return (KMF_ERR_BAD_PARAMETER);
2317 blocks = ciphertext->Length/modulus_len;
2318 out_data = output->Data;
2319 in_data = ciphertext->Data;
2320 out_len = modulus_len - 11;
2321 in_len = modulus_len;
2323 for (i = 0; i < blocks; i++) {
2324 out_len = RSA_private_decrypt(in_len,
2325 in_data, out_data, rsa, RSA_PKCS1_PADDING);
2327 if (out_len == 0) {
2328 ret = KMF_ERR_INTERNAL;
2329 goto cleanup;
2332 out_data += out_len;
2333 total_decrypted += out_len;
2334 in_data += in_len;
2337 output->Length = total_decrypted;
2339 cleanup:
2340 RSA_free(rsa);
2341 if (ret != KMF_OK)
2342 output->Length = 0;
2344 return (ret);
2349 * This function will create a certid from issuer_cert and user_cert.
2350 * The caller should use OCSP_CERTID_free(OCSP_CERTID *) to deallocate
2351 * certid memory after use.
2353 static KMF_RETURN
2354 create_certid(KMF_HANDLE_T handle, const KMF_DATA *issuer_cert,
2355 const KMF_DATA *user_cert, OCSP_CERTID **certid)
2357 KMF_RETURN ret = KMF_OK;
2358 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2359 X509 *issuer = NULL;
2360 X509 *cert = NULL;
2361 unsigned char *ptmp;
2363 if (issuer_cert == NULL || user_cert == NULL) {
2364 return (KMF_ERR_BAD_PARAMETER);
2367 /* convert the DER-encoded issuer cert to an internal X509 */
2368 ptmp = issuer_cert->Data;
2369 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2370 issuer_cert->Length);
2371 if (issuer == NULL) {
2372 SET_ERROR(kmfh, ERR_get_error());
2373 ret = KMF_ERR_OCSP_BAD_ISSUER;
2374 goto end;
2377 /* convert the DER-encoded user cert to an internal X509 */
2378 ptmp = user_cert->Data;
2379 cert = d2i_X509(NULL, (const uchar_t **)&ptmp,
2380 user_cert->Length);
2381 if (cert == NULL) {
2382 SET_ERROR(kmfh, ERR_get_error());
2384 ret = KMF_ERR_OCSP_BAD_CERT;
2385 goto end;
2388 /* create a CERTID */
2389 *certid = OCSP_cert_to_id(NULL, cert, issuer);
2390 if (*certid == NULL) {
2391 SET_ERROR(kmfh, ERR_get_error());
2392 ret = KMF_ERR_OCSP_CERTID;
2393 goto end;
2396 end:
2397 if (issuer != NULL) {
2398 X509_free(issuer);
2401 if (cert != NULL) {
2402 X509_free(cert);
2405 return (ret);
2408 KMF_RETURN
2409 OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
2410 int numattr, KMF_ATTRIBUTE *attrlist)
2412 KMF_RETURN ret = KMF_OK;
2413 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2414 OCSP_CERTID *id = NULL;
2415 OCSP_REQUEST *req = NULL;
2416 BIO *derbio = NULL;
2417 char *reqfile;
2418 KMF_DATA *issuer_cert;
2419 KMF_DATA *user_cert;
2421 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2422 attrlist, numattr);
2423 if (user_cert == NULL)
2424 return (KMF_ERR_BAD_PARAMETER);
2426 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2427 attrlist, numattr);
2428 if (issuer_cert == NULL)
2429 return (KMF_ERR_BAD_PARAMETER);
2431 reqfile = kmf_get_attr_ptr(KMF_OCSP_REQUEST_FILENAME_ATTR,
2432 attrlist, numattr);
2433 if (reqfile == NULL)
2434 return (KMF_ERR_BAD_PARAMETER);
2436 ret = create_certid(handle, issuer_cert, user_cert, &id);
2437 if (ret != KMF_OK) {
2438 return (ret);
2441 /* Create an OCSP request */
2442 req = OCSP_REQUEST_new();
2443 if (req == NULL) {
2444 SET_ERROR(kmfh, ERR_get_error());
2445 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2446 goto end;
2449 if (!OCSP_request_add0_id(req, id)) {
2450 ret = KMF_ERR_OCSP_CREATE_REQUEST;
2451 goto end;
2454 /* Write the request to the output file with DER encoding */
2455 derbio = BIO_new_file(reqfile, "wb");
2456 if (!derbio) {
2457 SET_ERROR(kmfh, ERR_get_error());
2458 ret = KMF_ERR_OPEN_FILE;
2459 goto end;
2461 if (i2d_OCSP_REQUEST_bio(derbio, req) <= 0) {
2462 ret = KMF_ERR_ENCODING;
2465 end:
2467 * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
2468 * will also deallocate certid's space.
2470 if (req != NULL) {
2471 OCSP_REQUEST_free(req);
2474 if (derbio != NULL) {
2475 (void) BIO_free(derbio);
2478 return (ret);
2481 /* ocsp_find_signer_sk() is copied from openssl source */
2482 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
2484 int i;
2485 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
2487 /* Easy if lookup by name */
2488 if (id->type == V_OCSP_RESPID_NAME)
2489 return (X509_find_by_subject(certs, id->value.byName));
2491 /* Lookup by key hash */
2493 /* If key hash isn't SHA1 length then forget it */
2494 if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2495 return (NULL);
2497 keyhash = id->value.byKey->data;
2498 /* Calculate hash of each key and compare */
2499 for (i = 0; i < sk_X509_num(certs); i++) {
2500 /* LINTED E_BAD_PTR_CAST_ALIGN */
2501 X509 *x = sk_X509_value(certs, i);
2502 /* Use pubkey_digest to get the key ID value */
2503 (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
2504 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
2505 return (x);
2507 return (NULL);
2510 /* ocsp_find_signer() is copied from openssl source */
2511 /* ARGSUSED2 */
2512 static int
2513 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
2514 X509_STORE *st, unsigned long flags)
2516 X509 *signer;
2517 OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2518 if ((signer = ocsp_find_signer_sk(certs, rid))) {
2519 *psigner = signer;
2520 return (2);
2522 if (!(flags & OCSP_NOINTERN) &&
2523 (signer = ocsp_find_signer_sk(bs->certs, rid))) {
2524 *psigner = signer;
2525 return (1);
2527 /* Maybe lookup from store if by subject name */
2529 *psigner = NULL;
2530 return (0);
2534 * This function will verify the signature of a basic response, using
2535 * the public key from the OCSP responder certificate.
2537 static KMF_RETURN
2538 check_response_signature(KMF_HANDLE_T handle, OCSP_BASICRESP *bs,
2539 KMF_DATA *signer_cert, KMF_DATA *issuer_cert)
2541 KMF_RETURN ret = KMF_OK;
2542 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2543 STACK_OF(X509) *cert_stack = NULL;
2544 X509 *signer = NULL;
2545 X509 *issuer = NULL;
2546 EVP_PKEY *skey = NULL;
2547 unsigned char *ptmp;
2550 if (bs == NULL || issuer_cert == NULL)
2551 return (KMF_ERR_BAD_PARAMETER);
2554 * Find the certificate that signed the basic response.
2556 * If signer_cert is not NULL, we will use that as the signer cert.
2557 * Otherwise, we will check if the issuer cert is actually the signer.
2558 * If we still do not find a signer, we will look for it from the
2559 * certificate list came with the response file.
2561 if (signer_cert != NULL) {
2562 ptmp = signer_cert->Data;
2563 signer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2564 signer_cert->Length);
2565 if (signer == NULL) {
2566 SET_ERROR(kmfh, ERR_get_error());
2567 ret = KMF_ERR_OCSP_BAD_SIGNER;
2568 goto end;
2570 } else {
2572 * Convert the issuer cert into X509 and push it into a
2573 * stack to be used by ocsp_find_signer().
2575 ptmp = issuer_cert->Data;
2576 issuer = d2i_X509(NULL, (const uchar_t **)&ptmp,
2577 issuer_cert->Length);
2578 if (issuer == NULL) {
2579 SET_ERROR(kmfh, ERR_get_error());
2580 ret = KMF_ERR_OCSP_BAD_ISSUER;
2581 goto end;
2584 if ((cert_stack = sk_X509_new_null()) == NULL) {
2585 ret = KMF_ERR_INTERNAL;
2586 goto end;
2589 if (sk_X509_push(cert_stack, issuer) == NULL) {
2590 ret = KMF_ERR_INTERNAL;
2591 goto end;
2594 ret = ocsp_find_signer(&signer, bs, cert_stack, NULL, 0);
2595 if (!ret) {
2596 /* can not find the signer */
2597 ret = KMF_ERR_OCSP_BAD_SIGNER;
2598 goto end;
2602 /* Verify the signature of the response */
2603 skey = X509_get_pubkey(signer);
2604 if (skey == NULL) {
2605 ret = KMF_ERR_OCSP_BAD_SIGNER;
2606 goto end;
2609 ret = OCSP_BASICRESP_verify(bs, skey, 0);
2610 if (ret == 0) {
2611 ret = KMF_ERR_OCSP_RESPONSE_SIGNATURE;
2612 goto end;
2615 end:
2616 if (issuer != NULL) {
2617 X509_free(issuer);
2620 if (signer != NULL) {
2621 X509_free(signer);
2624 if (skey != NULL) {
2625 EVP_PKEY_free(skey);
2628 if (cert_stack != NULL) {
2629 sk_X509_free(cert_stack);
2632 return (ret);
2637 KMF_RETURN
2638 OpenSSL_GetOCSPStatusForCert(KMF_HANDLE_T handle,
2639 int numattr, KMF_ATTRIBUTE *attrlist)
2641 KMF_RETURN ret = KMF_OK;
2642 BIO *derbio = NULL;
2643 OCSP_RESPONSE *resp = NULL;
2644 OCSP_BASICRESP *bs = NULL;
2645 OCSP_CERTID *id = NULL;
2646 OCSP_SINGLERESP *single = NULL;
2647 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2648 int index, status, reason;
2649 KMF_DATA *issuer_cert;
2650 KMF_DATA *user_cert;
2651 KMF_DATA *signer_cert;
2652 KMF_DATA *response;
2653 int *response_reason, *response_status, *cert_status;
2654 boolean_t ignore_response_sign = B_FALSE; /* default is FALSE */
2655 uint32_t response_lifetime;
2657 issuer_cert = kmf_get_attr_ptr(KMF_ISSUER_CERT_DATA_ATTR,
2658 attrlist, numattr);
2659 if (issuer_cert == NULL)
2660 return (KMF_ERR_BAD_PARAMETER);
2662 user_cert = kmf_get_attr_ptr(KMF_USER_CERT_DATA_ATTR,
2663 attrlist, numattr);
2664 if (user_cert == NULL)
2665 return (KMF_ERR_BAD_PARAMETER);
2667 response = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_DATA_ATTR,
2668 attrlist, numattr);
2669 if (response == NULL)
2670 return (KMF_ERR_BAD_PARAMETER);
2672 response_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_STATUS_ATTR,
2673 attrlist, numattr);
2674 if (response_status == NULL)
2675 return (KMF_ERR_BAD_PARAMETER);
2677 response_reason = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_REASON_ATTR,
2678 attrlist, numattr);
2679 if (response_reason == NULL)
2680 return (KMF_ERR_BAD_PARAMETER);
2682 cert_status = kmf_get_attr_ptr(KMF_OCSP_RESPONSE_CERT_STATUS_ATTR,
2683 attrlist, numattr);
2684 if (cert_status == NULL)
2685 return (KMF_ERR_BAD_PARAMETER);
2687 /* Read in the response */
2688 derbio = BIO_new_mem_buf(response->Data, response->Length);
2689 if (!derbio) {
2690 ret = KMF_ERR_MEMORY;
2691 return (ret);
2694 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
2695 if (resp == NULL) {
2696 ret = KMF_ERR_OCSP_MALFORMED_RESPONSE;
2697 goto end;
2700 /* Check the response status */
2701 status = OCSP_response_status(resp);
2702 *response_status = status;
2703 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2704 ret = KMF_ERR_OCSP_RESPONSE_STATUS;
2705 goto end;
2708 #ifdef DEBUG
2709 printf("Successfully checked the response file status.\n");
2710 #endif /* DEBUG */
2712 /* Extract basic response */
2713 bs = OCSP_response_get1_basic(resp);
2714 if (bs == NULL) {
2715 ret = KMF_ERR_OCSP_NO_BASIC_RESPONSE;
2716 goto end;
2719 #ifdef DEBUG
2720 printf("Successfully retrieved the basic response.\n");
2721 #endif /* DEBUG */
2723 /* Check the basic response signature if required */
2724 ret = kmf_get_attr(KMF_IGNORE_RESPONSE_SIGN_ATTR, attrlist, numattr,
2725 (void *)&ignore_response_sign, NULL);
2726 if (ret != KMF_OK)
2727 ret = KMF_OK;
2729 signer_cert = kmf_get_attr_ptr(KMF_SIGNER_CERT_DATA_ATTR,
2730 attrlist, numattr);
2732 if (ignore_response_sign == B_FALSE) {
2733 ret = check_response_signature(handle, bs,
2734 signer_cert, issuer_cert);
2735 if (ret != KMF_OK)
2736 goto end;
2739 #ifdef DEBUG
2740 printf("Successfully verified the response signature.\n");
2741 #endif /* DEBUG */
2743 /* Create a certid for the certificate in question */
2744 ret = create_certid(handle, issuer_cert, user_cert, &id);
2745 if (ret != KMF_OK) {
2746 ret = KMF_ERR_OCSP_CERTID;
2747 goto end;
2750 #ifdef DEBUG
2751 printf("successfully created a certid for the cert.\n");
2752 #endif /* DEBUG */
2754 /* Find the index of the single response for the certid */
2755 index = OCSP_resp_find(bs, id, -1);
2756 if (index < 0) {
2757 /* cound not find this certificate in the response */
2758 ret = KMF_ERR_OCSP_UNKNOWN_CERT;
2759 goto end;
2762 #ifdef DEBUG
2763 printf("Successfully found the single response index for the cert.\n");
2764 #endif /* DEBUG */
2766 /* Retrieve the single response and get the cert status */
2767 single = OCSP_resp_get0(bs, index);
2768 status = OCSP_single_get0_status(single, &reason, &rev, &thisupd,
2769 &nextupd);
2770 if (status == V_OCSP_CERTSTATUS_GOOD) {
2771 *cert_status = OCSP_GOOD;
2772 } else if (status == V_OCSP_CERTSTATUS_UNKNOWN) {
2773 *cert_status = OCSP_UNKNOWN;
2774 } else { /* revoked */
2775 *cert_status = OCSP_REVOKED;
2776 *response_reason = reason;
2778 ret = KMF_OK;
2780 /* resp. time is optional, so we don't care about the return code. */
2781 (void) kmf_get_attr(KMF_RESPONSE_LIFETIME_ATTR, attrlist, numattr,
2782 (void *)&response_lifetime, NULL);
2784 if (!OCSP_check_validity(thisupd, nextupd, 300,
2785 response_lifetime)) {
2786 ret = KMF_ERR_OCSP_STATUS_TIME_INVALID;
2787 goto end;
2790 #ifdef DEBUG
2791 printf("Successfully verify the time.\n");
2792 #endif /* DEBUG */
2794 end:
2795 if (derbio != NULL)
2796 (void) BIO_free(derbio);
2798 if (resp != NULL)
2799 OCSP_RESPONSE_free(resp);
2801 if (bs != NULL)
2802 OCSP_BASICRESP_free(bs);
2804 if (id != NULL)
2805 OCSP_CERTID_free(id);
2807 return (ret);
2810 static KMF_RETURN
2811 fetch_key(KMF_HANDLE_T handle, char *path,
2812 KMF_KEY_CLASS keyclass, KMF_KEY_HANDLE *key)
2814 KMF_RETURN rv = KMF_OK;
2815 EVP_PKEY *pkey = NULL;
2816 KMF_RAW_SYM_KEY *rkey = NULL;
2818 if (keyclass == KMF_ASYM_PRI ||
2819 keyclass == KMF_ASYM_PUB) {
2820 pkey = openssl_load_key(handle, path);
2821 if (pkey == NULL) {
2822 return (KMF_ERR_KEY_NOT_FOUND);
2824 if (key != NULL) {
2825 if (pkey->type == EVP_PKEY_RSA)
2826 key->keyalg = KMF_RSA;
2827 else if (pkey->type == EVP_PKEY_DSA)
2828 key->keyalg = KMF_DSA;
2830 key->kstype = KMF_KEYSTORE_OPENSSL;
2831 key->keyclass = keyclass;
2832 key->keyp = (void *)pkey;
2833 key->israw = FALSE;
2834 if (path != NULL &&
2835 ((key->keylabel = strdup(path)) == NULL)) {
2836 EVP_PKEY_free(pkey);
2837 return (KMF_ERR_MEMORY);
2839 } else {
2840 EVP_PKEY_free(pkey);
2841 pkey = NULL;
2843 } else if (keyclass == KMF_SYMMETRIC) {
2844 KMF_ENCODE_FORMAT fmt;
2846 * If the file is a recognized format,
2847 * then it is NOT a symmetric key.
2849 rv = kmf_get_file_format(path, &fmt);
2850 if (rv == KMF_OK || fmt != 0) {
2851 return (KMF_ERR_KEY_NOT_FOUND);
2852 } else if (rv == KMF_ERR_ENCODING) {
2854 * If we don't know the encoding,
2855 * it is probably a symmetric key.
2857 rv = KMF_OK;
2858 } else if (rv == KMF_ERR_OPEN_FILE) {
2859 return (KMF_ERR_KEY_NOT_FOUND);
2862 if (key != NULL) {
2863 KMF_DATA keyvalue;
2864 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
2865 if (rkey == NULL) {
2866 rv = KMF_ERR_MEMORY;
2867 goto out;
2870 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
2871 rv = kmf_read_input_file(handle, path, &keyvalue);
2872 if (rv != KMF_OK)
2873 goto out;
2875 rkey->keydata.len = keyvalue.Length;
2876 rkey->keydata.val = keyvalue.Data;
2878 key->kstype = KMF_KEYSTORE_OPENSSL;
2879 key->keyclass = keyclass;
2880 key->israw = TRUE;
2881 key->keyp = (void *)rkey;
2882 if (path != NULL &&
2883 ((key->keylabel = strdup(path)) == NULL)) {
2884 rv = KMF_ERR_MEMORY;
2888 out:
2889 if (rv != KMF_OK) {
2890 if (rkey != NULL) {
2891 kmf_free_raw_sym_key(rkey);
2893 if (pkey != NULL)
2894 EVP_PKEY_free(pkey);
2896 if (key != NULL) {
2897 key->keyalg = KMF_KEYALG_NONE;
2898 key->keyclass = KMF_KEYCLASS_NONE;
2899 key->keyp = NULL;
2903 return (rv);
2906 KMF_RETURN
2907 OpenSSL_FindKey(KMF_HANDLE_T handle,
2908 int numattr, KMF_ATTRIBUTE *attrlist)
2910 KMF_RETURN rv = KMF_OK;
2911 char *fullpath = NULL;
2912 uint32_t maxkeys;
2913 KMF_KEY_HANDLE *key;
2914 uint32_t *numkeys;
2915 KMF_KEY_CLASS keyclass;
2916 KMF_RAW_KEY_DATA *rawkey;
2917 char *dirpath;
2918 char *keyfile;
2920 if (handle == NULL)
2921 return (KMF_ERR_BAD_PARAMETER);
2923 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
2924 if (numkeys == NULL)
2925 return (KMF_ERR_BAD_PARAMETER);
2927 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
2928 (void *)&keyclass, NULL);
2929 if (rv != KMF_OK)
2930 return (KMF_ERR_BAD_PARAMETER);
2932 if (keyclass != KMF_ASYM_PUB &&
2933 keyclass != KMF_ASYM_PRI &&
2934 keyclass != KMF_SYMMETRIC)
2935 return (KMF_ERR_BAD_KEY_CLASS);
2937 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
2938 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
2940 fullpath = get_fullpath(dirpath, keyfile);
2942 if (fullpath == NULL)
2943 return (KMF_ERR_BAD_PARAMETER);
2945 maxkeys = *numkeys;
2946 if (maxkeys == 0)
2947 maxkeys = 0xFFFFFFFF;
2948 *numkeys = 0;
2950 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
2951 /* it is okay to have "keys" contains NULL */
2954 * The caller may want a list of the raw key data as well.
2955 * Useful for importing keys from a file into other keystores.
2957 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
2959 if (isdir(fullpath)) {
2960 DIR *dirp;
2961 struct dirent *dp;
2962 int n = 0;
2964 /* open all files in the directory and attempt to read them */
2965 if ((dirp = opendir(fullpath)) == NULL) {
2966 return (KMF_ERR_BAD_PARAMETER);
2968 rewinddir(dirp);
2969 while ((dp = readdir(dirp)) != NULL && n < maxkeys) {
2970 if (strcmp(dp->d_name, ".") &&
2971 strcmp(dp->d_name, "..")) {
2972 char *fname;
2974 fname = get_fullpath(fullpath,
2975 (char *)&dp->d_name);
2977 rv = fetch_key(handle, fname,
2978 keyclass, key ? &key[n] : NULL);
2980 if (rv == KMF_OK) {
2981 if (key != NULL && rawkey != NULL)
2982 rv = convertToRawKey(
2983 key[n].keyp, &rawkey[n]);
2984 n++;
2987 if (rv != KMF_OK || key == NULL)
2988 free(fname);
2991 (void) closedir(dirp);
2992 free(fullpath);
2993 (*numkeys) = n;
2994 } else {
2995 rv = fetch_key(handle, fullpath, keyclass, key);
2996 if (rv == KMF_OK)
2997 (*numkeys) = 1;
2999 if (rv != KMF_OK || key == NULL)
3000 free(fullpath);
3002 if (rv == KMF_OK && key != NULL && rawkey != NULL) {
3003 rv = convertToRawKey(key->keyp, rawkey);
3007 if (rv == KMF_OK && (*numkeys) == 0)
3008 rv = KMF_ERR_KEY_NOT_FOUND;
3009 else if (rv == KMF_ERR_KEY_NOT_FOUND && (*numkeys) > 0)
3010 rv = KMF_OK;
3012 return (rv);
3015 #define HANDLE_PK12_ERROR { \
3016 SET_ERROR(kmfh, ERR_get_error()); \
3017 rv = KMF_ERR_ENCODING; \
3018 goto out; \
3021 static int
3022 add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert)
3024 if (xcert != NULL && xcert->aux != NULL &&
3025 xcert->aux->alias != NULL) {
3026 if (PKCS12_add_friendlyname_asc(bag,
3027 (const char *)xcert->aux->alias->data,
3028 xcert->aux->alias->length) == 0)
3029 return (0);
3031 return (1);
3034 static PKCS7 *
3035 add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred,
3036 uchar_t *keyid, unsigned int keyidlen)
3038 PKCS12_SAFEBAG *bag = NULL;
3039 PKCS7 *cert_authsafe = NULL;
3040 STACK_OF(PKCS12_SAFEBAG) *bag_stack;
3042 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3043 if (bag_stack == NULL)
3044 return (NULL);
3046 /* Convert cert from X509 struct to PKCS#12 bag */
3047 bag = PKCS12_x5092certbag(sslcert);
3048 if (bag == NULL) {
3049 goto out;
3052 /* Add the key id to the certificate bag. */
3053 if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) {
3054 goto out;
3057 if (!add_alias_to_bag(bag, sslcert))
3058 goto out;
3060 /* Pile it on the bag_stack. */
3061 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) {
3062 goto out;
3064 /* Turn bag_stack of certs into encrypted authsafe. */
3065 cert_authsafe = PKCS12_pack_p7encdata(
3066 NID_pbe_WithSHA1And40BitRC2_CBC,
3067 cred->cred, cred->credlen, NULL, 0,
3068 PKCS12_DEFAULT_ITER, bag_stack);
3070 out:
3071 if (bag_stack != NULL)
3072 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3074 return (cert_authsafe);
3077 static PKCS7 *
3078 add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred,
3079 uchar_t *keyid, unsigned int keyidlen,
3080 char *label, int label_len)
3082 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3083 STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
3084 PKCS12_SAFEBAG *bag = NULL;
3085 PKCS7 *key_authsafe = NULL;
3087 p8 = EVP_PKEY2PKCS8(pkey);
3088 if (p8 == NULL) {
3089 return (NULL);
3091 /* Put the shrouded key into a PKCS#12 bag. */
3092 bag = PKCS12_MAKE_SHKEYBAG(
3093 NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
3094 cred->cred, cred->credlen,
3095 NULL, 0, PKCS12_DEFAULT_ITER, p8);
3097 /* Clean up the PKCS#8 shrouded key, don't need it now. */
3098 PKCS8_PRIV_KEY_INFO_free(p8);
3099 p8 = NULL;
3101 if (bag == NULL) {
3102 return (NULL);
3104 if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
3105 goto out;
3106 if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len))
3107 goto out;
3109 /* Start a PKCS#12 safebag container for the private key. */
3110 bag_stack = sk_PKCS12_SAFEBAG_new_null();
3111 if (bag_stack == NULL)
3112 goto out;
3114 /* Pile on the private key on the bag_stack. */
3115 if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
3116 goto out;
3118 key_authsafe = PKCS12_pack_p7data(bag_stack);
3120 out:
3121 if (bag_stack != NULL)
3122 sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
3123 bag_stack = NULL;
3124 return (key_authsafe);
3127 static EVP_PKEY *
3128 ImportRawRSAKey(KMF_RAW_RSA_KEY *key)
3130 RSA *rsa = NULL;
3131 EVP_PKEY *newkey = NULL;
3133 if ((rsa = RSA_new()) == NULL)
3134 return (NULL);
3136 if ((rsa->n = BN_bin2bn(key->mod.val, key->mod.len, rsa->n)) == NULL)
3137 return (NULL);
3139 if ((rsa->e = BN_bin2bn(key->pubexp.val, key->pubexp.len, rsa->e)) ==
3140 NULL)
3141 return (NULL);
3143 if (key->priexp.val != NULL)
3144 if ((rsa->d = BN_bin2bn(key->priexp.val, key->priexp.len,
3145 rsa->d)) == NULL)
3146 return (NULL);
3148 if (key->prime1.val != NULL)
3149 if ((rsa->p = BN_bin2bn(key->prime1.val, key->prime1.len,
3150 rsa->p)) == NULL)
3151 return (NULL);
3153 if (key->prime2.val != NULL)
3154 if ((rsa->q = BN_bin2bn(key->prime2.val, key->prime2.len,
3155 rsa->q)) == NULL)
3156 return (NULL);
3158 if (key->exp1.val != NULL)
3159 if ((rsa->dmp1 = BN_bin2bn(key->exp1.val, key->exp1.len,
3160 rsa->dmp1)) == NULL)
3161 return (NULL);
3163 if (key->exp2.val != NULL)
3164 if ((rsa->dmq1 = BN_bin2bn(key->exp2.val, key->exp2.len,
3165 rsa->dmq1)) == NULL)
3166 return (NULL);
3168 if (key->coef.val != NULL)
3169 if ((rsa->iqmp = BN_bin2bn(key->coef.val, key->coef.len,
3170 rsa->iqmp)) == NULL)
3171 return (NULL);
3173 if ((newkey = EVP_PKEY_new()) == NULL)
3174 return (NULL);
3176 (void) EVP_PKEY_set1_RSA(newkey, rsa);
3178 /* The original key must be freed once here or it leaks memory */
3179 RSA_free(rsa);
3181 return (newkey);
3184 static EVP_PKEY *
3185 ImportRawDSAKey(KMF_RAW_DSA_KEY *key)
3187 DSA *dsa = NULL;
3188 EVP_PKEY *newkey = NULL;
3190 if ((dsa = DSA_new()) == NULL)
3191 return (NULL);
3193 if ((dsa->p = BN_bin2bn(key->prime.val, key->prime.len,
3194 dsa->p)) == NULL)
3195 return (NULL);
3197 if ((dsa->q = BN_bin2bn(key->subprime.val, key->subprime.len,
3198 dsa->q)) == NULL)
3199 return (NULL);
3201 if ((dsa->g = BN_bin2bn(key->base.val, key->base.len,
3202 dsa->g)) == NULL)
3203 return (NULL);
3205 if ((dsa->priv_key = BN_bin2bn(key->value.val, key->value.len,
3206 dsa->priv_key)) == NULL)
3207 return (NULL);
3209 if (key->pubvalue.val != NULL) {
3210 if ((dsa->pub_key = BN_bin2bn(key->pubvalue.val,
3211 key->pubvalue.len, dsa->pub_key)) == NULL)
3212 return (NULL);
3215 if ((newkey = EVP_PKEY_new()) == NULL)
3216 return (NULL);
3218 (void) EVP_PKEY_set1_DSA(newkey, dsa);
3220 /* The original key must be freed once here or it leaks memory */
3221 DSA_free(dsa);
3222 return (newkey);
3225 static EVP_PKEY *
3226 raw_key_to_pkey(KMF_KEY_HANDLE *key)
3228 EVP_PKEY *pkey = NULL;
3229 KMF_RAW_KEY_DATA *rawkey;
3230 ASN1_TYPE *attr = NULL;
3231 KMF_RETURN ret;
3233 if (key == NULL || !key->israw)
3234 return (NULL);
3236 rawkey = (KMF_RAW_KEY_DATA *)key->keyp;
3237 if (rawkey->keytype == KMF_RSA) {
3238 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
3239 } else if (rawkey->keytype == KMF_DSA) {
3240 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
3241 } else if (rawkey->keytype == KMF_ECDSA) {
3243 * OpenSSL in Solaris does not support EC for
3244 * legal reasons
3246 return (NULL);
3247 } else {
3248 /* wrong kind of key */
3249 return (NULL);
3252 if (rawkey->label != NULL) {
3253 if ((attr = ASN1_TYPE_new()) == NULL) {
3254 EVP_PKEY_free(pkey);
3255 return (NULL);
3257 attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING);
3258 (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label,
3259 strlen(rawkey->label));
3260 attr->type = V_ASN1_BMPSTRING;
3261 attr->value.ptr = (char *)attr->value.bmpstring;
3262 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3263 if (ret != KMF_OK) {
3264 EVP_PKEY_free(pkey);
3265 ASN1_TYPE_free(attr);
3266 return (NULL);
3269 if (rawkey->id.Data != NULL) {
3270 if ((attr = ASN1_TYPE_new()) == NULL) {
3271 EVP_PKEY_free(pkey);
3272 return (NULL);
3274 attr->value.octet_string =
3275 ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
3276 attr->type = V_ASN1_OCTET_STRING;
3277 (void) ASN1_STRING_set(attr->value.octet_string,
3278 rawkey->id.Data, rawkey->id.Length);
3279 attr->value.ptr = (char *)attr->value.octet_string;
3280 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3281 if (ret != KMF_OK) {
3282 EVP_PKEY_free(pkey);
3283 ASN1_TYPE_free(attr);
3284 return (NULL);
3287 return (pkey);
3291 * Search a list of private keys to find one that goes with the certificate.
3293 static EVP_PKEY *
3294 find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist)
3296 int i;
3297 EVP_PKEY *pkey = NULL;
3299 if (numkeys == 0 || keylist == NULL || xcert == NULL)
3300 return (NULL);
3301 for (i = 0; i < numkeys; i++) {
3302 if (keylist[i].israw)
3303 pkey = raw_key_to_pkey(&keylist[i]);
3304 else
3305 pkey = (EVP_PKEY *)keylist[i].keyp;
3306 if (pkey != NULL) {
3307 if (X509_check_private_key(xcert, pkey)) {
3308 return (pkey);
3309 } else {
3310 EVP_PKEY_free(pkey);
3311 pkey = NULL;
3315 return (pkey);
3318 static KMF_RETURN
3319 local_export_pk12(KMF_HANDLE_T handle,
3320 KMF_CREDENTIAL *cred,
3321 int numcerts, KMF_X509_DER_CERT *certlist,
3322 int numkeys, KMF_KEY_HANDLE *keylist,
3323 char *filename)
3325 KMF_RETURN rv = KMF_OK;
3326 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3327 BIO *bio = NULL;
3328 PKCS7 *cert_authsafe = NULL;
3329 PKCS7 *key_authsafe = NULL;
3330 STACK_OF(PKCS7) *authsafe_stack = NULL;
3331 PKCS12 *p12_elem = NULL;
3332 int i;
3334 if (numcerts == 0 && numkeys == 0)
3335 return (KMF_ERR_BAD_PARAMETER);
3338 * Open the output file.
3340 if ((bio = BIO_new_file(filename, "wb")) == NULL) {
3341 SET_ERROR(kmfh, ERR_get_error());
3342 rv = KMF_ERR_OPEN_FILE;
3343 goto cleanup;
3346 /* Start a PKCS#7 stack. */
3347 authsafe_stack = sk_PKCS7_new_null();
3348 if (authsafe_stack == NULL) {
3349 rv = KMF_ERR_MEMORY;
3350 goto cleanup;
3352 if (numcerts > 0) {
3353 for (i = 0; rv == KMF_OK && i < numcerts; i++) {
3354 const uchar_t *p = certlist[i].certificate.Data;
3355 long len = certlist[i].certificate.Length;
3356 X509 *xcert = NULL;
3357 EVP_PKEY *pkey = NULL;
3358 unsigned char keyid[EVP_MAX_MD_SIZE];
3359 unsigned int keyidlen = 0;
3361 xcert = d2i_X509(NULL, &p, len);
3362 if (xcert == NULL) {
3363 SET_ERROR(kmfh, ERR_get_error());
3364 rv = KMF_ERR_ENCODING;
3366 if (certlist[i].kmf_private.label != NULL) {
3367 /* Set alias attribute */
3368 (void) X509_alias_set1(xcert,
3369 (uchar_t *)certlist[i].kmf_private.label,
3370 strlen(certlist[i].kmf_private.label));
3372 /* Check if there is a key corresponding to this cert */
3373 pkey = find_matching_key(xcert, numkeys, keylist);
3376 * If key is found, get fingerprint and create a
3377 * safebag.
3379 if (pkey != NULL) {
3380 (void) X509_digest(xcert, EVP_sha1(),
3381 keyid, &keyidlen);
3382 key_authsafe = add_key_to_safe(pkey, cred,
3383 keyid, keyidlen,
3384 certlist[i].kmf_private.label,
3385 (certlist[i].kmf_private.label ?
3386 strlen(certlist[i].kmf_private.label) : 0));
3388 if (key_authsafe == NULL) {
3389 X509_free(xcert);
3390 EVP_PKEY_free(pkey);
3391 goto cleanup;
3393 /* Put the key safe into the Auth Safe */
3394 if (!sk_PKCS7_push(authsafe_stack,
3395 key_authsafe)) {
3396 X509_free(xcert);
3397 EVP_PKEY_free(pkey);
3398 goto cleanup;
3402 /* create a certificate safebag */
3403 cert_authsafe = add_cert_to_safe(xcert, cred, keyid,
3404 keyidlen);
3405 if (cert_authsafe == NULL) {
3406 X509_free(xcert);
3407 EVP_PKEY_free(pkey);
3408 goto cleanup;
3410 if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) {
3411 X509_free(xcert);
3412 EVP_PKEY_free(pkey);
3413 goto cleanup;
3416 X509_free(xcert);
3417 if (pkey)
3418 EVP_PKEY_free(pkey);
3420 } else if (numcerts == 0 && numkeys > 0) {
3422 * If only adding keys to the file.
3424 for (i = 0; i < numkeys; i++) {
3425 EVP_PKEY *pkey = NULL;
3427 if (keylist[i].israw)
3428 pkey = raw_key_to_pkey(&keylist[i]);
3429 else
3430 pkey = (EVP_PKEY *)keylist[i].keyp;
3432 if (pkey == NULL)
3433 continue;
3435 key_authsafe = add_key_to_safe(pkey, cred,
3436 NULL, 0, NULL, 0);
3438 if (key_authsafe == NULL) {
3439 EVP_PKEY_free(pkey);
3440 goto cleanup;
3442 if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) {
3443 EVP_PKEY_free(pkey);
3444 goto cleanup;
3448 p12_elem = PKCS12_init(NID_pkcs7_data);
3449 if (p12_elem == NULL) {
3450 goto cleanup;
3453 /* Put the PKCS#7 stack into the PKCS#12 element. */
3454 if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) {
3455 goto cleanup;
3458 /* Set the integrity MAC on the PKCS#12 element. */
3459 if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen,
3460 NULL, 0, PKCS12_DEFAULT_ITER, NULL)) {
3461 goto cleanup;
3464 /* Write the PKCS#12 element to the export file. */
3465 if (!i2d_PKCS12_bio(bio, p12_elem)) {
3466 goto cleanup;
3468 PKCS12_free(p12_elem);
3470 cleanup:
3471 /* Clear away the PKCS#7 stack, we're done with it. */
3472 if (authsafe_stack)
3473 sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3475 if (bio != NULL)
3476 (void) BIO_free_all(bio);
3478 return (rv);
3481 KMF_RETURN
3482 openssl_build_pk12(KMF_HANDLE_T handle, int numcerts,
3483 KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist,
3484 KMF_CREDENTIAL *p12cred, char *filename)
3486 KMF_RETURN rv;
3488 if (certlist == NULL && keylist == NULL)
3489 return (KMF_ERR_BAD_PARAMETER);
3491 rv = local_export_pk12(handle, p12cred, numcerts, certlist,
3492 numkeys, keylist, filename);
3494 return (rv);
3497 KMF_RETURN
3498 OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
3500 KMF_RETURN rv;
3501 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
3502 char *fullpath = NULL;
3503 char *dirpath = NULL;
3504 char *certfile = NULL;
3505 char *keyfile = NULL;
3506 char *filename = NULL;
3507 KMF_CREDENTIAL *p12cred = NULL;
3508 KMF_X509_DER_CERT certdata;
3509 KMF_KEY_HANDLE key;
3510 int gotkey = 0;
3511 int gotcert = 0;
3513 if (handle == NULL)
3514 return (KMF_ERR_BAD_PARAMETER);
3517 * First, find the certificate.
3519 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
3520 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
3521 if (certfile != NULL) {
3522 fullpath = get_fullpath(dirpath, certfile);
3523 if (fullpath == NULL)
3524 return (KMF_ERR_BAD_PARAMETER);
3526 if (isdir(fullpath)) {
3527 free(fullpath);
3528 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3531 (void) memset(&certdata, 0, sizeof (certdata));
3532 rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL,
3533 fullpath, &certdata.certificate);
3534 if (rv != KMF_OK)
3535 goto end;
3537 gotcert++;
3538 certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
3539 free(fullpath);
3543 * Now find the private key.
3545 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
3546 if (keyfile != NULL) {
3547 fullpath = get_fullpath(dirpath, keyfile);
3548 if (fullpath == NULL)
3549 return (KMF_ERR_BAD_PARAMETER);
3551 if (isdir(fullpath)) {
3552 free(fullpath);
3553 return (KMF_ERR_AMBIGUOUS_PATHNAME);
3556 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
3557 rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key);
3558 if (rv != KMF_OK)
3559 goto end;
3560 gotkey++;
3564 * Open the output file.
3566 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
3567 numattr);
3568 if (filename == NULL) {
3569 rv = KMF_ERR_BAD_PARAMETER;
3570 goto end;
3573 /* Stick the key and the cert into a PKCS#12 file */
3574 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
3575 if (p12cred == NULL) {
3576 rv = KMF_ERR_BAD_PARAMETER;
3577 goto end;
3580 rv = local_export_pk12(handle, p12cred, 1, &certdata,
3581 1, &key, filename);
3583 end:
3584 if (fullpath)
3585 free(fullpath);
3587 if (gotcert)
3588 kmf_free_kmf_cert(handle, &certdata);
3589 if (gotkey)
3590 kmf_free_kmf_key(handle, &key);
3591 return (rv);
3595 * Helper function to extract keys and certificates from
3596 * a single PEM file. Typically the file should contain a
3597 * private key and an associated public key wrapped in an x509 cert.
3598 * However, the file may be just a list of X509 certs with no keys.
3600 static KMF_RETURN
3601 extract_pem(KMF_HANDLE *kmfh,
3602 char *issuer, char *subject, KMF_BIGINT *serial,
3603 char *filename, CK_UTF8CHAR *pin,
3604 CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
3605 int *numcerts)
3606 /* ARGSUSED6 */
3608 KMF_RETURN rv = KMF_OK;
3609 FILE *fp;
3610 STACK_OF(X509_INFO) *x509_info_stack = NULL;
3611 int i, ncerts = 0, matchcerts = 0;
3612 EVP_PKEY *pkey = NULL;
3613 X509_INFO *info;
3614 X509 *x;
3615 X509_INFO **cert_infos = NULL;
3616 KMF_DATA *certlist = NULL;
3618 if (priv_key)
3619 *priv_key = NULL;
3620 if (certs)
3621 *certs = NULL;
3622 fp = fopen(filename, "r");
3623 if (fp == NULL)
3624 return (KMF_ERR_OPEN_FILE);
3626 x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
3627 if (x509_info_stack == NULL) {
3628 (void) fclose(fp);
3629 return (KMF_ERR_ENCODING);
3631 cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) *
3632 sizeof (X509_INFO *));
3633 if (cert_infos == NULL) {
3634 (void) fclose(fp);
3635 rv = KMF_ERR_MEMORY;
3636 goto err;
3639 for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) {
3640 /* LINTED E_BAD_PTR_CAST_ALIGN */
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 /* LINTED E_BAD_PTR_CAST_ALIGN */
3723 info = (X509_INFO *)sk_X509_INFO_value(x509_info_stack, i);
3724 X509_INFO_free(info);
3726 if (x509_info_stack)
3727 sk_X509_INFO_free(x509_info_stack);
3729 if (cert_infos != NULL)
3730 free(cert_infos);
3732 return (rv);
3735 static KMF_RETURN
3736 openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
3737 STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
3739 KMF_RETURN ret;
3740 int i;
3742 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
3743 /* LINTED E_BAD_PTR_CAST_ALIGN */
3744 PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i);
3745 ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0),
3746 keys, certs);
3748 if (ret != KMF_OK)
3749 return (ret);
3752 return (ret);
3755 static KMF_RETURN
3756 set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
3758 X509_ATTRIBUTE *attr = NULL;
3760 if (pkey == NULL || attrib == NULL)
3761 return (KMF_ERR_BAD_PARAMETER);
3763 if (pkey->attributes == NULL) {
3764 pkey->attributes = sk_X509_ATTRIBUTE_new_null();
3765 if (pkey->attributes == NULL)
3766 return (KMF_ERR_MEMORY);
3768 attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr);
3769 if (attr != NULL) {
3770 int i;
3771 X509_ATTRIBUTE *a;
3772 for (i = 0;
3773 i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
3774 /* LINTED E_BAD_PTR_CASE_ALIGN */
3775 a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
3776 if (OBJ_obj2nid(a->object) == nid) {
3777 X509_ATTRIBUTE_free(a);
3778 /* LINTED E_BAD_PTR_CAST_ALIGN */
3779 (void) sk_X509_ATTRIBUTE_set(pkey->attributes,
3780 i, attr);
3781 return (KMF_OK);
3784 if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) {
3785 X509_ATTRIBUTE_free(attr);
3786 return (KMF_ERR_MEMORY);
3788 } else {
3789 return (KMF_ERR_MEMORY);
3792 return (KMF_OK);
3795 static KMF_RETURN
3796 openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen,
3797 STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist)
3799 KMF_RETURN ret = KMF_OK;
3800 PKCS8_PRIV_KEY_INFO *p8 = NULL;
3801 EVP_PKEY *pkey = NULL;
3802 X509 *xcert = NULL;
3803 ASN1_TYPE *keyid = NULL;
3804 ASN1_TYPE *fname = NULL;
3805 uchar_t *data = NULL;
3807 keyid = PKCS12_get_attr(bag, NID_localKeyID);
3808 fname = PKCS12_get_attr(bag, NID_friendlyName);
3810 switch (M_PKCS12_bag_type(bag)) {
3811 case NID_keyBag:
3812 if (keylist == NULL)
3813 goto end;
3814 pkey = EVP_PKCS82PKEY(bag->value.keybag);
3815 if (pkey == NULL)
3816 ret = KMF_ERR_PKCS12_FORMAT;
3818 break;
3819 case NID_pkcs8ShroudedKeyBag:
3820 if (keylist == NULL)
3821 goto end;
3822 p8 = M_PKCS12_decrypt_skey(bag, pass, passlen);
3823 if (p8 == NULL)
3824 return (KMF_ERR_AUTH_FAILED);
3825 pkey = EVP_PKCS82PKEY(p8);
3826 PKCS8_PRIV_KEY_INFO_free(p8);
3827 if (pkey == NULL)
3828 ret = KMF_ERR_PKCS12_FORMAT;
3829 break;
3830 case NID_certBag:
3831 if (certlist == NULL)
3832 goto end;
3833 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate)
3834 return (KMF_ERR_PKCS12_FORMAT);
3835 xcert = M_PKCS12_certbag2x509(bag);
3836 if (xcert == NULL) {
3837 ret = KMF_ERR_PKCS12_FORMAT;
3838 goto end;
3840 if (keyid != NULL) {
3841 if (X509_keyid_set1(xcert,
3842 keyid->value.octet_string->data,
3843 keyid->value.octet_string->length) == 0) {
3844 ret = KMF_ERR_PKCS12_FORMAT;
3845 goto end;
3848 if (fname != NULL) {
3849 int len, r;
3850 len = ASN1_STRING_to_UTF8(&data,
3851 fname->value.asn1_string);
3852 if (len > 0 && data != NULL) {
3853 r = X509_alias_set1(xcert, data, len);
3854 if (r == NULL) {
3855 ret = KMF_ERR_PKCS12_FORMAT;
3856 goto end;
3858 } else {
3859 ret = KMF_ERR_PKCS12_FORMAT;
3860 goto end;
3863 if (sk_X509_push(certlist, xcert) == 0)
3864 ret = KMF_ERR_MEMORY;
3865 else
3866 xcert = NULL;
3867 break;
3868 case NID_safeContentsBag:
3869 return (openssl_parse_bags(bag->value.safes, pass,
3870 keylist, certlist));
3871 default:
3872 ret = KMF_ERR_PKCS12_FORMAT;
3873 break;
3877 * Set the ID and/or FriendlyName attributes on the key.
3878 * If converting to PKCS11 objects, these can translate to CKA_ID
3879 * and CKA_LABEL values.
3881 if (pkey != NULL && ret == KMF_OK) {
3882 ASN1_TYPE *attr = NULL;
3883 if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) {
3884 if ((attr = ASN1_TYPE_new()) == NULL)
3885 return (KMF_ERR_MEMORY);
3886 attr->value.octet_string =
3887 ASN1_STRING_dup(keyid->value.octet_string);
3888 attr->type = V_ASN1_OCTET_STRING;
3889 attr->value.ptr = (char *)attr->value.octet_string;
3890 ret = set_pkey_attrib(pkey, attr, NID_localKeyID);
3891 OPENSSL_free(attr);
3894 if (ret == KMF_OK && fname != NULL &&
3895 fname->type == V_ASN1_BMPSTRING) {
3896 if ((attr = ASN1_TYPE_new()) == NULL)
3897 return (KMF_ERR_MEMORY);
3898 attr->value.bmpstring =
3899 ASN1_STRING_dup(fname->value.bmpstring);
3900 attr->type = V_ASN1_BMPSTRING;
3901 attr->value.ptr = (char *)attr->value.bmpstring;
3902 ret = set_pkey_attrib(pkey, attr, NID_friendlyName);
3903 OPENSSL_free(attr);
3906 if (ret == KMF_OK && keylist != NULL &&
3907 sk_EVP_PKEY_push(keylist, pkey) == 0)
3908 ret = KMF_ERR_MEMORY;
3910 if (ret == KMF_OK && keylist != NULL)
3911 pkey = NULL;
3912 end:
3913 if (pkey != NULL)
3914 EVP_PKEY_free(pkey);
3915 if (xcert != NULL)
3916 X509_free(xcert);
3917 if (data != NULL)
3918 OPENSSL_free(data);
3920 return (ret);
3923 static KMF_RETURN
3924 openssl_pkcs12_parse(PKCS12 *p12, char *pin,
3925 STACK_OF(EVP_PKEY) *keys,
3926 STACK_OF(X509) *certs,
3927 STACK_OF(X509) *ca)
3928 /* ARGSUSED3 */
3930 KMF_RETURN ret = KMF_OK;
3931 STACK_OF(PKCS7) *asafes = NULL;
3932 STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
3933 int i, bagnid;
3934 PKCS7 *p7;
3936 if (p12 == NULL || (keys == NULL && certs == NULL))
3937 return (KMF_ERR_BAD_PARAMETER);
3939 if (pin == NULL || *pin == NULL) {
3940 if (PKCS12_verify_mac(p12, NULL, 0)) {
3941 pin = NULL;
3942 } else if (PKCS12_verify_mac(p12, "", 0)) {
3943 pin = "";
3944 } else {
3945 return (KMF_ERR_AUTH_FAILED);
3947 } else if (!PKCS12_verify_mac(p12, pin, -1)) {
3948 return (KMF_ERR_AUTH_FAILED);
3951 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
3952 return (KMF_ERR_PKCS12_FORMAT);
3954 for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) {
3955 bags = NULL;
3956 /* LINTED E_BAD_PTR_CAST_ALIGN */
3957 p7 = sk_PKCS7_value(asafes, i);
3958 bagnid = OBJ_obj2nid(p7->type);
3960 if (bagnid == NID_pkcs7_data) {
3961 bags = PKCS12_unpack_p7data(p7);
3962 } else if (bagnid == NID_pkcs7_encrypted) {
3963 bags = PKCS12_unpack_p7encdata(p7, pin,
3964 (pin ? strlen(pin) : 0));
3965 } else {
3966 continue;
3968 if (bags == NULL) {
3969 ret = KMF_ERR_PKCS12_FORMAT;
3970 goto out;
3973 if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK)
3974 ret = KMF_ERR_PKCS12_FORMAT;
3976 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
3978 out:
3979 if (asafes != NULL)
3980 sk_PKCS7_pop_free(asafes, PKCS7_free);
3982 return (ret);
3986 * Helper function to decrypt and parse PKCS#12 import file.
3988 static KMF_RETURN
3989 extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
3990 STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs,
3991 STACK_OF(X509) **ca)
3992 /* ARGSUSED2 */
3994 PKCS12 *pk12, *pk12_tmp;
3995 STACK_OF(EVP_PKEY) *pkeylist = NULL;
3996 STACK_OF(X509) *xcertlist = NULL;
3997 STACK_OF(X509) *cacertlist = NULL;
3999 if ((pk12 = PKCS12_new()) == NULL) {
4000 return (KMF_ERR_MEMORY);
4003 if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
4004 /* This is ok; it seems to mean there is no more to read. */
4005 if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
4006 ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
4007 goto end_extract_pkcs12;
4009 PKCS12_free(pk12);
4010 return (KMF_ERR_PKCS12_FORMAT);
4012 pk12 = pk12_tmp;
4014 xcertlist = sk_X509_new_null();
4015 if (xcertlist == NULL) {
4016 PKCS12_free(pk12);
4017 return (KMF_ERR_MEMORY);
4019 pkeylist = sk_EVP_PKEY_new_null();
4020 if (pkeylist == NULL) {
4021 sk_X509_pop_free(xcertlist, X509_free);
4022 PKCS12_free(pk12);
4023 return (KMF_ERR_MEMORY);
4026 if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist,
4027 cacertlist) != KMF_OK) {
4028 sk_X509_pop_free(xcertlist, X509_free);
4029 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4030 PKCS12_free(pk12);
4031 return (KMF_ERR_PKCS12_FORMAT);
4034 if (priv_key && pkeylist)
4035 *priv_key = pkeylist;
4036 else if (pkeylist)
4037 sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free);
4038 if (certs && xcertlist)
4039 *certs = xcertlist;
4040 else if (xcertlist)
4041 sk_X509_pop_free(xcertlist, X509_free);
4042 if (ca && cacertlist)
4043 *ca = cacertlist;
4044 else if (cacertlist)
4045 sk_X509_pop_free(cacertlist, X509_free);
4047 end_extract_pkcs12:
4049 PKCS12_free(pk12);
4050 return (KMF_OK);
4053 static KMF_RETURN
4054 sslBN2KMFBN(BIGNUM *from, KMF_BIGINT *to)
4056 KMF_RETURN rv = KMF_OK;
4057 uint32_t sz;
4059 sz = BN_num_bytes(from);
4060 to->val = (uchar_t *)malloc(sz);
4061 if (to->val == NULL)
4062 return (KMF_ERR_MEMORY);
4064 if ((to->len = BN_bn2bin(from, to->val)) != sz) {
4065 free(to->val);
4066 to->val = NULL;
4067 to->len = 0;
4068 rv = KMF_ERR_MEMORY;
4071 return (rv);
4074 static KMF_RETURN
4075 exportRawRSAKey(RSA *rsa, KMF_RAW_KEY_DATA *key)
4077 KMF_RETURN rv;
4078 KMF_RAW_RSA_KEY *kmfkey = &key->rawdata.rsa;
4080 (void) memset(kmfkey, 0, sizeof (KMF_RAW_RSA_KEY));
4081 if ((rv = sslBN2KMFBN(rsa->n, &kmfkey->mod)) != KMF_OK)
4082 goto cleanup;
4084 if ((rv = sslBN2KMFBN(rsa->e, &kmfkey->pubexp)) != KMF_OK)
4085 goto cleanup;
4087 if (rsa->d != NULL)
4088 if ((rv = sslBN2KMFBN(rsa->d, &kmfkey->priexp)) != KMF_OK)
4089 goto cleanup;
4091 if (rsa->p != NULL)
4092 if ((rv = sslBN2KMFBN(rsa->p, &kmfkey->prime1)) != KMF_OK)
4093 goto cleanup;
4095 if (rsa->q != NULL)
4096 if ((rv = sslBN2KMFBN(rsa->q, &kmfkey->prime2)) != KMF_OK)
4097 goto cleanup;
4099 if (rsa->dmp1 != NULL)
4100 if ((rv = sslBN2KMFBN(rsa->dmp1, &kmfkey->exp1)) != KMF_OK)
4101 goto cleanup;
4103 if (rsa->dmq1 != NULL)
4104 if ((rv = sslBN2KMFBN(rsa->dmq1, &kmfkey->exp2)) != KMF_OK)
4105 goto cleanup;
4107 if (rsa->iqmp != NULL)
4108 if ((rv = sslBN2KMFBN(rsa->iqmp, &kmfkey->coef)) != KMF_OK)
4109 goto cleanup;
4110 cleanup:
4111 if (rv != KMF_OK)
4112 kmf_free_raw_key(key);
4113 else
4114 key->keytype = KMF_RSA;
4117 * Free the reference to this key, SSL will not actually free
4118 * the memory until the refcount == 0, so this is safe.
4120 RSA_free(rsa);
4122 return (rv);
4125 static KMF_RETURN
4126 exportRawDSAKey(DSA *dsa, KMF_RAW_KEY_DATA *key)
4128 KMF_RETURN rv;
4129 KMF_RAW_DSA_KEY *kmfkey = &key->rawdata.dsa;
4131 (void) memset(kmfkey, 0, sizeof (KMF_RAW_DSA_KEY));
4132 if ((rv = sslBN2KMFBN(dsa->p, &kmfkey->prime)) != KMF_OK)
4133 goto cleanup;
4135 if ((rv = sslBN2KMFBN(dsa->q, &kmfkey->subprime)) != KMF_OK)
4136 goto cleanup;
4138 if ((rv = sslBN2KMFBN(dsa->g, &kmfkey->base)) != KMF_OK)
4139 goto cleanup;
4141 if ((rv = sslBN2KMFBN(dsa->priv_key, &kmfkey->value)) != KMF_OK)
4142 goto cleanup;
4144 cleanup:
4145 if (rv != KMF_OK)
4146 kmf_free_raw_key(key);
4147 else
4148 key->keytype = KMF_DSA;
4151 * Free the reference to this key, SSL will not actually free
4152 * the memory until the refcount == 0, so this is safe.
4154 DSA_free(dsa);
4156 return (rv);
4159 static KMF_RETURN
4160 add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert,
4161 KMF_X509_DER_CERT **certlist, int *ncerts)
4163 KMF_RETURN rv = KMF_OK;
4164 KMF_X509_DER_CERT *list = (*certlist);
4165 KMF_X509_DER_CERT cert;
4166 int n = (*ncerts);
4168 if (list == NULL) {
4169 list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT));
4170 } else {
4171 list = (KMF_X509_DER_CERT *)realloc(list,
4172 sizeof (KMF_X509_DER_CERT) * (n + 1));
4175 if (list == NULL)
4176 return (KMF_ERR_MEMORY);
4178 (void) memset(&cert, 0, sizeof (cert));
4179 rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate);
4180 if (rv == KMF_OK) {
4181 int len = 0;
4182 /* Get the alias name for the cert if there is one */
4183 char *a = (char *)X509_alias_get0(sslcert, &len);
4184 if (a != NULL)
4185 cert.kmf_private.label = strdup(a);
4186 cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL;
4188 list[n] = cert;
4189 (*ncerts) = n + 1;
4191 *certlist = list;
4192 } else {
4193 free(list);
4196 return (rv);
4199 static KMF_RETURN
4200 add_key_to_list(KMF_RAW_KEY_DATA **keylist,
4201 KMF_RAW_KEY_DATA *newkey, int *nkeys)
4203 KMF_RAW_KEY_DATA *list = (*keylist);
4204 int n = (*nkeys);
4206 if (list == NULL) {
4207 list = (KMF_RAW_KEY_DATA *)malloc(sizeof (KMF_RAW_KEY_DATA));
4208 } else {
4209 list = (KMF_RAW_KEY_DATA *)realloc(list,
4210 sizeof (KMF_RAW_KEY_DATA) * (n + 1));
4213 if (list == NULL)
4214 return (KMF_ERR_MEMORY);
4216 list[n] = *newkey;
4217 (*nkeys) = n + 1;
4219 *keylist = list;
4221 return (KMF_OK);
4224 static X509_ATTRIBUTE *
4225 find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid)
4227 X509_ATTRIBUTE *a;
4228 int i;
4230 if (attrs == NULL)
4231 return (NULL);
4233 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
4234 /* LINTED E_BAD_PTR_CAST_ALIGN */
4235 a = sk_X509_ATTRIBUTE_value(attrs, i);
4236 if (OBJ_obj2nid(a->object) == nid)
4237 return (a);
4239 return (NULL);
4242 static KMF_RETURN
4243 convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key)
4245 KMF_RETURN rv = KMF_OK;
4246 X509_ATTRIBUTE *attr;
4248 if (pkey == NULL || key == NULL)
4249 return (KMF_ERR_BAD_PARAMETER);
4250 /* Convert SSL key to raw key */
4251 switch (pkey->type) {
4252 case EVP_PKEY_RSA:
4253 rv = exportRawRSAKey(EVP_PKEY_get1_RSA(pkey),
4254 key);
4255 if (rv != KMF_OK)
4256 return (rv);
4257 break;
4258 case EVP_PKEY_DSA:
4259 rv = exportRawDSAKey(EVP_PKEY_get1_DSA(pkey),
4260 key);
4261 if (rv != KMF_OK)
4262 return (rv);
4263 break;
4264 default:
4265 return (KMF_ERR_BAD_PARAMETER);
4268 * If friendlyName, add it to record.
4270 attr = find_attr(pkey->attributes, NID_friendlyName);
4271 if (attr != NULL) {
4272 ASN1_TYPE *ty = NULL;
4273 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4274 if (attr->single == 0 && numattr > 0) {
4275 /* LINTED E_BAD_PTR_CAST_ALIGN */
4276 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4278 if (ty != NULL) {
4279 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4280 key->label = uni2asc(ty->value.bmpstring->data,
4281 ty->value.bmpstring->length);
4282 #else
4283 key->label = OPENSSL_uni2asc(ty->value.bmpstring->data,
4284 ty->value.bmpstring->length);
4285 #endif
4287 } else {
4288 key->label = NULL;
4292 * If KeyID, add it to record as a KMF_DATA object.
4294 attr = find_attr(pkey->attributes, NID_localKeyID);
4295 if (attr != NULL) {
4296 ASN1_TYPE *ty = NULL;
4297 int numattr = sk_ASN1_TYPE_num(attr->value.set);
4298 if (attr->single == 0 && numattr > 0) {
4299 /* LINTED E_BAD_PTR_CAST_ALIGN */
4300 ty = sk_ASN1_TYPE_value(attr->value.set, 0);
4302 key->id.Data = (uchar_t *)malloc(
4303 ty->value.octet_string->length);
4304 if (key->id.Data == NULL)
4305 return (KMF_ERR_MEMORY);
4306 (void) memcpy(key->id.Data, ty->value.octet_string->data,
4307 ty->value.octet_string->length);
4308 key->id.Length = ty->value.octet_string->length;
4309 } else {
4310 (void) memset(&key->id, 0, sizeof (KMF_DATA));
4313 return (rv);
4316 static KMF_RETURN
4317 convertPK12Objects(
4318 KMF_HANDLE *kmfh,
4319 STACK_OF(EVP_PKEY) *sslkeys,
4320 STACK_OF(X509) *sslcert,
4321 STACK_OF(X509) *sslcacerts,
4322 KMF_RAW_KEY_DATA **keylist, int *nkeys,
4323 KMF_X509_DER_CERT **certlist, int *ncerts)
4325 KMF_RETURN rv = KMF_OK;
4326 KMF_RAW_KEY_DATA key;
4327 int i;
4329 for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) {
4330 /* LINTED E_BAD_PTR_CAST_ALIGN */
4331 EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i);
4332 rv = convertToRawKey(pkey, &key);
4333 if (rv == KMF_OK)
4334 rv = add_key_to_list(keylist, &key, nkeys);
4336 if (rv != KMF_OK)
4337 return (rv);
4340 /* Now add the certificate to the certlist */
4341 for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) {
4342 /* LINTED E_BAD_PTR_CAST_ALIGN */
4343 X509 *cert = sk_X509_value(sslcert, i);
4344 rv = add_cert_to_list(kmfh, cert, certlist, ncerts);
4345 if (rv != KMF_OK)
4346 return (rv);
4349 /* Also add any included CA certs to the list */
4350 for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
4351 X509 *c;
4353 * sk_X509_value() is macro that embeds a cast to (X509 *).
4354 * Here it translates into ((X509 *)sk_value((ca), (i))).
4355 * Lint is complaining about the embedded casting, and
4356 * to fix it, you need to fix openssl header files.
4358 /* LINTED E_BAD_PTR_CAST_ALIGN */
4359 c = sk_X509_value(sslcacerts, i);
4361 /* Now add the ca cert to the certlist */
4362 rv = add_cert_to_list(kmfh, c, certlist, ncerts);
4363 if (rv != KMF_OK)
4364 return (rv);
4366 return (rv);
4369 KMF_RETURN
4370 openssl_import_objects(KMF_HANDLE *kmfh,
4371 char *filename, KMF_CREDENTIAL *cred,
4372 KMF_X509_DER_CERT **certlist, int *ncerts,
4373 KMF_RAW_KEY_DATA **keylist, int *nkeys)
4375 KMF_RETURN rv = KMF_OK;
4376 KMF_ENCODE_FORMAT format;
4377 BIO *bio = NULL;
4378 STACK_OF(EVP_PKEY) *privkeys = NULL;
4379 STACK_OF(X509) *certs = NULL;
4380 STACK_OF(X509) *cacerts = NULL;
4383 * auto-detect the file format, regardless of what
4384 * the 'format' parameters in the params say.
4386 rv = kmf_get_file_format(filename, &format);
4387 if (rv != KMF_OK) {
4388 return (rv);
4391 /* This function only works for PEM or PKCS#12 files */
4392 if (format != KMF_FORMAT_PEM &&
4393 format != KMF_FORMAT_PEM_KEYPAIR &&
4394 format != KMF_FORMAT_PKCS12)
4395 return (KMF_ERR_ENCODING);
4397 *certlist = NULL;
4398 *keylist = NULL;
4399 *ncerts = 0;
4400 *nkeys = 0;
4402 if (format == KMF_FORMAT_PKCS12) {
4403 bio = BIO_new_file(filename, "rb");
4404 if (bio == NULL) {
4405 SET_ERROR(kmfh, ERR_get_error());
4406 rv = KMF_ERR_OPEN_FILE;
4407 goto end;
4410 rv = extract_pkcs12(bio, (uchar_t *)cred->cred,
4411 (uint32_t)cred->credlen, &privkeys, &certs, &cacerts);
4413 if (rv == KMF_OK)
4414 /* Convert keys and certs to exportable format */
4415 rv = convertPK12Objects(kmfh, privkeys, certs, cacerts,
4416 keylist, nkeys, certlist, ncerts);
4417 } else {
4418 EVP_PKEY *pkey;
4419 KMF_DATA *certdata = NULL;
4420 KMF_X509_DER_CERT *kmfcerts = NULL;
4421 int i;
4422 rv = extract_pem(kmfh, NULL, NULL, NULL, filename,
4423 (uchar_t *)cred->cred, (uint32_t)cred->credlen,
4424 &pkey, &certdata, ncerts);
4426 /* Reached end of import file? */
4427 if (rv == KMF_OK && pkey != NULL) {
4428 privkeys = sk_EVP_PKEY_new_null();
4429 if (privkeys == NULL) {
4430 rv = KMF_ERR_MEMORY;
4431 goto end;
4433 (void) sk_EVP_PKEY_push(privkeys, pkey);
4434 /* convert the certificate list here */
4435 if (*ncerts > 0 && certlist != NULL) {
4436 kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
4437 sizeof (KMF_X509_DER_CERT));
4438 if (kmfcerts == NULL) {
4439 rv = KMF_ERR_MEMORY;
4440 goto end;
4442 for (i = 0; i < *ncerts; i++) {
4443 kmfcerts[i].certificate = certdata[i];
4444 kmfcerts[i].kmf_private.keystore_type =
4445 KMF_KEYSTORE_OPENSSL;
4447 *certlist = kmfcerts;
4450 * Convert keys to exportable format, the certs
4451 * are already OK.
4453 rv = convertPK12Objects(kmfh, privkeys, NULL, NULL,
4454 keylist, nkeys, NULL, NULL);
4457 end:
4458 if (bio != NULL)
4459 (void) BIO_free(bio);
4461 if (privkeys)
4462 sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free);
4463 if (certs)
4464 sk_X509_pop_free(certs, X509_free);
4465 if (cacerts)
4466 sk_X509_pop_free(cacerts, X509_free);
4468 return (rv);
4471 static KMF_RETURN
4472 create_deskey(DES_cblock **deskey)
4474 DES_cblock *key;
4476 key = (DES_cblock *) malloc(sizeof (DES_cblock));
4477 if (key == NULL) {
4478 return (KMF_ERR_MEMORY);
4481 if (DES_random_key(key) == 0) {
4482 free(key);
4483 return (KMF_ERR_KEYGEN_FAILED);
4486 *deskey = key;
4487 return (KMF_OK);
4490 #define KEYGEN_RETRY 3
4491 #define DES3_KEY_SIZE 24
4493 static KMF_RETURN
4494 create_des3key(unsigned char **des3key)
4496 KMF_RETURN ret = KMF_OK;
4497 DES_cblock *deskey1 = NULL;
4498 DES_cblock *deskey2 = NULL;
4499 DES_cblock *deskey3 = NULL;
4500 unsigned char *newkey = NULL;
4501 int retry;
4503 if ((newkey = malloc(DES3_KEY_SIZE)) == NULL) {
4504 return (KMF_ERR_MEMORY);
4507 /* create the 1st DES key */
4508 if ((ret = create_deskey(&deskey1)) != KMF_OK) {
4509 goto out;
4513 * Create the 2nd DES key and make sure its value is different
4514 * from the 1st DES key.
4516 retry = 0;
4517 do {
4518 if (deskey2 != NULL) {
4519 free(deskey2);
4520 deskey2 = NULL;
4523 if ((ret = create_deskey(&deskey2)) != KMF_OK) {
4524 goto out;
4527 if (memcmp((const void *) deskey1, (const void *) deskey2, 8)
4528 == 0) {
4529 ret = KMF_ERR_KEYGEN_FAILED;
4530 retry++;
4532 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4534 if (ret != KMF_OK) {
4535 goto out;
4539 * Create the 3rd DES key and make sure its value is different
4540 * from the 2nd DES key.
4542 retry = 0;
4543 do {
4544 if (deskey3 != NULL) {
4545 free(deskey3);
4546 deskey3 = NULL;
4549 if ((ret = create_deskey(&deskey3)) != KMF_OK) {
4550 goto out;
4553 if (memcmp((const void *)deskey2, (const void *)deskey3, 8)
4554 == 0) {
4555 ret = KMF_ERR_KEYGEN_FAILED;
4556 retry++;
4558 } while (ret == KMF_ERR_KEYGEN_FAILED && retry < KEYGEN_RETRY);
4560 if (ret != KMF_OK) {
4561 goto out;
4564 /* Concatenate 3 DES keys into a DES3 key */
4565 (void) memcpy((void *)newkey, (const void *)deskey1, 8);
4566 (void) memcpy((void *)(newkey + 8), (const void *)deskey2, 8);
4567 (void) memcpy((void *)(newkey + 16), (const void *)deskey3, 8);
4568 *des3key = newkey;
4570 out:
4571 if (deskey1 != NULL)
4572 free(deskey1);
4574 if (deskey2 != NULL)
4575 free(deskey2);
4577 if (deskey3 != NULL)
4578 free(deskey3);
4580 if (ret != KMF_OK && newkey != NULL)
4581 free(newkey);
4583 return (ret);
4586 KMF_RETURN
4587 OpenSSL_CreateSymKey(KMF_HANDLE_T handle,
4588 int numattr, KMF_ATTRIBUTE *attrlist)
4590 KMF_RETURN ret = KMF_OK;
4591 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4592 char *fullpath = NULL;
4593 KMF_RAW_SYM_KEY *rkey = NULL;
4594 DES_cblock *deskey = NULL;
4595 unsigned char *des3key = NULL;
4596 unsigned char *random = NULL;
4597 int fd = -1;
4598 KMF_KEY_HANDLE *symkey;
4599 KMF_KEY_ALG keytype;
4600 uint32_t keylen;
4601 uint32_t keylen_size = sizeof (keylen);
4602 char *dirpath;
4603 char *keyfile;
4605 if (kmfh == NULL)
4606 return (KMF_ERR_UNINITIALIZED);
4608 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
4609 if (symkey == NULL)
4610 return (KMF_ERR_BAD_PARAMETER);
4612 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4614 keyfile = kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist, numattr);
4615 if (keyfile == NULL)
4616 return (KMF_ERR_BAD_PARAMETER);
4618 ret = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
4619 (void *)&keytype, NULL);
4620 if (ret != KMF_OK)
4621 return (KMF_ERR_BAD_PARAMETER);
4623 ret = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
4624 &keylen, &keylen_size);
4625 if (ret == KMF_ERR_ATTR_NOT_FOUND &&
4626 (keytype == KMF_DES || keytype == KMF_DES3))
4627 /* keylength is not required for DES and 3DES */
4628 ret = KMF_OK;
4629 if (ret != KMF_OK)
4630 return (KMF_ERR_BAD_PARAMETER);
4632 fullpath = get_fullpath(dirpath, keyfile);
4633 if (fullpath == NULL)
4634 return (KMF_ERR_BAD_PARAMETER);
4636 /* If the requested file exists, return an error */
4637 if (test_for_file(fullpath, 0400) == 1) {
4638 free(fullpath);
4639 return (KMF_ERR_DUPLICATE_KEYFILE);
4642 fd = open(fullpath, O_CREAT|O_TRUNC|O_RDWR, 0400);
4643 if (fd == -1) {
4644 ret = KMF_ERR_OPEN_FILE;
4645 goto out;
4648 rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
4649 if (rkey == NULL) {
4650 ret = KMF_ERR_MEMORY;
4651 goto out;
4653 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
4655 if (keytype == KMF_DES) {
4656 if ((ret = create_deskey(&deskey)) != KMF_OK) {
4657 goto out;
4659 rkey->keydata.val = (uchar_t *)deskey;
4660 rkey->keydata.len = 8;
4662 symkey->keyalg = KMF_DES;
4664 } else if (keytype == KMF_DES3) {
4665 if ((ret = create_des3key(&des3key)) != KMF_OK) {
4666 goto out;
4668 rkey->keydata.val = (uchar_t *)des3key;
4669 rkey->keydata.len = DES3_KEY_SIZE;
4670 symkey->keyalg = KMF_DES3;
4672 } else if (keytype == KMF_AES || keytype == KMF_RC4 ||
4673 keytype == KMF_GENERIC_SECRET) {
4674 int bytes;
4676 if (keylen % 8 != 0) {
4677 ret = KMF_ERR_BAD_KEY_SIZE;
4678 goto out;
4681 if (keytype == KMF_AES) {
4682 if (keylen != 128 &&
4683 keylen != 192 &&
4684 keylen != 256) {
4685 ret = KMF_ERR_BAD_KEY_SIZE;
4686 goto out;
4690 bytes = keylen/8;
4691 random = malloc(bytes);
4692 if (random == NULL) {
4693 ret = KMF_ERR_MEMORY;
4694 goto out;
4696 if (RAND_bytes(random, bytes) != 1) {
4697 ret = KMF_ERR_KEYGEN_FAILED;
4698 goto out;
4701 rkey->keydata.val = (uchar_t *)random;
4702 rkey->keydata.len = bytes;
4703 symkey->keyalg = keytype;
4705 } else {
4706 ret = KMF_ERR_BAD_KEY_TYPE;
4707 goto out;
4710 (void) write(fd, (const void *) rkey->keydata.val, rkey->keydata.len);
4712 symkey->kstype = KMF_KEYSTORE_OPENSSL;
4713 symkey->keyclass = KMF_SYMMETRIC;
4714 symkey->keylabel = (char *)fullpath;
4715 symkey->israw = TRUE;
4716 symkey->keyp = rkey;
4718 out:
4719 if (fd != -1)
4720 (void) close(fd);
4722 if (ret != KMF_OK && fullpath != NULL) {
4723 free(fullpath);
4725 if (ret != KMF_OK) {
4726 kmf_free_raw_sym_key(rkey);
4727 symkey->keyp = NULL;
4728 symkey->keyalg = KMF_KEYALG_NONE;
4731 return (ret);
4735 * Check a file to see if it is a CRL file with PEM or DER format.
4736 * If success, return its format in the "pformat" argument.
4738 KMF_RETURN
4739 OpenSSL_IsCRLFile(KMF_HANDLE_T handle, char *filename, int *pformat)
4741 KMF_RETURN ret = KMF_OK;
4742 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4743 BIO *bio = NULL;
4744 X509_CRL *xcrl = NULL;
4746 if (filename == NULL) {
4747 return (KMF_ERR_BAD_PARAMETER);
4750 bio = BIO_new_file(filename, "rb");
4751 if (bio == NULL) {
4752 SET_ERROR(kmfh, ERR_get_error());
4753 ret = KMF_ERR_OPEN_FILE;
4754 goto out;
4757 if ((xcrl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) {
4758 *pformat = KMF_FORMAT_PEM;
4759 goto out;
4761 (void) BIO_free(bio);
4764 * Now try to read it as raw DER data.
4766 bio = BIO_new_file(filename, "rb");
4767 if (bio == NULL) {
4768 SET_ERROR(kmfh, ERR_get_error());
4769 ret = KMF_ERR_OPEN_FILE;
4770 goto out;
4773 if ((xcrl = d2i_X509_CRL_bio(bio, NULL)) != NULL) {
4774 *pformat = KMF_FORMAT_ASN1;
4775 } else {
4776 ret = KMF_ERR_BAD_CRLFILE;
4779 out:
4780 if (bio != NULL)
4781 (void) BIO_free(bio);
4783 if (xcrl != NULL)
4784 X509_CRL_free(xcrl);
4786 return (ret);
4789 KMF_RETURN
4790 OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
4791 KMF_RAW_SYM_KEY *rkey)
4793 KMF_RETURN rv = KMF_OK;
4794 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4795 KMF_DATA keyvalue;
4797 if (kmfh == NULL)
4798 return (KMF_ERR_UNINITIALIZED);
4800 if (symkey == NULL || rkey == NULL)
4801 return (KMF_ERR_BAD_PARAMETER);
4802 else if (symkey->keyclass != KMF_SYMMETRIC)
4803 return (KMF_ERR_BAD_KEY_CLASS);
4805 if (symkey->israw) {
4806 KMF_RAW_SYM_KEY *rawkey = (KMF_RAW_SYM_KEY *)symkey->keyp;
4808 if (rawkey == NULL ||
4809 rawkey->keydata.val == NULL ||
4810 rawkey->keydata.len == 0)
4811 return (KMF_ERR_BAD_KEYHANDLE);
4813 rkey->keydata.len = rawkey->keydata.len;
4814 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
4815 return (KMF_ERR_MEMORY);
4816 (void) memcpy(rkey->keydata.val, rawkey->keydata.val,
4817 rkey->keydata.len);
4818 } else {
4819 rv = kmf_read_input_file(handle, symkey->keylabel, &keyvalue);
4820 if (rv != KMF_OK)
4821 return (rv);
4822 rkey->keydata.len = keyvalue.Length;
4823 rkey->keydata.val = keyvalue.Data;
4826 return (rv);
4830 * substitute for the unsafe access(2) function.
4831 * If the file in question already exists, return 1.
4832 * else 0. If an error occurs during testing (other
4833 * than EEXIST), return -1.
4835 static int
4836 test_for_file(char *filename, mode_t mode)
4838 int fd;
4841 * Try to create the file with the EXCL flag.
4842 * The call should fail if the file exists.
4844 fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
4845 if (fd == -1 && errno == EEXIST)
4846 return (1);
4847 else if (fd == -1) /* some other error */
4848 return (-1);
4850 /* The file did NOT exist. Delete the testcase. */
4851 (void) close(fd);
4852 (void) unlink(filename);
4853 return (0);
4856 KMF_RETURN
4857 OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr,
4858 KMF_ATTRIBUTE *attrlist)
4860 KMF_RETURN rv = KMF_OK;
4861 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4862 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
4863 KMF_RAW_KEY_DATA *rawkey;
4864 EVP_PKEY *pkey = NULL;
4865 KMF_ENCODE_FORMAT format = KMF_FORMAT_PEM;
4866 KMF_CREDENTIAL cred = { NULL, 0 };
4867 BIO *out = NULL;
4868 int keys = 0;
4869 char *fullpath = NULL;
4870 char *keyfile = NULL;
4871 char *dirpath = NULL;
4873 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
4874 if (pubkey != NULL)
4875 keys++;
4877 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
4878 if (prikey != NULL)
4879 keys++;
4881 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, attrlist, numattr);
4882 if (rawkey != NULL)
4883 keys++;
4886 * Exactly 1 type of key must be passed to this function.
4888 if (keys != 1)
4889 return (KMF_ERR_BAD_PARAMETER);
4891 keyfile = (char *)kmf_get_attr_ptr(KMF_KEY_FILENAME_ATTR, attrlist,
4892 numattr);
4893 if (keyfile == NULL)
4894 return (KMF_ERR_BAD_PARAMETER);
4896 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
4898 fullpath = get_fullpath(dirpath, keyfile);
4900 /* Once we have the full path, we don't need the pieces */
4901 if (fullpath == NULL)
4902 return (KMF_ERR_BAD_PARAMETER);
4904 /* If the requested file exists, return an error */
4905 if (test_for_file(fullpath, 0400) == 1) {
4906 free(fullpath);
4907 return (KMF_ERR_DUPLICATE_KEYFILE);
4910 rv = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
4911 &format, NULL);
4912 if (rv != KMF_OK)
4913 /* format is optional. */
4914 rv = KMF_OK;
4916 /* CRED is not required for OpenSSL files */
4917 (void) kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
4918 &cred, NULL);
4920 /* Store the private key to the keyfile */
4921 out = BIO_new_file(fullpath, "wb");
4922 if (out == NULL) {
4923 SET_ERROR(kmfh, ERR_get_error());
4924 rv = KMF_ERR_OPEN_FILE;
4925 goto end;
4928 if (prikey != NULL && prikey->keyp != NULL) {
4929 if (prikey->keyalg == KMF_RSA ||
4930 prikey->keyalg == KMF_DSA) {
4931 pkey = (EVP_PKEY *)prikey->keyp;
4933 rv = ssl_write_key(kmfh, format,
4934 out, &cred, pkey, TRUE);
4936 if (rv == KMF_OK && prikey->keylabel == NULL) {
4937 prikey->keylabel = strdup(fullpath);
4938 if (prikey->keylabel == NULL)
4939 rv = KMF_ERR_MEMORY;
4942 } else if (pubkey != NULL && pubkey->keyp != NULL) {
4943 if (pubkey->keyalg == KMF_RSA ||
4944 pubkey->keyalg == KMF_DSA) {
4945 pkey = (EVP_PKEY *)pubkey->keyp;
4947 rv = ssl_write_key(kmfh, format,
4948 out, &cred, pkey, FALSE);
4950 if (rv == KMF_OK && pubkey->keylabel == NULL) {
4951 pubkey->keylabel = strdup(fullpath);
4952 if (pubkey->keylabel == NULL)
4953 rv = KMF_ERR_MEMORY;
4956 } else if (rawkey != NULL) {
4957 if (rawkey->keytype == KMF_RSA) {
4958 pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
4959 } else if (rawkey->keytype == KMF_DSA) {
4960 pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
4961 } else {
4962 rv = KMF_ERR_BAD_PARAMETER;
4964 if (pkey != NULL) {
4965 KMF_KEY_CLASS kclass = KMF_ASYM_PRI;
4967 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
4968 (void *)&kclass, NULL);
4969 if (rv != KMF_OK)
4970 rv = KMF_OK;
4971 rv = ssl_write_key(kmfh, format, out,
4972 &cred, pkey, (kclass == KMF_ASYM_PRI));
4973 EVP_PKEY_free(pkey);
4977 end:
4979 if (out)
4980 (void) BIO_free(out);
4983 if (rv == KMF_OK)
4984 (void) chmod(fullpath, 0400);
4986 free(fullpath);
4987 return (rv);
4990 KMF_RETURN
4991 OpenSSL_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
4993 KMF_RETURN ret = KMF_OK;
4994 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
4995 X509_CRL *xcrl = NULL;
4996 X509 *xcert = NULL;
4997 EVP_PKEY *pkey;
4998 KMF_ENCODE_FORMAT format;
4999 BIO *in = NULL, *out = NULL;
5000 int openssl_ret = 0;
5001 KMF_ENCODE_FORMAT outformat;
5002 boolean_t crlcheck = FALSE;
5003 char *certfile, *dirpath, *crlfile, *incrl, *outcrl, *outcrlfile;
5005 if (numattr == 0 || attrlist == NULL) {
5006 return (KMF_ERR_BAD_PARAMETER);
5009 /* CRL check is optional */
5010 (void) kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
5011 &crlcheck, NULL);
5013 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5014 if (crlcheck == B_TRUE && certfile == NULL) {
5015 return (KMF_ERR_BAD_CERTFILE);
5018 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5019 incrl = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, numattr);
5020 outcrl = kmf_get_attr_ptr(KMF_CRL_OUTFILE_ATTR, attrlist, numattr);
5022 crlfile = get_fullpath(dirpath, incrl);
5024 if (crlfile == NULL)
5025 return (KMF_ERR_BAD_CRLFILE);
5027 outcrlfile = get_fullpath(dirpath, outcrl);
5028 if (outcrlfile == NULL)
5029 return (KMF_ERR_BAD_CRLFILE);
5031 if (isdir(outcrlfile)) {
5032 free(outcrlfile);
5033 return (KMF_ERR_BAD_CRLFILE);
5036 ret = kmf_is_crl_file(handle, crlfile, &format);
5037 if (ret != KMF_OK) {
5038 free(outcrlfile);
5039 return (ret);
5042 in = BIO_new_file(crlfile, "rb");
5043 if (in == NULL) {
5044 SET_ERROR(kmfh, ERR_get_error());
5045 ret = KMF_ERR_OPEN_FILE;
5046 goto end;
5049 if (format == KMF_FORMAT_ASN1) {
5050 xcrl = d2i_X509_CRL_bio(in, NULL);
5051 } else if (format == KMF_FORMAT_PEM) {
5052 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5055 if (xcrl == NULL) {
5056 SET_ERROR(kmfh, ERR_get_error());
5057 ret = KMF_ERR_BAD_CRLFILE;
5058 goto end;
5061 /* If bypasscheck is specified, no need to verify. */
5062 if (crlcheck == B_FALSE)
5063 goto output;
5065 ret = kmf_is_cert_file(handle, certfile, &format);
5066 if (ret != KMF_OK)
5067 goto end;
5069 /* Read in the CA cert file and convert to X509 */
5070 if (BIO_read_filename(in, certfile) <= 0) {
5071 SET_ERROR(kmfh, ERR_get_error());
5072 ret = KMF_ERR_OPEN_FILE;
5073 goto end;
5076 if (format == KMF_FORMAT_ASN1) {
5077 xcert = d2i_X509_bio(in, NULL);
5078 } else if (format == KMF_FORMAT_PEM) {
5079 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5080 } else {
5081 ret = KMF_ERR_BAD_CERT_FORMAT;
5082 goto end;
5085 if (xcert == NULL) {
5086 SET_ERROR(kmfh, ERR_get_error());
5087 ret = KMF_ERR_BAD_CERT_FORMAT;
5088 goto end;
5090 /* Now get the public key from the CA cert */
5091 pkey = X509_get_pubkey(xcert);
5092 if (pkey == NULL) {
5093 SET_ERROR(kmfh, ERR_get_error());
5094 ret = KMF_ERR_BAD_CERTFILE;
5095 goto end;
5098 /* Verify the CRL with the CA's public key */
5099 openssl_ret = X509_CRL_verify(xcrl, pkey);
5100 EVP_PKEY_free(pkey);
5101 if (openssl_ret > 0) {
5102 ret = KMF_OK; /* verify succeed */
5103 } else {
5104 SET_ERROR(kmfh, openssl_ret);
5105 ret = KMF_ERR_BAD_CRLFILE;
5108 output:
5109 ret = kmf_get_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, numattr,
5110 &outformat, NULL);
5111 if (ret != KMF_OK) {
5112 ret = KMF_OK;
5113 outformat = KMF_FORMAT_PEM;
5116 out = BIO_new_file(outcrlfile, "wb");
5117 if (out == NULL) {
5118 SET_ERROR(kmfh, ERR_get_error());
5119 ret = KMF_ERR_OPEN_FILE;
5120 goto end;
5123 if (outformat == KMF_FORMAT_ASN1) {
5124 openssl_ret = (int)i2d_X509_CRL_bio(out, xcrl);
5125 } else if (outformat == KMF_FORMAT_PEM) {
5126 openssl_ret = PEM_write_bio_X509_CRL(out, xcrl);
5127 } else {
5128 ret = KMF_ERR_BAD_PARAMETER;
5129 goto end;
5132 if (openssl_ret <= 0) {
5133 SET_ERROR(kmfh, ERR_get_error());
5134 ret = KMF_ERR_WRITE_FILE;
5135 } else {
5136 ret = KMF_OK;
5139 end:
5140 if (xcrl != NULL)
5141 X509_CRL_free(xcrl);
5143 if (xcert != NULL)
5144 X509_free(xcert);
5146 if (in != NULL)
5147 (void) BIO_free(in);
5149 if (out != NULL)
5150 (void) BIO_free(out);
5152 if (outcrlfile != NULL)
5153 free(outcrlfile);
5155 return (ret);
5158 KMF_RETURN
5159 OpenSSL_ListCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5161 KMF_RETURN ret = KMF_OK;
5162 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5163 X509_CRL *x = NULL;
5164 KMF_ENCODE_FORMAT format;
5165 char *crlfile = NULL;
5166 BIO *in = NULL;
5167 BIO *mem = NULL;
5168 long len;
5169 char *memptr;
5170 char *data = NULL;
5171 char **crldata;
5172 char *crlfilename, *dirpath;
5174 if (numattr == 0 || attrlist == NULL) {
5175 return (KMF_ERR_BAD_PARAMETER);
5177 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5178 attrlist, numattr);
5179 if (crlfilename == NULL)
5180 return (KMF_ERR_BAD_CRLFILE);
5182 crldata = (char **)kmf_get_attr_ptr(KMF_CRL_DATA_ATTR,
5183 attrlist, numattr);
5185 if (crldata == NULL)
5186 return (KMF_ERR_BAD_PARAMETER);
5188 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5190 crlfile = get_fullpath(dirpath, crlfilename);
5192 if (crlfile == NULL)
5193 return (KMF_ERR_BAD_CRLFILE);
5195 if (isdir(crlfile)) {
5196 free(crlfile);
5197 return (KMF_ERR_BAD_CRLFILE);
5200 ret = kmf_is_crl_file(handle, crlfile, &format);
5201 if (ret != KMF_OK) {
5202 free(crlfile);
5203 return (ret);
5206 if (bio_err == NULL)
5207 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
5209 in = BIO_new_file(crlfile, "rb");
5210 if (in == NULL) {
5211 SET_ERROR(kmfh, ERR_get_error());
5212 ret = KMF_ERR_OPEN_FILE;
5213 goto end;
5216 if (format == KMF_FORMAT_ASN1) {
5217 x = d2i_X509_CRL_bio(in, NULL);
5218 } else if (format == KMF_FORMAT_PEM) {
5219 x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5222 if (x == NULL) { /* should not happen */
5223 SET_ERROR(kmfh, ERR_get_error());
5224 ret = KMF_ERR_OPEN_FILE;
5225 goto end;
5228 mem = BIO_new(BIO_s_mem());
5229 if (mem == NULL) {
5230 SET_ERROR(kmfh, ERR_get_error());
5231 ret = KMF_ERR_MEMORY;
5232 goto end;
5235 (void) X509_CRL_print(mem, x);
5236 len = BIO_get_mem_data(mem, &memptr);
5237 if (len <= 0) {
5238 SET_ERROR(kmfh, ERR_get_error());
5239 ret = KMF_ERR_MEMORY;
5240 goto end;
5243 data = malloc(len + 1);
5244 if (data == NULL) {
5245 ret = KMF_ERR_MEMORY;
5246 goto end;
5249 (void) memcpy(data, memptr, len);
5250 data[len] = '\0';
5251 *crldata = data;
5253 end:
5254 if (x != NULL)
5255 X509_CRL_free(x);
5257 if (crlfile != NULL)
5258 free(crlfile);
5260 if (in != NULL)
5261 (void) BIO_free(in);
5263 if (mem != NULL)
5264 (void) BIO_free(mem);
5266 return (ret);
5269 KMF_RETURN
5270 OpenSSL_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5272 KMF_RETURN ret = KMF_OK;
5273 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5274 KMF_ENCODE_FORMAT format;
5275 char *crlfile = NULL;
5276 BIO *in = NULL;
5277 char *crlfilename, *dirpath;
5279 if (numattr == 0 || attrlist == NULL) {
5280 return (KMF_ERR_BAD_PARAMETER);
5283 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5284 attrlist, numattr);
5286 if (crlfilename == NULL)
5287 return (KMF_ERR_BAD_CRLFILE);
5289 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5291 crlfile = get_fullpath(dirpath, crlfilename);
5293 if (crlfile == NULL)
5294 return (KMF_ERR_BAD_CRLFILE);
5296 if (isdir(crlfile)) {
5297 ret = KMF_ERR_BAD_CRLFILE;
5298 goto end;
5301 ret = kmf_is_crl_file(handle, crlfile, &format);
5302 if (ret != KMF_OK)
5303 goto end;
5305 if (unlink(crlfile) != 0) {
5306 SET_SYS_ERROR(kmfh, errno);
5307 ret = KMF_ERR_INTERNAL;
5308 goto end;
5311 end:
5312 if (in != NULL)
5313 (void) BIO_free(in);
5314 if (crlfile != NULL)
5315 free(crlfile);
5317 return (ret);
5320 KMF_RETURN
5321 OpenSSL_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
5323 KMF_RETURN ret = KMF_OK;
5324 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5325 KMF_ENCODE_FORMAT format;
5326 BIO *in = NULL;
5327 X509 *xcert = NULL;
5328 X509_CRL *xcrl = NULL;
5329 STACK_OF(X509_REVOKED) *revoke_stack = NULL;
5330 X509_REVOKED *revoke;
5331 int i;
5332 char *crlfilename, *crlfile, *dirpath, *certfile;
5334 if (numattr == 0 || attrlist == NULL) {
5335 return (KMF_ERR_BAD_PARAMETER);
5338 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR,
5339 attrlist, numattr);
5341 if (crlfilename == NULL)
5342 return (KMF_ERR_BAD_CRLFILE);
5344 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
5345 if (certfile == NULL)
5346 return (KMF_ERR_BAD_CRLFILE);
5348 dirpath = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
5350 crlfile = get_fullpath(dirpath, crlfilename);
5352 if (crlfile == NULL)
5353 return (KMF_ERR_BAD_CRLFILE);
5355 if (isdir(crlfile)) {
5356 ret = KMF_ERR_BAD_CRLFILE;
5357 goto end;
5360 ret = kmf_is_crl_file(handle, crlfile, &format);
5361 if (ret != KMF_OK)
5362 goto end;
5364 /* Read the CRL file and load it into a X509_CRL structure */
5365 in = BIO_new_file(crlfilename, "rb");
5366 if (in == NULL) {
5367 SET_ERROR(kmfh, ERR_get_error());
5368 ret = KMF_ERR_OPEN_FILE;
5369 goto end;
5372 if (format == KMF_FORMAT_ASN1) {
5373 xcrl = d2i_X509_CRL_bio(in, NULL);
5374 } else if (format == KMF_FORMAT_PEM) {
5375 xcrl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
5378 if (xcrl == NULL) {
5379 SET_ERROR(kmfh, ERR_get_error());
5380 ret = KMF_ERR_BAD_CRLFILE;
5381 goto end;
5383 (void) BIO_free(in);
5385 /* Read the Certificate file and load it into a X509 structure */
5386 ret = kmf_is_cert_file(handle, certfile, &format);
5387 if (ret != KMF_OK)
5388 goto end;
5390 in = BIO_new_file(certfile, "rb");
5391 if (in == NULL) {
5392 SET_ERROR(kmfh, ERR_get_error());
5393 ret = KMF_ERR_OPEN_FILE;
5394 goto end;
5397 if (format == KMF_FORMAT_ASN1) {
5398 xcert = d2i_X509_bio(in, NULL);
5399 } else if (format == KMF_FORMAT_PEM) {
5400 xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
5403 if (xcert == NULL) {
5404 SET_ERROR(kmfh, ERR_get_error());
5405 ret = KMF_ERR_BAD_CERTFILE;
5406 goto end;
5409 /* Check if the certificate and the CRL have same issuer */
5410 if (X509_NAME_cmp(xcert->cert_info->issuer, xcrl->crl->issuer) != 0) {
5411 ret = KMF_ERR_ISSUER;
5412 goto end;
5415 /* Check to see if the certificate serial number is revoked */
5416 revoke_stack = X509_CRL_get_REVOKED(xcrl);
5417 if (sk_X509_REVOKED_num(revoke_stack) <= 0) {
5418 /* No revoked certificates in the CRL file */
5419 SET_ERROR(kmfh, ERR_get_error());
5420 ret = KMF_ERR_EMPTY_CRL;
5421 goto end;
5424 for (i = 0; i < sk_X509_REVOKED_num(revoke_stack); i++) {
5425 /* LINTED E_BAD_PTR_CAST_ALIGN */
5426 revoke = sk_X509_REVOKED_value(revoke_stack, i);
5427 if (ASN1_INTEGER_cmp(xcert->cert_info->serialNumber,
5428 revoke->serialNumber) == 0) {
5429 break;
5433 if (i < sk_X509_REVOKED_num(revoke_stack)) {
5434 ret = KMF_OK;
5435 } else {
5436 ret = KMF_ERR_NOT_REVOKED;
5439 end:
5440 if (in != NULL)
5441 (void) BIO_free(in);
5442 if (xcrl != NULL)
5443 X509_CRL_free(xcrl);
5444 if (xcert != NULL)
5445 X509_free(xcert);
5447 return (ret);
5450 KMF_RETURN
5451 OpenSSL_VerifyCRLFile(KMF_HANDLE_T handle, char *crlname, KMF_DATA *tacert)
5453 KMF_RETURN ret = KMF_OK;
5454 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5455 BIO *bcrl = NULL;
5456 X509_CRL *xcrl = NULL;
5457 X509 *xcert = NULL;
5458 EVP_PKEY *pkey;
5459 int sslret;
5460 KMF_ENCODE_FORMAT crl_format;
5461 unsigned char *p;
5462 long len;
5464 if (handle == NULL || crlname == NULL || tacert == NULL) {
5465 return (KMF_ERR_BAD_PARAMETER);
5468 ret = kmf_get_file_format(crlname, &crl_format);
5469 if (ret != KMF_OK)
5470 return (ret);
5472 bcrl = BIO_new_file(crlname, "rb");
5473 if (bcrl == NULL) {
5474 SET_ERROR(kmfh, ERR_get_error());
5475 ret = KMF_ERR_OPEN_FILE;
5476 goto cleanup;
5479 if (crl_format == KMF_FORMAT_ASN1) {
5480 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5481 } else if (crl_format == KMF_FORMAT_PEM) {
5482 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5483 } else {
5484 ret = KMF_ERR_BAD_PARAMETER;
5485 goto cleanup;
5488 if (xcrl == NULL) {
5489 SET_ERROR(kmfh, ERR_get_error());
5490 ret = KMF_ERR_BAD_CRLFILE;
5491 goto cleanup;
5494 p = tacert->Data;
5495 len = tacert->Length;
5496 xcert = d2i_X509(NULL, (const uchar_t **)&p, len);
5498 if (xcert == NULL) {
5499 SET_ERROR(kmfh, ERR_get_error());
5500 ret = KMF_ERR_BAD_CERTFILE;
5501 goto cleanup;
5504 /* Get issuer certificate public key */
5505 pkey = X509_get_pubkey(xcert);
5506 if (pkey == NULL) {
5507 SET_ERROR(kmfh, ERR_get_error());
5508 ret = KMF_ERR_BAD_CERT_FORMAT;
5509 goto cleanup;
5512 /* Verify CRL signature */
5513 sslret = X509_CRL_verify(xcrl, pkey);
5514 EVP_PKEY_free(pkey);
5515 if (sslret > 0) {
5516 ret = KMF_OK;
5517 } else {
5518 SET_ERROR(kmfh, sslret);
5519 ret = KMF_ERR_BAD_CRLFILE;
5522 cleanup:
5523 if (bcrl != NULL)
5524 (void) BIO_free(bcrl);
5526 if (xcrl != NULL)
5527 X509_CRL_free(xcrl);
5529 if (xcert != NULL)
5530 X509_free(xcert);
5532 return (ret);
5536 KMF_RETURN
5537 OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname)
5539 KMF_RETURN ret = KMF_OK;
5540 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
5541 KMF_ENCODE_FORMAT crl_format;
5542 BIO *bcrl = NULL;
5543 X509_CRL *xcrl = NULL;
5544 int i;
5546 if (handle == NULL || crlname == NULL) {
5547 return (KMF_ERR_BAD_PARAMETER);
5550 ret = kmf_is_crl_file(handle, crlname, &crl_format);
5551 if (ret != KMF_OK)
5552 return (ret);
5554 bcrl = BIO_new_file(crlname, "rb");
5555 if (bcrl == NULL) {
5556 SET_ERROR(kmfh, ERR_get_error());
5557 ret = KMF_ERR_OPEN_FILE;
5558 goto cleanup;
5561 if (crl_format == KMF_FORMAT_ASN1)
5562 xcrl = d2i_X509_CRL_bio(bcrl, NULL);
5563 else if (crl_format == KMF_FORMAT_PEM)
5564 xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL);
5566 if (xcrl == NULL) {
5567 SET_ERROR(kmfh, ERR_get_error());
5568 ret = KMF_ERR_BAD_CRLFILE;
5569 goto cleanup;
5571 i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL);
5572 if (i >= 0) {
5573 ret = KMF_ERR_VALIDITY_PERIOD;
5574 goto cleanup;
5576 if (X509_CRL_get_nextUpdate(xcrl)) {
5577 i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL);
5579 if (i <= 0) {
5580 ret = KMF_ERR_VALIDITY_PERIOD;
5581 goto cleanup;
5585 ret = KMF_OK;
5587 cleanup:
5588 if (bcrl != NULL)
5589 (void) BIO_free(bcrl);
5591 if (xcrl != NULL)
5592 X509_CRL_free(xcrl);
5594 return (ret);