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.
This commit is contained in:
Paul Bakker 2014-03-26 14:53:47 +01:00
parent 91c61bc4fd
commit db1f05985e

View File

@ -165,7 +165,7 @@ int pkcs11_sign( pkcs11_context *ctx,
const unsigned char *hash, const unsigned char *hash,
unsigned char *sig ) 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; unsigned char *p = sig;
const char *oid; const char *oid;
@ -175,8 +175,6 @@ int pkcs11_sign( pkcs11_context *ctx,
if( RSA_PRIVATE != mode ) if( RSA_PRIVATE != mode )
return POLARSSL_ERR_RSA_BAD_INPUT_DATA; return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
olen = ctx->len;
if( md_alg != POLARSSL_MD_NONE ) if( md_alg != POLARSSL_MD_NONE )
{ {
const md_info_t *md_info = md_info_from_type( md_alg ); 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 ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
hashlen = md_get_size( md_info ); 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 { * DigestInfo ::= SEQUENCE {
@ -216,15 +218,12 @@ int pkcs11_sign( pkcs11_context *ctx,
*p++ = 0x00; *p++ = 0x00;
*p++ = ASN1_OCTET_STRING; *p++ = ASN1_OCTET_STRING;
*p++ = hashlen; *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, 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 ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
} }