CERTCertificateList * CERT_DupCertList(const CERTCertificateList * oldList) { CERTCertificateList *newList = NULL; PRArenaPool *arena = NULL; SECItem *newItem; SECItem *oldItem; int len = oldList->len; int rv; /* arena for SecCertificateList */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) goto no_memory; /* now build the CERTCertificateList */ newList = PORT_ArenaNew(arena, CERTCertificateList); if (newList == NULL) goto no_memory; newList->arena = arena; newItem = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem)); if (newItem == NULL) goto no_memory; newList->certs = newItem; newList->len = len; for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) { rv = SECITEM_CopyItem(arena, newItem, oldItem); if (rv < 0) goto loser; } return newList; no_memory: PORT_SetError(SEC_ERROR_NO_MEMORY); loser: if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } return NULL; }
static CERTCertTrust * cert_trust_from_stan_trust(NSSTrust *t, PRArenaPool *arena) { CERTCertTrust *rvTrust; unsigned int client; if (!t) { return NULL; } rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust)); if (!rvTrust) return NULL; rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth); client = get_nss3trust_from_nss4trust(t->clientAuth); if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) { client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA); rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA; } rvTrust->sslFlags |= client; rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection); rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning); return rvTrust; }
/* * FUNCTION: PKIX_PL_Calloc (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Calloc( PKIX_UInt32 nElem, PKIX_UInt32 elSize, void **pMemory, void *plContext) { PKIX_PL_NssContext *nssContext = NULL; void *result = NULL; PKIX_ENTER(MEM, "PKIX_PL_Calloc"); PKIX_NULLCHECK_ONE(pMemory); if ((nElem == 0) || (elSize == 0)){ *pMemory = NULL; } else { nssContext = (PKIX_PL_NssContext *)plContext; if (nssContext != NULL && nssContext->arena != NULL) { PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n"); *pMemory = PORT_ArenaAlloc(nssContext->arena, elSize); } else { PKIX_MEM_DEBUG("\tCalling PR_Calloc.\n"); result = (void *) PR_Calloc(nElem, elSize); if (result == NULL) { PKIX_MEM_DEBUG("Fatal Error Occurred: " "PR_Calloc failed.\n"); PKIX_ERROR_ALLOC_ERROR(); } else { *pMemory = result; } } } cleanup: PKIX_RETURN(MEM); }
/* * Initializes a SECItem from a hexadecimal string * * Warning: This function ignores leading 00's, so any leading 00's * in the hexadecimal string must be optional. */ static SECItem * hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str, int kmflag) { int i = 0; int byteval = 0; int tmp = strlen(str); if ((tmp % 2) != 0) return NULL; /* skip leading 00's unless the hex string is "00" */ while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) { str += 2; tmp -= 2; } item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2, kmflag); if (item->data == NULL) return NULL; item->len = tmp/2; while (str[i]) { if ((str[i] >= '0') && (str[i] <= '9')) tmp = str[i] - '0'; else if ((str[i] >= 'a') && (str[i] <= 'f')) tmp = str[i] - 'a' + 10; else if ((str[i] >= 'A') && (str[i] <= 'F')) tmp = str[i] - 'A' + 10; else return NULL; byteval = byteval * 16 + tmp; if ((i % 2) != 0) { item->data[i/2] = byteval; byteval = 0; } i++; } return item; }
SECStatus SECITEM_CopyItem(PRArenaPool *arena, SecAsn1Item *to, const SecAsn1Item *from) { // to->type = from->type; if (from->Data && from->Length) { if ( arena ) { to->Data = (unsigned char*) PORT_ArenaAlloc(arena, from->Length); } else { to->Data = (unsigned char*) PORT_Alloc(from->Length); } if (!to->Data) { return SECFailure; } PORT_Memcpy(to->Data, from->Data, from->Length); to->Length = from->Length; } else { to->Data = 0; to->Length = 0; } return SECSuccess; }
SECStatus SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item, unsigned int oldlen, unsigned int newlen) { PORT_Assert(item != NULL); if (item == NULL) { /* XXX Set error. But to what? */ return SECFailure; } /* * If no old length, degenerate to just plain alloc. */ if (oldlen == 0) { PORT_Assert(item->data == NULL || item->len == 0); if (newlen == 0) { /* Nothing to do. Weird, but not a failure. */ return SECSuccess; } item->len = newlen; if (arena != NULL) { item->data = PORT_ArenaAlloc(arena, newlen); } else { item->data = PORT_Alloc(newlen); } } else { if (arena != NULL) { item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen); } else { item->data = PORT_Realloc(item->data, newlen); } } if (item->data == NULL) { return SECFailure; } return SECSuccess; }
/* * smaller version of EC_FillParams. In this code, we only need * oid and DER data. */ SECStatus LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, ECParams *params) { SECOidTag tag; SECItem oid = { siBuffer, NULL, 0}; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; /* For named curves, fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len); if (params->curveOID.data == NULL) { return SECFailure; } memcpy(params->curveOID.data, oid.data, oid.len); return SECSuccess; }
/* * SecCmsArrayAdd - add an element to the end of an array * * The array of pointers is either created (if array was empty before) or grown. */ OSStatus SecCmsArrayAdd(PRArenaPool *poolp, void ***array, void *obj) { void **p; int n; void **dest; PORT_Assert(array != NULL); if (array == NULL) return SECFailure; if (*array == NULL) { dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); n = 0; } else { n = 0; p = *array; while (*p++) n++; if (n>=(int)((INT_MAX/sizeof(void *))-2)) { // Prevent under-allocation due to integer overflow return SECFailure; } dest = (void **)PORT_ArenaGrow (poolp, *array, (n + 1) * sizeof(void *), (n + 2) * sizeof(void *)); } if (dest == NULL) return SECFailure; dest[n] = obj; dest[n+1] = NULL; *array = dest; return SECSuccess; }
/* * set the hasRootCerts flags in the module so it can be stored back * into the database. */ void SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod) { PK11PreSlotInfo *psi = NULL; int i; if (slot->hasRootCerts) { for (i = 0; i < mod->slotInfoCount; i++) { if (slot->slotID == mod->slotInfo[i].slotID) { psi = &mod->slotInfo[i]; break; } } if (psi == NULL) { /* allocate more slots */ PK11PreSlotInfo *psi_list = (PK11PreSlotInfo *) PORT_ArenaAlloc(mod->arena, (mod->slotInfoCount + 1) * sizeof(PK11PreSlotInfo)); /* copy the old ones */ if (mod->slotInfoCount > 0) { PORT_Memcpy(psi_list, mod->slotInfo, (mod->slotInfoCount) * sizeof(PK11PreSlotInfo)); } /* assign psi to the last new slot */ psi = &psi_list[mod->slotInfoCount]; psi->slotID = slot->slotID; psi->askpw = 0; psi->timeout = 0; psi->defaultFlags = 0; /* increment module count & store new list */ mod->slotInfo = psi_list; mod->slotInfoCount++; } psi->hasRootCerts = 1; } }
SECItem * SECITEM_AllocItem(PLArenaPool *arena, SECItem *item, unsigned int len) { SECItem *result = NULL; void *mark = NULL; if (arena != NULL) { mark = PORT_ArenaMark(arena); } if (item == NULL) { if (arena != NULL) { result = PORT_ArenaZAlloc(arena, sizeof(SECItem)); } else { result = PORT_ZAlloc(sizeof(SECItem)); } if (result == NULL) { goto loser; } } else { PORT_Assert(item->data == NULL); result = item; } result->len = len; if (len) { if (arena != NULL) { result->data = PORT_ArenaAlloc(arena, len); } else { result->data = PORT_Alloc(len); } if (result->data == NULL) { goto loser; } } else { result->data = NULL; } if (mark) { PORT_ArenaUnmark(arena, mark); } return(result); loser: if ( arena != NULL ) { if (mark) { PORT_ArenaRelease(arena, mark); } if (item != NULL) { item->data = NULL; item->len = 0; } } else { if (result != NULL) { SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE); } /* * If item is not NULL, the above has set item->data and * item->len to 0. */ } return(NULL); }
static void fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced) { CERTCertTrust* trust = NULL; NSSTrust *nssTrust; NSSCryptoContext *context = c->object.cryptoContext; nssCryptokiInstance *instance; NSSUTF8 *stanNick = NULL; /* We are holding the base class object's lock on entry of this function * This lock protects writes to fields of the CERTCertificate . * It is also needed by some functions to compute values such as trust. */ instance = get_cert_instance(c); if (instance) { stanNick = instance->label; } else if (context) { stanNick = c->object.tempName; } /* fill other fields needed by NSS3 functions using CERTCertificate */ if ((!cc->nickname && stanNick) || forced) { PRStatus nssrv; int nicklen, tokenlen, len; NSSUTF8 *tokenName = NULL; char *nick; if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) || (stanNick && PORT_Strchr(stanNick, ':') != NULL))) { tokenName = nssToken_GetName(instance->token); tokenlen = nssUTF8_Size(tokenName, &nssrv); } else { /* don't use token name for internal slot; 3.3 didn't */ tokenlen = 0; } if (stanNick) { nicklen = nssUTF8_Size(stanNick, &nssrv); len = tokenlen + nicklen; nick = PORT_ArenaAlloc(cc->arena, len); if (tokenName) { memcpy(nick, tokenName, tokenlen-1); nick[tokenlen-1] = ':'; memcpy(nick+tokenlen, stanNick, nicklen-1); } else { memcpy(nick, stanNick, nicklen-1); } nick[len-1] = '\0'; cc->nickname = nick; } else { cc->nickname = NULL; } } if (context) { /* trust */ nssTrust = nssCryptoContext_FindTrustForCertificate(context, c); if (!nssTrust) { /* chicken and egg issue: * * c->issuer and c->serial are empty at this point, but * nssTrustDomain_FindTrustForCertificate use them to look up * up the trust object, so we point them to cc->derIssuer and * cc->serialNumber. * * Our caller will fill these in with proper arena copies when we * return. */ c->issuer.data = cc->derIssuer.data; c->issuer.size = cc->derIssuer.len; c->serial.data = cc->serialNumber.data; c->serial.size = cc->serialNumber.len; nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c); } if (nssTrust) { trust = cert_trust_from_stan_trust(nssTrust, cc->arena); if (trust) { /* we should destroy cc->trust before replacing it, but it's allocated in cc->arena, so memory growth will occur on each refresh */ CERT_LockCertTrust(cc); cc->trust = trust; CERT_UnlockCertTrust(cc); } nssTrust_Destroy(nssTrust); } } else if (instance) { /* slot */ if (cc->slot != instance->token->pk11slot) { if (cc->slot) { PK11_FreeSlot(cc->slot); } cc->slot = PK11_ReferenceSlot(instance->token->pk11slot); } cc->ownSlot = PR_TRUE; /* pkcs11ID */ cc->pkcs11ID = instance->handle; /* trust */ trust = nssTrust_GetCERTCertTrustForCert(c, cc); if (trust) { /* we should destroy cc->trust before replacing it, but it's allocated in cc->arena, so memory growth will occur on each refresh */ CERT_LockCertTrust(cc); cc->trust = trust; CERT_UnlockCertTrust(cc); } nssCryptokiObject_Destroy(instance); } /* database handle is now the trust domain */ cc->dbhandle = c->object.trustDomain; /* subjectList ? */ /* istemp and isperm are supported in NSS 3.4 */ cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */ cc->isperm = PR_TRUE; /* by default */ /* pointer back */ cc->nssCertificate = c; if (trust) { /* force the cert type to be recomputed to include trust info */ PRUint32 nsCertType = cert_ComputeCertType(cc); /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */ PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32)); PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType); } }
static NSSLOWKEYPrivateKey * lg_mkSecretKeyRep(const CK_ATTRIBUTE *templ, CK_ULONG count, CK_KEY_TYPE key_type, SECItem *pubkey, SDB *sdbpw) { NSSLOWKEYPrivateKey *privKey = 0; PLArenaPool *arena = 0; CK_KEY_TYPE keyType; PRUint32 keyTypeStorage; SECItem keyTypeItem; CK_RV crv; SECStatus rv; static unsigned char derZero[1] = { 0 }; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; } privKey = (NSSLOWKEYPrivateKey *) PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPrivateKey)); if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; } privKey->arena = arena; /* Secret keys are represented in the database as "fake" RSA keys. * The RSA key is marked as a secret key representation by setting the * public exponent field to 0, which is an invalid RSA exponent. * The other fields are set as follows: * modulus - CKA_ID value for the secret key * private exponent - CKA_VALUE (the key itself) * coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm * is used for the key. * all others - set to integer 0 */ privKey->keyType = NSSLOWKEYRSAKey; /* The modulus is set to the key id of the symmetric key */ privKey->u.rsa.modulus.data = (unsigned char *)PORT_ArenaAlloc(arena, pubkey->len); if (privKey->u.rsa.modulus.data == NULL) { crv = CKR_HOST_MEMORY; goto loser; } privKey->u.rsa.modulus.len = pubkey->len; PORT_Memcpy(privKey->u.rsa.modulus.data, pubkey->data, pubkey->len); /* The public exponent is set to 0 to indicate a special key */ privKey->u.rsa.publicExponent.len = sizeof derZero; privKey->u.rsa.publicExponent.data = derZero; /* The private exponent is the actual key value */ crv = lg_PrivAttr2SecItem(arena, CKA_VALUE, templ, count, &privKey->u.rsa.privateExponent, sdbpw); if (crv != CKR_OK) goto loser; /* All other fields empty - needs testing */ privKey->u.rsa.prime1.len = sizeof derZero; privKey->u.rsa.prime1.data = derZero; privKey->u.rsa.prime2.len = sizeof derZero; privKey->u.rsa.prime2.data = derZero; privKey->u.rsa.exponent1.len = sizeof derZero; privKey->u.rsa.exponent1.data = derZero; privKey->u.rsa.exponent2.len = sizeof derZero; privKey->u.rsa.exponent2.data = derZero; /* Coeficient set to KEY_TYPE */ crv = lg_GetULongAttribute(CKA_KEY_TYPE, templ, count, &keyType); if (crv != CKR_OK) goto loser; /* on 64 bit platforms, we still want to store 32 bits of keyType (This is * safe since the PKCS #11 defines for all types are 32 bits or less). */ keyTypeStorage = (PRUint32)keyType; keyTypeStorage = PR_htonl(keyTypeStorage); keyTypeItem.data = (unsigned char *)&keyTypeStorage; keyTypeItem.len = sizeof(keyTypeStorage); rv = SECITEM_CopyItem(arena, &privKey->u.rsa.coefficient, &keyTypeItem); if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; } /* Private key version field set normally for compatibility */ rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, NSSLOWKEY_VERSION); if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; } loser: if (crv != CKR_OK) { PORT_FreeArena(arena, PR_FALSE); privKey = 0; } return privKey; }
NSS_EXTERN PRStatus STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust) { PRStatus nssrv; NSSCertificate *c = STAN_GetNSSCertificate(cc); NSSToken *tok; NSSTrustDomain *td; NSSTrust *nssTrust; NSSArena *arena; CERTCertTrust *oldTrust; CERTCertTrust *newTrust; nssListIterator *tokens; PRBool moving_object; nssCryptokiObject *newInstance; nssPKIObject *pkiob; if (c == NULL) { return PR_FAILURE; } oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc); if (oldTrust) { if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) { /* ... and the new trust is no different, done) */ return PR_SUCCESS; } else { /* take over memory already allocated in cc's arena */ newTrust = oldTrust; } } else { newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust)); } memcpy(newTrust, trust, sizeof(CERTCertTrust)); CERT_LockCertTrust(cc); cc->trust = newTrust; CERT_UnlockCertTrust(cc); /* Set the NSSCerticate's trust */ arena = nssArena_Create(); if (!arena) return PR_FAILURE; nssTrust = nss_ZNEW(arena, NSSTrust); if (!nssTrust) { nssArena_Destroy(arena); return PR_FAILURE; } pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock); if (!pkiob) { nssArena_Destroy(arena); return PR_FAILURE; } nssTrust->object = *pkiob; nssTrust->certificate = c; nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE); nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE); nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE); nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE); nssTrust->stepUpApproved = (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA); if (c->object.cryptoContext != NULL) { /* The cert is in a context, set the trust there */ NSSCryptoContext *cc = c->object.cryptoContext; nssrv = nssCryptoContext_ImportTrust(cc, nssTrust); if (nssrv != PR_SUCCESS) { goto done; } if (c->object.numInstances == 0) { /* The context is the only instance, finished */ goto done; } } td = STAN_GetDefaultTrustDomain(); tok = stan_GetTrustToken(c); moving_object = PR_FALSE; if (tok && PK11_IsReadOnly(tok->pk11slot)) { NSSRWLock_LockRead(td->tokensLock); tokens = nssList_CreateIterator(td->tokenList); if (!tokens) { nssrv = PR_FAILURE; NSSRWLock_UnlockRead(td->tokensLock); goto done; } for (tok = (NSSToken *)nssListIterator_Start(tokens); tok != (NSSToken *)NULL; tok = (NSSToken *)nssListIterator_Next(tokens)) { if (!PK11_IsReadOnly(tok->pk11slot)) break; } nssListIterator_Finish(tokens); nssListIterator_Destroy(tokens); NSSRWLock_UnlockRead(td->tokensLock); moving_object = PR_TRUE; } if (tok) { if (moving_object) { /* this is kind of hacky. the softoken needs the cert * object in order to store trust. forcing it to be perm */ NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); NSSASCII7 *email = NULL; if (PK11_IsInternal(tok->pk11slot)) { email = c->email; } newInstance = nssToken_ImportCertificate(tok, NULL, NSSCertificateType_PKIX, &c->id, nickname, &c->encoding, &c->issuer, &c->subject, &c->serial, email, PR_TRUE); nss_ZFreeIf(nickname); nickname = NULL; if (!newInstance) { nssrv = PR_FAILURE; goto done; } nssPKIObject_AddInstance(&c->object, newInstance); } newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, &c->issuer, &c->serial, nssTrust->serverAuth, nssTrust->clientAuth, nssTrust->codeSigning, nssTrust->emailProtection, nssTrust->stepUpApproved, PR_TRUE); /* If the selected token can't handle trust, dump the trust on * the internal token */ if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL); NSSASCII7 *email = c->email; tok = PK11Slot_GetNSSToken(slot); PK11_FreeSlot(slot); newInstance = nssToken_ImportCertificate(tok, NULL, NSSCertificateType_PKIX, &c->id, nickname, &c->encoding, &c->issuer, &c->subject, &c->serial, email, PR_TRUE); nss_ZFreeIf(nickname); nickname = NULL; if (!newInstance) { nssrv = PR_FAILURE; goto done; } nssPKIObject_AddInstance(&c->object, newInstance); newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding, &c->issuer, &c->serial, nssTrust->serverAuth, nssTrust->clientAuth, nssTrust->codeSigning, nssTrust->emailProtection, nssTrust->stepUpApproved, PR_TRUE); } if (newInstance) { nssCryptokiObject_Destroy(newInstance); nssrv = PR_SUCCESS; } else { nssrv = PR_FAILURE; } } else { nssrv = PR_FAILURE; } done: (void)nssTrust_Destroy(nssTrust); return nssrv; }
static SECStatus pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg) { SECItem* derCrl = NULL; crlOptions* options = (crlOptions*) arg; CERTCrlHeadNode *head = options->head; CERTCrlNode *new_node = NULL; CK_ATTRIBUTE fetchCrl[3] = { { CKA_VALUE, NULL, 0}, { CKA_NETSCAPE_KRL, NULL, 0}, { CKA_NETSCAPE_URL, NULL, 0}, }; const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]); CK_RV crv; SECStatus rv = SECFailure; PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory successfully */ int i; crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize); if (CKR_OK != crv) { PORT_SetError(PK11_MapError(crv)); goto loser; } if (!fetchCrl[1].pValue) { /* reject KRLs */ PORT_SetError(SEC_ERROR_CRL_INVALID); goto loser; } new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode)); if (new_node == NULL) { goto loser; } new_node->type = SEC_CRL_TYPE; derCrl = SECITEM_AllocItem(NULL, NULL, 0); if (!derCrl) { goto loser; } derCrl->type = siBuffer; derCrl->data = (unsigned char *)fetchCrl[0].pValue; derCrl->len = fetchCrl[0].ulValueLen; new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type, options->decodeOptions); if (new_node->crl == NULL) { goto loser; } adopted = PR_TRUE; /* now that the CRL has adopted the DER memory, we won't need to free it upon exit */ if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) { /* copy the URL if there is one */ int nnlen = fetchCrl[2].ulValueLen; new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena, nnlen+1); if ( !new_node->crl->url ) { goto loser; } PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); new_node->crl->url[nnlen] = 0; } else { new_node->crl->url = NULL; } new_node->next = NULL; if (head->last) { head->last->next = new_node; head->last = new_node; } else { head->first = head->last = new_node; } rv = SECSuccess; new_node->crl->slot = PK11_ReferenceSlot(slot); new_node->crl->pkcs11ID = crlID; loser: /* free attributes that weren't adopted by the CRL */ for (i=1;i<fetchCrlSize;i++) { if (fetchCrl[i].pValue) { PORT_Free(fetchCrl[i].pValue); } } /* free the DER if the CRL object didn't adopt it */ if (fetchCrl[0].pValue && PR_FALSE == adopted) { PORT_Free(fetchCrl[0].pValue); } if (derCrl && !adopted) { /* clear the data fields, which we already took care of above */ derCrl->data = NULL; derCrl->len = 0; /* free the memory for the SECItem structure itself */ SECITEM_FreeItem(derCrl, PR_TRUE); } return(rv); }
static SECStatus pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg) { SECItem derCrl; CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg; CERTCrlNode *new_node = NULL; CK_ATTRIBUTE fetchCrl[3] = { { CKA_VALUE, NULL, 0}, { CKA_NETSCAPE_KRL, NULL, 0}, { CKA_NETSCAPE_URL, NULL, 0}, }; const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]); CK_RV crv; SECStatus rv = SECFailure; crv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize); if (CKR_OK != crv) { PORT_SetError(PK11_MapError(crv)); goto loser; } if (!fetchCrl[1].pValue) { PORT_SetError(SEC_ERROR_CRL_INVALID); goto loser; } new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode)); if (new_node == NULL) { goto loser; } if (*((CK_BBOOL *)fetchCrl[1].pValue)) new_node->type = SEC_KRL_TYPE; else new_node->type = SEC_CRL_TYPE; derCrl.type = siBuffer; derCrl.data = (unsigned char *)fetchCrl[0].pValue; derCrl.len = fetchCrl[0].ulValueLen; new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type); if (new_node->crl == NULL) { goto loser; } if (fetchCrl[2].pValue) { int nnlen = fetchCrl[2].ulValueLen; new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen+1); if ( !new_node->crl->url ) { goto loser; } PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); new_node->crl->url[nnlen] = 0; } else { new_node->crl->url = NULL; } new_node->next = NULL; if (head->last) { head->last->next = new_node; head->last = new_node; } else { head->first = head->last = new_node; } rv = SECSuccess; loser: return(rv); }
// Extract the issuer and serial number from a certificate SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) { OSStatus status; SecCmsIssuerAndSN *certIssuerAndSN; CSSM_CL_HANDLE clHandle; CSSM_DATA_PTR serialNumber = 0; CSSM_DATA_PTR issuer = 0; CSSM_DATA certData = {}; CSSM_HANDLE resultsHandle = 0; uint32 numberOfFields = 0; CSSM_RETURN result; void *mark; mark = PORT_ArenaMark(pl); status = SecCertificateGetCLHandle(cert, &clHandle); if (status) goto loser; status = SecCertificateGetData(cert, &certData); if (status) goto loser; /* Get the issuer from the cert. */ result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); if (result || numberOfFields < 1) goto loser; result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); if (result) goto loser; /* Get the serialNumber from the cert. */ result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); if (result || numberOfFields < 1) goto loser; result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); if (result) goto loser; /* Allocate the SecCmsIssuerAndSN struct. */ certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); if (certIssuerAndSN == NULL) goto loser; /* Copy the issuer. */ certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length); if (!certIssuerAndSN->derIssuer.Data) goto loser; PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length); certIssuerAndSN->derIssuer.Length = issuer->Length; /* Copy the serialNumber. */ certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length); if (!certIssuerAndSN->serialNumber.Data) goto loser; PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length); certIssuerAndSN->serialNumber.Length = serialNumber->Length; PORT_ArenaUnmark(pl, mark); CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); return certIssuerAndSN; loser: PORT_ArenaRelease(pl, mark); if (serialNumber) CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); if (issuer) CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); PORT_SetError(SEC_INTERNAL_ONLY); return NULL; }
/* * SecCmsSignedDataEncodeAfterData - do all the necessary things to a SignedData * after all the encapsulated data was passed through the encoder. * * In detail: * - create the signatures in all the SignerInfos * * Please note that nothing is done to the Certificates and CRLs in the message - this * is entirely the responsibility of our callers. */ OSStatus SecCmsSignedDataEncodeAfterData(SecCmsSignedDataRef sigd) { SecCmsSignerInfoRef *signerinfos, signerinfo; SecCmsContentInfoRef cinfo; SECOidTag digestalgtag; OSStatus ret = SECFailure; OSStatus rv; CSSM_DATA_PTR contentType; int certcount; int i, ci, n, rci, si; PLArenaPool *poolp; CFArrayRef certlist; extern const SecAsn1Template SecCmsSignerInfoTemplate[]; poolp = sigd->cmsg->poolp; cinfo = &(sigd->contentInfo); /* did we have digest calculation going on? */ if (cinfo->digcx) { rv = SecCmsDigestContextFinishMultiple(cinfo->digcx, (SecArenaPoolRef)poolp, &(sigd->digests)); if (rv != SECSuccess) goto loser; /* error has been set by SecCmsDigestContextFinishMultiple */ cinfo->digcx = NULL; } signerinfos = sigd->signerInfos; certcount = 0; /* prepare all the SignerInfos (there may be none) */ for (i=0; i < SecCmsSignedDataSignerInfoCount(sigd); i++) { signerinfo = SecCmsSignedDataGetSignerInfo(sigd, i); /* find correct digest for this signerinfo */ digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); if (n < 0 || sigd->digests == NULL || sigd->digests[n] == NULL) { /* oops - digest not found */ PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); goto loser; } /* XXX if our content is anything else but data, we need to force the * presence of signed attributes (RFC2630 5.3 "signedAttributes is a * collection...") */ /* pass contentType here as we want a contentType attribute */ if ((contentType = SecCmsContentInfoGetContentTypeOID(cinfo)) == NULL) goto loser; /* sign the thing */ rv = SecCmsSignerInfoSign(signerinfo, sigd->digests[n], contentType); if (rv != SECSuccess) goto loser; /* while we're at it, count number of certs in certLists */ certlist = SecCmsSignerInfoGetCertList(signerinfo); if (certlist) certcount += CFArrayGetCount(certlist); } /* Now we can get a timestamp, since we have all the digests */ // We force the setting of a callback, since this is the most usual case if (!sigd->cmsg->tsaCallback) SecCmsMessageSetTSACallback(sigd->cmsg, (SecCmsTSACallback)SecCmsTSADefaultCallback); if (sigd->cmsg->tsaCallback && sigd->cmsg->tsaContext) { CSSM_DATA tsaResponse = {0,}; SecAsn1TSAMessageImprint messageImprint = {{{0},},{0,}}; // <rdar://problem/11073466> Add nonce support for timestamping client uint64_t nonce = 0; require_noerr(getRandomNonce(&nonce), tsxit); dprintf("SecCmsSignedDataSignerInfoCount: %d\n", SecCmsSignedDataSignerInfoCount(sigd)); // Calculate hash of encDigest and put in messageImprint.hashedMessage SecCmsSignerInfoRef signerinfo = SecCmsSignedDataGetSignerInfo(sigd, 0); // NB - assume 1 signer only! CSSM_DATA *encDigest = SecCmsSignerInfoGetEncDigest(signerinfo); require_noerr(createTSAMessageImprint(sigd, encDigest, &messageImprint), tsxit); // Callback to fire up XPC service to talk to TimeStamping server, etc. require_noerr(rv =(*sigd->cmsg->tsaCallback)(sigd->cmsg->tsaContext, &messageImprint, nonce, &tsaResponse), tsxit); require_noerr(rv = validateTSAResponseAndAddTimeStamp(signerinfo, &tsaResponse, nonce), tsxit); /* It is likely that every occurrence of "goto loser" in this file should also do a PORT_SetError. Since it is not clear what might depend on this behavior, we just do this in the timestamping case. */ tsxit: if (rv) { dprintf("Original timestamp error: %d\n", (int)rv); rv = remapTimestampError(rv); PORT_SetError(rv); goto loser; } } /* this is a SET OF, so we need to sort them guys */ rv = SecCmsArraySortByDER((void **)signerinfos, SecCmsSignerInfoTemplate, NULL); if (rv != SECSuccess) goto loser; /* * now prepare certs & crls */ /* count the rest of the certs */ if (sigd->certs != NULL) certcount += CFArrayGetCount(sigd->certs); if (certcount == 0) { sigd->rawCerts = NULL; } else { /* * Combine all of the certs and cert chains into rawcerts. * Note: certcount is an upper bound; we may not need that many slots * but we will allocate anyway to avoid having to do another pass. * (The temporary space saving is not worth it.) * * XXX ARGH - this NEEDS to be fixed. need to come up with a decent * SetOfDERcertficates implementation */ sigd->rawCerts = (CSSM_DATA_PTR *)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(CSSM_DATA_PTR)); if (sigd->rawCerts == NULL) return SECFailure; /* * XXX Want to check for duplicates and not add *any* cert that is * already in the set. This will be more important when we start * dealing with larger sets of certs, dual-key certs (signing and * encryption), etc. For the time being we can slide by... * * XXX ARGH - this NEEDS to be fixed. need to come up with a decent * SetOfDERcertficates implementation */ rci = 0; if (signerinfos != NULL) { for (si = 0; signerinfos[si] != NULL; si++) { signerinfo = signerinfos[si]; for (ci = 0; ci < CFArrayGetCount(signerinfo->certList); ci++) { sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(CSSM_DATA)); SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(signerinfo->certList, ci); SecCertificateGetData(cert, sigd->rawCerts[rci++]); } } } if (sigd->certs != NULL) { for (ci = 0; ci < CFArrayGetCount(sigd->certs); ci++) { sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(CSSM_DATA)); SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(sigd->certs, ci); SecCertificateGetData(cert, sigd->rawCerts[rci++]); } } sigd->rawCerts[rci] = NULL; /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ SecCmsArraySort((void **)sigd->rawCerts, SecCmsUtilDERCompare, NULL, NULL); } ret = SECSuccess; loser: dprintf("SecCmsSignedDataEncodeAfterData: ret: %ld, rv: %ld\n", (long)ret, (long)rv); return ret; }
static PRStatus CollectNicknames( NSSCertificate *c, void *data) { CERTCertNicknames *names; PRBool saveit = PR_FALSE; stringNode *node; int len; #ifdef notdef NSSTrustDomain *td; NSSTrust *trust; #endif char *stanNickname; char *nickname = NULL; names = (CERTCertNicknames *)data; stanNickname = nssCertificate_GetNickname(c,NULL); if ( stanNickname ) { nss_ZFreeIf(stanNickname); stanNickname = NULL; if (names->what == SEC_CERT_NICKNAMES_USER) { saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL); } #ifdef notdef else { td = NSSCertificate_GetTrustDomain(c); if (!td) { return PR_SUCCESS; } trust = nssTrustDomain_FindTrustForCertificate(td,c); switch(names->what) { case SEC_CERT_NICKNAMES_ALL: if ((trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) || (trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) || (trust->objectSigningFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER))) { saveit = PR_TRUE; } break; case SEC_CERT_NICKNAMES_SERVER: if ( trust->sslFlags & CERTDB_VALID_PEER ) { saveit = PR_TRUE; } break; case SEC_CERT_NICKNAMES_CA: if (((trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)|| ((trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA) || ((trust->objectSigningFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA)) { saveit = PR_TRUE; } break; } } #endif } /* traverse the list of collected nicknames and make sure we don't make * a duplicate */ if ( saveit ) { nickname = STAN_GetCERTCertificateName(NULL, c); /* nickname can only be NULL here if we are having memory * alloc problems */ if (nickname == NULL) { return PR_FAILURE; } node = (stringNode *)names->head; while ( node != NULL ) { if ( PORT_Strcmp(nickname, node->string) == 0 ) { /* if the string matches, then don't save this one */ saveit = PR_FALSE; break; } node = node->next; } } if ( saveit ) { /* allocate the node */ node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode)); if ( node == NULL ) { PORT_Free(nickname); return PR_FAILURE; } /* copy the string */ len = PORT_Strlen(nickname) + 1; node->string = (char*)PORT_ArenaAlloc(names->arena, len); if ( node->string == NULL ) { PORT_Free(nickname); return PR_FAILURE; } PORT_Memcpy(node->string, nickname, len); /* link it into the list */ node->next = (stringNode *)names->head; names->head = (void *)node; /* bump the count */ names->numnicknames++; } if (nickname) PORT_Free(nickname); return(PR_SUCCESS); }
static SECStatus GenerateCRL (CERTCertDBHandle *certHandle, char *certNickName, PRFileDesc *inCrlInitFile, PRFileDesc *inFile, char *outFileName, int ascii, char *slotName, PRInt32 importOptions, char *alg, PRBool quiet, PRInt32 decodeOptions, char *url, secuPWData *pwdata, int modifyFlag) { CERTCertificate *cert = NULL; CERTSignedCrl *signCrl = NULL; PLArenaPool *arena = NULL; SECStatus rv; SECOidTag hashAlgTag = SEC_OID_UNKNOWN; if (alg) { hashAlgTag = SECU_StringToSignatureAlgTag(alg); if (hashAlgTag == SEC_OID_UNKNOWN) { SECU_PrintError(progName, "%s -Z: %s is not a recognized type.\n", progName, alg); return SECFailure; } } else { hashAlgTag = SEC_OID_UNKNOWN; } arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); if (!arena) { SECU_PrintError(progName, "fail to allocate memory\n"); return SECFailure; } if (modifyFlag == PR_TRUE) { signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName, inFile, decodeOptions, importOptions); if (signCrl == NULL) { goto loser; } } if (!cert) { cert = FindSigningCert(certHandle, signCrl, certNickName); if (cert == NULL) { goto loser; } } if (!signCrl) { if (modifyFlag == PR_TRUE) { if (!outFileName) { int len = strlen(certNickName) + 5; outFileName = PORT_ArenaAlloc(arena, len); PR_snprintf(outFileName, len, "%s.crl", certNickName); } SECU_PrintError(progName, "Will try to generate crl. " "It will be saved in file: %s", outFileName); } signCrl = CreateNewCrl(arena, certHandle, cert); if (!signCrl) goto loser; } rv = UpdateCrl(signCrl, inCrlInitFile); if (rv != SECSuccess) { goto loser; } rv = SignAndStoreCrl(signCrl, cert, outFileName, hashAlgTag, ascii, slotName, url, pwdata); if (rv != SECSuccess) { goto loser; } if (signCrl && !quiet) { SECU_PrintCRLInfo (stdout, &signCrl->crl, "CRL Info:\n", 0); } loser: if (arena && (!signCrl || !signCrl->arena)) PORT_FreeArena (arena, PR_FALSE); if (signCrl) SEC_DestroyCrl (signCrl); if (cert) CERT_DestroyCertificate (cert); return (rv); }
/* * NSS_CMSSignedData_Encode_AfterData - do all the necessary things to a SignedData * after all the encapsulated data was passed through the encoder. * * In detail: * - create the signatures in all the SignerInfos * * Please note that nothing is done to the Certificates and CRLs in the message - this * is entirely the responsibility of our callers. */ SECStatus NSS_CMSSignedData_Encode_AfterData(NSSCMSSignedData *sigd) { NSSCMSSignerInfo **signerinfos, *signerinfo; NSSCMSContentInfo *cinfo; SECOidTag digestalgtag; SECStatus ret = SECFailure; SECStatus rv; SECItem *contentType; int certcount; int i, ci, cli, n, rci, si; PLArenaPool *poolp; CERTCertificateList *certlist; extern const SEC_ASN1Template NSSCMSSignerInfoTemplate[]; if (!sigd) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } poolp = sigd->cmsg->poolp; cinfo = &(sigd->contentInfo); /* did we have digest calculation going on? */ if (cinfo->privateInfo && cinfo->privateInfo->digcx) { rv = NSS_CMSDigestContext_FinishMultiple(cinfo->privateInfo->digcx, poolp, &(sigd->digests)); /* error has been set by NSS_CMSDigestContext_FinishMultiple */ cinfo->privateInfo->digcx = NULL; if (rv != SECSuccess) goto loser; } signerinfos = sigd->signerInfos; certcount = 0; /* prepare all the SignerInfos (there may be none) */ for (i = 0; i < NSS_CMSSignedData_SignerInfoCount(sigd); i++) { signerinfo = NSS_CMSSignedData_GetSignerInfo(sigd, i); /* find correct digest for this signerinfo */ digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo); n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); if (n < 0 || sigd->digests == NULL || sigd->digests[n] == NULL) { /* oops - digest not found */ PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); goto loser; } /* XXX if our content is anything else but data, we need to force the * presence of signed attributes (RFC2630 5.3 "signedAttributes is a * collection...") */ /* pass contentType here as we want a contentType attribute */ if ((contentType = NSS_CMSContentInfo_GetContentTypeOID(cinfo)) == NULL) goto loser; /* sign the thing */ rv = NSS_CMSSignerInfo_Sign(signerinfo, sigd->digests[n], contentType); if (rv != SECSuccess) goto loser; /* while we're at it, count number of certs in certLists */ certlist = NSS_CMSSignerInfo_GetCertList(signerinfo); if (certlist) certcount += certlist->len; } /* this is a SET OF, so we need to sort them guys */ rv = NSS_CMSArray_SortByDER((void **)signerinfos, NSSCMSSignerInfoTemplate, NULL); if (rv != SECSuccess) goto loser; /* * now prepare certs & crls */ /* count the rest of the certs */ if (sigd->certs != NULL) { for (ci = 0; sigd->certs[ci] != NULL; ci++) certcount++; } if (sigd->certLists != NULL) { for (cli = 0; sigd->certLists[cli] != NULL; cli++) certcount += sigd->certLists[cli]->len; } if (certcount == 0) { sigd->rawCerts = NULL; } else { /* * Combine all of the certs and cert chains into rawcerts. * Note: certcount is an upper bound; we may not need that many slots * but we will allocate anyway to avoid having to do another pass. * (The temporary space saving is not worth it.) * * XXX ARGH - this NEEDS to be fixed. need to come up with a decent * SetOfDERcertficates implementation */ sigd->rawCerts = (SECItem **)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(SECItem *)); if (sigd->rawCerts == NULL) return SECFailure; /* * XXX Want to check for duplicates and not add *any* cert that is * already in the set. This will be more important when we start * dealing with larger sets of certs, dual-key certs (signing and * encryption), etc. For the time being we can slide by... * * XXX ARGH - this NEEDS to be fixed. need to come up with a decent * SetOfDERcertficates implementation */ rci = 0; if (signerinfos != NULL) { for (si = 0; signerinfos[si] != NULL; si++) { signerinfo = signerinfos[si]; for (ci = 0; ci < signerinfo->certList->len; ci++) sigd->rawCerts[rci++] = &(signerinfo->certList->certs[ci]); } } if (sigd->certs != NULL) { for (ci = 0; sigd->certs[ci] != NULL; ci++) sigd->rawCerts[rci++] = &(sigd->certs[ci]->derCert); } if (sigd->certLists != NULL) { for (cli = 0; sigd->certLists[cli] != NULL; cli++) { for (ci = 0; ci < sigd->certLists[cli]->len; ci++) sigd->rawCerts[rci++] = &(sigd->certLists[cli]->certs[ci]); } } sigd->rawCerts[rci] = NULL; /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ NSS_CMSArray_Sort((void **)sigd->rawCerts, NSS_CMSUtil_DERCompare, NULL, NULL); } ret = SECSuccess; loser: return ret; }
SECStatus NSS_CMSUtil_EncryptSymKey_ESDH(PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *key, SECItem *encKey, SECItem **ukm, SECAlgorithmID *keyEncAlg, SECItem *pubKey) { #if 0 /* not yet done */ SECOidTag certalgtag; /* the certificate's encryption algorithm */ SECOidTag encalgtag; /* the algorithm used for key exchange/agreement */ SECStatus rv; SECItem *params = NULL; int data_len; SECStatus err; PK11SymKey *tek; CERTCertificate *ourCert; SECKEYPublicKey *ourPubKey; NSSCMSKEATemplateSelector whichKEA = NSSCMSKEAInvalid; certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); PORT_Assert(certalgtag == SEC_OID_X942_DIFFIE_HELMAN_KEY); /* We really want to show our KEA tag as the key exchange algorithm tag. */ encalgtag = SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN; /* Get the public key of the recipient. */ publickey = CERT_ExtractPublicKey(cert); if (publickey == NULL) goto loser; /* XXXX generate a DH key pair on a PKCS11 module (XXX which parameters?) */ /* XXXX */ourCert = PK11_FindBestKEAMatch(cert, wincx); if (ourCert == NULL) goto loser; arena = PORT_NewArena(1024); if (arena == NULL) goto loser; /* While we're here, extract the key pair's public key data and copy it into */ /* the outgoing parameters. */ /* XXXX */ourPubKey = CERT_ExtractPublicKey(ourCert); if (ourPubKey == NULL) { goto loser; } SECITEM_CopyItem(arena, pubKey, /* XXX */&(ourPubKey->u.fortezza.KEAKey)); SECKEY_DestroyPublicKey(ourPubKey); /* we only need the private key from now on */ ourPubKey = NULL; /* Extract our private key in order to derive the KEA key. */ ourPrivKey = PK11_FindKeyByAnyCert(ourCert,wincx); CERT_DestroyCertificate(ourCert); /* we're done with this */ if (!ourPrivKey) goto loser; /* If ukm desired, prepare it - allocate enough space (filled with zeros). */ if (ukm) { ukm->data = (unsigned char*)PORT_ArenaZAlloc(arena,/* XXXX */); ukm->len = /* XXXX */; } /* Generate the KEK (key exchange key) according to RFC2631 which we use * to wrap the bulk encryption key. */ kek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE, ukm, NULL, /* XXXX */CKM_KEA_KEY_DERIVE, /* XXXX */CKM_SKIPJACK_WRAP, CKA_WRAP, 0, wincx); SECKEY_DestroyPublicKey(publickey); SECKEY_DestroyPrivateKey(ourPrivKey); publickey = NULL; ourPrivKey = NULL; if (!kek) goto loser; /* allocate space for the encrypted CEK (bulk key) */ encKey->data = (unsigned char*)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE); encKey->len = SMIME_FORTEZZA_MAX_KEY_SIZE; if (encKey->data == NULL) { PK11_FreeSymKey(kek); goto loser; } /* Wrap the bulk key using CMSRC2WRAP or CMS3DESWRAP, depending on the */ /* bulk encryption algorithm */ switch (/* XXXX */PK11_AlgtagToMechanism(enccinfo->encalg)) { case /* XXXX */CKM_SKIPJACK_CFB8: err = PK11_WrapSymKey(/* XXXX */CKM_CMS3DES_WRAP, NULL, kek, bulkkey, encKey); whichKEA = NSSCMSKEAUsesSkipjack; break; case /* XXXX */CKM_SKIPJACK_CFB8: err = PK11_WrapSymKey(/* XXXX */CKM_CMSRC2_WRAP, NULL, kek, bulkkey, encKey); whichKEA = NSSCMSKEAUsesSkipjack; break; default: /* XXXX what do we do here? Neither RC2 nor 3DES... */ err = SECFailure; /* set error */ break; } PK11_FreeSymKey(kek); /* we do not need the KEK anymore */ if (err != SECSuccess) goto loser; PORT_Assert(whichKEA != NSSCMSKEAInvalid); /* see RFC2630 12.3.1.1 "keyEncryptionAlgorithm must be ..." */ /* params is the DER encoded key wrap algorithm (with parameters!) (XXX) */ params = SEC_ASN1EncodeItem(arena, NULL, &keaParams, sec_pkcs7_get_kea_template(whichKEA)); if (params == NULL) goto loser; /* now set keyEncAlg */ rv = SECOID_SetAlgorithmID(poolp, keyEncAlg, SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN, params); if (rv != SECSuccess) goto loser; /* XXXXXXX this is not right yet */ loser: if (arena) { PORT_FreeArena(arena, PR_FALSE); } if (publickey) { SECKEY_DestroyPublicKey(publickey); } if (ourPrivKey) { SECKEY_DestroyPrivateKey(ourPrivKey); } #endif return SECFailure; }
SECStatus NSS_CMSUtil_EncryptSymKey_MISSI(PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *bulkkey, SECOidTag symalgtag, SECItem *encKey, SECItem **pparams, void *pwfn_arg) { SECOidTag certalgtag; /* the certificate's encryption algorithm */ SECOidTag encalgtag; /* the algorithm used for key exchange/agreement */ SECStatus rv = SECFailure; SECItem *params = NULL; SECStatus err; PK11SymKey *tek; CERTCertificate *ourCert; SECKEYPublicKey *ourPubKey, *publickey = NULL; SECKEYPrivateKey *ourPrivKey = NULL; NSSCMSKEATemplateSelector whichKEA = NSSCMSKEAInvalid; NSSCMSSMIMEKEAParameters keaParams; PLArenaPool *arena = NULL; extern const SEC_ASN1Template *nss_cms_get_kea_template(NSSCMSKEATemplateSelector whichTemplate); /* Clear keaParams, since cleanup code checks the lengths */ (void) memset(&keaParams, 0, sizeof(keaParams)); certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); PORT_Assert(certalgtag == SEC_OID_MISSI_KEA_DSS_OLD || certalgtag == SEC_OID_MISSI_KEA_DSS || certalgtag == SEC_OID_MISSI_KEA); #define SMIME_FORTEZZA_RA_LENGTH 128 #define SMIME_FORTEZZA_IV_LENGTH 24 #define SMIME_FORTEZZA_MAX_KEY_SIZE 256 /* We really want to show our KEA tag as the key exchange algorithm tag. */ encalgtag = SEC_OID_NETSCAPE_SMIME_KEA; /* Get the public key of the recipient. */ publickey = CERT_ExtractPublicKey(cert); if (publickey == NULL) goto loser; /* Find our own cert, and extract its keys. */ ourCert = PK11_FindBestKEAMatch(cert, pwfn_arg); if (ourCert == NULL) goto loser; arena = PORT_NewArena(1024); if (arena == NULL) goto loser; ourPubKey = CERT_ExtractPublicKey(ourCert); if (ourPubKey == NULL) { CERT_DestroyCertificate(ourCert); goto loser; } /* While we're here, copy the public key into the outgoing * KEA parameters. */ SECITEM_CopyItem(arena, &(keaParams.originatorKEAKey), &(ourPubKey->u.fortezza.KEAKey)); SECKEY_DestroyPublicKey(ourPubKey); ourPubKey = NULL; /* Extract our private key in order to derive the KEA key. */ ourPrivKey = PK11_FindKeyByAnyCert(ourCert, pwfn_arg); CERT_DestroyCertificate(ourCert); /* we're done with this */ if (!ourPrivKey) goto loser; /* Prepare raItem with 128 bytes (filled with zeros). */ keaParams.originatorRA.data = (unsigned char *)PORT_ArenaAlloc(arena,SMIME_FORTEZZA_RA_LENGTH); keaParams.originatorRA.len = SMIME_FORTEZZA_RA_LENGTH; /* Generate the TEK (token exchange key) which we use * to wrap the bulk encryption key. (keaparams.originatorRA) will be * filled with a random seed which we need to send to * the recipient. (user keying material in RFC2630/DSA speak) */ tek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE, &keaParams.originatorRA, NULL, CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP, CKA_WRAP, 0, pwfn_arg); SECKEY_DestroyPublicKey(publickey); SECKEY_DestroyPrivateKey(ourPrivKey); publickey = NULL; ourPrivKey = NULL; if (!tek) goto loser; /* allocate space for the wrapped key data */ encKey->data = (unsigned char *)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE); encKey->len = SMIME_FORTEZZA_MAX_KEY_SIZE; if (encKey->data == NULL) { PK11_FreeSymKey(tek); goto loser; } /* Wrap the bulk key. What we do with the resulting data depends on whether we're using Skipjack to wrap the key. */ switch (PK11_AlgtagToMechanism(symalgtag)) { case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_ECB64: case CKM_SKIPJACK_OFB64: case CKM_SKIPJACK_CFB64: case CKM_SKIPJACK_CFB32: case CKM_SKIPJACK_CFB16: case CKM_SKIPJACK_CFB8: /* SKIPJACK, we use the wrap mechanism because we can do it on the hardware */ err = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, bulkkey, encKey); whichKEA = NSSCMSKEAUsesSkipjack; break; default: /* Not SKIPJACK, we encrypt the raw key data */ keaParams.nonSkipjackIV.data = (unsigned char *)PORT_ArenaAlloc(arena, SMIME_FORTEZZA_IV_LENGTH); keaParams.nonSkipjackIV.len = SMIME_FORTEZZA_IV_LENGTH; err = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, tek, bulkkey, encKey); if (err != SECSuccess) goto loser; if (encKey->len != PK11_GetKeyLength(bulkkey)) { /* The size of the encrypted key is not the same as that of the original bulk key, presumably due to padding. Encode and store the real size of the bulk key. */ if (SEC_ASN1EncodeInteger(arena, &keaParams.bulkKeySize, PK11_GetKeyLength(bulkkey)) == NULL) err = (SECStatus)PORT_GetError(); else /* use full template for encoding */ whichKEA = NSSCMSKEAUsesNonSkipjackWithPaddedEncKey; } else /* enc key length == bulk key length */ whichKEA = NSSCMSKEAUsesNonSkipjack; break; } PK11_FreeSymKey(tek); if (err != SECSuccess) goto loser; PORT_Assert(whichKEA != NSSCMSKEAInvalid); /* Encode the KEA parameters into the recipient info. */ params = SEC_ASN1EncodeItem(poolp, NULL, &keaParams, nss_cms_get_kea_template(whichKEA)); if (params == NULL) goto loser; /* pass back the algorithm params */ *pparams = params; rv = SECSuccess; loser: if (arena) PORT_FreeArena(arena, PR_FALSE); if (publickey) SECKEY_DestroyPublicKey(publickey); if (ourPrivKey) SECKEY_DestroyPrivateKey(ourPrivKey); return rv; }
SECStatus EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams, ECParams *params, int kmflag) { SECStatus rv = SECFailure; ECCurveName tag; SECItem oid = { siBuffer, NULL, 0}; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; }; oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == ECCurve_noName)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; params->cofactor = 0; params->type = ec_params_named; params->name = ECCurve_noName; /* For named curves, fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(NULL, oid.len, kmflag); if (params->curveOID.data == NULL) goto cleanup; memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG #ifndef SECOID_FindOIDTagDescription printf("Curve: %s\n", ecCurve_map[tag]->text); #else printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif #endif switch (tag) { /* Binary curves */ case ECCurve_X9_62_CHAR2_PNB163V1: /* Populate params for c2pnb163v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB163V2: /* Populate params for c2pnb163v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB163V3: /* Populate params for c2pnb163v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB176V1: /* Populate params for c2pnb176v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V1: /* Populate params for c2tnb191v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V2: /* Populate params for c2tnb191v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB191V3: /* Populate params for c2tnb191v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB208W1: /* Populate params for c2pnb208w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V1: /* Populate params for c2tnb239v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V2: /* Populate params for c2tnb239v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB239V3: /* Populate params for c2tnb239v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB272W1: /* Populate params for c2pnb272w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB304W1: /* Populate params for c2pnb304w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB359V1: /* Populate params for c2tnb359v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_PNB368W1: /* Populate params for c2pnb368w1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_X9_62_CHAR2_TNB431R1: /* Populate params for c2tnb431r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_113R1: /* Populate params for sect113r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_113R2: /* Populate params for sect113r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_131R1: /* Populate params for sect131r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_131R2: /* Populate params for sect131r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163K1: /* Populate params for sect163k1 * (the NIST K-163 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163R1: /* Populate params for sect163r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_163R2: /* Populate params for sect163r2 * (the NIST B-163 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_193R1: /* Populate params for sect193r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_193R2: /* Populate params for sect193r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_233K1: /* Populate params for sect233k1 * (the NIST K-233 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_233R1: /* Populate params for sect233r1 * (the NIST B-233 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_239K1: /* Populate params for sect239k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_283K1: /* Populate params for sect283k1 * (the NIST K-283 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_283R1: /* Populate params for sect283r1 * (the NIST B-283 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_409K1: /* Populate params for sect409k1 * (the NIST K-409 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_409R1: /* Populate params for sect409r1 * (the NIST B-409 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_571K1: /* Populate params for sect571k1 * (the NIST K-571 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m, params, kmflag) ); break; case ECCurve_SECG_CHAR2_571R1: /* Populate params for sect571r1 * (the NIST B-571 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m, params, kmflag) ); break; /* Prime curves */ case ECCurve_X9_62_PRIME_192V1: /* Populate params for prime192v1 aka secp192r1 * (the NIST P-192 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_192V2: /* Populate params for prime192v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_192V3: /* Populate params for prime192v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V1: /* Populate params for prime239v1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V2: /* Populate params for prime239v2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_239V3: /* Populate params for prime239v3 */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp, params, kmflag) ); break; case ECCurve_X9_62_PRIME_256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_112R1: /* Populate params for secp112r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_112R2: /* Populate params for secp112r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_128R1: /* Populate params for secp128r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_128R2: /* Populate params for secp128r2 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160K1: /* Populate params for secp160k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160R1: /* Populate params for secp160r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_160R2: /* Populate params for secp160r1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_192K1: /* Populate params for secp192k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_224K1: /* Populate params for secp224k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_224R1: /* Populate params for secp224r1 * (the NIST P-224 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_256K1: /* Populate params for secp256k1 */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp, params, kmflag) ); break; case ECCurve_SECG_PRIME_521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp, params, kmflag) ); break; default: break; }; cleanup: if (!params->cofactor) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); #if EC_DEBUG printf("Unrecognized curve, returning NULL params\n"); #endif } return rv; }
/* * load a new module into our address space and initialize it. */ SECStatus secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) { PRLibrary *library = NULL; CK_C_GetFunctionList entry = NULL; CK_INFO info; CK_ULONG slotCount = 0; SECStatus rv; PRBool alreadyLoaded = PR_FALSE; char *disableUnload = NULL; if (mod->loaded) return SECSuccess; /* internal modules get loaded from their internal list */ if (mod->internal && (mod->dllName == NULL)) { #ifdef NSS_TEST_BUILD entry = (CK_C_GetFunctionList)NSC_GetFunctionList; #else /* * Loads softoken as a dynamic library, * even though the rest of NSS assumes this as the "internal" module. */ if (!softokenLib && PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO)) return SECFailure; PR_ATOMIC_INCREMENT(&softokenLoadCount); if (mod->isFIPS) { entry = (CK_C_GetFunctionList) PR_FindSymbol(softokenLib, "FC_GetFunctionList"); } else { entry = (CK_C_GetFunctionList) PR_FindSymbol(softokenLib, "NSC_GetFunctionList"); } if (!entry) return SECFailure; #endif if (mod->isModuleDB) { mod->moduleDBFunc = (CK_C_GetFunctionList) #ifdef NSS_TEST_BUILD NSC_ModuleDBFunc; #else PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc"); #endif } if (mod->moduleDBOnly) { mod->loaded = PR_TRUE; return SECSuccess; } } else { /* Not internal, load the DLL and look up C_GetFunctionList */ if (mod->dllName == NULL) { return SECFailure; } /* load the library. If this succeeds, then we have to remember to * unload the library if anything goes wrong from here on out... */ library = PR_LoadLibrary(mod->dllName); mod->library = (void *)library; if (library == NULL) { return SECFailure; } /* * now we need to get the entry point to find the function pointers */ if (!mod->moduleDBOnly) { entry = (CK_C_GetFunctionList) PR_FindSymbol(library, "C_GetFunctionList"); } if (mod->isModuleDB) { mod->moduleDBFunc = (void *) PR_FindSymbol(library, "NSS_ReturnModuleSpecData"); } if (mod->moduleDBFunc == NULL) mod->isModuleDB = PR_FALSE; if (entry == NULL) { if (mod->isModuleDB) { mod->loaded = PR_TRUE; mod->moduleDBOnly = PR_TRUE; return SECSuccess; } PR_UnloadLibrary(library); return SECFailure; } } /* * We need to get the function list */ if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK) goto fail; #ifdef DEBUG_MODULE if (PR_TRUE) { modToDBG = PR_GetEnvSecure("NSS_DEBUG_PKCS11_MODULE"); if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) { mod->functionList = (void *)nss_InsertDeviceLog( (CK_FUNCTION_LIST_PTR)mod->functionList); } } #endif mod->isThreadSafe = PR_TRUE; /* Now we initialize the module */ rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded); if (rv != SECSuccess) { goto fail; } /* module has been reloaded, this module itself is done, * return to the caller */ if (mod->functionList == NULL) { mod->loaded = PR_TRUE; /* technically the module is loaded.. */ return SECSuccess; } /* check the version number */ if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2; if (info.cryptokiVersion.major != 2) goto fail2; /* all 2.0 are a priori *not* thread safe */ if (info.cryptokiVersion.minor < 1) { if (!loadSingleThreadedModules) { PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); goto fail2; } else { mod->isThreadSafe = PR_FALSE; } } mod->cryptokiVersion = info.cryptokiVersion; /* If we don't have a common name, get it from the PKCS 11 module */ if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) { mod->commonName = PK11_MakeString(mod->arena, NULL, (char *)info.libraryDescription, sizeof(info.libraryDescription)); if (mod->commonName == NULL) goto fail2; } /* initialize the Slots */ if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) { CK_SLOT_ID *slotIDs; int i; CK_RV crv; mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena, sizeof(PK11SlotInfo *) * slotCount); if (mod->slots == NULL) goto fail2; slotIDs = (CK_SLOT_ID *)PORT_Alloc(sizeof(CK_SLOT_ID) * slotCount); if (slotIDs == NULL) { goto fail2; } crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount); if (crv != CKR_OK) { PORT_Free(slotIDs); goto fail2; } /* Initialize each slot */ for (i = 0; i < (int)slotCount; i++) { mod->slots[i] = PK11_NewSlotInfo(mod); PK11_InitSlot(mod, slotIDs[i], mod->slots[i]); /* look down the slot info table */ PK11_LoadSlotList(mod->slots[i], mod->slotInfo, mod->slotInfoCount); SECMOD_SetRootCerts(mod->slots[i], mod); /* explicitly mark the internal slot as such if IsInternalKeySlot() * is set */ if (secmod_IsInternalKeySlot(mod) && (i == (mod->isFIPS ? 0 : 1))) { pk11_SetInternalKeySlotIfFirst(mod->slots[i]); } } mod->slotCount = slotCount; mod->slotInfoCount = 0; PORT_Free(slotIDs); } mod->loaded = PR_TRUE; mod->moduleID = nextModuleID++; return SECSuccess; fail2: if (enforceAlreadyInitializedError || (!alreadyLoaded)) { PK11_GETTAB(mod)->C_Finalize(NULL); } fail: mod->functionList = NULL; disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); if (library && !disableUnload) { PR_UnloadLibrary(library); } return SECFailure; }
CERTCertificateList * CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, PRBool includeRoot) { CERTCertificateList *chain = NULL; NSSCertificate **stanChain; NSSCertificate *stanCert; PRArenaPool *arena; NSSUsage nssUsage; int i, len; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSCryptoContext *cc = STAN_GetDefaultCryptoContext(); stanCert = STAN_GetNSSCertificate(cert); if (!stanCert) { /* error code is set */ return NULL; } nssUsage.anyUsage = PR_FALSE; nssUsage.nss3usage = usage; nssUsage.nss3lookingForCA = PR_FALSE; stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL, CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc); if (!stanChain) { PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); return NULL; } len = 0; stanCert = stanChain[0]; while (stanCert) { stanCert = stanChain[++len]; } arena = PORT_NewArena(4096); if (arena == NULL) { goto loser; } chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList)); if (!chain) goto loser; chain->certs = (SECItem*)PORT_ArenaAlloc(arena, len * sizeof(SECItem)); if (!chain->certs) goto loser; i = 0; stanCert = stanChain[i]; while (stanCert) { SECItem derCert; CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); if (!cCert) { goto loser; } derCert.len = (unsigned int)stanCert->encoding.size; derCert.data = (unsigned char *)stanCert->encoding.data; derCert.type = siBuffer; SECITEM_CopyItem(arena, &chain->certs[i], &derCert); stanCert = stanChain[++i]; if (!stanCert && !cCert->isRoot) { /* reached the end of the chain, but the final cert is * not a root. Don't discard it. */ includeRoot = PR_TRUE; } CERT_DestroyCertificate(cCert); } if ( !includeRoot && len > 1) { chain->len = len - 1; } else { chain->len = len; } chain->arena = arena; nss_ZFreeIf(stanChain); return chain; loser: i = 0; stanCert = stanChain[i]; while (stanCert) { CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert); if (cCert) { CERT_DestroyCertificate(cCert); } stanCert = stanChain[++i]; } nss_ZFreeIf(stanChain); if (arena) { PORT_FreeArena(arena, PR_FALSE); } return NULL; }
SECStatus ConfigSecureServerWithNamedCert(PRFileDesc *fd, const char *certName, /*optional*/ ScopedCERTCertificate *certOut, /*optional*/ SSLKEAType *keaOut) { ScopedCERTCertificate cert(PK11_FindCertFromNickname(certName, nullptr)); if (!cert) { PrintPRError("PK11_FindCertFromNickname failed"); return SECFailure; } // If an intermediate certificate issued the server certificate (rather than // directly by a trust anchor), we want to send it along in the handshake so // we don't encounter unknown issuer errors when that's not what we're // testing. UniqueCERTCertificateList certList; ScopedCERTCertificate issuerCert( CERT_FindCertByName(CERT_GetDefaultCertDB(), &cert->derIssuer)); // If we can't find the issuer cert, continue without it. if (issuerCert) { // Sadly, CERTCertificateList does not have a CERT_NewCertificateList // utility function, so we must create it ourselves. This consists // of creating an arena, allocating space for the CERTCertificateList, // and then transferring ownership of the arena to that list. ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { PrintPRError("PORT_NewArena failed"); return SECFailure; } certList.reset(static_cast<CERTCertificateList*>( PORT_ArenaAlloc(arena.get(), sizeof(CERTCertificateList)))); if (!certList) { PrintPRError("PORT_ArenaAlloc failed"); return SECFailure; } certList->arena = arena.forget(); // We also have to manually copy the certificates we care about to the // list, because there aren't any utility functions for that either. certList->certs = reinterpret_cast<SECItem*>( PORT_ArenaAlloc(certList->arena, 2 * sizeof(SECItem))); if (SECITEM_CopyItem(certList->arena, certList->certs, &cert->derCert) != SECSuccess) { PrintPRError("SECITEM_CopyItem failed"); return SECFailure; } if (SECITEM_CopyItem(certList->arena, certList->certs + 1, &issuerCert->derCert) != SECSuccess) { PrintPRError("SECITEM_CopyItem failed"); return SECFailure; } certList->len = 2; } ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); UniqueSECKEYPrivateKey key( PK11_FindKeyByDERCert(slot.get(), cert.get(), nullptr)); if (!key) { PrintPRError("PK11_FindKeyByDERCert failed"); return SECFailure; } SSLKEAType certKEA = NSS_FindCertKEAType(cert); if (SSL_ConfigSecureServerWithCertChain(fd, cert.get(), certList.get(), key.get(), certKEA) != SECSuccess) { PrintPRError("SSL_ConfigSecureServer failed"); return SECFailure; } if (certOut) { *certOut = cert.forget(); } if (keaOut) { *keaOut = certKEA; } return SECSuccess; }
SECStatus EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, ECParams *params) { SECStatus rv = SECFailure; SECOidTag tag; SECItem oid = { siBuffer, NULL, 0 }; #if EC_DEBUG int i; printf("Encoded params in EC_DecodeParams: "); for (i = 0; i < encodedParams->len; i++) { printf("%02x:", encodedParams->data[i]); } printf("\n"); #endif if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) && (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; }; oid.len = encodedParams->len - 2; oid.data = encodedParams->data + 2; if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } params->arena = arena; params->cofactor = 0; params->type = ec_params_named; params->name = ECCurve_noName; /* Fill out curveOID */ params->curveOID.len = oid.len; params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len); if (params->curveOID.data == NULL) goto cleanup; memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif switch (tag) { case SEC_OID_ANSIX962_EC_PRIME256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp, params)); break; case SEC_OID_SECG_EC_SECP384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp, params)); break; case SEC_OID_SECG_EC_SECP521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp, params)); break; case SEC_OID_CURVE25519: /* Populate params for Curve25519 */ CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params)); break; default: break; }; cleanup: if (!params->cofactor) { PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); #if EC_DEBUG printf("Unrecognized curve, returning NULL params\n"); #endif } return rv; }
SGNDigestInfo * SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig, unsigned len) { SGNDigestInfo *di; SECStatus rv; PLArenaPool *arena; SECItem *null_param; SECItem dummy_value; switch (algorithm) { case SEC_OID_MD2: case SEC_OID_MD5: case SEC_OID_SHA1: case SEC_OID_SHA224: case SEC_OID_SHA256: case SEC_OID_SHA384: case SEC_OID_SHA512: break; default: PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); return NULL; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { return NULL; } di = (SGNDigestInfo *) PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo)); if (di == NULL) { PORT_FreeArena(arena, PR_FALSE); return NULL; } di->arena = arena; /* * PKCS #1 specifies that the AlgorithmID must have a NULL parameter * (as opposed to no parameter at all). */ dummy_value.data = NULL; dummy_value.len = 0; null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate); if (null_param == NULL) { goto loser; } rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm, null_param); SECITEM_FreeItem(null_param, PR_TRUE); if (rv != SECSuccess) { goto loser; } di->digest.data = (unsigned char *) PORT_ArenaAlloc(arena, len); if (di->digest.data == NULL) { goto loser; } di->digest.len = len; PORT_Memcpy(di->digest.data, sig, len); return di; loser: SGN_DestroyDigestInfo(di); return NULL; }
SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len) { if (h->state == parseError) return PR_TRUE; while (len) { (*h->proc)(h, &buf, &len); if (h->state == parseComplete) { PORT_SetError(SEC_ERROR_BAD_DER); h->state = parseError; return PR_TRUE; } if (h->state == parseError) return PR_TRUE; PORT_Assert(h->state != parseComplete); if (h->state <= compositeDone) { if (h->proc == ParseTag) { PORT_Assert(h->state == tagDone); h->proc = ParseLength; h->state = notDone; } else if (h->proc == ParseLength) { SECArb *arb = &(h->stackPtr->arb); PORT_Assert(h->state == lengthDone || h->state == compositeDone); if (h->before) (*h->before)(h->beforeArg, arb, h->stackPtr - h->stack, PR_TRUE); /* * Check to see if this is the end of an indefinite * length composite */ if (h->state == compositeDone) { SECArb *parent = h->stackPtr->parent; PORT_Assert(parent); PORT_Assert(parent->tag & DER_CONSTRUCTED); if (parent->length != 0) { PORT_SetError(SEC_ERROR_BAD_DER); h->state = parseError; return PR_TRUE; } /* * NOTE: This does not check for an indefinite length * composite being contained inside a definite length * composite. It is not clear that is legal. */ h->stackPtr--; CreateArbNode(h); } else { h->stackPtr->pos = h->pos; if (arb->tag & DER_CONSTRUCTED) { SECArb *parent; /* * Make sure there is room on the stack before we * stick anything else there. */ PORT_Assert(h->stackPtr - h->stack < h->stackDepth); if (h->stackPtr - h->stack == h->stackDepth - 1) { int newDepth = h->stackDepth * 2; h->stack = DS_ArenaGrow(h->mine, h->stack, sizeof(ParseStackElem) * h->stackDepth, sizeof(ParseStackElem) * newDepth); h->stackPtr = h->stack + h->stackDepth + 1; h->stackDepth = newDepth; } parent = &(h->stackPtr->arb); h->stackPtr++; h->stackPtr->parent = parent; h->proc = ParseTag; h->state = notDone; h->pending = UNKNOWN; } else { if (arb->length < 0) { PORT_SetError(SEC_ERROR_BAD_DER); h->state = parseError; return PR_TRUE; } arb->body.item.len = 0; if (arb->length > 0 && h->keepLeaves) { arb->body.item.data = PORT_ArenaAlloc(h->his, arb->length); } else { arb->body.item.data = NULL; } h->proc = ParseLeaf; h->state = notDone; h->pending = arb->length; } } } else { ParseStackElem *parent; PORT_Assert(h->state = leafDone); PORT_Assert(h->proc == ParseLeaf); for (;;) { CreateArbNode(h); if (h->stackPtr == h->stack) break; parent = (h->stackPtr - 1); PORT_Assert(parent->arb.tag & DER_CONSTRUCTED); if (parent->arb.length == 0) /* need explicit end */ break; if (parent->pos + parent->arb.length > h->pos) break; if (parent->pos + parent->arb.length < h->pos) { PORT_SetError(SEC_ERROR_BAD_DER); h->state = parseError; return PR_TRUE; } h->stackPtr = parent; } } } } return PR_FALSE; }
/* * SecCmsDigestContextFinishMultiple - finish the digests and put them * into an array of CSSM_DATAs (allocated on poolp) */ OSStatus SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, CSSM_DATA_PTR **digestsp) { CSSM_CC_HANDLE digobj; CSSM_DATA_PTR *digests, digest; int i; void *mark; OSStatus rv = SECFailure; /* no contents? do not update digests */ if (digestsp == NULL || !cmsdigcx->saw_contents) { for (i = 0; i < cmsdigcx->digcnt; i++) if (cmsdigcx->digobjs[i]) CSSM_DeleteContext(cmsdigcx->digobjs[i]); rv = SECSuccess; if (digestsp) *digestsp = NULL; goto cleanup; } mark = PORT_ArenaMark ((PLArenaPool *)poolp); /* allocate digest array & CSSM_DATAs on arena */ digests = (CSSM_DATA_PTR *)PORT_ArenaAlloc((PLArenaPool *)poolp, (cmsdigcx->digcnt+1) * sizeof(CSSM_DATA_PTR)); digest = (CSSM_DATA_PTR)PORT_ArenaZAlloc((PLArenaPool *)poolp, cmsdigcx->digcnt * sizeof(CSSM_DATA)); if (digests == NULL || digest == NULL) { goto loser; } for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { digobj = cmsdigcx->digobjs[i]; CSSM_QUERY_SIZE_DATA dataSize; rv = CSSM_QuerySize(digobj, CSSM_FALSE, 1, &dataSize); if (rv != CSSM_OK) { goto loser; } int diglength = dataSize.SizeOutputBlock; if (digobj) { digest->Data = (unsigned char*)PORT_ArenaAlloc((PLArenaPool *)poolp, diglength); if (digest->Data == NULL) goto loser; digest->Length = diglength; rv = CSSM_DigestDataFinal(digobj, digest); if (rv != CSSM_OK) { goto loser; } CSSM_DeleteContext(digobj); } else { digest->Data = NULL; digest->Length = 0; } digests[i] = digest; } digests[i] = NULL; *digestsp = digests; rv = SECSuccess; loser: if (rv == SECSuccess) PORT_ArenaUnmark((PLArenaPool *)poolp, mark); else PORT_ArenaRelease((PLArenaPool *)poolp, mark); cleanup: if (cmsdigcx->digcnt > 0) { PORT_Free(cmsdigcx->digobjs); } PORT_Free(cmsdigcx); return rv; }