Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / pk11wrap / pk11nobj.c
blobd94820bc4ae3b952387a41ffb9029b750f3466af
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects,
38 * etc).
41 #include "secport.h"
42 #include "seccomon.h"
43 #include "secmod.h"
44 #include "secmodi.h"
45 #include "secmodti.h"
46 #include "pkcs11.h"
47 #include "pk11func.h"
48 #include "cert.h"
49 #include "certi.h"
50 #include "secitem.h"
51 #include "sechash.h"
52 #include "secoid.h"
54 #include "certdb.h"
55 #include "secerr.h"
56 #include "sslerr.h"
58 #include "pki3hack.h"
59 #include "dev3hack.h"
61 #include "devm.h"
62 #include "pki.h"
63 #include "pkim.h"
65 extern const NSSError NSS_ERROR_NOT_FOUND;
67 CK_TRUST
68 pk11_GetTrustField(PK11SlotInfo *slot, PRArenaPool *arena,
69 CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type)
71 CK_TRUST rv = 0;
72 SECItem item;
74 item.data = NULL;
75 item.len = 0;
77 if( SECSuccess == PK11_ReadAttribute(slot, id, type, arena, &item) ) {
78 PORT_Assert(item.len == sizeof(CK_TRUST));
79 PORT_Memcpy(&rv, item.data, sizeof(CK_TRUST));
80 /* Damn, is there an endian problem here? */
81 return rv;
84 return 0;
87 PRBool
88 pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
90 PRArenaPool *arena;
92 CK_ATTRIBUTE tobjTemplate[] = {
93 { CKA_CLASS, NULL, 0 },
94 { CKA_CERT_SHA1_HASH, NULL, 0 },
97 CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
98 CK_OBJECT_HANDLE tobjID;
99 unsigned char sha1_hash[SHA1_LENGTH];
101 CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth;
103 PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);
105 PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
106 PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash,
107 SHA1_LENGTH);
109 tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate,
110 sizeof(tobjTemplate)/sizeof(tobjTemplate[0]));
111 if( CK_INVALID_HANDLE == tobjID ) {
112 return PR_FALSE;
115 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
116 if( NULL == arena ) return PR_FALSE;
118 /* Unfortunately, it seems that PK11_GetAttributes doesn't deal
119 * well with nonexistant attributes. I guess we have to check
120 * the trust info fields one at a time.
123 /* We could verify CKA_CERT_HASH here */
125 /* We could verify CKA_EXPIRES here */
128 /* "Purpose" trust information */
129 serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
130 clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH);
131 codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
132 emailProtection = pk11_GetTrustField(slot, arena, tobjID,
133 CKA_TRUST_EMAIL_PROTECTION);
134 /* Here's where the fun logic happens. We have to map back from the
135 * key usage, extended key usage, purpose, and possibly other trust values
136 * into the old trust-flags bits. */
138 /* First implementation: keep it simple for testing. We can study what other
139 * mappings would be appropriate and add them later.. fgmr 20000724 */
141 if ( serverAuth == CKT_NETSCAPE_TRUSTED ) {
142 trust->sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
145 if ( serverAuth == CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
146 trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA |
147 CERTDB_NS_TRUSTED_CA;
149 if ( clientAuth == CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
150 trust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA ;
153 if ( emailProtection == CKT_NETSCAPE_TRUSTED ) {
154 trust->emailFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
157 if ( emailProtection == CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
158 trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
161 if( codeSigning == CKT_NETSCAPE_TRUSTED ) {
162 trust->objectSigningFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
165 if( codeSigning == CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
166 trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
169 /* There's certainly a lot more logic that can go here.. */
171 PORT_FreeArena(arena, PR_FALSE);
173 return PR_TRUE;
176 static SECStatus
177 pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg)
179 SECItem derCrl;
180 CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg;
181 CERTCrlNode *new_node = NULL;
182 CK_ATTRIBUTE fetchCrl[3] = {
183 { CKA_VALUE, NULL, 0},
184 { CKA_NETSCAPE_KRL, NULL, 0},
185 { CKA_NETSCAPE_URL, NULL, 0},
187 const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
188 CK_RV crv;
189 SECStatus rv = SECFailure;
191 crv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize);
192 if (CKR_OK != crv) {
193 PORT_SetError(PK11_MapError(crv));
194 goto loser;
197 if (!fetchCrl[1].pValue) {
198 PORT_SetError(SEC_ERROR_CRL_INVALID);
199 goto loser;
202 new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode));
203 if (new_node == NULL) {
204 goto loser;
207 if (*((CK_BBOOL *)fetchCrl[1].pValue))
208 new_node->type = SEC_KRL_TYPE;
209 else
210 new_node->type = SEC_CRL_TYPE;
212 derCrl.type = siBuffer;
213 derCrl.data = (unsigned char *)fetchCrl[0].pValue;
214 derCrl.len = fetchCrl[0].ulValueLen;
215 new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type);
216 if (new_node->crl == NULL) {
217 goto loser;
220 if (fetchCrl[2].pValue) {
221 int nnlen = fetchCrl[2].ulValueLen;
222 new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen+1);
223 if ( !new_node->crl->url ) {
224 goto loser;
226 PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
227 new_node->crl->url[nnlen] = 0;
228 } else {
229 new_node->crl->url = NULL;
233 new_node->next = NULL;
234 if (head->last) {
235 head->last->next = new_node;
236 head->last = new_node;
237 } else {
238 head->first = head->last = new_node;
240 rv = SECSuccess;
242 loser:
243 return(rv);
247 * Return a list of all the CRLs .
248 * CRLs are allocated in the list's arena.
250 SECStatus
251 PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
252 pk11TraverseSlot creater;
253 CK_ATTRIBUTE theTemplate[2];
254 CK_ATTRIBUTE *attrs;
255 CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL;
256 CK_BBOOL isKrl = CK_FALSE;
258 attrs = theTemplate;
259 PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++;
260 if (type != -1) {
261 isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE);
262 PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++;
265 creater.callback = pk11_CollectCrls;
266 creater.callbackArg = (void *) nodes;
267 creater.findTemplate = theTemplate;
268 creater.templateCount = (attrs - theTemplate);
270 return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
273 struct crlOptionsStr {
274 CERTCrlHeadNode* head;
275 PRInt32 decodeOptions;
278 typedef struct crlOptionsStr crlOptions;
280 static SECStatus
281 pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
282 void *arg)
284 SECItem* derCrl = NULL;
285 crlOptions* options = (crlOptions*) arg;
286 CERTCrlHeadNode *head = options->head;
287 CERTCrlNode *new_node = NULL;
288 CK_ATTRIBUTE fetchCrl[3] = {
289 { CKA_VALUE, NULL, 0},
290 { CKA_NETSCAPE_KRL, NULL, 0},
291 { CKA_NETSCAPE_URL, NULL, 0},
293 const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
294 CK_RV crv;
295 SECStatus rv = SECFailure;
296 PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
297 successfully */
298 int i;
300 crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize);
301 if (CKR_OK != crv) {
302 PORT_SetError(PK11_MapError(crv));
303 goto loser;
306 if (!fetchCrl[1].pValue) {
307 /* reject KRLs */
308 PORT_SetError(SEC_ERROR_CRL_INVALID);
309 goto loser;
312 new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
313 sizeof(CERTCrlNode));
314 if (new_node == NULL) {
315 goto loser;
318 new_node->type = SEC_CRL_TYPE;
320 derCrl = SECITEM_AllocItem(NULL, NULL, 0);
321 if (!derCrl) {
322 goto loser;
324 derCrl->type = siBuffer;
325 derCrl->data = (unsigned char *)fetchCrl[0].pValue;
326 derCrl->len = fetchCrl[0].ulValueLen;
327 new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type,
328 options->decodeOptions);
329 if (new_node->crl == NULL) {
330 goto loser;
332 adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
333 we won't need to free it upon exit */
335 if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
336 /* copy the URL if there is one */
337 int nnlen = fetchCrl[2].ulValueLen;
338 new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena,
339 nnlen+1);
340 if ( !new_node->crl->url ) {
341 goto loser;
343 PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
344 new_node->crl->url[nnlen] = 0;
345 } else {
346 new_node->crl->url = NULL;
349 new_node->next = NULL;
350 if (head->last) {
351 head->last->next = new_node;
352 head->last = new_node;
353 } else {
354 head->first = head->last = new_node;
356 rv = SECSuccess;
357 new_node->crl->slot = PK11_ReferenceSlot(slot);
358 new_node->crl->pkcs11ID = crlID;
360 loser:
361 /* free attributes that weren't adopted by the CRL */
362 for (i=1;i<fetchCrlSize;i++) {
363 if (fetchCrl[i].pValue) {
364 PORT_Free(fetchCrl[i].pValue);
367 /* free the DER if the CRL object didn't adopt it */
368 if (fetchCrl[0].pValue && PR_FALSE == adopted) {
369 PORT_Free(fetchCrl[0].pValue);
371 if (derCrl && !adopted) {
372 /* clear the data fields, which we already took care of above */
373 derCrl->data = NULL;
374 derCrl->len = 0;
375 /* free the memory for the SECItem structure itself */
376 SECITEM_FreeItem(derCrl, PR_TRUE);
378 return(rv);
382 * Return a list of CRLs matching specified issuer and type
383 * CRLs are not allocated in the list's arena, but rather in their own,
384 * arena, so that they can be used individually in the CRL cache .
385 * CRLs are always partially decoded for efficiency.
387 SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
388 void *wincx)
390 pk11TraverseSlot creater;
391 CK_ATTRIBUTE theTemplate[2];
392 CK_ATTRIBUTE *attrs;
393 CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL;
394 crlOptions options;
396 attrs = theTemplate;
397 PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++;
399 options.head = nodes;
401 /* - do a partial decoding - we don't need to decode the entries while
402 fetching
403 - don't copy the DER for optimal performance - CRL can be very large
404 - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
405 - keep bad CRL objects. The CRL cache is interested in them, for
406 security purposes. Bad CRL objects are a sign of something amiss.
409 options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
410 CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
411 if (issuer)
413 PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); attrs++;
416 creater.callback = pk11_RetrieveCrlsCallback;
417 creater.callbackArg = (void *) &options;
418 creater.findTemplate = theTemplate;
419 creater.templateCount = (attrs - theTemplate);
421 return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
425 * return the crl associated with a derSubjectName
427 SECItem *
428 PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
429 SECItem *name, int type, char **pUrl)
431 NSSCRL **crls, **crlp, *crl = NULL;
432 NSSDER subject;
433 SECItem *rvItem;
434 NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
435 char * url = NULL;
437 PORT_SetError(0);
438 NSSITEM_FROM_SECITEM(&subject, name);
439 if (*slot) {
440 nssCryptokiObject **instances;
441 nssPKIObjectCollection *collection;
442 nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
443 NSSToken *token = PK11Slot_GetNSSToken(*slot);
444 collection = nssCRLCollection_Create(td, NULL);
445 if (!collection) {
446 goto loser;
448 instances = nssToken_FindCRLsBySubject(token, NULL, &subject,
449 tokenOnly, 0, NULL);
450 nssPKIObjectCollection_AddInstances(collection, instances, 0);
451 nss_ZFreeIf(instances);
452 crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
453 nssPKIObjectCollection_Destroy(collection);
454 } else {
455 crls = nssTrustDomain_FindCRLsBySubject(td, &subject);
457 if ((!crls) || (*crls == NULL)) {
458 if (crls) {
459 nssCRLArray_Destroy(crls);
461 if (NSS_GetError() == NSS_ERROR_NOT_FOUND) {
462 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
464 goto loser;
466 for (crlp = crls; *crlp; crlp++) {
467 if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) ||
468 ((*crlp)->isKRL && type != SEC_CRL_TYPE))
470 crl = nssCRL_AddRef(*crlp);
471 break;
474 nssCRLArray_Destroy(crls);
475 if (!crl) {
476 /* CRL collection was found, but no interesting CRL's were on it.
477 * Not an error */
478 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
479 goto loser;
481 if (crl->url) {
482 url = PORT_Strdup(crl->url);
483 if (!url) {
484 goto loser;
487 rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size);
488 if (!rvItem) {
489 goto loser;
491 memcpy(rvItem->data, crl->encoding.data, crl->encoding.size);
492 *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot);
493 *crlHandle = crl->object.instances[0]->handle;
494 *pUrl = url;
495 nssCRL_Destroy(crl);
496 return rvItem;
498 loser:
499 if (url)
500 PORT_Free(url);
501 if (crl)
502 nssCRL_Destroy(crl);
503 if (PORT_GetError() == 0) {
504 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
506 return NULL;
509 CK_OBJECT_HANDLE
510 PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name,
511 char *url, int type)
513 NSSItem derCRL, derSubject;
514 NSSToken *token = PK11Slot_GetNSSToken(slot);
515 nssCryptokiObject *object;
516 PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE;
517 CK_OBJECT_HANDLE rvH;
519 NSSITEM_FROM_SECITEM(&derSubject, name);
520 NSSITEM_FROM_SECITEM(&derCRL, crl);
522 object = nssToken_ImportCRL(token, NULL,
523 &derSubject, &derCRL, isKRL, url, PR_TRUE);
525 if (object) {
526 rvH = object->handle;
527 nssCryptokiObject_Destroy(object);
528 } else {
529 rvH = CK_INVALID_HANDLE;
531 return rvH;
536 * delete a crl.
538 SECStatus
539 SEC_DeletePermCRL(CERTSignedCrl *crl)
541 PRStatus status;
542 NSSToken *token;
543 nssCryptokiObject *object;
544 PK11SlotInfo *slot = crl->slot;
546 if (slot == NULL) {
547 PORT_Assert(slot);
548 /* shouldn't happen */
549 PORT_SetError( SEC_ERROR_CRL_INVALID);
550 return SECFailure;
552 token = PK11Slot_GetNSSToken(slot);
554 object = nss_ZNEW(NULL, nssCryptokiObject);
555 if (!object) {
556 return SECFailure;
558 object->token = nssToken_AddRef(token);
559 object->handle = crl->pkcs11ID;
560 object->isTokenObject = PR_TRUE;
562 status = nssToken_DeleteStoredObject(object);
564 nssCryptokiObject_Destroy(object);
565 return (status == PR_SUCCESS) ? SECSuccess : SECFailure;
569 * return the certificate associated with a derCert
571 SECItem *
572 PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
573 SECItem *name, SECItem **profileTime)
575 CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
576 CK_ATTRIBUTE theTemplate[] = {
577 { CKA_SUBJECT, NULL, 0 },
578 { CKA_CLASS, NULL, 0 },
579 { CKA_NETSCAPE_EMAIL, NULL, 0 },
581 CK_ATTRIBUTE smimeData[] = {
582 { CKA_SUBJECT, NULL, 0 },
583 { CKA_VALUE, NULL, 0 },
585 /* if you change the array, change the variable below as well */
586 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
587 CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
588 CK_ATTRIBUTE *attrs = theTemplate;
589 CK_RV crv;
590 SECItem *emailProfile = NULL;
592 if (!emailAddr || !emailAddr[0]) {
593 PORT_SetError(SEC_ERROR_INVALID_ARGS);
594 return NULL;
597 PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++;
598 PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
599 PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr));
600 attrs++;
602 if (*slot) {
603 smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize);
604 } else {
605 PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
606 PR_FALSE,PR_TRUE,NULL);
607 PK11SlotListElement *le;
609 if (!list) {
610 return NULL;
612 /* loop through all the slots */
613 for (le = list->head; le; le = le->next) {
614 smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize);
615 if (smimeh != CK_INVALID_HANDLE) {
616 *slot = PK11_ReferenceSlot(le->slot);
617 break;
620 PK11_FreeSlotList(list);
623 if (smimeh == CK_INVALID_HANDLE) {
624 PORT_SetError(SEC_ERROR_NO_KRL);
625 return NULL;
628 if (profileTime) {
629 PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0);
632 crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2);
633 if (crv != CKR_OK) {
634 PORT_SetError(PK11_MapError (crv));
635 goto loser;
638 if (!profileTime) {
639 SECItem profileSubject;
641 profileSubject.data = (unsigned char*) smimeData[0].pValue;
642 profileSubject.len = smimeData[0].ulValueLen;
643 if (!SECITEM_ItemsAreEqual(&profileSubject,name)) {
644 goto loser;
648 emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
649 if (emailProfile == NULL) {
650 goto loser;
653 emailProfile->data = (unsigned char*) smimeData[1].pValue;
654 emailProfile->len = smimeData[1].ulValueLen;
656 if (profileTime) {
657 *profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
658 if (*profileTime) {
659 (*profileTime)->data = (unsigned char*) smimeData[0].pValue;
660 (*profileTime)->len = smimeData[0].ulValueLen;
664 loser:
665 if (emailProfile == NULL) {
666 if (smimeData[1].pValue) {
667 PORT_Free(smimeData[1].pValue);
670 if (profileTime == NULL || *profileTime == NULL) {
671 if (smimeData[0].pValue) {
672 PORT_Free(smimeData[0].pValue);
675 return emailProfile;
679 SECStatus
680 PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
681 SECItem *emailProfile, SECItem *profileTime)
683 CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
684 CK_BBOOL ck_true = CK_TRUE;
685 CK_ATTRIBUTE theTemplate[] = {
686 { CKA_CLASS, NULL, 0 },
687 { CKA_TOKEN, NULL, 0 },
688 { CKA_SUBJECT, NULL, 0 },
689 { CKA_NETSCAPE_EMAIL, NULL, 0 },
690 { CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 },
691 { CKA_VALUE, NULL, 0 }
693 /* if you change the array, change the variable below as well */
694 int realSize = 0;
695 CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
696 CK_ATTRIBUTE *attrs = theTemplate;
697 CK_SESSION_HANDLE rwsession;
698 PK11SlotInfo *free_slot = NULL;
699 CK_RV crv;
700 #ifdef DEBUG
701 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
702 #endif
704 PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
705 PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); attrs++;
706 PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++;
707 PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL,
708 emailAddr, PORT_Strlen(emailAddr)+1); attrs++;
709 if (profileTime) {
710 PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data,
711 profileTime->len); attrs++;
712 PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data,
713 emailProfile->len); attrs++;
715 realSize = attrs - theTemplate;
716 PORT_Assert (realSize <= tsize);
718 if (slot == NULL) {
719 free_slot = slot = PK11_GetInternalKeySlot();
720 /* we need to free the key slot in the end!!! */
723 rwsession = PK11_GetRWSession(slot);
724 if (rwsession == CK_INVALID_SESSION) {
725 PORT_SetError(SEC_ERROR_READ_ONLY);
726 if (free_slot) {
727 PK11_FreeSlot(free_slot);
729 return SECFailure;
732 crv = PK11_GETTAB(slot)->
733 C_CreateObject(rwsession,theTemplate,realSize,&smimeh);
734 if (crv != CKR_OK) {
735 PORT_SetError( PK11_MapError(crv) );
738 PK11_RestoreROSession(slot,rwsession);
740 if (free_slot) {
741 PK11_FreeSlot(free_slot);
743 return SECSuccess;
747 CERTSignedCrl * crl_storeCRL (PK11SlotInfo *slot,char *url,
748 CERTSignedCrl *newCrl, SECItem *derCrl, int type);
750 /* import the CRL into the token */
752 CERTSignedCrl* PK11_ImportCRL(PK11SlotInfo * slot, SECItem *derCRL, char *url,
753 int type, void *wincx, PRInt32 importOptions, PRArenaPool* arena,
754 PRInt32 decodeoptions)
756 CERTSignedCrl *newCrl, *crl;
757 SECStatus rv;
758 CERTCertificate *caCert = NULL;
760 newCrl = crl = NULL;
762 do {
763 newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type,
764 decodeoptions);
765 if (newCrl == NULL) {
766 if (type == SEC_CRL_TYPE) {
767 /* only promote error when the error code is too generic */
768 if (PORT_GetError () == SEC_ERROR_BAD_DER)
769 PORT_SetError(SEC_ERROR_CRL_INVALID);
770 } else {
771 PORT_SetError(SEC_ERROR_KRL_INVALID);
773 break;
776 if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){
777 CERTCertDBHandle* handle = CERT_GetDefaultCertDB();
778 PR_ASSERT(handle != NULL);
779 caCert = CERT_FindCertByName (handle,
780 &newCrl->crl.derName);
781 if (caCert == NULL) {
782 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
783 break;
786 /* If caCert is a v3 certificate, make sure that it can be used for
787 crl signing purpose */
788 rv = CERT_CheckCertUsage (caCert, KU_CRL_SIGN);
789 if (rv != SECSuccess) {
790 break;
793 rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert,
794 PR_Now(), wincx);
795 if (rv != SECSuccess) {
796 if (type == SEC_CRL_TYPE) {
797 PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
798 } else {
799 PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
801 break;
805 crl = crl_storeCRL(slot, url, newCrl, derCRL, type);
807 } while (0);
809 if (crl == NULL) {
810 SEC_DestroyCrl (newCrl);
812 if (caCert) {
813 CERT_DestroyCertificate(caCert);
815 return (crl);