dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libkmf / plugins / kmf_nss / common / nss_spi.c
blob10fd7c45849bcf7571cee6f8c19e7d436cd86b6a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * NSS keystore wrapper
25 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <synch.h>
35 #include <kmfapiP.h>
36 #include <ber_der.h>
37 /* NSS related headers */
39 #include <mps/nss.h>
40 #include <mps/cert.h>
41 #include <mps/certdb.h>
42 #include <mps/secoid.h>
43 #include <mps/secder.h>
44 #include <mps/secerr.h>
45 #include <mps/cryptohi.h>
46 #include <mps/keyhi.h>
47 #include <mps/keythi.h>
48 #include <mps/pk11func.h>
49 #include <mps/pk11pqg.h>
50 #include <mps/pkcs12.h>
51 #include <mps/p12plcy.h>
52 #include <mps/prerror.h>
54 #define NSS_OK 0
56 mutex_t init_lock = DEFAULTMUTEX;
57 static int nss_initialized = 0;
59 KMF_RETURN
60 NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
62 KMF_RETURN
63 NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
65 void
66 NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
68 KMF_RETURN
69 NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
71 KMF_RETURN
72 NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
74 KMF_RETURN
75 NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
77 KMF_RETURN
78 NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
80 KMF_RETURN
81 NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
83 KMF_RETURN
84 NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
86 KMF_RETURN
87 NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
88 KMF_DATA *, KMF_DATA *);
90 KMF_RETURN
91 NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
93 KMF_RETURN
94 NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
96 KMF_RETURN
97 NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
99 KMF_RETURN
100 NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
102 KMF_RETURN
103 NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
105 KMF_RETURN
106 NSS_GetErrorString(KMF_HANDLE_T, char **);
108 KMF_RETURN
109 NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
111 KMF_RETURN
112 NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
114 KMF_RETURN
115 NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
116 KMF_DATA *, KMF_DATA *);
118 KMF_RETURN
119 NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
121 KMF_RETURN
122 NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
124 KMF_RETURN
125 NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
127 KMF_RETURN
128 NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
130 static
131 KMF_PLUGIN_FUNCLIST nss_plugin_table =
133 1, /* Version */
134 NSS_ConfigureKeystore,
135 NSS_FindCert,
136 NSS_FreeKMFCert,
137 NSS_StoreCert,
138 NSS_ImportCert,
139 NSS_ImportCRL,
140 NSS_DeleteCert,
141 NSS_DeleteCRL,
142 NSS_CreateKeypair,
143 NSS_FindKey,
144 NSS_EncodePubKeyData,
145 NSS_SignData,
146 NSS_DeleteKey,
147 NULL /* ListCRL */,
148 NSS_FindCRL,
149 NSS_FindCertInCRL,
150 NSS_GetErrorString,
151 NSS_FindPrikeyByCert,
152 NSS_DecryptData,
153 NSS_ExportPK12,
154 NSS_CreateSymKey,
155 NSS_GetSymKeyValue,
156 NSS_SetTokenPin,
157 NSS_StoreKey,
158 NULL /* Finalize */
161 /* additions for importing and exporting PKCS 12 files */
162 typedef struct p12uContextStr {
163 char *filename; /* name of file */
164 PRFileDesc *file; /* pointer to file */
165 PRBool error; /* error occurred? */
166 int errorValue; /* which error occurred? */
167 } p12uContext;
169 #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \
170 h->lasterr.errcode = c;
172 KMF_PLUGIN_FUNCLIST *
173 KMF_Plugin_Initialize()
175 (void) SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
176 (void) SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
177 (void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
178 (void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
179 (void) SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
180 (void) SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
181 (void) SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
183 return (&nss_plugin_table);
186 static char *
187 /*ARGSUSED*/
188 nss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg)
190 if (retry)
191 return (NULL);
192 if (arg != NULL)
193 return ((char *)strdup(arg));
194 else
195 return (NULL);
198 static KMF_RETURN
199 nss_authenticate(KMF_HANDLE_T handle,
200 PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred)
203 SECStatus nssrv = SECSuccess;
204 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
206 /* If a password was given, try to login to the slot */
207 if (cred == NULL || cred->cred == NULL || cred->credlen == 0 ||
208 nss_slot == NULL) {
209 return (KMF_ERR_BAD_PARAMETER);
212 if (PK11_IsLoggedIn(nss_slot, NULL)) {
213 return (KMF_OK);
216 PK11_SetPasswordFunc(nss_getpassword);
217 nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred);
219 if (nssrv != SECSuccess) {
220 SET_ERROR(kmfh, nssrv);
221 PK11_FreeSlot(nss_slot);
222 return (KMF_ERR_AUTH_FAILED);
225 return (KMF_OK);
228 static SECStatus
229 Init_NSS_DBs(const char *configdir,
230 const char *certPrefix,
231 const char *keyPrefix,
232 const char *secmodName)
234 SECStatus rv = NSS_OK;
236 (void) mutex_lock(&init_lock);
238 /* If another thread already did it, return OK. */
239 if (nss_initialized) {
240 (void) mutex_unlock(&init_lock);
241 return (SECSuccess);
244 rv = NSS_Initialize((configdir && strlen(configdir)) ?
245 configdir : "./", certPrefix, keyPrefix,
246 secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE);
247 if (rv != SECSuccess) {
248 goto end;
251 nss_initialized++;
252 end:
253 (void) mutex_unlock(&init_lock);
254 return (rv);
258 * When it is called the first time, it will intialize NSS. Once the NSS
259 * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED
260 * if it is called again.
262 KMF_RETURN
263 NSS_ConfigureKeystore(KMF_HANDLE_T handle,
264 int numattr, KMF_ATTRIBUTE *attrlist)
266 KMF_RETURN rv = KMF_OK;
267 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
268 char *configdir;
269 char *certPrefix;
270 char *keyPrefix;
271 char *secModName;
273 configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
274 certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr);
275 keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr);
276 secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr);
278 (void) mutex_lock(&init_lock);
279 if (nss_initialized == 0) {
280 SECStatus err;
282 (void) mutex_unlock(&init_lock);
283 err = Init_NSS_DBs(configdir, certPrefix,
284 keyPrefix, secModName);
285 if (err != SECSuccess) {
286 SET_ERROR(kmfh, err);
287 return (KMF_ERR_INTERNAL);
289 } else {
290 rv = KMF_KEYSTORE_ALREADY_INITIALIZED;
291 (void) mutex_unlock(&init_lock);
294 return (rv);
298 * This function sets up the slot to be used for other operations.
299 * This function is basically called by every NSS SPI function.
300 * For those functions that can only be performed in the internal slot, the
301 * boolean "internal_slot_only" argument needs to be TRUE.
302 * A slot pointer will be returned when this function is executed successfully.
304 KMF_RETURN
305 do_nss_init(void *handle, int numattr,
306 KMF_ATTRIBUTE *attrlist,
307 boolean_t internal_slot_only,
308 PK11SlotInfo **nss_slot)
310 KMF_RETURN rv = KMF_OK;
311 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
312 char *slotlabel = NULL;
314 if (!nss_initialized)
315 return (KMF_ERR_PLUGIN_INIT);
317 slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
319 * NSS Is already initialized, but we need to find
320 * the right slot.
322 if (slotlabel == NULL ||
323 strcmp(slotlabel, "internal") == 0) {
324 *nss_slot = PK11_GetInternalKeySlot();
325 } else if (internal_slot_only == TRUE) {
326 rv = KMF_ERR_SLOTNAME;
327 goto end;
328 } else {
329 *nss_slot = PK11_FindSlotByName(slotlabel);
332 if (*nss_slot == NULL) {
333 SET_ERROR(kmfh, PORT_GetError());
334 rv = KMF_ERR_SLOTNAME;
335 goto end;
339 * If the token was not yet initialized, return an error.
341 if (PK11_NeedUserInit(*nss_slot)) {
342 rv = KMF_ERR_UNINITIALIZED_TOKEN;
345 end:
346 return (rv);
349 static KMF_RETURN
350 nss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert)
352 kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS;
353 kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
355 kmf_cert->certificate.Length = nss_cert->derCert.len;
357 if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) ==
358 NULL) {
359 kmf_cert->certificate.Length = 0;
360 return (KMF_ERR_MEMORY);
362 (void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data,
363 nss_cert->derCert.len);
364 if (nss_cert->nickname != NULL)
365 kmf_cert->kmf_private.label =
366 (char *)strdup(nss_cert->nickname);
367 return (KMF_OK);
370 static KMF_RETURN
371 nss_getcert_by_label(KMF_HANDLE *kmfh,
372 char *name, KMF_X509_DER_CERT *kmf_cert,
373 uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria)
375 KMF_RETURN rv = KMF_OK;
376 CERTCertificate *nss_cert;
377 SECCertTimeValidity validity;
379 nss_cert = PK11_FindCertFromNickname(name, NULL);
380 if (nss_cert == NULL) {
381 *num_certs = 0;
382 SET_ERROR(kmfh, PORT_GetError());
383 *num_certs = 0;
384 return (KMF_ERR_CERT_NOT_FOUND);
385 } else {
386 *num_certs = 1;
389 switch (find_criteria) {
390 case KMF_ALL_CERTS:
391 break;
392 case KMF_NONEXPIRED_CERTS:
393 validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
394 PR_FALSE);
395 if (validity != secCertTimeValid) {
396 /* this is an invalid cert, reject it */
397 *num_certs = 0;
398 CERT_DestroyCertificate(nss_cert);
399 return (KMF_OK);
401 break;
402 case KMF_EXPIRED_CERTS:
403 validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
404 PR_FALSE);
405 if (validity == secCertTimeValid) {
406 /* this is a valid cert, reject it in this case. */
407 *num_certs = 0;
408 CERT_DestroyCertificate(nss_cert);
409 return (KMF_OK);
411 break;
412 default:
413 return (KMF_ERR_BAD_PARAMETER);
416 if (kmf_cert != NULL)
417 rv = nss2kmf_cert(nss_cert, kmf_cert);
419 /* We copied the data we need, so cleanup the internal record */
420 CERT_DestroyCertificate(nss_cert);
422 if (rv != KMF_OK)
423 *num_certs = 0;
425 return (rv);
428 static KMF_RETURN
429 nss_find_matching_certs(PK11SlotInfo *slot,
430 char *issuer, char *subject, KMF_BIGINT *serial,
431 CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria)
433 KMF_RETURN rv = KMF_OK;
434 SECStatus ret;
435 CERTCertList *list;
436 CERTCertListNode *node;
437 KMF_X509_NAME issuerDN, subjectDN;
438 boolean_t findIssuer = FALSE;
439 boolean_t findSubject = FALSE;
440 boolean_t findSerial = FALSE;
442 if (issuer != NULL && strlen(issuer)) {
443 rv = kmf_dn_parser(issuer, &issuerDN);
444 if (rv != KMF_OK)
445 return (rv);
446 findIssuer = TRUE;
448 if (subject != NULL && strlen(subject)) {
449 rv = kmf_dn_parser(subject, &subjectDN);
450 if (rv != KMF_OK)
451 return (rv);
452 findSubject = TRUE;
454 if (serial != 0 && serial->val != NULL && serial->len > 0)
455 findSerial = TRUE;
457 list = PK11_ListCertsInSlot(slot);
458 if (list) {
459 node = CERT_LIST_HEAD(list);
460 while (!CERT_LIST_END(node, list)) {
461 KMF_X509_NAME cmpDN;
462 KMF_DATA der;
463 boolean_t match;
464 CERTCertListNode *freenode;
466 if (findIssuer) {
467 der.Data = node->cert->derIssuer.data;
468 der.Length = node->cert->derIssuer.len;
469 rv = DerDecodeName(&der, &cmpDN);
470 if (rv == KMF_OK) {
471 match = !KMF_CompareRDNs(&issuerDN,
472 &cmpDN);
473 kmf_free_dn(&cmpDN);
474 if (!match)
475 goto delete_and_cont;
476 } else {
477 goto delete_and_cont;
480 if (findSubject) {
481 der.Data = node->cert->derSubject.data;
482 der.Length = node->cert->derSubject.len;
483 rv = DerDecodeName(&der, &cmpDN);
484 if (rv == KMF_OK) {
485 match = !KMF_CompareRDNs(&subjectDN,
486 &cmpDN);
487 kmf_free_dn(&cmpDN);
488 if (!match)
489 goto delete_and_cont;
490 } else {
491 goto delete_and_cont;
494 if (findSerial) {
495 SECItem *sernum;
497 sernum = &node->cert->serialNumber;
499 if (serial->len != sernum->len)
500 goto delete_and_cont;
502 if (memcmp(sernum->data, serial->val,
503 serial->len))
504 goto delete_and_cont;
507 /* select the certs using find criteria */
508 switch (find_criteria) {
509 case KMF_ALL_CERTS:
510 break;
511 case KMF_NONEXPIRED_CERTS:
512 ret = CERT_CertTimesValid(node->cert);
513 if (ret == SECFailure) {
514 /* this is an invalid cert */
515 goto skip;
517 break;
519 case KMF_EXPIRED_CERTS:
520 ret = CERT_CertTimesValid(node->cert);
521 if (ret != SECFailure) {
522 /* this is a valid cert */
523 goto skip;
525 break;
527 skip:
528 node = CERT_LIST_NEXT(node);
529 continue;
530 delete_and_cont:
531 freenode = node;
532 node = CERT_LIST_NEXT(node);
533 CERT_RemoveCertListNode(freenode);
537 if (rv == KMF_OK && certlist != NULL) {
538 *certlist = list;
539 } else {
540 CERT_DestroyCertList(list);
542 return (rv);
545 static KMF_RETURN
546 convertCertList(void *kmfhandle,
547 CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts,
548 uint32_t *numcerts)
550 KMF_RETURN rv = KMF_OK;
551 CERTCertListNode *node;
552 uint32_t maxcerts = *numcerts;
554 maxcerts = *numcerts;
555 if (maxcerts == 0)
556 maxcerts = 0xFFFFFFFF;
558 *numcerts = 0;
561 * Don't copy more certs than the caller wanted.
563 for (node = CERT_LIST_HEAD(nsscerts);
564 !CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
565 (*numcerts) < maxcerts;
566 node = CERT_LIST_NEXT(node), (*numcerts)++) {
567 if (kmfcerts != NULL)
568 rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
572 * If we failed, delete any certs allocated so far.
574 if (rv != KMF_OK) {
575 int i;
576 for (i = 0; i < *numcerts; i++)
577 kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]);
579 *numcerts = 0;
581 return (rv);
584 KMF_RETURN
585 NSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
587 KMF_RETURN rv = KMF_OK;
588 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
589 PK11SlotInfo *nss_slot = NULL;
590 CERTCertList *certlist = NULL;
591 uint32_t maxcerts;
592 uint32_t *num_certs;
593 KMF_X509_DER_CERT *kmfcerts = NULL;
594 char *certlabel = NULL;
595 char *issuer = NULL;
596 char *subject = NULL;
597 KMF_BIGINT *serial = NULL;
598 KMF_CERT_VALIDITY validity;
600 if (handle == NULL || attrlist == NULL || numattr == 0) {
601 return (KMF_ERR_BAD_PARAMETER);
603 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
604 if (rv != KMF_OK)
605 return (rv);
607 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
608 if (num_certs == NULL)
609 return (KMF_ERR_BAD_PARAMETER);
611 maxcerts = *num_certs;
612 if (maxcerts == 0)
613 maxcerts = 0xFFFFFFFF;
614 *num_certs = 0;
616 /* Get the optional returned certificate list */
617 kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr);
619 /* Get optional search criteria attributes */
620 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
621 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
622 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
623 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
625 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
626 &validity, NULL);
627 if (rv != KMF_OK) {
628 validity = KMF_ALL_CERTS;
629 rv = KMF_OK;
632 if (certlabel != NULL) {
633 /* This will only find 1 certificate */
634 rv = nss_getcert_by_label(kmfh, certlabel, kmfcerts, num_certs,
635 validity);
636 } else {
638 * Build a list of matching certs.
640 rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
641 &certlist, validity);
644 * If the caller supplied a pointer to storage for
645 * a list of certs, convert up to 'maxcerts' of the
646 * matching certs.
648 if (rv == KMF_OK && certlist != NULL) {
649 rv = convertCertList(handle, certlist, kmfcerts,
650 &maxcerts);
651 CERT_DestroyCertList(certlist);
652 if (rv == KMF_OK)
653 *num_certs = maxcerts;
657 if (nss_slot != NULL) {
658 PK11_FreeSlot(nss_slot);
661 if (rv == KMF_OK && *num_certs == 0)
662 rv = KMF_ERR_CERT_NOT_FOUND;
664 return (rv);
667 void
668 /*ARGSUSED*/
669 NSS_FreeKMFCert(KMF_HANDLE_T handle,
670 KMF_X509_DER_CERT *kmf_cert)
672 if (kmf_cert != NULL) {
673 if (kmf_cert->certificate.Data != NULL) {
674 free(kmf_cert->certificate.Data);
675 kmf_cert->certificate.Data = NULL;
676 kmf_cert->certificate.Length = 0;
678 if (kmf_cert->kmf_private.label != NULL) {
679 free(kmf_cert->kmf_private.label);
680 kmf_cert->kmf_private.label = NULL;
685 KMF_RETURN
686 NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
688 KMF_RETURN rv = KMF_OK;
689 int nssrv;
690 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
691 CERTCertificate *cert = NULL;
692 PK11SlotInfo *nss_slot = NULL;
693 char *certlabel = NULL;
694 char *issuer = NULL;
695 char *subject = NULL;
696 KMF_BIGINT *serial = NULL;
697 KMF_CERT_VALIDITY validity;
699 if (handle == NULL || attrlist == NULL || numattr == 0) {
700 return (KMF_ERR_BAD_PARAMETER);
702 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
703 if (rv != KMF_OK)
704 return (rv);
706 /* Get the search criteria attributes. They are all optional. */
707 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
708 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
709 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
710 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
712 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
713 &validity, NULL);
714 if (rv != KMF_OK) {
715 validity = KMF_ALL_CERTS;
716 rv = KMF_OK;
719 /* Start finding the matched certificates and delete them. */
720 if (certlabel != NULL) {
721 cert = PK11_FindCertFromNickname(certlabel, NULL);
722 if (cert == NULL) {
723 return (KMF_ERR_CERT_NOT_FOUND);
726 switch (validity) {
727 case KMF_ALL_CERTS:
728 break;
729 case KMF_NONEXPIRED_CERTS:
730 nssrv = CERT_CertTimesValid(cert);
731 if (nssrv == SECFailure) {
732 /* this is an invalid cert - skip it */
733 goto out;
735 break;
736 case KMF_EXPIRED_CERTS:
737 nssrv = CERT_CertTimesValid(cert);
738 if (nssrv != SECFailure) {
739 /* this is a valid cert - skip it */
740 goto out;
742 break;
744 /* delete it from database */
745 nssrv = SEC_DeletePermCertificate(cert);
746 if (nssrv) {
747 SET_ERROR(kmfh, nssrv);
748 rv = KMF_ERR_INTERNAL;
750 } else {
751 CERTCertListNode *node;
752 CERTCertList *certlist = NULL;
754 rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
755 &certlist, validity);
757 for (node = CERT_LIST_HEAD(certlist);
758 !CERT_LIST_END(node, certlist) && rv == KMF_OK;
759 node = CERT_LIST_NEXT(node)) {
761 nssrv = SEC_DeletePermCertificate(node->cert);
762 if (nssrv) {
763 SET_ERROR(kmfh, nssrv);
764 rv = KMF_ERR_INTERNAL;
768 if (rv == KMF_OK && certlist != NULL) {
769 CERT_DestroyCertList(certlist);
770 } else if (rv == KMF_OK && certlist == NULL) {
771 rv = KMF_ERR_CERT_NOT_FOUND;
774 out:
775 if (nss_slot != NULL) {
776 PK11_FreeSlot(nss_slot);
779 if (cert != NULL) {
780 CERT_DestroyCertificate(cert);
783 return (rv);
786 static void
787 InitRandom(char *filename)
789 char buf[2048];
790 int fd;
791 PRInt32 count;
793 fd = open(filename, O_RDONLY);
794 if (!fd)
795 return;
797 count = read(fd, buf, sizeof (buf));
798 if (count > 0) {
799 (void) PK11_RandomUpdate(buf, count);
802 (void) close(fd);
805 KMF_RETURN
806 NSS_CreateKeypair(KMF_HANDLE_T handle,
807 int numattr, KMF_ATTRIBUTE *attrlist)
809 KMF_RETURN rv = KMF_OK;
810 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
811 PK11RSAGenParams rsaparams;
812 void *nssparams;
813 CK_MECHANISM_TYPE mechanism;
814 ulong_t publicExponent = 0x010001;
815 PK11SlotInfo *nss_slot = NULL;
816 SECKEYPrivateKey *NSSprivkey = NULL;
817 SECKEYPublicKey *NSSpubkey = NULL;
818 SECKEYECParams *ecparams = NULL;
819 PQGParams *pqgParams = NULL;
820 KMF_CREDENTIAL cred;
821 boolean_t storekey = TRUE;
822 uint32_t keylen = 1024, len;
823 uint32_t keylen_size = sizeof (uint32_t);
824 KMF_KEY_ALG keytype = KMF_RSA;
825 KMF_KEY_HANDLE *pubkey = NULL;
826 KMF_KEY_HANDLE *privkey = NULL;
827 char *keylabel = NULL;
829 if (handle == NULL || attrlist == NULL || numattr == 0) {
830 return (KMF_ERR_BAD_PARAMETER);
832 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
833 if (rv != KMF_OK) {
834 return (rv);
837 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
838 (void *)&cred, NULL);
839 if (rv != KMF_OK)
840 return (rv);
842 rv = nss_authenticate(handle, nss_slot, &cred);
843 if (rv != KMF_OK) {
844 return (rv);
847 /* "storekey" is optional. Default is TRUE */
848 (void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
849 &storekey, NULL);
851 /* keytype is optional. KMF_RSA is default */
852 (void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
853 (void *)&keytype, NULL);
855 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
856 &keylen, &keylen_size);
857 if (rv == KMF_ERR_ATTR_NOT_FOUND)
858 /* Default keylen = 1024 */
859 rv = KMF_OK;
860 else if (rv != KMF_OK)
861 return (KMF_ERR_BAD_PARAMETER);
863 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
864 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
865 if (pubkey == NULL || privkey == NULL)
866 return (KMF_ERR_BAD_PARAMETER);
868 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
869 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
871 rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr, NULL, &len);
872 if (rv == KMF_OK && len > 0) {
873 keylabel = malloc(len + 1);
874 if (keylabel == NULL)
875 return (KMF_ERR_MEMORY);
876 /* Now fill in the label value */
877 (void) memset(keylabel, 0, len + 1);
878 rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,
879 keylabel, NULL);
880 if (rv != KMF_OK) {
881 free(keylabel);
882 goto cleanup;
886 /* Get some random bits */
887 InitRandom("/dev/urandom");
888 if (keytype == KMF_RSA) {
889 KMF_BIGINT rsaexp;
891 rsaparams.keySizeInBits = keylen;
893 * NSS only allows for a 4 byte exponent.
894 * Ignore the exponent parameter if it is too big.
896 if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr,
897 &rsaexp, NULL)) == KMF_OK) {
898 if (rsaexp.len > 0 &&
899 rsaexp.len <= sizeof (publicExponent) &&
900 rsaexp.val != NULL) {
901 (void) memcpy(&publicExponent, rsaexp.val,
902 rsaexp.len);
905 rsaparams.pe = publicExponent;
906 mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
907 nssparams = &rsaparams;
908 } else if (keytype == KMF_DSA) {
909 PQGVerify *pqgVerify = NULL;
910 int ks;
911 SECStatus nssrv, passed;
913 mechanism = CKM_DSA_KEY_PAIR_GEN;
915 ks = PQG_PBITS_TO_INDEX(keylen);
916 nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
917 if (nssrv != SECSuccess) {
918 SET_ERROR(kmfh, rv);
919 PK11_PQG_DestroyVerify(pqgVerify);
920 rv = KMF_ERR_KEYGEN_FAILED;
921 goto cleanup;
924 nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
925 if (nssrv != SECSuccess || passed != SECSuccess) {
926 SET_ERROR(kmfh, rv);
927 rv = KMF_ERR_KEYGEN_FAILED;
930 PK11_PQG_DestroyVerify(pqgVerify);
932 if (rv != KMF_OK) {
933 SET_ERROR(kmfh, PORT_GetError());
934 goto cleanup;
937 nssparams = pqgParams;
938 } else if (keytype == KMF_ECDSA) {
939 KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
940 attrlist, numattr);
941 if (eccoid == NULL)
942 return (KMF_ERR_BAD_PARAMETER);
944 ecparams = SECITEM_AllocItem(NULL, NULL, (eccoid->Length));
945 if (!ecparams)
946 return (KMF_ERR_MEMORY);
948 (void) memcpy(ecparams->data, eccoid->Data, eccoid->Length);
950 mechanism = CKM_EC_KEY_PAIR_GEN;
951 nssparams = ecparams;
952 } else {
953 rv = KMF_ERR_BAD_PARAMETER;
954 goto cleanup;
957 NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
958 &NSSpubkey,
959 storekey, /* isPermanent */
960 PR_TRUE, /* isSensitive */
961 (void *)cred.cred);
963 if (NSSprivkey == NULL || NSSpubkey == NULL) {
964 SET_ERROR(kmfh, PORT_GetError());
965 rv = KMF_ERR_KEYGEN_FAILED;
966 } else {
967 if (keylabel != NULL && strlen(keylabel)) {
968 (void) PK11_SetPrivateKeyNickname(NSSprivkey,
969 keylabel);
970 (void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
972 /* Now, convert it to a KMF_KEY object for the framework */
973 privkey->kstype = KMF_KEYSTORE_NSS;
974 privkey->keyalg = keytype;
975 privkey->keyclass = KMF_ASYM_PRI;
976 privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
977 privkey->keyp = (void *)NSSprivkey;
979 pubkey->kstype = KMF_KEYSTORE_NSS;
980 pubkey->keyalg = keytype;
981 pubkey->keyp = (void *)NSSpubkey;
982 pubkey->keyclass = KMF_ASYM_PUB;
983 pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
985 rv = KMF_OK;
987 cleanup:
988 if (rv != KMF_OK) {
989 if (NSSpubkey)
990 (void) PK11_DeleteTokenPublicKey(NSSpubkey);
991 if (NSSprivkey)
992 (void) PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
994 privkey->keyp = NULL;
995 pubkey->keyp = NULL;
998 free(keylabel);
1000 if (pqgParams != NULL)
1001 PK11_PQG_DestroyParams(pqgParams);
1003 if (ecparams != NULL)
1004 SECITEM_FreeItem(ecparams, PR_TRUE);
1006 if (nss_slot != NULL)
1007 PK11_FreeSlot(nss_slot);
1009 return (rv);
1012 KMF_RETURN
1013 NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1014 KMF_OID *AlgOID, KMF_DATA *tobesigned,
1015 KMF_DATA *output)
1017 KMF_RETURN ret = KMF_OK;
1018 KMF_ALGORITHM_INDEX AlgId;
1019 SECOidTag signAlgTag;
1020 SECKEYPrivateKey *NSSprivkey = NULL;
1021 SECStatus rv;
1022 SECItem signed_data;
1023 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1025 signed_data.data = 0;
1026 if (key == NULL || AlgOID == NULL ||
1027 tobesigned == NULL || output == NULL ||
1028 tobesigned->Data == NULL ||
1029 output->Data == NULL)
1030 return (KMF_ERR_BAD_PARAMETER);
1032 /* Map the OID to a NSS algorithm */
1033 AlgId = x509_algoid_to_algid(AlgOID);
1034 if (AlgId == KMF_ALGID_NONE)
1035 return (KMF_ERR_BAD_PARAMETER);
1037 NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1039 if (AlgId == KMF_ALGID_MD5WithRSA)
1040 signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1041 else if (AlgId == KMF_ALGID_MD2WithRSA)
1042 signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1043 else if (AlgId == KMF_ALGID_SHA1WithRSA)
1044 signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1045 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1046 signAlgTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1047 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1048 signAlgTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1049 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1050 signAlgTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1051 else if (AlgId == KMF_ALGID_SHA1WithDSA)
1052 signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1053 else if (AlgId == KMF_ALGID_SHA1WithECDSA || AlgId == KMF_ALGID_ECDSA)
1054 signAlgTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
1055 else if (AlgId == KMF_ALGID_SHA256WithECDSA)
1056 signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
1057 else if (AlgId == KMF_ALGID_SHA384WithECDSA)
1058 signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
1059 else if (AlgId == KMF_ALGID_SHA512WithECDSA)
1060 signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
1061 else /* NSS does not support DSA with SHA2 hashes (FIPS 186-3) */
1062 return (KMF_ERR_BAD_PARAMETER);
1064 rv = SEC_SignData(&signed_data, tobesigned->Data,
1065 tobesigned->Length, NSSprivkey, signAlgTag);
1067 if (rv != 0) {
1068 SET_ERROR(kmfh, rv);
1069 return (KMF_ERR_INTERNAL);
1072 if (signed_data.len <= output->Length) {
1073 (void) memcpy(output->Data, signed_data.data, signed_data.len);
1074 output->Length = signed_data.len;
1075 } else {
1076 output->Length = 0;
1077 ret = KMF_ERR_BAD_PARAMETER;
1079 free(signed_data.data);
1081 return (ret);
1084 KMF_RETURN
1085 NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1086 KMF_DATA *encoded)
1088 KMF_RETURN ret = KMF_OK;
1089 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1090 SECItem *rvitem;
1091 CERTSubjectPublicKeyInfo *spki = NULL;
1093 if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1094 return (KMF_ERR_BAD_PARAMETER);
1096 spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1097 if (spki == NULL) {
1098 SET_ERROR(kmfh, PORT_GetError());
1099 return (KMF_ERR_MEMORY);
1102 rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1103 CERT_SubjectPublicKeyInfoTemplate);
1104 if (rvitem != NULL) {
1105 encoded->Data = malloc(rvitem->len);
1106 if (encoded->Data == NULL) {
1107 ret = KMF_ERR_MEMORY;
1108 } else {
1109 (void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1110 encoded->Length = rvitem->len;
1112 SECITEM_FreeItem(rvitem, TRUE);
1113 } else {
1114 SET_ERROR(kmfh, PORT_GetError());
1115 encoded->Data = NULL;
1116 encoded->Length = 0;
1117 ret = KMF_ERR_ENCODING;
1119 SECKEY_DestroySubjectPublicKeyInfo(spki);
1121 return (ret);
1124 KMF_RETURN
1125 NSS_DeleteKey(KMF_HANDLE_T handle,
1126 int numattr, KMF_ATTRIBUTE *attrlist)
1128 KMF_RETURN rv = KMF_OK;
1129 PK11SlotInfo *nss_slot = NULL;
1130 KMF_KEY_HANDLE *key;
1131 KMF_CREDENTIAL cred;
1132 boolean_t delete_token = B_TRUE;
1134 if (handle == NULL || attrlist == NULL || numattr == 0) {
1135 return (KMF_ERR_BAD_PARAMETER);
1138 * "delete_token" means to clear it from the token storage as well
1139 * as from memory.
1141 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1142 if (key == NULL || key->keyp == NULL)
1143 return (KMF_ERR_BAD_PARAMETER);
1145 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1146 (void *)&delete_token, NULL);
1147 if (rv != KMF_OK)
1148 /* "delete_token" is optional. Default is TRUE */
1149 rv = KMF_OK;
1151 if (delete_token) {
1152 SECStatus nssrv = SECSuccess;
1153 if (key->keyclass != KMF_ASYM_PUB &&
1154 key->keyclass != KMF_ASYM_PRI &&
1155 key->keyclass != KMF_SYMMETRIC)
1156 return (KMF_ERR_BAD_KEY_CLASS);
1158 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1159 if (rv != KMF_OK) {
1160 return (rv);
1163 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1164 (void *)&cred, NULL);
1165 if (rv != KMF_OK)
1166 return (KMF_ERR_BAD_PARAMETER);
1168 rv = nss_authenticate(handle, nss_slot, &cred);
1169 if (rv != KMF_OK) {
1170 return (rv);
1173 if (key->keyclass == KMF_ASYM_PUB) {
1174 nssrv = PK11_DeleteTokenPublicKey(
1175 (SECKEYPublicKey *)key->keyp);
1176 } else if (key->keyclass == KMF_ASYM_PRI) {
1177 nssrv = PK11_DeleteTokenPrivateKey(
1178 (SECKEYPrivateKey *)key->keyp, PR_TRUE);
1179 } else if (key->keyclass == KMF_SYMMETRIC) {
1180 nssrv = PK11_DeleteTokenSymKey(
1181 (PK11SymKey *) key->keyp);
1182 if (nssrv == SECSuccess)
1183 PK11_FreeSymKey((PK11SymKey *) key->keyp);
1185 if (nssrv != SECSuccess) {
1186 SET_ERROR(handle, PORT_GetError());
1187 rv = KMF_ERR_INTERNAL;
1189 } else {
1190 if (key->keyclass == KMF_ASYM_PUB) {
1191 SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1192 } else if (key->keyclass == KMF_ASYM_PRI) {
1193 SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1194 } else if (key->keyclass == KMF_SYMMETRIC) {
1195 PK11_FreeSymKey((PK11SymKey *) key->keyp);
1196 } else {
1197 return (KMF_ERR_BAD_KEY_CLASS);
1200 key->keyp = NULL;
1202 return (rv);
1205 KMF_RETURN
1206 NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1208 KMF_RETURN ret = KMF_OK;
1209 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1210 char *str;
1212 /* Get the error string in the default language */
1213 str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1215 if (str != NULL) {
1216 *msgstr = (char *)strdup(str);
1217 if ((*msgstr) == NULL)
1218 ret = KMF_ERR_MEMORY;
1219 } else {
1220 *msgstr = NULL;
1223 return (ret);
1226 KMF_RETURN
1227 NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1229 KMF_RETURN rv = KMF_OK;
1230 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1231 PK11SlotInfo *nss_slot = NULL;
1232 KMF_CREDENTIAL cred;
1233 KMF_KEY_HANDLE *key = NULL;
1234 KMF_DATA *cert = NULL;
1235 CERTCertificate *nss_cert = NULL;
1236 SECKEYPrivateKey* privkey = NULL;
1238 if (handle == NULL || attrlist == NULL || numattr == 0) {
1239 return (KMF_ERR_BAD_PARAMETER);
1242 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1243 if (rv != KMF_OK)
1244 return (rv);
1246 /* Get the credential */
1247 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1248 (void *)&cred, NULL);
1249 if (rv != KMF_OK)
1250 return (KMF_ERR_BAD_PARAMETER);
1251 rv = nss_authenticate(handle, nss_slot, &cred);
1252 if (rv != KMF_OK)
1253 return (rv);
1255 /* Get the key handle */
1256 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1257 if (key == NULL)
1258 return (KMF_ERR_BAD_PARAMETER);
1260 /* Get the cert data and decode it */
1261 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1262 if (cert == NULL || cert->Data == NULL)
1263 return (KMF_ERR_BAD_PARAMETER);
1265 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
1266 cert->Length);
1267 if (nss_cert == NULL) {
1268 SET_ERROR(kmfh, PORT_GetError());
1269 return (KMF_ERR_BAD_CERT_FORMAT);
1272 privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1273 if (privkey == NULL) {
1274 SET_ERROR(kmfh, PORT_GetError());
1275 return (KMF_ERR_KEY_NOT_FOUND);
1278 key->kstype = KMF_KEYSTORE_NSS;
1279 key->keyclass = KMF_ASYM_PRI;
1280 key->keyp = (void *)privkey;
1281 key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1283 CERT_DestroyCertificate(nss_cert);
1285 return (KMF_OK);
1289 KMF_RETURN
1290 NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1291 KMF_OID *AlgOID, KMF_DATA *ciphertext,
1292 KMF_DATA *output)
1294 KMF_RETURN ret = KMF_OK;
1295 SECKEYPrivateKey *NSSprivkey = NULL;
1296 SECStatus rv;
1297 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1298 unsigned int in_len = 0, out_len = 0;
1299 unsigned int total_decrypted = 0, modulus_len = 0;
1300 uint8_t *in_data, *out_data;
1301 int i, blocks;
1303 if (key == NULL || AlgOID == NULL ||
1304 ciphertext == NULL || output == NULL ||
1305 ciphertext->Data == NULL ||
1306 output->Data == NULL)
1307 return (KMF_ERR_BAD_PARAMETER);
1309 NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1310 modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1312 blocks = ciphertext->Length/modulus_len;
1313 out_data = output->Data;
1314 in_data = ciphertext->Data;
1315 out_len = modulus_len - 11;
1316 in_len = modulus_len;
1318 for (i = 0; i < blocks; i++) {
1319 rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1320 &out_len, ciphertext->Length, in_data, in_len);
1322 if (rv != 0) {
1323 SET_ERROR(kmfh, rv);
1324 return (KMF_ERR_INTERNAL);
1327 out_data += out_len;
1328 total_decrypted += out_len;
1329 in_data += in_len;
1332 output->Length = total_decrypted;
1334 return (ret);
1337 static KMF_KEY_ALG
1338 pk11keytype2kmf(CK_KEY_TYPE type)
1340 switch (type) {
1341 case CKK_RSA:
1342 return (KMF_RSA);
1343 case CKK_DSA:
1344 return (KMF_RSA);
1345 case CKK_AES:
1346 return (KMF_AES);
1347 case CKK_RC4:
1348 return (KMF_RC4);
1349 case CKK_DES:
1350 return (KMF_DES);
1351 case CKK_DES3:
1352 return (KMF_DES3);
1353 case CKK_EC:
1354 return (KMF_ECDSA);
1355 default:
1356 /* not supported */
1357 return (KMF_KEYALG_NONE);
1361 KMF_RETURN
1362 NSS_FindKey(KMF_HANDLE_T handle,
1363 int numattr, KMF_ATTRIBUTE *attrlist)
1365 KMF_RETURN rv;
1366 SECKEYPrivateKeyList *prilist;
1367 SECKEYPrivateKeyListNode *prinode;
1368 SECKEYPublicKeyList *publist;
1369 SECKEYPublicKeyListNode *pubnode;
1370 PK11SlotInfo *nss_slot = NULL;
1371 PK11SymKey *symlist = NULL;
1372 int count;
1373 uint32_t maxkeys;
1374 KMF_KEY_HANDLE *keys;
1375 uint32_t *numkeys;
1376 KMF_CREDENTIAL *cred = NULL;
1377 KMF_KEY_CLASS keyclass;
1378 char *findLabel;
1379 char *nick;
1380 int match = 0;
1381 KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
1383 if (handle == NULL || attrlist == NULL || numattr == 0) {
1384 return (KMF_ERR_BAD_PARAMETER);
1387 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1388 if (numkeys == NULL)
1389 return (KMF_ERR_BAD_PARAMETER);
1391 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1392 if (rv != KMF_OK) {
1393 return (rv);
1396 /* It is OK if this is NULL, we dont need a cred to find public keys */
1397 cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1399 if (cred != NULL) {
1400 rv = nss_authenticate(handle, nss_slot, cred);
1401 if (rv != KMF_OK) {
1402 return (rv);
1406 maxkeys = *numkeys;
1407 if (maxkeys == 0)
1408 maxkeys = 0xFFFFFFFF;
1409 *numkeys = 0;
1411 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
1412 (void *)&keyclass, NULL);
1413 if (rv != KMF_OK)
1414 return (KMF_ERR_BAD_PARAMETER);
1416 findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1418 if (keyclass == KMF_ASYM_PUB) {
1419 publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
1420 if (publist == NULL) {
1421 rv = KMF_ERR_KEY_NOT_FOUND;
1422 goto cleanup;
1424 } else if (keyclass == KMF_ASYM_PRI) {
1425 prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
1426 if (prilist == NULL) {
1427 rv = KMF_ERR_KEY_NOT_FOUND;
1428 goto cleanup;
1430 } else if (keyclass == KMF_SYMMETRIC) {
1431 symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
1432 if (symlist == NULL) {
1433 rv = KMF_ERR_KEY_NOT_FOUND;
1434 goto cleanup;
1436 } else {
1437 rv = KMF_ERR_BAD_KEY_CLASS;
1438 goto cleanup;
1441 keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1442 /* it is okay to have "keys" contains NULL */
1444 if (keyclass == KMF_ASYM_PUB) {
1445 for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1446 !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
1447 pubnode = PUBKEY_LIST_NEXT(pubnode)) {
1448 match = 0;
1450 * Due to bug in NSS, we have to manually match
1451 * the labels to be sure we have a match.
1453 nick = PK11_GetPublicKeyNickname(pubnode->key);
1454 if (findLabel) {
1455 match = (nick &&
1456 (strcmp(nick, findLabel) == 0));
1457 } else {
1458 /* always match if findLabel is NULL */
1459 match = 1;
1461 if (keys != NULL && match) {
1462 keys[count].kstype = KMF_KEYSTORE_NSS;
1463 keys[count].keyclass = KMF_ASYM_PUB;
1464 keys[count].keyp = (void *)pubnode->key;
1465 keys[count].keylabel = nick;
1467 if (pubnode->key->keyType == rsaKey)
1468 keys[count].keyalg = KMF_RSA;
1469 else if (pubnode->key->keyType == dsaKey)
1470 keys[count].keyalg = KMF_DSA;
1471 else if (pubnode->key->keyType == ecKey)
1472 keys[count].keyalg = KMF_ECDSA;
1474 if (match)
1475 count++;
1477 *numkeys = count;
1478 } else if (keyclass == KMF_ASYM_PRI) {
1479 for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1480 !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
1481 prinode = PRIVKEY_LIST_NEXT(prinode)) {
1482 match = 0;
1484 * Due to bug in NSS, we have to manually match
1485 * the labels to be sure we have a match.
1487 nick = PK11_GetPrivateKeyNickname(prinode->key);
1488 if (findLabel) {
1489 match = (nick &&
1490 (strcmp(nick, findLabel) == 0));
1491 } else {
1492 /* always match if findLabel is NULL */
1493 match = 1;
1495 if (keys != NULL && match) {
1496 keys[count].kstype = KMF_KEYSTORE_NSS;
1497 keys[count].keyclass = KMF_ASYM_PRI;
1498 keys[count].keyp = (void *)prinode->key;
1499 keys[count].keylabel = nick;
1501 if (prinode->key->keyType == rsaKey)
1502 keys[count].keyalg = KMF_RSA;
1503 else if (prinode->key->keyType == dsaKey)
1504 keys[count].keyalg = KMF_DSA;
1505 else if (prinode->key->keyType == ecKey)
1506 keys[count].keyalg = KMF_ECDSA;
1508 if (match)
1509 count++;
1511 *numkeys = count;
1512 } else if (keyclass == KMF_SYMMETRIC) {
1513 count = 0;
1514 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1515 (void *)&keytype, NULL);
1516 if (rv != KMF_OK)
1517 rv = KMF_OK;
1518 while (symlist && count < maxkeys) {
1519 PK11SymKey *symkey = symlist;
1520 CK_KEY_TYPE type;
1521 KMF_KEY_ALG keyalg;
1523 match = 0;
1524 type = PK11_GetSymKeyType(symkey);
1525 keyalg = pk11keytype2kmf(type);
1527 symlist = PK11_GetNextSymKey(symkey);
1530 * If keytype is specified in the searching parameter,
1531 * check the keytype and skip the key if its keytype
1532 * doesn't match.
1534 if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
1535 /* free that key since we arent using it */
1536 PK11_FreeSymKey(symkey);
1537 continue;
1540 * Due to bug in NSS, we have to manually match
1541 * the labels to be sure we have a match.
1543 nick = PK11_GetSymKeyNickname(symkey);
1544 if (findLabel) {
1545 match = (nick &&
1546 (strcmp(nick, findLabel) == 0));
1547 } else {
1548 /* always match if findLabel is NULL */
1549 match = 1;
1552 if (keys != NULL && match) {
1553 keys[count].kstype = KMF_KEYSTORE_NSS;
1554 keys[count].keyclass = KMF_SYMMETRIC;
1555 keys[count].keyp = (void *) symkey;
1556 keys[count].keylabel = nick;
1557 keys[count].keyalg = keyalg;
1558 } else {
1559 PK11_FreeSymKey(symkey);
1561 if (match)
1562 count++;
1565 * Cleanup memory for unused keys.
1567 while (symlist != NULL) {
1568 PK11SymKey *symkey = symlist;
1570 PK11_FreeSymKey(symkey);
1571 symlist = PK11_GetNextSymKey(symkey);
1573 *numkeys = count;
1576 cleanup:
1577 if (nss_slot != NULL) {
1578 PK11_FreeSlot(nss_slot);
1581 return (rv);
1584 static SECStatus
1585 p12u_SwapUnicodeBytes(SECItem *uniItem)
1587 unsigned int i;
1588 unsigned char a;
1589 if ((uniItem == NULL) || (uniItem->len % 2)) {
1590 return (SECFailure);
1592 for (i = 0; i < uniItem->len; i += 2) {
1593 a = uniItem->data[i];
1594 uniItem->data[i] = uniItem->data[i+1];
1595 uniItem->data[i+1] = a;
1597 return (SECSuccess);
1600 static PRBool
1601 p12u_ucs2_ascii_conversion_function(
1602 PRBool toUnicode,
1603 unsigned char *inBuf,
1604 unsigned int inBufLen,
1605 unsigned char *outBuf,
1606 unsigned int maxOutBufLen,
1607 unsigned int *outBufLen,
1608 PRBool swapBytes)
1610 SECItem it = { siBuffer, NULL, 0 };
1611 SECItem *dup = NULL;
1612 PRBool ret;
1614 it.data = inBuf;
1615 it.len = inBufLen;
1616 dup = SECITEM_DupItem(&it);
1618 * If converting Unicode to ASCII, swap bytes before conversion
1619 * as neccessary.
1621 if (!toUnicode && swapBytes) {
1622 if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
1623 SECITEM_ZfreeItem(dup, PR_TRUE);
1624 return (PR_FALSE);
1627 /* Perform the conversion. */
1628 ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
1629 outBuf, maxOutBufLen, outBufLen);
1630 if (dup)
1631 SECITEM_ZfreeItem(dup, PR_TRUE);
1633 return (ret);
1636 static PRBool
1637 p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
1639 if (!p12ctx || !p12ctx->filename) {
1640 return (PR_FALSE);
1643 if (fileRead) {
1644 p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
1645 } else {
1646 p12ctx->file = PR_Open(p12ctx->filename,
1647 PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
1650 if (!p12ctx->file) {
1651 p12ctx->error = PR_TRUE;
1652 return (PR_FALSE);
1655 return (PR_TRUE);
1658 static void
1659 p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
1661 if (!ppCtx || !(*ppCtx)) {
1662 return;
1665 if ((*ppCtx)->file != NULL) {
1666 (void) PR_Close((*ppCtx)->file);
1669 if ((*ppCtx)->filename != NULL) {
1670 if (removeFile) {
1671 (void) PR_Delete((*ppCtx)->filename);
1673 free((*ppCtx)->filename);
1676 free(*ppCtx);
1677 *ppCtx = NULL;
1680 static p12uContext *
1681 p12u_InitContext(PRBool fileImport, char *filename)
1683 p12uContext *p12ctx;
1685 p12ctx = PORT_ZNew(p12uContext);
1686 if (!p12ctx) {
1687 return (NULL);
1690 p12ctx->error = PR_FALSE;
1691 p12ctx->errorValue = 0;
1692 p12ctx->filename = strdup(filename);
1694 if (!p12u_OpenFile(p12ctx, fileImport)) {
1695 p12u_DestroyContext(&p12ctx, PR_FALSE);
1696 return (NULL);
1699 return (p12ctx);
1702 static void
1703 p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
1705 p12uContext *p12cxt = arg;
1706 int writeLen;
1708 if (!p12cxt || (p12cxt->error == PR_TRUE)) {
1709 return;
1712 if (p12cxt->file == NULL) {
1713 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1714 p12cxt->error = PR_TRUE;
1715 return;
1718 writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
1720 if (writeLen != (int)len) {
1721 (void) PR_Close(p12cxt->file);
1722 free(p12cxt->filename);
1723 p12cxt->filename = NULL;
1724 p12cxt->file = NULL;
1725 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1726 p12cxt->error = PR_TRUE;
1730 #define HANDLE_NSS_ERROR(r) {\
1731 SET_ERROR(kmfh, PORT_GetError()); \
1732 rv = r; \
1733 goto out; }
1735 static KMF_RETURN
1736 add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
1737 CERTCertificate *cert, SECItem *pwitem)
1739 KMF_RETURN rv = KMF_OK;
1740 SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
1742 keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
1743 if (PK11_IsFIPS()) {
1744 certSafe = keySafe;
1745 } else {
1746 certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
1747 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
1750 if (!certSafe || !keySafe) {
1751 rv = KMF_ERR_INTERNAL;
1752 goto out;
1755 if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
1756 CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
1757 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
1758 != SECSuccess) {
1759 rv = KMF_ERR_INTERNAL;
1761 out:
1762 return (rv);
1765 KMF_RETURN
1766 NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1768 KMF_RETURN rv;
1769 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1770 SEC_PKCS12ExportContext *p12ecx = NULL;
1771 p12uContext *p12ctx = NULL;
1772 CERTCertList *certlist = NULL;
1773 CERTCertificate *nsscert = NULL;
1774 CERTCertListNode* node = NULL;
1775 PK11SlotInfo *slot = NULL;
1776 SECItem pwitem = { siBuffer, NULL, 0 };
1777 KMF_CREDENTIAL *cred = NULL;
1778 KMF_CREDENTIAL *p12cred = NULL;
1779 char *certlabel = NULL;
1780 char *issuer = NULL;
1781 char *subject = NULL;
1782 KMF_BIGINT *serial = NULL;
1783 char *filename = NULL;
1785 if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1786 return (KMF_ERR_BAD_PARAMETER);
1789 rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
1790 if (rv != KMF_OK)
1791 return (rv);
1793 cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1794 if (cred == NULL)
1795 return (KMF_ERR_BAD_PARAMETER);
1797 rv = nss_authenticate(handle, slot, cred);
1798 if (rv != KMF_OK)
1799 return (rv);
1801 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
1802 if (p12cred == NULL)
1803 return (KMF_ERR_BAD_PARAMETER);
1805 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
1806 numattr);
1807 if (filename == NULL)
1808 return (KMF_ERR_BAD_PARAMETER);
1810 /* Get optional search criteria attributes */
1811 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1812 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1813 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1814 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1817 * Find the certificate(s) first.
1819 if (certlabel != NULL) {
1820 nsscert = PK11_FindCertFromNickname(certlabel, NULL);
1821 if (nsscert == NULL) {
1822 HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
1824 } else {
1825 rv = nss_find_matching_certs(slot, issuer, subject, serial,
1826 &certlist, 0);
1828 if (rv == KMF_OK && certlist == NULL) {
1829 return (KMF_ERR_CERT_NOT_FOUND);
1831 if (rv != KMF_OK)
1832 return (rv);
1836 * The KMF_CREDENTIAL holds the password to use for
1837 * encrypting the PKCS12 key information.
1839 pwitem.data = (uchar_t *)p12cred->cred;
1840 pwitem.len = p12cred->credlen;
1842 p12ctx = p12u_InitContext(PR_FALSE, filename);
1843 if (!p12ctx) {
1844 HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1847 PORT_SetUCS2_ASCIIConversionFunction(
1848 p12u_ucs2_ascii_conversion_function);
1850 p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
1851 if (!p12ecx) {
1852 HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1855 if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
1856 != SECSuccess) {
1857 HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
1861 * NSS actually supports storing a list of keys and certs
1862 * in the PKCS#12 PDU. Nice feature.
1864 if (certlist != NULL) {
1865 for (node = CERT_LIST_HEAD(certlist);
1866 !CERT_LIST_END(node, certlist) && rv == KMF_OK;
1867 node = CERT_LIST_NEXT(node)) {
1868 rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
1870 } else if (nsscert != NULL) {
1871 rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
1874 if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
1875 != SECSuccess) {
1876 HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
1878 out:
1879 if (nsscert)
1880 CERT_DestroyCertificate(nsscert);
1882 if (certlist)
1883 CERT_DestroyCertList(certlist);
1885 if (p12ctx)
1886 p12u_DestroyContext(&p12ctx, PR_FALSE);
1888 if (p12ecx)
1889 SEC_PKCS12DestroyExportContext(p12ecx);
1891 return (rv);
1894 #define SETATTR(t, n, atype, value, size) \
1895 t[n].type = atype; \
1896 t[n].pValue = (CK_BYTE *)value; \
1897 t[n].ulValueLen = (CK_ULONG)size;
1899 KMF_RETURN
1900 NSS_CreateSymKey(KMF_HANDLE_T handle,
1901 int numattr, KMF_ATTRIBUTE *attrlist)
1903 KMF_RETURN rv = KMF_OK;
1904 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1905 PK11SlotInfo *nss_slot = NULL;
1906 PK11SymKey *nsskey = NULL;
1907 CK_MECHANISM_TYPE keyType;
1908 SECStatus nssrv;
1909 int keySize;
1910 KMF_KEY_HANDLE *symkey;
1911 KMF_CREDENTIAL cred;
1912 uint32_t keylen;
1913 uint32_t keylen_size = sizeof (uint32_t);
1914 KMF_KEY_ALG keytype;
1915 char *keylabel = NULL;
1917 if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1918 return (KMF_ERR_BAD_PARAMETER);
1921 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1922 if (symkey == NULL)
1923 return (KMF_ERR_BAD_PARAMETER);
1925 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
1926 NULL);
1927 if (rv != KMF_OK)
1928 return (KMF_ERR_BAD_PARAMETER);
1930 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
1931 &keylen_size);
1932 if (rv == KMF_ERR_ATTR_NOT_FOUND &&
1933 (keytype == KMF_DES || keytype == KMF_DES3))
1934 /* keylength is not required for DES and 3DES */
1935 rv = KMF_OK;
1936 if (rv != KMF_OK)
1937 return (KMF_ERR_BAD_PARAMETER);
1939 keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1940 if (keylabel == NULL)
1941 return (KMF_ERR_BAD_PARAMETER);
1943 switch (keytype) {
1944 case KMF_AES:
1945 keyType = CKM_AES_KEY_GEN;
1946 keySize = keylen;
1947 if (keySize == 0 || (keySize % 8) != 0)
1948 return (KMF_ERR_BAD_KEY_SIZE);
1949 break;
1950 case KMF_RC4:
1951 keyType = CKM_RC4_KEY_GEN;
1952 keySize = keylen;
1953 if (keySize == 0 || (keySize % 8) != 0)
1954 return (KMF_ERR_BAD_KEY_SIZE);
1955 break;
1956 case KMF_DES:
1957 keyType = CKM_DES_KEY_GEN;
1958 keySize = 0; /* required by PK11_TokenKeyGen() */
1959 break;
1960 case KMF_DES3:
1961 keyType = CKM_DES3_KEY_GEN;
1962 keySize = 0; /* required by PK11_TokenKeyGen() */
1963 break;
1964 case KMF_GENERIC_SECRET:
1965 keyType = CKM_GENERIC_SECRET_KEY_GEN;
1966 keySize = keylen;
1967 if (keySize == 0 || (keySize % 8) != 0)
1968 return (KMF_ERR_BAD_KEY_SIZE);
1969 break;
1970 default:
1971 rv = KMF_ERR_BAD_KEY_TYPE;
1972 goto out;
1975 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1976 if (rv != KMF_OK) {
1977 return (rv);
1980 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1981 (void *)&cred, NULL);
1982 if (rv != KMF_OK)
1983 return (KMF_ERR_BAD_PARAMETER);
1985 rv = nss_authenticate(handle, nss_slot, &cred);
1986 if (rv != KMF_OK) {
1987 return (rv);
1990 /* convert key length to bytes */
1991 nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize / 8, NULL,
1992 PR_TRUE, (void *)cred.cred);
1993 if (nsskey == NULL) {
1994 SET_ERROR(kmfh, PORT_GetError());
1995 rv = KMF_ERR_KEYGEN_FAILED;
1996 goto out;
1999 nssrv = PK11_SetSymKeyNickname(nsskey, keylabel);
2000 if (nssrv != SECSuccess) {
2001 SET_ERROR(kmfh, PORT_GetError());
2002 rv = KMF_ERR_KEYGEN_FAILED;
2003 goto out;
2006 symkey->kstype = KMF_KEYSTORE_NSS;
2007 symkey->keyalg = keytype;
2008 symkey->keyclass = KMF_SYMMETRIC;
2009 symkey->israw = FALSE;
2010 symkey->keyp = (void *)nsskey;
2012 out:
2013 if (nss_slot != NULL)
2014 PK11_FreeSlot(nss_slot);
2016 if (rv != KMF_OK && nsskey != NULL) {
2017 (void) PK11_DeleteTokenSymKey(nsskey);
2018 PK11_FreeSymKey(nsskey);
2020 return (rv);
2023 KMF_RETURN
2024 NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2025 KMF_RAW_SYM_KEY *rkey)
2027 KMF_RETURN rv = KMF_OK;
2028 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2029 SECItem *value = NULL;
2030 PK11SymKey *nsskey;
2031 SECStatus nss_rv;
2033 if (kmfh == NULL)
2034 return (KMF_ERR_UNINITIALIZED);
2036 if (symkey == NULL || rkey == NULL)
2037 return (KMF_ERR_BAD_PARAMETER);
2038 else if (symkey->keyclass != KMF_SYMMETRIC)
2039 return (KMF_ERR_BAD_KEY_CLASS);
2041 if (symkey->israw) {
2042 KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2044 if (rawkey == NULL ||
2045 rawkey->rawdata.sym.keydata.val == NULL ||
2046 rawkey->rawdata.sym.keydata.len == 0)
2047 return (KMF_ERR_BAD_KEYHANDLE);
2049 rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2050 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2051 return (KMF_ERR_MEMORY);
2052 (void) memcpy(rkey->keydata.val,
2053 rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2054 } else {
2055 nsskey = (PK11SymKey *)(symkey->keyp);
2056 if (nsskey == NULL)
2057 return (KMF_ERR_BAD_KEYHANDLE);
2059 nss_rv = PK11_ExtractKeyValue(nsskey);
2060 if (nss_rv != SECSuccess) {
2061 SET_ERROR(kmfh, PORT_GetError());
2062 rv = KMF_ERR_GETKEYVALUE_FAILED;
2063 goto out;
2066 value = PK11_GetKeyData(nsskey);
2067 if (value == NULL) {
2068 SET_ERROR(kmfh, PORT_GetError());
2069 rv = KMF_ERR_GETKEYVALUE_FAILED;
2070 goto out;
2073 if (value->len == 0 || value->data == NULL) {
2074 rv = KMF_ERR_GETKEYVALUE_FAILED;
2075 goto out;
2078 rkey->keydata.val = malloc(value->len);
2079 if (rkey->keydata.val == NULL) {
2080 rv = KMF_ERR_MEMORY;
2081 goto out;
2083 (void) memcpy(rkey->keydata.val, value->data, value->len);
2084 rkey->keydata.len = value->len;
2085 (void) memset(value->data, 0, value->len);
2087 out:
2088 if (value != NULL)
2089 SECITEM_FreeItem(value, PR_TRUE);
2090 return (rv);
2093 KMF_RETURN
2094 NSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2096 KMF_RETURN ret = KMF_OK;
2097 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2098 int rv;
2099 PK11SlotInfo *nss_slot = NULL;
2100 KMF_CREDENTIAL oldcred, newcred;
2102 if (handle == NULL || attrlist == NULL || numattr == 0)
2103 return (KMF_ERR_BAD_PARAMETER);
2105 ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2106 (void *)&oldcred, NULL);
2107 if (ret != KMF_OK)
2108 return (KMF_ERR_BAD_PARAMETER);
2109 ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr,
2110 (void *)&newcred, NULL);
2111 if (ret != KMF_OK)
2112 return (KMF_ERR_BAD_PARAMETER);
2114 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2115 /* If it was uninitialized, set it */
2116 if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2117 rv = PK11_InitPin(nss_slot, NULL, newcred.cred);
2118 if (rv != SECSuccess) {
2119 SET_ERROR(kmfh, PORT_GetError());
2120 ret = KMF_ERR_AUTH_FAILED;
2121 } else {
2122 ret = KMF_OK;
2124 } else if (ret == KMF_OK) {
2125 ret = nss_authenticate(handle, nss_slot, &oldcred);
2126 if (ret != KMF_OK) {
2127 return (ret);
2129 rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred);
2130 if (rv != SECSuccess) {
2131 SET_ERROR(kmfh, PORT_GetError());
2132 ret = KMF_ERR_AUTH_FAILED;
2136 return (ret);
2139 KMF_RETURN
2140 NSS_StoreKey(KMF_HANDLE_T handle,
2141 int numattr, KMF_ATTRIBUTE *attrlist)
2143 KMF_RETURN rv = KMF_OK;
2144 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2145 PK11SlotInfo *nss_slot = NULL;
2146 KMF_CREDENTIAL cred = { NULL, 0 };
2147 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
2148 KMF_RAW_KEY_DATA *rawkey = NULL;
2149 char *keylabel = NULL;
2150 SECStatus ckrv = SECSuccess;
2151 SECItem nickname = { siBuffer, NULL, 0 };
2152 CERTCertificate *nss_cert = NULL;
2154 if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2155 return (KMF_ERR_BAD_PARAMETER);
2158 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2159 if (rv != KMF_OK) {
2160 return (rv);
2163 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2164 (void *)&cred, NULL);
2165 if (rv != KMF_OK)
2166 return (KMF_ERR_BAD_PARAMETER);
2168 rv = nss_authenticate(handle, nss_slot, &cred);
2169 if (rv != KMF_OK) {
2170 return (rv);
2173 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
2174 if (pubkey == NULL) {
2175 /* look for private key */
2176 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist,
2177 numattr);
2178 if (prikey == NULL)
2179 /* look for raw key */
2180 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR,
2181 attrlist, numattr);
2184 /* If no keys were found, return error */
2185 if (pubkey == NULL && prikey == NULL && rawkey == NULL)
2186 return (KMF_ERR_ATTR_NOT_FOUND);
2188 keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2189 if (keylabel != NULL) {
2190 nickname.data = (uchar_t *)keylabel;
2191 nickname.len = strlen(keylabel);
2194 if (rawkey != NULL) {
2195 uchar_t ver = 0;
2196 SECKEYPrivateKeyInfo rpk;
2197 KMF_DATA derkey = { 0, NULL };
2198 KMF_DATA *cert;
2200 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2201 if (cert == NULL)
2202 return (rv);
2204 * Decode the cert into an NSS CERT object so we can access the
2205 * SPKI and KeyUsage data later.
2207 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2208 cert->Length);
2210 if (nss_cert == NULL) {
2211 SET_ERROR(kmfh, PORT_GetError());
2212 rv = KMF_ERR_BAD_CERT_FORMAT;
2213 goto cleanup;
2216 (void) memset(&rpk, 0, sizeof (rpk));
2217 rpk.arena = NULL;
2218 rpk.version.type = siUnsignedInteger;
2219 rpk.version.data = &ver;
2220 rpk.version.len = 1;
2221 if (rawkey->keytype == KMF_RSA) {
2222 rv = DerEncodeRSAPrivateKey(&derkey,
2223 &rawkey->rawdata.rsa);
2224 if (rv != KMF_OK)
2225 goto cleanup;
2226 } else if (rawkey->keytype == KMF_DSA) {
2227 rv = DerEncodeDSAPrivateKey(&derkey,
2228 &rawkey->rawdata.dsa);
2229 if (rv != KMF_OK)
2230 goto cleanup;
2231 } else if (rawkey->keytype == KMF_ECDSA) {
2232 rv = DerEncodeECPrivateKey(&derkey,
2233 &rawkey->rawdata.ec);
2234 if (rv != KMF_OK)
2235 goto cleanup;
2237 rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2238 rpk.privateKey.data = derkey.Data;
2239 rpk.privateKey.len = derkey.Length;
2240 rpk.attributes = NULL;
2242 ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname,
2243 &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE,
2244 TRUE, nss_cert->keyUsage, NULL);
2245 if (ckrv != CKR_OK) {
2246 SET_ERROR(kmfh, PORT_GetError());
2247 rv = KMF_ERR_INTERNAL;
2249 kmf_free_data(&derkey);
2250 } else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) {
2251 CK_OBJECT_HANDLE pk;
2252 SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp;
2254 pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE);
2255 if (pk == CK_INVALID_HANDLE) {
2256 SET_ERROR(kmfh, PORT_GetError());
2257 rv = KMF_ERR_INTERNAL;
2259 } else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) {
2260 SECKEYPrivateKey *pk;
2261 SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp;
2263 pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE,
2264 PR_TRUE);
2265 if (pk == CK_INVALID_HANDLE) {
2266 SET_ERROR(kmfh, PORT_GetError());
2267 rv = KMF_ERR_INTERNAL;
2269 /* We stored it, but don't need the handle anymore */
2270 SECKEY_DestroyPrivateKey(pk);
2273 cleanup:
2274 if (nss_cert != NULL)
2275 CERT_DestroyCertificate(nss_cert);
2276 PK11_FreeSlot(nss_slot);
2277 return (rv);
2281 * This function is called by NSS_StoreCert() and NSS_ImportCert().
2282 * The "label" and "trust_flag" arguments can be NULL.
2284 static KMF_RETURN
2285 store_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert,
2286 char *label, char *trust_flag)
2288 KMF_RETURN ret = KMF_OK;
2289 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2290 SECStatus nss_rv;
2291 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2292 CERTCertificate *nss_cert = NULL;
2293 CERTCertTrust *nss_trust = NULL;
2295 if (nss_slot == NULL || cert == NULL)
2296 return (KMF_ERR_BAD_PARAMETER);
2298 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2299 cert->Length);
2300 if (nss_cert == NULL) {
2301 SET_ERROR(kmfh, PORT_GetError());
2302 ret = KMF_ERR_BAD_CERT_FORMAT;
2303 goto out;
2306 /* Store the cert into the NSS database */
2307 nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
2308 label, 0);
2309 if (nss_rv) {
2310 SET_ERROR(kmfh, nss_rv);
2311 ret = KMF_ERR_BAD_CERT_FORMAT;
2312 goto out;
2315 /* If trust_flag is NULL, then we are done */
2316 if (trust_flag == NULL)
2317 goto out;
2319 nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
2320 if (nss_trust == NULL) {
2321 ret = KMF_ERR_MEMORY;
2322 goto out;
2325 nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag);
2326 if (nss_rv) {
2327 SET_ERROR(kmfh, nss_rv);
2328 ret = KMF_ERR_BAD_PARAMETER;
2329 goto out;
2332 nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
2333 if (nss_rv) {
2334 SET_ERROR(kmfh, nss_rv);
2335 ret = KMF_ERR_BAD_PARAMETER;
2338 out:
2339 if (nss_cert != NULL) {
2340 CERT_DestroyCertificate(nss_cert);
2343 if (nss_trust != NULL) {
2344 free(nss_trust);
2347 return (ret);
2351 KMF_RETURN
2352 NSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2354 KMF_RETURN ret = KMF_OK;
2355 PK11SlotInfo *nss_slot = NULL;
2356 KMF_DATA *cert = NULL;
2357 char *label = NULL;
2358 char *trust_flag = NULL;
2360 if (handle == NULL || attrlist == NULL || numattr == 0) {
2361 return (KMF_ERR_BAD_PARAMETER);
2364 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2365 if (ret != KMF_OK)
2366 return (ret);
2368 /* Get the cert data */
2369 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2370 if (cert == NULL || cert->Data == NULL)
2371 return (KMF_ERR_BAD_PARAMETER);
2373 /* The label attribute is optional */
2374 label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2376 /* The trustflag attriburte is optional */
2377 trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2379 ret = store_cert(handle, nss_slot, cert, label, trust_flag);
2381 out:
2382 if (nss_slot != NULL) {
2383 PK11_FreeSlot(nss_slot);
2386 return (ret);
2390 KMF_RETURN
2391 NSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2393 KMF_RETURN ret = KMF_OK;
2394 PK11SlotInfo *nss_slot = NULL;
2395 KMF_DATA cert = { 0, NULL };
2396 KMF_DATA cert_der = { 0, NULL };
2397 KMF_DATA *cptr = NULL;
2398 KMF_ENCODE_FORMAT format;
2399 char *label = NULL;
2400 char *trust_flag = NULL;
2401 char *certfile = NULL;
2403 if (handle == NULL || attrlist == NULL || numattr == 0) {
2404 return (KMF_ERR_BAD_PARAMETER);
2407 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2408 if (ret != KMF_OK)
2409 return (ret);
2411 /* Get the input cert filename attribute */
2412 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
2413 if (certfile == NULL)
2414 return (KMF_ERR_BAD_PARAMETER);
2416 /* Check the cert file and auto-detect the file format of it. */
2417 ret = kmf_is_cert_file(handle, certfile, &format);
2418 if (ret != KMF_OK)
2419 return (ret);
2421 ret = kmf_read_input_file(handle, certfile, &cert);
2422 if (ret != KMF_OK) {
2423 return (ret);
2427 * If the imported cert is in PEM format, convert it to
2428 * DER format in order to store it in NSS token.
2430 if (format == KMF_FORMAT_PEM) {
2431 int derlen;
2432 ret = kmf_pem_to_der(cert.Data, cert.Length,
2433 &cert_der.Data, &derlen);
2434 if (ret != KMF_OK) {
2435 goto cleanup;
2437 cert_der.Length = (size_t)derlen;
2438 cptr = &cert_der;
2439 } else {
2440 cptr = &cert;
2443 label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2444 trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2445 ret = store_cert(handle, nss_slot, cptr, label, trust_flag);
2447 cleanup:
2448 if (format == KMF_FORMAT_PEM) {
2449 kmf_free_data(&cert_der);
2452 kmf_free_data(&cert);
2454 return (ret);
2458 KMF_RETURN
2459 NSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2461 KMF_RETURN ret = KMF_OK;
2462 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2463 PK11SlotInfo *nss_slot = NULL;
2464 CERTSignedCrl *nss_crl = NULL;
2465 KMF_ENCODE_FORMAT format;
2466 int importOptions;
2467 SECItem crlDER;
2468 KMF_DATA crl1;
2469 KMF_DATA crl2;
2470 char *crlfilename;
2471 boolean_t crlcheck = FALSE;
2473 if (attrlist == NULL || numattr == 0) {
2474 return (KMF_ERR_BAD_PARAMETER);
2477 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2478 if (ret != KMF_OK) {
2479 return (ret);
2482 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist,
2483 numattr);
2484 if (crlfilename == NULL)
2485 return (KMF_ERR_BAD_CRLFILE);
2488 * Check if the input CRL file is a valid CRL file and auto-detect
2489 * the encoded format of the file.
2491 ret = kmf_is_crl_file(handle, crlfilename, &format);
2492 if (ret != KMF_OK)
2493 return (ret);
2495 ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
2496 &crlcheck, NULL);
2497 if (ret != KMF_OK)
2498 ret = KMF_OK; /* CRL_CHECK is optional */
2500 /* set importOptions */
2501 if (crlcheck == B_FALSE) {
2502 importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
2503 CRL_IMPORT_BYPASS_CHECKS;
2504 } else {
2505 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
2509 /* Read in the CRL file */
2510 crl1.Data = NULL;
2511 crl2.Data = NULL;
2512 ret = kmf_read_input_file(handle, crlfilename, &crl1);
2513 if (ret != KMF_OK) {
2514 return (ret);
2517 /* If the input CRL is in PEM format, convert it to DER first. */
2518 if (format == KMF_FORMAT_PEM) {
2519 int len;
2520 ret = kmf_pem_to_der(crl1.Data, crl1.Length,
2521 &crl2.Data, &len);
2522 if (ret != KMF_OK) {
2523 goto out;
2525 crl2.Length = (size_t)len;
2528 crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
2529 crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
2531 nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
2532 NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
2534 if (nss_crl == NULL) {
2535 SET_ERROR(kmfh, PORT_GetError());
2536 ret = KMF_ERR_BAD_CRLFILE;
2537 goto out;
2540 out:
2541 if (nss_slot != NULL) {
2542 PK11_FreeSlot(nss_slot);
2545 if (crl1.Data != NULL) {
2546 free(crl1.Data);
2549 if (crl2.Data != NULL) {
2550 free(crl2.Data);
2553 if (nss_crl != NULL) {
2554 (void) SEC_DestroyCrl(nss_crl);
2557 return (ret);
2560 KMF_RETURN
2561 NSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2563 KMF_RETURN rv = KMF_OK;
2564 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2565 CERTSignedCrl *crl = NULL;
2566 CERTCertificate *cert = NULL;
2567 PK11SlotInfo *nss_slot = NULL;
2568 CERTCrlHeadNode *crlList = NULL;
2569 CERTCrlNode *crlNode = NULL;
2570 PRArenaPool *arena = NULL;
2571 CERTName *name = NULL;
2572 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2573 char *issuername, *subjectname;
2575 /* check params */
2576 if (numattr == 0 || attrlist == NULL) {
2577 return (KMF_ERR_BAD_PARAMETER);
2580 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2581 if (rv != KMF_OK) {
2582 return (rv);
2585 issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist,
2586 numattr);
2587 subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist,
2588 numattr);
2590 /* Caller must specify issuer or subject but not both */
2591 if ((issuername == NULL && subjectname == NULL) ||
2592 (issuername != NULL && subjectname != NULL))
2593 return (KMF_ERR_BAD_PARAMETER);
2595 /* Find the CRL based on the deletion criteria. */
2596 if (issuername != NULL) {
2598 * If the deletion is based on the issuer's certificate
2599 * nickname, we will get the issuer's cert first, then
2600 * get the CRL from the cert.
2602 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2603 issuername);
2604 if (!cert) {
2605 SET_ERROR(kmfh, PORT_GetError());
2606 rv = KMF_ERR_CERT_NOT_FOUND;
2607 goto out;
2610 crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
2611 SEC_CRL_TYPE);
2612 if (crl == NULL) {
2613 SET_ERROR(kmfh, PORT_GetError());
2614 rv = KMF_ERR_CRL_NOT_FOUND;
2615 goto out;
2617 } else {
2619 * If the deletion is based on the CRL's subject name, we will
2620 * get all the CRLs from the internal database and search
2621 * for the CRL with the same subject name.
2623 boolean_t found = B_FALSE;
2624 int nssrv;
2626 nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2627 if (nssrv) {
2628 SET_ERROR(kmfh, nssrv);
2629 rv = KMF_ERR_CRL_NOT_FOUND;
2630 goto out;
2633 if (crlList == NULL) {
2634 SET_ERROR(kmfh, PORT_GetError());
2635 rv = KMF_ERR_CRL_NOT_FOUND;
2636 goto out;
2639 /* Allocate space for name */
2640 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2641 if (arena == NULL) {
2642 rv = KMF_ERR_MEMORY;
2643 goto out;
2646 name = PORT_ArenaZAlloc(arena, sizeof (*name));
2647 if (name == NULL) {
2648 rv = KMF_ERR_MEMORY;
2649 goto out;
2651 name->arena = arena;
2653 crlNode = crlList->first;
2654 while (crlNode && !found) {
2655 char *asciiname = NULL;
2656 SECItem* issuer;
2658 name = &crlNode->crl->crl.name;
2659 if (!name) {
2660 SET_ERROR(kmfh, PORT_GetError());
2661 rv = KMF_ERR_CRL_NOT_FOUND;
2662 break;
2665 asciiname = CERT_NameToAscii(name);
2666 if (asciiname == NULL) {
2667 SET_ERROR(kmfh, PORT_GetError());
2668 rv = KMF_ERR_CRL_NOT_FOUND;
2669 break;
2672 if (strcmp(subjectname, asciiname) == 0) {
2673 found = B_TRUE;
2674 issuer = &crlNode->crl->crl.derName;
2675 crl = SEC_FindCrlByName(certHandle, issuer,
2676 SEC_CRL_TYPE);
2677 if (crl == NULL) {
2678 /* We found a cert but no CRL */
2679 SET_ERROR(kmfh, PORT_GetError());
2680 rv = KMF_ERR_CRL_NOT_FOUND;
2683 PORT_Free(asciiname);
2684 crlNode = crlNode->next;
2687 if (rv) {
2688 goto out;
2692 if (crl) {
2693 (void) SEC_DeletePermCRL(crl);
2696 out:
2697 if (nss_slot != NULL) {
2698 PK11_FreeSlot(nss_slot);
2701 if (crlList != NULL) {
2702 PORT_FreeArena(crlList->arena, PR_FALSE);
2705 if (arena != NULL) {
2706 PORT_FreeArena(arena, PR_FALSE);
2709 if (cert != NULL) {
2710 CERT_DestroyCertificate(cert);
2713 if (crl != NULL) {
2714 (void) SEC_DestroyCrl(crl);
2717 return (rv);
2720 KMF_RETURN
2721 NSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2723 KMF_RETURN rv = KMF_OK;
2724 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2725 PK11SlotInfo *nss_slot = NULL;
2726 CERTCrlHeadNode *crlList = NULL;
2727 CERTCrlNode *crlNode = NULL;
2728 PRArenaPool *arena = NULL;
2729 CERTName *name = NULL;
2730 SECStatus nssrv;
2731 char *asciiname = NULL;
2732 int crl_num;
2733 int i, *CRLCount;
2734 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2735 char **CRLNameList;
2737 if (numattr == 0 || attrlist == NULL) {
2738 return (KMF_ERR_BAD_PARAMETER);
2741 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2742 if (rv != KMF_OK) {
2743 return (rv);
2746 CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR, attrlist, numattr);
2747 if (CRLCount == NULL)
2748 return (KMF_ERR_BAD_PARAMETER);
2750 CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR,
2751 attrlist, numattr);
2753 /* Look up Crls */
2754 nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2755 if (nssrv) {
2756 SET_ERROR(kmfh, rv);
2757 rv = KMF_ERR_CRL_NOT_FOUND;
2758 goto out;
2761 /* Allocate space for name first */
2762 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2763 if (arena == NULL) {
2764 rv = KMF_ERR_MEMORY;
2765 goto out;
2768 name = PORT_ArenaZAlloc(arena, sizeof (*name));
2769 if (name == NULL) {
2770 rv = KMF_ERR_MEMORY;
2771 goto out;
2773 name->arena = arena;
2776 * Loop thru the crlList and create a crl list with CRL's subject name.
2778 crlNode = crlList->first;
2779 crl_num = 0;
2780 while (crlNode) {
2781 char *subj_name;
2783 /* Get the CRL subject name */
2784 name = &crlNode->crl->crl.name;
2785 if (!name) {
2786 SET_ERROR(kmfh, PORT_GetError());
2787 rv = KMF_ERR_CRL_NOT_FOUND;
2788 break;
2792 if (CRLNameList != NULL) {
2793 asciiname = CERT_NameToAscii(name);
2794 if (asciiname == NULL) {
2795 SET_ERROR(kmfh, PORT_GetError());
2796 rv = KMF_ERR_CRL_NOT_FOUND;
2797 break;
2799 subj_name = strdup(asciiname);
2800 PORT_Free(asciiname);
2801 if (subj_name == NULL) {
2802 rv = KMF_ERR_MEMORY;
2803 break;
2805 CRLNameList[crl_num] = subj_name;
2808 crl_num++;
2809 crlNode = crlNode->next;
2812 if (rv == KMF_OK) {
2813 /* success */
2814 *CRLCount = crl_num;
2817 out:
2818 if (nss_slot != NULL) {
2819 PK11_FreeSlot(nss_slot);
2822 if (crlList != NULL) {
2823 PORT_FreeArena(crlList->arena, PR_FALSE);
2826 if (arena != NULL) {
2827 PORT_FreeArena(arena, PR_FALSE);
2830 /* If failed, free memory allocated for the returning rlist */
2831 if (rv && (CRLNameList != NULL)) {
2832 for (i = 0; i < crl_num; i++) {
2833 free(CRLNameList[i]);
2837 return (rv);
2840 KMF_RETURN
2841 NSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2843 KMF_RETURN rv = KMF_OK;
2844 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2845 PK11SlotInfo *nss_slot = NULL;
2846 CERTCertificate *cert = NULL;
2847 CERTSignedCrl *crl = NULL;
2848 CERTCrlEntry *entry;
2849 boolean_t match = B_FALSE;
2850 int i;
2851 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2852 char *certlabel;
2853 KMF_DATA *certdata;
2855 /* check params */
2856 if (numattr == 0 || attrlist == NULL) {
2857 return (KMF_ERR_BAD_PARAMETER);
2860 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2861 if (rv != KMF_OK) {
2862 return (rv);
2865 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2867 /* Find the certificate first */
2868 if (certlabel != NULL) {
2869 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2870 certlabel);
2871 } else {
2872 SECItem derCert = { siBuffer, NULL, 0 };
2874 certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR,
2875 attrlist, numattr);
2877 if (certdata == NULL)
2878 return (KMF_ERR_BAD_PARAMETER);
2880 derCert.data = certdata->Data;
2881 derCert.len = certdata->Length;
2883 cert = CERT_FindCertByDERCert(certHandle, &derCert);
2886 if (cert == NULL) {
2887 SET_ERROR(kmfh, PORT_GetError());
2888 rv = KMF_ERR_CERT_NOT_FOUND;
2889 goto out;
2892 /* Find the CRL with the same issuer as the given certificate. */
2893 crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
2894 if (crl == NULL) {
2896 * Could not find the CRL issued by the same issuer. This
2897 * usually means that the CRL is not installed in the DB.
2899 SET_ERROR(kmfh, PORT_GetError());
2900 rv = KMF_ERR_CRL_NOT_FOUND;
2901 goto out;
2905 /* Check if the certificate's serialNumber is revoked in the CRL */
2906 i = 0;
2907 while ((entry = (crl->crl).entries[i++]) != NULL) {
2908 if (SECITEM_CompareItem(&(cert->serialNumber),
2909 &(entry->serialNumber)) == SECEqual) {
2910 match = B_TRUE;
2911 break;
2915 if (!match) {
2916 rv = KMF_ERR_NOT_REVOKED;
2919 out:
2920 if (nss_slot != NULL) {
2921 PK11_FreeSlot(nss_slot);
2924 if (cert != NULL) {
2925 CERT_DestroyCertificate(cert);
2928 if (crl != NULL) {
2929 (void) SEC_DestroyCrl(crl);
2932 return (rv);