/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/nss/pkikeys.c
1 607 строк
57 KB
lsh123
Update file headers for doxygen, use common copyright header, bump copyright to 2026 (#1122)
07 апр 2026, 04:13
Не верифицирован
07 апр 2026, 04:13
2e557ee
Код
Авторство
О чём код?
/** * XML Security Library (http://www.aleksey.com/xmlsec). * * This is free software; see the Copyright file in the source distribution for precise wording. * * Copyright (C) 2003-2026 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. * Copyright (c) 2003 America Online, Inc. All rights reserved. */ /** * @addtogroup xmlsec_nss_pkikeys * @brief Private/public keys implementation for NSS. */ #include "globals.h" #include <string.h> #include <pk11pub.h> #include <keyhi.h> #include <pk11pqg.h> #include <xmlsec/xmlsec.h> #include <xmlsec/base64.h> #include <xmlsec/errors.h> #include <xmlsec/keys.h> #include <xmlsec/keyinfo.h> #include <xmlsec/private.h> #include <xmlsec/transforms.h> #include <xmlsec/xmltree.h> #include <xmlsec/nss/crypto.h> #include <xmlsec/nss/pkikeys.h> #include "../cast_helpers.h" #include "../keysdata_helpers.h" /****************************************************************************** * * Internal NSS PKI key CTX * *****************************************************************************/ typedef struct _xmlSecNssPKIKeyDataCtx xmlSecNssPKIKeyDataCtx, *xmlSecNssPKIKeyDataCtxPtr; struct _xmlSecNssPKIKeyDataCtx { SECKEYPublicKey *pubkey; SECKEYPrivateKey *privkey; }; /****************************************************************************** * * PKI key data (dsa/rsa/ec) * *****************************************************************************/ XMLSEC_KEY_DATA_DECLARE(NssPKIKeyData, xmlSecNssPKIKeyDataCtx) #define xmlSecNssPKIKeyDataSize XMLSEC_KEY_DATA_SIZE(NssPKIKeyData) static int xmlSecNssPKIKeyDataInitialize (xmlSecKeyDataPtr data); static void xmlSecNssPKIKeyDataFinalize (xmlSecKeyDataPtr data); static xmlSecKeyDataType xmlSecNssPKIKeyDataGetType (xmlSecKeyDataPtr data); static xmlSecSize xmlSecNssPKIKeyDataGetSize (xmlSecKeyDataPtr data); static void xmlSecNSSPKIKeyDataCtxFree (xmlSecNssPKIKeyDataCtxPtr ctx); static int xmlSecNSSPKIKeyDataCtxDup (xmlSecNssPKIKeyDataCtxPtr ctxDst, xmlSecNssPKIKeyDataCtxPtr ctxSrc); static int xmlSecNssPKIKeyDataAdoptKey (xmlSecKeyDataPtr data, SECKEYPrivateKey *privkey, SECKEYPublicKey *pubkey); static int xmlSecNssPKIKeyDataInitialize(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), -1); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); memset(ctx, 0, sizeof(xmlSecNssPKIKeyDataCtx)); return(0); } static void xmlSecNssPKIKeyDataFinalize(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; xmlSecAssert(xmlSecKeyDataIsValid(data)); xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize)); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert(ctx != NULL); xmlSecNSSPKIKeyDataCtxFree(ctx); memset(ctx, 0, sizeof(xmlSecNssPKIKeyDataCtx)); } static void xmlSecNSSPKIKeyDataCtxFree(xmlSecNssPKIKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); if (ctx->privkey != NULL) { SECKEY_DestroyPrivateKey(ctx->privkey); ctx->privkey = NULL; } if (ctx->pubkey) { SECKEY_DestroyPublicKey(ctx->pubkey); ctx->pubkey = NULL; } } static int xmlSecNSSPKIKeyDataCtxDup(xmlSecNssPKIKeyDataCtxPtr ctxDst, xmlSecNssPKIKeyDataCtxPtr ctxSrc) { xmlSecNSSPKIKeyDataCtxFree(ctxDst); if (ctxSrc->privkey != NULL) { ctxDst->privkey = SECKEY_CopyPrivateKey(ctxSrc->privkey); if(ctxDst->privkey == NULL) { xmlSecNssError("SECKEY_CopyPrivateKey", NULL); return(-1); } } if (ctxSrc->pubkey != NULL) { ctxDst->pubkey = SECKEY_CopyPublicKey(ctxSrc->pubkey); if(ctxDst->pubkey == NULL) { xmlSecNssError("SECKEY_CopyPublicKey", NULL); return(-1); } } return (0); } static int xmlSecNssPKIKeyDataAdoptKey(xmlSecKeyDataPtr data, SECKEYPrivateKey *privkey, SECKEYPublicKey *pubkey) { xmlSecNssPKIKeyDataCtxPtr ctx; SECKEYPublicKey *pubkey2 = NULL; KeyType pubType = nullKey; KeyType priType = nullKey; xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), -1); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); /* get public key if needed from private */ if ((pubkey == NULL) && (privkey != NULL)) { pubkey2 = SECKEY_ConvertToPublicKey(privkey); if(pubkey2 == NULL) { xmlSecNssError("SECKEY_ConvertToPublicKey", NULL); return(-1); } } /* ensure key types match */ if (privkey != NULL) { priType = SECKEY_GetPrivateKeyType(privkey); } if (pubkey != NULL) { pubType = SECKEY_GetPublicKeyType(pubkey); } else if (pubkey2 != NULL) { pubType = SECKEY_GetPublicKeyType(pubkey2); } if ((priType != nullKey) && (pubType != priType)) { xmlSecNssError3("SECKEY_GetPrivateKeyType/SECKEY_GetPublicKeyType", NULL, "pubType=%u; priType=%u", pubType, priType); if (pubkey2 != NULL) { SECKEY_DestroyPublicKey(pubkey2); } return(-1); } /* destroy old keys (if needed) and set new ones */ if (ctx->privkey != NULL) { SECKEY_DestroyPrivateKey(ctx->privkey); } ctx->privkey = privkey; if (ctx->pubkey != NULL) { SECKEY_DestroyPublicKey(ctx->pubkey); } ctx->pubkey = (pubkey != NULL) ? pubkey : pubkey2; /* done */ return(0); } /** * @brief Build a KeyData object from the given Private Key and Public * @param privkey the NSS Private Key handle * @param pubkey the NSS Public Key handle * * Key handles. * * @return pointer to KeyData object or NULL if an error occurs. */ xmlSecKeyDataPtr xmlSecNssPKIAdoptKey(SECKEYPrivateKey *privkey, SECKEYPublicKey *pubkey) { xmlSecKeyDataPtr data = NULL; int ret; KeyType pubType = nullKey; KeyType priType = nullKey; if(privkey != NULL) { priType = SECKEY_GetPrivateKeyType(privkey); } if(pubkey != NULL) { pubType = SECKEY_GetPublicKeyType(pubkey); } if(priType != nullKey && pubType != nullKey) { if(pubType != priType) { xmlSecNssError3("SECKEY_GetPrivateKeyType/SECKEY_GetPublicKeyType", NULL, "pubType=%u; priType=%u", pubType, priType); return(NULL); } } pubType = (priType != nullKey) ? priType : pubType; switch(pubType) { #ifndef XMLSEC_NO_RSA case rsaKey: data = xmlSecKeyDataCreate(xmlSecNssKeyDataRsaId); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate(KeyDataRsaId)", NULL); return(NULL); } break; #endif /* XMLSEC_NO_RSA */ #ifndef XMLSEC_NO_DSA case dsaKey: data = xmlSecKeyDataCreate(xmlSecNssKeyDataDsaId); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", NULL); return(NULL); } break; #endif /* XMLSEC_NO_DSA */ #ifndef XMLSEC_NO_EC case ecKey: data = xmlSecKeyDataCreate(xmlSecNssKeyDataEcId); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", NULL); return(NULL); } break; #endif /* XMLSEC_NO_EC */ #ifndef XMLSEC_NO_EDDSA case edKey: data = xmlSecKeyDataCreate(xmlSecNssKeyDataEdDSAId); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", NULL); return(NULL); } break; #endif /* XMLSEC_NO_EDDSA */ #ifndef XMLSEC_NO_XDH case ecMontKey: data = xmlSecKeyDataCreate(xmlSecNssKeyDataXdhId); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", NULL); return(NULL); } break; #endif /* XMLSEC_NO_XDH */ default: xmlSecUnsupportedEnumValueError("pubType", pubType, NULL); return(NULL); } xmlSecAssert2(data != NULL, NULL); ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey); if(ret < 0) { xmlSecInternalError("xmlSecNssPKIKeyDataAdoptKey", NULL); xmlSecKeyDataDestroy(data); return(NULL); } return(data); } /** * @brief Gets the Public Key from the key data. * @param data the pointer to NSS Key data. * * * @return pointer to SECKEYPublicKey or NULL if an error occurs. * Caller is responsible for freeing the key when done */ SECKEYPublicKey * xmlSecNssPKIKeyDataGetPubKey(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; SECKEYPublicKey *ret; xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), NULL); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->pubkey != NULL, NULL); ret = SECKEY_CopyPublicKey(ctx->pubkey); return(ret); } /** * @brief Gets the Private Key from the key data. * @param data the pointer to NSS Key data. * * * @return pointer to SECKEYPrivateKey or NULL if an error occurs. * Caller is responsible for freeing the key when done */ SECKEYPrivateKey* xmlSecNssPKIKeyDataGetPrivKey(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; SECKEYPrivateKey* ret; xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), NULL); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->privkey != NULL, NULL); ret = SECKEY_CopyPrivateKey(ctx->privkey); return(ret); } /** * @brief Gets the Key Type from the key data. * @param data the pointer to NSS Key data. * @return Key Type */ KeyType xmlSecNssPKIKeyDataGetKeyType(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; KeyType kt = nullKey; xmlSecAssert2(xmlSecKeyDataIsValid(data), nullKey); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), nullKey); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, nullKey); if (ctx->pubkey != NULL) { kt = SECKEY_GetPublicKeyType(ctx->pubkey); } else if(ctx->privkey != NULL) { kt = SECKEY_GetPrivateKeyType(ctx->privkey); } return(kt); } /** * xmlSecNssPKIKeyDataDuplicate * @param dst the pointer to NSS Key data to copy to. * @param src the pointer to NSS Key data to copy from. * * @brief Duplicates the keydata from src to dst * * @return -1 on error, 0 on success */ int xmlSecNssPKIKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { xmlSecNssPKIKeyDataCtxPtr ctxDst; xmlSecNssPKIKeyDataCtxPtr ctxSrc; xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecNssPKIKeyDataSize), -1); xmlSecAssert2(xmlSecKeyDataIsValid(src), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecNssPKIKeyDataSize), -1); ctxDst = xmlSecNssPKIKeyDataGetCtx(dst); xmlSecAssert2(ctxDst != NULL, -1); ctxSrc = xmlSecNssPKIKeyDataGetCtx(src); xmlSecAssert2(ctxSrc != NULL, -1); if (xmlSecNSSPKIKeyDataCtxDup(ctxDst, ctxSrc) != 0) { xmlSecInternalError("xmlSecNssPKIKeydataCtxDup", xmlSecKeyDataGetName(dst)); return(-1); } return(0); } static xmlSecKeyDataType xmlSecNssPKIKeyDataGetType(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), xmlSecKeyDataTypeUnknown); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown); if(ctx->pubkey == NULL) { return(xmlSecKeyDataTypeUnknown); } return ((ctx->privkey != NULL) ? (xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic) : xmlSecKeyDataTypePublic); } static xmlSecSize xmlSecNssPKIKeyDataGetSize(xmlSecKeyDataPtr data) { xmlSecNssPKIKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecNssPKIKeyDataSize), 0); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); xmlSecAssert2(ctx->pubkey != NULL, 0); switch(SECKEY_GetPublicKeyType(ctx->pubkey)) { case dsaKey: case rsaKey: return(8 * SECKEY_PublicKeyStrength(ctx->pubkey)); case ecKey: return(SECKEY_SignatureLen(ctx->pubkey)); #ifndef XMLSEC_NO_EDDSA case edKey: return(SECKEY_SignatureLen(ctx->pubkey)); #endif /* XMLSEC_NO_EDDSA */ #ifndef XMLSEC_NO_XDH case ecMontKey: return(8 * ctx->pubkey->u.ec.publicValue.len); #endif /* XMLSEC_NO_XDH */ default: break; } return(0); } /****************************************************************************** * * Helpers * *****************************************************************************/ static int xmlSecNssGetBigNumValue(xmlSecBufferPtr buf, PRArenaPool *arena, SECItem *val) { xmlSecByte* data; xmlSecSize size; xmlSecAssert2(buf != NULL, -1); xmlSecAssert2(arena != NULL, -1); xmlSecAssert2(val != NULL, -1); xmlSecAssert2(val->data == NULL, -1); xmlSecAssert2(val->len == 0, -1); data = xmlSecBufferGetData(buf); size = xmlSecBufferGetSize(buf); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(size > 0, -1); XMLSEC_SAFE_CAST_SIZE_TO_UINT(size, val->len, return(-1), NULL); val->data = PORT_ArenaZAlloc(arena, val->len); if(val->data == NULL) { xmlSecMallocError(size, NULL); val->len = 0; return(-1); } PORT_Memcpy(val->data, data, val->len); return(0); } static int xmlSecNssSetBigNumValue(const SECItem *val, xmlSecBufferPtr buf) { int ret; xmlSecAssert2(val != NULL, -1); xmlSecAssert2(val->data != NULL, -1); xmlSecAssert2(val->len > 0, -1); xmlSecAssert2(buf != NULL, -1); ret = xmlSecBufferSetData(buf, val->data, val->len); if(ret < 0) { xmlSecInternalError2("xmlSecBufferSetData", NULL, "size=%u", val->len); return(-1); } return(0); } /****************************************************************************** * * Helper macro to declare PKI key data klass (dsa/rsa/ec) * *****************************************************************************/ #define XMLSEC_NSS_PKI_KEY_KLASS_EX(lcname, ucname, ns, generate, xmlRead, xmlWrite) \ static xmlSecKeyDataKlass xmlSecNssKeyData ## lcname ## Klass = { \ sizeof(xmlSecKeyDataKlass), /* xmlSecSize klassSize */ \ xmlSecNssPKIKeyDataSize, /* xmlSecSize objSize */ \ /* data */ \ xmlSecName ## ucname ## KeyValue, /* const xmlChar* name; */ \ xmlSecKeyDataUsageReadFromFile | xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, \ /* xmlSecKeyDataUsage usage; */ \ xmlSecHref ## ucname ## KeyValue, /* const xmlChar* href; */ \ xmlSecNode ## ucname ## KeyValue, /* const xmlChar* dataNodeName; */ \ ns, /* const xmlChar* dataNodeNs; */ \ /* constructors/destructor */ \ xmlSecNssPKIKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ \ xmlSecNssPKIKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ \ xmlSecNssPKIKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ \ generate, /* xmlSecKeyDataGenerateMethod generate; */ \ /* get info */ \ xmlSecNssPKIKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ \ xmlSecNssPKIKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ \ NULL, /* DEPRECATED xmlSecKeyDataGetIdentifier getIdentifier; */ \ /* read/write */ \ xmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ \ xmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ \ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ \ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ \ /* debug */ \ xmlSecKeyDataDebugDumpImpl, /* xmlSecKeyDataDebugDumpMethod debugDump; */ \ xmlSecKeyDataDebugXmlDumpImpl, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ \ /* reserved for the future */ \ NULL, /* void* reserved0; */ \ NULL, /* void* reserved1; */ \ }; #ifndef XMLSEC_NO_DSA /****************************************************************************** * * <dsig:DSAKeyValue/> processing * * * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue) * * DSA keys and the DSA signature algorithm are specified in [DSS]. * DSA public key values can have the following fields: * * * P - a prime modulus meeting the [DSS] requirements * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime * divisor of P-1 * * G - an integer with certain properties with respect to P and Q * * Y - G**X mod P (where X is part of the private key and not made * public) * * J - (P - 1) / Q * * seed - a DSA prime generation seed * * pgenCounter - a DSA prime generation counter * * Parameter J is available for inclusion solely for efficiency as it is * calculatable from P and Q. Parameters seed and pgenCounter are used in the * DSA prime number generation algorithm specified in [DSS]. As such, they are * optional but must either both be present or both be absent. This prime * generation algorithm is designed to provide assurance that a weak prime is * not being used and it yields a P and Q value. Parameters P, Q, and G can be * public and common to a group of users. They might be known from application * context. As such, they are optional but P and Q must either both appear or * both be absent. If all of P, Q, seed, and pgenCounter are present, * implementations are not required to check if they are consistent and are * free to use either P and Q or seed and pgenCounter. All parameters are * encoded as base64 [MIME] values. * * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are * represented in XML as octet strings as defined by the ds:CryptoBinary type. * * Schema Definition: * * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/> * <complexType name="DSAKeyValueType"> * <sequence> * <sequence minOccurs="0"> * <element name="P" type="ds:CryptoBinary"/> * <element name="Q" type="ds:CryptoBinary"/> * </sequence> * <element name="G" type="ds:CryptoBinary" minOccurs="0"/> * <element name="Y" type="ds:CryptoBinary"/> * <element name="J" type="ds:CryptoBinary" minOccurs="0"/> * <sequence minOccurs="0"> * <element name="Seed" type="ds:CryptoBinary"/> * <element name="PgenCounter" type="ds:CryptoBinary"/> * </sequence> * </sequence> * </complexType> * * DTD Definition: * * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) > * <!ELEMENT P (#PCDATA) > * <!ELEMENT Q (#PCDATA) > * <!ELEMENT G (#PCDATA) > * <!ELEMENT Y (#PCDATA) > * <!ELEMENT J (#PCDATA) > * <!ELEMENT Seed (#PCDATA) > * <!ELEMENT PgenCounter (#PCDATA) > * * ============================================================================ * * To support reading/writing private keys an X element added (before Y). * * The current implementation does not support Seed and PgenCounter! * by this the P, Q and G are *required*! * *****************************************************************************/ static int xmlSecNssKeyDataDsaXmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssKeyDataDsaXmlWrite (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssKeyDataDsaGenerate (xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type); static xmlSecKeyDataPtr xmlSecNssKeyDataDsaRead (xmlSecKeyDataId id, xmlSecKeyValueDsaPtr dsaValue); static int xmlSecNssKeyDataDsaWrite (xmlSecKeyDataId id, xmlSecKeyDataPtr data, xmlSecKeyValueDsaPtr dsaValue, int writePrivateKey); XMLSEC_NSS_PKI_KEY_KLASS_EX(Dsa, DSA, xmlSecDSigNs, xmlSecNssKeyDataDsaGenerate, xmlSecNssKeyDataDsaXmlRead, xmlSecNssKeyDataDsaXmlWrite) /** * @brief The DSA key data klass. * @return pointer to DSA key data klass. */ xmlSecKeyDataId xmlSecNssKeyDataDsaGetKlass(void) { return(&xmlSecNssKeyDataDsaKlass); } static int xmlSecNssKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -1); return(xmlSecKeyDataDsaXmlRead(id, key, node, keyInfoCtx, xmlSecNssKeyDataDsaRead)); } static int xmlSecNssKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -1); return(xmlSecKeyDataDsaXmlWrite(id, key, node, keyInfoCtx, xmlSecBase64GetDefaultLineSize(), 1, /* add line breaks */ xmlSecNssKeyDataDsaWrite)); } static int xmlSecNssKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type XMLSEC_ATTRIBUTE_UNUSED) { PQGParams *pqgParams = NULL; PQGVerify *pqgVerify = NULL; SECStatus rv; SECStatus res; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; int ret = -1; int index; unsigned int uIndex; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), -1); xmlSecAssert2(sizeBits > 0, -1); index = PQG_PBITS_TO_INDEX(sizeBits); if(index < 0) { xmlSecNssError2("PQG_PBITS_TO_INDEX", xmlSecKeyDataGetName(data), "size=" XMLSEC_SIZE_FMT, sizeBits); goto done; } XMLSEC_SAFE_CAST_INT_TO_UINT(index, uIndex, goto done, xmlSecKeyDataGetName(data)); rv = PK11_PQG_ParamGen(uIndex, &pqgParams, &pqgVerify); if (rv != SECSuccess) { xmlSecNssError2("PK11_PQG_ParamGen", xmlSecKeyDataGetName(data), "size=" XMLSEC_SIZE_FMT, sizeBits); goto done; } rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &res); if (rv != SECSuccess || res != SECSuccess) { xmlSecNssError2("PK11_PQG_VerifyParams", xmlSecKeyDataGetName(data), "size=" XMLSEC_SIZE_FMT, sizeBits); goto done; } slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL); if(slot == NULL) { xmlSecNssError("PK11_GetBestSlot", xmlSecKeyDataGetName(data)); goto done; } rv = PK11_Authenticate(slot, PR_TRUE, NULL /* default pwd callback */); if (rv != SECSuccess) { xmlSecNssError2("PK11_Authenticate", xmlSecKeyDataGetName(data), "token=%s", xmlSecErrorsSafeString(PK11_GetTokenName(slot))); goto done; } privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, pqgParams, &pubkey, PR_FALSE, PR_TRUE, NULL); if((privkey == NULL) || (pubkey == NULL)) { xmlSecNssError("PK11_GenerateKeyPair", xmlSecKeyDataGetName(data)); goto done; } ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey); if(ret < 0) { xmlSecInternalError("xmlSecNssPKIKeyDataAdoptKey", xmlSecKeyDataGetName(data)); goto done; } ret = 0; done: if (slot != NULL) { PK11_FreeSlot(slot); } if (pqgParams != NULL) { PK11_PQG_DestroyParams(pqgParams); } if (pqgVerify != NULL) { PK11_PQG_DestroyVerify(pqgVerify); } if (ret == 0) { return (0); } if (pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if (privkey != NULL) { SECKEY_DestroyPrivateKey(privkey); } return(-1); } static xmlSecKeyDataPtr xmlSecNssKeyDataDsaRead(xmlSecKeyDataId id, xmlSecKeyValueDsaPtr dsaValue) { xmlSecKeyDataPtr data = NULL; xmlSecKeyDataPtr res = NULL; PK11SlotInfo *slot = NULL; CK_OBJECT_HANDLE handle; SECKEYPublicKey *pubkey=NULL; PRArenaPool *arena = NULL; int ret; xmlSecAssert2(id == xmlSecNssKeyDataDsaId, NULL); xmlSecAssert2(dsaValue != NULL, NULL); slot = PK11_GetBestSlot(CKM_DSA, NULL); if(slot == NULL) { xmlSecNssError("PK11_GetBestSlot", xmlSecKeyDataKlassGetName(id)); goto done; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if(arena == NULL) { xmlSecNssError("PORT_NewArena", xmlSecKeyDataKlassGetName(id)); goto done; } pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); if(pubkey == NULL) { xmlSecNssError2("PORT_ArenaZAlloc", xmlSecKeyDataKlassGetName(id), "size=" XMLSEC_SIZE_T_FMT, sizeof(SECKEYPublicKey)); goto done; } pubkey->arena = arena; pubkey->u.dsa.params.arena = arena; pubkey->keyType = dsaKey; arena = NULL; /* owned by pubkey */ /* p */ ret = xmlSecNssGetBigNumValue(&(dsaValue->p), pubkey->arena, &(pubkey->u.dsa.params.prime)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(p)", xmlSecKeyDataKlassGetName(id)); goto done; } /* q */ ret = xmlSecNssGetBigNumValue(&(dsaValue->q), pubkey->arena, &(pubkey->u.dsa.params.subPrime)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(q)", xmlSecKeyDataKlassGetName(id)); goto done; } /* g */ ret = xmlSecNssGetBigNumValue(&(dsaValue->g), pubkey->arena, &(pubkey->u.dsa.params.base)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(g)", xmlSecKeyDataKlassGetName(id)); goto done; } /* next is X (priv key). NSS does not support it, we just ignore it */ /* y */ ret = xmlSecNssGetBigNumValue(&(dsaValue->y), pubkey->arena, &(pubkey->u.dsa.publicValue)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(y)", xmlSecKeyDataKlassGetName(id)); goto done; } /* create key */ handle = PK11_ImportPublicKey(slot, pubkey, PR_FALSE); if(handle == CK_INVALID_HANDLE) { xmlSecNssError("PK11_ImportPublicKey", xmlSecKeyDataKlassGetName(id)); goto done; } data = xmlSecKeyDataCreate(id); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", xmlSecKeyDataKlassGetName(id)); goto done; } ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey); if(ret < 0) { xmlSecInternalError("xmlSecNssPKIKeyDataAdoptKey", xmlSecKeyDataGetName(data)); goto done; } pubkey = NULL; /* owned by data now */ /* success */ res = data; data = NULL; done: if (slot != NULL) { PK11_FreeSlot(slot); } if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } if (pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if (data != NULL) { xmlSecKeyDataDestroy(data); } return(res); } static int xmlSecNssKeyDataDsaWrite(xmlSecKeyDataId id, xmlSecKeyDataPtr data, xmlSecKeyValueDsaPtr dsaValue, int writePrivateKey XMLSEC_ATTRIBUTE_UNUSED) { xmlSecNssPKIKeyDataCtxPtr ctx; int ret; xmlSecAssert2(id == xmlSecNssKeyDataDsaId, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataDsaId), -1); xmlSecAssert2(dsaValue != NULL, -1); UNREFERENCED_PARAMETER(writePrivateKey); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->pubkey != NULL, -1); xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == dsaKey, -1); /* p */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.dsa.params.prime), &(dsaValue->p)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(p)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* q */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.dsa.params.subPrime), &(dsaValue->q)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(q)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* g */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.dsa.params.base), &(dsaValue->g)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(g)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* x: not supported in NSS */ /* y */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.dsa.publicValue), &(dsaValue->y)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(y)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* done */ return(0); } #endif /* XMLSEC_NO_DSA */ #ifndef XMLSEC_NO_RSA /****************************************************************************** * * <dsig:RSAKeyValue/> processing * * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue * The RSAKeyValue Element * * RSA key values have two fields: Modulus and Exponent. * * <RSAKeyValue> * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= * </Modulus> * <Exponent>AQAB</Exponent> * </RSAKeyValue> * * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are * represented in XML as octet strings as defined by the ds:CryptoBinary type. * * Schema Definition: * * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/> * <complexType name="RSAKeyValueType"> * <sequence> * <element name="Modulus" type="ds:CryptoBinary"/> * <element name="Exponent" type="ds:CryptoBinary"/> * </sequence> * </complexType> * * DTD Definition: * * <!ELEMENT RSAKeyValue (Modulus, Exponent) > * <!ELEMENT Modulus (#PCDATA) > * <!ELEMENT Exponent (#PCDATA) > * * ============================================================================ * * To support reading/writing private keys an PrivateExponent element is added * to the end * *****************************************************************************/ static int xmlSecNssKeyDataRsaXmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssKeyDataRsaXmlWrite (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssKeyDataRsaGenerate (xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type); static xmlSecKeyDataPtr xmlSecNssKeyDataRsaRead (xmlSecKeyDataId id, xmlSecKeyValueRsaPtr rsaValue); static int xmlSecNssKeyDataRsaWrite (xmlSecKeyDataId id, xmlSecKeyDataPtr data, xmlSecKeyValueRsaPtr rsaValue, int writePrivateKey); XMLSEC_NSS_PKI_KEY_KLASS_EX(Rsa, RSA, xmlSecDSigNs, xmlSecNssKeyDataRsaGenerate, xmlSecNssKeyDataRsaXmlRead, xmlSecNssKeyDataRsaXmlWrite) /** * @brief The RSA key data klass. * @return pointer to RSA key data klass. */ xmlSecKeyDataId xmlSecNssKeyDataRsaGetKlass(void) { return(&xmlSecNssKeyDataRsaKlass); } static int xmlSecNssKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -1); return(xmlSecKeyDataRsaXmlRead(id, key, node, keyInfoCtx, xmlSecNssKeyDataRsaRead)); } static int xmlSecNssKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -1); return(xmlSecKeyDataRsaXmlWrite(id, key, node, keyInfoCtx, xmlSecBase64GetDefaultLineSize(), 1, /* add line breaks */ xmlSecNssKeyDataRsaWrite)); } static xmlSecKeyDataPtr xmlSecNssKeyDataRsaRead(xmlSecKeyDataId id, xmlSecKeyValueRsaPtr rsaValue) { xmlSecKeyDataPtr data = NULL; xmlSecKeyDataPtr res = NULL; PK11SlotInfo *slot = NULL; SECKEYPublicKey *pubkey=NULL; PRArenaPool *arena = NULL; int ret; xmlSecAssert2(id == xmlSecNssKeyDataRsaId, NULL); xmlSecAssert2(rsaValue != NULL, NULL); slot = PK11_GetBestSlot(CKM_RSA_PKCS, NULL); if(slot == NULL) { xmlSecNssError("PK11_GetBestSlot", xmlSecKeyDataKlassGetName(id)); goto done; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if(arena == NULL) { xmlSecNssError("PORT_NewArena", xmlSecKeyDataKlassGetName(id)); goto done; } pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); if(pubkey == NULL) { xmlSecNssError("PORT_ArenaZAlloc", xmlSecKeyDataKlassGetName(id)); goto done; } pubkey->arena = arena; pubkey->keyType = rsaKey; arena = NULL; /* owned by pubkey */ /* Modulus */ ret = xmlSecNssGetBigNumValue(&(rsaValue->modulus), pubkey->arena, &(pubkey->u.rsa.modulus)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(Modulus)", xmlSecKeyDataKlassGetName(id)); goto done; } /* Exponent */ ret = xmlSecNssGetBigNumValue(&(rsaValue->publicExponent), pubkey->arena, &(pubkey->u.rsa.publicExponent)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(Exponent)", xmlSecKeyDataKlassGetName(id)); goto done; } /* next is PrivateExponent (priv key). NSS does not support it, we just ignore it */ /* create key */ data = xmlSecKeyDataCreate(id); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", xmlSecKeyDataKlassGetName(id)); ret = -1; goto done; } ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey); if(ret < 0) { xmlSecInternalError("xmlSecNssPKIKeyDataAdoptKey", xmlSecKeyDataKlassGetName(id)); xmlSecKeyDataDestroy(data); goto done; } pubkey = NULL; /* owned by data now */ /* success */ res = data; data = NULL; done: if (slot != 0) { PK11_FreeSlot(slot); } if(arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } if (pubkey != 0) { SECKEY_DestroyPublicKey(pubkey); } if (data != 0) { xmlSecKeyDataDestroy(data); } return(res); } static int xmlSecNssKeyDataRsaWrite(xmlSecKeyDataId id,xmlSecKeyDataPtr data, xmlSecKeyValueRsaPtr rsaValue, int writePrivateKey XMLSEC_ATTRIBUTE_UNUSED) { xmlSecNssPKIKeyDataCtxPtr ctx; int ret; xmlSecAssert2(id == xmlSecNssKeyDataRsaId, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), -1); xmlSecAssert2(rsaValue != NULL, -1); UNREFERENCED_PARAMETER(writePrivateKey); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->pubkey != NULL, -1); xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == rsaKey, -1); /* Modulus */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.rsa.modulus), &(rsaValue->modulus)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(Modulus)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* Exponent */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.rsa.publicExponent), &(rsaValue->publicExponent)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(Exponent)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* next is PrivateExponent node: not supported in NSS */ return(0); } static int xmlSecNssKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type XMLSEC_ATTRIBUTE_UNUSED) { PK11RSAGenParams params; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privkey = NULL; SECKEYPublicKey *pubkey = NULL; SECStatus rv; int ret = -1; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataRsaId), -1); xmlSecAssert2(sizeBits > 0, -1); XMLSEC_SAFE_CAST_SIZE_TO_INT(sizeBits, params.keySizeInBits, return(-1), xmlSecKeyDataGetName(data)); params.pe = 65537; slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, NULL); if(slot == NULL) { xmlSecNssError("PK11_GetBestSlot", xmlSecKeyDataGetName(data)); goto done; } rv = PK11_Authenticate(slot, PR_TRUE, NULL /* default pwd callback */); if (rv != SECSuccess) { xmlSecNssError2("PK11_Authenticate", xmlSecKeyDataGetName(data), "token=%s", xmlSecErrorsSafeString(PK11_GetTokenName(slot))); goto done; } privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶ms, &pubkey, PR_FALSE, PR_TRUE, NULL); if(privkey == NULL || pubkey == NULL) { xmlSecNssError("PK11_GenerateKeyPair", xmlSecKeyDataGetName(data)); goto done; } ret = xmlSecNssPKIKeyDataAdoptKey(data, privkey, pubkey); if(ret < 0) { xmlSecInternalError("xmlSecNssPKIKeyDataAdoptKey", xmlSecKeyDataGetName(data)); goto done; } ret = 0; done: if (slot != NULL) { PK11_FreeSlot(slot); } if (ret == 0) { return (0); } if (pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if (privkey != NULL) { SECKEY_DestroyPrivateKey(privkey); } return(-1); } #endif /* XMLSEC_NO_RSA */ #ifndef XMLSEC_NO_EC static int xmlSecNssKeyDataEcXmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecNssKeyDataEcXmlWrite (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static xmlSecKeyDataPtr xmlSecNssKeyDataEcRead (xmlSecKeyDataId id, xmlSecKeyValueEcPtr ecValue); static int xmlSecNssKeyDataEcWrite (xmlSecKeyDataId id, xmlSecKeyDataPtr data, xmlSecKeyValueEcPtr ecValue); XMLSEC_NSS_PKI_KEY_KLASS_EX(Ec, EC, xmlSecDSig11Ns, NULL, xmlSecNssKeyDataEcXmlRead, xmlSecNssKeyDataEcXmlWrite) /** * @brief The EC key data klass. * @return pointer to EC key data klass. */ xmlSecKeyDataId xmlSecNsskeyDataEcGetKlass(void) { return(&xmlSecNssKeyDataEcKlass); } static int xmlSecNssKeyDataEcXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAssert2(id == xmlSecNssKeyDataEcId, -1); return(xmlSecKeyDataEcXmlRead(id, key, node, keyInfoCtx, xmlSecNssKeyDataEcRead)); } static int xmlSecNssKeyDataEcXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecAssert2(id == xmlSecNssKeyDataEcId, -1); return(xmlSecKeyDataEcXmlWrite(id, key, node, keyInfoCtx, xmlSecBase64GetDefaultLineSize(), 1, /* add line breaks */ xmlSecNssKeyDataEcWrite)); } typedef struct _xmlSecNssKeyDataEcCurveNameAndOID { SECOidTag curveOidTag; xmlChar oid[128]; } xmlSecNssKeyDataEcCurveNameAndOID; static const xmlSecNssKeyDataEcCurveNameAndOID g_xmlSecNssKeyDataEcCurveNameAndOID[] = { { SEC_OID_ANSIX962_EC_PRIME192V1, "1.2.840.10045.3.1.1" }, /* "prime192v1" */ { SEC_OID_ANSIX962_EC_PRIME192V2, "1.2.840.10045.3.1.2" }, { SEC_OID_ANSIX962_EC_PRIME192V3, "1.2.840.10045.3.1.3" }, { SEC_OID_ANSIX962_EC_PRIME239V1, "1.2.840.10045.3.1.4" }, { SEC_OID_ANSIX962_EC_PRIME239V2, "1.2.840.10045.3.1.5" }, { SEC_OID_ANSIX962_EC_PRIME239V3, "1.2.840.10045.3.1.6" }, { SEC_OID_ANSIX962_EC_PRIME256V1, "1.2.840.10045.3.1.7" }, /* prime256v1 */ { SEC_OID_SECG_EC_SECP224R1, "1.3.132.0.33" }, /* secp224r1 */ { SEC_OID_SECG_EC_SECP384R1, "1.3.132.0.34" }, /* secp384r1 */ { SEC_OID_SECG_EC_SECP521R1, "1.3.132.0.35" } /* secp521r1 */ }; static const xmlChar* xmlSecNssKeyDataEcGetOidFromOidTag(SECOidTag curveOidTag) { xmlSecSize size = sizeof(g_xmlSecNssKeyDataEcCurveNameAndOID) / sizeof(g_xmlSecNssKeyDataEcCurveNameAndOID[0]); xmlSecAssert2(curveOidTag != SEC_OID_UNKNOWN, NULL); for(xmlSecSize ii = 0; ii < size; ++ii) { if(curveOidTag == g_xmlSecNssKeyDataEcCurveNameAndOID[ii].curveOidTag) { return(g_xmlSecNssKeyDataEcCurveNameAndOID[ii].oid); } } return(NULL); } static SECOidTag xmlSecNssKeyDataEcGetOidTagFromOid(const xmlChar * oid) { xmlSecSize size = sizeof(g_xmlSecNssKeyDataEcCurveNameAndOID) / sizeof(g_xmlSecNssKeyDataEcCurveNameAndOID[0]); xmlSecAssert2(oid != NULL, SEC_OID_UNKNOWN); for(xmlSecSize ii = 0; ii < size; ++ii) { if(xmlStrcmp(oid, g_xmlSecNssKeyDataEcCurveNameAndOID[ii].oid) == 0) { return(g_xmlSecNssKeyDataEcCurveNameAndOID[ii].curveOidTag); } } return(SEC_OID_UNKNOWN); } static xmlSecKeyDataPtr xmlSecNssKeyDataEcRead(xmlSecKeyDataId id, xmlSecKeyValueEcPtr ecValue) { xmlSecKeyDataPtr data = NULL; xmlSecKeyDataPtr res = NULL; PK11SlotInfo *slot = NULL; CK_OBJECT_HANDLE handle; SECKEYPublicKey *pubkey=NULL; PRArenaPool *arena = NULL; SECItem ecparams = { siBuffer, NULL, 0 }; SECOidData *oidData = NULL; SECOidTag oidTag; SECStatus rv; int ret; xmlSecAssert2(id == xmlSecNssKeyDataEcId, NULL); xmlSecAssert2(ecValue != NULL, NULL); xmlSecAssert2(ecValue->curve != NULL, NULL); /* prepare and create public key */ slot = PK11_GetBestSlot(CKM_ECDSA, NULL); if(slot == NULL) { xmlSecNssError("PK11_GetBestSlot", xmlSecKeyDataKlassGetName(id)); goto done; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if(arena == NULL) { xmlSecNssError("PORT_NewArena", xmlSecKeyDataKlassGetName(id)); goto done; } pubkey = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); if(pubkey == NULL) { xmlSecNssError2("PORT_ArenaZAlloc", xmlSecKeyDataKlassGetName(id), "size=" XMLSEC_SIZE_T_FMT, sizeof(SECKEYPublicKey)); goto done; } pubkey->arena = arena; pubkey->keyType = ecKey; arena = NULL; /* owned by pubkey */ /* get curve */ oidTag = xmlSecNssKeyDataEcGetOidTagFromOid(ecValue->curve); if(oidTag == SEC_OID_UNKNOWN) { xmlSecInternalError2("xmlSecNssKeyDataEcGetOidTagFromOid", xmlSecKeyDataKlassGetName(id), "curve_oid=%s", xmlSecErrorsSafeString(ecValue->curve)); goto done; } oidData = SECOID_FindOIDByTag(oidTag); if(oidData == NULL) { xmlSecNssError2("SECOID_FindOIDByTag", xmlSecKeyDataKlassGetName(id), "curve_oid=%s", xmlSecErrorsSafeString(ecValue->curve)); goto done; } if(SECITEM_AllocItem(pubkey->arena, &ecparams, (2 + oidData->oid.len)) == NULL) { xmlSecNssError2("SECITEM_AllocItem", xmlSecKeyDataKlassGetName(id), "curve_oid=%u", (2 + oidData->oid.len)); goto done; } ecparams.data[0] = SEC_ASN1_OBJECT_ID; XMLSEC_SAFE_CAST_UINT_TO_BYTE(oidData->oid.len, ecparams.data[1], goto done, xmlSecKeyDataKlassGetName(id)); memcpy(ecparams.data + 2, oidData->oid.data, oidData->oid.len); rv = SECITEM_CopyItem(pubkey->arena, &(pubkey->u.ec.DEREncodedParams), &(ecparams)); if(rv != SECSuccess) { xmlSecNssError("SECITEM_CopyItem", xmlSecKeyDataKlassGetName(id)); goto done; } /* publicValue */ ret = xmlSecNssGetBigNumValue(&(ecValue->pubkey), pubkey->arena, &(pubkey->u.ec.publicValue)); if(ret < 0) { xmlSecInternalError("xmlSecNssGetBigNumValue(publicValue)", xmlSecKeyDataKlassGetName(id)); goto done; } /* create key */ handle = PK11_ImportPublicKey(slot, pubkey, PR_FALSE); if(handle == CK_INVALID_HANDLE) { xmlSecNssError("PK11_ImportPublicKey", xmlSecKeyDataKlassGetName(id)); goto done; } data = xmlSecKeyDataCreate(id); if(data == NULL) { xmlSecInternalError("xmlSecKeyDataCreate", xmlSecKeyDataKlassGetName(id)); goto done; } ret = xmlSecNssPKIKeyDataAdoptKey(data, NULL, pubkey); if(ret < 0) { xmlSecInternalError("xmlSecNssPKIKeyDataAdoptKey", xmlSecKeyDataGetName(data)); goto done; } pubkey = NULL; /* owned by data now */ /* success */ res = data; data = NULL; done: if (pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } if (slot != NULL) { PK11_FreeSlot(slot); } if (data != NULL) { xmlSecKeyDataDestroy(data); } return(res); } static SECOidTag xmlSecNssKeyDataEcGetOidTag(const SECKEYECParams *params) { SECItem oid = { siBuffer, NULL, 0 }; SECOidData *oidData = NULL; xmlSecAssert2(params != NULL, SEC_OID_UNKNOWN); /* * 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->len <= 2) || (params->data[0] != SEC_ASN1_OBJECT_ID)) { return(SEC_OID_UNKNOWN); } oid.len = params->len - 2; oid.data = params->data + 2; oidData = SECOID_FindOID(&oid); if(oidData == NULL) { return(SEC_OID_UNKNOWN); } return oidData->offset; } static int xmlSecNssKeyDataEcWrite(xmlSecKeyDataId id, xmlSecKeyDataPtr data, xmlSecKeyValueEcPtr ecValue) { xmlSecNssPKIKeyDataCtxPtr ctx; SECOidTag oidTag; const xmlChar * curve; int ret; xmlSecAssert2(id == xmlSecNssKeyDataEcId, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcId), -1); xmlSecAssert2(ecValue != NULL, -1); xmlSecAssert2(ecValue->curve == NULL, -1); ctx = xmlSecNssPKIKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->pubkey != NULL, -1); xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == ecKey, -1); /* curve */ oidTag = xmlSecNssKeyDataEcGetOidTag(&(ctx->pubkey->u.ec.DEREncodedParams)); if(oidTag == SEC_OID_UNKNOWN) { xmlSecInternalError("xmlSecNssKeyDataEcGetOidTag", xmlSecKeyDataKlassGetName(id)); return(-1); } curve = xmlSecNssKeyDataEcGetOidFromOidTag(oidTag); if(curve == NULL) { xmlSecNssError2("xmlSecNssKeyDataEcGetOidFromOidTag", xmlSecKeyDataKlassGetName(id), "oidTag=%d", (int)oidTag); return(-1); } ecValue->curve = xmlStrdup(curve); if(ecValue->curve == NULL) { xmlSecStrdupError(curve, xmlSecKeyDataKlassGetName(id)); return(-1); } /* publicValue */ ret = xmlSecNssSetBigNumValue(&(ctx->pubkey->u.ec.publicValue), &(ecValue->pubkey)); if(ret < 0) { xmlSecInternalError("xmlSecNssNodeSetBigNumValue(p)", xmlSecKeyDataKlassGetName(id)); return(-1); } /* done */ return(0); } #endif /* XMLSEC_NO_EC */ #ifndef XMLSEC_NO_EDDSA /****************************************************************************** * * EdDSA key data (Ed25519 and Ed448) * *****************************************************************************/ /* EdDSA klass: no XML KeyValue representation, load from file/DER/PEM only */ #define XMLSEC_NSS_PKI_KEY_KLASS_EDDSA(lcname, ucname, generate) \ static xmlSecKeyDataKlass xmlSecNssKeyData ## lcname ## Klass = { \ sizeof(xmlSecKeyDataKlass), /* xmlSecSize klassSize */ \ xmlSecNssPKIKeyDataSize, /* xmlSecSize objSize */ \ /* data */ \ xmlSecName ## ucname ## KeyValue, /* const xmlChar* name; */ \ xmlSecKeyDataUsageReadFromFile | xmlSecKeyDataUsageRetrievalMethodNodeXml, \ /* xmlSecKeyDataUsage usage; */ \ xmlSecHref ## ucname ## KeyValue, /* const xmlChar* href; */ \ NULL, /* const xmlChar* dataNodeName; */ \ NULL, /* const xmlChar* dataNodeNs; */ \ /* constructors/destructor */ \ xmlSecNssPKIKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ \ xmlSecNssPKIKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ \ xmlSecNssPKIKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ \ generate, /* xmlSecKeyDataGenerateMethod generate; */ \ /* get info */ \ xmlSecNssPKIKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ \ xmlSecNssPKIKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ \ NULL, /* DEPRECATED xmlSecKeyDataGetIdentifier getIdentifier; */ \ /* read/write */ \ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */ \ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ \ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ \ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ \ /* debug */ \ xmlSecKeyDataDebugDumpImpl, /* xmlSecKeyDataDebugDumpMethod debugDump; */ \ xmlSecKeyDataDebugXmlDumpImpl, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ \ /* reserved for the future */ \ NULL, /* void* reserved0; */ \ NULL, /* void* reserved1; */ \ }; XMLSEC_NSS_PKI_KEY_KLASS_EDDSA(EdDSA, EdDSA, NULL) /** * @brief The EdDSA key data klass (Ed25519 and Ed448). * @return pointer to EdDSA key data klass. */ xmlSecKeyDataId xmlSecNssKeyDataEdDSAGetKlass(void) { return(&xmlSecNssKeyDataEdDSAKlass); } #endif /* XMLSEC_NO_EDDSA */ #ifndef XMLSEC_NO_XDH /****************************************************************************** * * XDH key data (X25519 and X448, RFC 7748) * *****************************************************************************/ /* XDH klass: no XML KeyValue representation, load from file/DER/PEM only */ #define XMLSEC_NSS_PKI_KEY_KLASS_XDH(lcname, ucname, generate) \ static xmlSecKeyDataKlass xmlSecNssKeyData ## lcname ## Klass = { \ sizeof(xmlSecKeyDataKlass), /* xmlSecSize klassSize */ \ xmlSecNssPKIKeyDataSize, /* xmlSecSize objSize */ \ /* data */ \ xmlSecName ## ucname ## KeyValue, /* const xmlChar* name; */ \ xmlSecKeyDataUsageReadFromFile | xmlSecKeyDataUsageRetrievalMethodNodeXml, \ /* xmlSecKeyDataUsage usage; */ \ xmlSecHref ## ucname ## KeyValue, /* const xmlChar* href; */ \ NULL, /* const xmlChar* dataNodeName; */ \ NULL, /* const xmlChar* dataNodeNs; */ \ /* constructors/destructor */ \ xmlSecNssPKIKeyDataInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ \ xmlSecNssPKIKeyDataDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ \ xmlSecNssPKIKeyDataFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ \ generate, /* xmlSecKeyDataGenerateMethod generate; */ \ /* get info */ \ xmlSecNssPKIKeyDataGetType, /* xmlSecKeyDataGetTypeMethod getType; */ \ xmlSecNssPKIKeyDataGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ \ NULL, /* DEPRECATED xmlSecKeyDataGetIdentifier getIdentifier; */ \ /* read/write */ \ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */ \ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ \ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ \ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ \ /* debug */ \ xmlSecKeyDataDebugDumpImpl, /* xmlSecKeyDataDebugDumpMethod debugDump; */ \ xmlSecKeyDataDebugXmlDumpImpl, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ \ /* reserved for the future */ \ NULL, /* void* reserved0; */ \ NULL, /* void* reserved1; */ \ }; XMLSEC_NSS_PKI_KEY_KLASS_XDH(Xdh, XDH, NULL) /** * @brief The XDH key data klass (X25519 and X448). * @return pointer to XDH key data klass. */ xmlSecKeyDataId xmlSecNssKeyDataXdhGetKlass(void) { return(&xmlSecNssKeyDataXdhKlass); } #endif /* XMLSEC_NO_XDH */