From db1f05985e035a3d1eb5eec805aa5ee9b94521e2 Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Wed, 26 Mar 2014 14:53:47 +0100
Subject: [PATCH] Add a check for buffer overflow to pkcs11_sign()
pkcs11_sign() reuses *sig to store the header and hash, but those might
be larger than the actual sig, causing a buffer overflow.
An overflow can occur when using raw sigs with hashlen > siglen, or when
the RSA key is less than 664 bits long (or less when using hashes
shorter than SHA512)
As siglen is always within the 'low realm' < 32k, an overflow of asnlen
+ hashlen is not possible.
---
library/pkcs11.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/library/pkcs11.c b/library/pkcs11.c
index d758460e3..054fdb783 100644
--- a/library/pkcs11.c
+++ b/library/pkcs11.c
@@ -165,7 +165,7 @@ int pkcs11_sign( pkcs11_context *ctx,
const unsigned char *hash,
unsigned char *sig )
{
- size_t olen, asn_len = 0, oid_size = 0;
+ size_t sig_len = 0, asn_len = 0, oid_size = 0;
unsigned char *p = sig;
const char *oid;
@@ -175,8 +175,6 @@ int pkcs11_sign( pkcs11_context *ctx,
if( RSA_PRIVATE != mode )
return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
- olen = ctx->len;
-
if( md_alg != POLARSSL_MD_NONE )
{
const md_info_t *md_info = md_info_from_type( md_alg );
@@ -187,13 +185,17 @@ int pkcs11_sign( pkcs11_context *ctx,
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
hashlen = md_get_size( md_info );
+ asn_len = 10 + oid_size;
}
- if( md_alg == POLARSSL_MD_NONE )
+ sig_len = ctx->len;
+ if ( hashlen > ctx_len || asn_len > sig_len ||
+ hashlen + asn_len > sig_len )
{
- memcpy( p, hash, hashlen );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
- else
+
+ if( md_alg != POLARSSL_MD_NONE)
{
/*
* DigestInfo ::= SEQUENCE {
@@ -216,15 +218,12 @@ int pkcs11_sign( pkcs11_context *ctx,
*p++ = 0x00;
*p++ = ASN1_OCTET_STRING;
*p++ = hashlen;
-
- /* Determine added ASN length */
- asn_len = p - sig;
-
- memcpy( p, hash, hashlen );
}
+ memcpy( p, hash, hashlen );
+
if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
- asn_len + hashlen, sig, &olen ) != CKR_OK )
+ asn_len + hashlen, sig, &sig_len ) != CKR_OK )
{
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}