1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11nobj.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,785 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects, 1.9 + * etc). 1.10 + */ 1.11 + 1.12 +#include "secport.h" 1.13 +#include "seccomon.h" 1.14 +#include "secmod.h" 1.15 +#include "secmodi.h" 1.16 +#include "secmodti.h" 1.17 +#include "pkcs11.h" 1.18 +#include "pk11func.h" 1.19 +#include "cert.h" 1.20 +#include "certi.h" 1.21 +#include "secitem.h" 1.22 +#include "sechash.h" 1.23 +#include "secoid.h" 1.24 + 1.25 +#include "certdb.h" 1.26 +#include "secerr.h" 1.27 +#include "sslerr.h" 1.28 + 1.29 +#include "pki3hack.h" 1.30 +#include "dev3hack.h" 1.31 + 1.32 +#include "devm.h" 1.33 +#include "pki.h" 1.34 +#include "pkim.h" 1.35 + 1.36 +extern const NSSError NSS_ERROR_NOT_FOUND; 1.37 + 1.38 +CK_TRUST 1.39 +pk11_GetTrustField(PK11SlotInfo *slot, PLArenaPool *arena, 1.40 + CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type) 1.41 +{ 1.42 + CK_TRUST rv = 0; 1.43 + SECItem item; 1.44 + 1.45 + item.data = NULL; 1.46 + item.len = 0; 1.47 + 1.48 + if( SECSuccess == PK11_ReadAttribute(slot, id, type, arena, &item) ) { 1.49 + PORT_Assert(item.len == sizeof(CK_TRUST)); 1.50 + PORT_Memcpy(&rv, item.data, sizeof(CK_TRUST)); 1.51 + /* Damn, is there an endian problem here? */ 1.52 + return rv; 1.53 + } 1.54 + 1.55 + return 0; 1.56 +} 1.57 + 1.58 +PRBool 1.59 +pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust) 1.60 +{ 1.61 + PLArenaPool *arena; 1.62 + 1.63 + CK_ATTRIBUTE tobjTemplate[] = { 1.64 + { CKA_CLASS, NULL, 0 }, 1.65 + { CKA_CERT_SHA1_HASH, NULL, 0 }, 1.66 + }; 1.67 + 1.68 + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; 1.69 + CK_OBJECT_HANDLE tobjID; 1.70 + unsigned char sha1_hash[SHA1_LENGTH]; 1.71 + 1.72 + CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth; 1.73 + 1.74 + PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len); 1.75 + 1.76 + PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc)); 1.77 + PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash, 1.78 + SHA1_LENGTH); 1.79 + 1.80 + tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, 1.81 + sizeof(tobjTemplate)/sizeof(tobjTemplate[0])); 1.82 + if( CK_INVALID_HANDLE == tobjID ) { 1.83 + return PR_FALSE; 1.84 + } 1.85 + 1.86 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.87 + if( NULL == arena ) return PR_FALSE; 1.88 + 1.89 + /* Unfortunately, it seems that PK11_GetAttributes doesn't deal 1.90 + * well with nonexistent attributes. I guess we have to check 1.91 + * the trust info fields one at a time. 1.92 + */ 1.93 + 1.94 + /* We could verify CKA_CERT_HASH here */ 1.95 + 1.96 + /* We could verify CKA_EXPIRES here */ 1.97 + 1.98 + 1.99 + /* "Purpose" trust information */ 1.100 + serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH); 1.101 + clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); 1.102 + codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING); 1.103 + emailProtection = pk11_GetTrustField(slot, arena, tobjID, 1.104 + CKA_TRUST_EMAIL_PROTECTION); 1.105 + /* Here's where the fun logic happens. We have to map back from the 1.106 + * key usage, extended key usage, purpose, and possibly other trust values 1.107 + * into the old trust-flags bits. */ 1.108 + 1.109 + /* First implementation: keep it simple for testing. We can study what other 1.110 + * mappings would be appropriate and add them later.. fgmr 20000724 */ 1.111 + 1.112 + if ( serverAuth == CKT_NSS_TRUSTED ) { 1.113 + trust->sslFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED; 1.114 + } 1.115 + 1.116 + if ( serverAuth == CKT_NSS_TRUSTED_DELEGATOR ) { 1.117 + trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | 1.118 + CERTDB_NS_TRUSTED_CA; 1.119 + } 1.120 + if ( clientAuth == CKT_NSS_TRUSTED_DELEGATOR ) { 1.121 + trust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA ; 1.122 + } 1.123 + 1.124 + if ( emailProtection == CKT_NSS_TRUSTED ) { 1.125 + trust->emailFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED; 1.126 + } 1.127 + 1.128 + if ( emailProtection == CKT_NSS_TRUSTED_DELEGATOR ) { 1.129 + trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA; 1.130 + } 1.131 + 1.132 + if( codeSigning == CKT_NSS_TRUSTED ) { 1.133 + trust->objectSigningFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED; 1.134 + } 1.135 + 1.136 + if( codeSigning == CKT_NSS_TRUSTED_DELEGATOR ) { 1.137 + trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA; 1.138 + } 1.139 + 1.140 + /* There's certainly a lot more logic that can go here.. */ 1.141 + 1.142 + PORT_FreeArena(arena, PR_FALSE); 1.143 + 1.144 + return PR_TRUE; 1.145 +} 1.146 + 1.147 +static SECStatus 1.148 +pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg) 1.149 +{ 1.150 + SECItem derCrl; 1.151 + CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg; 1.152 + CERTCrlNode *new_node = NULL; 1.153 + CK_ATTRIBUTE fetchCrl[3] = { 1.154 + { CKA_VALUE, NULL, 0}, 1.155 + { CKA_NETSCAPE_KRL, NULL, 0}, 1.156 + { CKA_NETSCAPE_URL, NULL, 0}, 1.157 + }; 1.158 + const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]); 1.159 + CK_RV crv; 1.160 + SECStatus rv = SECFailure; 1.161 + 1.162 + crv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize); 1.163 + if (CKR_OK != crv) { 1.164 + PORT_SetError(PK11_MapError(crv)); 1.165 + goto loser; 1.166 + } 1.167 + 1.168 + if (!fetchCrl[1].pValue) { 1.169 + PORT_SetError(SEC_ERROR_CRL_INVALID); 1.170 + goto loser; 1.171 + } 1.172 + 1.173 + new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode)); 1.174 + if (new_node == NULL) { 1.175 + goto loser; 1.176 + } 1.177 + 1.178 + if (*((CK_BBOOL *)fetchCrl[1].pValue)) 1.179 + new_node->type = SEC_KRL_TYPE; 1.180 + else 1.181 + new_node->type = SEC_CRL_TYPE; 1.182 + 1.183 + derCrl.type = siBuffer; 1.184 + derCrl.data = (unsigned char *)fetchCrl[0].pValue; 1.185 + derCrl.len = fetchCrl[0].ulValueLen; 1.186 + new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type); 1.187 + if (new_node->crl == NULL) { 1.188 + goto loser; 1.189 + } 1.190 + 1.191 + if (fetchCrl[2].pValue) { 1.192 + int nnlen = fetchCrl[2].ulValueLen; 1.193 + new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen+1); 1.194 + if ( !new_node->crl->url ) { 1.195 + goto loser; 1.196 + } 1.197 + PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); 1.198 + new_node->crl->url[nnlen] = 0; 1.199 + } else { 1.200 + new_node->crl->url = NULL; 1.201 + } 1.202 + 1.203 + 1.204 + new_node->next = NULL; 1.205 + if (head->last) { 1.206 + head->last->next = new_node; 1.207 + head->last = new_node; 1.208 + } else { 1.209 + head->first = head->last = new_node; 1.210 + } 1.211 + rv = SECSuccess; 1.212 + 1.213 +loser: 1.214 + return(rv); 1.215 +} 1.216 + 1.217 +/* 1.218 + * Return a list of all the CRLs . 1.219 + * CRLs are allocated in the list's arena. 1.220 + */ 1.221 +SECStatus 1.222 +PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) { 1.223 + pk11TraverseSlot creater; 1.224 + CK_ATTRIBUTE theTemplate[2]; 1.225 + CK_ATTRIBUTE *attrs; 1.226 + CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL; 1.227 + CK_BBOOL isKrl = CK_FALSE; 1.228 + 1.229 + attrs = theTemplate; 1.230 + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++; 1.231 + if (type != -1) { 1.232 + isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE); 1.233 + PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++; 1.234 + } 1.235 + 1.236 + creater.callback = pk11_CollectCrls; 1.237 + creater.callbackArg = (void *) nodes; 1.238 + creater.findTemplate = theTemplate; 1.239 + creater.templateCount = (attrs - theTemplate); 1.240 + 1.241 + return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx); 1.242 +} 1.243 + 1.244 +struct crlOptionsStr { 1.245 + CERTCrlHeadNode* head; 1.246 + PRInt32 decodeOptions; 1.247 +}; 1.248 + 1.249 +typedef struct crlOptionsStr crlOptions; 1.250 + 1.251 +static SECStatus 1.252 +pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, 1.253 + void *arg) 1.254 +{ 1.255 + SECItem* derCrl = NULL; 1.256 + crlOptions* options = (crlOptions*) arg; 1.257 + CERTCrlHeadNode *head = options->head; 1.258 + CERTCrlNode *new_node = NULL; 1.259 + CK_ATTRIBUTE fetchCrl[3] = { 1.260 + { CKA_VALUE, NULL, 0}, 1.261 + { CKA_NETSCAPE_KRL, NULL, 0}, 1.262 + { CKA_NETSCAPE_URL, NULL, 0}, 1.263 + }; 1.264 + const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]); 1.265 + CK_RV crv; 1.266 + SECStatus rv = SECFailure; 1.267 + PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory 1.268 + successfully */ 1.269 + int i; 1.270 + 1.271 + crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize); 1.272 + if (CKR_OK != crv) { 1.273 + PORT_SetError(PK11_MapError(crv)); 1.274 + goto loser; 1.275 + } 1.276 + 1.277 + if (!fetchCrl[1].pValue) { 1.278 + /* reject KRLs */ 1.279 + PORT_SetError(SEC_ERROR_CRL_INVALID); 1.280 + goto loser; 1.281 + } 1.282 + 1.283 + new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, 1.284 + sizeof(CERTCrlNode)); 1.285 + if (new_node == NULL) { 1.286 + goto loser; 1.287 + } 1.288 + 1.289 + new_node->type = SEC_CRL_TYPE; 1.290 + 1.291 + derCrl = SECITEM_AllocItem(NULL, NULL, 0); 1.292 + if (!derCrl) { 1.293 + goto loser; 1.294 + } 1.295 + derCrl->type = siBuffer; 1.296 + derCrl->data = (unsigned char *)fetchCrl[0].pValue; 1.297 + derCrl->len = fetchCrl[0].ulValueLen; 1.298 + new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type, 1.299 + options->decodeOptions); 1.300 + if (new_node->crl == NULL) { 1.301 + goto loser; 1.302 + } 1.303 + adopted = PR_TRUE; /* now that the CRL has adopted the DER memory, 1.304 + we won't need to free it upon exit */ 1.305 + 1.306 + if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) { 1.307 + /* copy the URL if there is one */ 1.308 + int nnlen = fetchCrl[2].ulValueLen; 1.309 + new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena, 1.310 + nnlen+1); 1.311 + if ( !new_node->crl->url ) { 1.312 + goto loser; 1.313 + } 1.314 + PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); 1.315 + new_node->crl->url[nnlen] = 0; 1.316 + } else { 1.317 + new_node->crl->url = NULL; 1.318 + } 1.319 + 1.320 + new_node->next = NULL; 1.321 + if (head->last) { 1.322 + head->last->next = new_node; 1.323 + head->last = new_node; 1.324 + } else { 1.325 + head->first = head->last = new_node; 1.326 + } 1.327 + rv = SECSuccess; 1.328 + new_node->crl->slot = PK11_ReferenceSlot(slot); 1.329 + new_node->crl->pkcs11ID = crlID; 1.330 + 1.331 +loser: 1.332 + /* free attributes that weren't adopted by the CRL */ 1.333 + for (i=1;i<fetchCrlSize;i++) { 1.334 + if (fetchCrl[i].pValue) { 1.335 + PORT_Free(fetchCrl[i].pValue); 1.336 + } 1.337 + } 1.338 + /* free the DER if the CRL object didn't adopt it */ 1.339 + if (fetchCrl[0].pValue && PR_FALSE == adopted) { 1.340 + PORT_Free(fetchCrl[0].pValue); 1.341 + } 1.342 + if (derCrl && !adopted) { 1.343 + /* clear the data fields, which we already took care of above */ 1.344 + derCrl->data = NULL; 1.345 + derCrl->len = 0; 1.346 + /* free the memory for the SECItem structure itself */ 1.347 + SECITEM_FreeItem(derCrl, PR_TRUE); 1.348 + } 1.349 + return(rv); 1.350 +} 1.351 + 1.352 +/* 1.353 + * Return a list of CRLs matching specified issuer and type 1.354 + * CRLs are not allocated in the list's arena, but rather in their own, 1.355 + * arena, so that they can be used individually in the CRL cache . 1.356 + * CRLs are always partially decoded for efficiency. 1.357 + */ 1.358 +SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer, 1.359 + void *wincx) 1.360 +{ 1.361 + pk11TraverseSlot creater; 1.362 + CK_ATTRIBUTE theTemplate[2]; 1.363 + CK_ATTRIBUTE *attrs; 1.364 + CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; 1.365 + crlOptions options; 1.366 + 1.367 + attrs = theTemplate; 1.368 + PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; 1.369 + 1.370 + options.head = nodes; 1.371 + 1.372 + /* - do a partial decoding - we don't need to decode the entries while 1.373 + fetching 1.374 + - don't copy the DER for optimal performance - CRL can be very large 1.375 + - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it 1.376 + - keep bad CRL objects. The CRL cache is interested in them, for 1.377 + security purposes. Bad CRL objects are a sign of something amiss. 1.378 + */ 1.379 + 1.380 + options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER | 1.381 + CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL; 1.382 + if (issuer) 1.383 + { 1.384 + PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); attrs++; 1.385 + } 1.386 + 1.387 + creater.callback = pk11_RetrieveCrlsCallback; 1.388 + creater.callbackArg = (void *) &options; 1.389 + creater.findTemplate = theTemplate; 1.390 + creater.templateCount = (attrs - theTemplate); 1.391 + 1.392 + return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx); 1.393 +} 1.394 + 1.395 +/* 1.396 + * return the crl associated with a derSubjectName 1.397 + */ 1.398 +SECItem * 1.399 +PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, 1.400 + SECItem *name, int type, char **pUrl) 1.401 +{ 1.402 + NSSCRL **crls, **crlp, *crl = NULL; 1.403 + NSSDER subject; 1.404 + SECItem *rvItem; 1.405 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.406 + char * url = NULL; 1.407 + 1.408 + PORT_SetError(0); 1.409 + NSSITEM_FROM_SECITEM(&subject, name); 1.410 + if (*slot) { 1.411 + nssCryptokiObject **instances; 1.412 + nssPKIObjectCollection *collection; 1.413 + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 1.414 + NSSToken *token = PK11Slot_GetNSSToken(*slot); 1.415 + collection = nssCRLCollection_Create(td, NULL); 1.416 + if (!collection) { 1.417 + goto loser; 1.418 + } 1.419 + instances = nssToken_FindCRLsBySubject(token, NULL, &subject, 1.420 + tokenOnly, 0, NULL); 1.421 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.422 + nss_ZFreeIf(instances); 1.423 + crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); 1.424 + nssPKIObjectCollection_Destroy(collection); 1.425 + } else { 1.426 + crls = nssTrustDomain_FindCRLsBySubject(td, &subject); 1.427 + } 1.428 + if ((!crls) || (*crls == NULL)) { 1.429 + if (crls) { 1.430 + nssCRLArray_Destroy(crls); 1.431 + } 1.432 + if (NSS_GetError() == NSS_ERROR_NOT_FOUND) { 1.433 + PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); 1.434 + } 1.435 + goto loser; 1.436 + } 1.437 + for (crlp = crls; *crlp; crlp++) { 1.438 + if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) || 1.439 + ((*crlp)->isKRL && type != SEC_CRL_TYPE)) 1.440 + { 1.441 + crl = nssCRL_AddRef(*crlp); 1.442 + break; 1.443 + } 1.444 + } 1.445 + nssCRLArray_Destroy(crls); 1.446 + if (!crl) { 1.447 + /* CRL collection was found, but no interesting CRL's were on it. 1.448 + * Not an error */ 1.449 + PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); 1.450 + goto loser; 1.451 + } 1.452 + if (crl->url) { 1.453 + url = PORT_Strdup(crl->url); 1.454 + if (!url) { 1.455 + goto loser; 1.456 + } 1.457 + } 1.458 + rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size); 1.459 + if (!rvItem) { 1.460 + goto loser; 1.461 + } 1.462 + memcpy(rvItem->data, crl->encoding.data, crl->encoding.size); 1.463 + *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot); 1.464 + *crlHandle = crl->object.instances[0]->handle; 1.465 + *pUrl = url; 1.466 + nssCRL_Destroy(crl); 1.467 + return rvItem; 1.468 + 1.469 +loser: 1.470 + if (url) 1.471 + PORT_Free(url); 1.472 + if (crl) 1.473 + nssCRL_Destroy(crl); 1.474 + if (PORT_GetError() == 0) { 1.475 + PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); 1.476 + } 1.477 + return NULL; 1.478 +} 1.479 + 1.480 +CK_OBJECT_HANDLE 1.481 +PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, 1.482 + char *url, int type) 1.483 +{ 1.484 + NSSItem derCRL, derSubject; 1.485 + NSSToken *token = PK11Slot_GetNSSToken(slot); 1.486 + nssCryptokiObject *object; 1.487 + PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE; 1.488 + CK_OBJECT_HANDLE rvH; 1.489 + 1.490 + NSSITEM_FROM_SECITEM(&derSubject, name); 1.491 + NSSITEM_FROM_SECITEM(&derCRL, crl); 1.492 + 1.493 + object = nssToken_ImportCRL(token, NULL, 1.494 + &derSubject, &derCRL, isKRL, url, PR_TRUE); 1.495 + 1.496 + if (object) { 1.497 + rvH = object->handle; 1.498 + nssCryptokiObject_Destroy(object); 1.499 + } else { 1.500 + rvH = CK_INVALID_HANDLE; 1.501 + PORT_SetError(SEC_ERROR_CRL_IMPORT_FAILED); 1.502 + } 1.503 + return rvH; 1.504 +} 1.505 + 1.506 + 1.507 +/* 1.508 + * delete a crl. 1.509 + */ 1.510 +SECStatus 1.511 +SEC_DeletePermCRL(CERTSignedCrl *crl) 1.512 +{ 1.513 + PRStatus status; 1.514 + NSSToken *token; 1.515 + nssCryptokiObject *object; 1.516 + PK11SlotInfo *slot = crl->slot; 1.517 + 1.518 + if (slot == NULL) { 1.519 + PORT_Assert(slot); 1.520 + /* shouldn't happen */ 1.521 + PORT_SetError( SEC_ERROR_CRL_INVALID); 1.522 + return SECFailure; 1.523 + } 1.524 + token = PK11Slot_GetNSSToken(slot); 1.525 + 1.526 + object = nss_ZNEW(NULL, nssCryptokiObject); 1.527 + if (!object) { 1.528 + return SECFailure; 1.529 + } 1.530 + object->token = nssToken_AddRef(token); 1.531 + object->handle = crl->pkcs11ID; 1.532 + object->isTokenObject = PR_TRUE; 1.533 + 1.534 + status = nssToken_DeleteStoredObject(object); 1.535 + 1.536 + nssCryptokiObject_Destroy(object); 1.537 + return (status == PR_SUCCESS) ? SECSuccess : SECFailure; 1.538 +} 1.539 + 1.540 +/* 1.541 + * return the certificate associated with a derCert 1.542 + */ 1.543 +SECItem * 1.544 +PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr, 1.545 + SECItem *name, SECItem **profileTime) 1.546 +{ 1.547 + CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME; 1.548 + CK_ATTRIBUTE theTemplate[] = { 1.549 + { CKA_SUBJECT, NULL, 0 }, 1.550 + { CKA_CLASS, NULL, 0 }, 1.551 + { CKA_NETSCAPE_EMAIL, NULL, 0 }, 1.552 + }; 1.553 + CK_ATTRIBUTE smimeData[] = { 1.554 + { CKA_SUBJECT, NULL, 0 }, 1.555 + { CKA_VALUE, NULL, 0 }, 1.556 + }; 1.557 + /* if you change the array, change the variable below as well */ 1.558 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.559 + CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; 1.560 + CK_ATTRIBUTE *attrs = theTemplate; 1.561 + CK_RV crv; 1.562 + SECItem *emailProfile = NULL; 1.563 + 1.564 + if (!emailAddr || !emailAddr[0]) { 1.565 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.566 + return NULL; 1.567 + } 1.568 + 1.569 + PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; 1.570 + PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++; 1.571 + PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr)); 1.572 + attrs++; 1.573 + 1.574 + if (*slot) { 1.575 + smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize); 1.576 + } else { 1.577 + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1.578 + PR_FALSE,PR_TRUE,NULL); 1.579 + PK11SlotListElement *le; 1.580 + 1.581 + if (!list) { 1.582 + return NULL; 1.583 + } 1.584 + /* loop through all the slots */ 1.585 + for (le = list->head; le; le = le->next) { 1.586 + smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); 1.587 + if (smimeh != CK_INVALID_HANDLE) { 1.588 + *slot = PK11_ReferenceSlot(le->slot); 1.589 + break; 1.590 + } 1.591 + } 1.592 + PK11_FreeSlotList(list); 1.593 + } 1.594 + 1.595 + if (smimeh == CK_INVALID_HANDLE) { 1.596 + PORT_SetError(SEC_ERROR_NO_KRL); 1.597 + return NULL; 1.598 + } 1.599 + 1.600 + if (profileTime) { 1.601 + PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0); 1.602 + } 1.603 + 1.604 + crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2); 1.605 + if (crv != CKR_OK) { 1.606 + PORT_SetError(PK11_MapError (crv)); 1.607 + goto loser; 1.608 + } 1.609 + 1.610 + if (!profileTime) { 1.611 + SECItem profileSubject; 1.612 + 1.613 + profileSubject.data = (unsigned char*) smimeData[0].pValue; 1.614 + profileSubject.len = smimeData[0].ulValueLen; 1.615 + if (!SECITEM_ItemsAreEqual(&profileSubject,name)) { 1.616 + goto loser; 1.617 + } 1.618 + } 1.619 + 1.620 + emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.621 + if (emailProfile == NULL) { 1.622 + goto loser; 1.623 + } 1.624 + 1.625 + emailProfile->data = (unsigned char*) smimeData[1].pValue; 1.626 + emailProfile->len = smimeData[1].ulValueLen; 1.627 + 1.628 + if (profileTime) { 1.629 + *profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.630 + if (*profileTime) { 1.631 + (*profileTime)->data = (unsigned char*) smimeData[0].pValue; 1.632 + (*profileTime)->len = smimeData[0].ulValueLen; 1.633 + } 1.634 + } 1.635 + 1.636 +loser: 1.637 + if (emailProfile == NULL) { 1.638 + if (smimeData[1].pValue) { 1.639 + PORT_Free(smimeData[1].pValue); 1.640 + } 1.641 + } 1.642 + if (profileTime == NULL || *profileTime == NULL) { 1.643 + if (smimeData[0].pValue) { 1.644 + PORT_Free(smimeData[0].pValue); 1.645 + } 1.646 + } 1.647 + return emailProfile; 1.648 +} 1.649 + 1.650 + 1.651 +SECStatus 1.652 +PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, 1.653 + SECItem *emailProfile, SECItem *profileTime) 1.654 +{ 1.655 + CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME; 1.656 + CK_BBOOL ck_true = CK_TRUE; 1.657 + CK_ATTRIBUTE theTemplate[] = { 1.658 + { CKA_CLASS, NULL, 0 }, 1.659 + { CKA_TOKEN, NULL, 0 }, 1.660 + { CKA_SUBJECT, NULL, 0 }, 1.661 + { CKA_NETSCAPE_EMAIL, NULL, 0 }, 1.662 + { CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 }, 1.663 + { CKA_VALUE, NULL, 0 } 1.664 + }; 1.665 + /* if you change the array, change the variable below as well */ 1.666 + int realSize = 0; 1.667 + CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; 1.668 + CK_ATTRIBUTE *attrs = theTemplate; 1.669 + CK_SESSION_HANDLE rwsession; 1.670 + PK11SlotInfo *free_slot = NULL; 1.671 + CK_RV crv; 1.672 +#ifdef DEBUG 1.673 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.674 +#endif 1.675 + 1.676 + PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++; 1.677 + PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); attrs++; 1.678 + PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++; 1.679 + PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, 1.680 + emailAddr, PORT_Strlen(emailAddr)+1); attrs++; 1.681 + if (profileTime) { 1.682 + PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data, 1.683 + profileTime->len); attrs++; 1.684 + PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data, 1.685 + emailProfile->len); attrs++; 1.686 + } 1.687 + realSize = attrs - theTemplate; 1.688 + PORT_Assert (realSize <= tsize); 1.689 + 1.690 + if (slot == NULL) { 1.691 + free_slot = slot = PK11_GetInternalKeySlot(); 1.692 + /* we need to free the key slot in the end!!! */ 1.693 + } 1.694 + 1.695 + rwsession = PK11_GetRWSession(slot); 1.696 + if (rwsession == CK_INVALID_SESSION) { 1.697 + PORT_SetError(SEC_ERROR_READ_ONLY); 1.698 + if (free_slot) { 1.699 + PK11_FreeSlot(free_slot); 1.700 + } 1.701 + return SECFailure; 1.702 + } 1.703 + 1.704 + crv = PK11_GETTAB(slot)-> 1.705 + C_CreateObject(rwsession,theTemplate,realSize,&smimeh); 1.706 + if (crv != CKR_OK) { 1.707 + PORT_SetError( PK11_MapError(crv) ); 1.708 + } 1.709 + 1.710 + PK11_RestoreROSession(slot,rwsession); 1.711 + 1.712 + if (free_slot) { 1.713 + PK11_FreeSlot(free_slot); 1.714 + } 1.715 + return SECSuccess; 1.716 +} 1.717 + 1.718 + 1.719 +CERTSignedCrl * crl_storeCRL (PK11SlotInfo *slot,char *url, 1.720 + CERTSignedCrl *newCrl, SECItem *derCrl, int type); 1.721 + 1.722 +/* import the CRL into the token */ 1.723 + 1.724 +CERTSignedCrl* PK11_ImportCRL(PK11SlotInfo * slot, SECItem *derCRL, char *url, 1.725 + int type, void *wincx, PRInt32 importOptions, PLArenaPool* arena, 1.726 + PRInt32 decodeoptions) 1.727 +{ 1.728 + CERTSignedCrl *newCrl, *crl; 1.729 + SECStatus rv; 1.730 + CERTCertificate *caCert = NULL; 1.731 + 1.732 + newCrl = crl = NULL; 1.733 + 1.734 + do { 1.735 + newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type, 1.736 + decodeoptions); 1.737 + if (newCrl == NULL) { 1.738 + if (type == SEC_CRL_TYPE) { 1.739 + /* only promote error when the error code is too generic */ 1.740 + if (PORT_GetError () == SEC_ERROR_BAD_DER) 1.741 + PORT_SetError(SEC_ERROR_CRL_INVALID); 1.742 + } else { 1.743 + PORT_SetError(SEC_ERROR_KRL_INVALID); 1.744 + } 1.745 + break; 1.746 + } 1.747 + 1.748 + if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){ 1.749 + CERTCertDBHandle* handle = CERT_GetDefaultCertDB(); 1.750 + PR_ASSERT(handle != NULL); 1.751 + caCert = CERT_FindCertByName (handle, 1.752 + &newCrl->crl.derName); 1.753 + if (caCert == NULL) { 1.754 + PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 1.755 + break; 1.756 + } 1.757 + 1.758 + /* If caCert is a v3 certificate, make sure that it can be used for 1.759 + crl signing purpose */ 1.760 + rv = CERT_CheckCertUsage (caCert, KU_CRL_SIGN); 1.761 + if (rv != SECSuccess) { 1.762 + break; 1.763 + } 1.764 + 1.765 + rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert, 1.766 + PR_Now(), wincx); 1.767 + if (rv != SECSuccess) { 1.768 + if (type == SEC_CRL_TYPE) { 1.769 + PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE); 1.770 + } else { 1.771 + PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE); 1.772 + } 1.773 + break; 1.774 + } 1.775 + } 1.776 + 1.777 + crl = crl_storeCRL(slot, url, newCrl, derCRL, type); 1.778 + 1.779 + } while (0); 1.780 + 1.781 + if (crl == NULL) { 1.782 + SEC_DestroyCrl (newCrl); 1.783 + } 1.784 + if (caCert) { 1.785 + CERT_DestroyCertificate(caCert); 1.786 + } 1.787 + return (crl); 1.788 +}