From 060c56871cf1b994748aa3bfe83ec75960b61f59 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 12 Jan 2009 21:48:39 +0000 Subject: [PATCH] - Fixed possible heap overflow in pkcs1_decrypt on data larger than output buffer after padding. For instance the premaster decryption in ssl_parse_client_key_exchange() in ssl_serv.c (Thanks to Christophe Devine) --- include/polarssl/rsa.h | 8 ++++++-- library/rsa.c | 9 +++++++-- library/ssl_srv.c | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/polarssl/rsa.h b/include/polarssl/rsa.h index abca193606..f02df5a8a4 100644 --- a/include/polarssl/rsa.h +++ b/include/polarssl/rsa.h @@ -31,6 +31,7 @@ #define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x0440 #define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x0450 #define POLARSSL_ERR_RSA_VERIFY_FAILED -0x0460 +#define POLARSSL_ERR_RSA_OUTPUT_TO_LARGE -0x0470 /* * PKCS#1 constants @@ -216,16 +217,19 @@ int rsa_pkcs1_encrypt( rsa_context *ctx, * \param input buffer holding the encrypted data * \param output buffer that will hold the plaintext * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer * * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code * * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. */ int rsa_pkcs1_decrypt( rsa_context *ctx, int mode, int *olen, unsigned char *input, - unsigned char *output ); + unsigned char *output, + int output_max_len); /** * \brief Do a private RSA to sign a message digest diff --git a/library/rsa.c b/library/rsa.c index 5236856b32..211de4edcc 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -328,7 +328,8 @@ int rsa_pkcs1_encrypt( rsa_context *ctx, int rsa_pkcs1_decrypt( rsa_context *ctx, int mode, int *olen, unsigned char *input, - unsigned char *output ) + unsigned char *output, + int output_max_len) { int ret, ilen; unsigned char *p; @@ -369,6 +370,9 @@ int rsa_pkcs1_decrypt( rsa_context *ctx, return( POLARSSL_ERR_RSA_INVALID_PADDING ); } + if (ilen - (int)(p - buf) > output_max_len) + return( POLARSSL_ERR_RSA_OUTPUT_TO_LARGE ); + *olen = ilen - (int)(p - buf); memcpy( output, p, *olen ); @@ -677,7 +681,8 @@ int rsa_self_test( int verbose ) printf( "passed\n PKCS#1 decryption : " ); if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted ) != 0 ) + rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) { if( verbose != 0 ) printf( "failed\n" ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index cb8d14002c..a8b90223b0 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -726,7 +726,8 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) } ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen, - ssl->in_msg + i, ssl->premaster ); + ssl->in_msg + i, ssl->premaster, + sizeof(ssl->premaster) ); if( ret != 0 || ssl->pmslen != 48 || ssl->premaster[0] != ssl->max_major_ver ||