| Index: nss/lib/cryptohi/seckey.c
|
| diff --git a/nss/lib/cryptohi/seckey.c b/nss/lib/cryptohi/seckey.c
|
| deleted file mode 100644
|
| index 827413a7012c20d35e87be63518db0773e850390..0000000000000000000000000000000000000000
|
| --- a/nss/lib/cryptohi/seckey.c
|
| +++ /dev/null
|
| @@ -1,1939 +0,0 @@
|
| -/* This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -#include "cryptohi.h"
|
| -#include "keyhi.h"
|
| -#include "secoid.h"
|
| -#include "secitem.h"
|
| -#include "secder.h"
|
| -#include "base64.h"
|
| -#include "secasn1.h"
|
| -#include "cert.h"
|
| -#include "pk11func.h"
|
| -#include "secerr.h"
|
| -#include "secdig.h"
|
| -#include "prtime.h"
|
| -#include "keyi.h"
|
| -
|
| -SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
|
| -SEC_ASN1_MKSUB(SEC_IntegerTemplate)
|
| -
|
| -const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE,
|
| - 0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
|
| - { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
|
| - offsetof(CERTSubjectPublicKeyInfo, algorithm),
|
| - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
|
| - { SEC_ASN1_BIT_STRING,
|
| - offsetof(CERTSubjectPublicKeyInfo, subjectPublicKey) },
|
| - { 0 }
|
| -};
|
| -
|
| -const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
|
| - {
|
| - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
|
| - { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge, spki) },
|
| - { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge, challenge) },
|
| - { 0 }
|
| - };
|
| -
|
| -const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.rsa.modulus) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.rsa.publicExponent) },
|
| - { 0 }
|
| -};
|
| -
|
| -static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = {
|
| - { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0,
|
| - SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }
|
| -};
|
| -
|
| -/* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */
|
| -const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] =
|
| - {
|
| - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) },
|
| - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
|
| - SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
| - offsetof(SECKEYRSAPSSParams, hashAlg),
|
| - seckey_PointerToAlgorithmIDTemplate },
|
| - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
|
| - SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
| - offsetof(SECKEYRSAPSSParams, maskAlg),
|
| - seckey_PointerToAlgorithmIDTemplate },
|
| - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
|
| - SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2,
|
| - offsetof(SECKEYRSAPSSParams, saltLength),
|
| - SEC_ASN1_SUB(SEC_IntegerTemplate) },
|
| - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
|
| - SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3,
|
| - offsetof(SECKEYRSAPSSParams, trailerField),
|
| - SEC_ASN1_SUB(SEC_IntegerTemplate) },
|
| - { 0 }
|
| - };
|
| -
|
| -const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dsa.publicValue) },
|
| - { 0 }
|
| -};
|
| -
|
| -const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) },
|
| - { 0 }
|
| -};
|
| -
|
| -const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.publicValue) },
|
| - { 0 }
|
| -};
|
| -
|
| -const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.prime) },
|
| - { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.base) },
|
| - /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
|
| - { SEC_ASN1_SKIP_REST },
|
| - { 0 }
|
| -};
|
| -
|
| -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
|
| -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
|
| -SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate)
|
| -SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
|
| -
|
| -/*
|
| - * See bugzilla bug 125359
|
| - * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
|
| - * all of the templates above that en/decode into integers must be converted
|
| - * from ASN.1's signed integer type. This is done by marking either the
|
| - * source or destination (encoding or decoding, respectively) type as
|
| - * siUnsignedInteger.
|
| - */
|
| -static void
|
| -prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
|
| -{
|
| - pubk->u.rsa.modulus.type = siUnsignedInteger;
|
| - pubk->u.rsa.publicExponent.type = siUnsignedInteger;
|
| -}
|
| -
|
| -static void
|
| -prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
|
| -{
|
| - pubk->u.dsa.publicValue.type = siUnsignedInteger;
|
| -}
|
| -
|
| -static void
|
| -prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
|
| -{
|
| - params->prime.type = siUnsignedInteger;
|
| - params->subPrime.type = siUnsignedInteger;
|
| - params->base.type = siUnsignedInteger;
|
| -}
|
| -
|
| -static void
|
| -prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
|
| -{
|
| - pubk->u.dh.prime.type = siUnsignedInteger;
|
| - pubk->u.dh.base.type = siUnsignedInteger;
|
| - pubk->u.dh.publicValue.type = siUnsignedInteger;
|
| -}
|
| -
|
| -/* Create an RSA key pair is any slot able to do so.
|
| -** The created keys are "session" (temporary), not "token" (permanent),
|
| -** and they are "sensitive", which makes them costly to move to another token.
|
| -*/
|
| -SECKEYPrivateKey *
|
| -SECKEY_CreateRSAPrivateKey(int keySizeInBits, SECKEYPublicKey **pubk, void *cx)
|
| -{
|
| - SECKEYPrivateKey *privk;
|
| - PK11RSAGenParams param;
|
| - PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, cx);
|
| - if (!slot) {
|
| - return NULL;
|
| - }
|
| -
|
| - param.keySizeInBits = keySizeInBits;
|
| - param.pe = 65537L;
|
| -
|
| - privk = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶m, pubk,
|
| - PR_FALSE, PR_TRUE, cx);
|
| - PK11_FreeSlot(slot);
|
| - return (privk);
|
| -}
|
| -
|
| -/* Create a DH key pair in any slot able to do so,
|
| -** This is a "session" (temporary), not "token" (permanent) key.
|
| -** Because of the high probability that this key will need to be moved to
|
| -** another token, and the high cost of moving "sensitive" keys, we attempt
|
| -** to create this key pair without the "sensitive" attribute, but revert to
|
| -** creating a "sensitive" key if necessary.
|
| -*/
|
| -SECKEYPrivateKey *
|
| -SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
|
| -{
|
| - SECKEYPrivateKey *privk;
|
| - PK11SlotInfo *slot;
|
| -
|
| - if (!param || !param->base.data || !param->prime.data ||
|
| - SECKEY_BigIntegerBitLength(¶m->prime) < DH_MIN_P_BITS ||
|
| - param->base.len == 0 || param->base.len > param->prime.len + 1 ||
|
| - (param->base.len == 1 && param->base.data[0] == 0)) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return NULL;
|
| - }
|
| -
|
| - slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, cx);
|
| - if (!slot) {
|
| - return NULL;
|
| - }
|
| -
|
| - privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
|
| - pubk, PR_FALSE, PR_FALSE, cx);
|
| - if (!privk)
|
| - privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
|
| - pubk, PR_FALSE, PR_TRUE, cx);
|
| -
|
| - PK11_FreeSlot(slot);
|
| - return (privk);
|
| -}
|
| -
|
| -/* Create an EC key pair in any slot able to do so,
|
| -** This is a "session" (temporary), not "token" (permanent) key.
|
| -** Because of the high probability that this key will need to be moved to
|
| -** another token, and the high cost of moving "sensitive" keys, we attempt
|
| -** to create this key pair without the "sensitive" attribute, but revert to
|
| -** creating a "sensitive" key if necessary.
|
| -*/
|
| -SECKEYPrivateKey *
|
| -SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
|
| -{
|
| - SECKEYPrivateKey *privk;
|
| - PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN, cx);
|
| - if (!slot) {
|
| - return NULL;
|
| - }
|
| -
|
| - privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
|
| - param, pubk,
|
| - PK11_ATTR_SESSION |
|
| - PK11_ATTR_INSENSITIVE |
|
| - PK11_ATTR_PUBLIC,
|
| - CKF_DERIVE, CKF_DERIVE |
|
| - CKF_SIGN,
|
| - cx);
|
| - if (!privk)
|
| - privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
|
| - param, pubk,
|
| - PK11_ATTR_SESSION |
|
| - PK11_ATTR_SENSITIVE |
|
| - PK11_ATTR_PRIVATE,
|
| - CKF_DERIVE, CKF_DERIVE |
|
| - CKF_SIGN,
|
| - cx);
|
| -
|
| - PK11_FreeSlot(slot);
|
| - return (privk);
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
|
| -{
|
| - if (privk) {
|
| - if (privk->pkcs11Slot) {
|
| - if (privk->pkcs11IsTemp) {
|
| - PK11_DestroyObject(privk->pkcs11Slot, privk->pkcs11ID);
|
| - }
|
| - PK11_FreeSlot(privk->pkcs11Slot);
|
| - }
|
| - if (privk->arena) {
|
| - PORT_FreeArena(privk->arena, PR_TRUE);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
|
| -{
|
| - if (pubk) {
|
| - if (pubk->pkcs11Slot) {
|
| - if (!PK11_IsPermObject(pubk->pkcs11Slot, pubk->pkcs11ID)) {
|
| - PK11_DestroyObject(pubk->pkcs11Slot, pubk->pkcs11ID);
|
| - }
|
| - PK11_FreeSlot(pubk->pkcs11Slot);
|
| - }
|
| - if (pubk->arena) {
|
| - PORT_FreeArena(pubk->arena, PR_FALSE);
|
| - }
|
| - }
|
| -}
|
| -
|
| -SECStatus
|
| -SECKEY_CopySubjectPublicKeyInfo(PLArenaPool *arena,
|
| - CERTSubjectPublicKeyInfo *to,
|
| - CERTSubjectPublicKeyInfo *from)
|
| -{
|
| - SECStatus rv;
|
| - SECItem spk;
|
| -
|
| - rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
|
| - if (rv == SECSuccess) {
|
| - /*
|
| - * subjectPublicKey is a bit string, whose length is in bits.
|
| - * Convert the length from bits to bytes for SECITEM_CopyItem.
|
| - */
|
| - spk = from->subjectPublicKey;
|
| - DER_ConvertBitString(&spk);
|
| - rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
|
| - /* Set the length back to bits. */
|
| - if (rv == SECSuccess) {
|
| - to->subjectPublicKey.len = from->subjectPublicKey.len;
|
| - }
|
| - }
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -/* Procedure to update the pqg parameters for a cert's public key.
|
| - * pqg parameters only need to be updated for DSA certificates.
|
| - * The procedure uses calls to itself recursively to update a certificate
|
| - * issuer's pqg parameters. Some important rules are:
|
| - * - Do nothing if the cert already has PQG parameters.
|
| - * - If the cert does not have PQG parameters, obtain them from the issuer.
|
| - * - A valid cert chain cannot have a DSA cert without
|
| - * pqg parameters that has a parent that is not a DSA cert. */
|
| -
|
| -static SECStatus
|
| -seckey_UpdateCertPQGChain(CERTCertificate *subjectCert, int count)
|
| -{
|
| - SECStatus rv;
|
| - SECOidData *oid = NULL;
|
| - int tag;
|
| - CERTSubjectPublicKeyInfo *subjectSpki = NULL;
|
| - CERTSubjectPublicKeyInfo *issuerSpki = NULL;
|
| - CERTCertificate *issuerCert = NULL;
|
| -
|
| - rv = SECSuccess;
|
| -
|
| - /* increment cert chain length counter*/
|
| - count++;
|
| -
|
| - /* check if cert chain length exceeds the maximum length*/
|
| - if (count > CERT_MAX_CERT_CHAIN) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);
|
| - if (oid != NULL) {
|
| - tag = oid->offset;
|
| -
|
| - /* Check if cert has a DSA or EC public key. If not, return
|
| - * success since no PQG params need to be updated.
|
| - *
|
| - * Question: do we really need to do this for EC keys. They don't have
|
| - * PQG parameters, but they do have parameters. The question is does
|
| - * the child cert inherit thost parameters for EC from the parent, or
|
| - * do we always include those parameters in each cert.
|
| - */
|
| -
|
| - if ((tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
|
| - (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
|
| - (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
|
| - (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
|
| - (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
|
| - (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
|
| - (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
|
| -
|
| - return SECSuccess;
|
| - }
|
| - } else {
|
| - return SECFailure; /* return failure if oid is NULL */
|
| - }
|
| -
|
| - /* if cert has PQG parameters, return success */
|
| -
|
| - subjectSpki = &subjectCert->subjectPublicKeyInfo;
|
| -
|
| - if (subjectSpki->algorithm.parameters.len != 0) {
|
| - return SECSuccess;
|
| - }
|
| -
|
| - /* check if the cert is self-signed */
|
| - if (subjectCert->isRoot) {
|
| - /* fail since cert is self-signed and has no pqg params. */
|
| - return SECFailure;
|
| - }
|
| -
|
| - /* get issuer cert */
|
| - issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
|
| - if (!issuerCert) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - /* if parent is not DSA, return failure since
|
| - we don't allow this case. */
|
| -
|
| - oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
|
| - if (oid != NULL) {
|
| - tag = oid->offset;
|
| -
|
| - /* Check if issuer cert has a DSA public key. If not,
|
| - * return failure. */
|
| -
|
| - if ((tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
|
| - (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
|
| - (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
|
| - (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
|
| - (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
|
| - (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
|
| - (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
|
| - rv = SECFailure;
|
| - goto loser;
|
| - }
|
| - } else {
|
| - rv = SECFailure; /* return failure if oid is NULL */
|
| - goto loser;
|
| - }
|
| -
|
| - /* at this point the subject cert has no pqg parameters and the
|
| - * issuer cert has a DSA public key. Update the issuer's
|
| - * pqg parameters with a recursive call to this same function. */
|
| -
|
| - rv = seckey_UpdateCertPQGChain(issuerCert, count);
|
| - if (rv != SECSuccess) {
|
| - rv = SECFailure;
|
| - goto loser;
|
| - }
|
| -
|
| - /* ensure issuer has pqg parameters */
|
| -
|
| - issuerSpki = &issuerCert->subjectPublicKeyInfo;
|
| - if (issuerSpki->algorithm.parameters.len == 0) {
|
| - rv = SECFailure;
|
| - }
|
| -
|
| - /* if update was successful and pqg params present, then copy the
|
| - * parameters to the subject cert's key. */
|
| -
|
| - if (rv == SECSuccess) {
|
| - rv = SECITEM_CopyItem(subjectCert->arena,
|
| - &subjectSpki->algorithm.parameters,
|
| - &issuerSpki->algorithm.parameters);
|
| - }
|
| -
|
| -loser:
|
| - if (issuerCert) {
|
| - CERT_DestroyCertificate(issuerCert);
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -SECStatus
|
| -SECKEY_UpdateCertPQG(CERTCertificate *subjectCert)
|
| -{
|
| - if (!subjectCert) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return SECFailure;
|
| - }
|
| - return seckey_UpdateCertPQGChain(subjectCert, 0);
|
| -}
|
| -
|
| -/* Decode the DSA PQG parameters. The params could be stored in two
|
| - * possible formats, the old fortezza-only wrapped format or
|
| - * the normal standard format. Store the decoded parameters in
|
| - * a V3 certificate data structure. */
|
| -
|
| -static SECStatus
|
| -seckey_DSADecodePQG(PLArenaPool *arena, SECKEYPublicKey *pubk,
|
| - const SECItem *params)
|
| -{
|
| - SECStatus rv;
|
| - SECItem newparams;
|
| -
|
| - if (params == NULL)
|
| - return SECFailure;
|
| -
|
| - if (params->data == NULL)
|
| - return SECFailure;
|
| -
|
| - PORT_Assert(arena);
|
| -
|
| - /* make a copy of the data into the arena so QuickDER output is valid */
|
| - rv = SECITEM_CopyItem(arena, &newparams, params);
|
| -
|
| - /* Check if params use the standard format.
|
| - * The value 0xa1 will appear in the first byte of the parameter data
|
| - * if the PQG parameters are not using the standard format. This
|
| - * code should be changed to use a better method to detect non-standard
|
| - * parameters. */
|
| -
|
| - if ((newparams.data[0] != 0xa1) &&
|
| - (newparams.data[0] != 0xa0)) {
|
| -
|
| - if (SECSuccess == rv) {
|
| - /* PQG params are in the standard format */
|
| - prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
|
| - rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
|
| - SECKEY_PQGParamsTemplate,
|
| - &newparams);
|
| - }
|
| - } else {
|
| -
|
| - if (SECSuccess == rv) {
|
| - /* else the old fortezza-only wrapped format is used. */
|
| - PORT_SetError(SEC_ERROR_BAD_DER);
|
| - rv = SECFailure;
|
| - }
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -/* Function used to make an oid tag to a key type */
|
| -KeyType
|
| -seckey_GetKeyType(SECOidTag tag)
|
| -{
|
| - KeyType keyType;
|
| -
|
| - switch (tag) {
|
| - case SEC_OID_X500_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
| - keyType = rsaKey;
|
| - break;
|
| - case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
|
| - keyType = rsaPssKey;
|
| - break;
|
| - case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
|
| - keyType = rsaOaepKey;
|
| - break;
|
| - case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
| - keyType = dsaKey;
|
| - break;
|
| - case SEC_OID_MISSI_KEA_DSS_OLD:
|
| - case SEC_OID_MISSI_KEA_DSS:
|
| - case SEC_OID_MISSI_DSS_OLD:
|
| - case SEC_OID_MISSI_DSS:
|
| - keyType = fortezzaKey;
|
| - break;
|
| - case SEC_OID_MISSI_KEA:
|
| - case SEC_OID_MISSI_ALT_KEA:
|
| - keyType = keaKey;
|
| - break;
|
| - case SEC_OID_X942_DIFFIE_HELMAN_KEY:
|
| - keyType = dhKey;
|
| - break;
|
| - case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
| - keyType = ecKey;
|
| - break;
|
| - /* accommodate applications that hand us a signature type when they
|
| - * should be handing us a cipher type */
|
| - case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
|
| - keyType = rsaKey;
|
| - break;
|
| - default:
|
| - keyType = nullKey;
|
| - }
|
| - return keyType;
|
| -}
|
| -
|
| -/* Function used to determine what kind of cert we are dealing with. */
|
| -KeyType
|
| -CERT_GetCertKeyType(const CERTSubjectPublicKeyInfo *spki)
|
| -{
|
| - return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
|
| -}
|
| -
|
| -static SECKEYPublicKey *
|
| -seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
|
| -{
|
| - SECKEYPublicKey *pubk;
|
| - SECItem os, newOs, newParms;
|
| - SECStatus rv;
|
| - PLArenaPool *arena;
|
| - SECOidTag tag;
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL)
|
| - return NULL;
|
| -
|
| - pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
|
| - if (pubk == NULL) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - return NULL;
|
| - }
|
| -
|
| - pubk->arena = arena;
|
| - pubk->pkcs11Slot = 0;
|
| - pubk->pkcs11ID = CK_INVALID_HANDLE;
|
| -
|
| - /* Convert bit string length from bits to bytes */
|
| - os = spki->subjectPublicKey;
|
| - DER_ConvertBitString(&os);
|
| -
|
| - tag = SECOID_GetAlgorithmTag(&spki->algorithm);
|
| -
|
| - /* copy the DER into the arena, since Quick DER returns data that points
|
| - into the DER input, which may get freed by the caller */
|
| - rv = SECITEM_CopyItem(arena, &newOs, &os);
|
| - if (rv == SECSuccess)
|
| - switch (tag) {
|
| - case SEC_OID_X500_RSA_ENCRYPTION:
|
| - case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
| - pubk->keyType = rsaKey;
|
| - prepare_rsa_pub_key_for_asn1(pubk);
|
| - rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
|
| - if (rv == SECSuccess)
|
| - return pubk;
|
| - break;
|
| - case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
| - case SEC_OID_SDN702_DSA_SIGNATURE:
|
| - pubk->keyType = dsaKey;
|
| - prepare_dsa_pub_key_for_asn1(pubk);
|
| - rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
|
| - if (rv != SECSuccess)
|
| - break;
|
| -
|
| - rv = seckey_DSADecodePQG(arena, pubk,
|
| - &spki->algorithm.parameters);
|
| -
|
| - if (rv == SECSuccess)
|
| - return pubk;
|
| - break;
|
| - case SEC_OID_X942_DIFFIE_HELMAN_KEY:
|
| - pubk->keyType = dhKey;
|
| - prepare_dh_pub_key_for_asn1(pubk);
|
| - rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
|
| - if (rv != SECSuccess)
|
| - break;
|
| -
|
| - /* copy the DER into the arena, since Quick DER returns data that points
|
| - into the DER input, which may get freed by the caller */
|
| - rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
|
| - if (rv != SECSuccess)
|
| - break;
|
| -
|
| - rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
|
| - &newParms);
|
| -
|
| - if (rv == SECSuccess)
|
| - return pubk;
|
| - break;
|
| - case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
|
| - pubk->keyType = ecKey;
|
| - pubk->u.ec.size = 0;
|
| -
|
| - /* Since PKCS#11 directly takes the DER encoding of EC params
|
| - * and public value, we don't need any decoding here.
|
| - */
|
| - rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams,
|
| - &spki->algorithm.parameters);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
|
| - if (rv == SECSuccess)
|
| - return pubk;
|
| - break;
|
| -
|
| - default:
|
| - PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
| - rv = SECFailure;
|
| - break;
|
| - }
|
| -
|
| - SECKEY_DestroyPublicKey(pubk);
|
| - return NULL;
|
| -}
|
| -
|
| -/* required for JSS */
|
| -SECKEYPublicKey *
|
| -SECKEY_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
|
| -{
|
| - return seckey_ExtractPublicKey(spki);
|
| -}
|
| -
|
| -SECKEYPublicKey *
|
| -CERT_ExtractPublicKey(CERTCertificate *cert)
|
| -{
|
| - SECStatus rv;
|
| -
|
| - if (!cert) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return NULL;
|
| - }
|
| - rv = SECKEY_UpdateCertPQG(cert);
|
| - if (rv != SECSuccess)
|
| - return NULL;
|
| -
|
| - return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
|
| -}
|
| -
|
| -int
|
| -SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
|
| -{
|
| - SECOidTag tag;
|
| - SECItem oid = { siBuffer, NULL, 0 };
|
| -
|
| - /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
|
| - * followed by the length of the curve oid and the curve oid.
|
| - */
|
| - oid.len = encodedParams->data[1];
|
| - oid.data = encodedParams->data + 2;
|
| - if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
|
| - return 0;
|
| -
|
| - switch (tag) {
|
| - case SEC_OID_SECG_EC_SECP112R1:
|
| - case SEC_OID_SECG_EC_SECP112R2:
|
| - return 112;
|
| -
|
| - case SEC_OID_SECG_EC_SECT113R1:
|
| - case SEC_OID_SECG_EC_SECT113R2:
|
| - return 113;
|
| -
|
| - case SEC_OID_SECG_EC_SECP128R1:
|
| - case SEC_OID_SECG_EC_SECP128R2:
|
| - return 128;
|
| -
|
| - case SEC_OID_SECG_EC_SECT131R1:
|
| - case SEC_OID_SECG_EC_SECT131R2:
|
| - return 131;
|
| -
|
| - case SEC_OID_SECG_EC_SECP160K1:
|
| - case SEC_OID_SECG_EC_SECP160R1:
|
| - case SEC_OID_SECG_EC_SECP160R2:
|
| - return 160;
|
| -
|
| - case SEC_OID_SECG_EC_SECT163K1:
|
| - case SEC_OID_SECG_EC_SECT163R1:
|
| - case SEC_OID_SECG_EC_SECT163R2:
|
| - case SEC_OID_ANSIX962_EC_C2PNB163V1:
|
| - case SEC_OID_ANSIX962_EC_C2PNB163V2:
|
| - case SEC_OID_ANSIX962_EC_C2PNB163V3:
|
| - return 163;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB176V1:
|
| - return 176;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2TNB191V1:
|
| - case SEC_OID_ANSIX962_EC_C2TNB191V2:
|
| - case SEC_OID_ANSIX962_EC_C2TNB191V3:
|
| - case SEC_OID_ANSIX962_EC_C2ONB191V4:
|
| - case SEC_OID_ANSIX962_EC_C2ONB191V5:
|
| - return 191;
|
| -
|
| - case SEC_OID_SECG_EC_SECP192K1:
|
| - case SEC_OID_ANSIX962_EC_PRIME192V1:
|
| - case SEC_OID_ANSIX962_EC_PRIME192V2:
|
| - case SEC_OID_ANSIX962_EC_PRIME192V3:
|
| - return 192;
|
| -
|
| - case SEC_OID_SECG_EC_SECT193R1:
|
| - case SEC_OID_SECG_EC_SECT193R2:
|
| - return 193;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB208W1:
|
| - return 208;
|
| -
|
| - case SEC_OID_SECG_EC_SECP224K1:
|
| - case SEC_OID_SECG_EC_SECP224R1:
|
| - return 224;
|
| -
|
| - case SEC_OID_SECG_EC_SECT233K1:
|
| - case SEC_OID_SECG_EC_SECT233R1:
|
| - return 233;
|
| -
|
| - case SEC_OID_SECG_EC_SECT239K1:
|
| - case SEC_OID_ANSIX962_EC_C2TNB239V1:
|
| - case SEC_OID_ANSIX962_EC_C2TNB239V2:
|
| - case SEC_OID_ANSIX962_EC_C2TNB239V3:
|
| - case SEC_OID_ANSIX962_EC_C2ONB239V4:
|
| - case SEC_OID_ANSIX962_EC_C2ONB239V5:
|
| - case SEC_OID_ANSIX962_EC_PRIME239V1:
|
| - case SEC_OID_ANSIX962_EC_PRIME239V2:
|
| - case SEC_OID_ANSIX962_EC_PRIME239V3:
|
| - return 239;
|
| -
|
| - case SEC_OID_SECG_EC_SECP256K1:
|
| - case SEC_OID_ANSIX962_EC_PRIME256V1:
|
| - return 256;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB272W1:
|
| - return 272;
|
| -
|
| - case SEC_OID_SECG_EC_SECT283K1:
|
| - case SEC_OID_SECG_EC_SECT283R1:
|
| - return 283;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB304W1:
|
| - return 304;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2TNB359V1:
|
| - return 359;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB368W1:
|
| - return 368;
|
| -
|
| - case SEC_OID_SECG_EC_SECP384R1:
|
| - return 384;
|
| -
|
| - case SEC_OID_SECG_EC_SECT409K1:
|
| - case SEC_OID_SECG_EC_SECT409R1:
|
| - return 409;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2TNB431R1:
|
| - return 431;
|
| -
|
| - case SEC_OID_SECG_EC_SECP521R1:
|
| - return 521;
|
| -
|
| - case SEC_OID_SECG_EC_SECT571K1:
|
| - case SEC_OID_SECG_EC_SECT571R1:
|
| - return 571;
|
| -
|
| - default:
|
| - PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -int
|
| -SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
|
| -{
|
| - SECOidTag tag;
|
| - SECItem oid = { siBuffer, NULL, 0 };
|
| -
|
| - /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
|
| - * followed by the length of the curve oid and the curve oid.
|
| - */
|
| - oid.len = encodedParams->data[1];
|
| - oid.data = encodedParams->data + 2;
|
| - if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
|
| - return 0;
|
| -
|
| - switch (tag) {
|
| - case SEC_OID_SECG_EC_SECP112R1:
|
| - return 112;
|
| - case SEC_OID_SECG_EC_SECP112R2:
|
| - return 110;
|
| -
|
| - case SEC_OID_SECG_EC_SECT113R1:
|
| - case SEC_OID_SECG_EC_SECT113R2:
|
| - return 113;
|
| -
|
| - case SEC_OID_SECG_EC_SECP128R1:
|
| - return 128;
|
| - case SEC_OID_SECG_EC_SECP128R2:
|
| - return 126;
|
| -
|
| - case SEC_OID_SECG_EC_SECT131R1:
|
| - case SEC_OID_SECG_EC_SECT131R2:
|
| - return 131;
|
| -
|
| - case SEC_OID_SECG_EC_SECP160K1:
|
| - case SEC_OID_SECG_EC_SECP160R1:
|
| - case SEC_OID_SECG_EC_SECP160R2:
|
| - return 161;
|
| -
|
| - case SEC_OID_SECG_EC_SECT163K1:
|
| - return 163;
|
| - case SEC_OID_SECG_EC_SECT163R1:
|
| - return 162;
|
| - case SEC_OID_SECG_EC_SECT163R2:
|
| - case SEC_OID_ANSIX962_EC_C2PNB163V1:
|
| - return 163;
|
| - case SEC_OID_ANSIX962_EC_C2PNB163V2:
|
| - case SEC_OID_ANSIX962_EC_C2PNB163V3:
|
| - return 162;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB176V1:
|
| - return 161;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2TNB191V1:
|
| - return 191;
|
| - case SEC_OID_ANSIX962_EC_C2TNB191V2:
|
| - return 190;
|
| - case SEC_OID_ANSIX962_EC_C2TNB191V3:
|
| - return 189;
|
| - case SEC_OID_ANSIX962_EC_C2ONB191V4:
|
| - return 191;
|
| - case SEC_OID_ANSIX962_EC_C2ONB191V5:
|
| - return 188;
|
| -
|
| - case SEC_OID_SECG_EC_SECP192K1:
|
| - case SEC_OID_ANSIX962_EC_PRIME192V1:
|
| - case SEC_OID_ANSIX962_EC_PRIME192V2:
|
| - case SEC_OID_ANSIX962_EC_PRIME192V3:
|
| - return 192;
|
| -
|
| - case SEC_OID_SECG_EC_SECT193R1:
|
| - case SEC_OID_SECG_EC_SECT193R2:
|
| - return 193;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB208W1:
|
| - return 193;
|
| -
|
| - case SEC_OID_SECG_EC_SECP224K1:
|
| - return 225;
|
| - case SEC_OID_SECG_EC_SECP224R1:
|
| - return 224;
|
| -
|
| - case SEC_OID_SECG_EC_SECT233K1:
|
| - return 232;
|
| - case SEC_OID_SECG_EC_SECT233R1:
|
| - return 233;
|
| -
|
| - case SEC_OID_SECG_EC_SECT239K1:
|
| - case SEC_OID_ANSIX962_EC_C2TNB239V1:
|
| - return 238;
|
| - case SEC_OID_ANSIX962_EC_C2TNB239V2:
|
| - return 237;
|
| - case SEC_OID_ANSIX962_EC_C2TNB239V3:
|
| - return 236;
|
| - case SEC_OID_ANSIX962_EC_C2ONB239V4:
|
| - return 238;
|
| - case SEC_OID_ANSIX962_EC_C2ONB239V5:
|
| - return 237;
|
| - case SEC_OID_ANSIX962_EC_PRIME239V1:
|
| - case SEC_OID_ANSIX962_EC_PRIME239V2:
|
| - case SEC_OID_ANSIX962_EC_PRIME239V3:
|
| - return 239;
|
| -
|
| - case SEC_OID_SECG_EC_SECP256K1:
|
| - case SEC_OID_ANSIX962_EC_PRIME256V1:
|
| - return 256;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB272W1:
|
| - return 257;
|
| -
|
| - case SEC_OID_SECG_EC_SECT283K1:
|
| - return 281;
|
| - case SEC_OID_SECG_EC_SECT283R1:
|
| - return 282;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB304W1:
|
| - return 289;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2TNB359V1:
|
| - return 353;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2PNB368W1:
|
| - return 353;
|
| -
|
| - case SEC_OID_SECG_EC_SECP384R1:
|
| - return 384;
|
| -
|
| - case SEC_OID_SECG_EC_SECT409K1:
|
| - return 407;
|
| - case SEC_OID_SECG_EC_SECT409R1:
|
| - return 409;
|
| -
|
| - case SEC_OID_ANSIX962_EC_C2TNB431R1:
|
| - return 418;
|
| -
|
| - case SEC_OID_SECG_EC_SECP521R1:
|
| - return 521;
|
| -
|
| - case SEC_OID_SECG_EC_SECT571K1:
|
| - case SEC_OID_SECG_EC_SECT571R1:
|
| - return 570;
|
| -
|
| - default:
|
| - PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -/* The number of bits in the number from the first non-zero bit onward. */
|
| -unsigned
|
| -SECKEY_BigIntegerBitLength(const SECItem *number)
|
| -{
|
| - const unsigned char *p;
|
| - unsigned octets;
|
| - unsigned bits;
|
| -
|
| - if (!number || !number->data) {
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - return 0;
|
| - }
|
| -
|
| - p = number->data;
|
| - octets = number->len;
|
| - while (octets > 0 && !*p) {
|
| - ++p;
|
| - --octets;
|
| - }
|
| - if (octets == 0) {
|
| - return 0;
|
| - }
|
| - /* bits = 7..1 because we know at least one bit is set already */
|
| - /* Note: This could do a binary search, but this is faster for keys if we
|
| - * assume that good keys will have the MSB set. */
|
| - for (bits = 7; bits > 0; --bits) {
|
| - if (*p & (1 << bits)) {
|
| - break;
|
| - }
|
| - }
|
| - return octets * 8 + bits - 7;
|
| -}
|
| -
|
| -/* returns key strength in bytes (not bits) */
|
| -unsigned
|
| -SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
|
| -{
|
| - return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
|
| -}
|
| -
|
| -/* returns key strength in bits */
|
| -unsigned
|
| -SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
|
| -{
|
| - unsigned bitSize = 0;
|
| -
|
| - if (!pubk) {
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - return 0;
|
| - }
|
| -
|
| - /* interpret modulus length as key strength */
|
| - switch (pubk->keyType) {
|
| - case rsaKey:
|
| - bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
|
| - break;
|
| - case dsaKey:
|
| - bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.params.prime);
|
| - break;
|
| - case dhKey:
|
| - bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.prime);
|
| - break;
|
| - case ecKey:
|
| - bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
| - break;
|
| - default:
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - break;
|
| - }
|
| - return bitSize;
|
| -}
|
| -
|
| -/* returns signature length in bytes (not bits) */
|
| -unsigned
|
| -SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
|
| -{
|
| - unsigned char b0;
|
| - unsigned size;
|
| -
|
| - switch (pubk->keyType) {
|
| - case rsaKey:
|
| - b0 = pubk->u.rsa.modulus.data[0];
|
| - return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
|
| - case dsaKey:
|
| - return pubk->u.dsa.params.subPrime.len * 2;
|
| - case ecKey:
|
| - /* Get the base point order length in bits and adjust */
|
| - size = SECKEY_ECParamsToBasePointOrderLen(
|
| - &pubk->u.ec.DEREncodedParams);
|
| - return ((size + 7) / 8) * 2;
|
| - default:
|
| - break;
|
| - }
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - return 0;
|
| -}
|
| -
|
| -SECKEYPrivateKey *
|
| -SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
|
| -{
|
| - SECKEYPrivateKey *copyk;
|
| - PLArenaPool *arena;
|
| -
|
| - if (!privk || !privk->pkcs11Slot) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return NULL;
|
| - }
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - copyk = (SECKEYPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
|
| - if (copyk) {
|
| - copyk->arena = arena;
|
| - copyk->keyType = privk->keyType;
|
| -
|
| - /* copy the PKCS #11 parameters */
|
| - copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
|
| - /* if the key we're referencing was a temparary key we have just
|
| - * created, that we want to go away when we're through, we need
|
| - * to make a copy of it */
|
| - if (privk->pkcs11IsTemp) {
|
| - copyk->pkcs11ID =
|
| - PK11_CopyKey(privk->pkcs11Slot, privk->pkcs11ID);
|
| - if (copyk->pkcs11ID == CK_INVALID_HANDLE)
|
| - goto fail;
|
| - } else {
|
| - copyk->pkcs11ID = privk->pkcs11ID;
|
| - }
|
| - copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
|
| - copyk->wincx = privk->wincx;
|
| - copyk->staticflags = privk->staticflags;
|
| - return copyk;
|
| - } else {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - }
|
| -
|
| -fail:
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - return NULL;
|
| -}
|
| -
|
| -SECKEYPublicKey *
|
| -SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
|
| -{
|
| - SECKEYPublicKey *copyk;
|
| - PLArenaPool *arena;
|
| - SECStatus rv = SECSuccess;
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - return NULL;
|
| - }
|
| -
|
| - copyk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
|
| - if (!copyk) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - return NULL;
|
| - }
|
| -
|
| - copyk->arena = arena;
|
| - copyk->keyType = pubk->keyType;
|
| - if (pubk->pkcs11Slot &&
|
| - PK11_IsPermObject(pubk->pkcs11Slot, pubk->pkcs11ID)) {
|
| - copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
|
| - copyk->pkcs11ID = pubk->pkcs11ID;
|
| - } else {
|
| - copyk->pkcs11Slot = NULL; /* go get own reference */
|
| - copyk->pkcs11ID = CK_INVALID_HANDLE;
|
| - }
|
| - switch (pubk->keyType) {
|
| - case rsaKey:
|
| - rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus,
|
| - &pubk->u.rsa.modulus);
|
| - if (rv == SECSuccess) {
|
| - rv = SECITEM_CopyItem(arena, ©k->u.rsa.publicExponent,
|
| - &pubk->u.rsa.publicExponent);
|
| - if (rv == SECSuccess)
|
| - return copyk;
|
| - }
|
| - break;
|
| - case dsaKey:
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dsa.publicValue,
|
| - &pubk->u.dsa.publicValue);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.prime,
|
| - &pubk->u.dsa.params.prime);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.subPrime,
|
| - &pubk->u.dsa.params.subPrime);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.base,
|
| - &pubk->u.dsa.params.base);
|
| - break;
|
| - case dhKey:
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dh.prime, &pubk->u.dh.prime);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dh.base, &pubk->u.dh.base);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.dh.publicValue,
|
| - &pubk->u.dh.publicValue);
|
| - break;
|
| - case ecKey:
|
| - copyk->u.ec.size = pubk->u.ec.size;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.ec.DEREncodedParams,
|
| - &pubk->u.ec.DEREncodedParams);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = SECITEM_CopyItem(arena, ©k->u.ec.publicValue,
|
| - &pubk->u.ec.publicValue);
|
| - break;
|
| - case nullKey:
|
| - return copyk;
|
| - default:
|
| - PORT_SetError(SEC_ERROR_INVALID_KEY);
|
| - rv = SECFailure;
|
| - break;
|
| - }
|
| - if (rv == SECSuccess)
|
| - return copyk;
|
| -
|
| - SECKEY_DestroyPublicKey(copyk);
|
| - return NULL;
|
| -}
|
| -
|
| -SECKEYPublicKey *
|
| -SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
|
| -{
|
| - SECKEYPublicKey *pubk;
|
| - PLArenaPool *arena;
|
| - CERTCertificate *cert;
|
| - SECStatus rv;
|
| -
|
| - /*
|
| - * First try to look up the cert.
|
| - */
|
| - cert = PK11_GetCertFromPrivateKey(privk);
|
| - if (cert) {
|
| - pubk = CERT_ExtractPublicKey(cert);
|
| - CERT_DestroyCertificate(cert);
|
| - return pubk;
|
| - }
|
| -
|
| - /* couldn't find the cert, build pub key by hand */
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - return NULL;
|
| - }
|
| - pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
|
| - sizeof(SECKEYPublicKey));
|
| - if (pubk == NULL) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - return NULL;
|
| - }
|
| - pubk->keyType = privk->keyType;
|
| - pubk->pkcs11Slot = NULL;
|
| - pubk->pkcs11ID = CK_INVALID_HANDLE;
|
| - pubk->arena = arena;
|
| -
|
| - switch (privk->keyType) {
|
| - case nullKey:
|
| - case dhKey:
|
| - case dsaKey:
|
| - /* Nothing to query, if the cert isn't there, we're done -- no way
|
| - * to get the public key */
|
| - break;
|
| - case rsaKey:
|
| - rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
|
| - CKA_MODULUS, arena, &pubk->u.rsa.modulus);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
|
| - CKA_PUBLIC_EXPONENT, arena, &pubk->u.rsa.publicExponent);
|
| - if (rv != SECSuccess)
|
| - break;
|
| - return pubk;
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - return NULL;
|
| -}
|
| -
|
| -static CERTSubjectPublicKeyInfo *
|
| -seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk)
|
| -{
|
| - CERTSubjectPublicKeyInfo *spki;
|
| - PLArenaPool *arena;
|
| - SECItem params = { siBuffer, NULL, 0 };
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - return NULL;
|
| - }
|
| -
|
| - spki = (CERTSubjectPublicKeyInfo *)PORT_ArenaZAlloc(arena, sizeof(*spki));
|
| - if (spki != NULL) {
|
| - SECStatus rv;
|
| - SECItem *rv_item;
|
| -
|
| - spki->arena = arena;
|
| - switch (pubk->keyType) {
|
| - case rsaKey:
|
| - rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
|
| - SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
|
| - if (rv == SECSuccess) {
|
| - /*
|
| - * DER encode the public key into the subjectPublicKeyInfo.
|
| - */
|
| - prepare_rsa_pub_key_for_asn1(pubk);
|
| - rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
|
| - pubk, SECKEY_RSAPublicKeyTemplate);
|
| - if (rv_item != NULL) {
|
| - /*
|
| - * The stored value is supposed to be a BIT_STRING,
|
| - * so convert the length.
|
| - */
|
| - spki->subjectPublicKey.len <<= 3;
|
| - /*
|
| - * We got a good one; return it.
|
| - */
|
| - return spki;
|
| - }
|
| - }
|
| - break;
|
| - case dsaKey:
|
| - /* DER encode the params. */
|
| - prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
|
| - rv_item = SEC_ASN1EncodeItem(arena, ¶ms, &pubk->u.dsa.params,
|
| - SECKEY_PQGParamsTemplate);
|
| - if (rv_item != NULL) {
|
| - rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
|
| - SEC_OID_ANSIX9_DSA_SIGNATURE,
|
| - ¶ms);
|
| - if (rv == SECSuccess) {
|
| - /*
|
| - * DER encode the public key into the subjectPublicKeyInfo.
|
| - */
|
| - prepare_dsa_pub_key_for_asn1(pubk);
|
| - rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
|
| - pubk,
|
| - SECKEY_DSAPublicKeyTemplate);
|
| - if (rv_item != NULL) {
|
| - /*
|
| - * The stored value is supposed to be a BIT_STRING,
|
| - * so convert the length.
|
| - */
|
| - spki->subjectPublicKey.len <<= 3;
|
| - /*
|
| - * We got a good one; return it.
|
| - */
|
| - return spki;
|
| - }
|
| - }
|
| - }
|
| - SECITEM_FreeItem(¶ms, PR_FALSE);
|
| - break;
|
| - case ecKey:
|
| - rv = SECITEM_CopyItem(arena, ¶ms,
|
| - &pubk->u.ec.DEREncodedParams);
|
| - if (rv != SECSuccess)
|
| - break;
|
| -
|
| - rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
|
| - SEC_OID_ANSIX962_EC_PUBLIC_KEY,
|
| - ¶ms);
|
| - if (rv != SECSuccess)
|
| - break;
|
| -
|
| - rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
|
| - &pubk->u.ec.publicValue);
|
| -
|
| - if (rv == SECSuccess) {
|
| - /*
|
| - * The stored value is supposed to be a BIT_STRING,
|
| - * so convert the length.
|
| - */
|
| - spki->subjectPublicKey.len <<= 3;
|
| - /*
|
| - * We got a good one; return it.
|
| - */
|
| - return spki;
|
| - }
|
| - break;
|
| - case dhKey: /* later... */
|
| -
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - } else {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - }
|
| -
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - return NULL;
|
| -}
|
| -
|
| -CERTSubjectPublicKeyInfo *
|
| -SECKEY_CreateSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
|
| -{
|
| - CERTSubjectPublicKeyInfo *spki;
|
| - SECKEYPublicKey *tempKey;
|
| -
|
| - if (!pubk) {
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| - return NULL;
|
| - }
|
| -
|
| - tempKey = SECKEY_CopyPublicKey(pubk);
|
| - if (!tempKey) {
|
| - return NULL;
|
| - }
|
| - spki = seckey_CreateSubjectPublicKeyInfo_helper(tempKey);
|
| - SECKEY_DestroyPublicKey(tempKey);
|
| - return spki;
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
|
| -{
|
| - if (spki && spki->arena) {
|
| - PORT_FreeArena(spki->arena, PR_FALSE);
|
| - }
|
| -}
|
| -
|
| -SECItem *
|
| -SECKEY_EncodeDERSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
|
| -{
|
| - CERTSubjectPublicKeyInfo *spki = NULL;
|
| - SECItem *spkiDER = NULL;
|
| -
|
| - /* get the subjectpublickeyinfo */
|
| - spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
|
| - if (spki == NULL) {
|
| - goto finish;
|
| - }
|
| -
|
| - /* DER-encode the subjectpublickeyinfo */
|
| - spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL /*dest*/, spki,
|
| - CERT_SubjectPublicKeyInfoTemplate);
|
| -
|
| - SECKEY_DestroySubjectPublicKeyInfo(spki);
|
| -
|
| -finish:
|
| - return spkiDER;
|
| -}
|
| -
|
| -CERTSubjectPublicKeyInfo *
|
| -SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider)
|
| -{
|
| - PLArenaPool *arena;
|
| - CERTSubjectPublicKeyInfo *spki;
|
| - SECStatus rv;
|
| - SECItem newSpkider;
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - return NULL;
|
| - }
|
| -
|
| - spki = (CERTSubjectPublicKeyInfo *)
|
| - PORT_ArenaZAlloc(arena, sizeof(CERTSubjectPublicKeyInfo));
|
| - if (spki != NULL) {
|
| - spki->arena = arena;
|
| -
|
| - /* copy the DER into the arena, since Quick DER returns data that points
|
| - into the DER input, which may get freed by the caller */
|
| - rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
|
| - if (rv == SECSuccess) {
|
| - rv = SEC_QuickDERDecodeItem(arena, spki,
|
| - CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
|
| - }
|
| - if (rv == SECSuccess)
|
| - return spki;
|
| - } else {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - }
|
| -
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - return NULL;
|
| -}
|
| -
|
| -/*
|
| - * Decode a base64 ascii encoded DER encoded subject public key info.
|
| - */
|
| -CERTSubjectPublicKeyInfo *
|
| -SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(const char *spkistr)
|
| -{
|
| - CERTSubjectPublicKeyInfo *spki;
|
| - SECStatus rv;
|
| - SECItem der;
|
| -
|
| - rv = ATOB_ConvertAsciiToItem(&der, spkistr);
|
| - if (rv != SECSuccess)
|
| - return NULL;
|
| -
|
| - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
|
| -
|
| - PORT_Free(der.data);
|
| - return spki;
|
| -}
|
| -
|
| -/*
|
| - * Decode a base64 ascii encoded DER encoded public key and challenge
|
| - * Verify digital signature and make sure challenge matches
|
| - */
|
| -CERTSubjectPublicKeyInfo *
|
| -SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
|
| - void *wincx)
|
| -{
|
| - CERTSubjectPublicKeyInfo *spki = NULL;
|
| - CERTPublicKeyAndChallenge pkac;
|
| - SECStatus rv;
|
| - SECItem signedItem;
|
| - PLArenaPool *arena = NULL;
|
| - CERTSignedData sd;
|
| - SECItem sig;
|
| - SECKEYPublicKey *pubKey = NULL;
|
| - unsigned int len;
|
| -
|
| - signedItem.data = NULL;
|
| -
|
| - /* convert the base64 encoded data to binary */
|
| - rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
|
| - if (rv != SECSuccess) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* create an arena */
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* decode the outer wrapping of signed data */
|
| - PORT_Memset(&sd, 0, sizeof(CERTSignedData));
|
| - rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem);
|
| - if (rv) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* decode the public key and challenge wrapper */
|
| - PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
|
| - rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate,
|
| - &sd.data);
|
| - if (rv) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* decode the subject public key info */
|
| - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
|
| - if (spki == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* get the public key */
|
| - pubKey = seckey_ExtractPublicKey(spki);
|
| - if (pubKey == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* check the signature */
|
| - sig = sd.signature;
|
| - DER_ConvertBitString(&sig);
|
| - rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
|
| - &(sd.signatureAlgorithm), NULL, wincx);
|
| - if (rv != SECSuccess) {
|
| - goto loser;
|
| - }
|
| -
|
| - /* check the challenge */
|
| - if (challenge) {
|
| - len = PORT_Strlen(challenge);
|
| - /* length is right */
|
| - if (len != pkac.challenge.len) {
|
| - goto loser;
|
| - }
|
| - /* actual data is right */
|
| - if (PORT_Memcmp(challenge, pkac.challenge.data, len) != 0) {
|
| - goto loser;
|
| - }
|
| - }
|
| - goto done;
|
| -
|
| -loser:
|
| - /* make sure that we return null if we got an error */
|
| - if (spki) {
|
| - SECKEY_DestroySubjectPublicKeyInfo(spki);
|
| - }
|
| - spki = NULL;
|
| -
|
| -done:
|
| - if (signedItem.data) {
|
| - PORT_Free(signedItem.data);
|
| - }
|
| - if (arena) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - }
|
| - if (pubKey) {
|
| - SECKEY_DestroyPublicKey(pubKey);
|
| - }
|
| -
|
| - return spki;
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
|
| - PRBool freeit)
|
| -{
|
| - PLArenaPool *poolp;
|
| -
|
| - if (pvk != NULL) {
|
| - if (pvk->arena) {
|
| - poolp = pvk->arena;
|
| - /* zero structure since PORT_FreeArena does not support
|
| - * this yet.
|
| - */
|
| - PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
|
| - PORT_Memset(pvk, 0, sizeof(*pvk));
|
| - if (freeit == PR_TRUE) {
|
| - PORT_FreeArena(poolp, PR_TRUE);
|
| - } else {
|
| - pvk->arena = poolp;
|
| - }
|
| - } else {
|
| - SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
|
| - SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
|
| - SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
|
| - PORT_Memset(pvk, 0, sizeof(*pvk));
|
| - if (freeit == PR_TRUE) {
|
| - PORT_Free(pvk);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
|
| - PRBool freeit)
|
| -{
|
| - PLArenaPool *poolp;
|
| -
|
| - if (epki != NULL) {
|
| - if (epki->arena) {
|
| - poolp = epki->arena;
|
| - /* zero structure since PORT_FreeArena does not support
|
| - * this yet.
|
| - */
|
| - PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
|
| - PORT_Memset(epki, 0, sizeof(*epki));
|
| - if (freeit == PR_TRUE) {
|
| - PORT_FreeArena(poolp, PR_TRUE);
|
| - } else {
|
| - epki->arena = poolp;
|
| - }
|
| - } else {
|
| - SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
|
| - SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
|
| - PORT_Memset(epki, 0, sizeof(*epki));
|
| - if (freeit == PR_TRUE) {
|
| - PORT_Free(epki);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -SECStatus
|
| -SECKEY_CopyPrivateKeyInfo(PLArenaPool *poolp,
|
| - SECKEYPrivateKeyInfo *to,
|
| - const SECKEYPrivateKeyInfo *from)
|
| -{
|
| - SECStatus rv = SECFailure;
|
| -
|
| - if ((to == NULL) || (from == NULL)) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
|
| - if (rv != SECSuccess) {
|
| - return SECFailure;
|
| - }
|
| - rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
|
| - if (rv != SECSuccess) {
|
| - return SECFailure;
|
| - }
|
| - rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -SECStatus
|
| -SECKEY_CopyEncryptedPrivateKeyInfo(PLArenaPool *poolp,
|
| - SECKEYEncryptedPrivateKeyInfo *to,
|
| - const SECKEYEncryptedPrivateKeyInfo *from)
|
| -{
|
| - SECStatus rv = SECFailure;
|
| -
|
| - if ((to == NULL) || (from == NULL)) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
|
| - if (rv != SECSuccess) {
|
| - return SECFailure;
|
| - }
|
| - rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -KeyType
|
| -SECKEY_GetPrivateKeyType(const SECKEYPrivateKey *privKey)
|
| -{
|
| - return privKey->keyType;
|
| -}
|
| -
|
| -KeyType
|
| -SECKEY_GetPublicKeyType(const SECKEYPublicKey *pubKey)
|
| -{
|
| - return pubKey->keyType;
|
| -}
|
| -
|
| -SECKEYPublicKey *
|
| -SECKEY_ImportDERPublicKey(const SECItem *derKey, CK_KEY_TYPE type)
|
| -{
|
| - SECKEYPublicKey *pubk = NULL;
|
| - SECStatus rv = SECFailure;
|
| - SECItem newDerKey;
|
| - PLArenaPool *arena = NULL;
|
| -
|
| - if (!derKey) {
|
| - return NULL;
|
| - }
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - PORT_SetError(SEC_ERROR_NO_MEMORY);
|
| - goto finish;
|
| - }
|
| -
|
| - pubk = PORT_ArenaZNew(arena, SECKEYPublicKey);
|
| - if (pubk == NULL) {
|
| - goto finish;
|
| - }
|
| - pubk->arena = arena;
|
| -
|
| - rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
|
| - if (SECSuccess != rv) {
|
| - goto finish;
|
| - }
|
| -
|
| - pubk->pkcs11Slot = NULL;
|
| - pubk->pkcs11ID = CK_INVALID_HANDLE;
|
| -
|
| - switch (type) {
|
| - case CKK_RSA:
|
| - prepare_rsa_pub_key_for_asn1(pubk);
|
| - rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
|
| - pubk->keyType = rsaKey;
|
| - break;
|
| - case CKK_DSA:
|
| - prepare_dsa_pub_key_for_asn1(pubk);
|
| - rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
|
| - pubk->keyType = dsaKey;
|
| - break;
|
| - case CKK_DH:
|
| - prepare_dh_pub_key_for_asn1(pubk);
|
| - rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
|
| - pubk->keyType = dhKey;
|
| - break;
|
| - default:
|
| - rv = SECFailure;
|
| - break;
|
| - }
|
| -
|
| -finish:
|
| - if (rv != SECSuccess) {
|
| - if (arena != NULL) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - }
|
| - pubk = NULL;
|
| - }
|
| - return pubk;
|
| -}
|
| -
|
| -SECKEYPrivateKeyList *
|
| -SECKEY_NewPrivateKeyList(void)
|
| -{
|
| - PLArenaPool *arena = NULL;
|
| - SECKEYPrivateKeyList *ret = NULL;
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
|
| - sizeof(SECKEYPrivateKeyList));
|
| - if (ret == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - ret->arena = arena;
|
| -
|
| - PR_INIT_CLIST(&ret->list);
|
| -
|
| - return (ret);
|
| -
|
| -loser:
|
| - if (arena != NULL) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - }
|
| -
|
| - return (NULL);
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys)
|
| -{
|
| - while (!PR_CLIST_IS_EMPTY(&keys->list)) {
|
| - SECKEY_RemovePrivateKeyListNode(
|
| - (SECKEYPrivateKeyListNode *)(PR_LIST_HEAD(&keys->list)));
|
| - }
|
| -
|
| - PORT_FreeArena(keys->arena, PR_FALSE);
|
| -
|
| - return;
|
| -}
|
| -
|
| -void
|
| -SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node)
|
| -{
|
| - PR_ASSERT(node->key);
|
| - SECKEY_DestroyPrivateKey(node->key);
|
| - node->key = NULL;
|
| - PR_REMOVE_LINK(&node->links);
|
| - return;
|
| -}
|
| -
|
| -SECStatus
|
| -SECKEY_AddPrivateKeyToListTail(SECKEYPrivateKeyList *list,
|
| - SECKEYPrivateKey *key)
|
| -{
|
| - SECKEYPrivateKeyListNode *node;
|
| -
|
| - node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena,
|
| - sizeof(SECKEYPrivateKeyListNode));
|
| - if (node == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - PR_INSERT_BEFORE(&node->links, &list->list);
|
| - node->key = key;
|
| - return (SECSuccess);
|
| -
|
| -loser:
|
| - return (SECFailure);
|
| -}
|
| -
|
| -SECKEYPublicKeyList *
|
| -SECKEY_NewPublicKeyList(void)
|
| -{
|
| - PLArenaPool *arena = NULL;
|
| - SECKEYPublicKeyList *ret = NULL;
|
| -
|
| - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena,
|
| - sizeof(SECKEYPublicKeyList));
|
| - if (ret == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - ret->arena = arena;
|
| -
|
| - PR_INIT_CLIST(&ret->list);
|
| -
|
| - return (ret);
|
| -
|
| -loser:
|
| - if (arena != NULL) {
|
| - PORT_FreeArena(arena, PR_FALSE);
|
| - }
|
| -
|
| - return (NULL);
|
| -}
|
| -
|
| -void
|
| -SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys)
|
| -{
|
| - while (!PR_CLIST_IS_EMPTY(&keys->list)) {
|
| - SECKEY_RemovePublicKeyListNode(
|
| - (SECKEYPublicKeyListNode *)(PR_LIST_HEAD(&keys->list)));
|
| - }
|
| -
|
| - PORT_FreeArena(keys->arena, PR_FALSE);
|
| -
|
| - return;
|
| -}
|
| -
|
| -void
|
| -SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node)
|
| -{
|
| - PR_ASSERT(node->key);
|
| - SECKEY_DestroyPublicKey(node->key);
|
| - node->key = NULL;
|
| - PR_REMOVE_LINK(&node->links);
|
| - return;
|
| -}
|
| -
|
| -SECStatus
|
| -SECKEY_AddPublicKeyToListTail(SECKEYPublicKeyList *list,
|
| - SECKEYPublicKey *key)
|
| -{
|
| - SECKEYPublicKeyListNode *node;
|
| -
|
| - node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena,
|
| - sizeof(SECKEYPublicKeyListNode));
|
| - if (node == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - PR_INSERT_BEFORE(&node->links, &list->list);
|
| - node->key = key;
|
| - return (SECSuccess);
|
| -
|
| -loser:
|
| - return (SECFailure);
|
| -}
|
| -
|
| -#define SECKEY_CacheAttribute(key, attribute) \
|
| - if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \
|
| - key->staticflags |= SECKEY_##attribute; \
|
| - } else { \
|
| - key->staticflags &= (~SECKEY_##attribute); \
|
| - }
|
| -
|
| -SECStatus
|
| -SECKEY_CacheStaticFlags(SECKEYPrivateKey *key)
|
| -{
|
| - SECStatus rv = SECFailure;
|
| - if (key && key->pkcs11Slot && key->pkcs11ID) {
|
| - key->staticflags |= SECKEY_Attributes_Cached;
|
| - SECKEY_CacheAttribute(key, CKA_PRIVATE);
|
| - SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE);
|
| - rv = SECSuccess;
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -SECOidTag
|
| -SECKEY_GetECCOid(const SECKEYECParams *params)
|
| -{
|
| - SECItem oid = { siBuffer, NULL, 0 };
|
| - SECOidData *oidData = NULL;
|
| -
|
| - /*
|
| - * params->data needs to contain the ASN encoding of an object ID (OID)
|
| - * representing a named curve. Here, we strip away everything
|
| - * before the actual OID and use the OID to look up a named curve.
|
| - */
|
| - if (params->data[0] != SEC_ASN1_OBJECT_ID)
|
| - return 0;
|
| - oid.len = params->len - 2;
|
| - oid.data = params->data + 2;
|
| - if ((oidData = SECOID_FindOID(&oid)) == NULL)
|
| - return 0;
|
| -
|
| - return oidData->offset;
|
| -}
|
|
|