557b8d663a
In order to remove large buffers from the stack, the der data is written into the same buffer that the pem is eventually written into, however although the pem data is zero terminated, there is now data left in the buffer after the zero termination, which can cause mbedtls_x509_crt_parse to fail to parse the same buffer if passed back in. Patches also applied to mbedtls_pk_write_pubkey_pem, and mbedtls_pk_write_key_pem, which use similar methods of writing der data to the same buffer, and tests modified to hopefully catch any future regression on this. Signed-off-by: Paul Elliott <paul.elliott@arm.com>
381 lines
13 KiB
Text
381 lines
13 KiB
Text
/* BEGIN_HEADER */
|
|
#include "mbedtls/bignum.h"
|
|
#include "mbedtls/x509_crt.h"
|
|
#include "mbedtls/x509_csr.h"
|
|
#include "mbedtls/pem.h"
|
|
#include "mbedtls/oid.h"
|
|
#include "mbedtls/rsa.h"
|
|
|
|
/* These are the same depends as the test function x509_crs_check_opaque(),
|
|
* the only function using PSA here. Using a weaker condition would result in
|
|
* warnings about the static functions defined in psa_crypto_helpers.h being
|
|
* unused. */
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
|
|
defined(MBEDTLS_PEM_WRITE_C) && \
|
|
defined(MBEDTLS_X509_CSR_WRITE_C)
|
|
#include "psa/crypto.h"
|
|
#include "mbedtls/psa_util.h"
|
|
#include "test/psa_crypto_helpers.h"
|
|
#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
|
|
#else
|
|
/* Define empty macros so that we can use them in the preamble and teardown
|
|
* of every test function that uses PSA conditionally based on
|
|
* MBEDTLS_USE_PSA_CRYPTO. */
|
|
#define PSA_INIT( ) ( (void) 0 )
|
|
#define PSA_DONE( ) ( (void) 0 )
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C && MBEDTLS_X509_CSR_WRITE_C */
|
|
|
|
#if defined(MBEDTLS_RSA_C)
|
|
int mbedtls_rsa_decrypt_func( void *ctx, int mode, size_t *olen,
|
|
const unsigned char *input, unsigned char *output,
|
|
size_t output_max_len )
|
|
{
|
|
return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, NULL, NULL, mode, olen,
|
|
input, output, output_max_len ) );
|
|
}
|
|
int mbedtls_rsa_sign_func( void *ctx,
|
|
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
|
|
int mode, mbedtls_md_type_t md_alg, unsigned int hashlen,
|
|
const unsigned char *hash, unsigned char *sig )
|
|
{
|
|
return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, mode,
|
|
md_alg, hashlen, hash, sig ) );
|
|
}
|
|
size_t mbedtls_rsa_key_len_func( void *ctx )
|
|
{
|
|
return( ((const mbedtls_rsa_context *) ctx)->len );
|
|
}
|
|
#endif /* MBEDTLS_RSA_C */
|
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
|
|
defined(MBEDTLS_PEM_WRITE_C) && defined(MBEDTLS_X509_CSR_WRITE_C)
|
|
static int x509_crt_verifycsr( const unsigned char *buf, size_t buflen )
|
|
{
|
|
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
|
|
const mbedtls_md_info_t *md_info;
|
|
mbedtls_x509_csr csr;
|
|
int ret = 0;
|
|
|
|
mbedtls_x509_csr_init( &csr );
|
|
|
|
if( mbedtls_x509_csr_parse( &csr, buf, buflen ) != 0 )
|
|
{
|
|
ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
|
|
goto cleanup;
|
|
}
|
|
|
|
md_info = mbedtls_md_info_from_type( csr.sig_md );
|
|
if( mbedtls_md( md_info, csr.cri.p, csr.cri.len, hash ) != 0 )
|
|
{
|
|
/* Note: this can't happen except after an internal error */
|
|
ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
|
|
goto cleanup;
|
|
}
|
|
|
|
if( mbedtls_pk_verify_ext( csr.sig_pk, csr.sig_opts, &csr.pk,
|
|
csr.sig_md, hash, mbedtls_md_get_size( md_info ),
|
|
csr.sig.p, csr.sig.len ) != 0 )
|
|
{
|
|
ret = MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
mbedtls_x509_csr_free( &csr );
|
|
return( ret );
|
|
}
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C && MBEDTLS_X509_CSR_WRITE_C */
|
|
|
|
/* END_HEADER */
|
|
|
|
/* BEGIN_DEPENDENCIES
|
|
* depends_on:MBEDTLS_BIGNUM_C:MBEDTLS_FS_IO:MBEDTLS_PK_PARSE_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C:MBEDTLS_X509_CSR_WRITE_C */
|
|
void x509_csr_check( char * key_file, char * cert_req_check_file, int md_type,
|
|
int key_usage, int set_key_usage, int cert_type,
|
|
int set_cert_type )
|
|
{
|
|
mbedtls_pk_context key;
|
|
mbedtls_x509write_csr req;
|
|
unsigned char buf[4096];
|
|
unsigned char check_buf[4000];
|
|
int ret;
|
|
size_t olen = 0, pem_len = 0, buf_index;
|
|
int der_len = -1;
|
|
FILE *f;
|
|
const char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
|
|
mbedtls_test_rnd_pseudo_info rnd_info;
|
|
|
|
memset( &rnd_info, 0x2a, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
|
|
|
mbedtls_pk_init( &key );
|
|
TEST_ASSERT( mbedtls_pk_parse_keyfile( &key, key_file, NULL ) == 0 );
|
|
|
|
mbedtls_x509write_csr_init( &req );
|
|
mbedtls_x509write_csr_set_md_alg( &req, md_type );
|
|
mbedtls_x509write_csr_set_key( &req, &key );
|
|
TEST_ASSERT( mbedtls_x509write_csr_set_subject_name( &req, subject_name ) == 0 );
|
|
if( set_key_usage != 0 )
|
|
TEST_ASSERT( mbedtls_x509write_csr_set_key_usage( &req, key_usage ) == 0 );
|
|
if( set_cert_type != 0 )
|
|
TEST_ASSERT( mbedtls_x509write_csr_set_ns_cert_type( &req, cert_type ) == 0 );
|
|
|
|
ret = mbedtls_x509write_csr_pem( &req, buf, sizeof( buf ),
|
|
mbedtls_test_rnd_pseudo_rand, &rnd_info );
|
|
TEST_ASSERT( ret == 0 );
|
|
|
|
pem_len = strlen( (char *) buf );
|
|
|
|
for( buf_index = pem_len; buf_index < sizeof( buf ); ++buf_index )
|
|
{
|
|
TEST_ASSERT( buf[buf_index] == 0 );
|
|
}
|
|
|
|
f = fopen( cert_req_check_file, "r" );
|
|
TEST_ASSERT( f != NULL );
|
|
olen = fread( check_buf, 1, sizeof( check_buf ), f );
|
|
fclose( f );
|
|
|
|
TEST_ASSERT( olen >= pem_len - 1 );
|
|
TEST_ASSERT( memcmp( buf, check_buf, pem_len - 1 ) == 0 );
|
|
|
|
der_len = mbedtls_x509write_csr_der( &req, buf, sizeof( buf ),
|
|
mbedtls_test_rnd_pseudo_rand,
|
|
&rnd_info );
|
|
TEST_ASSERT( der_len >= 0 );
|
|
|
|
if( der_len == 0 )
|
|
goto exit;
|
|
|
|
ret = mbedtls_x509write_csr_der( &req, buf, (size_t)( der_len - 1 ),
|
|
mbedtls_test_rnd_pseudo_rand, &rnd_info );
|
|
TEST_ASSERT( ret == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
|
|
|
exit:
|
|
mbedtls_x509write_csr_free( &req );
|
|
mbedtls_pk_free( &key );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C:MBEDTLS_X509_CSR_WRITE_C:MBEDTLS_USE_PSA_CRYPTO */
|
|
void x509_csr_check_opaque( char *key_file, int md_type, int key_usage,
|
|
int cert_type )
|
|
{
|
|
mbedtls_pk_context key;
|
|
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
|
psa_algorithm_t md_alg_psa;
|
|
mbedtls_x509write_csr req;
|
|
unsigned char buf[4096];
|
|
int ret;
|
|
size_t pem_len = 0;
|
|
const char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
|
|
mbedtls_test_rnd_pseudo_info rnd_info;
|
|
|
|
PSA_INIT( );
|
|
memset( &rnd_info, 0x2a, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
|
|
|
md_alg_psa = mbedtls_psa_translate_md( (mbedtls_md_type_t) md_type );
|
|
TEST_ASSERT( md_alg_psa != MBEDTLS_MD_NONE );
|
|
|
|
mbedtls_pk_init( &key );
|
|
TEST_ASSERT( mbedtls_pk_parse_keyfile( &key, key_file, NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_pk_wrap_as_opaque( &key, &key_id, md_alg_psa ) == 0 );
|
|
|
|
mbedtls_x509write_csr_init( &req );
|
|
mbedtls_x509write_csr_set_md_alg( &req, md_type );
|
|
mbedtls_x509write_csr_set_key( &req, &key );
|
|
TEST_ASSERT( mbedtls_x509write_csr_set_subject_name( &req, subject_name ) == 0 );
|
|
if( key_usage != 0 )
|
|
TEST_ASSERT( mbedtls_x509write_csr_set_key_usage( &req, key_usage ) == 0 );
|
|
if( cert_type != 0 )
|
|
TEST_ASSERT( mbedtls_x509write_csr_set_ns_cert_type( &req, cert_type ) == 0 );
|
|
|
|
ret = mbedtls_x509write_csr_pem( &req, buf, sizeof( buf ) - 1,
|
|
mbedtls_test_rnd_pseudo_rand, &rnd_info );
|
|
|
|
TEST_ASSERT( ret == 0 );
|
|
|
|
pem_len = strlen( (char *) buf );
|
|
buf[pem_len] = '\0';
|
|
TEST_ASSERT( x509_crt_verifycsr( buf, pem_len + 1 ) == 0 );
|
|
|
|
|
|
exit:
|
|
mbedtls_x509write_csr_free( &req );
|
|
mbedtls_pk_free( &key );
|
|
psa_destroy_key( key_id );
|
|
PSA_DONE( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C:MBEDTLS_X509_CRT_WRITE_C:MBEDTLS_SHA1_C */
|
|
void x509_crt_check( char *subject_key_file, char *subject_pwd,
|
|
char *subject_name, char *issuer_key_file,
|
|
char *issuer_pwd, char *issuer_name,
|
|
char *serial_str, char *not_before, char *not_after,
|
|
int md_type, int key_usage, int set_key_usage,
|
|
int cert_type, int set_cert_type, int auth_ident,
|
|
int ver, char *cert_check_file, int rsa_alt )
|
|
{
|
|
mbedtls_pk_context subject_key, issuer_key, issuer_key_alt;
|
|
mbedtls_pk_context *key = &issuer_key;
|
|
|
|
mbedtls_x509write_cert crt;
|
|
unsigned char buf[4096];
|
|
unsigned char check_buf[5000];
|
|
mbedtls_mpi serial;
|
|
int ret;
|
|
size_t olen = 0, pem_len = 0, buf_index = 0;
|
|
int der_len = -1;
|
|
FILE *f;
|
|
mbedtls_test_rnd_pseudo_info rnd_info;
|
|
|
|
memset( &rnd_info, 0x2a, sizeof( mbedtls_test_rnd_pseudo_info ) );
|
|
mbedtls_mpi_init( &serial );
|
|
|
|
mbedtls_pk_init( &subject_key );
|
|
mbedtls_pk_init( &issuer_key );
|
|
mbedtls_pk_init( &issuer_key_alt );
|
|
|
|
mbedtls_x509write_crt_init( &crt );
|
|
|
|
TEST_ASSERT( mbedtls_pk_parse_keyfile( &subject_key, subject_key_file,
|
|
subject_pwd ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_pk_parse_keyfile( &issuer_key, issuer_key_file,
|
|
issuer_pwd ) == 0 );
|
|
|
|
#if defined(MBEDTLS_RSA_C)
|
|
/* For RSA PK contexts, create a copy as an alternative RSA context. */
|
|
if( rsa_alt == 1 && mbedtls_pk_get_type( &issuer_key ) == MBEDTLS_PK_RSA )
|
|
{
|
|
TEST_ASSERT( mbedtls_pk_setup_rsa_alt( &issuer_key_alt,
|
|
mbedtls_pk_rsa( issuer_key ),
|
|
mbedtls_rsa_decrypt_func,
|
|
mbedtls_rsa_sign_func,
|
|
mbedtls_rsa_key_len_func ) == 0 );
|
|
|
|
key = &issuer_key_alt;
|
|
}
|
|
#else
|
|
(void) rsa_alt;
|
|
#endif
|
|
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &serial, 10, serial_str ) == 0 );
|
|
|
|
if( ver != -1 )
|
|
mbedtls_x509write_crt_set_version( &crt, ver );
|
|
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_serial( &crt, &serial ) == 0 );
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_validity( &crt, not_before,
|
|
not_after ) == 0 );
|
|
mbedtls_x509write_crt_set_md_alg( &crt, md_type );
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_issuer_name( &crt, issuer_name ) == 0 );
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_subject_name( &crt, subject_name ) == 0 );
|
|
mbedtls_x509write_crt_set_subject_key( &crt, &subject_key );
|
|
|
|
mbedtls_x509write_crt_set_issuer_key( &crt, key );
|
|
|
|
if( crt.version >= MBEDTLS_X509_CRT_VERSION_3 )
|
|
{
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_basic_constraints( &crt, 0, 0 ) == 0 );
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_subject_key_identifier( &crt ) == 0 );
|
|
if( auth_ident )
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_authority_key_identifier( &crt ) == 0 );
|
|
if( set_key_usage != 0 )
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_key_usage( &crt, key_usage ) == 0 );
|
|
if( set_cert_type != 0 )
|
|
TEST_ASSERT( mbedtls_x509write_crt_set_ns_cert_type( &crt, cert_type ) == 0 );
|
|
}
|
|
|
|
ret = mbedtls_x509write_crt_pem( &crt, buf, sizeof( buf ),
|
|
mbedtls_test_rnd_pseudo_rand, &rnd_info );
|
|
TEST_ASSERT( ret == 0 );
|
|
|
|
pem_len = strlen( (char *) buf );
|
|
|
|
// check that the rest of the buffer remains clear
|
|
for( buf_index = pem_len; buf_index < sizeof( buf ); ++buf_index )
|
|
{
|
|
TEST_ASSERT( buf[buf_index] == 0 );
|
|
}
|
|
|
|
f = fopen( cert_check_file, "r" );
|
|
TEST_ASSERT( f != NULL );
|
|
olen = fread( check_buf, 1, sizeof( check_buf ), f );
|
|
fclose( f );
|
|
TEST_ASSERT( olen < sizeof( check_buf ) );
|
|
|
|
TEST_ASSERT( olen >= pem_len - 1 );
|
|
TEST_ASSERT( memcmp( buf, check_buf, pem_len - 1 ) == 0 );
|
|
|
|
der_len = mbedtls_x509write_crt_der( &crt, buf, sizeof( buf ),
|
|
mbedtls_test_rnd_pseudo_rand,
|
|
&rnd_info );
|
|
TEST_ASSERT( der_len >= 0 );
|
|
|
|
if( der_len == 0 )
|
|
goto exit;
|
|
|
|
ret = mbedtls_x509write_crt_der( &crt, buf, (size_t)( der_len - 1 ),
|
|
mbedtls_test_rnd_pseudo_rand, &rnd_info );
|
|
TEST_ASSERT( ret == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
|
|
|
exit:
|
|
mbedtls_x509write_crt_free( &crt );
|
|
mbedtls_pk_free( &issuer_key_alt );
|
|
mbedtls_pk_free( &subject_key );
|
|
mbedtls_pk_free( &issuer_key );
|
|
mbedtls_mpi_free( &serial );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_X509_CREATE_C:MBEDTLS_X509_USE_C */
|
|
void mbedtls_x509_string_to_names( char * name, char * parsed_name, int result
|
|
)
|
|
{
|
|
int ret;
|
|
size_t len = 0;
|
|
mbedtls_asn1_named_data *names = NULL;
|
|
mbedtls_x509_name parsed, *parsed_cur, *parsed_prv;
|
|
unsigned char buf[1024], out[1024], *c;
|
|
|
|
memset( &parsed, 0, sizeof( parsed ) );
|
|
memset( out, 0, sizeof( out ) );
|
|
memset( buf, 0, sizeof( buf ) );
|
|
c = buf + sizeof( buf );
|
|
|
|
ret = mbedtls_x509_string_to_names( &names, name );
|
|
TEST_ASSERT( ret == result );
|
|
|
|
if( ret != 0 )
|
|
goto exit;
|
|
|
|
ret = mbedtls_x509_write_names( &c, buf, names );
|
|
TEST_ASSERT( ret > 0 );
|
|
|
|
TEST_ASSERT( mbedtls_asn1_get_tag( &c, buf + sizeof( buf ), &len,
|
|
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) == 0 );
|
|
TEST_ASSERT( mbedtls_x509_get_name( &c, buf + sizeof( buf ), &parsed ) == 0 );
|
|
|
|
ret = mbedtls_x509_dn_gets( (char *) out, sizeof( out ), &parsed );
|
|
TEST_ASSERT( ret > 0 );
|
|
|
|
TEST_ASSERT( strcmp( (char *) out, parsed_name ) == 0 );
|
|
|
|
exit:
|
|
mbedtls_asn1_free_named_data_list( &names );
|
|
|
|
parsed_cur = parsed.next;
|
|
while( parsed_cur != 0 )
|
|
{
|
|
parsed_prv = parsed_cur;
|
|
parsed_cur = parsed_cur->next;
|
|
mbedtls_free( parsed_prv );
|
|
}
|
|
}
|
|
/* END_CASE */
|