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 ); }