mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-01-07 10:05:40 +00:00
Subdivide rsa_rsassa_pkcs1_v15_encode
Split the DigestInfo construction and the initial padding out of rsa_rsassa_pkcs1_v15_encode into their own functions.
This commit is contained in:
parent
ef3d613252
commit
8b586af38b
219
library/rsa.c
219
library/rsa.c
|
@ -1523,6 +1523,112 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
|
|||
* Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
|
||||
*/
|
||||
|
||||
/* Encode a hash into a DigestInfo structure as specified by PKCS#1
|
||||
* (RFC 8017, EMSA-PKCS1-v1_5-ENCODE step 2).
|
||||
* Write to the left of p and set *p to the leftmost byte written. */
|
||||
static int rsa_emsa_pkcs1_v15_encode_digestinfo( unsigned char **p,
|
||||
unsigned char *start,
|
||||
mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash,
|
||||
size_t hashlen )
|
||||
{
|
||||
const mbedtls_md_info_t *md_info;
|
||||
const char *oid;
|
||||
size_t oid_size;
|
||||
|
||||
if( md_alg == MBEDTLS_MD_NONE )
|
||||
{
|
||||
if( *p < start + hashlen )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
*p -= hashlen;
|
||||
memcpy( *p, hash, hashlen );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
md_info = mbedtls_md_info_from_type( md_alg );
|
||||
if( md_info == NULL )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
if( hashlen == 0 )
|
||||
hashlen = mbedtls_md_get_size( md_info );
|
||||
else if ( hashlen != mbedtls_md_get_size( md_info ) )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
/* Double-check that 8 + hashlen + oid_size can be used as a
|
||||
* 1-byte ASN.1 length encoding and that there's no overflow. */
|
||||
if( 8 + hashlen + oid_size >= 0x80 ||
|
||||
10 + hashlen < hashlen ||
|
||||
10 + hashlen + oid_size < 10 + hashlen )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* Static bounds check:
|
||||
* - Need 10 bytes for five tag-length pairs.
|
||||
* (Insist on 1-byte length encodings to protect against variants of
|
||||
* Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
|
||||
* - Need hashlen bytes for hash
|
||||
* - Need oid_size bytes for hash alg OID.
|
||||
*/
|
||||
if( *p < start + 10 + oid_size + hashlen )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
*p -= 10 + oid_size + hashlen;
|
||||
start = *p;
|
||||
|
||||
/* Signing hashed data, add corresponding ASN.1 structure
|
||||
*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm DigestAlgorithmIdentifier,
|
||||
* digest Digest }
|
||||
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||
* Digest ::= OCTET STRING
|
||||
*
|
||||
* Schematic:
|
||||
* TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ]
|
||||
* TAG-NULL + LEN [ NULL ] ]
|
||||
* TAG-OCTET + LEN [ HASH ] ]
|
||||
*/
|
||||
*start++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
|
||||
*start++ = (unsigned char)( 0x08 + oid_size + hashlen );
|
||||
*start++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
|
||||
*start++ = (unsigned char)( 0x04 + oid_size );
|
||||
*start++ = MBEDTLS_ASN1_OID;
|
||||
*start++ = (unsigned char) oid_size;
|
||||
memcpy( start, oid, oid_size );
|
||||
start += oid_size;
|
||||
*start++ = MBEDTLS_ASN1_NULL;
|
||||
*start++ = 0x00;
|
||||
*start++ = MBEDTLS_ASN1_OCTET_STRING;
|
||||
*start++ = (unsigned char) hashlen;
|
||||
memcpy( start, hash, hashlen );
|
||||
start += hashlen;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Pad data as specified by PKCS#1
|
||||
* (RFC 8017, EMSA-PKCS1-v1_5-ENCODE steps 3-5 without T). */
|
||||
static int rsa_rsassa_pkcs1_v15_encode_pad( unsigned char *p,
|
||||
size_t nb_pad )
|
||||
{
|
||||
/* Need space for signature header and padding delimiter (3 bytes),
|
||||
* and 8 bytes for the minimal padding */
|
||||
if( nb_pad < 3 + 8 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
nb_pad -= 3;
|
||||
|
||||
/* Now nb_pad is the amount of memory to be filled
|
||||
* with padding, and at least 8 bytes long. */
|
||||
|
||||
/* Write signature header and padding */
|
||||
*p++ = 0;
|
||||
*p++ = MBEDTLS_RSA_SIGN;
|
||||
memset( p, 0xFF, nb_pad );
|
||||
p += nb_pad;
|
||||
*p++ = 0;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Construct a PKCS v1.5 encoding of a hashed message
|
||||
*
|
||||
* This is used both for signature generation and verification.
|
||||
|
@ -1547,107 +1653,24 @@ static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg,
|
|||
size_t dst_len,
|
||||
unsigned char *dst )
|
||||
{
|
||||
size_t oid_size = 0;
|
||||
size_t nb_pad = dst_len;
|
||||
unsigned char *p = dst;
|
||||
const char *oid = NULL;
|
||||
int ret;
|
||||
unsigned char *p = dst + dst_len;
|
||||
|
||||
/* Are we signing hashed or raw data? */
|
||||
/* Ignore hashlen if a hash algorithm is specified. This is
|
||||
* fragile, but documented, bhavior. */
|
||||
if( md_alg != MBEDTLS_MD_NONE )
|
||||
hashlen = 0;
|
||||
|
||||
ret = rsa_emsa_pkcs1_v15_encode_digestinfo( &p, dst,
|
||||
md_alg, hash, hashlen );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = rsa_rsassa_pkcs1_v15_encode_pad( dst, p - dst );
|
||||
if( ret != 0 )
|
||||
{
|
||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
|
||||
if( md_info == NULL )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
hashlen = mbedtls_md_get_size( md_info );
|
||||
|
||||
/* Double-check that 8 + hashlen + oid_size can be used as a
|
||||
* 1-byte ASN.1 length encoding and that there's no overflow. */
|
||||
if( 8 + hashlen + oid_size >= 0x80 ||
|
||||
10 + hashlen < hashlen ||
|
||||
10 + hashlen + oid_size < 10 + hashlen )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* Static bounds check:
|
||||
* - Need 10 bytes for five tag-length pairs.
|
||||
* (Insist on 1-byte length encodings to protect against variants of
|
||||
* Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
|
||||
* - Need hashlen bytes for hash
|
||||
* - Need oid_size bytes for hash alg OID.
|
||||
*/
|
||||
if( nb_pad < 10 + hashlen + oid_size )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
nb_pad -= 10 + hashlen + oid_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nb_pad < hashlen )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
nb_pad -= hashlen;
|
||||
}
|
||||
|
||||
/* Need space for signature header and padding delimiter (3 bytes),
|
||||
* and 8 bytes for the minimal padding */
|
||||
if( nb_pad < 3 + 8 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
nb_pad -= 3;
|
||||
|
||||
/* Now nb_pad is the amount of memory to be filled
|
||||
* with padding, and at least 8 bytes long. */
|
||||
|
||||
/* Write signature header and padding */
|
||||
*p++ = 0;
|
||||
*p++ = MBEDTLS_RSA_SIGN;
|
||||
memset( p, 0xFF, nb_pad );
|
||||
p += nb_pad;
|
||||
*p++ = 0;
|
||||
|
||||
/* Are we signing raw data? */
|
||||
if( md_alg == MBEDTLS_MD_NONE )
|
||||
{
|
||||
memcpy( p, hash, hashlen );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Signing hashed data, add corresponding ASN.1 structure
|
||||
*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm DigestAlgorithmIdentifier,
|
||||
* digest Digest }
|
||||
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||
* Digest ::= OCTET STRING
|
||||
*
|
||||
* Schematic:
|
||||
* TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ]
|
||||
* TAG-NULL + LEN [ NULL ] ]
|
||||
* TAG-OCTET + LEN [ HASH ] ]
|
||||
*/
|
||||
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
|
||||
*p++ = (unsigned char)( 0x08 + oid_size + hashlen );
|
||||
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
|
||||
*p++ = (unsigned char)( 0x04 + oid_size );
|
||||
*p++ = MBEDTLS_ASN1_OID;
|
||||
*p++ = (unsigned char) oid_size;
|
||||
memcpy( p, oid, oid_size );
|
||||
p += oid_size;
|
||||
*p++ = MBEDTLS_ASN1_NULL;
|
||||
*p++ = 0x00;
|
||||
*p++ = MBEDTLS_ASN1_OCTET_STRING;
|
||||
*p++ = (unsigned char) hashlen;
|
||||
memcpy( p, hash, hashlen );
|
||||
p += hashlen;
|
||||
|
||||
/* Just a sanity-check, should be automatic
|
||||
* after the initial bounds check. */
|
||||
if( p != dst + dst_len )
|
||||
{
|
||||
mbedtls_zeroize( dst, dst_len );
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
memset( dst, 0, dst_len );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
|
|
Loading…
Reference in a new issue