bool CryptoKey::PublicKeyValid(SECKEYPublicKey* aPubKey) { ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return false; } // This assumes that NSS checks the validity of a public key when // it is imported into a PKCS#11 module, and returns CK_INVALID_HANDLE // if it is invalid. CK_OBJECT_HANDLE id = PK11_ImportPublicKey(slot, aPubKey, PR_FALSE); if (id == CK_INVALID_HANDLE) { return false; } SECStatus rv = PK11_DestroyObject(slot, id); return (rv == SECSuccess); }
static int cmmf_create_witness_and_challenge(PRArenaPool *poolp, CMMFChallenge *challenge, long inRandom, SECItem *senderDER, SECKEYPublicKey *inPubKey, void *passwdArg) { SECItem *encodedRandNum; SECItem encodedRandStr = {siBuffer, NULL, 0}; SECItem *dummy; unsigned char *randHash, *senderHash, *encChal=NULL; unsigned modulusLen = 0; SECStatus rv = SECFailure; CMMFRand randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}}; PK11SlotInfo *slot; PK11SymKey *symKey = NULL; CK_OBJECT_HANDLE id; CERTSubjectPublicKeyInfo *spki = NULL; encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber, inRandom); encodedRandNum = &challenge->randomNumber; randHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH); senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH); if (randHash == NULL) { goto loser; } rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data, (PRUint32)encodedRandNum->len); if (rv != SECSuccess) { goto loser; } rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data, (PRUint32)senderDER->len); if (rv != SECSuccess) { goto loser; } challenge->witness.data = randHash; challenge->witness.len = SHA1_LENGTH; randStr.integer = *encodedRandNum; randStr.senderHash.data = senderHash; randStr.senderHash.len = SHA1_LENGTH; dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr, CMMFRandTemplate); if (dummy != &encodedRandStr) { rv = SECFailure; goto loser; } /* XXXX Now I have to encrypt encodedRandStr and stash it away. */ modulusLen = SECKEY_PublicKeyStrength(inPubKey); encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen); if (encChal == NULL) { rv = SECFailure; goto loser; } slot =PK11_GetBestSlotWithAttributes(CKM_RSA_PKCS, CKF_WRAP, 0, passwdArg); if (slot == NULL) { rv = SECFailure; goto loser; } id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE); /* In order to properly encrypt the data, we import as a symmetric * key, and then wrap that key. That in essence encrypts the data. * This is the method recommended in the PK11 world in order * to prevent threading issues as well as breaking any other semantics * the PK11 libraries depend on. */ symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated, CKA_VALUE, &encodedRandStr, passwdArg); if (symKey == NULL) { rv = SECFailure; goto loser; } challenge->challenge.data = encChal; challenge->challenge.len = modulusLen; rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey, &challenge->challenge); PK11_FreeSlot(slot); if (rv != SECSuccess) { goto loser; } rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER); crmf_get_public_value(inPubKey, &challenge->key); /* Fall through */ loser: if (spki != NULL) { SECKEY_DestroySubjectPublicKeyInfo(spki); } if (encodedRandStr.data != NULL) { PORT_Free(encodedRandStr.data); } if (encodedRandNum != NULL) { SECITEM_FreeItem(encodedRandNum, PR_TRUE); } if (symKey != NULL) { PK11_FreeSymKey(symKey); } return rv; }