Skip to content

Commit 1602795

Browse files
authored
Merge pull request #333 from gilles-peskine-arm/psa-streamline_encodings-prepare_for_types
Streamline PSA key type encodings: prepare
2 parents 81f7909 + 4cd3277 commit 1602795

11 files changed

+189
-71
lines changed

include/mbedtls/psa_util.h

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -378,24 +378,6 @@ static inline psa_ecc_curve_t mbedtls_psa_translate_ecc_group( mbedtls_ecp_group
378378
}
379379
}
380380

381-
382-
#define MBEDTLS_PSA_ECC_KEY_BITS_OF_CURVE( curve ) \
383-
( curve == PSA_ECC_CURVE_SECP192R1 ? 192 : \
384-
curve == PSA_ECC_CURVE_SECP224R1 ? 224 : \
385-
curve == PSA_ECC_CURVE_SECP256R1 ? 256 : \
386-
curve == PSA_ECC_CURVE_SECP384R1 ? 384 : \
387-
curve == PSA_ECC_CURVE_SECP521R1 ? 521 : \
388-
curve == PSA_ECC_CURVE_SECP192K1 ? 192 : \
389-
curve == PSA_ECC_CURVE_SECP224K1 ? 224 : \
390-
curve == PSA_ECC_CURVE_SECP256K1 ? 256 : \
391-
curve == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \
392-
curve == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \
393-
curve == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \
394-
0 )
395-
396-
#define MBEDTLS_PSA_ECC_KEY_BYTES_OF_CURVE( curve ) \
397-
( ( MBEDTLS_PSA_ECC_KEY_BITS_OF_CURVE( curve ) + 7 ) / 8 )
398-
399381
/* Translations for PK layer */
400382

401383
static inline int mbedtls_psa_err_translate_pk( psa_status_t status )

include/psa/crypto_values.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@
604604
(type) == PSA_KEY_TYPE_DES ? 8 : \
605605
(type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \
606606
(type) == PSA_KEY_TYPE_ARC4 ? 1 : \
607+
(type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \
607608
0)
608609

609610
/** Vendor-defined algorithm flag.

library/psa_crypto.c

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,20 @@ static psa_status_t psa_import_rsa_key( psa_key_type_t type,
584584
#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */
585585

586586
#if defined(MBEDTLS_ECP_C)
587+
static psa_status_t psa_prepare_import_ec_key( psa_ecc_curve_t curve,
588+
mbedtls_ecp_keypair **p_ecp )
589+
{
590+
mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
591+
*p_ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
592+
if( *p_ecp == NULL )
593+
return( PSA_ERROR_INSUFFICIENT_MEMORY );
594+
mbedtls_ecp_keypair_init( *p_ecp );
595+
596+
/* Load the group. */
597+
grp_id = mbedtls_ecc_group_of_psa( curve );
598+
return( mbedtls_to_psa_error(
599+
mbedtls_ecp_group_load( &( *p_ecp )->grp, grp_id ) ) );
600+
}
587601

588602
/* Import a public key given as the uncompressed representation defined by SEC1
589603
* 2.3.3 as the content of an ECPoint. */
@@ -594,19 +608,11 @@ static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve,
594608
{
595609
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
596610
mbedtls_ecp_keypair *ecp = NULL;
597-
mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
598-
599-
*p_ecp = NULL;
600-
ecp = mbedtls_calloc( 1, sizeof( *ecp ) );
601-
if( ecp == NULL )
602-
return( PSA_ERROR_INSUFFICIENT_MEMORY );
603-
mbedtls_ecp_keypair_init( ecp );
604611

605-
/* Load the group. */
606-
status = mbedtls_to_psa_error(
607-
mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
612+
status = psa_prepare_import_ec_key( curve, &ecp );
608613
if( status != PSA_SUCCESS )
609614
goto exit;
615+
610616
/* Load the public value. */
611617
status = mbedtls_to_psa_error(
612618
mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
@@ -631,9 +637,7 @@ static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve,
631637
}
632638
return( status );
633639
}
634-
#endif /* defined(MBEDTLS_ECP_C) */
635640

636-
#if defined(MBEDTLS_ECP_C)
637641
/* Import a private key given as a byte string which is the private value
638642
* in big-endian order. */
639643
static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve,
@@ -643,22 +647,14 @@ static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve,
643647
{
644648
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
645649
mbedtls_ecp_keypair *ecp = NULL;
646-
mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
647650

648651
if( PSA_BITS_TO_BYTES( PSA_ECC_CURVE_BITS( curve ) ) != data_length )
649652
return( PSA_ERROR_INVALID_ARGUMENT );
650653

651-
*p_ecp = NULL;
652-
ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
653-
if( ecp == NULL )
654-
return( PSA_ERROR_INSUFFICIENT_MEMORY );
655-
mbedtls_ecp_keypair_init( ecp );
656-
657-
/* Load the group. */
658-
status = mbedtls_to_psa_error(
659-
mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
654+
status = psa_prepare_import_ec_key( curve, &ecp );
660655
if( status != PSA_SUCCESS )
661656
goto exit;
657+
662658
/* Load the secret value. */
663659
status = mbedtls_to_psa_error(
664660
mbedtls_mpi_read_binary( &ecp->d, data, data_length ) );

scripts/generate_psa_constants.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,16 @@ def read_line(self, line):
270270
# Other macro without parameter
271271
return
272272

273+
_nonascii_re = re.compile(rb'[^\x00-\x7f]+')
274+
_continued_line_re = re.compile(rb'\\\r?\n\Z')
273275
def read_file(self, header_file):
274276
for line in header_file:
275-
while line.endswith('\\\n'):
277+
m = re.search(self._continued_line_re, line)
278+
while m:
276279
cont = next(header_file)
277-
line = line[:-2] + cont
280+
line = line[:m.start(0)] + cont
281+
m = re.search(self._continued_line_re, line)
282+
line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
278283
self.read_line(line)
279284

280285
@staticmethod
@@ -380,7 +385,7 @@ def write_file(self, output_file):
380385
def generate_psa_constants(header_file_names, output_file_name):
381386
collector = MacroCollector()
382387
for header_file_name in header_file_names:
383-
with open(header_file_name) as header_file:
388+
with open(header_file_name, 'rb') as header_file:
384389
collector.read_file(header_file)
385390
temp_file_name = output_file_name + '.tmp'
386391
with open(temp_file_name, 'w') as output_file:

tests/scripts/test_psa_constant_names.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ class read_file_lines:
4343
except that if process(line) raises an exception, then the read_file_lines
4444
snippet annotates the exception with the file name and line number.
4545
"""
46-
def __init__(self, filename):
46+
def __init__(self, filename, binary=False):
4747
self.filename = filename
4848
self.line_number = 'entry'
4949
self.generator = None
50+
self.binary = binary
5051
def __enter__(self):
51-
self.generator = enumerate(open(self.filename, 'r'))
52+
self.generator = enumerate(open(self.filename,
53+
'rb' if self.binary else 'r'))
5254
return self
5355
def __iter__(self):
5456
for line_number, content in self.generator:
@@ -100,6 +102,8 @@ def __init__(self):
100102
# Any function ending in _algorithm also gets added to
101103
# self.algorithms.
102104
'key_type': [self.key_types],
105+
'block_cipher_key_type': [self.key_types],
106+
'stream_cipher_key_type': [self.key_types],
103107
'ecc_key_types': [self.ecc_curves],
104108
'dh_key_types': [self.dh_groups],
105109
'hash_algorithm': [self.hash_algorithms],
@@ -224,13 +228,15 @@ def parse_header_line(self, line):
224228
if m.group(3):
225229
self.argspecs[name] = self._argument_split(m.group(3))
226230

231+
_nonascii_re = re.compile(rb'[^\x00-\x7f]+')
227232
def parse_header(self, filename):
228233
"""Parse a C header file, looking for "#define PSA_xxx"."""
229-
with read_file_lines(filename) as lines:
234+
with read_file_lines(filename, binary=True) as lines:
230235
for line in lines:
236+
line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
231237
self.parse_header_line(line)
232238

233-
_macro_identifier_re = r'[A-Z]\w+'
239+
_macro_identifier_re = re.compile(r'[A-Z]\w+')
234240
def generate_undeclared_names(self, expr):
235241
for name in re.findall(self._macro_identifier_re, expr):
236242
if name not in self.all_declared:
@@ -385,6 +391,8 @@ def run_one(self, inputs, type_word):
385391
outputs = output.decode('ascii').strip().split('\n')
386392
self.count += len(expressions)
387393
for expr, value, output in zip(expressions, values, outputs):
394+
if self.options.show:
395+
sys.stdout.write('{} {}\t{}\n'.format(type_word, value, output))
388396
if normalize(expr) != normalize(output):
389397
self.errors.append(self.Error(type=type_word,
390398
expression=expr,
@@ -430,6 +438,12 @@ def main():
430438
parser.add_argument('--program',
431439
default='programs/psa/psa_constant_names',
432440
help='Program to test')
441+
parser.add_argument('--show',
442+
action='store_true',
443+
help='Keep the intermediate C file')
444+
parser.add_argument('--no-show',
445+
action='store_false', dest='show',
446+
help='Don\'t show tested values (default)')
433447
options = parser.parse_args()
434448
headers = [os.path.join(options.include[0], h) for h in HEADERS]
435449
inputs = gather_inputs(headers, TEST_SUITES)

tests/suites/test_suite_psa_crypto.data

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,14 @@ PSA import/export EC secp256r1 public key: good
228228
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
229229
import_export:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1
230230

231+
PSA import/export EC secp521r1 public key: good
232+
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
233+
import_export:"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP521R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:521:0:PSA_SUCCESS:1
234+
235+
PSA import/export EC brainpoolP256r1 public key: good
236+
depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED
237+
import_export:"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_BRAINPOOL_P256R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1
238+
231239
PSA import/export AES key: policy forbids export
232240
depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
233241
import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:128:0:PSA_ERROR_NOT_PERMITTED:1

tests/suites/test_suite_psa_crypto.function

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ static const size_t INVALID_EXPORT_LENGTH = ~0U;
106106
#undef KNOWN_SUPPORTED_CIPHER_KEY_TYPE
107107
#endif
108108

109+
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
110+
int lifetime_is_secure_element( psa_key_lifetime_t lifetime )
111+
{
112+
/* At the moment, anything that isn't a built-in lifetime is either
113+
* a secure element or unassigned. */
114+
return( lifetime != PSA_KEY_LIFETIME_VOLATILE &&
115+
lifetime != PSA_KEY_LIFETIME_PERSISTENT );
116+
}
117+
#else
118+
int lifetime_is_secure_element( psa_key_lifetime_t lifetime )
119+
{
120+
(void) lifetime;
121+
return( 0 );
122+
}
123+
#endif
124+
109125
/** Test if a buffer contains a constant byte value.
110126
*
111127
* `mem_is_char(buffer, c, size)` is true after `memset(buffer, c, size)`.
@@ -212,6 +228,69 @@ static int construct_fake_rsa_key( unsigned char *buffer,
212228
return( len );
213229
}
214230

231+
int check_key_attributes_sanity( psa_key_handle_t key )
232+
{
233+
int ok = 0;
234+
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
235+
psa_key_lifetime_t lifetime;
236+
psa_key_id_t id;
237+
psa_key_type_t type;
238+
psa_key_type_t bits;
239+
240+
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
241+
lifetime = psa_get_key_lifetime( &attributes );
242+
id = psa_get_key_id( &attributes );
243+
type = psa_get_key_type( &attributes );
244+
bits = psa_get_key_bits( &attributes );
245+
246+
/* Persistence */
247+
if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
248+
TEST_ASSERT( id == 0 );
249+
else
250+
{
251+
TEST_ASSERT(
252+
( PSA_KEY_ID_USER_MIN <= id && id <= PSA_KEY_ID_USER_MAX ) ||
253+
( PSA_KEY_ID_USER_MIN <= id && id <= PSA_KEY_ID_USER_MAX ) );
254+
}
255+
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
256+
/* randomly-generated 64-bit constant, should never appear in test data */
257+
psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
258+
psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
259+
if( lifetime_is_secure_element( lifetime ) )
260+
{
261+
/* Mbed Crypto currently always exposes the slot number to
262+
* applications. This is not mandated by the PSA specification
263+
* and may change in future versions. */
264+
TEST_EQUAL( status, 0 );
265+
TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
266+
}
267+
else
268+
{
269+
TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
270+
}
271+
#endif
272+
273+
/* Type and size */
274+
TEST_ASSERT( type != 0 );
275+
TEST_ASSERT( bits != 0 );
276+
TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
277+
if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
278+
TEST_ASSERT( bits % 8 == 0 );
279+
280+
/* MAX macros concerning specific key types */
281+
if( PSA_KEY_TYPE_IS_ECC( type ) )
282+
TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
283+
else if( PSA_KEY_TYPE_IS_RSA( type ) )
284+
TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
285+
TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_SIZE( type ) <= PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE );
286+
287+
ok = 1;
288+
289+
exit:
290+
psa_reset_key_attributes( &attributes );
291+
return( ok );
292+
}
293+
215294
int exercise_mac_setup( psa_key_type_t key_type,
216295
const unsigned char *key_bytes,
217296
size_t key_length,
@@ -1021,6 +1100,10 @@ static int exercise_key( psa_key_handle_t handle,
10211100
psa_algorithm_t alg )
10221101
{
10231102
int ok;
1103+
1104+
if( ! check_key_attributes_sanity( handle ) )
1105+
return( 0 );
1106+
10241107
if( alg == 0 )
10251108
ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
10261109
else if( PSA_ALG_IS_MAC( alg ) )

tests/suites/test_suite_psa_crypto_metadata.data

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -315,25 +315,25 @@ key_type:PSA_KEY_TYPE_HMAC:KEY_TYPE_IS_UNSTRUCTURED
315315
Key type: secret for key derivation
316316
key_type:PSA_KEY_TYPE_DERIVE:KEY_TYPE_IS_UNSTRUCTURED
317317

318-
Key type: AES
318+
Block cipher key type: AES
319319
depends_on:MBEDTLS_AES_C
320-
key_type:PSA_KEY_TYPE_AES:KEY_TYPE_IS_UNSTRUCTURED
320+
block_cipher_key_type:PSA_KEY_TYPE_AES:16
321321

322-
Key type: DES
322+
Block cipher key type: DES
323323
depends_on:MBEDTLS_DES_C
324-
key_type:PSA_KEY_TYPE_DES:KEY_TYPE_IS_UNSTRUCTURED
324+
block_cipher_key_type:PSA_KEY_TYPE_DES:8
325325

326-
Key type: Camellia
326+
Block cipher key type: Camellia
327327
depends_on:MBEDTLS_CAMELLIA_C
328-
key_type:PSA_KEY_TYPE_CAMELLIA:KEY_TYPE_IS_UNSTRUCTURED
328+
block_cipher_key_type:PSA_KEY_TYPE_CAMELLIA:16
329329

330-
Key type: ARC4
330+
Stream cipher key type: ARC4
331331
depends_on:MBEDTLS_ARC4_C
332-
key_type:PSA_KEY_TYPE_ARC4:KEY_TYPE_IS_UNSTRUCTURED
332+
stream_cipher_key_type:PSA_KEY_TYPE_ARC4
333333

334-
Key type: ChaCha20
334+
Stream cipher key type: ChaCha20
335335
depends_on:MBEDTLS_CHACHA20_C
336-
key_type:PSA_KEY_TYPE_CHACHA20:KEY_TYPE_IS_UNSTRUCTURED
336+
stream_cipher_key_type:PSA_KEY_TYPE_CHACHA20
337337

338338
Key type: RSA public key
339339
depends_on:MBEDTLS_RSA_C

tests/suites/test_suite_psa_crypto_metadata.function

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,33 @@ void key_type( int type_arg, int classification_flags )
449449
}
450450
/* END_CASE */
451451

452+
/* BEGIN_CASE */
453+
void block_cipher_key_type( int type_arg, int block_size_arg )
454+
{
455+
psa_key_type_t type = type_arg;
456+
size_t block_size = block_size_arg;
457+
458+
test_key_type( type_arg, KEY_TYPE_IS_UNSTRUCTURED );
459+
460+
TEST_EQUAL( type & PSA_KEY_TYPE_CATEGORY_MASK,
461+
PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
462+
TEST_EQUAL( PSA_BLOCK_CIPHER_BLOCK_SIZE( type ), block_size );
463+
}
464+
/* END_CASE */
465+
466+
/* BEGIN_CASE */
467+
void stream_cipher_key_type( int type_arg )
468+
{
469+
psa_key_type_t type = type_arg;
470+
471+
test_key_type( type_arg, KEY_TYPE_IS_UNSTRUCTURED );
472+
473+
TEST_EQUAL( type & PSA_KEY_TYPE_CATEGORY_MASK,
474+
PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
475+
TEST_EQUAL( PSA_BLOCK_CIPHER_BLOCK_SIZE( type ), 1 );
476+
}
477+
/* END_CASE */
478+
452479
/* BEGIN_CASE */
453480
void ecc_key_types( int curve_arg, int curve_bits_arg )
454481
{

0 commit comments

Comments
 (0)