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