security/nss/lib/pk11wrap/pk11nobj.c

changeset 0
6474c204b198
     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 +}

mercurial