/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/gnutls/signatures.c
1 872 строки
63 KB
Javid Khan
avoid integer overflow in length check in xmlSecGnuTLSReadDerInteger (#1197)
01 июн 2026, 18:26
Не верифицирован
01 июн 2026, 18:26
8424f58
Код
Авторство
О чём код?
/** * 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) 2002-2026 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. */ /** * @addtogroup xmlsec_gnutls_crypto * @brief Signatures implementation for GnuTLS. */ #include "globals.h" #include <string.h> #include <gnutls/gnutls.h> #include <gnutls/abstract.h> #include <gnutls/crypto.h> #include <xmlsec/xmlsec.h> #include <xmlsec/keys.h> #include <xmlsec/transforms.h> #include <xmlsec/errors.h> #include <xmlsec/gnutls/crypto.h> #include "../cast_helpers.h" /* https://www.w3.org/TR/xmldsig-core1/#sec-DSA * The output of the DSA algorithm consists of a pair of integers usually referred by the pair (r, s). * DSA-SHA1: Integer to octet-stream conversion must be done according to the I2OSP operation defined * in the RFC 3447 [PKCS1] specification with a l parameter equal to 20 * DSA-SHA256: The pairs (2048, 256) and (3072, 256) correspond to the algorithm DSAwithSHA256 */ #define XMLSEC_GNUTLS_SIGNATURE_DSA_SHA1_HALF_LEN 20 #define XMLSEC_GNUTLS_SIGNATURE_DSA_SHA256_HALF_LEN (256 / 8) /****************************************************************************** * * Internal GNUTLS signatures ctx * *****************************************************************************/ typedef gnutls_pubkey_t (*xmlSecGnuTLSKeyDataGetPublicKeyMethod) (xmlSecKeyDataPtr data); typedef gnutls_privkey_t (*xmlSecGnuTLSKeyDataGetPrivateKeyMethod) (xmlSecKeyDataPtr data); typedef struct _xmlSecGnuTLSSignatureCtx xmlSecGnuTLSSignatureCtx, *xmlSecGnuTLSSignatureCtxPtr; struct _xmlSecGnuTLSSignatureCtx { xmlSecGnuTLSKeyDataGetPublicKeyMethod getPubKey; xmlSecGnuTLSKeyDataGetPrivateKeyMethod getPrivKey; gnutls_digest_algorithm_t dgstAlgo; gnutls_hash_hd_t hash; /* either digest of content; or the content to be signed */ xmlSecBuffer preSignBuffer; xmlSecKeyDataId keyId; xmlSecKeyDataPtr keyData; gnutls_sign_algorithm_t signAlgo; unsigned int signFlags; unsigned int verifyFlags; }; /****************************************************************************** * * Signature transforms * *****************************************************************************/ XMLSEC_TRANSFORM_DECLARE(GnuTLSSignature, xmlSecGnuTLSSignatureCtx) #define xmlSecGnuTLSSignatureSize XMLSEC_TRANSFORM_SIZE(GnuTLSSignature) static int xmlSecGnuTLSSignatureCheckId (xmlSecTransformPtr transform); static int xmlSecGnuTLSSignatureInitialize (xmlSecTransformPtr transform); static void xmlSecGnuTLSSignatureFinalize (xmlSecTransformPtr transform); static int xmlSecGnuTLSSignatureSetKeyReq (xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq); static int xmlSecGnuTLSSignatureSetKey (xmlSecTransformPtr transform, xmlSecKeyPtr key); static int xmlSecGnuTLSSignatureVerify (xmlSecTransformPtr transform, const xmlSecByte* data, xmlSecSize dataSize, xmlSecTransformCtxPtr transformCtx); static int xmlSecGnuTLSSignatureExecute (xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx); static int xmlSecGnuTLSSignatureCheckId(xmlSecTransformPtr transform) { /* DSA */ #ifndef XMLSEC_NO_DSA #ifndef XMLSEC_NO_SHA1 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformDsaSha1Id)) { return(1); } #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformDsaSha256Id)) { return(1); } #endif /* XMLSEC_NO_SHA256 */ #endif /* XMLSEC_NO_DSA */ /* ECDSA */ #ifndef XMLSEC_NO_EC #ifndef XMLSEC_NO_SHA1 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha1Id)) { return(1); } #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA224 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha224Id)) { return(1); } #endif /* XMLSEC_NO_SHA224 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha256Id)) { return(1); } #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha384Id)) { return(1); } #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha512Id)) { return(1); } #endif /* XMLSEC_NO_SHA512 */ #ifndef XMLSEC_NO_SHA3 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_224Id)) { return(1); } if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_256Id)) { return(1); } if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_384Id)) { return(1); } if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_512Id)) { return(1); } #endif /* XMLSEC_NO_SHA3 */ #endif /* XMLSEC_NO_EC */ /* GOST 2001 */ #ifndef XMLSEC_NO_GOST if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformGost2001GostR3411_94Id)) { return(1); } #endif /* XMLSEC_NO_GOST */ #ifndef XMLSEC_NO_GOST2012 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformGostR3410_2012GostR3411_2012_256Id)) { return(1); } if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformGostR3410_2012GostR3411_2012_512Id)) { return(1); } #endif /* XMLSEC_NO_GOST2012 */ /* ML-DSA */ #ifndef XMLSEC_NO_MLDSA if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformMLDSA44Id)) { return(1); } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformMLDSA65Id)) { return(1); } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformMLDSA87Id)) { return(1); } else #endif /* XMLSEC_NO_MLDSA */ /* EdDSA */ #ifndef XMLSEC_NO_EDDSA if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEdDSAEd25519Id)) { return(1); } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEdDSAEd448Id)) { return(1); } else #endif /* XMLSEC_NO_EDDSA */ /* RSA */ #ifndef XMLSEC_NO_RSA #ifndef XMLSEC_NO_SHA1 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha1Id)) { return(1); } #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA224 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha224Id)) { return(1); } #endif /* XMLSEC_NO_SHA224 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha256Id)) { return(1); } #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha384Id)) { return(1); } #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha512Id)) { return(1); } #endif /* XMLSEC_NO_SHA512 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaPssSha256Id)) { return(1); } #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaPssSha384Id)) { return(1); } #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaPssSha512Id)) { return(1); } #endif /* XMLSEC_NO_SHA512 */ #endif /* XMLSEC_NO_RSA */ return(0); } static int xmlSecGnuTLSSignatureInitialize(xmlSecTransformPtr transform) { xmlSecGnuTLSSignatureCtxPtr ctx; int err; xmlSecAssert2(xmlSecGnuTLSSignatureCheckId(transform), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSSignatureSize), -1); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); memset(ctx, 0, sizeof(xmlSecGnuTLSSignatureCtx)); /* DSA */ #ifndef XMLSEC_NO_DSA #ifndef XMLSEC_NO_SHA1 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformDsaSha1Id)) { ctx->keyId = xmlSecGnuTLSKeyDataDsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA1; ctx->signAlgo = GNUTLS_SIGN_DSA_SHA1; ctx->getPubKey = xmlSecGnuTLSKeyDataDsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataDsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformDsaSha256Id)) { ctx->keyId = xmlSecGnuTLSKeyDataDsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA256; ctx->signAlgo = GNUTLS_SIGN_DSA_SHA256; ctx->getPubKey = xmlSecGnuTLSKeyDataDsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataDsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA256 */ #endif /* XMLSEC_NO_DSA */ /* ECDSA */ #ifndef XMLSEC_NO_SHA1 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha1Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA1; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA1; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA224 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha224Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA224; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA224; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else #endif /* XMLSEC_NO_SHA224 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha256Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA256; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA256; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha384Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA384; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA384; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha512Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA512; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA512; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else #endif /* XMLSEC_NO_SHA512 */ /* ECDSA SHA3 */ #ifndef XMLSEC_NO_SHA3 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_224Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA3_224; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA3_224; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_256Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA3_256; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA3_256; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_384Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA3_384; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA3_384; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEcdsaSha3_512Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEcId; ctx->dgstAlgo = GNUTLS_DIG_SHA3_512; ctx->signAlgo = GNUTLS_SIGN_ECDSA_SHA3_512; ctx->getPubKey = xmlSecGnuTLSKeyDataEcGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEcGetPrivateKey; } else #endif /* XMLSEC_NO_SHA3 */ /* GOST 2001 */ #ifndef XMLSEC_NO_GOST if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformGost2001GostR3411_94Id)) { ctx->keyId = xmlSecGnuTLSKeyDataGost2001Id; ctx->dgstAlgo = GNUTLS_DIG_GOSTR_94; ctx->signAlgo = GNUTLS_SIGN_GOST_94; ctx->verifyFlags = GNUTLS_VERIFY_ALLOW_BROKEN; ctx->getPubKey = xmlSecGnuTLSKeyDataGost2001GetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataGost2001GetPrivateKey; } else #endif /* XMLSEC_NO_GOST */ /* GOST 2012 */ #ifndef XMLSEC_NO_GOST2012 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformGostR3410_2012GostR3411_2012_256Id)) { ctx->keyId = xmlSecGnuTLSKeyDataGost2012_256Id; ctx->dgstAlgo = GNUTLS_DIG_STREEBOG_256; ctx->signAlgo = GNUTLS_SIGN_GOST_256; ctx->getPubKey = xmlSecGnuTLSKeyDataGost2012_256GetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataGost2012_256GetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformGostR3410_2012GostR3411_2012_512Id)) { ctx->keyId = xmlSecGnuTLSKeyDataGost2012_512Id; ctx->dgstAlgo = GNUTLS_DIG_STREEBOG_512; ctx->signAlgo = GNUTLS_SIGN_GOST_512; ctx->getPubKey = xmlSecGnuTLSKeyDataGost2012_512GetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataGost2012_512GetPrivateKey; } else #endif /* XMLSEC_NO_GOST2012 */ /* ML-DSA */ #ifndef XMLSEC_NO_MLDSA /* ML-DSA uses hard coded SHAKE-128 and SHAKE-256 so no need to have digest here */ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformMLDSA44Id)) { ctx->keyId = xmlSecGnuTLSKeyDataMLDSAId; ctx->dgstAlgo = GNUTLS_DIG_UNKNOWN; ctx->signAlgo = GNUTLS_SIGN_MLDSA44; ctx->getPubKey = xmlSecGnuTLSKeyDataMLDSAGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataMLDSAGetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformMLDSA65Id)) { ctx->keyId = xmlSecGnuTLSKeyDataMLDSAId; ctx->dgstAlgo = GNUTLS_DIG_UNKNOWN; ctx->signAlgo = GNUTLS_SIGN_MLDSA65; ctx->getPubKey = xmlSecGnuTLSKeyDataMLDSAGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataMLDSAGetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformMLDSA87Id)) { ctx->keyId = xmlSecGnuTLSKeyDataMLDSAId; ctx->dgstAlgo = GNUTLS_DIG_UNKNOWN; ctx->signAlgo = GNUTLS_SIGN_MLDSA87; ctx->getPubKey = xmlSecGnuTLSKeyDataMLDSAGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataMLDSAGetPrivateKey; } else #endif /* XMLSEC_NO_MLDSA */ /* EdDSA */ #ifndef XMLSEC_NO_EDDSA /* EdDSA uses its own internally defined hash so no need to have digest here */ if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEdDSAEd25519Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEdDSAId; ctx->dgstAlgo = GNUTLS_DIG_UNKNOWN; ctx->signAlgo = GNUTLS_SIGN_EDDSA_ED25519; ctx->getPubKey = xmlSecGnuTLSKeyDataEdDSAGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEdDSAGetPrivateKey; } else if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformEdDSAEd448Id)) { ctx->keyId = xmlSecGnuTLSKeyDataEdDSAId; ctx->dgstAlgo = GNUTLS_DIG_UNKNOWN; ctx->signAlgo = GNUTLS_SIGN_EDDSA_ED448; ctx->getPubKey = xmlSecGnuTLSKeyDataEdDSAGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataEdDSAGetPrivateKey; } else #endif /* XMLSEC_NO_EDDSA */ /* RSA */ #ifndef XMLSEC_NO_RSA #ifndef XMLSEC_NO_SHA1 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha1Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA1; ctx->signAlgo = GNUTLS_SIGN_RSA_SHA1; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA224 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha224Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA224; ctx->signAlgo = GNUTLS_SIGN_RSA_SHA224; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA224 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha256Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA256; ctx->signAlgo = GNUTLS_SIGN_RSA_SHA256; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha384Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA384; ctx->signAlgo = GNUTLS_SIGN_RSA_SHA384; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaSha512Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA512; ctx->signAlgo = GNUTLS_SIGN_RSA_SHA512; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA512 */ #ifndef XMLSEC_NO_SHA256 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaPssSha256Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA256; ctx->signAlgo = GNUTLS_SIGN_RSA_PSS_SHA256; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaPssSha384Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA384; ctx->signAlgo = GNUTLS_SIGN_RSA_PSS_SHA384; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformRsaPssSha512Id)) { ctx->keyId = xmlSecGnuTLSKeyDataRsaId; ctx->dgstAlgo = GNUTLS_DIG_SHA512; ctx->signAlgo = GNUTLS_SIGN_RSA_PSS_SHA512; ctx->getPubKey = xmlSecGnuTLSKeyDataRsaGetPublicKey; ctx->getPrivKey = xmlSecGnuTLSKeyDataRsaGetPrivateKey; } else #endif /* XMLSEC_NO_SHA512 */ #endif /* XMLSEC_NO_RSA */ if(1) { xmlSecInvalidTransfromError(transform) return(-1); } /* create hash (skip for algorithms that don't use separate digest like ML-DSA) */ if(ctx->dgstAlgo != GNUTLS_DIG_UNKNOWN) { err = gnutls_hash_init(&(ctx->hash), ctx->dgstAlgo); if(err != GNUTLS_E_SUCCESS) { xmlSecGnuTLSError("gnutls_hash_init", err, NULL); return(-1); } } /* create buffer */ if(xmlSecBufferInitialize(&(ctx->preSignBuffer), 0) < 0) { xmlSecInternalError("xmlSecBufferInitialize(preSignBuffer)", xmlSecTransformGetName(transform)); return(-1); } /* done */ return(0); } static void xmlSecGnuTLSSignatureFinalize(xmlSecTransformPtr transform) { xmlSecGnuTLSSignatureCtxPtr ctx; xmlSecAssert(xmlSecGnuTLSSignatureCheckId(transform)); xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSSignatureSize)); xmlSecAssert((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify)); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert(ctx != NULL); if(ctx->keyData != NULL) { xmlSecKeyDataDestroy(ctx->keyData); } if(ctx->hash != NULL) { gnutls_hash_deinit(ctx->hash, NULL); } xmlSecBufferFinalize(&(ctx->preSignBuffer)); memset(ctx, 0, sizeof(xmlSecGnuTLSSignatureCtx)); } static int xmlSecGnuTLSSignatureSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { xmlSecGnuTLSSignatureCtxPtr ctx; xmlSecKeyDataPtr value; xmlSecAssert2(xmlSecGnuTLSSignatureCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSSignatureSize), -1); xmlSecAssert2(key != NULL, -1); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->keyId != NULL, -1); xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); value = xmlSecKeyGetValue(key); xmlSecAssert2(value != NULL, -1); ctx->keyData = xmlSecKeyDataDuplicate(value); if(ctx->keyData == NULL) { xmlSecInternalError("xmlSecKeyDataDuplicate", xmlSecTransformGetName(transform)); return(-1); } return(0); } static int xmlSecGnuTLSSignatureSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { xmlSecGnuTLSSignatureCtxPtr ctx; xmlSecAssert2(xmlSecGnuTLSSignatureCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSSignatureSize), -1); xmlSecAssert2(keyReq != NULL, -1); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->keyId != NULL, -1); keyReq->keyId = ctx->keyId; if(transform->operation == xmlSecTransformOperationSign) { keyReq->keyType = xmlSecKeyDataTypePrivate; keyReq->keyUsage = xmlSecKeyUsageSign; } else { keyReq->keyType = xmlSecKeyDataTypePublic; keyReq->keyUsage = xmlSecKeyUsageVerify; } return(0); } /* * https://www.w3.org/TR/xmldsig-core1/#sec-DSA * * The output of the DSA algorithm consists of a pair of integers usually referred by the pair (r, s). * The signature value consists of the base64 encoding of the concatenation of two octet-streams that * respectively result from the octet-encoding of the values r and s in that order. Integer to octet-stream * conversion must be done according to the I2OSP operation defined in the RFC 3447 [PKCS1] specification * with a l parameter equal to 20. * * https://www.w3.org/TR/xmldsig-core1/#sec-ECDSA * * The output of the ECDSA algorithm consists of a pair of integers usually referred by the pair (r, s). * The signature value consists of the base64 encoding of the concatenation of two octet-streams that respectively * result from the octet-encoding of the values r and s in that order. Integer to octet-stream conversion must * be done according to the I2OSP operation defined in the RFC 3447 [PKCS1] specification with the l parameter equal * to the size of the base point order of the curve in bytes (e.g. 32 for the P-256 curve and 66 for the P-521 curve). * * DER DSA signature: * SEQUENCE 30 <length byte> * INTEGER (r) 02 <length byte> <integer bytes> * INTEGER (s) 02 <length byte> <integer bytes> */ #define XMLSEC_GNUTLS_ASN1_TAG_SEQUENCE 0x30 #define XMLSEC_GNUTLS_ASN1_TAG_INTEGER 0x02 #define XMLSEC_GNUTLS_GET_SIZE_OF_SIZE(size, sizeOfSize) \ if((size) <= 0x78) { \ (sizeOfSize) = 1; \ } else if((size) <= 0xFF) { \ (sizeOfSize) = 2; \ } else if((size) <= 0xFFFF) { \ (sizeOfSize) = 3; \ } else { \ xmlSecInvalidSizeMoreThanError("ASN1 value length", (size), (xmlSecSize)(0xFFFF), NULL); \ return(-1); \ } #define XMLSEC_GNUTLS_PUT_LENGTH(pp, size) \ if((size) <= 0x78) { \ (*(pp)++) = (xmlSecByte)(size); \ } else if((size) <= 0xFF) { \ (*(pp)++) = (xmlSecByte)(0x81); \ (*(pp)++) = (xmlSecByte)((size) & 0xFF); \ } else if((size) <= 0xFFFF) { \ (*(pp)++) = (xmlSecByte)(0x82); \ (*(pp)++) = (xmlSecByte)(((size) >> 8) & 0xFF); \ (*(pp)++) = (xmlSecByte)((size) & 0xFF); \ } else { \ xmlSecInvalidSizeMoreThanError("ASN1 value length", (size), (xmlSecSize)(0xFFFF), NULL); \ return(-1); \ } static int xmlSecGnuTLSToDer(const gnutls_datum_t* src, gnutls_datum_t* dst, xmlSecSize size) { xmlSecByte * pp; xmlSecSize sizeOfSize; xmlSecSize seqSize, sizeOfSeqSize; xmlSecSize length; xmlSecAssert2(src != NULL, -1); xmlSecAssert2(src->data != NULL, -1); xmlSecAssert2(dst != NULL, -1); xmlSecAssert2(dst->data == NULL, -1); xmlSecAssert2(size > 0, -1); /* check size: we expect the r and s to be the same size and match the size of * the key (RFC 6931) */ if(src->size == 2 * size) { /* good, do nothing */ } else if((src->size < 2 * size) && (src->size % 2 == 0)) { /* however some implementations (e.g. Java) cut leading zeros: * https://github.com/lsh123/xmlsec/issues/228 */ size = src->size / 2; } else if((src->size > 2 * size) && (src->size % 2 == 0)) { /* however some implementations (e.g. Java) add leading zeros: * https://github.com/lsh123/xmlsec/issues/941*/ size = src->size / 2; } else { xmlSecInternalError3("Invalid signature size", NULL, "actual=%u; expected=" XMLSEC_SIZE_FMT, src->size, 2 * size); return(-1); } XMLSEC_GNUTLS_GET_SIZE_OF_SIZE(size, sizeOfSize); seqSize = 2 * (size + sizeOfSize + 1); /* 2 integers: 2 * (int tag + int len + int val)*/ XMLSEC_GNUTLS_GET_SIZE_OF_SIZE(seqSize, sizeOfSeqSize); length = 1 + sizeOfSeqSize + seqSize; /* sequence: sqn tag + sqn len + sqn val */ /* allocate memory */ XMLSEC_SAFE_CAST_SIZE_TO_UINT(length, dst->size, return(-1), NULL); dst->data = gnutls_malloc(dst->size); if(dst->data == NULL) { xmlSecGnuTLSError("gnutls_malloc", 0, NULL); return(-1); } pp = dst->data; /* sequence */ (*pp++) = XMLSEC_GNUTLS_ASN1_TAG_SEQUENCE; XMLSEC_GNUTLS_PUT_LENGTH(pp, seqSize); /* r */ (*pp++) = XMLSEC_GNUTLS_ASN1_TAG_INTEGER; XMLSEC_GNUTLS_PUT_LENGTH(pp, size); memcpy(pp, src->data, size); pp += size; /* s */ (*pp++) = XMLSEC_GNUTLS_ASN1_TAG_INTEGER; XMLSEC_GNUTLS_PUT_LENGTH(pp, size); memcpy(pp, src->data + size, size); pp += size; /* success */ return(0); } #define XMLSEC_GNUTLS_GET_BYTE(data, dataSize, ii, cc) \ if((*(ii)) >= (dataSize)) { \ return(-1); \ } \ (cc) = (data)[(*(ii))++]; \ static int xmlSecGnuTLSReadDerLength(const xmlSecByte * data, xmlSecSize dataSize, xmlSecSize * ii, xmlSecSize * res) { xmlSecSize cc; xmlSecAssert2(data != NULL, -1); xmlSecAssert2(ii != NULL, -1); xmlSecAssert2(res != NULL, -1); XMLSEC_GNUTLS_GET_BYTE(data, dataSize, ii, cc); if((cc & 0x80) == 0) { (*res) = cc; } else if (cc == 0x80) { /* indefinite length not supported */ return(-1); } else if (cc == 0xff) { /* forbidden length value. */ return(-1); } else { xmlSecSize length = 0; for(xmlSecSize count = cc & 0x7f; count; count--) { XMLSEC_GNUTLS_GET_BYTE(data, dataSize, ii, cc); length <<= 8; length |= (cc & 0xff); } (*res) = length; } /* success */ return(0); } static int xmlSecGnuTLSReadDerInteger(const xmlSecByte * data, xmlSecSize dataSize, xmlSecSize * ii, xmlSecByte * res, xmlSecSize resSize) { xmlSecSize cc; xmlSecSize len; int ret; xmlSecAssert2(data != NULL, -1); xmlSecAssert2(ii != NULL, -1); xmlSecAssert2(res != NULL, -1); /* tag */ XMLSEC_GNUTLS_GET_BYTE(data, dataSize, ii, cc); if(cc != XMLSEC_GNUTLS_ASN1_TAG_INTEGER) { return(-1); } /* len */ ret = xmlSecGnuTLSReadDerLength(data, dataSize, ii, &len); if(ret < 0) { return(-1); } /* val: (*ii) <= dataSize here, so check len without overflowing (*ii) + len */ if(len > dataSize - (*ii)) { return(-1); } /* skip zeros if any */ while((len > 0) && (data[(*ii)] == 0)) { ++(*ii); --len; } if(len > resSize) { return(-1); } /* add 0s at the beginning if needed */ memcpy(res + (resSize - len), data + (*ii), len); (*ii) += len; /* success */ return(0); } static int xmlSecGnuTLSFromDer(const gnutls_datum_t* src, gnutls_datum_t* dst, xmlSecSize size) { xmlSecSize ii = 0; xmlSecSize len, srcSize; int ret; int res = -1; xmlSecAssert2(src != NULL, -1); xmlSecAssert2(src->data != NULL, -1); xmlSecAssert2(dst != NULL, -1); xmlSecAssert2(dst->data == NULL, -1); xmlSecAssert2(size > 0, -1); /* allocate memory */ len = 2 * size; XMLSEC_SAFE_CAST_SIZE_TO_UINT(len, dst->size, return(-1), NULL); dst->data = gnutls_malloc(dst->size); if(dst->data == NULL) { xmlSecGnuTLSError("gnutls_malloc", 0, NULL); return(-1); } memset(dst->data, 0, dst->size); XMLSEC_SAFE_CAST_UINT_TO_SIZE(src->size, srcSize, goto done, NULL); /* sequence tag */ if(srcSize < ii + 1) { xmlSecInvalidSizeLessThanError("Expected asn1 sequence tag", srcSize, ii + 2, NULL); goto done; } if(src->data[ii] != XMLSEC_GNUTLS_ASN1_TAG_SEQUENCE) { xmlSecInvalidDataError("Expected asn1 sequence tag", NULL); goto done; } ++ii; /* sequence len */ ret = xmlSecGnuTLSReadDerLength(src->data, srcSize, &ii, &len); if(ret < 0) { xmlSecInvalidDataError("Invalid DER sequence length", NULL); goto done; } /* r */ ret = xmlSecGnuTLSReadDerInteger(src->data, srcSize, &ii, dst->data, size); if(ret < 0) { xmlSecInvalidDataError("Cannot read DER integer r", NULL); goto done; } /* s */ ret = xmlSecGnuTLSReadDerInteger(src->data, srcSize, &ii, dst->data + size, size); if(ret < 0) { xmlSecInvalidDataError("Cannot read DER integer s", NULL); goto done; } /* check leftovers */ if(ii != srcSize) { xmlSecInvalidDataError("Unexpected data", NULL); goto done; } /* success */ res = 0; done: if(res < 0) { if(dst->data != NULL) { gnutls_free(dst->data); dst->data = NULL; } dst->size = 0; } return(res); } /* returns res = 0 if no der conversion is expected or the half size of the resulting signature (i.e. size of each r and s integers) */ static int xmlSecGnuTLSSignatureGetDerHalfSize(gnutls_sign_algorithm_t algo, xmlSecSize keySize, xmlSecSize * res) { xmlSecAssert2(res != 0, -1); switch(algo) { /* Fixed length (DSA-SHA*) */ #ifndef XMLSEC_NO_DSA case GNUTLS_SIGN_DSA_SHA1: (*res) = XMLSEC_GNUTLS_SIGNATURE_DSA_SHA1_HALF_LEN; break; case GNUTLS_SIGN_DSA_SHA256: (*res) = XMLSEC_GNUTLS_SIGNATURE_DSA_SHA256_HALF_LEN; break; #endif /* XMLSEC_NO_DSA */ /* Key length (ECDSA-SHA*) */ #ifndef XMLSEC_NO_EC case GNUTLS_SIGN_ECDSA_SHA1: case GNUTLS_SIGN_ECDSA_SHA224: case GNUTLS_SIGN_ECDSA_SHA256: case GNUTLS_SIGN_ECDSA_SHA384: case GNUTLS_SIGN_ECDSA_SHA512: case GNUTLS_SIGN_ECDSA_SHA3_224: case GNUTLS_SIGN_ECDSA_SHA3_256: case GNUTLS_SIGN_ECDSA_SHA3_384: case GNUTLS_SIGN_ECDSA_SHA3_512: if(keySize < 8) { xmlSecInvalidSizeDataError("keySize", keySize, "EC key size", NULL); return(-1); } (*res) = (keySize + 7) / 8; break; #endif /* XMLSEC_NO_EC */ default: /* don't convert to DER */ (*res) = 0; break; } /* done */ return(0); } static int xmlSecGnuTLSSignatureGetDataToSign(xmlSecGnuTLSSignatureCtxPtr ctx, gnutls_datum_t* dataToSign) { int ret; xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(dataToSign != NULL, -1); if (ctx->hash != NULL) { unsigned int hashSize; /* get hash size and setup buffer */ hashSize = gnutls_hash_get_len(ctx->dgstAlgo); if(hashSize <= 0) { xmlSecInternalError("gnutls_hash_get_len", NULL); return(-1); } ret = xmlSecBufferSetSize(&(ctx->preSignBuffer), hashSize); if(ret < 0) { xmlSecInternalError("xmlSecBufferSetSize", NULL); return(-1); } /* get hash */ gnutls_hash_output(ctx->hash, xmlSecBufferGetData(&(ctx->preSignBuffer))); dataToSign->data = xmlSecBufferGetData(&(ctx->preSignBuffer)); dataToSign->size = hashSize; } else { xmlSecSize dataSize; /* get data size -- we should have SOME data and zero size is an error */ dataSize = xmlSecBufferGetSize(&(ctx->preSignBuffer)); if(dataSize <= 0) { xmlSecInternalError("xmlSecBufferGetSize", NULL); return(-1); } /* no hash, sign the whole data */ dataToSign->data = xmlSecBufferGetData(&(ctx->preSignBuffer)); XMLSEC_SAFE_CAST_SIZE_TO_UINT(dataSize, dataToSign->size, return(-1), NULL); } /* done */ return(0); } static int xmlSecGnuTLSSignatureVerify( xmlSecTransformPtr transform, const xmlSecByte* data, xmlSecSize dataSize, xmlSecTransformCtxPtr transformCtx ) { xmlSecGnuTLSSignatureCtxPtr ctx; gnutls_datum_t dataToSign, signature; gnutls_pubkey_t pubkey; xmlSecSize keySize, signHalfSize = 0; int err; int ret; xmlSecAssert2(xmlSecGnuTLSSignatureCheckId(transform), -1); xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSSignatureSize), -1); xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); xmlSecAssert2(data != NULL, -1); xmlSecAssert2(transformCtx != NULL, -1); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert2(ctx->keyData != NULL, -1); xmlSecAssert2(ctx->getPubKey != NULL, -1); /* get pubkey */ pubkey = ctx->getPubKey(ctx->keyData); if(pubkey == NULL) { xmlSecInternalError("ctx->getPubKey", xmlSecTransformGetName(transform)); return(-1); } /* do we need to convert signature to DER? */ keySize = xmlSecKeyDataGetSize(ctx->keyData); if(keySize <= 0) { xmlSecInternalError("keySize", xmlSecTransformGetName(transform)); return(-1); } ret = xmlSecGnuTLSSignatureGetDerHalfSize(ctx->signAlgo, keySize, &signHalfSize); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSSignatureGetDerHalfSize", xmlSecTransformGetName(transform)); return(-1); } /* get data to sign */ ret = xmlSecGnuTLSSignatureGetDataToSign(ctx, &dataToSign); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSSignatureGetDataToSign", xmlSecTransformGetName(transform)); return(-1); } /* verify */ signature.data = (xmlSecByte*)data; XMLSEC_SAFE_CAST_SIZE_TO_UINT(dataSize, signature.size, return(-1), xmlSecTransformGetName(transform)); /* however some implementations (e.g. Java) just put ASN1 structure in the signature * and in this case we ALREADY have ASN1 * https://github.com/lsh123/xmlsec/issues/995 */ if((signHalfSize > 0) && ((transformCtx->flags & XMLSEC_TRANSFORMCTX_FLAGS_SUPPORT_ASN1_SIGNATURE_VALUES) == 0)) { gnutls_datum_t der_signature = { NULL, 0 }; ret = xmlSecGnuTLSToDer(&signature, &der_signature, signHalfSize); if((ret < 0) || (der_signature.data == NULL)) { xmlSecInternalError("xmlSecGnuTLSToDer", xmlSecTransformGetName(transform)); return(-1); } if(ctx->hash != NULL) { err = gnutls_pubkey_verify_hash2(pubkey, ctx->signAlgo, ctx->verifyFlags, &dataToSign, &der_signature); } else { err = gnutls_pubkey_verify_data2(pubkey, ctx->signAlgo, ctx->verifyFlags, &dataToSign, &der_signature); } gnutls_free(der_signature.data); } else { if(ctx->hash != NULL) { err = gnutls_pubkey_verify_hash2(pubkey, ctx->signAlgo, ctx->verifyFlags, &dataToSign, &signature); } else { err = gnutls_pubkey_verify_data2(pubkey, ctx->signAlgo, ctx->verifyFlags, &dataToSign, &signature); } } /* In case of a verification failure GNUTLS_E_PK_SIG_VERIFY_FAILED is returned, and zero or positive code on success. */ if(err >= 0) { /* signature is good */ transform->status = xmlSecTransformStatusOk; } else if(err == GNUTLS_E_PK_SIG_VERIFY_FAILED) { /* signature verification failed */ xmlSecOtherError(XMLSEC_ERRORS_R_DATA_NOT_MATCH, xmlSecTransformGetName(transform), "Signature verification failed"); transform->status = xmlSecTransformStatusFail; } else { /* an error */ if(ctx->hash != NULL) { xmlSecGnuTLSError("gnutls_pubkey_verify_hash2", err, xmlSecTransformGetName(transform)); } else { xmlSecGnuTLSError("gnutls_pubkey_verify_data2", err, xmlSecTransformGetName(transform)); } return(-1); } /* done */ return(0); } static int xmlSecGnuTLSSignatureSign( xmlSecTransformPtr transform, xmlSecGnuTLSSignatureCtxPtr ctx, xmlSecBufferPtr out, xmlSecTransformCtxPtr transformCtx ) { gnutls_datum_t dataToSign, signature = { NULL, 0 }; gnutls_privkey_t privkey; xmlSecSize keySize, signHalfSize = 0; int err; int ret; xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->keyData != NULL, -1); xmlSecAssert2(ctx->getPrivKey != NULL, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(transformCtx != NULL, -1); /* get key */ privkey = ctx->getPrivKey(ctx->keyData); if(privkey == NULL) { xmlSecInternalError("ctx->getPrivKey", xmlSecTransformGetName(transform)); return(-1); } /* do we need to convert signature from DER? */ keySize = xmlSecKeyDataGetSize(ctx->keyData); if(keySize <= 0) { xmlSecInternalError("keySize", xmlSecTransformGetName(transform)); return(-1); } ret = xmlSecGnuTLSSignatureGetDerHalfSize(ctx->signAlgo, keySize, &signHalfSize); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSSignatureGetDerHalfSize", xmlSecTransformGetName(transform)); return(-1); } /* get data to sign */ ret = xmlSecGnuTLSSignatureGetDataToSign(ctx, &dataToSign); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSSignatureGetDataToSign", xmlSecTransformGetName(transform)); return(-1); } /* sign */ if(ctx->hash != NULL) { err = gnutls_privkey_sign_hash2(privkey, ctx->signAlgo, ctx->signFlags, &dataToSign, &signature); if((err != GNUTLS_E_SUCCESS) || (signature.data == NULL)) { xmlSecGnuTLSError("gnutls_privkey_sign_hash2", err, xmlSecTransformGetName(transform)); return(-1); } } else { err = gnutls_privkey_sign_data2(privkey, ctx->signAlgo, ctx->signFlags, &dataToSign, &signature); if((err != GNUTLS_E_SUCCESS) || (signature.data == NULL)) { xmlSecGnuTLSError("gnutls_privkey_sign_data2", err, xmlSecTransformGetName(transform)); return(-1); } } /* however some implementations (e.g. Java) just put ASN1 structure in the signature * and in this case we ALREADY have ASN1 * https://github.com/lsh123/xmlsec/issues/995 */ if((signHalfSize > 0) && ((transformCtx->flags & XMLSEC_TRANSFORMCTX_FLAGS_SUPPORT_ASN1_SIGNATURE_VALUES) == 0)) { gnutls_datum_t xmldsig_signature = { NULL, 0 }; ret = xmlSecGnuTLSFromDer(&signature, &xmldsig_signature, signHalfSize); if((ret < 0) || (xmldsig_signature.data == NULL)) { xmlSecInternalError("xmlSecGnuTLSFromDer", xmlSecTransformGetName(transform)); gnutls_free(signature.data); return(-1); } /* xmldsig_signature -> signature */ gnutls_free(signature.data); signature.data = xmldsig_signature.data; signature.size = xmldsig_signature.size; } /* append to the output */ ret = xmlSecBufferAppend(out, signature.data, signature.size); if(ret < 0) { xmlSecInternalError("xmlSecBufferAppend", xmlSecTransformGetName(transform)); gnutls_free(signature.data); return(-1); } gnutls_free(signature.data); /* success */ return(0); } static int xmlSecGnuTLSSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { xmlSecGnuTLSSignatureCtxPtr ctx; xmlSecBufferPtr in, out; xmlSecSize inSize, outSize; int err; int ret; xmlSecAssert2(xmlSecGnuTLSSignatureCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSSignatureSize), -1); xmlSecAssert2(transformCtx != NULL, -1); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); in = &(transform->inBuf); out = &(transform->outBuf); inSize = xmlSecBufferGetSize(in); outSize = xmlSecBufferGetSize(out); ctx = xmlSecGnuTLSSignatureGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); if(transform->status == xmlSecTransformStatusNone) { xmlSecAssert2(outSize == 0, -1); transform->status = xmlSecTransformStatusWorking; } if((transform->status == xmlSecTransformStatusWorking) && (inSize > 0)) { /* update hash or buffer */ if(ctx->hash != NULL) { err = gnutls_hash(ctx->hash, xmlSecBufferGetData(in), inSize); if(err != GNUTLS_E_SUCCESS) { xmlSecGnuTLSError("gnutls_hash", err, xmlSecTransformGetName(transform)); return(-1); } } else { ret = xmlSecBufferAppend(&(ctx->preSignBuffer), xmlSecBufferGetData(in), inSize); if(ret < 0) { xmlSecInternalError("xmlSecBufferAppend(preSignBuffer)", xmlSecTransformGetName(transform)); return(-1); } } /* remove input */ ret = xmlSecBufferRemoveHead(in, inSize); if(ret < 0) { xmlSecInternalError2("xmlSecBufferRemoveHead", xmlSecTransformGetName(transform), "size=" XMLSEC_SIZE_FMT, inSize); return(-1); } inSize = 0; } if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) { xmlSecAssert2(outSize == 0, -1); if(transform->operation == xmlSecTransformOperationSign) { ret = xmlSecGnuTLSSignatureSign(transform, ctx, out, transformCtx); if(ret < 0) { xmlSecInternalError("xmlSecGnuTLSSignatureSign", xmlSecTransformGetName(transform)); return(-1); } } transform->status = xmlSecTransformStatusFinished; } if((transform->status == xmlSecTransformStatusWorking) || (transform->status == xmlSecTransformStatusFinished)) { /* the only way we can get here is if there is no input */ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); } else { xmlSecInvalidTransfromStatusError(transform); return(-1); } return(0); } /* Helper macros to define the transform klass */ #define XMLSEC_GNUTLS_SIGNATURE_KLASS_EX(name, readNode) \ static xmlSecTransformKlass xmlSecGnuTLS ## name ## Klass = { \ sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ \ xmlSecGnuTLSSignatureSize, /* xmlSecSize objSize */ \ xmlSecName ## name, /* const xmlChar* name; */ \ xmlSecHref ## name, /* const xmlChar* href; */ \ xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ \ xmlSecGnuTLSSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ \ xmlSecGnuTLSSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ \ readNode, /* xmlSecTransformNodeReadMethod readNode; */ \ NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ \ xmlSecGnuTLSSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ \ xmlSecGnuTLSSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ \ xmlSecGnuTLSSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ \ xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ \ xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ \ xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ \ NULL, /* xmlSecTransformPushXmlMethod pushXml; */ \ NULL, /* xmlSecTransformPopXmlMethod popXml; */ \ xmlSecGnuTLSSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ \ NULL, /* void* reserved0; */ \ NULL, /* void* reserved1; */ \ }; #define XMLSEC_GNUTLS_SIGNATURE_KLASS(name) \ XMLSEC_GNUTLS_SIGNATURE_KLASS_EX(name, NULL) /* DSA */ #ifndef XMLSEC_NO_DSA #ifndef XMLSEC_NO_SHA1 /****************************************************************************** * * DSA-SHA1 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(DsaSha1) /** * @brief The DSA-SHA1 signature transform klass. * @return DSA-SHA1 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformDsaSha1GetKlass(void) { return(&xmlSecGnuTLSDsaSha1Klass); } #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA256 /****************************************************************************** * * DSA-SHA2-256 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(DsaSha256) /** * @brief The DSA-SHA2-256 signature transform klass. * @return DSA-SHA2-256 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformDsaSha256GetKlass(void) { return(&xmlSecGnuTLSDsaSha256Klass); } #endif /* XMLSEC_NO_SHA256 */ #endif /* XMLSEC_NO_DSA */ /* EC */ #ifndef XMLSEC_NO_EC /* * https://www.w3.org/TR/xmldsig-core1/#sec-ECDSA * * The output of the ECDSA algorithm consists of a pair of integers usually referred by the pair (r, s). * The signature value consists of the base64 encoding of the concatenation of two octet-streams that respectively * result from the octet-encoding of the values r and s in that order. Integer to octet-stream conversion must * be done according to the I2OSP operation defined in the RFC 3447 [PKCS1] specification with the l parameter equal * to the size of the base point order of the curve in bytes (e.g. 32 for the P-256 curve and 66 for the P-521 curve). */ #ifndef XMLSEC_NO_SHA1 /****************************************************************************** * * ECDSA-SHA1 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha1) /** * @brief The ECDSA-SHA1 signature transform klass. * @return ECDSA-SHA1 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha1GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha1Klass); } #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA224 /****************************************************************************** * * ECDSA-SHA2-224 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha224) /** * @brief The ECDSA-SHA2-224 signature transform klass. * @return ECDSA-SHA2-224 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha224GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha224Klass); } #endif /* XMLSEC_NO_SHA224 */ #ifndef XMLSEC_NO_SHA256 /****************************************************************************** * * ECDSA-SHA2-256 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha256) /** * @brief The ECDSA-SHA2-256 signature transform klass. * @return ECDSA-SHA2-256 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha256GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha256Klass); } #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 /****************************************************************************** * * ECDSA-SHA2-384 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha384) /** * @brief The ECDSA-SHA2-384 signature transform klass. * @return ECDSA-SHA2-384 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha384GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha384Klass); } #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 /****************************************************************************** * * ECDSA-SHA2-512 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha512) /** * @brief The ECDSA-SHA2-512 signature transform klass. * @return ECDSA-SHA2-512 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha512GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha512Klass); } #endif /* XMLSEC_NO_SHA512 */ #ifndef XMLSEC_NO_SHA3 /****************************************************************************** * * ECDSA-SHA3-224 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha3_224) /** * @brief The ECDSA-SHA3-224 signature transform klass. * @return ECDSA-SHA3-224 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha3_224GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha3_224Klass); } /****************************************************************************** * * ECDSA-SHA3-256 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha3_256) /** * @brief The ECDSA-SHA3-256 signature transform klass. * @return ECDSA-SHA3-256 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha3_256GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha3_256Klass); } /****************************************************************************** * * ECDSA-SHA3-384 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha3_384) /** * @brief The ECDSA-SHA3-384 signature transform klass. * @return ECDSA-SHA3-384 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha3_384GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha3_384Klass); } /****************************************************************************** * * ECDSA-SHA3-512 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EcdsaSha3_512) /** * @brief The ECDSA-SHA3-512 signature transform klass. * @return ECDSA-SHA3-512 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEcdsaSha3_512GetKlass(void) { return(&xmlSecGnuTLSEcdsaSha3_512Klass); } #endif /* XMLSEC_NO_SHA3 */ #endif /* XMLSEC_NO_EC */ /* GOST 2001 */ #ifndef XMLSEC_NO_GOST /****************************************************************************** * * GOST2001 GOSTR3411_94 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(Gost2001GostR3411_94) /** * @brief GOST2001 GOSTR3411_94 signature transform klass. * @details The GOST2001 GOSTR3411_94 signature transform klass. * @return GOST2001 GOSTR3411_94 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformGost2001GostR3411_94GetKlass(void) { return(&xmlSecGnuTLSGost2001GostR3411_94Klass); } #endif /* XMLSEC_NO_GOST */ /* GOST 2012 */ #ifndef XMLSEC_NO_GOST2012 /****************************************************************************** * * GOST R 34.10-2012 - GOST R 34.11-2012 256 bit signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(GostR3410_2012GostR3411_2012_256) /** * @brief GOST R 34.10-2012 signature klass (256 bit). * @details The GOST R 34.10-2012 - GOST R 34.11-2012 256 bit signature transform klass. * @return GOST R 34.10-2012 - GOST R 34.11-2012 256 bit signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformGostR3410_2012GostR3411_2012_256GetKlass(void) { return(&xmlSecGnuTLSGostR3410_2012GostR3411_2012_256Klass); } /****************************************************************************** * * GOST R 34.10-2012 - GOST R 34.11-2012 512 bit signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(GostR3410_2012GostR3411_2012_512) /** * @brief GOST R 34.10-2012 signature klass (512 bit). * @details The GOST R 34.10-2012 - GOST R 34.11-2012 512 bit signature transform klass. * @return GOST R 34.10-2012 - GOST R 34.11-2012 512 bit signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformGostR3410_2012GostR3411_2012_512GetKlass(void) { return(&xmlSecGnuTLSGostR3410_2012GostR3411_2012_512Klass); } #endif /* XMLSEC_NO_GOST2012 */ /* RSA */ #ifndef XMLSEC_NO_RSA #ifndef XMLSEC_NO_SHA1 /****************************************************************************** * * RSA-SHA1 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaSha1) /** * @brief The RSA-SHA1 signature transform klass. * @return RSA-SHA1 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaSha1GetKlass(void) { return(&xmlSecGnuTLSRsaSha1Klass); } #endif /* XMLSEC_NO_SHA1 */ #ifndef XMLSEC_NO_SHA224 /****************************************************************************** * * RSA-SHA2-224 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaSha224) /** * @brief The RSA-SHA2-224 signature transform klass. * @return RSA-SHA2-224 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaSha224GetKlass(void) { return(&xmlSecGnuTLSRsaSha224Klass); } #endif /* XMLSEC_NO_SHA224 */ #ifndef XMLSEC_NO_SHA256 /****************************************************************************** * * RSA-SHA2-256 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaSha256) /** * @brief The RSA-SHA2-256 signature transform klass. * @return RSA-SHA2-256 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaSha256GetKlass(void) { return(&xmlSecGnuTLSRsaSha256Klass); } #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 /****************************************************************************** * * RSA-SHA2-384 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaSha384) /** * @brief The RSA-SHA2-384 signature transform klass. * @return RSA-SHA2-384 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaSha384GetKlass(void) { return(&xmlSecGnuTLSRsaSha384Klass); } #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 /****************************************************************************** * * RSA-SHA2-512 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaSha512) /** * @brief The RSA-SHA2-512 signature transform klass. * @return RSA-SHA2-512 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaSha512GetKlass(void) { return(&xmlSecGnuTLSRsaSha512Klass); } #endif /* XMLSEC_NO_SHA512 */ #ifndef XMLSEC_NO_SHA256 /****************************************************************************** * * RSA-PSS-SHA2-256 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaPssSha256) /** * @brief The RSA-PSS-SHA2-256 signature transform klass. * @return RSA-PSS-SHA2-256 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaPssSha256GetKlass(void) { return(&xmlSecGnuTLSRsaPssSha256Klass); } #endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_SHA384 /****************************************************************************** * * RSA-PSS-SHA2-384 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaPssSha384) /** * @brief The RSA-PSS-SHA2-384 signature transform klass. * @return RSA-PSS-SHA2-384 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaPssSha384GetKlass(void) { return(&xmlSecGnuTLSRsaPssSha384Klass); } #endif /* XMLSEC_NO_SHA384 */ #ifndef XMLSEC_NO_SHA512 /****************************************************************************** * * RSA-PSS-SHA2-512 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(RsaPssSha512) /** * @brief The RSA-PSS-SHA2-512 signature transform klass. * @return RSA-PSS-SHA2-512 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformRsaPssSha512GetKlass(void) { return(&xmlSecGnuTLSRsaPssSha512Klass); } #endif /* XMLSEC_NO_SHA512 */ #endif /* XMLSEC_NO_RSA */ /****************************************************************************** * * ML-DSA signatures * *****************************************************************************/ #ifndef XMLSEC_NO_MLDSA /****************************************************************************** * * ML-DSA-44 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(MLDSA44) /** * @brief The ML-DSA-44 signature transform klass. * @return ML-DSA-44 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformMLDSA44GetKlass(void) { return(&xmlSecGnuTLSMLDSA44Klass); } /****************************************************************************** * * ML-DSA-65 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(MLDSA65) /** * @brief The ML-DSA-65 signature transform klass. * @return ML-DSA-65 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformMLDSA65GetKlass(void) { return(&xmlSecGnuTLSMLDSA65Klass); } /****************************************************************************** * * ML-DSA-87 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(MLDSA87) /** * @brief The ML-DSA-87 signature transform klass. * @return ML-DSA-87 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformMLDSA87GetKlass(void) { return(&xmlSecGnuTLSMLDSA87Klass); } #endif /* XMLSEC_NO_MLDSA */ /****************************************************************************** * * EdDSA signatures * *****************************************************************************/ #ifndef XMLSEC_NO_EDDSA /****************************************************************************** * * EdDSA-Ed25519 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EdDSAEd25519) /** * @brief The EdDSA-Ed25519 signature transform klass. * @return EdDSA-Ed25519 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEdDSAEd25519GetKlass(void) { return(&xmlSecGnuTLSEdDSAEd25519Klass); } /****************************************************************************** * * EdDSA-Ed448 signature transform * *****************************************************************************/ XMLSEC_GNUTLS_SIGNATURE_KLASS(EdDSAEd448) /** * @brief The EdDSA-Ed448 signature transform klass. * @return EdDSA-Ed448 signature transform klass. */ xmlSecTransformId xmlSecGnuTLSTransformEdDSAEd448GetKlass(void) { return(&xmlSecGnuTLSEdDSAEd448Klass); } #endif /* XMLSEC_NO_EDDSA */