security/nss/lib/pk11wrap/pk11nobj.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 /*
     5  * This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects,
     6  * etc).
     7  */
     9 #include "secport.h"
    10 #include "seccomon.h"
    11 #include "secmod.h"
    12 #include "secmodi.h"
    13 #include "secmodti.h"
    14 #include "pkcs11.h"
    15 #include "pk11func.h"
    16 #include "cert.h"
    17 #include "certi.h" 
    18 #include "secitem.h"
    19 #include "sechash.h" 
    20 #include "secoid.h"
    22 #include "certdb.h" 
    23 #include "secerr.h"
    24 #include "sslerr.h"
    26 #include "pki3hack.h"
    27 #include "dev3hack.h" 
    29 #include "devm.h" 
    30 #include "pki.h"
    31 #include "pkim.h" 
    33 extern const NSSError NSS_ERROR_NOT_FOUND;
    35 CK_TRUST
    36 pk11_GetTrustField(PK11SlotInfo *slot, PLArenaPool *arena,
    37                    CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type)
    38 {
    39   CK_TRUST rv = 0;
    40   SECItem item;
    42   item.data = NULL;
    43   item.len = 0;
    45   if( SECSuccess == PK11_ReadAttribute(slot, id, type, arena, &item) ) {
    46     PORT_Assert(item.len == sizeof(CK_TRUST));
    47     PORT_Memcpy(&rv, item.data, sizeof(CK_TRUST));
    48     /* Damn, is there an endian problem here? */
    49     return rv;
    50   }
    52   return 0;
    53 }
    55 PRBool
    56 pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
    57 {
    58   PLArenaPool *arena;
    60   CK_ATTRIBUTE tobjTemplate[] = {
    61     { CKA_CLASS, NULL, 0 },
    62     { CKA_CERT_SHA1_HASH, NULL, 0 },
    63   };
    65   CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
    66   CK_OBJECT_HANDLE tobjID;
    67   unsigned char sha1_hash[SHA1_LENGTH];
    69   CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth;
    71   PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);
    73   PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
    74   PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash, 
    75                 SHA1_LENGTH);
    77   tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, 
    78                                      sizeof(tobjTemplate)/sizeof(tobjTemplate[0]));
    79   if( CK_INVALID_HANDLE == tobjID ) {
    80     return PR_FALSE;
    81   }
    83   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    84   if( NULL == arena ) return PR_FALSE;
    86   /* Unfortunately, it seems that PK11_GetAttributes doesn't deal
    87    * well with nonexistent attributes.  I guess we have to check 
    88    * the trust info fields one at a time.
    89    */
    91   /* We could verify CKA_CERT_HASH here */
    93   /* We could verify CKA_EXPIRES here */
    96   /* "Purpose" trust information */
    97   serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
    98   clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH);
    99   codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
   100   emailProtection = pk11_GetTrustField(slot, arena, tobjID, 
   101 						CKA_TRUST_EMAIL_PROTECTION);
   102   /* Here's where the fun logic happens.  We have to map back from the 
   103    * key usage, extended key usage, purpose, and possibly other trust values 
   104    * into the old trust-flags bits.  */
   106   /* First implementation: keep it simple for testing.  We can study what other
   107    * mappings would be appropriate and add them later.. fgmr 20000724 */
   109   if ( serverAuth ==  CKT_NSS_TRUSTED ) {
   110     trust->sslFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
   111   }
   113   if ( serverAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
   114     trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | 
   115 							CERTDB_NS_TRUSTED_CA;
   116   }
   117   if ( clientAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
   118     trust->sslFlags |=  CERTDB_TRUSTED_CLIENT_CA ;
   119   }
   121   if ( emailProtection == CKT_NSS_TRUSTED ) {
   122     trust->emailFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
   123   }
   125   if ( emailProtection == CKT_NSS_TRUSTED_DELEGATOR ) {
   126     trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
   127   }
   129   if( codeSigning == CKT_NSS_TRUSTED ) {
   130     trust->objectSigningFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
   131   }
   133   if( codeSigning == CKT_NSS_TRUSTED_DELEGATOR ) {
   134     trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
   135   }
   137   /* There's certainly a lot more logic that can go here.. */
   139   PORT_FreeArena(arena, PR_FALSE);
   141   return PR_TRUE;
   142 }
   144 static SECStatus
   145 pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg)
   146 {
   147     SECItem derCrl;
   148     CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg;
   149     CERTCrlNode *new_node = NULL;
   150     CK_ATTRIBUTE fetchCrl[3] = {
   151 	 { CKA_VALUE, NULL, 0},
   152 	 { CKA_NETSCAPE_KRL, NULL, 0},
   153 	 { CKA_NETSCAPE_URL, NULL, 0},
   154     };
   155     const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
   156     CK_RV crv;
   157     SECStatus rv = SECFailure;
   159     crv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize);
   160     if (CKR_OK != crv) {
   161 	PORT_SetError(PK11_MapError(crv));
   162 	goto loser;
   163     }
   165     if (!fetchCrl[1].pValue) {
   166 	PORT_SetError(SEC_ERROR_CRL_INVALID);
   167 	goto loser;
   168     }
   170     new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode));
   171     if (new_node == NULL) {
   172         goto loser;
   173     }
   175     if (*((CK_BBOOL *)fetchCrl[1].pValue))
   176         new_node->type = SEC_KRL_TYPE;
   177     else
   178         new_node->type = SEC_CRL_TYPE;
   180     derCrl.type = siBuffer;
   181     derCrl.data = (unsigned char *)fetchCrl[0].pValue;
   182     derCrl.len = fetchCrl[0].ulValueLen;
   183     new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type);
   184     if (new_node->crl == NULL) {
   185 	goto loser;
   186     }
   188     if (fetchCrl[2].pValue) {
   189         int nnlen = fetchCrl[2].ulValueLen;
   190         new_node->crl->url  = (char *)PORT_ArenaAlloc(head->arena, nnlen+1);
   191         if ( !new_node->crl->url ) {
   192             goto loser;
   193         }
   194         PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
   195         new_node->crl->url[nnlen] = 0;
   196     } else {
   197         new_node->crl->url = NULL;
   198     }
   201     new_node->next = NULL;
   202     if (head->last) {
   203         head->last->next = new_node;
   204         head->last = new_node;
   205     } else {
   206         head->first = head->last = new_node;
   207     }
   208     rv = SECSuccess;
   210 loser:
   211     return(rv);
   212 }
   214 /*
   215  * Return a list of all the CRLs .
   216  * CRLs are allocated in the list's arena.
   217  */
   218 SECStatus
   219 PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
   220     pk11TraverseSlot creater;
   221     CK_ATTRIBUTE theTemplate[2];
   222     CK_ATTRIBUTE *attrs;
   223     CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL;
   224     CK_BBOOL isKrl = CK_FALSE;
   226     attrs = theTemplate;
   227     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++;
   228     if (type != -1) {
   229 	isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE);
   230         PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++;
   231     }
   233     creater.callback = pk11_CollectCrls;
   234     creater.callbackArg = (void *) nodes;
   235     creater.findTemplate = theTemplate;
   236     creater.templateCount = (attrs - theTemplate);
   238     return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
   239 }
   241 struct crlOptionsStr {
   242     CERTCrlHeadNode* head;
   243     PRInt32 decodeOptions;
   244 };
   246 typedef struct crlOptionsStr crlOptions;
   248 static SECStatus
   249 pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
   250                           void *arg)
   251 {
   252     SECItem* derCrl = NULL;
   253     crlOptions* options = (crlOptions*) arg;
   254     CERTCrlHeadNode *head = options->head;
   255     CERTCrlNode *new_node = NULL;
   256     CK_ATTRIBUTE fetchCrl[3] = {
   257 	 { CKA_VALUE, NULL, 0},
   258 	 { CKA_NETSCAPE_KRL, NULL, 0},
   259 	 { CKA_NETSCAPE_URL, NULL, 0},
   260     };
   261     const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
   262     CK_RV crv;
   263     SECStatus rv = SECFailure;
   264     PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
   265                                   successfully */
   266     int i;
   268     crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize);
   269     if (CKR_OK != crv) {
   270 	PORT_SetError(PK11_MapError(crv));
   271 	goto loser;
   272     }
   274     if (!fetchCrl[1].pValue) {
   275         /* reject KRLs */
   276 	PORT_SetError(SEC_ERROR_CRL_INVALID);
   277 	goto loser;
   278     }
   280     new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
   281                                               sizeof(CERTCrlNode));
   282     if (new_node == NULL) {
   283         goto loser;
   284     }
   286     new_node->type = SEC_CRL_TYPE;
   288     derCrl = SECITEM_AllocItem(NULL, NULL, 0);
   289     if (!derCrl) {
   290         goto loser;
   291     }
   292     derCrl->type = siBuffer;
   293     derCrl->data = (unsigned char *)fetchCrl[0].pValue;
   294     derCrl->len = fetchCrl[0].ulValueLen;
   295     new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type,
   296                                                options->decodeOptions);
   297     if (new_node->crl == NULL) {
   298 	goto loser;
   299     }    
   300     adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
   301                           we won't need to free it upon exit */
   303     if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
   304         /* copy the URL if there is one */
   305         int nnlen = fetchCrl[2].ulValueLen;
   306         new_node->crl->url  = (char *)PORT_ArenaAlloc(new_node->crl->arena,
   307                                                       nnlen+1);
   308         if ( !new_node->crl->url ) {
   309             goto loser;
   310         }
   311         PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
   312         new_node->crl->url[nnlen] = 0;
   313     } else {
   314         new_node->crl->url = NULL;
   315     }
   317     new_node->next = NULL;
   318     if (head->last) {
   319         head->last->next = new_node;
   320         head->last = new_node;
   321     } else {
   322         head->first = head->last = new_node;
   323     }
   324     rv = SECSuccess;
   325     new_node->crl->slot = PK11_ReferenceSlot(slot);
   326     new_node->crl->pkcs11ID = crlID;
   328 loser:
   329     /* free attributes that weren't adopted by the CRL */
   330     for (i=1;i<fetchCrlSize;i++) {
   331         if (fetchCrl[i].pValue) {
   332             PORT_Free(fetchCrl[i].pValue);
   333         }
   334     }
   335     /* free the DER if the CRL object didn't adopt it */
   336     if (fetchCrl[0].pValue && PR_FALSE == adopted) {
   337         PORT_Free(fetchCrl[0].pValue);
   338     }
   339     if (derCrl && !adopted) {
   340         /* clear the data fields, which we already took care of above */
   341         derCrl->data = NULL;
   342         derCrl->len = 0;
   343         /* free the memory for the SECItem structure itself */
   344         SECITEM_FreeItem(derCrl, PR_TRUE);
   345     }
   346     return(rv);
   347 }
   349 /*
   350  * Return a list of CRLs matching specified issuer and type
   351  * CRLs are not allocated in the list's arena, but rather in their own,
   352  * arena, so that they can be used individually in the CRL cache .
   353  * CRLs are always partially decoded for efficiency.
   354  */
   355 SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
   356                             void *wincx)
   357 {
   358     pk11TraverseSlot creater;
   359     CK_ATTRIBUTE theTemplate[2];
   360     CK_ATTRIBUTE *attrs;
   361     CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL;
   362     crlOptions options;
   364     attrs = theTemplate;
   365     PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++;
   367     options.head = nodes;
   369     /* - do a partial decoding - we don't need to decode the entries while
   370        fetching
   371        - don't copy the DER for optimal performance - CRL can be very large
   372        - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
   373        - keep bad CRL objects. The CRL cache is interested in them, for
   374          security purposes. Bad CRL objects are a sign of something amiss.
   375     */
   377     options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
   378                             CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
   379     if (issuer)
   380     {
   381         PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); attrs++;
   382     }
   384     creater.callback = pk11_RetrieveCrlsCallback;
   385     creater.callbackArg = (void *) &options;
   386     creater.findTemplate = theTemplate;
   387     creater.templateCount = (attrs - theTemplate);
   389     return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
   390 }
   392 /*
   393  * return the crl associated with a derSubjectName 
   394  */
   395 SECItem *
   396 PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
   397 					 SECItem *name, int type, char **pUrl)
   398 {
   399     NSSCRL **crls, **crlp, *crl = NULL;
   400     NSSDER subject;
   401     SECItem *rvItem;
   402     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
   403     char * url = NULL;
   405     PORT_SetError(0);
   406     NSSITEM_FROM_SECITEM(&subject, name);
   407     if (*slot) {
   408 	nssCryptokiObject **instances;
   409 	nssPKIObjectCollection *collection;
   410 	nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
   411 	NSSToken *token = PK11Slot_GetNSSToken(*slot);
   412 	collection = nssCRLCollection_Create(td, NULL);
   413 	if (!collection) {
   414 	    goto loser;
   415 	}
   416 	instances = nssToken_FindCRLsBySubject(token, NULL, &subject, 
   417 	                                       tokenOnly, 0, NULL);
   418 	nssPKIObjectCollection_AddInstances(collection, instances, 0);
   419 	nss_ZFreeIf(instances);
   420 	crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
   421 	nssPKIObjectCollection_Destroy(collection);
   422     } else {
   423 	crls = nssTrustDomain_FindCRLsBySubject(td, &subject);
   424     }
   425     if ((!crls) || (*crls == NULL)) {
   426 	if (crls) {
   427 	    nssCRLArray_Destroy(crls);
   428 	}
   429 	if (NSS_GetError() == NSS_ERROR_NOT_FOUND) {
   430 	    PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
   431 	}
   432 	goto loser;
   433     }
   434     for (crlp = crls; *crlp; crlp++) {
   435 	if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) ||
   436 	    ((*crlp)->isKRL && type != SEC_CRL_TYPE)) 
   437 	{
   438 	    crl = nssCRL_AddRef(*crlp);
   439 	    break;
   440 	}
   441     }
   442     nssCRLArray_Destroy(crls);
   443     if (!crl) { 
   444 	/* CRL collection was found, but no interesting CRL's were on it.
   445 	 * Not an error */
   446 	PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
   447 	goto loser;
   448     }
   449     if (crl->url) {
   450 	url = PORT_Strdup(crl->url);
   451 	if (!url) {
   452 	    goto loser;
   453 	}
   454     }
   455     rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size);
   456     if (!rvItem) {
   457 	goto loser;
   458     }
   459     memcpy(rvItem->data, crl->encoding.data, crl->encoding.size);
   460     *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot);
   461     *crlHandle = crl->object.instances[0]->handle;
   462     *pUrl = url;
   463     nssCRL_Destroy(crl);
   464     return rvItem;
   466 loser:
   467     if (url)
   468     	PORT_Free(url);
   469     if (crl)
   470 	nssCRL_Destroy(crl);
   471     if (PORT_GetError() == 0) {
   472 	PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
   473     }
   474     return NULL;
   475 }
   477 CK_OBJECT_HANDLE
   478 PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, 
   479 							char *url, int type)
   480 {
   481     NSSItem derCRL, derSubject;
   482     NSSToken *token = PK11Slot_GetNSSToken(slot);
   483     nssCryptokiObject *object;
   484     PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE;
   485     CK_OBJECT_HANDLE rvH;
   487     NSSITEM_FROM_SECITEM(&derSubject, name);
   488     NSSITEM_FROM_SECITEM(&derCRL, crl);
   490     object = nssToken_ImportCRL(token, NULL, 
   491                                 &derSubject, &derCRL, isKRL, url, PR_TRUE);
   493     if (object) {
   494 	rvH = object->handle;
   495 	nssCryptokiObject_Destroy(object);
   496     } else {
   497 	rvH = CK_INVALID_HANDLE;
   498         PORT_SetError(SEC_ERROR_CRL_IMPORT_FAILED);
   499     }
   500     return rvH;
   501 }
   504 /*
   505  * delete a crl.
   506  */
   507 SECStatus
   508 SEC_DeletePermCRL(CERTSignedCrl *crl)
   509 {
   510     PRStatus status;
   511     NSSToken *token;
   512     nssCryptokiObject *object;
   513     PK11SlotInfo *slot = crl->slot;
   515     if (slot == NULL) {
   516         PORT_Assert(slot);
   517 	/* shouldn't happen */
   518 	PORT_SetError( SEC_ERROR_CRL_INVALID);
   519 	return SECFailure;
   520     }
   521     token = PK11Slot_GetNSSToken(slot);
   523     object = nss_ZNEW(NULL, nssCryptokiObject);
   524     if (!object) {
   525         return SECFailure;
   526     }
   527     object->token = nssToken_AddRef(token);
   528     object->handle = crl->pkcs11ID;
   529     object->isTokenObject = PR_TRUE;
   531     status = nssToken_DeleteStoredObject(object);
   533     nssCryptokiObject_Destroy(object);
   534     return (status == PR_SUCCESS) ? SECSuccess : SECFailure;
   535 }
   537 /*
   538  * return the certificate associated with a derCert 
   539  */
   540 SECItem *
   541 PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
   542 				 SECItem *name, SECItem **profileTime)
   543 {
   544     CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
   545     CK_ATTRIBUTE theTemplate[] = {
   546 	{ CKA_SUBJECT, NULL, 0 },
   547 	{ CKA_CLASS, NULL, 0 },
   548 	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
   549     };
   550     CK_ATTRIBUTE smimeData[] =  {
   551 	{ CKA_SUBJECT, NULL, 0 },
   552 	{ CKA_VALUE, NULL, 0 },
   553     };
   554     /* if you change the array, change the variable below as well */
   555     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
   556     CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
   557     CK_ATTRIBUTE *attrs = theTemplate;
   558     CK_RV crv;
   559     SECItem *emailProfile = NULL;
   561     if (!emailAddr || !emailAddr[0]) {
   562 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   563 	return NULL;
   564     }
   566     PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++;
   567     PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
   568     PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr)); 
   569 								    attrs++;
   571     if (*slot) {
   572     	smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize);
   573     } else {
   574 	PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
   575 							PR_FALSE,PR_TRUE,NULL);
   576 	PK11SlotListElement *le;
   578 	if (!list) {
   579 	    return NULL;
   580 	}
   581 	/* loop through all the slots */
   582 	for (le = list->head; le; le = le->next) {
   583 	    smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize);
   584 	    if (smimeh != CK_INVALID_HANDLE) {
   585 		*slot = PK11_ReferenceSlot(le->slot);
   586 		break;
   587 	    }
   588 	}
   589 	PK11_FreeSlotList(list);
   590     }
   592     if (smimeh == CK_INVALID_HANDLE) {
   593 	PORT_SetError(SEC_ERROR_NO_KRL);
   594 	return NULL;
   595     }
   597     if (profileTime) {
   598     	PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0);
   599     } 
   601     crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2);
   602     if (crv != CKR_OK) {
   603 	PORT_SetError(PK11_MapError (crv));
   604 	goto loser;
   605     }
   607     if (!profileTime) {
   608 	SECItem profileSubject;
   610 	profileSubject.data = (unsigned char*) smimeData[0].pValue;
   611 	profileSubject.len = smimeData[0].ulValueLen;
   612 	if (!SECITEM_ItemsAreEqual(&profileSubject,name)) {
   613 	    goto loser;
   614 	}
   615     }
   617     emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
   618     if (emailProfile == NULL) {
   619 	goto loser;
   620     }
   622     emailProfile->data = (unsigned char*) smimeData[1].pValue;
   623     emailProfile->len = smimeData[1].ulValueLen;
   625     if (profileTime) {
   626 	*profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
   627 	if (*profileTime) {
   628 	    (*profileTime)->data = (unsigned char*) smimeData[0].pValue;
   629 	    (*profileTime)->len = smimeData[0].ulValueLen;
   630 	}
   631     }
   633 loser:
   634     if (emailProfile == NULL) {
   635 	if (smimeData[1].pValue) {
   636 	    PORT_Free(smimeData[1].pValue);
   637 	}
   638     }
   639     if (profileTime == NULL || *profileTime == NULL) {
   640 	if (smimeData[0].pValue) {
   641 	    PORT_Free(smimeData[0].pValue);
   642 	}
   643     }
   644     return emailProfile;
   645 }
   648 SECStatus
   649 PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
   650 				 SECItem *emailProfile,  SECItem *profileTime)
   651 {
   652     CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
   653     CK_BBOOL ck_true = CK_TRUE;
   654     CK_ATTRIBUTE theTemplate[] = {
   655 	{ CKA_CLASS, NULL, 0 },
   656 	{ CKA_TOKEN, NULL, 0 },
   657 	{ CKA_SUBJECT, NULL, 0 },
   658 	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
   659 	{ CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 },
   660 	{ CKA_VALUE, NULL, 0 }
   661     };
   662     /* if you change the array, change the variable below as well */
   663     int realSize = 0;
   664     CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
   665     CK_ATTRIBUTE *attrs = theTemplate;
   666     CK_SESSION_HANDLE rwsession;
   667     PK11SlotInfo *free_slot = NULL;
   668     CK_RV crv;
   669 #ifdef DEBUG
   670     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
   671 #endif
   673     PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
   674     PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); attrs++;
   675     PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++;
   676     PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, 
   677 				emailAddr, PORT_Strlen(emailAddr)+1); attrs++;
   678     if (profileTime) {
   679 	PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data,
   680 	                                            profileTime->len); attrs++;
   681 	PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data,
   682 	                                            emailProfile->len); attrs++;
   683     }
   684     realSize = attrs - theTemplate;
   685     PORT_Assert (realSize <= tsize);
   687     if (slot == NULL) {
   688 	free_slot = slot = PK11_GetInternalKeySlot();
   689 	/* we need to free the key slot in the end!!! */
   690     }
   692     rwsession = PK11_GetRWSession(slot);
   693     if (rwsession == CK_INVALID_SESSION) {
   694 	PORT_SetError(SEC_ERROR_READ_ONLY);
   695 	if (free_slot) {
   696 	    PK11_FreeSlot(free_slot);
   697 	}
   698 	return SECFailure;
   699     }
   701     crv = PK11_GETTAB(slot)->
   702                         C_CreateObject(rwsession,theTemplate,realSize,&smimeh);
   703     if (crv != CKR_OK) {
   704         PORT_SetError( PK11_MapError(crv) );
   705     }
   707     PK11_RestoreROSession(slot,rwsession);
   709     if (free_slot) {
   710 	PK11_FreeSlot(free_slot);
   711     }
   712     return SECSuccess;
   713 }
   716 CERTSignedCrl * crl_storeCRL (PK11SlotInfo *slot,char *url,
   717                   CERTSignedCrl *newCrl, SECItem *derCrl, int type);
   719 /* import the CRL into the token */
   721 CERTSignedCrl* PK11_ImportCRL(PK11SlotInfo * slot, SECItem *derCRL, char *url,
   722     int type, void *wincx, PRInt32 importOptions, PLArenaPool* arena,
   723     PRInt32 decodeoptions)
   724 {
   725     CERTSignedCrl *newCrl, *crl;
   726     SECStatus rv;
   727     CERTCertificate *caCert = NULL;
   729     newCrl = crl = NULL;
   731     do {
   732         newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type,
   733                                             decodeoptions);
   734         if (newCrl == NULL) {
   735             if (type == SEC_CRL_TYPE) {
   736                 /* only promote error when the error code is too generic */
   737                 if (PORT_GetError () == SEC_ERROR_BAD_DER)
   738                     PORT_SetError(SEC_ERROR_CRL_INVALID);
   739 	        } else {
   740                 PORT_SetError(SEC_ERROR_KRL_INVALID);
   741             }
   742             break;		
   743         }
   745         if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){
   746             CERTCertDBHandle* handle = CERT_GetDefaultCertDB();
   747             PR_ASSERT(handle != NULL);
   748             caCert = CERT_FindCertByName (handle,
   749                                           &newCrl->crl.derName);
   750             if (caCert == NULL) {
   751                 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);	    
   752                 break;
   753             }
   755             /* If caCert is a v3 certificate, make sure that it can be used for
   756                crl signing purpose */
   757             rv = CERT_CheckCertUsage (caCert, KU_CRL_SIGN);
   758             if (rv != SECSuccess) {
   759                 break;
   760             }
   762             rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert,
   763                                        PR_Now(), wincx);
   764             if (rv != SECSuccess) {
   765                 if (type == SEC_CRL_TYPE) {
   766                     PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
   767                 } else {
   768                     PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
   769                 }
   770                 break;
   771             }
   772         }
   774 	crl = crl_storeCRL(slot, url, newCrl, derCRL, type);
   776     } while (0);
   778     if (crl == NULL) {
   779 	SEC_DestroyCrl (newCrl);
   780     }
   781     if (caCert) {
   782         CERT_DestroyCertificate(caCert);
   783     }
   784     return (crl);
   785 }

mercurial