1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * NSS keystore wrapper
24 *
25 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 *
28 * Copyright 2021 RackTop Systems, Inc.
29 */
30
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <synch.h>
36
37 #include <mps/nss.h>
38 #include <mps/cert.h>
39 #include <mps/certdb.h>
40 #include <mps/secoid.h>
41 #include <mps/secder.h>
42 #include <mps/secerr.h>
43 #include <mps/cryptohi.h>
44 #include <mps/keyhi.h>
45 #include <mps/keythi.h>
46 #include <mps/pk11func.h>
47 #include <mps/pk11pqg.h>
48 #include <mps/pkcs12.h>
49 #include <mps/p12plcy.h>
50 #include <mps/prerror.h>
51
52 #include <kmfapiP.h>
53 #include <ber_der.h>
54
55 #define NSS_OK 0
56
57 mutex_t init_lock = DEFAULTMUTEX;
58 static int nss_initialized = 0;
59
60 KMF_RETURN
61 NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
62
63 KMF_RETURN
64 NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
65
66 void
67 NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *);
68
69 KMF_RETURN
70 NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
71
72 KMF_RETURN
73 NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
74
75 KMF_RETURN
76 NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
77
78 KMF_RETURN
79 NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
80
81 KMF_RETURN
82 NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
83
84 KMF_RETURN
85 NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *);
86
87 KMF_RETURN
88 NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
89 KMF_DATA *, KMF_DATA *);
90
91 KMF_RETURN
92 NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
93
94 KMF_RETURN
95 NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
96
97 KMF_RETURN
98 NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
99
100 KMF_RETURN
101 NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
102
103 KMF_RETURN
104 NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
105
106 KMF_RETURN
107 NSS_GetErrorString(KMF_HANDLE_T, char **);
108
109 KMF_RETURN
110 NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
111
112 KMF_RETURN
113 NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
114
115 KMF_RETURN
116 NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *,
117 KMF_DATA *, KMF_DATA *);
118
119 KMF_RETURN
120 NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
121
122 KMF_RETURN
123 NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
124
125 KMF_RETURN
126 NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *);
127
128 KMF_RETURN
129 NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
130
131 static
132 KMF_PLUGIN_FUNCLIST nss_plugin_table =
133 {
134 1, /* Version */
135 NSS_ConfigureKeystore,
136 NSS_FindCert,
137 NSS_FreeKMFCert,
138 NSS_StoreCert,
139 NSS_ImportCert,
140 NSS_ImportCRL,
141 NSS_DeleteCert,
142 NSS_DeleteCRL,
143 NSS_CreateKeypair,
144 NSS_FindKey,
145 NSS_EncodePubKeyData,
146 NSS_SignData,
147 NSS_DeleteKey,
148 NULL /* ListCRL */,
149 NSS_FindCRL,
150 NSS_FindCertInCRL,
151 NSS_GetErrorString,
152 NSS_FindPrikeyByCert,
153 NSS_DecryptData,
154 NSS_ExportPK12,
155 NSS_CreateSymKey,
156 NSS_GetSymKeyValue,
157 NSS_SetTokenPin,
158 NSS_StoreKey,
159 NULL /* Finalize */
160 };
161
162 /* additions for importing and exporting PKCS 12 files */
163 typedef struct p12uContextStr {
164 char *filename; /* name of file */
165 PRFileDesc *file; /* pointer to file */
166 PRBool error; /* error occurred? */
167 int errorValue; /* which error occurred? */
168 } p12uContext;
169
170 #define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \
171 h->lasterr.errcode = c;
172
173 KMF_PLUGIN_FUNCLIST *
KMF_Plugin_Initialize()174 KMF_Plugin_Initialize()
175 {
176 (void) SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
177 (void) SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
178 (void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
179 (void) SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
180 (void) SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
181 (void) SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
182 (void) SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
183
184 return (&nss_plugin_table);
185 }
186
187 static char *
188 /*ARGSUSED*/
nss_getpassword(PK11SlotInfo * slot,PRBool retry,void * arg)189 nss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg)
190 {
191 if (retry)
192 return (NULL);
193 if (arg != NULL)
194 return ((char *)strdup(arg));
195 else
196 return (NULL);
197 }
198
199 static KMF_RETURN
nss_authenticate(KMF_HANDLE_T handle,PK11SlotInfo * nss_slot,KMF_CREDENTIAL * cred)200 nss_authenticate(KMF_HANDLE_T handle,
201 PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred)
202 {
203
204 SECStatus nssrv = SECSuccess;
205 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
206
207 /* If a password was given, try to login to the slot */
208 if (cred == NULL || cred->cred == NULL || cred->credlen == 0 ||
209 nss_slot == NULL) {
210 return (KMF_ERR_BAD_PARAMETER);
211 }
212
213 if (PK11_IsLoggedIn(nss_slot, NULL)) {
214 return (KMF_OK);
215 }
216
217 PK11_SetPasswordFunc(nss_getpassword);
218 nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred);
219
220 if (nssrv != SECSuccess) {
221 SET_ERROR(kmfh, nssrv);
222 PK11_FreeSlot(nss_slot);
223 return (KMF_ERR_AUTH_FAILED);
224 }
225
226 return (KMF_OK);
227 }
228
229 static SECStatus
Init_NSS_DBs(const char * configdir,const char * certPrefix,const char * keyPrefix,const char * secmodName)230 Init_NSS_DBs(const char *configdir,
231 const char *certPrefix,
232 const char *keyPrefix,
233 const char *secmodName)
234 {
235 SECStatus rv = NSS_OK;
236
237 (void) mutex_lock(&init_lock);
238
239 /* If another thread already did it, return OK. */
240 if (nss_initialized) {
241 (void) mutex_unlock(&init_lock);
242 return (SECSuccess);
243 }
244
245 rv = NSS_Initialize((configdir && strlen(configdir)) ?
246 configdir : "./", certPrefix, keyPrefix,
247 secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE);
248 if (rv != SECSuccess) {
249 goto end;
250 }
251
252 nss_initialized++;
253 end:
254 (void) mutex_unlock(&init_lock);
255 return (rv);
256 }
257
258 /*
259 * When it is called the first time, it will intialize NSS. Once the NSS
260 * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED
261 * if it is called again.
262 */
263 KMF_RETURN
NSS_ConfigureKeystore(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)264 NSS_ConfigureKeystore(KMF_HANDLE_T handle,
265 int numattr, KMF_ATTRIBUTE *attrlist)
266 {
267 KMF_RETURN rv = KMF_OK;
268 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
269 char *configdir;
270 char *certPrefix;
271 char *keyPrefix;
272 char *secModName;
273
274 configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
275 certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr);
276 keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr);
277 secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr);
278
279 (void) mutex_lock(&init_lock);
280 if (nss_initialized == 0) {
281 SECStatus err;
282
283 (void) mutex_unlock(&init_lock);
284 err = Init_NSS_DBs(configdir, certPrefix,
285 keyPrefix, secModName);
286 if (err != SECSuccess) {
287 SET_ERROR(kmfh, err);
288 return (KMF_ERR_INTERNAL);
289 }
290 } else {
291 rv = KMF_KEYSTORE_ALREADY_INITIALIZED;
292 (void) mutex_unlock(&init_lock);
293 }
294
295 return (rv);
296 }
297
298 /*
299 * This function sets up the slot to be used for other operations.
300 * This function is basically called by every NSS SPI function.
301 * For those functions that can only be performed in the internal slot, the
302 * boolean "internal_slot_only" argument needs to be TRUE.
303 * A slot pointer will be returned when this function is executed successfully.
304 */
305 KMF_RETURN
do_nss_init(void * handle,int numattr,KMF_ATTRIBUTE * attrlist,boolean_t internal_slot_only,PK11SlotInfo ** nss_slot)306 do_nss_init(void *handle, int numattr,
307 KMF_ATTRIBUTE *attrlist,
308 boolean_t internal_slot_only,
309 PK11SlotInfo **nss_slot)
310 {
311 KMF_RETURN rv = KMF_OK;
312 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
313 char *slotlabel = NULL;
314
315 if (!nss_initialized)
316 return (KMF_ERR_PLUGIN_INIT);
317
318 slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr);
319 /*
320 * NSS Is already initialized, but we need to find
321 * the right slot.
322 */
323 if (slotlabel == NULL ||
324 strcmp(slotlabel, "internal") == 0) {
325 *nss_slot = PK11_GetInternalKeySlot();
326 } else if (internal_slot_only == TRUE) {
327 rv = KMF_ERR_SLOTNAME;
328 goto end;
329 } else {
330 *nss_slot = PK11_FindSlotByName(slotlabel);
331 }
332
333 if (*nss_slot == NULL) {
334 SET_ERROR(kmfh, PORT_GetError());
335 rv = KMF_ERR_SLOTNAME;
336 goto end;
337 }
338
339 /*
340 * If the token was not yet initialized, return an error.
341 */
342 if (PK11_NeedUserInit(*nss_slot)) {
343 rv = KMF_ERR_UNINITIALIZED_TOKEN;
344 }
345
346 end:
347 return (rv);
348 }
349
350 static KMF_RETURN
nss2kmf_cert(CERTCertificate * nss_cert,KMF_X509_DER_CERT * kmf_cert)351 nss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert)
352 {
353 kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS;
354 kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
355
356 kmf_cert->certificate.Length = nss_cert->derCert.len;
357
358 if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) ==
359 NULL) {
360 kmf_cert->certificate.Length = 0;
361 return (KMF_ERR_MEMORY);
362 }
363 (void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data,
364 nss_cert->derCert.len);
365 if (nss_cert->nickname != NULL)
366 kmf_cert->kmf_private.label =
367 (char *)strdup(nss_cert->nickname);
368 return (KMF_OK);
369 }
370
371 static KMF_RETURN
nss_getcert_by_label(KMF_HANDLE * kmfh,char * name,KMF_X509_DER_CERT * kmf_cert,uint32_t * num_certs,KMF_CERT_VALIDITY find_criteria)372 nss_getcert_by_label(KMF_HANDLE *kmfh,
373 char *name, KMF_X509_DER_CERT *kmf_cert,
374 uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria)
375 {
376 KMF_RETURN rv = KMF_OK;
377 CERTCertificate *nss_cert;
378 SECCertTimeValidity validity;
379
380 nss_cert = PK11_FindCertFromNickname(name, NULL);
381 if (nss_cert == NULL) {
382 *num_certs = 0;
383 SET_ERROR(kmfh, PORT_GetError());
384 *num_certs = 0;
385 return (KMF_ERR_CERT_NOT_FOUND);
386 } else {
387 *num_certs = 1;
388 }
389
390 switch (find_criteria) {
391 case KMF_ALL_CERTS:
392 break;
393 case KMF_NONEXPIRED_CERTS:
394 validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
395 PR_FALSE);
396 if (validity != secCertTimeValid) {
397 /* this is an invalid cert, reject it */
398 *num_certs = 0;
399 CERT_DestroyCertificate(nss_cert);
400 return (KMF_OK);
401 }
402 break;
403 case KMF_EXPIRED_CERTS:
404 validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(),
405 PR_FALSE);
406 if (validity == secCertTimeValid) {
407 /* this is a valid cert, reject it in this case. */
408 *num_certs = 0;
409 CERT_DestroyCertificate(nss_cert);
410 return (KMF_OK);
411 }
412 break;
413 default:
414 return (KMF_ERR_BAD_PARAMETER);
415 }
416
417 if (kmf_cert != NULL)
418 rv = nss2kmf_cert(nss_cert, kmf_cert);
419
420 /* We copied the data we need, so cleanup the internal record */
421 CERT_DestroyCertificate(nss_cert);
422
423 if (rv != KMF_OK)
424 *num_certs = 0;
425
426 return (rv);
427 }
428
429 static KMF_RETURN
nss_find_matching_certs(PK11SlotInfo * slot,char * issuer,char * subject,KMF_BIGINT * serial,CERTCertList ** certlist,KMF_CERT_VALIDITY find_criteria)430 nss_find_matching_certs(PK11SlotInfo *slot,
431 char *issuer, char *subject, KMF_BIGINT *serial,
432 CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria)
433 {
434 KMF_RETURN rv = KMF_OK;
435 SECStatus ret;
436 CERTCertList *list;
437 CERTCertListNode *node;
438 KMF_X509_NAME issuerDN, subjectDN;
439 boolean_t findIssuer = FALSE;
440 boolean_t findSubject = FALSE;
441 boolean_t findSerial = FALSE;
442
443 if (issuer != NULL && strlen(issuer)) {
444 rv = kmf_dn_parser(issuer, &issuerDN);
445 if (rv != KMF_OK)
446 return (rv);
447 findIssuer = TRUE;
448 }
449 if (subject != NULL && strlen(subject)) {
450 rv = kmf_dn_parser(subject, &subjectDN);
451 if (rv != KMF_OK)
452 return (rv);
453 findSubject = TRUE;
454 }
455 if (serial != 0 && serial->val != NULL && serial->len > 0)
456 findSerial = TRUE;
457
458 list = PK11_ListCertsInSlot(slot);
459 if (list) {
460 node = CERT_LIST_HEAD(list);
461 while (!CERT_LIST_END(node, list)) {
462 KMF_X509_NAME cmpDN;
463 KMF_DATA der;
464 boolean_t match;
465 CERTCertListNode *freenode;
466
467 if (findIssuer) {
468 der.Data = node->cert->derIssuer.data;
469 der.Length = node->cert->derIssuer.len;
470 rv = DerDecodeName(&der, &cmpDN);
471 if (rv == KMF_OK) {
472 match = !KMF_CompareRDNs(&issuerDN,
473 &cmpDN);
474 kmf_free_dn(&cmpDN);
475 if (!match)
476 goto delete_and_cont;
477 } else {
478 goto delete_and_cont;
479 }
480 }
481 if (findSubject) {
482 der.Data = node->cert->derSubject.data;
483 der.Length = node->cert->derSubject.len;
484 rv = DerDecodeName(&der, &cmpDN);
485 if (rv == KMF_OK) {
486 match = !KMF_CompareRDNs(&subjectDN,
487 &cmpDN);
488 kmf_free_dn(&cmpDN);
489 if (!match)
490 goto delete_and_cont;
491 } else {
492 goto delete_and_cont;
493 }
494 }
495 if (findSerial) {
496 SECItem *sernum;
497
498 sernum = &node->cert->serialNumber;
499
500 if (serial->len != sernum->len)
501 goto delete_and_cont;
502
503 if (memcmp(sernum->data, serial->val,
504 serial->len))
505 goto delete_and_cont;
506 }
507
508 /* select the certs using find criteria */
509 switch (find_criteria) {
510 case KMF_ALL_CERTS:
511 break;
512 case KMF_NONEXPIRED_CERTS:
513 ret = CERT_CertTimesValid(node->cert);
514 if (ret == SECFailure) {
515 /* this is an invalid cert */
516 goto skip;
517 }
518 break;
519
520 case KMF_EXPIRED_CERTS:
521 ret = CERT_CertTimesValid(node->cert);
522 if (ret != SECFailure) {
523 /* this is a valid cert */
524 goto skip;
525 }
526 break;
527 }
528 skip:
529 node = CERT_LIST_NEXT(node);
530 continue;
531 delete_and_cont:
532 freenode = node;
533 node = CERT_LIST_NEXT(node);
534 CERT_RemoveCertListNode(freenode);
535 }
536 }
537
538 if (rv == KMF_OK && certlist != NULL) {
539 *certlist = list;
540 } else {
541 CERT_DestroyCertList(list);
542 }
543 return (rv);
544 }
545
546 static KMF_RETURN
convertCertList(void * kmfhandle,CERTCertList * nsscerts,KMF_X509_DER_CERT * kmfcerts,uint32_t * numcerts)547 convertCertList(void *kmfhandle,
548 CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts,
549 uint32_t *numcerts)
550 {
551 KMF_RETURN rv = KMF_OK;
552 CERTCertListNode *node;
553 uint32_t maxcerts = *numcerts;
554
555 maxcerts = *numcerts;
556 if (maxcerts == 0)
557 maxcerts = 0xFFFFFFFF;
558
559 *numcerts = 0;
560
561 /*
562 * Don't copy more certs than the caller wanted.
563 */
564 for (node = CERT_LIST_HEAD(nsscerts);
565 !CERT_LIST_END(node, nsscerts) && rv == KMF_OK &&
566 (*numcerts) < maxcerts;
567 node = CERT_LIST_NEXT(node), (*numcerts)++) {
568 if (kmfcerts != NULL)
569 rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]);
570 }
571
572 /*
573 * If we failed, delete any certs allocated so far.
574 */
575 if (rv != KMF_OK) {
576 int i;
577 for (i = 0; i < *numcerts; i++)
578 kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]);
579
580 *numcerts = 0;
581 }
582 return (rv);
583 }
584
585 KMF_RETURN
NSS_FindCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)586 NSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
587 {
588 KMF_RETURN rv = KMF_OK;
589 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
590 PK11SlotInfo *nss_slot = NULL;
591 CERTCertList *certlist = NULL;
592 uint32_t maxcerts;
593 uint32_t *num_certs;
594 KMF_X509_DER_CERT *kmfcerts = NULL;
595 char *certlabel = NULL;
596 char *issuer = NULL;
597 char *subject = NULL;
598 KMF_BIGINT *serial = NULL;
599 KMF_CERT_VALIDITY validity;
600
601 if (handle == NULL || attrlist == NULL || numattr == 0) {
602 return (KMF_ERR_BAD_PARAMETER);
603 }
604 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
605 if (rv != KMF_OK)
606 return (rv);
607
608 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
609 if (num_certs == NULL)
610 return (KMF_ERR_BAD_PARAMETER);
611
612 maxcerts = *num_certs;
613 if (maxcerts == 0)
614 maxcerts = 0xFFFFFFFF;
615 *num_certs = 0;
616
617 /* Get the optional returned certificate list */
618 kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr);
619
620 /* Get optional search criteria attributes */
621 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
622 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
623 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
624 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
625
626 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
627 &validity, NULL);
628 if (rv != KMF_OK) {
629 validity = KMF_ALL_CERTS;
630 rv = KMF_OK;
631 }
632
633 if (certlabel != NULL) {
634 /* This will only find 1 certificate */
635 rv = nss_getcert_by_label(kmfh, certlabel, kmfcerts, num_certs,
636 validity);
637 } else {
638 /*
639 * Build a list of matching certs.
640 */
641 rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
642 &certlist, validity);
643
644 /*
645 * If the caller supplied a pointer to storage for
646 * a list of certs, convert up to 'maxcerts' of the
647 * matching certs.
648 */
649 if (rv == KMF_OK && certlist != NULL) {
650 rv = convertCertList(handle, certlist, kmfcerts,
651 &maxcerts);
652 CERT_DestroyCertList(certlist);
653 if (rv == KMF_OK)
654 *num_certs = maxcerts;
655 }
656 }
657
658 if (nss_slot != NULL) {
659 PK11_FreeSlot(nss_slot);
660 }
661
662 if (rv == KMF_OK && *num_certs == 0)
663 rv = KMF_ERR_CERT_NOT_FOUND;
664
665 return (rv);
666 }
667
668 void
669 /*ARGSUSED*/
NSS_FreeKMFCert(KMF_HANDLE_T handle,KMF_X509_DER_CERT * kmf_cert)670 NSS_FreeKMFCert(KMF_HANDLE_T handle,
671 KMF_X509_DER_CERT *kmf_cert)
672 {
673 if (kmf_cert != NULL) {
674 if (kmf_cert->certificate.Data != NULL) {
675 free(kmf_cert->certificate.Data);
676 kmf_cert->certificate.Data = NULL;
677 kmf_cert->certificate.Length = 0;
678 }
679 if (kmf_cert->kmf_private.label != NULL) {
680 free(kmf_cert->kmf_private.label);
681 kmf_cert->kmf_private.label = NULL;
682 }
683 }
684 }
685
686 KMF_RETURN
NSS_DeleteCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)687 NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
688 {
689 KMF_RETURN rv = KMF_OK;
690 int nssrv;
691 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
692 CERTCertificate *cert = NULL;
693 PK11SlotInfo *nss_slot = NULL;
694 char *certlabel = NULL;
695 char *issuer = NULL;
696 char *subject = NULL;
697 KMF_BIGINT *serial = NULL;
698 KMF_CERT_VALIDITY validity;
699
700 if (handle == NULL || attrlist == NULL || numattr == 0) {
701 return (KMF_ERR_BAD_PARAMETER);
702 }
703 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
704 if (rv != KMF_OK)
705 return (rv);
706
707 /* Get the search criteria attributes. They are all optional. */
708 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
709 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
710 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
711 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
712
713 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr,
714 &validity, NULL);
715 if (rv != KMF_OK) {
716 validity = KMF_ALL_CERTS;
717 rv = KMF_OK;
718 }
719
720 /* Start finding the matched certificates and delete them. */
721 if (certlabel != NULL) {
722 cert = PK11_FindCertFromNickname(certlabel, NULL);
723 if (cert == NULL) {
724 return (KMF_ERR_CERT_NOT_FOUND);
725 }
726
727 switch (validity) {
728 case KMF_ALL_CERTS:
729 break;
730 case KMF_NONEXPIRED_CERTS:
731 nssrv = CERT_CertTimesValid(cert);
732 if (nssrv == SECFailure) {
733 /* this is an invalid cert - skip it */
734 goto out;
735 }
736 break;
737 case KMF_EXPIRED_CERTS:
738 nssrv = CERT_CertTimesValid(cert);
739 if (nssrv != SECFailure) {
740 /* this is a valid cert - skip it */
741 goto out;
742 }
743 break;
744 }
745 /* delete it from database */
746 nssrv = SEC_DeletePermCertificate(cert);
747 if (nssrv) {
748 SET_ERROR(kmfh, nssrv);
749 rv = KMF_ERR_INTERNAL;
750 }
751 } else {
752 CERTCertListNode *node;
753 CERTCertList *certlist = NULL;
754
755 rv = nss_find_matching_certs(nss_slot, issuer, subject, serial,
756 &certlist, validity);
757
758 for (node = CERT_LIST_HEAD(certlist);
759 !CERT_LIST_END(node, certlist) && rv == KMF_OK;
760 node = CERT_LIST_NEXT(node)) {
761
762 nssrv = SEC_DeletePermCertificate(node->cert);
763 if (nssrv) {
764 SET_ERROR(kmfh, nssrv);
765 rv = KMF_ERR_INTERNAL;
766 }
767 }
768
769 if (rv == KMF_OK && certlist != NULL) {
770 CERT_DestroyCertList(certlist);
771 } else if (rv == KMF_OK && certlist == NULL) {
772 rv = KMF_ERR_CERT_NOT_FOUND;
773 }
774 }
775 out:
776 if (nss_slot != NULL) {
777 PK11_FreeSlot(nss_slot);
778 }
779
780 if (cert != NULL) {
781 CERT_DestroyCertificate(cert);
782 }
783
784 return (rv);
785 }
786
787 static void
InitRandom(char * filename)788 InitRandom(char *filename)
789 {
790 char buf[2048];
791 int fd;
792 PRInt32 count;
793
794 fd = open(filename, O_RDONLY);
795 if (!fd)
796 return;
797
798 count = read(fd, buf, sizeof (buf));
799 if (count > 0) {
800 (void) PK11_RandomUpdate(buf, count);
801 }
802
803 (void) close(fd);
804 }
805
806 KMF_RETURN
NSS_CreateKeypair(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)807 NSS_CreateKeypair(KMF_HANDLE_T handle,
808 int numattr, KMF_ATTRIBUTE *attrlist)
809 {
810 KMF_RETURN rv = KMF_OK;
811 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
812 PK11RSAGenParams rsaparams;
813 void *nssparams;
814 CK_MECHANISM_TYPE mechanism;
815 ulong_t publicExponent = 0x010001;
816 PK11SlotInfo *nss_slot = NULL;
817 SECKEYPrivateKey *NSSprivkey = NULL;
818 SECKEYPublicKey *NSSpubkey = NULL;
819 SECKEYECParams *ecparams = NULL;
820 PQGParams *pqgParams = NULL;
821 KMF_CREDENTIAL cred;
822 boolean_t storekey = TRUE;
823 uint32_t keylen = 1024, len;
824 uint32_t keylen_size = sizeof (uint32_t);
825 KMF_KEY_ALG keytype = KMF_RSA;
826 KMF_KEY_HANDLE *pubkey = NULL;
827 KMF_KEY_HANDLE *privkey = NULL;
828 char *keylabel = NULL;
829
830 if (handle == NULL || attrlist == NULL || numattr == 0) {
831 return (KMF_ERR_BAD_PARAMETER);
832 }
833 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
834 if (rv != KMF_OK) {
835 return (rv);
836 }
837
838 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
839 (void *)&cred, NULL);
840 if (rv != KMF_OK)
841 return (rv);
842
843 rv = nss_authenticate(handle, nss_slot, &cred);
844 if (rv != KMF_OK) {
845 return (rv);
846 }
847
848 /* "storekey" is optional. Default is TRUE */
849 (void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr,
850 &storekey, NULL);
851
852 /* keytype is optional. KMF_RSA is default */
853 (void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
854 (void *)&keytype, NULL);
855
856 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr,
857 &keylen, &keylen_size);
858 if (rv == KMF_ERR_ATTR_NOT_FOUND)
859 /* Default keylen = 1024 */
860 rv = KMF_OK;
861 else if (rv != KMF_OK)
862 return (KMF_ERR_BAD_PARAMETER);
863
864 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
865 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr);
866 if (pubkey == NULL || privkey == NULL)
867 return (KMF_ERR_BAD_PARAMETER);
868
869 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
870 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
871
872 rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr, NULL, &len);
873 if (rv == KMF_OK && len > 0) {
874 keylabel = malloc(len + 1);
875 if (keylabel == NULL)
876 return (KMF_ERR_MEMORY);
877 /* Now fill in the label value */
878 (void) memset(keylabel, 0, len + 1);
879 rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr,
880 keylabel, NULL);
881 if (rv != KMF_OK) {
882 free(keylabel);
883 goto cleanup;
884 }
885 }
886
887 /* Get some random bits */
888 InitRandom("/dev/urandom");
889 if (keytype == KMF_RSA) {
890 KMF_BIGINT rsaexp;
891
892 rsaparams.keySizeInBits = keylen;
893 /*
894 * NSS only allows for a 4 byte exponent.
895 * Ignore the exponent parameter if it is too big.
896 */
897 if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr,
898 &rsaexp, NULL)) == KMF_OK) {
899 if (rsaexp.len > 0 &&
900 rsaexp.len <= sizeof (publicExponent) &&
901 rsaexp.val != NULL) {
902 (void) memcpy(&publicExponent, rsaexp.val,
903 rsaexp.len);
904 }
905 }
906 rsaparams.pe = publicExponent;
907 mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
908 nssparams = &rsaparams;
909 } else if (keytype == KMF_DSA) {
910 PQGVerify *pqgVerify = NULL;
911 int ks;
912 SECStatus nssrv, passed;
913
914 mechanism = CKM_DSA_KEY_PAIR_GEN;
915
916 ks = PQG_PBITS_TO_INDEX(keylen);
917 nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify);
918 if (nssrv != SECSuccess) {
919 SET_ERROR(kmfh, rv);
920 PK11_PQG_DestroyVerify(pqgVerify);
921 rv = KMF_ERR_KEYGEN_FAILED;
922 goto cleanup;
923 }
924
925 nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
926 if (nssrv != SECSuccess || passed != SECSuccess) {
927 SET_ERROR(kmfh, rv);
928 rv = KMF_ERR_KEYGEN_FAILED;
929 }
930
931 PK11_PQG_DestroyVerify(pqgVerify);
932
933 if (rv != KMF_OK) {
934 SET_ERROR(kmfh, PORT_GetError());
935 goto cleanup;
936 }
937
938 nssparams = pqgParams;
939 } else if (keytype == KMF_ECDSA) {
940 KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
941 attrlist, numattr);
942 if (eccoid == NULL)
943 return (KMF_ERR_BAD_PARAMETER);
944
945 ecparams = SECITEM_AllocItem(NULL, NULL, (eccoid->Length));
946 if (!ecparams)
947 return (KMF_ERR_MEMORY);
948
949 (void) memcpy(ecparams->data, eccoid->Data, eccoid->Length);
950
951 mechanism = CKM_EC_KEY_PAIR_GEN;
952 nssparams = ecparams;
953 } else {
954 rv = KMF_ERR_BAD_PARAMETER;
955 goto cleanup;
956 }
957
958 NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams,
959 &NSSpubkey,
960 storekey, /* isPermanent */
961 PR_TRUE, /* isSensitive */
962 (void *)cred.cred);
963
964 if (NSSprivkey == NULL || NSSpubkey == NULL) {
965 SET_ERROR(kmfh, PORT_GetError());
966 rv = KMF_ERR_KEYGEN_FAILED;
967 } else {
968 if (keylabel != NULL && strlen(keylabel)) {
969 (void) PK11_SetPrivateKeyNickname(NSSprivkey,
970 keylabel);
971 (void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel);
972 }
973 /* Now, convert it to a KMF_KEY object for the framework */
974 privkey->kstype = KMF_KEYSTORE_NSS;
975 privkey->keyalg = keytype;
976 privkey->keyclass = KMF_ASYM_PRI;
977 privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey);
978 privkey->keyp = (void *)NSSprivkey;
979
980 pubkey->kstype = KMF_KEYSTORE_NSS;
981 pubkey->keyalg = keytype;
982 pubkey->keyp = (void *)NSSpubkey;
983 pubkey->keyclass = KMF_ASYM_PUB;
984 pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey);
985
986 rv = KMF_OK;
987 }
988 cleanup:
989 if (rv != KMF_OK) {
990 if (NSSpubkey)
991 (void) PK11_DeleteTokenPublicKey(NSSpubkey);
992 if (NSSprivkey)
993 (void) PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE);
994
995 privkey->keyp = NULL;
996 pubkey->keyp = NULL;
997 }
998
999 if (keylabel)
1000 free(keylabel);
1001
1002 if (pqgParams != NULL)
1003 PK11_PQG_DestroyParams(pqgParams);
1004
1005 if (ecparams != NULL)
1006 SECITEM_FreeItem(ecparams, PR_TRUE);
1007
1008 if (nss_slot != NULL)
1009 PK11_FreeSlot(nss_slot);
1010
1011 return (rv);
1012 }
1013
1014 KMF_RETURN
NSS_SignData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * tobesigned,KMF_DATA * output)1015 NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1016 KMF_OID *AlgOID, KMF_DATA *tobesigned,
1017 KMF_DATA *output)
1018 {
1019 KMF_RETURN ret = KMF_OK;
1020 KMF_ALGORITHM_INDEX AlgId;
1021 SECOidTag signAlgTag;
1022 SECKEYPrivateKey *NSSprivkey = NULL;
1023 SECStatus rv;
1024 SECItem signed_data;
1025 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1026
1027 signed_data.data = 0;
1028 if (key == NULL || AlgOID == NULL ||
1029 tobesigned == NULL || output == NULL ||
1030 tobesigned->Data == NULL ||
1031 output->Data == NULL)
1032 return (KMF_ERR_BAD_PARAMETER);
1033
1034 /* Map the OID to a NSS algorithm */
1035 AlgId = x509_algoid_to_algid(AlgOID);
1036 if (AlgId == KMF_ALGID_NONE)
1037 return (KMF_ERR_BAD_PARAMETER);
1038
1039 NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1040
1041 if (AlgId == KMF_ALGID_MD5WithRSA)
1042 signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1043 else if (AlgId == KMF_ALGID_MD2WithRSA)
1044 signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1045 else if (AlgId == KMF_ALGID_SHA1WithRSA)
1046 signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1047 else if (AlgId == KMF_ALGID_SHA256WithRSA)
1048 signAlgTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1049 else if (AlgId == KMF_ALGID_SHA384WithRSA)
1050 signAlgTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1051 else if (AlgId == KMF_ALGID_SHA512WithRSA)
1052 signAlgTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1053 else if (AlgId == KMF_ALGID_SHA1WithDSA)
1054 signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
1055 else if (AlgId == KMF_ALGID_SHA1WithECDSA || AlgId == KMF_ALGID_ECDSA)
1056 signAlgTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
1057 else if (AlgId == KMF_ALGID_SHA256WithECDSA)
1058 signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
1059 else if (AlgId == KMF_ALGID_SHA384WithECDSA)
1060 signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
1061 else if (AlgId == KMF_ALGID_SHA512WithECDSA)
1062 signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
1063 else /* NSS does not support DSA with SHA2 hashes (FIPS 186-3) */
1064 return (KMF_ERR_BAD_PARAMETER);
1065
1066 rv = SEC_SignData(&signed_data, tobesigned->Data,
1067 tobesigned->Length, NSSprivkey, signAlgTag);
1068
1069 if (rv != 0) {
1070 SET_ERROR(kmfh, rv);
1071 return (KMF_ERR_INTERNAL);
1072 }
1073
1074 if (signed_data.len <= output->Length) {
1075 (void) memcpy(output->Data, signed_data.data, signed_data.len);
1076 output->Length = signed_data.len;
1077 } else {
1078 output->Length = 0;
1079 ret = KMF_ERR_BAD_PARAMETER;
1080 }
1081 free(signed_data.data);
1082
1083 return (ret);
1084 }
1085
1086 KMF_RETURN
NSS_EncodePubKeyData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * keyp,KMF_DATA * encoded)1087 NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
1088 KMF_DATA *encoded)
1089 {
1090 KMF_RETURN ret = KMF_OK;
1091 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1092 SECItem *rvitem;
1093 CERTSubjectPublicKeyInfo *spki = NULL;
1094
1095 if (keyp == NULL || encoded == NULL || keyp->keyp == NULL)
1096 return (KMF_ERR_BAD_PARAMETER);
1097
1098 spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp);
1099 if (spki == NULL) {
1100 SET_ERROR(kmfh, PORT_GetError());
1101 return (KMF_ERR_MEMORY);
1102 }
1103
1104 rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki,
1105 CERT_SubjectPublicKeyInfoTemplate);
1106 if (rvitem != NULL) {
1107 encoded->Data = malloc(rvitem->len);
1108 if (encoded->Data == NULL) {
1109 ret = KMF_ERR_MEMORY;
1110 } else {
1111 (void) memcpy(encoded->Data, rvitem->data, rvitem->len);
1112 encoded->Length = rvitem->len;
1113 }
1114 SECITEM_FreeItem(rvitem, TRUE);
1115 } else {
1116 SET_ERROR(kmfh, PORT_GetError());
1117 encoded->Data = NULL;
1118 encoded->Length = 0;
1119 ret = KMF_ERR_ENCODING;
1120 }
1121 SECKEY_DestroySubjectPublicKeyInfo(spki);
1122
1123 return (ret);
1124 }
1125
1126 KMF_RETURN
NSS_DeleteKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)1127 NSS_DeleteKey(KMF_HANDLE_T handle,
1128 int numattr, KMF_ATTRIBUTE *attrlist)
1129 {
1130 KMF_RETURN rv = KMF_OK;
1131 PK11SlotInfo *nss_slot = NULL;
1132 KMF_KEY_HANDLE *key;
1133 KMF_CREDENTIAL cred;
1134 boolean_t delete_token = B_TRUE;
1135
1136 if (handle == NULL || attrlist == NULL || numattr == 0) {
1137 return (KMF_ERR_BAD_PARAMETER);
1138 }
1139 /*
1140 * "delete_token" means to clear it from the token storage as well
1141 * as from memory.
1142 */
1143 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1144 if (key == NULL || key->keyp == NULL)
1145 return (KMF_ERR_BAD_PARAMETER);
1146
1147 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr,
1148 (void *)&delete_token, NULL);
1149 if (rv != KMF_OK)
1150 /* "delete_token" is optional. Default is TRUE */
1151 rv = KMF_OK;
1152
1153 if (delete_token) {
1154 SECStatus nssrv = SECSuccess;
1155 if (key->keyclass != KMF_ASYM_PUB &&
1156 key->keyclass != KMF_ASYM_PRI &&
1157 key->keyclass != KMF_SYMMETRIC)
1158 return (KMF_ERR_BAD_KEY_CLASS);
1159
1160 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1161 if (rv != KMF_OK) {
1162 return (rv);
1163 }
1164
1165 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1166 (void *)&cred, NULL);
1167 if (rv != KMF_OK)
1168 return (KMF_ERR_BAD_PARAMETER);
1169
1170 rv = nss_authenticate(handle, nss_slot, &cred);
1171 if (rv != KMF_OK) {
1172 return (rv);
1173 }
1174
1175 if (key->keyclass == KMF_ASYM_PUB) {
1176 nssrv = PK11_DeleteTokenPublicKey(
1177 (SECKEYPublicKey *)key->keyp);
1178 } else if (key->keyclass == KMF_ASYM_PRI) {
1179 nssrv = PK11_DeleteTokenPrivateKey(
1180 (SECKEYPrivateKey *)key->keyp, PR_TRUE);
1181 } else if (key->keyclass == KMF_SYMMETRIC) {
1182 nssrv = PK11_DeleteTokenSymKey(
1183 (PK11SymKey *) key->keyp);
1184 if (nssrv == SECSuccess)
1185 PK11_FreeSymKey((PK11SymKey *) key->keyp);
1186 }
1187 if (nssrv != SECSuccess) {
1188 SET_ERROR(handle, PORT_GetError());
1189 rv = KMF_ERR_INTERNAL;
1190 }
1191 } else {
1192 if (key->keyclass == KMF_ASYM_PUB) {
1193 SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp);
1194 } else if (key->keyclass == KMF_ASYM_PRI) {
1195 SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp);
1196 } else if (key->keyclass == KMF_SYMMETRIC) {
1197 PK11_FreeSymKey((PK11SymKey *) key->keyp);
1198 } else {
1199 return (KMF_ERR_BAD_KEY_CLASS);
1200 }
1201 }
1202 key->keyp = NULL;
1203
1204 return (rv);
1205 }
1206
1207 KMF_RETURN
NSS_GetErrorString(KMF_HANDLE_T handle,char ** msgstr)1208 NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr)
1209 {
1210 KMF_RETURN ret = KMF_OK;
1211 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1212 char *str;
1213
1214 /* Get the error string in the default language */
1215 str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode);
1216
1217 if (str != NULL) {
1218 *msgstr = (char *)strdup(str);
1219 if ((*msgstr) == NULL)
1220 ret = KMF_ERR_MEMORY;
1221 } else {
1222 *msgstr = NULL;
1223 }
1224
1225 return (ret);
1226 }
1227
1228 KMF_RETURN
NSS_FindPrikeyByCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)1229 NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1230 {
1231 KMF_RETURN rv = KMF_OK;
1232 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1233 PK11SlotInfo *nss_slot = NULL;
1234 KMF_CREDENTIAL cred;
1235 KMF_KEY_HANDLE *key = NULL;
1236 KMF_DATA *cert = NULL;
1237 CERTCertificate *nss_cert = NULL;
1238 SECKEYPrivateKey* privkey = NULL;
1239
1240 if (handle == NULL || attrlist == NULL || numattr == 0) {
1241 return (KMF_ERR_BAD_PARAMETER);
1242 }
1243
1244 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1245 if (rv != KMF_OK)
1246 return (rv);
1247
1248 /* Get the credential */
1249 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1250 (void *)&cred, NULL);
1251 if (rv != KMF_OK)
1252 return (KMF_ERR_BAD_PARAMETER);
1253 rv = nss_authenticate(handle, nss_slot, &cred);
1254 if (rv != KMF_OK)
1255 return (rv);
1256
1257 /* Get the key handle */
1258 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1259 if (key == NULL)
1260 return (KMF_ERR_BAD_PARAMETER);
1261
1262 /* Get the cert data and decode it */
1263 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
1264 if (cert == NULL || cert->Data == NULL)
1265 return (KMF_ERR_BAD_PARAMETER);
1266
1267 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
1268 cert->Length);
1269 if (nss_cert == NULL) {
1270 SET_ERROR(kmfh, PORT_GetError());
1271 return (KMF_ERR_BAD_CERT_FORMAT);
1272 }
1273
1274 privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL);
1275 if (privkey == NULL) {
1276 SET_ERROR(kmfh, PORT_GetError());
1277 return (KMF_ERR_KEY_NOT_FOUND);
1278 }
1279
1280 key->kstype = KMF_KEYSTORE_NSS;
1281 key->keyclass = KMF_ASYM_PRI;
1282 key->keyp = (void *)privkey;
1283 key->keylabel = PK11_GetPrivateKeyNickname(privkey);
1284
1285 CERT_DestroyCertificate(nss_cert);
1286
1287 return (KMF_OK);
1288 }
1289
1290
1291 KMF_RETURN
NSS_DecryptData(KMF_HANDLE_T handle,KMF_KEY_HANDLE * key,KMF_OID * AlgOID,KMF_DATA * ciphertext,KMF_DATA * output)1292 NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
1293 KMF_OID *AlgOID, KMF_DATA *ciphertext,
1294 KMF_DATA *output)
1295 {
1296 KMF_RETURN ret = KMF_OK;
1297 SECKEYPrivateKey *NSSprivkey = NULL;
1298 SECStatus rv;
1299 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1300 unsigned int in_len = 0, out_len = 0;
1301 unsigned int total_decrypted = 0, modulus_len = 0;
1302 uint8_t *in_data, *out_data;
1303 int i, blocks;
1304
1305 if (key == NULL || AlgOID == NULL ||
1306 ciphertext == NULL || output == NULL ||
1307 ciphertext->Data == NULL ||
1308 output->Data == NULL)
1309 return (KMF_ERR_BAD_PARAMETER);
1310
1311 NSSprivkey = (SECKEYPrivateKey *)key->keyp;
1312 modulus_len = PK11_GetPrivateModulusLen(NSSprivkey);
1313
1314 blocks = ciphertext->Length/modulus_len;
1315 out_data = output->Data;
1316 in_data = ciphertext->Data;
1317 out_len = modulus_len - 11;
1318 in_len = modulus_len;
1319
1320 for (i = 0; i < blocks; i++) {
1321 rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data,
1322 &out_len, ciphertext->Length, in_data, in_len);
1323
1324 if (rv != 0) {
1325 SET_ERROR(kmfh, rv);
1326 return (KMF_ERR_INTERNAL);
1327 }
1328
1329 out_data += out_len;
1330 total_decrypted += out_len;
1331 in_data += in_len;
1332 }
1333
1334 output->Length = total_decrypted;
1335
1336 return (ret);
1337 }
1338
1339 static KMF_KEY_ALG
pk11keytype2kmf(CK_KEY_TYPE type)1340 pk11keytype2kmf(CK_KEY_TYPE type)
1341 {
1342 switch (type) {
1343 case CKK_RSA:
1344 return (KMF_RSA);
1345 case CKK_DSA:
1346 return (KMF_RSA);
1347 case CKK_AES:
1348 return (KMF_AES);
1349 case CKK_RC4:
1350 return (KMF_RC4);
1351 case CKK_DES:
1352 return (KMF_DES);
1353 case CKK_DES3:
1354 return (KMF_DES3);
1355 case CKK_EC:
1356 return (KMF_ECDSA);
1357 default:
1358 /* not supported */
1359 return (KMF_KEYALG_NONE);
1360 }
1361 }
1362
1363 KMF_RETURN
NSS_FindKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)1364 NSS_FindKey(KMF_HANDLE_T handle,
1365 int numattr, KMF_ATTRIBUTE *attrlist)
1366 {
1367 KMF_RETURN rv;
1368 SECKEYPrivateKeyList *prilist;
1369 SECKEYPrivateKeyListNode *prinode;
1370 SECKEYPublicKeyList *publist;
1371 SECKEYPublicKeyListNode *pubnode;
1372 PK11SlotInfo *nss_slot = NULL;
1373 PK11SymKey *symlist = NULL;
1374 int count;
1375 uint32_t maxkeys;
1376 KMF_KEY_HANDLE *keys;
1377 uint32_t *numkeys;
1378 KMF_CREDENTIAL *cred = NULL;
1379 KMF_KEY_CLASS keyclass;
1380 char *findLabel;
1381 char *nick;
1382 int match = 0;
1383 KMF_KEY_ALG keytype = KMF_KEYALG_NONE;
1384
1385 if (handle == NULL || attrlist == NULL || numattr == 0) {
1386 return (KMF_ERR_BAD_PARAMETER);
1387 }
1388
1389 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr);
1390 if (numkeys == NULL)
1391 return (KMF_ERR_BAD_PARAMETER);
1392
1393 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1394 if (rv != KMF_OK) {
1395 return (rv);
1396 }
1397
1398 /* It is OK if this is NULL, we dont need a cred to find public keys */
1399 cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1400
1401 if (cred != NULL) {
1402 rv = nss_authenticate(handle, nss_slot, cred);
1403 if (rv != KMF_OK) {
1404 return (rv);
1405 }
1406 }
1407
1408 maxkeys = *numkeys;
1409 if (maxkeys == 0)
1410 maxkeys = 0xFFFFFFFF;
1411 *numkeys = 0;
1412
1413 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr,
1414 (void *)&keyclass, NULL);
1415 if (rv != KMF_OK)
1416 return (KMF_ERR_BAD_PARAMETER);
1417
1418 findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1419
1420 if (keyclass == KMF_ASYM_PUB) {
1421 publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel);
1422 if (publist == NULL) {
1423 rv = KMF_ERR_KEY_NOT_FOUND;
1424 goto cleanup;
1425 }
1426 } else if (keyclass == KMF_ASYM_PRI) {
1427 prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL);
1428 if (prilist == NULL) {
1429 rv = KMF_ERR_KEY_NOT_FOUND;
1430 goto cleanup;
1431 }
1432 } else if (keyclass == KMF_SYMMETRIC) {
1433 symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL);
1434 if (symlist == NULL) {
1435 rv = KMF_ERR_KEY_NOT_FOUND;
1436 goto cleanup;
1437 }
1438 } else {
1439 rv = KMF_ERR_BAD_KEY_CLASS;
1440 goto cleanup;
1441 }
1442
1443 keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1444 /* it is okay to have "keys" contains NULL */
1445
1446 if (keyclass == KMF_ASYM_PUB) {
1447 for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist);
1448 !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys;
1449 pubnode = PUBKEY_LIST_NEXT(pubnode)) {
1450 match = 0;
1451 /*
1452 * Due to bug in NSS, we have to manually match
1453 * the labels to be sure we have a match.
1454 */
1455 nick = PK11_GetPublicKeyNickname(pubnode->key);
1456 if (findLabel) {
1457 match = (nick &&
1458 (strcmp(nick, findLabel) == 0));
1459 } else {
1460 /* always match if findLabel is NULL */
1461 match = 1;
1462 }
1463 if (keys != NULL && match) {
1464 keys[count].kstype = KMF_KEYSTORE_NSS;
1465 keys[count].keyclass = KMF_ASYM_PUB;
1466 keys[count].keyp = (void *)pubnode->key;
1467 keys[count].keylabel = nick;
1468
1469 if (pubnode->key->keyType == rsaKey)
1470 keys[count].keyalg = KMF_RSA;
1471 else if (pubnode->key->keyType == dsaKey)
1472 keys[count].keyalg = KMF_DSA;
1473 else if (pubnode->key->keyType == ecKey)
1474 keys[count].keyalg = KMF_ECDSA;
1475 }
1476 if (match)
1477 count++;
1478 }
1479 *numkeys = count;
1480 } else if (keyclass == KMF_ASYM_PRI) {
1481 for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist);
1482 !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys;
1483 prinode = PRIVKEY_LIST_NEXT(prinode)) {
1484 match = 0;
1485 /*
1486 * Due to bug in NSS, we have to manually match
1487 * the labels to be sure we have a match.
1488 */
1489 nick = PK11_GetPrivateKeyNickname(prinode->key);
1490 if (findLabel) {
1491 match = (nick &&
1492 (strcmp(nick, findLabel) == 0));
1493 } else {
1494 /* always match if findLabel is NULL */
1495 match = 1;
1496 }
1497 if (keys != NULL && match) {
1498 keys[count].kstype = KMF_KEYSTORE_NSS;
1499 keys[count].keyclass = KMF_ASYM_PRI;
1500 keys[count].keyp = (void *)prinode->key;
1501 keys[count].keylabel = nick;
1502
1503 if (prinode->key->keyType == rsaKey)
1504 keys[count].keyalg = KMF_RSA;
1505 else if (prinode->key->keyType == dsaKey)
1506 keys[count].keyalg = KMF_DSA;
1507 else if (prinode->key->keyType == ecKey)
1508 keys[count].keyalg = KMF_ECDSA;
1509 }
1510 if (match)
1511 count++;
1512 }
1513 *numkeys = count;
1514 } else if (keyclass == KMF_SYMMETRIC) {
1515 count = 0;
1516 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr,
1517 (void *)&keytype, NULL);
1518 if (rv != KMF_OK)
1519 rv = KMF_OK;
1520 while (symlist && count < maxkeys) {
1521 PK11SymKey *symkey = symlist;
1522 CK_KEY_TYPE type;
1523 KMF_KEY_ALG keyalg;
1524
1525 match = 0;
1526 type = PK11_GetSymKeyType(symkey);
1527 keyalg = pk11keytype2kmf(type);
1528
1529 symlist = PK11_GetNextSymKey(symkey);
1530
1531 /*
1532 * If keytype is specified in the searching parameter,
1533 * check the keytype and skip the key if its keytype
1534 * doesn't match.
1535 */
1536 if (keytype != KMF_KEYALG_NONE && keytype != keyalg) {
1537 /* free that key since we arent using it */
1538 PK11_FreeSymKey(symkey);
1539 continue;
1540 }
1541 /*
1542 * Due to bug in NSS, we have to manually match
1543 * the labels to be sure we have a match.
1544 */
1545 nick = PK11_GetSymKeyNickname(symkey);
1546 if (findLabel) {
1547 match = (nick &&
1548 (strcmp(nick, findLabel) == 0));
1549 } else {
1550 /* always match if findLabel is NULL */
1551 match = 1;
1552 }
1553
1554 if (keys != NULL && match) {
1555 keys[count].kstype = KMF_KEYSTORE_NSS;
1556 keys[count].keyclass = KMF_SYMMETRIC;
1557 keys[count].keyp = (void *) symkey;
1558 keys[count].keylabel = nick;
1559 keys[count].keyalg = keyalg;
1560 } else {
1561 PK11_FreeSymKey(symkey);
1562 }
1563 if (match)
1564 count++;
1565 }
1566 /*
1567 * Cleanup memory for unused keys.
1568 */
1569 while (symlist != NULL) {
1570 PK11SymKey *symkey = symlist;
1571
1572 PK11_FreeSymKey(symkey);
1573 symlist = PK11_GetNextSymKey(symkey);
1574 }
1575 *numkeys = count;
1576 }
1577
1578 cleanup:
1579 if (nss_slot != NULL) {
1580 PK11_FreeSlot(nss_slot);
1581 }
1582
1583 return (rv);
1584 }
1585
1586 static SECStatus
p12u_SwapUnicodeBytes(SECItem * uniItem)1587 p12u_SwapUnicodeBytes(SECItem *uniItem)
1588 {
1589 unsigned int i;
1590 unsigned char a;
1591 if ((uniItem == NULL) || (uniItem->len % 2)) {
1592 return (SECFailure);
1593 }
1594 for (i = 0; i < uniItem->len; i += 2) {
1595 a = uniItem->data[i];
1596 uniItem->data[i] = uniItem->data[i+1];
1597 uniItem->data[i+1] = a;
1598 }
1599 return (SECSuccess);
1600 }
1601
1602 static PRBool
p12u_ucs2_ascii_conversion_function(PRBool toUnicode,unsigned char * inBuf,unsigned int inBufLen,unsigned char * outBuf,unsigned int maxOutBufLen,unsigned int * outBufLen,PRBool swapBytes)1603 p12u_ucs2_ascii_conversion_function(
1604 PRBool toUnicode,
1605 unsigned char *inBuf,
1606 unsigned int inBufLen,
1607 unsigned char *outBuf,
1608 unsigned int maxOutBufLen,
1609 unsigned int *outBufLen,
1610 PRBool swapBytes)
1611 {
1612 SECItem it = { siBuffer, NULL, 0 };
1613 SECItem *dup = NULL;
1614 PRBool ret;
1615
1616 it.data = inBuf;
1617 it.len = inBufLen;
1618 dup = SECITEM_DupItem(&it);
1619 /*
1620 * If converting Unicode to ASCII, swap bytes before conversion
1621 * as neccessary.
1622 */
1623 if (!toUnicode && swapBytes) {
1624 if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
1625 SECITEM_ZfreeItem(dup, PR_TRUE);
1626 return (PR_FALSE);
1627 }
1628 }
1629 /* Perform the conversion. */
1630 ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
1631 outBuf, maxOutBufLen, outBufLen);
1632 if (dup)
1633 SECITEM_ZfreeItem(dup, PR_TRUE);
1634
1635 return (ret);
1636 }
1637
1638 static PRBool
p12u_OpenFile(p12uContext * p12ctx,PRBool fileRead)1639 p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead)
1640 {
1641 if (!p12ctx || !p12ctx->filename) {
1642 return (PR_FALSE);
1643 }
1644
1645 if (fileRead) {
1646 p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400);
1647 } else {
1648 p12ctx->file = PR_Open(p12ctx->filename,
1649 PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600);
1650 }
1651
1652 if (!p12ctx->file) {
1653 p12ctx->error = PR_TRUE;
1654 return (PR_FALSE);
1655 }
1656
1657 return (PR_TRUE);
1658 }
1659
1660 static void
p12u_DestroyContext(p12uContext ** ppCtx,PRBool removeFile)1661 p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile)
1662 {
1663 if (!ppCtx || !(*ppCtx)) {
1664 return;
1665 }
1666
1667 if ((*ppCtx)->file != NULL) {
1668 (void) PR_Close((*ppCtx)->file);
1669 }
1670
1671 if ((*ppCtx)->filename != NULL) {
1672 if (removeFile) {
1673 (void) PR_Delete((*ppCtx)->filename);
1674 }
1675 free((*ppCtx)->filename);
1676 }
1677
1678 free(*ppCtx);
1679 *ppCtx = NULL;
1680 }
1681
1682 static p12uContext *
p12u_InitContext(PRBool fileImport,char * filename)1683 p12u_InitContext(PRBool fileImport, char *filename)
1684 {
1685 p12uContext *p12ctx;
1686
1687 p12ctx = PORT_ZNew(p12uContext);
1688 if (!p12ctx) {
1689 return (NULL);
1690 }
1691
1692 p12ctx->error = PR_FALSE;
1693 p12ctx->errorValue = 0;
1694 p12ctx->filename = strdup(filename);
1695
1696 if (!p12u_OpenFile(p12ctx, fileImport)) {
1697 p12u_DestroyContext(&p12ctx, PR_FALSE);
1698 return (NULL);
1699 }
1700
1701 return (p12ctx);
1702 }
1703
1704 static void
p12u_WriteToExportFile(void * arg,const char * buf,unsigned long len)1705 p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
1706 {
1707 p12uContext *p12cxt = arg;
1708 int writeLen;
1709
1710 if (!p12cxt || (p12cxt->error == PR_TRUE)) {
1711 return;
1712 }
1713
1714 if (p12cxt->file == NULL) {
1715 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1716 p12cxt->error = PR_TRUE;
1717 return;
1718 }
1719
1720 writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
1721
1722 if (writeLen != (int)len) {
1723 (void) PR_Close(p12cxt->file);
1724 free(p12cxt->filename);
1725 p12cxt->filename = NULL;
1726 p12cxt->file = NULL;
1727 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
1728 p12cxt->error = PR_TRUE;
1729 }
1730 }
1731
1732 #define HANDLE_NSS_ERROR(r) {\
1733 SET_ERROR(kmfh, PORT_GetError()); \
1734 rv = r; \
1735 goto out; }
1736
1737 static KMF_RETURN
add_cert_to_bag(SEC_PKCS12ExportContext * p12ecx,CERTCertificate * cert,SECItem * pwitem)1738 add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx,
1739 CERTCertificate *cert, SECItem *pwitem)
1740 {
1741 KMF_RETURN rv = KMF_OK;
1742 SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
1743
1744 keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
1745 if (PK11_IsFIPS()) {
1746 certSafe = keySafe;
1747 } else {
1748 certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
1749 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
1750 }
1751
1752 if (!certSafe || !keySafe) {
1753 rv = KMF_ERR_INTERNAL;
1754 goto out;
1755 }
1756
1757 if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
1758 CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
1759 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
1760 != SECSuccess) {
1761 rv = KMF_ERR_INTERNAL;
1762 }
1763 out:
1764 return (rv);
1765 }
1766
1767 KMF_RETURN
NSS_ExportPK12(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)1768 NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
1769 {
1770 KMF_RETURN rv;
1771 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1772 SEC_PKCS12ExportContext *p12ecx = NULL;
1773 p12uContext *p12ctx = NULL;
1774 CERTCertList *certlist = NULL;
1775 CERTCertificate *nsscert = NULL;
1776 CERTCertListNode* node = NULL;
1777 PK11SlotInfo *slot = NULL;
1778 SECItem pwitem = { siBuffer, NULL, 0 };
1779 KMF_CREDENTIAL *cred = NULL;
1780 KMF_CREDENTIAL *p12cred = NULL;
1781 char *certlabel = NULL;
1782 char *issuer = NULL;
1783 char *subject = NULL;
1784 KMF_BIGINT *serial = NULL;
1785 char *filename = NULL;
1786
1787 if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1788 return (KMF_ERR_BAD_PARAMETER);
1789 }
1790
1791 rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot);
1792 if (rv != KMF_OK)
1793 return (rv);
1794
1795 cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr);
1796 if (cred == NULL)
1797 return (KMF_ERR_BAD_PARAMETER);
1798
1799 rv = nss_authenticate(handle, slot, cred);
1800 if (rv != KMF_OK)
1801 return (rv);
1802
1803 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr);
1804 if (p12cred == NULL)
1805 return (KMF_ERR_BAD_PARAMETER);
1806
1807 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist,
1808 numattr);
1809 if (filename == NULL)
1810 return (KMF_ERR_BAD_PARAMETER);
1811
1812 /* Get optional search criteria attributes */
1813 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
1814 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr);
1815 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr);
1816 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr);
1817
1818 /*
1819 * Find the certificate(s) first.
1820 */
1821 if (certlabel != NULL) {
1822 nsscert = PK11_FindCertFromNickname(certlabel, NULL);
1823 if (nsscert == NULL) {
1824 HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND)
1825 }
1826 } else {
1827 rv = nss_find_matching_certs(slot, issuer, subject, serial,
1828 &certlist, 0);
1829
1830 if (rv == KMF_OK && certlist == NULL) {
1831 return (KMF_ERR_CERT_NOT_FOUND);
1832 }
1833 if (rv != KMF_OK)
1834 return (rv);
1835 }
1836
1837 /*
1838 * The KMF_CREDENTIAL holds the password to use for
1839 * encrypting the PKCS12 key information.
1840 */
1841 pwitem.data = (uchar_t *)p12cred->cred;
1842 pwitem.len = p12cred->credlen;
1843
1844 p12ctx = p12u_InitContext(PR_FALSE, filename);
1845 if (!p12ctx) {
1846 HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1847 }
1848
1849 PORT_SetUCS2_ASCIIConversionFunction(
1850 p12u_ucs2_ascii_conversion_function);
1851
1852 p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL);
1853 if (!p12ecx) {
1854 HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE)
1855 }
1856
1857 if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
1858 != SECSuccess) {
1859 HANDLE_NSS_ERROR(KMF_ERR_INTERNAL)
1860 }
1861
1862 /*
1863 * NSS actually supports storing a list of keys and certs
1864 * in the PKCS#12 PDU. Nice feature.
1865 */
1866 if (certlist != NULL) {
1867 for (node = CERT_LIST_HEAD(certlist);
1868 !CERT_LIST_END(node, certlist) && rv == KMF_OK;
1869 node = CERT_LIST_NEXT(node)) {
1870 rv = add_cert_to_bag(p12ecx, node->cert, &pwitem);
1871 }
1872 } else if (nsscert != NULL) {
1873 rv = add_cert_to_bag(p12ecx, nsscert, &pwitem);
1874 }
1875
1876 if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx)
1877 != SECSuccess) {
1878 HANDLE_NSS_ERROR(KMF_ERR_ENCODING)
1879 }
1880 out:
1881 if (nsscert)
1882 CERT_DestroyCertificate(nsscert);
1883
1884 if (certlist)
1885 CERT_DestroyCertList(certlist);
1886
1887 if (p12ctx)
1888 p12u_DestroyContext(&p12ctx, PR_FALSE);
1889
1890 if (p12ecx)
1891 SEC_PKCS12DestroyExportContext(p12ecx);
1892
1893 return (rv);
1894 }
1895
1896 #define SETATTR(t, n, atype, value, size) \
1897 t[n].type = atype; \
1898 t[n].pValue = (CK_BYTE *)value; \
1899 t[n].ulValueLen = (CK_ULONG)size;
1900
1901 KMF_RETURN
NSS_CreateSymKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)1902 NSS_CreateSymKey(KMF_HANDLE_T handle,
1903 int numattr, KMF_ATTRIBUTE *attrlist)
1904 {
1905 KMF_RETURN rv = KMF_OK;
1906 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
1907 PK11SlotInfo *nss_slot = NULL;
1908 PK11SymKey *nsskey = NULL;
1909 CK_MECHANISM_TYPE keyType;
1910 SECStatus nssrv;
1911 int keySize;
1912 KMF_KEY_HANDLE *symkey;
1913 KMF_CREDENTIAL cred;
1914 uint32_t keylen;
1915 uint32_t keylen_size = sizeof (uint32_t);
1916 KMF_KEY_ALG keytype;
1917 char *keylabel = NULL;
1918
1919 if (kmfh == NULL || attrlist == NULL || numattr == 0) {
1920 return (KMF_ERR_BAD_PARAMETER);
1921 }
1922
1923 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr);
1924 if (symkey == NULL)
1925 return (KMF_ERR_BAD_PARAMETER);
1926
1927 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype,
1928 NULL);
1929 if (rv != KMF_OK)
1930 return (KMF_ERR_BAD_PARAMETER);
1931
1932 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen,
1933 &keylen_size);
1934 if (rv == KMF_ERR_ATTR_NOT_FOUND &&
1935 (keytype == KMF_DES || keytype == KMF_DES3))
1936 /* keylength is not required for DES and 3DES */
1937 rv = KMF_OK;
1938 if (rv != KMF_OK)
1939 return (KMF_ERR_BAD_PARAMETER);
1940
1941 keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
1942 if (keylabel == NULL)
1943 return (KMF_ERR_BAD_PARAMETER);
1944
1945 switch (keytype) {
1946 case KMF_AES:
1947 keyType = CKM_AES_KEY_GEN;
1948 keySize = keylen;
1949 if (keySize == 0 || (keySize % 8) != 0)
1950 return (KMF_ERR_BAD_KEY_SIZE);
1951 break;
1952 case KMF_RC4:
1953 keyType = CKM_RC4_KEY_GEN;
1954 keySize = keylen;
1955 if (keySize == 0 || (keySize % 8) != 0)
1956 return (KMF_ERR_BAD_KEY_SIZE);
1957 break;
1958 case KMF_DES:
1959 keyType = CKM_DES_KEY_GEN;
1960 keySize = 0; /* required by PK11_TokenKeyGen() */
1961 break;
1962 case KMF_DES3:
1963 keyType = CKM_DES3_KEY_GEN;
1964 keySize = 0; /* required by PK11_TokenKeyGen() */
1965 break;
1966 case KMF_GENERIC_SECRET:
1967 keyType = CKM_GENERIC_SECRET_KEY_GEN;
1968 keySize = keylen;
1969 if (keySize == 0 || (keySize % 8) != 0)
1970 return (KMF_ERR_BAD_KEY_SIZE);
1971 break;
1972 default:
1973 rv = KMF_ERR_BAD_KEY_TYPE;
1974 goto out;
1975 }
1976
1977 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
1978 if (rv != KMF_OK) {
1979 return (rv);
1980 }
1981
1982 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
1983 (void *)&cred, NULL);
1984 if (rv != KMF_OK)
1985 return (KMF_ERR_BAD_PARAMETER);
1986
1987 rv = nss_authenticate(handle, nss_slot, &cred);
1988 if (rv != KMF_OK) {
1989 return (rv);
1990 }
1991
1992 /* convert key length to bytes */
1993 nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize / 8, NULL,
1994 PR_TRUE, (void *)cred.cred);
1995 if (nsskey == NULL) {
1996 SET_ERROR(kmfh, PORT_GetError());
1997 rv = KMF_ERR_KEYGEN_FAILED;
1998 goto out;
1999 }
2000
2001 nssrv = PK11_SetSymKeyNickname(nsskey, keylabel);
2002 if (nssrv != SECSuccess) {
2003 SET_ERROR(kmfh, PORT_GetError());
2004 rv = KMF_ERR_KEYGEN_FAILED;
2005 goto out;
2006 }
2007
2008 symkey->kstype = KMF_KEYSTORE_NSS;
2009 symkey->keyalg = keytype;
2010 symkey->keyclass = KMF_SYMMETRIC;
2011 symkey->israw = FALSE;
2012 symkey->keyp = (void *)nsskey;
2013
2014 out:
2015 if (nss_slot != NULL)
2016 PK11_FreeSlot(nss_slot);
2017
2018 if (rv != KMF_OK && nsskey != NULL) {
2019 (void) PK11_DeleteTokenSymKey(nsskey);
2020 PK11_FreeSymKey(nsskey);
2021 }
2022 return (rv);
2023 }
2024
2025 KMF_RETURN
NSS_GetSymKeyValue(KMF_HANDLE_T handle,KMF_KEY_HANDLE * symkey,KMF_RAW_SYM_KEY * rkey)2026 NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
2027 KMF_RAW_SYM_KEY *rkey)
2028 {
2029 KMF_RETURN rv = KMF_OK;
2030 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2031 SECItem *value = NULL;
2032 PK11SymKey *nsskey;
2033 SECStatus nss_rv;
2034
2035 if (kmfh == NULL)
2036 return (KMF_ERR_UNINITIALIZED);
2037
2038 if (symkey == NULL || rkey == NULL)
2039 return (KMF_ERR_BAD_PARAMETER);
2040 else if (symkey->keyclass != KMF_SYMMETRIC)
2041 return (KMF_ERR_BAD_KEY_CLASS);
2042
2043 if (symkey->israw) {
2044 KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp;
2045
2046 if (rawkey == NULL ||
2047 rawkey->rawdata.sym.keydata.val == NULL ||
2048 rawkey->rawdata.sym.keydata.len == 0)
2049 return (KMF_ERR_BAD_KEYHANDLE);
2050
2051 rkey->keydata.len = rawkey->rawdata.sym.keydata.len;
2052 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL)
2053 return (KMF_ERR_MEMORY);
2054 (void) memcpy(rkey->keydata.val,
2055 rawkey->rawdata.sym.keydata.val, rkey->keydata.len);
2056 } else {
2057 nsskey = (PK11SymKey *)(symkey->keyp);
2058 if (nsskey == NULL)
2059 return (KMF_ERR_BAD_KEYHANDLE);
2060
2061 nss_rv = PK11_ExtractKeyValue(nsskey);
2062 if (nss_rv != SECSuccess) {
2063 SET_ERROR(kmfh, PORT_GetError());
2064 rv = KMF_ERR_GETKEYVALUE_FAILED;
2065 goto out;
2066 }
2067
2068 value = PK11_GetKeyData(nsskey);
2069 if (value == NULL) {
2070 SET_ERROR(kmfh, PORT_GetError());
2071 rv = KMF_ERR_GETKEYVALUE_FAILED;
2072 goto out;
2073 }
2074
2075 if (value->len == 0 || value->data == NULL) {
2076 rv = KMF_ERR_GETKEYVALUE_FAILED;
2077 goto out;
2078 }
2079
2080 rkey->keydata.val = malloc(value->len);
2081 if (rkey->keydata.val == NULL) {
2082 rv = KMF_ERR_MEMORY;
2083 goto out;
2084 }
2085 (void) memcpy(rkey->keydata.val, value->data, value->len);
2086 rkey->keydata.len = value->len;
2087 (void) memset(value->data, 0, value->len);
2088 }
2089 out:
2090 if (value != NULL)
2091 SECITEM_FreeItem(value, PR_TRUE);
2092 return (rv);
2093 }
2094
2095 KMF_RETURN
NSS_SetTokenPin(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2096 NSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2097 {
2098 KMF_RETURN ret = KMF_OK;
2099 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2100 int rv;
2101 PK11SlotInfo *nss_slot = NULL;
2102 KMF_CREDENTIAL oldcred, newcred;
2103
2104 if (handle == NULL || attrlist == NULL || numattr == 0)
2105 return (KMF_ERR_BAD_PARAMETER);
2106
2107 ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2108 (void *)&oldcred, NULL);
2109 if (ret != KMF_OK)
2110 return (KMF_ERR_BAD_PARAMETER);
2111 ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr,
2112 (void *)&newcred, NULL);
2113 if (ret != KMF_OK)
2114 return (KMF_ERR_BAD_PARAMETER);
2115
2116 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2117 /* If it was uninitialized, set it */
2118 if (ret == KMF_ERR_UNINITIALIZED_TOKEN) {
2119 rv = PK11_InitPin(nss_slot, NULL, newcred.cred);
2120 if (rv != SECSuccess) {
2121 SET_ERROR(kmfh, PORT_GetError());
2122 ret = KMF_ERR_AUTH_FAILED;
2123 } else {
2124 ret = KMF_OK;
2125 }
2126 } else if (ret == KMF_OK) {
2127 ret = nss_authenticate(handle, nss_slot, &oldcred);
2128 if (ret != KMF_OK) {
2129 return (ret);
2130 }
2131 rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred);
2132 if (rv != SECSuccess) {
2133 SET_ERROR(kmfh, PORT_GetError());
2134 ret = KMF_ERR_AUTH_FAILED;
2135 }
2136 }
2137
2138 return (ret);
2139 }
2140
2141 KMF_RETURN
NSS_StoreKey(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2142 NSS_StoreKey(KMF_HANDLE_T handle,
2143 int numattr, KMF_ATTRIBUTE *attrlist)
2144 {
2145 KMF_RETURN rv = KMF_OK;
2146 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2147 PK11SlotInfo *nss_slot = NULL;
2148 KMF_CREDENTIAL cred = { NULL, 0 };
2149 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL;
2150 KMF_RAW_KEY_DATA *rawkey = NULL;
2151 char *keylabel = NULL;
2152 SECStatus ckrv = SECSuccess;
2153 SECItem nickname = { siBuffer, NULL, 0 };
2154 CERTCertificate *nss_cert = NULL;
2155
2156 if (kmfh == NULL || attrlist == NULL || numattr == 0) {
2157 return (KMF_ERR_BAD_PARAMETER);
2158 }
2159
2160 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2161 if (rv != KMF_OK) {
2162 return (rv);
2163 }
2164
2165 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr,
2166 (void *)&cred, NULL);
2167 if (rv != KMF_OK)
2168 return (KMF_ERR_BAD_PARAMETER);
2169
2170 rv = nss_authenticate(handle, nss_slot, &cred);
2171 if (rv != KMF_OK) {
2172 return (rv);
2173 }
2174
2175 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr);
2176 if (pubkey == NULL) {
2177 /* look for private key */
2178 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist,
2179 numattr);
2180 if (prikey == NULL)
2181 /* look for raw key */
2182 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR,
2183 attrlist, numattr);
2184 }
2185
2186 /* If no keys were found, return error */
2187 if (pubkey == NULL && prikey == NULL && rawkey == NULL)
2188 return (KMF_ERR_ATTR_NOT_FOUND);
2189
2190 keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr);
2191 if (keylabel != NULL) {
2192 nickname.data = (uchar_t *)keylabel;
2193 nickname.len = strlen(keylabel);
2194 }
2195
2196 if (rawkey != NULL) {
2197 uchar_t ver = 0;
2198 SECKEYPrivateKeyInfo rpk;
2199 KMF_DATA derkey = { 0, NULL };
2200 KMF_DATA *cert;
2201
2202 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2203 if (cert == NULL)
2204 return (rv);
2205 /*
2206 * Decode the cert into an NSS CERT object so we can access the
2207 * SPKI and KeyUsage data later.
2208 */
2209 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2210 cert->Length);
2211
2212 if (nss_cert == NULL) {
2213 SET_ERROR(kmfh, PORT_GetError());
2214 rv = KMF_ERR_BAD_CERT_FORMAT;
2215 goto cleanup;
2216 }
2217
2218 (void) memset(&rpk, 0, sizeof (rpk));
2219 rpk.arena = NULL;
2220 rpk.version.type = siUnsignedInteger;
2221 rpk.version.data = &ver;
2222 rpk.version.len = 1;
2223 if (rawkey->keytype == KMF_RSA) {
2224 rv = DerEncodeRSAPrivateKey(&derkey,
2225 &rawkey->rawdata.rsa);
2226 if (rv != KMF_OK)
2227 goto cleanup;
2228 } else if (rawkey->keytype == KMF_DSA) {
2229 rv = DerEncodeDSAPrivateKey(&derkey,
2230 &rawkey->rawdata.dsa);
2231 if (rv != KMF_OK)
2232 goto cleanup;
2233 } else if (rawkey->keytype == KMF_ECDSA) {
2234 rv = DerEncodeECPrivateKey(&derkey,
2235 &rawkey->rawdata.ec);
2236 if (rv != KMF_OK)
2237 goto cleanup;
2238 }
2239 rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
2240 rpk.privateKey.data = derkey.Data;
2241 rpk.privateKey.len = derkey.Length;
2242 rpk.attributes = NULL;
2243
2244 ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname,
2245 &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE,
2246 TRUE, nss_cert->keyUsage, NULL);
2247 if (ckrv != CKR_OK) {
2248 SET_ERROR(kmfh, PORT_GetError());
2249 rv = KMF_ERR_INTERNAL;
2250 }
2251 kmf_free_data(&derkey);
2252 } else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) {
2253 CK_OBJECT_HANDLE pk;
2254 SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp;
2255
2256 pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE);
2257 if (pk == CK_INVALID_HANDLE) {
2258 SET_ERROR(kmfh, PORT_GetError());
2259 rv = KMF_ERR_INTERNAL;
2260 }
2261 } else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) {
2262 SECKEYPrivateKey *pk;
2263 SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp;
2264
2265 pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE,
2266 PR_TRUE);
2267 if (pk == CK_INVALID_HANDLE) {
2268 SET_ERROR(kmfh, PORT_GetError());
2269 rv = KMF_ERR_INTERNAL;
2270 }
2271 /* We stored it, but don't need the handle anymore */
2272 SECKEY_DestroyPrivateKey(pk);
2273 }
2274
2275 cleanup:
2276 if (nss_cert != NULL)
2277 CERT_DestroyCertificate(nss_cert);
2278 PK11_FreeSlot(nss_slot);
2279 return (rv);
2280 }
2281
2282 /*
2283 * This function is called by NSS_StoreCert() and NSS_ImportCert().
2284 * The "label" and "trust_flag" arguments can be NULL.
2285 */
2286 static KMF_RETURN
store_cert(KMF_HANDLE_T handle,PK11SlotInfo * nss_slot,KMF_DATA * cert,char * label,char * trust_flag)2287 store_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert,
2288 char *label, char *trust_flag)
2289 {
2290 KMF_RETURN ret = KMF_OK;
2291 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2292 SECStatus nss_rv;
2293 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2294 CERTCertificate *nss_cert = NULL;
2295 CERTCertTrust *nss_trust = NULL;
2296
2297 if (nss_slot == NULL || cert == NULL)
2298 return (KMF_ERR_BAD_PARAMETER);
2299
2300 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data,
2301 cert->Length);
2302 if (nss_cert == NULL) {
2303 SET_ERROR(kmfh, PORT_GetError());
2304 ret = KMF_ERR_BAD_CERT_FORMAT;
2305 goto out;
2306 }
2307
2308 /* Store the cert into the NSS database */
2309 nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE,
2310 label, 0);
2311 if (nss_rv) {
2312 SET_ERROR(kmfh, nss_rv);
2313 ret = KMF_ERR_BAD_CERT_FORMAT;
2314 goto out;
2315 }
2316
2317 /* If trust_flag is NULL, then we are done */
2318 if (trust_flag == NULL)
2319 goto out;
2320
2321 nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust));
2322 if (nss_trust == NULL) {
2323 ret = KMF_ERR_MEMORY;
2324 goto out;
2325 }
2326
2327 nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag);
2328 if (nss_rv) {
2329 SET_ERROR(kmfh, nss_rv);
2330 ret = KMF_ERR_BAD_PARAMETER;
2331 goto out;
2332 }
2333
2334 nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust);
2335 if (nss_rv) {
2336 SET_ERROR(kmfh, nss_rv);
2337 ret = KMF_ERR_BAD_PARAMETER;
2338 }
2339
2340 out:
2341 if (nss_cert != NULL) {
2342 CERT_DestroyCertificate(nss_cert);
2343 }
2344
2345 if (nss_trust != NULL) {
2346 free(nss_trust);
2347 }
2348
2349 return (ret);
2350 }
2351
2352
2353 KMF_RETURN
NSS_StoreCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2354 NSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2355 {
2356 KMF_RETURN ret = KMF_OK;
2357 PK11SlotInfo *nss_slot = NULL;
2358 KMF_DATA *cert = NULL;
2359 char *label = NULL;
2360 char *trust_flag = NULL;
2361
2362 if (handle == NULL || attrlist == NULL || numattr == 0) {
2363 return (KMF_ERR_BAD_PARAMETER);
2364 }
2365
2366 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2367 if (ret != KMF_OK)
2368 return (ret);
2369
2370 /* Get the cert data */
2371 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
2372 if (cert == NULL || cert->Data == NULL)
2373 return (KMF_ERR_BAD_PARAMETER);
2374
2375 /* The label attribute is optional */
2376 label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2377
2378 /* The trustflag attriburte is optional */
2379 trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2380
2381 ret = store_cert(handle, nss_slot, cert, label, trust_flag);
2382
2383 out:
2384 if (nss_slot != NULL) {
2385 PK11_FreeSlot(nss_slot);
2386 }
2387
2388 return (ret);
2389 }
2390
2391
2392 KMF_RETURN
NSS_ImportCert(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2393 NSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2394 {
2395 KMF_RETURN ret = KMF_OK;
2396 PK11SlotInfo *nss_slot = NULL;
2397 KMF_DATA cert = { 0, NULL };
2398 KMF_DATA cert_der = { 0, NULL };
2399 KMF_DATA *cptr = NULL;
2400 KMF_ENCODE_FORMAT format;
2401 char *label = NULL;
2402 char *trust_flag = NULL;
2403 char *certfile = NULL;
2404
2405 if (handle == NULL || attrlist == NULL || numattr == 0) {
2406 return (KMF_ERR_BAD_PARAMETER);
2407 }
2408
2409 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2410 if (ret != KMF_OK)
2411 return (ret);
2412
2413 /* Get the input cert filename attribute */
2414 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr);
2415 if (certfile == NULL)
2416 return (KMF_ERR_BAD_PARAMETER);
2417
2418 /* Check the cert file and auto-detect the file format of it. */
2419 ret = kmf_is_cert_file(handle, certfile, &format);
2420 if (ret != KMF_OK)
2421 return (ret);
2422
2423 ret = kmf_read_input_file(handle, certfile, &cert);
2424 if (ret != KMF_OK) {
2425 return (ret);
2426 }
2427
2428 /*
2429 * If the imported cert is in PEM format, convert it to
2430 * DER format in order to store it in NSS token.
2431 */
2432 if (format == KMF_FORMAT_PEM) {
2433 int derlen;
2434 ret = kmf_pem_to_der(cert.Data, cert.Length,
2435 &cert_der.Data, &derlen);
2436 if (ret != KMF_OK) {
2437 goto cleanup;
2438 }
2439 cert_der.Length = (size_t)derlen;
2440 cptr = &cert_der;
2441 } else {
2442 cptr = &cert;
2443 }
2444
2445 label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2446 trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr);
2447 ret = store_cert(handle, nss_slot, cptr, label, trust_flag);
2448
2449 cleanup:
2450 if (format == KMF_FORMAT_PEM) {
2451 kmf_free_data(&cert_der);
2452 }
2453
2454 kmf_free_data(&cert);
2455
2456 return (ret);
2457 }
2458
2459
2460 KMF_RETURN
NSS_ImportCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2461 NSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2462 {
2463 KMF_RETURN ret = KMF_OK;
2464 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2465 PK11SlotInfo *nss_slot = NULL;
2466 CERTSignedCrl *nss_crl = NULL;
2467 KMF_ENCODE_FORMAT format;
2468 int importOptions;
2469 SECItem crlDER;
2470 KMF_DATA crl1;
2471 KMF_DATA crl2;
2472 char *crlfilename;
2473 boolean_t crlcheck = FALSE;
2474
2475 if (attrlist == NULL || numattr == 0) {
2476 return (KMF_ERR_BAD_PARAMETER);
2477 }
2478
2479 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2480 if (ret != KMF_OK) {
2481 return (ret);
2482 }
2483
2484 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist,
2485 numattr);
2486 if (crlfilename == NULL)
2487 return (KMF_ERR_BAD_CRLFILE);
2488
2489 /*
2490 * Check if the input CRL file is a valid CRL file and auto-detect
2491 * the encoded format of the file.
2492 */
2493 ret = kmf_is_crl_file(handle, crlfilename, &format);
2494 if (ret != KMF_OK)
2495 return (ret);
2496
2497 ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr,
2498 &crlcheck, NULL);
2499 if (ret != KMF_OK)
2500 ret = KMF_OK; /* CRL_CHECK is optional */
2501
2502 /* set importOptions */
2503 if (crlcheck == B_FALSE) {
2504 importOptions = CRL_IMPORT_DEFAULT_OPTIONS |
2505 CRL_IMPORT_BYPASS_CHECKS;
2506 } else {
2507 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
2508 }
2509
2510
2511 /* Read in the CRL file */
2512 crl1.Data = NULL;
2513 crl2.Data = NULL;
2514 ret = kmf_read_input_file(handle, crlfilename, &crl1);
2515 if (ret != KMF_OK) {
2516 return (ret);
2517 }
2518
2519 /* If the input CRL is in PEM format, convert it to DER first. */
2520 if (format == KMF_FORMAT_PEM) {
2521 int len;
2522 ret = kmf_pem_to_der(crl1.Data, crl1.Length,
2523 &crl2.Data, &len);
2524 if (ret != KMF_OK) {
2525 goto out;
2526 }
2527 crl2.Length = (size_t)len;
2528 }
2529
2530 crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data;
2531 crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length;
2532
2533 nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE,
2534 NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS);
2535
2536 if (nss_crl == NULL) {
2537 SET_ERROR(kmfh, PORT_GetError());
2538 ret = KMF_ERR_BAD_CRLFILE;
2539 goto out;
2540 }
2541
2542 out:
2543 if (nss_slot != NULL) {
2544 PK11_FreeSlot(nss_slot);
2545 }
2546
2547 if (crl1.Data != NULL) {
2548 free(crl1.Data);
2549 }
2550
2551 if (crl2.Data != NULL) {
2552 free(crl2.Data);
2553 }
2554
2555 if (nss_crl != NULL) {
2556 (void) SEC_DestroyCrl(nss_crl);
2557 }
2558
2559 return (ret);
2560 }
2561
2562 KMF_RETURN
NSS_DeleteCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2563 NSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2564 {
2565 KMF_RETURN rv = KMF_OK;
2566 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2567 CERTSignedCrl *crl = NULL;
2568 CERTCertificate *cert = NULL;
2569 PK11SlotInfo *nss_slot = NULL;
2570 CERTCrlHeadNode *crlList = NULL;
2571 CERTCrlNode *crlNode = NULL;
2572 PRArenaPool *arena = NULL;
2573 CERTName *name = NULL;
2574 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2575 char *issuername, *subjectname;
2576
2577 /* check params */
2578 if (numattr == 0 || attrlist == NULL) {
2579 return (KMF_ERR_BAD_PARAMETER);
2580 }
2581
2582 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2583 if (rv != KMF_OK) {
2584 return (rv);
2585 }
2586
2587 issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist,
2588 numattr);
2589 subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist,
2590 numattr);
2591
2592 /* Caller must specify issuer or subject but not both */
2593 if ((issuername == NULL && subjectname == NULL) ||
2594 (issuername != NULL && subjectname != NULL))
2595 return (KMF_ERR_BAD_PARAMETER);
2596
2597 /* Find the CRL based on the deletion criteria. */
2598 if (issuername != NULL) {
2599 /*
2600 * If the deletion is based on the issuer's certificate
2601 * nickname, we will get the issuer's cert first, then
2602 * get the CRL from the cert.
2603 */
2604 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2605 issuername);
2606 if (!cert) {
2607 SET_ERROR(kmfh, PORT_GetError());
2608 rv = KMF_ERR_CERT_NOT_FOUND;
2609 goto out;
2610 }
2611
2612 crl = SEC_FindCrlByName(certHandle, &cert->derSubject,
2613 SEC_CRL_TYPE);
2614 if (crl == NULL) {
2615 SET_ERROR(kmfh, PORT_GetError());
2616 rv = KMF_ERR_CRL_NOT_FOUND;
2617 goto out;
2618 }
2619 } else {
2620 /*
2621 * If the deletion is based on the CRL's subject name, we will
2622 * get all the CRLs from the internal database and search
2623 * for the CRL with the same subject name.
2624 */
2625 boolean_t found = B_FALSE;
2626 int nssrv;
2627
2628 nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2629 if (nssrv) {
2630 SET_ERROR(kmfh, nssrv);
2631 rv = KMF_ERR_CRL_NOT_FOUND;
2632 goto out;
2633 }
2634
2635 if (crlList == NULL) {
2636 SET_ERROR(kmfh, PORT_GetError());
2637 rv = KMF_ERR_CRL_NOT_FOUND;
2638 goto out;
2639 }
2640
2641 /* Allocate space for name */
2642 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2643 if (arena == NULL) {
2644 rv = KMF_ERR_MEMORY;
2645 goto out;
2646 }
2647
2648 name = PORT_ArenaZAlloc(arena, sizeof (*name));
2649 if (name == NULL) {
2650 rv = KMF_ERR_MEMORY;
2651 goto out;
2652 }
2653 name->arena = arena;
2654
2655 crlNode = crlList->first;
2656 while (crlNode && !found) {
2657 char *asciiname = NULL;
2658 SECItem* issuer;
2659
2660 name = &crlNode->crl->crl.name;
2661 if (!name) {
2662 SET_ERROR(kmfh, PORT_GetError());
2663 rv = KMF_ERR_CRL_NOT_FOUND;
2664 break;
2665 }
2666
2667 asciiname = CERT_NameToAscii(name);
2668 if (asciiname == NULL) {
2669 SET_ERROR(kmfh, PORT_GetError());
2670 rv = KMF_ERR_CRL_NOT_FOUND;
2671 break;
2672 }
2673
2674 if (strcmp(subjectname, asciiname) == 0) {
2675 found = B_TRUE;
2676 issuer = &crlNode->crl->crl.derName;
2677 crl = SEC_FindCrlByName(certHandle, issuer,
2678 SEC_CRL_TYPE);
2679 if (crl == NULL) {
2680 /* We found a cert but no CRL */
2681 SET_ERROR(kmfh, PORT_GetError());
2682 rv = KMF_ERR_CRL_NOT_FOUND;
2683 }
2684 }
2685 PORT_Free(asciiname);
2686 crlNode = crlNode->next;
2687 }
2688
2689 if (rv) {
2690 goto out;
2691 }
2692 }
2693
2694 if (crl) {
2695 (void) SEC_DeletePermCRL(crl);
2696 }
2697
2698 out:
2699 if (nss_slot != NULL) {
2700 PK11_FreeSlot(nss_slot);
2701 }
2702
2703 if (crlList != NULL) {
2704 PORT_FreeArena(crlList->arena, PR_FALSE);
2705 }
2706
2707 if (arena != NULL) {
2708 PORT_FreeArena(arena, PR_FALSE);
2709 }
2710
2711 if (cert != NULL) {
2712 CERT_DestroyCertificate(cert);
2713 }
2714
2715 if (crl != NULL) {
2716 (void) SEC_DestroyCrl(crl);
2717 }
2718
2719 return (rv);
2720 }
2721
2722 KMF_RETURN
NSS_FindCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2723 NSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2724 {
2725 KMF_RETURN rv = KMF_OK;
2726 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2727 PK11SlotInfo *nss_slot = NULL;
2728 CERTCrlHeadNode *crlList = NULL;
2729 CERTCrlNode *crlNode = NULL;
2730 PRArenaPool *arena = NULL;
2731 CERTName *name = NULL;
2732 SECStatus nssrv;
2733 char *asciiname = NULL;
2734 int crl_num;
2735 int i, *CRLCount;
2736 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2737 char **CRLNameList;
2738
2739 if (numattr == 0 || attrlist == NULL) {
2740 return (KMF_ERR_BAD_PARAMETER);
2741 }
2742
2743 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2744 if (rv != KMF_OK) {
2745 return (rv);
2746 }
2747
2748 CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR, attrlist, numattr);
2749 if (CRLCount == NULL)
2750 return (KMF_ERR_BAD_PARAMETER);
2751
2752 CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR,
2753 attrlist, numattr);
2754
2755 /* Look up Crls */
2756 nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE);
2757 if (nssrv) {
2758 SET_ERROR(kmfh, rv);
2759 rv = KMF_ERR_CRL_NOT_FOUND;
2760 goto out;
2761 }
2762
2763 /* Allocate space for name first */
2764 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
2765 if (arena == NULL) {
2766 rv = KMF_ERR_MEMORY;
2767 goto out;
2768 }
2769
2770 name = PORT_ArenaZAlloc(arena, sizeof (*name));
2771 if (name == NULL) {
2772 rv = KMF_ERR_MEMORY;
2773 goto out;
2774 }
2775 name->arena = arena;
2776
2777 /*
2778 * Loop thru the crlList and create a crl list with CRL's subject name.
2779 */
2780 crlNode = crlList->first;
2781 crl_num = 0;
2782 while (crlNode) {
2783 char *subj_name;
2784
2785 /* Get the CRL subject name */
2786 name = &crlNode->crl->crl.name;
2787 if (!name) {
2788 SET_ERROR(kmfh, PORT_GetError());
2789 rv = KMF_ERR_CRL_NOT_FOUND;
2790 break;
2791 }
2792
2793
2794 if (CRLNameList != NULL) {
2795 asciiname = CERT_NameToAscii(name);
2796 if (asciiname == NULL) {
2797 SET_ERROR(kmfh, PORT_GetError());
2798 rv = KMF_ERR_CRL_NOT_FOUND;
2799 break;
2800 }
2801 subj_name = strdup(asciiname);
2802 PORT_Free(asciiname);
2803 if (subj_name == NULL) {
2804 rv = KMF_ERR_MEMORY;
2805 break;
2806 }
2807 CRLNameList[crl_num] = subj_name;
2808 }
2809
2810 crl_num++;
2811 crlNode = crlNode->next;
2812 }
2813
2814 if (rv == KMF_OK) {
2815 /* success */
2816 *CRLCount = crl_num;
2817 }
2818
2819 out:
2820 if (nss_slot != NULL) {
2821 PK11_FreeSlot(nss_slot);
2822 }
2823
2824 if (crlList != NULL) {
2825 PORT_FreeArena(crlList->arena, PR_FALSE);
2826 }
2827
2828 if (arena != NULL) {
2829 PORT_FreeArena(arena, PR_FALSE);
2830 }
2831
2832 /* If failed, free memory allocated for the returning rlist */
2833 if (rv && (CRLNameList != NULL)) {
2834 for (i = 0; i < crl_num; i++) {
2835 free(CRLNameList[i]);
2836 }
2837 }
2838
2839 return (rv);
2840 }
2841
2842 KMF_RETURN
NSS_FindCertInCRL(KMF_HANDLE_T handle,int numattr,KMF_ATTRIBUTE * attrlist)2843 NSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
2844 {
2845 KMF_RETURN rv = KMF_OK;
2846 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
2847 PK11SlotInfo *nss_slot = NULL;
2848 CERTCertificate *cert = NULL;
2849 CERTSignedCrl *crl = NULL;
2850 CERTCrlEntry *entry;
2851 boolean_t match = B_FALSE;
2852 int i;
2853 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
2854 char *certlabel;
2855 KMF_DATA *certdata;
2856
2857 /* check params */
2858 if (numattr == 0 || attrlist == NULL) {
2859 return (KMF_ERR_BAD_PARAMETER);
2860 }
2861
2862 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot);
2863 if (rv != KMF_OK) {
2864 return (rv);
2865 }
2866
2867 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr);
2868
2869 /* Find the certificate first */
2870 if (certlabel != NULL) {
2871 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle,
2872 certlabel);
2873 } else {
2874 SECItem derCert = { siBuffer, NULL, 0 };
2875
2876 certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR,
2877 attrlist, numattr);
2878
2879 if (certdata == NULL)
2880 return (KMF_ERR_BAD_PARAMETER);
2881
2882 derCert.data = certdata->Data;
2883 derCert.len = certdata->Length;
2884
2885 cert = CERT_FindCertByDERCert(certHandle, &derCert);
2886 }
2887
2888 if (cert == NULL) {
2889 SET_ERROR(kmfh, PORT_GetError());
2890 rv = KMF_ERR_CERT_NOT_FOUND;
2891 goto out;
2892 }
2893
2894 /* Find the CRL with the same issuer as the given certificate. */
2895 crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE);
2896 if (crl == NULL) {
2897 /*
2898 * Could not find the CRL issued by the same issuer. This
2899 * usually means that the CRL is not installed in the DB.
2900 */
2901 SET_ERROR(kmfh, PORT_GetError());
2902 rv = KMF_ERR_CRL_NOT_FOUND;
2903 goto out;
2904
2905 }
2906
2907 /* Check if the certificate's serialNumber is revoked in the CRL */
2908 i = 0;
2909 while ((entry = (crl->crl).entries[i++]) != NULL) {
2910 if (SECITEM_CompareItem(&(cert->serialNumber),
2911 &(entry->serialNumber)) == SECEqual) {
2912 match = B_TRUE;
2913 break;
2914 }
2915 }
2916
2917 if (!match) {
2918 rv = KMF_ERR_NOT_REVOKED;
2919 }
2920
2921 out:
2922 if (nss_slot != NULL) {
2923 PK11_FreeSlot(nss_slot);
2924 }
2925
2926 if (cert != NULL) {
2927 CERT_DestroyCertificate(cert);
2928 }
2929
2930 if (crl != NULL) {
2931 (void) SEC_DestroyCrl(crl);
2932 }
2933
2934 return (rv);
2935 }
2936