SECStatus SEC_DerSignData(PRArenaPool *arena, SECItem *result, unsigned char *buf, int len, SECKEYPrivateKey *pk, SECOidTag algID) { SECItem it; CERTSignedData sd; SECStatus rv; it.data = 0; /* XXX We should probably have some asserts here to make sure the key type * and algID match */ if (algID == SEC_OID_UNKNOWN) { switch(pk->keyType) { case rsaKey: algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break; case dsaKey: algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break; case ecKey: algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; break; default: PORT_SetError(SEC_ERROR_INVALID_KEY); return SECFailure; } } /* Sign input buffer */ rv = SEC_SignData(&it, buf, len, pk, algID); if (rv) goto loser; /* Fill out SignedData object */ PORT_Memset(&sd, 0, sizeof(sd)); sd.data.data = buf; sd.data.len = len; sd.signature.data = it.data; sd.signature.len = it.len << 3; /* convert to bit string */ rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0); if (rv) goto loser; /* DER encode the signed data object */ rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd); /* FALL THROUGH */ loser: PORT_Free(it.data); return rv; }
SECStatus SGN_Digest(SECKEYPrivateKey *privKey, SECOidTag algtag, SECItem *result, SECItem *digest) { int modulusLen; SECStatus rv; SECItem digder; PLArenaPool *arena = 0; SGNDigestInfo *di = 0; result->data = 0; if (privKey->keyType == rsaKey) { arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { rv = SECFailure; goto loser; } /* Construct digest info */ di = SGN_CreateDigestInfo(algtag, digest->data, digest->len); if (!di) { rv = SECFailure; goto loser; } /* Der encode the digest as a DigestInfo */ rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); if (rv != SECSuccess) { goto loser; } } else { digder.data = digest->data; digder.len = digest->len; } /* ** Encrypt signature after constructing appropriate PKCS#1 signature ** block */ modulusLen = PK11_SignatureLen(privKey); if (modulusLen <= 0) { PORT_SetError(SEC_ERROR_INVALID_KEY); rv = SECFailure; goto loser; } result->len = modulusLen; result->data = (unsigned char*) PORT_Alloc(modulusLen); result->type = siBuffer; if (result->data == NULL) { rv = SECFailure; goto loser; } rv = PK11_Sign(privKey, result, &digder); if (rv != SECSuccess) { PORT_Free(result->data); result->data = NULL; } loser: SGN_DestroyDigestInfo(di); if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } return rv; }
SECStatus SGN_End(SGNContext *cx, SECItem *result) { unsigned char digest[HASH_LENGTH_MAX]; unsigned part1; int signatureLen; SECStatus rv; SECItem digder, sigitem; PLArenaPool *arena = 0; SECKEYPrivateKey *privKey = cx->key; SGNDigestInfo *di = 0; result->data = 0; digder.data = 0; /* Finish up digest function */ if (cx->hashcx == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest)); if (privKey->keyType == rsaKey) { arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { rv = SECFailure; goto loser; } /* Construct digest info */ di = SGN_CreateDigestInfo(cx->hashalg, digest, part1); if (!di) { rv = SECFailure; goto loser; } /* Der encode the digest as a DigestInfo */ rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); if (rv != SECSuccess) { goto loser; } } else { digder.data = digest; digder.len = part1; } /* ** Encrypt signature after constructing appropriate PKCS#1 signature ** block */ signatureLen = PK11_SignatureLen(privKey); if (signatureLen <= 0) { PORT_SetError(SEC_ERROR_INVALID_KEY); rv = SECFailure; goto loser; } sigitem.len = signatureLen; sigitem.data = (unsigned char*) PORT_Alloc(signatureLen); if (sigitem.data == NULL) { rv = SECFailure; goto loser; } rv = PK11_Sign(privKey, &sigitem, &digder); if (rv != SECSuccess) { PORT_Free(sigitem.data); sigitem.data = NULL; goto loser; } if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len); PORT_Free(sigitem.data); if (rv != SECSuccess) goto loser; } else { result->len = sigitem.len; result->data = sigitem.data; } loser: SGN_DestroyDigestInfo(di); if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } return rv; }
nsresult nsKeygenFormProcessor::GetPublicKey(const nsAString& aValue, const nsAString& aChallenge, const nsAFlatString& aKeyType, nsAString& aOutPublicKey, const nsAString& aKeyParams) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) { return NS_ERROR_NOT_AVAILABLE; } nsresult rv = NS_ERROR_FAILURE; char *keystring = nullptr; char *keyparamsString = nullptr; uint32_t keyGenMechanism; PK11SlotInfo *slot = nullptr; PK11RSAGenParams rsaParams; SECOidTag algTag; int keysize = 0; void *params = nullptr; SECKEYPrivateKey *privateKey = nullptr; SECKEYPublicKey *publicKey = nullptr; CERTSubjectPublicKeyInfo *spkInfo = nullptr; SECStatus srv = SECFailure; SECItem spkiItem; SECItem pkacItem; SECItem signedItem; CERTPublicKeyAndChallenge pkac; pkac.challenge.data = nullptr; nsIGeneratingKeypairInfoDialogs * dialogs; nsKeygenThread *KeygenRunnable = 0; nsCOMPtr<nsIKeygenThread> runnable; // permanent and sensitive flags for keygen PK11AttrFlags attrFlags = PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE; UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { goto loser; } // Get the key size // for (size_t i = 0; i < number_of_key_size_choices; ++i) { if (aValue.Equals(mSECKeySizeChoiceList[i].name)) { keysize = mSECKeySizeChoiceList[i].size; break; } } if (!keysize) { goto loser; } // Set the keygen mechanism if (aKeyType.IsEmpty() || aKeyType.LowerCaseEqualsLiteral("rsa")) { keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; } else if (aKeyType.LowerCaseEqualsLiteral("ec")) { keyparamsString = ToNewCString(aKeyParams); if (!keyparamsString) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } keyGenMechanism = CKM_EC_KEY_PAIR_GEN; /* ecParams are initialized later */ } else { goto loser; } // Get the slot rv = GetSlot(keyGenMechanism, &slot); if (NS_FAILED(rv)) { goto loser; } switch (keyGenMechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: rsaParams.keySizeInBits = keysize; rsaParams.pe = DEFAULT_RSA_KEYGEN_PE; algTag = DEFAULT_RSA_KEYGEN_ALG; params = &rsaParams; break; case CKM_EC_KEY_PAIR_GEN: /* XXX We ought to rethink how the KEYGEN tag is * displayed. The pulldown selections presented * to the user must depend on the keytype. * The displayed selection could be picked * from the keyparams attribute (this is currently called * the pqg attribute). * For now, we pick ecparams from the keyparams field * if it specifies a valid supported curve, or else * we pick one of secp384r1, secp256r1 or secp192r1 * respectively depending on the user's selection * (High, Medium, Low). * (RSA uses RSA-2048, RSA-1024 and RSA-512 for historical * reasons, while ECC choices represent a stronger mapping) * NOTE: The user's selection * is silently ignored when a valid curve is presented * in keyparams. */ if ((params = decode_ec_params(keyparamsString)) == nullptr) { /* The keyparams attribute did not specify a valid * curve name so use a curve based on the keysize. * NOTE: Here keysize is used only as an indication of * High/Medium/Low strength; elliptic curve * cryptography uses smaller keys than RSA to provide * equivalent security. */ switch (keysize) { case 2048: params = decode_ec_params("secp384r1"); break; case 1024: case 512: params = decode_ec_params("secp256r1"); break; } } /* XXX The signature algorithm ought to choose the hashing * algorithm based on key size once ECDSA variations based * on SHA256 SHA384 and SHA512 are standardized. */ algTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; break; default: goto loser; } /* Make sure token is initialized. */ rv = setPassword(slot, m_ctx, locker); if (NS_FAILED(rv)) goto loser; srv = PK11_Authenticate(slot, true, m_ctx); if (srv != SECSuccess) { goto loser; } rv = getNSSDialogs((void**)&dialogs, NS_GET_IID(nsIGeneratingKeypairInfoDialogs), NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID); if (NS_SUCCEEDED(rv)) { KeygenRunnable = new nsKeygenThread(); NS_IF_ADDREF(KeygenRunnable); } if (NS_FAILED(rv) || !KeygenRunnable) { rv = NS_OK; privateKey = PK11_GenerateKeyPairWithFlags(slot, keyGenMechanism, params, &publicKey, attrFlags, m_ctx); } else { KeygenRunnable->SetParams( slot, attrFlags, nullptr, 0, keyGenMechanism, params, m_ctx ); runnable = do_QueryInterface(KeygenRunnable); if (runnable) { rv = dialogs->DisplayGeneratingKeypairInfo(m_ctx, runnable); // We call join on the thread so we can be sure that no // simultaneous access to the passed parameters will happen. KeygenRunnable->Join(); NS_RELEASE(dialogs); if (NS_SUCCEEDED(rv)) { PK11SlotInfo *used_slot = nullptr; rv = KeygenRunnable->ConsumeResult(&used_slot, &privateKey, &publicKey); if (NS_SUCCEEDED(rv) && used_slot) { PK11_FreeSlot(used_slot); } } } } if (NS_FAILED(rv) || !privateKey) { goto loser; } // just in case we'll need to authenticate to the db -jp // privateKey->wincx = m_ctx; /* * Create a subject public key info from the public key. */ spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey); if ( !spkInfo ) { goto loser; } /* * Now DER encode the whole subjectPublicKeyInfo. */ srv = DER_Encode(arena.get(), &spkiItem, CERTSubjectPublicKeyInfoTemplate, spkInfo); if (srv != SECSuccess) { goto loser; } /* * set up the PublicKeyAndChallenge data structure, then DER encode it */ pkac.spki = spkiItem; pkac.challenge.len = aChallenge.Length(); pkac.challenge.data = (unsigned char *)ToNewCString(aChallenge); if (!pkac.challenge.data) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } srv = DER_Encode(arena.get(), &pkacItem, CERTPublicKeyAndChallengeTemplate, &pkac); if (srv != SECSuccess) { goto loser; } /* * now sign the DER encoded PublicKeyAndChallenge */ srv = SEC_DerSignData(arena.get(), &signedItem, pkacItem.data, pkacItem.len, privateKey, algTag); if (srv != SECSuccess) { goto loser; } /* * Convert the signed public key and challenge into base64/ascii. */ keystring = BTOA_DataToAscii(signedItem.data, signedItem.len); if (!keystring) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } CopyASCIItoUTF16(keystring, aOutPublicKey); free(keystring); rv = NS_OK; GatherKeygenTelemetry(keyGenMechanism, keysize, keyparamsString); loser: if (srv != SECSuccess) { if ( privateKey ) { PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID); } if ( publicKey ) { PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID); } } if ( spkInfo ) { SECKEY_DestroySubjectPublicKeyInfo(spkInfo); } if ( publicKey ) { SECKEY_DestroyPublicKey(publicKey); } if ( privateKey ) { SECKEY_DestroyPrivateKey(privateKey); } if (slot) { PK11_FreeSlot(slot); } if (KeygenRunnable) { NS_RELEASE(KeygenRunnable); } if (keyparamsString) { free(keyparamsString); } if (pkac.challenge.data) { free(pkac.challenge.data); } // If params is non-null and doesn't point to rsaParams, it was allocated // in decode_ec_params. We have to free this memory. if (params && params != &rsaParams) { SECITEM_FreeItem(static_cast<SECItem*>(params), true); params = nullptr; } return rv; }
SECStatus SGN_End(SGNContext *cx, SECItem *result) { unsigned char digest[HASH_LENGTH_MAX]; unsigned part1; int signatureLen; SECStatus rv; SECItem digder, sigitem; PLArenaPool *arena = 0; SECKEYPrivateKey *privKey = cx->key; SGNDigestInfo *di = 0; result->data = 0; digder.data = 0; sigitem.data = 0; /* Finish up digest function */ if (cx->hashcx == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest)); if (privKey->keyType == rsaKey && cx->signalg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { rv = SECFailure; goto loser; } /* Construct digest info */ di = SGN_CreateDigestInfo(cx->hashalg, digest, part1); if (!di) { rv = SECFailure; goto loser; } /* Der encode the digest as a DigestInfo */ rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); if (rv != SECSuccess) { goto loser; } } else { digder.data = digest; digder.len = part1; } /* ** Encrypt signature after constructing appropriate PKCS#1 signature ** block */ signatureLen = PK11_SignatureLen(privKey); if (signatureLen <= 0) { PORT_SetError(SEC_ERROR_INVALID_KEY); rv = SECFailure; goto loser; } sigitem.len = signatureLen; sigitem.data = (unsigned char *)PORT_Alloc(signatureLen); if (sigitem.data == NULL) { rv = SECFailure; goto loser; } if (cx->signalg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { CK_RSA_PKCS_PSS_PARAMS mech; SECItem mechItem = { siBuffer, (unsigned char *)&mech, sizeof(mech) }; PORT_Memset(&mech, 0, sizeof(mech)); if (cx->params && cx->params->data) { SECKEYRSAPSSParams params; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { rv = SECFailure; goto loser; } PORT_Memset(¶ms, 0, sizeof(params)); rv = SEC_QuickDERDecodeItem(arena, ¶ms, SECKEY_RSAPSSParamsTemplate, cx->params); if (rv != SECSuccess) { goto loser; } rv = sec_RSAPSSParamsToMechanism(&mech, ¶ms); if (rv != SECSuccess) { goto loser; } } else { mech.hashAlg = CKM_SHA_1; mech.mgf = CKG_MGF1_SHA1; mech.sLen = digder.len; } rv = PK11_SignWithMechanism(privKey, CKM_RSA_PKCS_PSS, &mechItem, &sigitem, &digder); if (rv != SECSuccess) { goto loser; } } else { rv = PK11_Sign(privKey, &sigitem, &digder); if (rv != SECSuccess) { goto loser; } } if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len); if (rv != SECSuccess) goto loser; SECITEM_FreeItem(&sigitem, PR_FALSE); } else { result->len = sigitem.len; result->data = sigitem.data; } loser: if (rv != SECSuccess) { SECITEM_FreeItem(&sigitem, PR_FALSE); } SGN_DestroyDigestInfo(di); if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } return rv; }
nsresult nsKeygenFormProcessor::GetPublicKey(nsAString& aValue, nsAString& aChallenge, nsAFlatString& aKeyType, nsAString& aOutPublicKey, nsAString& aKeyParams) { nsNSSShutDownPreventionLock locker; nsresult rv = NS_ERROR_FAILURE; char *keystring = nsnull; char *keyparamsString = nsnull, *str = nsnull; KeyType type; PRUint32 keyGenMechanism; PRInt32 primeBits; PK11SlotInfo *slot = nsnull; PK11RSAGenParams rsaParams; SECOidTag algTag; int keysize = 0; void *params; SECKEYPrivateKey *privateKey = nsnull; SECKEYPublicKey *publicKey = nsnull; CERTSubjectPublicKeyInfo *spkInfo = nsnull; PRArenaPool *arena = nsnull; SECStatus sec_rv = SECFailure; SECItem spkiItem; SECItem pkacItem; SECItem signedItem; CERTPublicKeyAndChallenge pkac; pkac.challenge.data = nsnull; nsIGeneratingKeypairInfoDialogs * dialogs; nsKeygenThread *KeygenRunnable = 0; nsCOMPtr<nsIKeygenThread> runnable; // Get the key size // for (size_t i = 0; i < number_of_key_size_choices; ++i) { if (aValue.Equals(mSECKeySizeChoiceList[i].name)) { keysize = mSECKeySizeChoiceList[i].size; break; } } if (!keysize) { goto loser; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { goto loser; } // Set the keygen mechanism if (aKeyType.IsEmpty() || aKeyType.LowerCaseEqualsLiteral("rsa")) { type = rsaKey; keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; } else if (aKeyType.LowerCaseEqualsLiteral("dsa")) { char * end; keyparamsString = ToNewCString(aKeyParams); if (!keyparamsString) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } type = dsaKey; keyGenMechanism = CKM_DSA_KEY_PAIR_GEN; if (strcmp(keyparamsString, "null") == 0) goto loser; str = keyparamsString; PRBool found_match = PR_FALSE; do { end = strchr(str, ','); if (end != nsnull) *end = '\0'; primeBits = pqg_prime_bits(str); if (keysize == primeBits) { found_match = PR_TRUE; break; } str = end + 1; } while (end != nsnull); if (!found_match) { goto loser; } } else if (aKeyType.LowerCaseEqualsLiteral("ec")) { keyparamsString = ToNewCString(aKeyParams); if (!keyparamsString) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } type = ecKey; keyGenMechanism = CKM_EC_KEY_PAIR_GEN; /* ecParams are initialized later */ } else { goto loser; } // Get the slot rv = GetSlot(keyGenMechanism, &slot); if (NS_FAILED(rv)) { goto loser; } switch (keyGenMechanism) { case CKM_RSA_PKCS_KEY_PAIR_GEN: rsaParams.keySizeInBits = keysize; rsaParams.pe = DEFAULT_RSA_KEYGEN_PE; algTag = DEFAULT_RSA_KEYGEN_ALG; params = &rsaParams; break; case CKM_DSA_KEY_PAIR_GEN: // XXX Fix this! XXX // goto loser; case CKM_EC_KEY_PAIR_GEN: /* XXX We ought to rethink how the KEYGEN tag is * displayed. The pulldown selections presented * to the user must depend on the keytype. * The displayed selection could be picked * from the keyparams attribute (this is currently called * the pqg attribute). * For now, we pick ecparams from the keyparams field * if it specifies a valid supported curve, or else * we pick one of secp384r1, secp256r1 or secp192r1 * respectively depending on the user's selection * (High, Medium, Low). * (RSA uses RSA-2048, RSA-1024 and RSA-512 for historical * reasons, while ECC choices represent a stronger mapping) * NOTE: The user's selection * is silently ignored when a valid curve is presented * in keyparams. */ if ((params = decode_ec_params(keyparamsString)) == nsnull) { /* The keyparams attribute did not specify a valid * curve name so use a curve based on the keysize. * NOTE: Here keysize is used only as an indication of * High/Medium/Low strength; elliptic curve * cryptography uses smaller keys than RSA to provide * equivalent security. */ switch (keysize) { case 2048: params = decode_ec_params("secp384r1"); break; case 1024: case 512: params = decode_ec_params("secp256r1"); break; } } /* XXX The signature algorithm ought to choose the hashing * algorithm based on key size once ECDSA variations based * on SHA256 SHA384 and SHA512 are standardized. */ algTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; break; default: goto loser; } /* Make sure token is initialized. */ rv = setPassword(slot, m_ctx); if (NS_FAILED(rv)) goto loser; sec_rv = PK11_Authenticate(slot, PR_TRUE, m_ctx); if (sec_rv != SECSuccess) { goto loser; } rv = getNSSDialogs((void**)&dialogs, NS_GET_IID(nsIGeneratingKeypairInfoDialogs), NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID); if (NS_SUCCEEDED(rv)) { KeygenRunnable = new nsKeygenThread(); NS_IF_ADDREF(KeygenRunnable); } if (NS_FAILED(rv) || !KeygenRunnable) { rv = NS_OK; privateKey = PK11_GenerateKeyPair(slot, keyGenMechanism, params, &publicKey, PR_TRUE, PR_TRUE, m_ctx); } else { KeygenRunnable->SetParams( slot, keyGenMechanism, params, PR_TRUE, PR_TRUE, m_ctx ); runnable = do_QueryInterface(KeygenRunnable); if (runnable) { { nsPSMUITracker tracker; if (tracker.isUIForbidden()) { rv = NS_ERROR_NOT_AVAILABLE; } else { rv = dialogs->DisplayGeneratingKeypairInfo(m_ctx, runnable); // We call join on the thread, // so we can be sure that no simultaneous access to the passed parameters will happen. KeygenRunnable->Join(); } } NS_RELEASE(dialogs); if (NS_SUCCEEDED(rv)) { rv = KeygenRunnable->GetParams(&privateKey, &publicKey); } } } if (NS_FAILED(rv) || !privateKey) { goto loser; } // just in case we'll need to authenticate to the db -jp // privateKey->wincx = m_ctx; /* * Create a subject public key info from the public key. */ spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey); if ( !spkInfo ) { goto loser; } /* * Now DER encode the whole subjectPublicKeyInfo. */ sec_rv=DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate, spkInfo); if (sec_rv != SECSuccess) { goto loser; } /* * set up the PublicKeyAndChallenge data structure, then DER encode it */ pkac.spki = spkiItem; pkac.challenge.len = aChallenge.Length(); pkac.challenge.data = (unsigned char *)ToNewCString(aChallenge); if (!pkac.challenge.data) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } sec_rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate, &pkac); if ( sec_rv != SECSuccess ) { goto loser; } /* * now sign the DER encoded PublicKeyAndChallenge */ sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len, privateKey, algTag); if ( sec_rv != SECSuccess ) { goto loser; } /* * Convert the signed public key and challenge into base64/ascii. */ keystring = BTOA_DataToAscii(signedItem.data, signedItem.len); if (!keystring) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; } CopyASCIItoUTF16(keystring, aOutPublicKey); nsCRT::free(keystring); rv = NS_OK; loser: if ( sec_rv != SECSuccess ) { if ( privateKey ) { PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID); } if ( publicKey ) { PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID); } } if ( spkInfo ) { SECKEY_DestroySubjectPublicKeyInfo(spkInfo); } if ( publicKey ) { SECKEY_DestroyPublicKey(publicKey); } if ( privateKey ) { SECKEY_DestroyPrivateKey(privateKey); } if ( arena ) { PORT_FreeArena(arena, PR_TRUE); } if (slot != nsnull) { PK11_FreeSlot(slot); } if (KeygenRunnable) { NS_RELEASE(KeygenRunnable); } if (keyparamsString) { nsMemory::Free(keyparamsString); } if (pkac.challenge.data) { nsMemory::Free(pkac.challenge.data); } return rv; }