From 72849877d0534f8fdb88b8772bcc4ae74987846d Mon Sep 17 00:00:00 2001 From: Andres AG Date: Thu, 19 Jan 2017 11:24:33 +0000 Subject: [PATCH] Fix data loss in unsigned int cast in PK This patch introduces some additional checks in the PK module for 64-bit systems only. The problem is that the API functions in the PK abstraction accept a size_t value for the hashlen, while the RSA module accepts an unsigned int for the hashlen. Instead of silently casting size_t to unsigned int, this change checks whether the hashlen overflows an unsigned int and returns an error. --- library/pk.c | 11 ++++++++++- library/pk_wrap.c | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/library/pk.c b/library/pk.c index 10bd0a582..8d13bc5ce 100644 --- a/library/pk.c +++ b/library/pk.c @@ -29,6 +29,8 @@ #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" +#include "mbedtls/bignum.h" + #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif @@ -39,6 +41,8 @@ #include "mbedtls/ecdsa.h" #endif +#include + /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; @@ -209,6 +213,11 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, int ret; const mbedtls_pk_rsassa_pss_options *pss_opts; +#if defined(MBEDTLS_HAVE_INT64) + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + if( options == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -232,7 +241,7 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, return( 0 ); #else return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); -#endif +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* General case: no options */ diff --git a/library/pk_wrap.c b/library/pk_wrap.c index 712ad4832..db6274cbf 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -30,6 +30,7 @@ /* Even if RSA not activated, for the sake of RSA-alt */ #include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" #include @@ -49,6 +50,8 @@ #define mbedtls_free free #endif +#include + #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { @@ -74,6 +77,11 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, { int ret; +#if defined(MBEDTLS_HAVE_INT64) + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + if( sig_len < ((mbedtls_rsa_context *) ctx)->len ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); @@ -93,6 +101,11 @@ static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { +#if defined(MBEDTLS_HAVE_INT64) + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + *sig_len = ((mbedtls_rsa_context *) ctx)->len; return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, @@ -402,6 +415,11 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, { mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; +#if defined(MBEDTLS_HAVE_INT64) + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,