From 34b349675af9f72eb822837a8772cc1ead7115c7 Mon Sep 17 00:00:00 2001 From: Aleksey Sanin <aleksey@aleksey.com> Date: Mon, 15 Jun 2009 17:45:36 +0000 Subject: Fixed HMAC vuln with small values of HMAC length --- diff --git a/include/xmlsec/gnutls/crypto.h b/include/xmlsec/gnutls/crypto.h index dd80436..f7fbbad 100644 --- a/include/xmlsec/gnutls/crypto.h +++ b/include/xmlsec/gnutls/crypto.h @@ -113,6 +113,10 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecGnuTLSTransformDes3CbcGetKlass(void * *******************************************************************/ #ifndef XMLSEC_NO_HMAC + +XMLSEC_CRYPTO_EXPORT int xmlSecGnuTLSHmacGetMinOutputLength(); +XMLSEC_CRYPTO_EXPORT void xmlSecGnuTLSHmacSetMinOutputLength(int min_length); + /** * xmlSecGnuTLSKeyDataHmacId: * diff --git a/include/xmlsec/nss/crypto.h b/include/xmlsec/nss/crypto.h index f1cd44e..381ee1f 100644 --- a/include/xmlsec/nss/crypto.h +++ b/include/xmlsec/nss/crypto.h @@ -191,6 +191,10 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecNssTransformDsaSha1GetKlass(void); * *******************************************************************/ #ifndef XMLSEC_NO_HMAC + +XMLSEC_CRYPTO_EXPORT int xmlSecNssHmacGetMinOutputLength(); +XMLSEC_CRYPTO_EXPORT void xmlSecNssHmacSetMinOutputLength(int min_length); + /** * xmlSecNssKeyDataHmacId: * diff --git a/include/xmlsec/openssl/crypto.h b/include/xmlsec/openssl/crypto.h index 2274e35..3b50b40 100644 --- a/include/xmlsec/openssl/crypto.h +++ b/include/xmlsec/openssl/crypto.h @@ -200,6 +200,10 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecOpenSSLTransformDsaSha1GetKlass(voi * *******************************************************************/ #ifndef XMLSEC_NO_HMAC + +XMLSEC_CRYPTO_EXPORT int xmlSecOpenSSLHmacGetMinOutputLength(); +XMLSEC_CRYPTO_EXPORT void xmlSecOpenSSLHmacSetMinOutputLength(int min_length); + /** * xmlSecOpenSSLKeyDataHmacId: * diff --git a/src/gnutls/hmac.c b/src/gnutls/hmac.c index 1119110..5a0940c 100644 --- a/src/gnutls/hmac.c +++ b/src/gnutls/hmac.c @@ -23,10 +23,40 @@ #include <xmlsec/gnutls/app.h> #include <xmlsec/gnutls/crypto.h> +#define XMLSEC_GNUTLS_MIN_HMAC_SIZE 64 #define XMLSEC_GNUTLS_MAX_HMAC_SIZE 128 /************************************************************************** * + * Configuration + * + *****************************************************************************/ +static int g_xmlsec_gnutls_hmac_min_length = XMLSEC_GNUTLS_MIN_HMAC_SIZE; + +/** + * xmlSecGnuTLSHmacGetMinOutputLength: + * + * Returns the min HMAC output length + */ +int xmlSecGnuTLSHmacGetMinOutputLength() +{ + return g_xmlsec_gnutls_hmac_min_length; +} + +/** + * xmlSecGnuTLSHmacSetMinOutputLength: + * + * @min_length: the new min length + * + * Sets the min HMAC output length + */ +void xmlSecGnuTLSHmacSetMinOutputLength(int min_length) +{ + g_xmlsec_gnutls_hmac_min_length = min_length; +} + +/************************************************************************** + * * Internal GNUTLS HMAC CTX * *****************************************************************************/ @@ -178,7 +208,20 @@ xmlSecGnuTLSHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTr ctx->dgstSize = atoi((char*)content); xmlFree(content); } - /* todo: error if dgstSize == 0 ?*/ + + /* Ensure that HMAC length is greater than min specified. + Otherwise, an attacker can set this lenght to 0 or very + small value + */ + if(ctx->dgstSize < xmlSecGnuTLSHmacGetMinOutputLength()) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecNodeHMACOutputLength, + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, + "HMAC output length is too small"); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); } diff --git a/src/nss/hmac.c b/src/nss/hmac.c index f67ec9d..a7c2018 100644 --- a/src/nss/hmac.c +++ b/src/nss/hmac.c @@ -26,10 +26,40 @@ #include <xmlsec/nss/app.h> #include <xmlsec/nss/crypto.h> +#define XMLSEC_NSS_MIN_HMAC_SIZE 64 #define XMLSEC_NSS_MAX_HMAC_SIZE 128 /************************************************************************** * + * Configuration + * + *****************************************************************************/ +static int g_xmlsec_nss_hmac_min_length = XMLSEC_NSS_MIN_HMAC_SIZE; + +/** + * xmlSecNssHmacGetMinOutputLength: + * + * Returns the min HMAC output length + */ +int xmlSecNssHmacGetMinOutputLength() +{ + return g_xmlsec_nss_hmac_min_length; +} + +/** + * xmlSecNssHmacSetMinOutputLength: + * + * @min_length: the new min length + * + * Sets the min HMAC output length + */ +void xmlSecNssHmacSetMinOutputLength(int min_length) +{ + g_xmlsec_nss_hmac_min_length = min_length; +} + +/************************************************************************** + * * Internal NSS HMAC CTX * *****************************************************************************/ @@ -162,7 +192,20 @@ xmlSecNssHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTrans ctx->dgstSize = atoi((char*)content); xmlFree(content); } - /* todo: error if dgstSize == 0 ?*/ + + /* Ensure that HMAC length is greater than min specified. + Otherwise, an attacker can set this lenght to 0 or very + small value + */ + if(ctx->dgstSize < xmlSecNssHmacGetMinOutputLength()) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecNodeHMACOutputLength, + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, + "HMAC output length is too small"); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); } diff --git a/src/openssl/hmac.c b/src/openssl/hmac.c index 492663b..76fca0e 100644 --- a/src/openssl/hmac.c +++ b/src/openssl/hmac.c @@ -32,6 +32,36 @@ #include <xmlsec/openssl/crypto.h> +#define XMLSEC_OPENSSL_MIN_HMAC_SIZE 64 + +/************************************************************************** + * + * Configuration + * + *****************************************************************************/ +static int g_xmlsec_openssl_hmac_min_length = XMLSEC_OPENSSL_MIN_HMAC_SIZE; + +/** + * xmlSecOpenSSLHmacGetMinOutputLength: + * + * Returns the min HMAC output length + */ +int xmlSecOpenSSLHmacGetMinOutputLength() +{ + return g_xmlsec_openssl_hmac_min_length; +} + +/** + * xmlSecOpenSSLHmacSetMinOutputLength: + * + * @min_length: the new min length + * + * Sets the min HMAC output length + */ +void xmlSecOpenSSLHmacSetMinOutputLength(int min_length) +{ + g_xmlsec_openssl_hmac_min_length = min_length; +} /************************************************************************** * @@ -240,7 +270,20 @@ xmlSecOpenSSLHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecT ctx->dgstSize = atoi((char*)content); xmlFree(content); } - /* todo: error if dgstSize == 0 ?*/ + + /* Ensure that HMAC length is greater than min specified. + Otherwise, an attacker can set this lenght to 0 or very + small value + */ + if(ctx->dgstSize < xmlSecOpenSSLHmacGetMinOutputLength()) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + xmlSecNodeHMACOutputLength, + XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, + "HMAC output length is too small"); + return(-1); + } + cur = xmlSecGetNextElementNode(cur->next); }