mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-05-01 19:56:25 +00:00
Fix ASN1 bitstring writing
Refactor the function mbedtls_asn1_write_bitstring() that removes trailing 0s at the end of DER encoded bitstrings. The function is implemented according to Hanno Becker's suggestions. This commit also changes the functions x509write_crt_set_ns_cert_type and crt_set_key_usage to call the new function as the use named bitstrings instead of the regular bitstrings.
This commit is contained in:
parent
bdc807dbe8
commit
04ee5e0bbd
|
@ -204,9 +204,10 @@ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
|
||||||
const unsigned char *buf, size_t bits );
|
const unsigned char *buf, size_t bits );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and
|
* \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
|
||||||
* value in ASN.1 format
|
* and value in ASN.1 format.
|
||||||
* Note: function works backwards in data buffer
|
*
|
||||||
|
* \note This function works backwards in data buffer.
|
||||||
*
|
*
|
||||||
* \param p reference to current position pointer
|
* \param p reference to current position pointer
|
||||||
* \param start start of the buffer (for bounds-checking)
|
* \param start start of the buffer (for bounds-checking)
|
||||||
|
|
|
@ -294,22 +294,28 @@ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
|
||||||
const unsigned char *buf, size_t bits )
|
const unsigned char *buf, size_t bits )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
size_t len = 0, size;
|
size_t len = 0;
|
||||||
|
size_t unused_bits, byte_len;
|
||||||
|
|
||||||
size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
|
byte_len = ( bits + 7 ) / 8;
|
||||||
|
unused_bits = ( byte_len * 8 ) - bits;
|
||||||
|
|
||||||
// Calculate byte length
|
if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
|
||||||
//
|
|
||||||
if( *p < start || (size_t)( *p - start ) < size + 1 )
|
|
||||||
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||||
|
|
||||||
len = size + 1;
|
len = byte_len + 1;
|
||||||
(*p) -= size;
|
|
||||||
memcpy( *p, buf, size );
|
|
||||||
|
|
||||||
// Write unused bits
|
/* Write the bitstring. Ensure the unused bits are zeroed */
|
||||||
//
|
if( byte_len > 0 )
|
||||||
*--(*p) = (unsigned char) (size * 8 - bits);
|
{
|
||||||
|
byte_len--;
|
||||||
|
*--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
|
||||||
|
( *p ) -= byte_len;
|
||||||
|
memcpy( *p, buf, byte_len );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write unused bits */
|
||||||
|
*--( *p ) = (unsigned char)unused_bits;
|
||||||
|
|
||||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
|
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
|
||||||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
|
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
|
||||||
|
|
|
@ -222,26 +222,51 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_SHA1_C */
|
#endif /* MBEDTLS_SHA1_C */
|
||||||
|
|
||||||
|
static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring,
|
||||||
|
size_t bit_offset )
|
||||||
|
{
|
||||||
|
size_t unused_bits;
|
||||||
|
|
||||||
|
/* Count the unused bits removing trailing 0s */
|
||||||
|
for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
|
||||||
|
if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
return( unused_bits );
|
||||||
|
}
|
||||||
|
|
||||||
int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
|
int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
|
||||||
unsigned int key_usage )
|
unsigned int key_usage )
|
||||||
{
|
{
|
||||||
unsigned char buf[4], ku;
|
unsigned char buf[4], ku;
|
||||||
unsigned char *c;
|
unsigned char *c;
|
||||||
int ret;
|
int ret;
|
||||||
|
size_t unused_bits;
|
||||||
|
const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
|
||||||
|
MBEDTLS_X509_KU_NON_REPUDIATION |
|
||||||
|
MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
|
||||||
|
MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
|
||||||
|
MBEDTLS_X509_KU_KEY_AGREEMENT |
|
||||||
|
MBEDTLS_X509_KU_KEY_CERT_SIGN |
|
||||||
|
MBEDTLS_X509_KU_CRL_SIGN;
|
||||||
|
|
||||||
/* We currently only support 7 bits, from 0x80 to 0x02 */
|
/* Check that nothing other than the allowed flags is set */
|
||||||
if( ( key_usage & ~0xfe ) != 0 )
|
if( ( key_usage & ~allowed_bits ) != 0 )
|
||||||
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
|
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
|
||||||
|
|
||||||
c = buf + 4;
|
c = buf + 4;
|
||||||
ku = (unsigned char) key_usage;
|
ku = (unsigned char)key_usage;
|
||||||
|
unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 );
|
||||||
|
ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits );
|
||||||
|
|
||||||
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 )
|
if( ret < 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
else if( ret < 3 || ret > 4 )
|
||||||
|
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
|
||||||
|
|
||||||
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
|
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
|
||||||
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
|
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
|
||||||
1, buf, 4 );
|
1, c, (size_t)ret );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
|
@ -253,16 +278,22 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
|
||||||
{
|
{
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
unsigned char *c;
|
unsigned char *c;
|
||||||
|
size_t unused_bits;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
c = buf + 4;
|
c = buf + 4;
|
||||||
|
|
||||||
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
|
unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
|
||||||
|
ret = mbedtls_asn1_write_bitstring( &c,
|
||||||
|
buf,
|
||||||
|
&ns_cert_type,
|
||||||
|
8 - unused_bits );
|
||||||
|
if( ret < 3 || ret > 4 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
|
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
|
||||||
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
|
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
|
||||||
0, buf, 4 );
|
0, c, (size_t)ret );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
|
|
|
@ -85,20 +85,39 @@ int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
|
||||||
0, val, val_len );
|
0, val, val_len );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring,
|
||||||
|
size_t bit_offset )
|
||||||
|
{
|
||||||
|
size_t unused_bits;
|
||||||
|
|
||||||
|
/* Count the unused bits removing trailing 0s */
|
||||||
|
for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
|
||||||
|
if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
return( unused_bits );
|
||||||
|
}
|
||||||
|
|
||||||
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
|
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
|
||||||
{
|
{
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
unsigned char *c;
|
unsigned char *c;
|
||||||
|
size_t unused_bits;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
c = buf + 4;
|
c = buf + 4;
|
||||||
|
|
||||||
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
|
unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 );
|
||||||
|
ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits );
|
||||||
|
|
||||||
|
if( ret < 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
else if( ret < 3 || ret > 4 )
|
||||||
|
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
|
||||||
|
|
||||||
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
|
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
|
||||||
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
|
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
|
||||||
buf, 4 );
|
c, (size_t)ret );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
|
@ -110,16 +129,25 @@ int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
|
||||||
{
|
{
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
unsigned char *c;
|
unsigned char *c;
|
||||||
|
size_t unused_bits;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
c = buf + 4;
|
c = buf + 4;
|
||||||
|
|
||||||
if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
|
unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
|
||||||
|
ret = mbedtls_asn1_write_bitstring( &c,
|
||||||
|
buf,
|
||||||
|
&ns_cert_type,
|
||||||
|
8 - unused_bits );
|
||||||
|
|
||||||
|
if( ret < 0 )
|
||||||
|
return( ret );
|
||||||
|
else if( ret < 3 || ret > 4 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
|
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
|
||||||
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
|
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
|
||||||
buf, 4 );
|
c, (size_t)ret );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue