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 ||