Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tidy up attribute management inside psa_crypto #197

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
424f894
SE keys: store the bit size internally (partial implementation)
gilles-peskine-arm Jul 15, 2019
dc5bfe9
SE keys: implement and test psa_get_key_attributes
gilles-peskine-arm Jul 24, 2019
1801740
SE driver: report the bit size on key import
gilles-peskine-arm Jul 24, 2019
e60d1d0
SE keys: save the bit size in storage
gilles-peskine-arm Jul 24, 2019
fc321f1
SE keys: test that the bit size is saved and loaded correctly
gilles-peskine-arm Jul 24, 2019
7e0cff9
Move attribute fields to a substructure
gilles-peskine-arm Jul 30, 2019
c744d99
Limit keys to 65528 bits
gilles-peskine-arm Jul 30, 2019
68cc433
Store key sizes in 16 bits in attributes
gilles-peskine-arm Jul 30, 2019
8e33870
Use psa_core_key_attributes_t in key slots in memory
gilles-peskine-arm Jul 30, 2019
4ed0e6f
Switch storage functions over to psa_core_key_attributes_t
gilles-peskine-arm Jul 30, 2019
2431859
Take advantage of psa_core_key_attributes_t internally: key loading
gilles-peskine-arm Jul 30, 2019
b46bef2
Store the key size in the slot in memory
gilles-peskine-arm Jul 30, 2019
76aa09c
Take advantage of psa_core_key_attributes_t internally #2
gilles-peskine-arm Jul 31, 2019
41e50d2
Remove "allocated" flag from key slots
gilles-peskine-arm Jul 31, 2019
7c227ae
Test key creation with an invalid type (0 and nonzero)
gilles-peskine-arm Jul 31, 2019
6edfa29
Add test function for import with a bad policy
gilles-peskine-arm Jul 31, 2019
3825e14
Fix policy validity check on key creation.
gilles-peskine-arm Jul 31, 2019
1b8594a
More refactoring: consolidate attribute validation
gilles-peskine-arm Jul 31, 2019
8908c5e
Make psa_calculate_key_bits return psa_key_bits_t
gilles-peskine-arm Jul 31, 2019
1b9505c
Correct some comments
gilles-peskine-arm Aug 7, 2019
49232e8
Avoid a lowercase letter in a macro name
gilles-peskine-arm Aug 7, 2019
b1f6c5f
Fix copypasta in test data
gilles-peskine-arm Aug 7, 2019
a6b2f60
Fix double free in psa_generate_key when psa_generate_random fails
gilles-peskine-arm Aug 7, 2019
bdc96fd
Add tests to generate more random than MBEDTLS_CTR_DRBG_MAX_REQUEST
gilles-peskine-arm Aug 7, 2019
f181eca
Fix psa_generate_random for >1024 bytes
gilles-peskine-arm Aug 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/psa/crypto_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ static inline struct psa_key_policy_s psa_key_policy_init( void )
return( v );
}

/* The maximum size of a key in bits.
* This is a whole number of bytes, to facilitate some calculations
* such as the maximum size of key data in storage.
*/
#define PSA_MAX_KEY_BITS 0xfff8

typedef struct
{
psa_key_type_t type;
Expand Down
16 changes: 13 additions & 3 deletions library/psa_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,11 +706,14 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,

if( key_type_is_raw_bytes( slot->type ) )
{
/* Ensure that a bytes-to-bit conversion won't overflow. */
size_t bit_size = PSA_BYTES_TO_BITS( data_length );
/* Ensure that the bytes-to-bit conversion doesn't overflow. */
yanesca marked this conversation as resolved.
Show resolved Hide resolved
if( data_length > SIZE_MAX / 8 )
return( PSA_ERROR_NOT_SUPPORTED );
status = prepare_raw_data_slot( slot->type,
PSA_BYTES_TO_BITS( data_length ),
/* Ensure that the key is not overly large. */
if( bit_size > PSA_MAX_KEY_BITS )
return( PSA_ERROR_NOT_SUPPORTED );
status = prepare_raw_data_slot( slot->type, bit_size,
&slot->data.raw );
if( status != PSA_SUCCESS )
return( status );
Expand Down Expand Up @@ -1470,6 +1473,13 @@ static psa_status_t psa_start_key_creation(
}
slot->type = attributes->core.type;

/* Refuse to create overly large keys.
* Note that this doesn't trigger on import if the attributes don't
* explicitly specify a size (so psa_get_key_bits returns 0), so
* psa_import_key() needs its own checks. */
if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS )
return( PSA_ERROR_NOT_SUPPORTED );

#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* For a key in a secure element, we need to do three things:
* create the key file in internal storage, create the
Expand Down
11 changes: 8 additions & 3 deletions library/psa_crypto_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ extern "C" {
#include <stdint.h>
#include <string.h>

/* Limit the maximum key size to 30kB (just in case someone tries to
* inadvertently store an obscene amount of data) */
#define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 )
/* Limit the maximum key size in storage. This should have no effect
* since the key size is limited in memory. */
#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) )
/* Sanity check: a file size must fit in 32 bits. Allow a generous
* 64kB of metadata. */
#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000
#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000
#endif

/** The maximum permitted persistent slot number.
*
Expand Down
26 changes: 26 additions & 0 deletions tests/suites/test_suite_psa_crypto.data
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,14 @@ PSA import AES: bits=128 wrong
depends_on:MBEDTLS_AES_C
import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT

PSA import large key: raw, 65528 bits (ok)
depends_on:HAVE_RAM_AVAILABLE_128k
import_large_key:PSA_KEY_TYPE_RAW_DATA:8191:PSA_SUCCESS

PSA import large key: raw, 65536 bits (not supported)
yanesca marked this conversation as resolved.
Show resolved Hide resolved
depends_on:HAVE_RAM_AVAILABLE_128k
import_large_key:PSA_KEY_TYPE_RAW_DATA:8192:PSA_ERROR_NOT_SUPPORTED

PSA import RSA key pair: maximum size exceeded
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:1:PSA_ERROR_NOT_SUPPORTED
Expand Down Expand Up @@ -2075,6 +2083,17 @@ PSA key derivation: TLS 1.2 PRF SHA-256, derive key export, 1+41
depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION
derive_key_export:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41

# This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes
# and not expected to be raised any time soon) is less than the maximum
# output from HKDF-SHA512 (255*64 = 16320 bytes).
PSA key derivation: largest possible key
depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION
derive_large_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_MAX_KEY_BITS:PSA_SUCCESS

PSA key derivation: key too large
depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION
derive_large_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED

PSA key agreement setup: ECDH + HKDF-SHA-256: good
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_MD_C:MBEDTLS_SHA256_C
key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_SUCCESS
Expand Down Expand Up @@ -2188,6 +2207,13 @@ generate_key:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_AR
PSA generate key: raw data, 8 bits
generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS

PSA generate key: raw data, 65528 bits (ok)
depends_on:HAVE_RAM_AVAILABLE_128k
generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved

PSA generate key: raw data, 65536 bits (not supported)
generate_key:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED

PSA generate key: AES, 128 bits, CTR
depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS
Expand Down
102 changes: 101 additions & 1 deletion tests/suites/test_suite_psa_crypto.function
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

#include "psa_crypto_helpers.h"

/* Tests that require more than 128kB of RAM plus change have this symbol
* as a dependency. Currently we always define this symbol, so the tests
* are always executed. In the future we should make this conditional
* so that tests that require a lot of memory are skipped on constrained
* platforms. */
#define HAVE_RAM_AVAILABLE_128k
k-stachowiak marked this conversation as resolved.
Show resolved Hide resolved

/** An invalid export length that will never be set by psa_export_key(). */
static const size_t INVALID_EXPORT_LENGTH = ~0U;

Expand Down Expand Up @@ -556,7 +563,8 @@ static int setup_key_derivation_wrap( psa_key_derivation_operation_t* operation,
TEST_ASSERT( ! "Key derivation algorithm not supported" );
}

PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
if( capacity != SIZE_MAX )
PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );

return( 1 );

Expand Down Expand Up @@ -1237,6 +1245,54 @@ exit:
}
/* END_CASE */

/* BEGIN_CASE */
void import_large_key( int type_arg, int byte_size_arg,
int expected_status_arg )
{
psa_key_type_t type = type_arg;
size_t byte_size = byte_size_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t expected_status = expected_status_arg;
psa_key_handle_t handle = 0;
psa_status_t status;
uint8_t *buffer = NULL;
size_t buffer_size = byte_size + 1;
size_t n;

/* It would be better to skip the test than fail it if the allocation
* fails, but the test framework doesn't support this yet. */
ASSERT_ALLOC( buffer, buffer_size );
memset( buffer, 'K', byte_size );

PSA_ASSERT( psa_crypto_init( ) );

/* Try importing the key */
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
psa_set_key_type( &attributes, type );
status = psa_import_key( &attributes, buffer, byte_size, &handle );
TEST_EQUAL( status, expected_status );

if( status == PSA_SUCCESS )
{
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
TEST_EQUAL( psa_get_key_type( &attributes ), type );
TEST_EQUAL( psa_get_key_bits( &attributes ),
PSA_BYTES_TO_BITS( byte_size ) );
memset( buffer, 0, byte_size + 1 );
PSA_ASSERT( psa_export_key( handle, buffer, byte_size, &n ) );
for( n = 0; n < byte_size; n++ )
TEST_EQUAL( buffer[n], 'K' );
for( n = byte_size; n < buffer_size; n++ )
TEST_EQUAL( buffer[n], 0 );
}

exit:
psa_destroy_key( handle );
PSA_DONE( );
mbedtls_free( buffer );
}
/* END_CASE */

/* BEGIN_CASE */
void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg )
{
Expand Down Expand Up @@ -4563,6 +4619,50 @@ exit:
}
/* END_CASE */

/* BEGIN_CASE */
void derive_large_key( int alg_arg,
data_t *key_data, data_t *input1, data_t *input2,
int bits_arg,
int expected_status_arg )
{
psa_key_handle_t base_handle = 0;
psa_key_handle_t derived_handle = 0;
psa_algorithm_t alg = alg_arg;
size_t bits = bits_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;

PSA_ASSERT( psa_crypto_init( ) );

psa_set_key_usage_flags( &base_attributes, PSA_KEY_USAGE_DERIVE );
psa_set_key_algorithm( &base_attributes, alg );
psa_set_key_type( &base_attributes, PSA_KEY_TYPE_DERIVE );
PSA_ASSERT( psa_import_key( &base_attributes, key_data->x, key_data->len,
&base_handle ) );

if( !setup_key_derivation_wrap( &operation, base_handle, alg,
input1->x, input1->len,
input2->x, input2->len, SIZE_MAX ) )
goto exit;

psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
psa_set_key_algorithm( &derived_attributes, 0 );
psa_set_key_type( &derived_attributes, PSA_KEY_TYPE_RAW_DATA );
psa_set_key_bits( &derived_attributes, bits );
TEST_EQUAL( psa_key_derivation_output_key( &derived_attributes, &operation,
&derived_handle ),
expected_status );

exit:
psa_key_derivation_abort( &operation );
psa_destroy_key( base_handle );
psa_destroy_key( derived_handle );
PSA_DONE( );
}
/* END_CASE */

/* BEGIN_CASE */
void key_agreement_setup( int alg_arg,
int our_key_type_arg, data_t *our_key_data,
Expand Down
4 changes: 2 additions & 2 deletions tests/suites/test_suite_psa_crypto_persistent_key.data
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ parse_storage_data_check:"505341004b4559":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY
# Not specific to files, but only run this test in an environment where the maximum size could be reached.
Save maximum size persistent raw key
depends_on:MBEDTLS_PSA_ITS_FILE_C
save_large_persistent_key:0:PSA_SUCCESS
save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE:PSA_SUCCESS

Save larger than maximum size persistent raw key, should fail
save_large_persistent_key:1:PSA_ERROR_INSUFFICIENT_STORAGE
save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE + 1:PSA_ERROR_NOT_SUPPORTED

Persistent key destroy
depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
Expand Down
7 changes: 2 additions & 5 deletions tests/suites/test_suite_psa_crypto_persistent_key.function
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,14 @@ exit:
/* END_CASE */

/* BEGIN_CASE */
void save_large_persistent_key( int data_too_large, int expected_status )
void save_large_persistent_key( int data_length_arg, int expected_status )
{
psa_key_id_t key_id = 42;
psa_key_handle_t handle = 0;
uint8_t *data = NULL;
size_t data_length = PSA_CRYPTO_MAX_STORAGE_SIZE;
size_t data_length = data_length_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;

if( data_too_large )
data_length += 1;

ASSERT_ALLOC( data, data_length );

PSA_ASSERT( psa_crypto_init() );
Expand Down