Skip to content

Commit

Permalink
nss: add ECDSA-SHA256 support (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
vmiklos authored and lsh123 committed Feb 25, 2017
1 parent 25951df commit bf68612
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 12 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -598,7 +598,7 @@ dnl ==========================================================================
XMLSEC_NO_NSS="1"
SEAMONKEY_MIN_VERSION="1.0"
MOZILLA_MIN_VERSION="1.4"
NSS_MIN_VERSION="3.9"
NSS_MIN_VERSION="3.11.1"
NSPR_MIN_VERSION="4.4.1"
NSS_CFLAGS=""
NSS_LIBS=""
Expand Down
30 changes: 30 additions & 0 deletions include/xmlsec/nss/crypto.h
Expand Up @@ -187,6 +187,36 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecNssTransformDsaSha1GetKlass(void);
#endif /* XMLSEC_NO_DSA */


/********************************************************************
*
* ECDSA transform
*
*******************************************************************/
#ifndef XMLSEC_NO_ECDSA

/**
* xmlSecNssKeyDataEcdsaId:
*
* The ECDSA key klass.
*/
#define xmlSecNssKeyDataEcdsaId xmlSecNssKeyDataEcdsaGetKlass()
XMLSEC_CRYPTO_EXPORT xmlSecKeyDataId xmlSecNssKeyDataEcdsaGetKlass(void);

#ifndef XMLSEC_NO_SHA256

/**
* xmlSecNssTransformEcdsaSha256Id:
*
* The ECDSA SHA256 signature transform klass.
*/
#define xmlSecNssTransformEcdsaSha256Id xmlSecNssTransformEcdsaSha256GetKlass()
XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecNssTransformEcdsaSha256GetKlass(void);

#endif /* XMLSEC_NO_SHA256 */

#endif /* XMLSEC_NO_ECDSA */


/********************************************************************
*
* HMAC transforms
Expand Down
1 change: 1 addition & 0 deletions include/xmlsec/nss/symbols.h
Expand Up @@ -65,6 +65,7 @@ extern "C" {
#define xmlSecTransformDes3CbcId xmlSecNssTransformDes3CbcId
#define xmlSecTransformKWDes3Id xmlSecNssTransformKWDes3Id
#define xmlSecTransformDsaSha1Id xmlSecNssTransformDsaSha1Id
#define xmlSecTransformEcdsaSha256Id xmlSecNssTransformEcdsaSha256Id
#define xmlSecTransformHmacMd5Id xmlSecNssTransformHmacMd5Id
#define xmlSecTransformHmacRipemd160Id xmlSecNssTransformHmacRipemd160Id
#define xmlSecTransformHmacSha1Id xmlSecNssTransformHmacSha1Id
Expand Down
2 changes: 1 addition & 1 deletion src/nss/README
@@ -1,6 +1,6 @@
WHAT VERSION OF NSS?
------------------------------------------------------------------------
NSS 3.9 or greater and NSPR 4.4.1 or greater are required.
NSS 3.11.1 or greater and NSPR 4.4.1 or greater are required.

KEYS MANAGER
------------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions src/nss/crypto.c
Expand Up @@ -124,6 +124,13 @@ xmlSecCryptoGetFunctions_nss(void) {
gXmlSecNssFunctions->transformDsaSha1GetKlass = xmlSecNssTransformDsaSha1GetKlass;
#endif /* XMLSEC_NO_DSA */

/******************************* ECDSA ******************************/
#ifndef XMLSEC_NO_ECDSA
#ifndef XMLSEC_NO_SHA256
gXmlSecNssFunctions->transformEcdsaSha256GetKlass = xmlSecNssTransformEcdsaSha256GetKlass;
#endif /* XMLSEC_NO_SHA256 */
#endif /* XMLSEC_NO_ECDSA */

/******************************* HMAC ********************************/
#ifndef XMLSEC_NO_HMAC

Expand Down
137 changes: 137 additions & 0 deletions src/nss/pkikeys.c
Expand Up @@ -238,6 +238,15 @@ xmlSecNssPKIAdoptKey(SECKEYPrivateKey *privkey,
}
break;
#endif /* XMLSEC_NO_DSA */
#ifndef XMLSEC_NO_ECDSA
case ecKey:
data = xmlSecKeyDataCreate(xmlSecNssKeyDataEcdsaId);
if(data == NULL) {
xmlSecInternalError("xmlSecKeyDataCreate", NULL);
return(NULL);
}
break;
#endif /* XMLSEC_NO_ECDSA */
default:
xmlSecError(XMLSEC_ERRORS_HERE,
NULL,
Expand Down Expand Up @@ -1379,5 +1388,133 @@ xmlSecNssKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {

#endif /* XMLSEC_NO_RSA */

#ifndef XMLSEC_NO_ECDSA
static int xmlSecNssKeyDataEcdsaInitialize(xmlSecKeyDataPtr data);
static int xmlSecNssKeyDataEcdsaDuplicate(xmlSecKeyDataPtr dst,
xmlSecKeyDataPtr src);
static void xmlSecNssKeyDataEcdsaFinalize(xmlSecKeyDataPtr data);

static xmlSecKeyDataType xmlSecNssKeyDataEcdsaGetType(xmlSecKeyDataPtr data);
static xmlSecSize xmlSecNssKeyDataEcdsaGetSize(xmlSecKeyDataPtr data);
static void xmlSecNssKeyDataEcdsaDebugDump(xmlSecKeyDataPtr data,
FILE* output);
static void xmlSecNssKeyDataEcdsaDebugXmlDump(xmlSecKeyDataPtr data,
FILE* output);

static xmlSecKeyDataKlass xmlSecNssKeyDataEcdsaKlass = {
sizeof(xmlSecKeyDataKlass),
xmlSecNssPKIKeyDataSize,

/* data */
xmlSecNameECDSAKeyValue,
xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
/* xmlSecKeyDataUsage usage; */
xmlSecHrefECDSAKeyValue, /* const xmlChar* href; */
xmlSecNodeECDSAKeyValue, /* const xmlChar* dataNodeName; */
xmlSecDSigNs, /* const xmlChar* dataNodeNs; */

/* constructors/destructor */
xmlSecNssKeyDataEcdsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
xmlSecNssKeyDataEcdsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
xmlSecNssKeyDataEcdsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
NULL, /* xmlSecKeyDataGenerateMethod generate; */

/* get info */
xmlSecNssKeyDataEcdsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
xmlSecNssKeyDataEcdsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */

/* read/write */
NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
NULL, /* xmlSecKeyDataBinReadMethod binRead; */
NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */

/* debug */
xmlSecNssKeyDataEcdsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
xmlSecNssKeyDataEcdsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */

/* reserved for the future */
NULL, /* void* reserved0; */
NULL, /* void* reserved1; */
};

/**
* xmlSecNssKeyDataEcdsaGetKlass:
*
* The ECDSA key data klass.
*
* Returns: pointer to ECDSA key data klass.
*/
xmlSecKeyDataId
xmlSecNssKeyDataEcdsaGetKlass(void) {
return(&xmlSecNssKeyDataEcdsaKlass);
}

static int
xmlSecNssKeyDataEcdsaInitialize(xmlSecKeyDataPtr data) {
xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcdsaId), -1);

return(xmlSecNssPKIKeyDataInitialize(data));
}

static int
xmlSecNssKeyDataEcdsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecNssKeyDataEcdsaId), -1);
xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecNssKeyDataEcdsaId), -1);

return(xmlSecNssPKIKeyDataDuplicate(dst, src));
}

static void
xmlSecNssKeyDataEcdsaFinalize(xmlSecKeyDataPtr data) {
xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcdsaId));

xmlSecNssPKIKeyDataFinalize(data);
}

static xmlSecKeyDataType
xmlSecNssKeyDataEcdsaGetType(xmlSecKeyDataPtr data) {
xmlSecNssPKIKeyDataCtxPtr ctx;

xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcdsaId), xmlSecKeyDataTypeUnknown);
ctx = xmlSecNssPKIKeyDataGetCtx(data);
xmlSecAssert2(ctx != NULL, -1);
xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == ecKey, -1);
if (ctx->privkey != NULL) {
return(xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
} else {
return(xmlSecKeyDataTypePublic);
}
}

static xmlSecSize
xmlSecNssKeyDataEcdsaGetSize(xmlSecKeyDataPtr data) {
xmlSecNssPKIKeyDataCtxPtr ctx;

xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcdsaId), 0);
ctx = xmlSecNssPKIKeyDataGetCtx(data);
xmlSecAssert2(ctx != NULL, -1);
xmlSecAssert2(SECKEY_GetPublicKeyType(ctx->pubkey) == ecKey, -1);

return(SECKEY_SignatureLen(ctx->pubkey));
}

static void
xmlSecNssKeyDataEcdsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcdsaId));
xmlSecAssert(output != NULL);

fprintf(output, "=== ecdsa key: size = %d\n",
xmlSecNssKeyDataEcdsaGetSize(data));
}

static void
xmlSecNssKeyDataEcdsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecNssKeyDataEcdsaId));
xmlSecAssert(output != NULL);

fprintf(output, "<ECDSAKeyValue size=\"%d\" />\n",
xmlSecNssKeyDataEcdsaGetSize(data));
}
#endif /* XMLSEC_NO_ECDSA */
108 changes: 98 additions & 10 deletions src/nss/signatures.c
Expand Up @@ -83,6 +83,14 @@ xmlSecNssSignatureCheckId(xmlSecTransformPtr transform) {
}
#endif /* XMLSEC_NO_DSA */

#ifndef XMLSEC_NO_ECDSA
#ifndef XMLSEC_NO_SHA256
if(xmlSecTransformCheckId(transform, xmlSecNssTransformEcdsaSha256Id)) {
return(1);
}
#endif /* XMLSEC_NO_SHA256 */
#endif /* XMLSEC_NO_ECDSA */

#ifndef XMLSEC_NO_RSA

#ifndef XMLSEC_NO_MD5
Expand Down Expand Up @@ -139,6 +147,16 @@ xmlSecNssSignatureInitialize(xmlSecTransformPtr transform) {
} else
#endif /* XMLSEC_NO_DSA */

#ifndef XMLSEC_NO_ECDSA
#ifndef XMLSEC_NO_SHA256
if(xmlSecTransformCheckId(transform, xmlSecNssTransformEcdsaSha256Id)) {
ctx->keyId = xmlSecNssKeyDataEcdsaId;
/* This creates a signature which is ASN1 encoded */
ctx->alg = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
} else
#endif /* XMLSEC_NO_SHA256 */
#endif /* XMLSEC_NO_ECDSA */

#ifndef XMLSEC_NO_RSA

#ifndef XMLSEC_NO_MD5
Expand Down Expand Up @@ -315,14 +333,14 @@ xmlSecNssSignatureVerify(xmlSecTransformPtr transform,
signature.data = (unsigned char *)data;
signature.len = dataSize;

if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST || ctx->alg == SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE) {
/* This creates a signature which is ASN1 encoded */
SECItem signatureDer;
SECStatus statusDer;

statusDer = DSAU_EncodeDerSig(&signatureDer, &signature);
statusDer = DSAU_EncodeDerSigWithLen(&signatureDer, &signature, signature.len);
if(statusDer != SECSuccess) {
xmlSecNssError("DSAU_EncodeDerSig",
xmlSecNssError("DSAU_EncodeDerSigWithLen",
xmlSecTransformGetName(transform));
return(-1);
}
Expand Down Expand Up @@ -440,16 +458,36 @@ xmlSecNssSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransfor
return(-1);
}

if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST || ctx->alg == SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE) {
/* This creates a signature which is ASN1 encoded */
SECItem * signatureClr;

signatureClr = DSAU_DecodeDerSig(&signature);
if(signatureClr == NULL) {
xmlSecNssError("DSAU_DecodeDerSig",
xmlSecTransformGetName(transform));
SECITEM_FreeItem(&signature, PR_FALSE);
return(-1);
if(ctx->alg == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) {
signatureClr = DSAU_DecodeDerSig(&signature);
if(signatureClr == NULL) {
xmlSecNssError("DSAU_DecodeDerSig",
xmlSecTransformGetName(transform));
SECITEM_FreeItem(&signature, PR_FALSE);
return(-1);
}
} else {
/* In the ECDSA case the signature length depends on the
* key parameters. */
int signatureSize = PK11_SignatureLen(ctx->u.sig.privkey);
if(signatureSize < 1) {
xmlSecNssError("PK11_SignatureLen",
xmlSecTransformGetName(transform));
SECITEM_FreeItem(&signature, PR_FALSE);
return(-1);
}

signatureClr = DSAU_DecodeDerSigToLen(&signature, signatureSize);
if(signatureClr == NULL) {
xmlSecNssError("DSAU_DecodeDerSigToLen",
xmlSecTransformGetName(transform));
SECITEM_FreeItem(&signature, PR_FALSE);
return(-1);
}
}

ret = xmlSecBufferSetData(out, signatureClr->data, signatureClr->len);
Expand Down Expand Up @@ -540,6 +578,56 @@ xmlSecNssTransformDsaSha1GetKlass(void) {

#endif /* XMLSEC_NO_DSA */

#ifndef XMLSEC_NO_ECDSA
#ifndef XMLSEC_NO_SHA256
/****************************************************************************
*
* ECDSA-SHA256 signature transform
*
***************************************************************************/

static xmlSecTransformKlass xmlSecNssEcdsaSha256Klass = {
/* klass/object sizes */
sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
xmlSecNssSignatureSize, /* xmlSecSize objSize */

xmlSecNameEcdsaSha256, /* const xmlChar* name; */
xmlSecHrefEcdsaSha256, /* const xmlChar* href; */
xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */

xmlSecNssSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */
xmlSecNssSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */
NULL, /* xmlSecTransformNodeReadMethod readNode; */
NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
xmlSecNssSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
xmlSecNssSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */
xmlSecNssSignatureVerify, /* xmlSecTransformVerifyMethod verify; */
xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
NULL, /* xmlSecTransformPushXmlMethod pushXml; */
NULL, /* xmlSecTransformPopXmlMethod popXml; */
xmlSecNssSignatureExecute, /* xmlSecTransformExecuteMethod execute; */

NULL, /* void* reserved0; */
NULL, /* void* reserved1; */
};

/**
* xmlSecNssTransformEcdsaSha256GetKlass:
*
* The ECDSA-SHA256 signature transform klass.
*
* Returns: ECDSA-SHA256 signature transform klass.
*/
xmlSecTransformId
xmlSecNssTransformEcdsaSha256GetKlass(void) {
return(&xmlSecNssEcdsaSha256Klass);
}

#endif /* XMLSEC_NO_SHA256 */
#endif /* XMLSEC_NO_ECDSA */

#ifndef XMLSEC_NO_RSA

#ifndef XMLSEC_NO_MD5
Expand Down

0 comments on commit bf68612

Please sign in to comment.