Commit e1160d90 authored by ROOL's avatar ROOL 🤖
Browse files

Library update

Detail:
  This is release 2.16.1 direct from ARM, with customisations to ro_config.h/timing.c/entropy_poll.c/net_sockets.[c|h] to port to RISC OS.
Admin:
  Submission for TCP/IP bounty.

Version 2.13. Tagged as 'mbedTLS-2_13'
parent c0c94bd8
/* (2.12)
/* (2.13)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 2.12
#define Module_MajorVersion_CMHG 2.13
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 27 Jan 2019
#define Module_Date_CMHG 30 Mar 2019
#define Module_MajorVersion "2.12"
#define Module_Version 212
#define Module_MajorVersion "2.13"
#define Module_Version 213
#define Module_MinorVersion ""
#define Module_Date "27 Jan 2019"
#define Module_Date "30 Mar 2019"
#define Module_ApplicationDate "27-Jan-19"
#define Module_ApplicationDate "30-Mar-19"
#define Module_ComponentName "mbedTLS"
#define Module_ComponentPath "apache/RiscOS/Sources/Lib/mbedTLS"
#define Module_FullVersion "2.12"
#define Module_HelpVersion "2.12 (27 Jan 2019)"
#define Module_LibraryVersionInfo "2:12"
#define Module_FullVersion "2.13"
#define Module_HelpVersion "2.13 (30 Mar 2019)"
#define Module_LibraryVersionInfo "2:13"
......@@ -294,22 +294,28 @@ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits )
{
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 ) < size + 1 )
if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
len = size + 1;
(*p) -= size;
memcpy( *p, buf, size );
len = byte_len + 1;
// Write unused bits
//
*--(*p) = (unsigned char) (size * 8 - bits);
/* Write the bitstring. Ensure the unused bits are zeroed */
if( byte_len > 0 )
{
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_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
......
......@@ -527,26 +527,38 @@ cleanup:
}
/*
* Helper to write the digits high-order first
* Helper to write the digits high-order first.
*/
static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
static int mpi_write_hlp( mbedtls_mpi *X, int radix,
char **p, const size_t buflen )
{
int ret;
mbedtls_mpi_uint r;
size_t length = 0;
char *p_end = *p + buflen;
if( radix < 2 || radix > 16 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
do
{
if( length >= buflen )
{
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
}
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
/*
* Write the residue in the current position, as an ASCII character.
*/
if( r < 0xA )
*(--p_end) = (char)( '0' + r );
else
*(--p_end) = (char)( 'A' + ( r - 0xA ) );
if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
length++;
} while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
if( r < 10 )
*(*p)++ = (char)( r + 0x30 );
else
*(*p)++ = (char)( r + 0x37 );
memmove( *p, p_end, length );
*p += length;
cleanup:
......@@ -619,7 +631,7 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
if( T.s == -1 )
T.s = 1;
MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
}
*p++ = '\0';
......@@ -715,14 +727,101 @@ cleanup:
}
#endif /* MBEDTLS_FS_IO */
/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
* into the storage form used by mbedtls_mpi. */
static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
{
uint8_t i;
mbedtls_mpi_uint tmp = 0;
/* This works regardless of the endianness. */
for( i = 0; i < ciL; i++, x >>= 8 )
tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
return( tmp );
}
static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
{
#if defined(__BYTE_ORDER__)
/* Nothing to do on bigendian systems. */
#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
return( x );
#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
/* For GCC and Clang, have builtins for byte swapping. */
#if defined(__GNUC__) && defined(__GNUC_PREREQ)
#if __GNUC_PREREQ(4,3)
#define have_bswap
#endif
#endif
#if defined(__clang__) && defined(__has_builtin)
#if __has_builtin(__builtin_bswap32) && \
__has_builtin(__builtin_bswap64)
#define have_bswap
#endif
#endif
#if defined(have_bswap)
/* The compiler is hopefully able to statically evaluate this! */
switch( sizeof(mbedtls_mpi_uint) )
{
case 4:
return( __builtin_bswap32(x) );
case 8:
return( __builtin_bswap64(x) );
}
#endif
#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
#endif /* __BYTE_ORDER__ */
/* Fall back to C-based reordering if we don't know the byte order
* or we couldn't use a compiler-specific builtin. */
return( mpi_uint_bigendian_to_host_c( x ) );
}
static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
{
mbedtls_mpi_uint *cur_limb_left;
mbedtls_mpi_uint *cur_limb_right;
if( limbs == 0 )
return;
/*
* Traverse limbs and
* - adapt byte-order in each limb
* - swap the limbs themselves.
* For that, simultaneously traverse the limbs from left to right
* and from right to left, as long as the left index is not bigger
* than the right index (it's not a problem if limbs is odd and the
* indices coincide in the last iteration).
*/
for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
cur_limb_left <= cur_limb_right;
cur_limb_left++, cur_limb_right-- )
{
mbedtls_mpi_uint tmp;
/* Note that if cur_limb_left == cur_limb_right,
* this code effectively swaps the bytes only once. */
tmp = mpi_uint_bigendian_to_host( *cur_limb_left );
*cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right );
*cur_limb_right = tmp;
}
}
/*
* Import X from unsigned binary data, big endian
*/
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
{
int ret;
size_t i, j;
size_t const limbs = CHARS_TO_LIMBS( buflen );
size_t const limbs = CHARS_TO_LIMBS( buflen );
size_t const overhead = ( limbs * ciL ) - buflen;
unsigned char *Xp;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
......@@ -734,11 +833,17 @@ int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t bu
mbedtls_mpi_init( X );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
}
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
for( i = buflen, j = 0; i > 0; i--, j++ )
X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
/* Avoid calling `memcpy` with NULL source argument,
* even if buflen is 0. */
if( buf != NULL )
{
Xp = (unsigned char*) X->p;
memcpy( Xp + overhead, buf, buflen );
mpi_bigendian_to_host( X->p, limbs );
}
cleanup:
......@@ -2008,18 +2113,28 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
void *p_rng )
{
int ret;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
size_t const limbs = CHARS_TO_LIMBS( size );
size_t const overhead = ( limbs * ciL ) - size;
unsigned char *Xp;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( f_rng != NULL );
if( size > MBEDTLS_MPI_MAX_SIZE )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
/* Ensure that target MPI has exactly the necessary number of limbs */
if( X->n != limbs )
{
mbedtls_mpi_free( X );
mbedtls_mpi_init( X );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
}
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
Xp = (unsigned char*) X->p;
f_rng( p_rng, Xp + overhead, size );
MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
mpi_bigendian_to_host( X->p, limbs );
cleanup:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
return( ret );
}
......
......@@ -800,11 +800,16 @@ cleanup:
int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = 0;
ECDSA_VALIDATE_RET( ctx != NULL );
ECDSA_VALIDATE_RET( f_rng != NULL );
return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
ret = mbedtls_ecp_group_load( &ctx->grp, gid );
if( ret != 0 )
return( ret );
return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d,
&ctx->Q, f_rng, p_rng ) );
}
#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
......
......@@ -43,11 +43,11 @@
/*
* Ordered from most preferred to least preferred in terms of security.
*
* Current rule (except rc4, weak and null which come last):
* Current rule (except RC4 and 3DES, weak and null which come last):
* 1. By key exchange:
* Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK
* 2. By key length and cipher:
* ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
* ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128
* 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8
* 4. By hash function used when relevant
* 5. By key exchange/auth again: EC > non-EC
......@@ -126,11 +126,6 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
/* All remaining >= 128-bit ephemeral suites */
MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
/* The PSK ephemeral suites */
MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
......@@ -162,9 +157,6 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
/* The ECJPAKE suite */
MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8,
......@@ -228,11 +220,6 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
/* All remaining >= 128-bit suites */
MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
/* The RSA PSK suites */
MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
......@@ -251,8 +238,6 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
/* The PSK suites */
MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
......@@ -275,6 +260,16 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
/* 3DES suites */
MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
/* RC4 suites */
......@@ -2187,6 +2182,26 @@ const int *mbedtls_ssl_list_ciphersuites( void )
static int supported_ciphersuites[MAX_CIPHERSUITES];
static int supported_init = 0;
static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info )
{
(void)cs_info;
#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES)
if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
return( 1 );
#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */
#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES)
if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB ||
cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC )
{
return( 1 );
}
#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */
return( 0 );
}
const int *mbedtls_ssl_list_ciphersuites( void )
{
/*
......@@ -2202,14 +2217,12 @@ const int *mbedtls_ssl_list_ciphersuites( void )
*p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1;
p++ )
{
#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES)
const mbedtls_ssl_ciphersuite_t *cs_info;
if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL &&
cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 )
#else
if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL )
#endif
!ciphersuite_is_removed( cs_info ) )
{
*(q++) = *p;
}
}
*q = 0;
......
......@@ -300,6 +300,9 @@ static const char *features[] = {
#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES)
"MBEDTLS_REMOVE_ARC4_CIPHERSUITES",
#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */
#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES)
"MBEDTLS_REMOVE_3DES_CIPHERSUITES",
#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
"MBEDTLS_ECP_DP_SECP192R1_ENABLED",
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
......
......@@ -368,7 +368,7 @@ static void x509_crt_verify_chain_reset(
for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
{
ver_chain->items[i].crt = NULL;
ver_chain->items[i].flags = -1;
ver_chain->items[i].flags = (uint32_t) -1;
}
ver_chain->len = 0;
......
......@@ -279,15 +279,24 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
{
mbedtls_pem_init( &pem );
ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN CERTIFICATE REQUEST-----",
"-----END CERTIFICATE REQUEST-----",
buf, NULL, 0, &use_len );
"-----BEGIN CERTIFICATE REQUEST-----",
"-----END CERTIFICATE REQUEST-----",
buf, NULL, 0, &use_len );
if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN NEW CERTIFICATE REQUEST-----",
"-----END NEW CERTIFICATE REQUEST-----",
buf, NULL, 0, &use_len );
}
if( ret == 0 )
{
/*
* Was PEM encoded, parse the result
*/
ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
}
mbedtls_pem_free( &pem );
if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
......
......@@ -218,26 +218,51 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *
}
#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,
unsigned int key_usage )
{
unsigned char buf[4], ku;
unsigned char *c;
int ret;
/* We currently only support 7 bits, from 0x80 to 0x02 */
if( ( key_usage & ~0xfe ) != 0 )
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;
/* Check that nothing other than the allowed flags is set */
if( ( key_usage & ~allowed_bits ) != 0 )
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
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 );
else if( ret < 3 || ret > 4 )
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
1, buf, 4 );
1, c, (size_t)ret );
if( ret != 0 )
return( ret );
......@@ -249,16 +274,22 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
{
unsigned char buf[4];
unsigned char *c;
size_t unused_bits;
int ret;
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 );
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
0, buf, 4 );
0, c, (size_t)ret );
if( ret != 0 )
return( ret );
......
......@@ -81,20 +81,39 @@ int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
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 )
{
unsigned char buf[4];
unsigned char *c;
size_t unused_bits;
int ret;
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 );
else if( ret < 3 || ret > 4 )
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
buf, 4 );
c, (size_t)ret );
if( ret != 0 )
return( ret );
......@@ -106,16 +125,25 @@ int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
{
unsigned char buf[4];
unsigned char *c;
size_t unused_bits;
int ret;
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 );