1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-08-01 10:06:53 +03:00

Merge branch 'psa-api-1.0-beta' into merge-psa-api-branch-into-development

This commit is contained in:
Janos Follath
2019-08-08 14:40:23 +01:00
60 changed files with 10579 additions and 4410 deletions

View File

@ -86,6 +86,7 @@ MBEDTLS_NO_PLATFORM_ENTROPY
MBEDTLS_RSA_NO_CRT
MBEDTLS_NO_UDBL_DIVISION
MBEDTLS_NO_64BIT_MULTIPLICATION
MBEDTLS_PSA_CRYPTO_SE_C
MBEDTLS_PSA_CRYPTO_SPM
MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
MBEDTLS_PSA_INJECT_ENTROPY
@ -109,6 +110,7 @@ MBEDTLS_MEMORY_BUFFER_ALLOC_C
MBEDTLS_PLATFORM_TIME_ALT
MBEDTLS_PLATFORM_FPRINTF_ALT
MBEDTLS_PSA_ITS_FILE_C
MBEDTLS_PSA_CRYPTO_SE_C
MBEDTLS_PSA_CRYPTO_STORAGE_C
);

View File

@ -1,9 +1,15 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""Generate programs/psa/psa_constant_names_generated.c
which is included by programs/psa/psa_constant_names.c.
The code generated by this module is only meant to be used in the context
of that program.
"""
import os
import re
import sys
output_template = '''\
OUTPUT_TEMPLATE = '''\
/* Automatically generated by generate_psa_constant.py. DO NOT EDIT. */
static const char *psa_strerror(psa_status_t status)
@ -22,6 +28,14 @@ static const char *psa_ecc_curve_name(psa_ecc_curve_t curve)
}
}
static const char *psa_dh_group_name(psa_dh_group_t group)
{
switch (group) {
%(dh_group_cases)s
default: return NULL;
}
}
static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg)
{
switch (hash_alg) {
@ -30,6 +44,14 @@ static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg)
}
}
static const char *psa_ka_algorithm_name(psa_algorithm_t ka_alg)
{
switch (ka_alg) {
%(ka_algorithm_cases)s
default: return NULL;
}
}
static int psa_snprint_key_type(char *buffer, size_t buffer_size,
psa_key_type_t type)
{
@ -47,12 +69,13 @@ static int psa_snprint_key_type(char *buffer, size_t buffer_size,
return (int) required_size;
}
#define NO_LENGTH_MODIFIER 0xfffffffflu
static int psa_snprint_algorithm(char *buffer, size_t buffer_size,
psa_algorithm_t alg)
{
size_t required_size = 0;
psa_algorithm_t core_alg = alg;
unsigned long length_modifier = 0;
unsigned long length_modifier = NO_LENGTH_MODIFIER;
if (PSA_ALG_IS_MAC(alg)) {
core_alg = PSA_ALG_TRUNCATED_MAC(alg, 0);
if (core_alg != alg) {
@ -70,6 +93,15 @@ static int psa_snprint_algorithm(char *buffer, size_t buffer_size,
"PSA_ALG_AEAD_WITH_TAG_LENGTH(", 29);
length_modifier = PSA_AEAD_TAG_LENGTH(alg);
}
} else if (PSA_ALG_IS_KEY_AGREEMENT(alg) &&
!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
core_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
append(&buffer, buffer_size, &required_size,
"PSA_ALG_KEY_AGREEMENT(", 22);
append_with_alg(&buffer, buffer_size, &required_size,
psa_ka_algorithm_name,
PSA_ALG_KEY_AGREEMENT_GET_BASE(alg));
append(&buffer, buffer_size, &required_size, ", ", 2);
}
switch (core_alg) {
%(algorithm_cases)s
@ -81,9 +113,11 @@ static int psa_snprint_algorithm(char *buffer, size_t buffer_size,
break;
}
if (core_alg != alg) {
append(&buffer, buffer_size, &required_size, ", ", 2);
append_integer(&buffer, buffer_size, &required_size,
"%%lu", length_modifier);
if (length_modifier != NO_LENGTH_MODIFIER) {
append(&buffer, buffer_size, &required_size, ", ", 2);
append_integer(&buffer, buffer_size, &required_size,
"%%lu", length_modifier);
}
append(&buffer, buffer_size, &required_size, ")", 1);
}
buffer[0] = 0;
@ -119,19 +153,28 @@ static int psa_snprint_key_usage(char *buffer, size_t buffer_size,
/* End of automatically generated file. */
'''
key_type_from_curve_template = '''if (%(tester)s(type)) {
KEY_TYPE_FROM_CURVE_TEMPLATE = '''if (%(tester)s(type)) {
append_with_curve(&buffer, buffer_size, &required_size,
"%(builder)s", %(builder_length)s,
PSA_KEY_TYPE_GET_CURVE(type));
} else '''
algorithm_from_hash_template = '''if (%(tester)s(core_alg)) {
append_with_hash(&buffer, buffer_size, &required_size,
"%(builder)s", %(builder_length)s,
PSA_ALG_GET_HASH(core_alg));
KEY_TYPE_FROM_GROUP_TEMPLATE = '''if (%(tester)s(type)) {
append_with_group(&buffer, buffer_size, &required_size,
"%(builder)s", %(builder_length)s,
PSA_KEY_TYPE_GET_GROUP(type));
} else '''
bit_test_template = '''\
ALGORITHM_FROM_HASH_TEMPLATE = '''if (%(tester)s(core_alg)) {
append(&buffer, buffer_size, &required_size,
"%(builder)s(", %(builder_length)s + 1);
append_with_alg(&buffer, buffer_size, &required_size,
psa_hash_algorithm_name,
PSA_ALG_GET_HASH(core_alg));
append(&buffer, buffer_size, &required_size, ")", 1);
} else '''
BIT_TEST_TEMPLATE = '''\
if (%(var)s & %(flag)s) {
if (required_size != 0) {
append(&buffer, buffer_size, &required_size, " | ", 3);
@ -142,13 +185,22 @@ bit_test_template = '''\
'''
class MacroCollector:
"""Collect PSA crypto macro definitions from C header files.
1. Call `read_file` on the input header file(s).
2. Call `write_file` to write ``psa_constant_names_generated.c``.
"""
def __init__(self):
self.statuses = set()
self.key_types = set()
self.key_types_from_curve = {}
self.key_types_from_group = {}
self.ecc_curves = set()
self.dh_groups = set()
self.algorithms = set()
self.hash_algorithms = set()
self.ka_algorithms = set()
self.algorithms_from_hash = {}
self.key_usages = set()
@ -158,6 +210,11 @@ class MacroCollector:
definition_re = re.compile(r'\s*#\s*define\s+(\w+)(?:\s+|\((\w+)\)\s*)(.+)(?:/[*/])?')
def read_line(self, line):
"""Parse a C header line and record the PSA identifier it defines if any.
This function analyzes lines that start with "#define PSA_"
(up to non-significant whitespace) and skips all non-matching lines.
"""
# pylint: disable=too-many-branches
m = re.match(self.definition_re, line)
if not m:
return
@ -167,12 +224,11 @@ class MacroCollector:
return
elif (name.startswith('PSA_ERROR_') or name == 'PSA_SUCCESS') \
and not parameter:
if name in [
'PSA_ERROR_UNKNOWN_ERROR',
if name in ['PSA_ERROR_UNKNOWN_ERROR',
'PSA_ERROR_OCCUPIED_SLOT',
'PSA_ERROR_EMPTY_SLOT',
'PSA_ERROR_INSUFFICIENT_CAPACITY',
]:
]:
# Ad hoc skipping of deprecated error codes, which share
# numerical values with non-deprecated error codes
return
@ -182,8 +238,12 @@ class MacroCollector:
self.key_types.add(name)
elif name.startswith('PSA_KEY_TYPE_') and parameter == 'curve':
self.key_types_from_curve[name] = name[:13] + 'IS_' + name[13:]
elif name.startswith('PSA_KEY_TYPE_') and parameter == 'group':
self.key_types_from_group[name] = name[:13] + 'IS_' + name[13:]
elif name.startswith('PSA_ECC_CURVE_') and not parameter:
self.ecc_curves.add(name)
elif name.startswith('PSA_DH_GROUP_') and not parameter:
self.dh_groups.add(name)
elif name.startswith('PSA_ALG_') and not parameter:
if name in ['PSA_ALG_ECDSA_BASE',
'PSA_ALG_RSA_PKCS1V15_SIGN_BASE']:
@ -193,6 +253,9 @@ class MacroCollector:
# Ad hoc detection of hash algorithms
if re.search(r'0x010000[0-9A-Fa-f]{2}', definition):
self.hash_algorithms.add(name)
# Ad hoc detection of key agreement algorithms
if re.search(r'0x30[0-9A-Fa-f]{2}0000', definition):
self.ka_algorithms.add(name)
elif name.startswith('PSA_ALG_') and parameter == 'hash_alg':
if name in ['PSA_ALG_DSA', 'PSA_ALG_ECDSA']:
# A naming irregularity
@ -210,81 +273,105 @@ class MacroCollector:
for line in header_file:
self.read_line(line)
def make_return_case(self, name):
@staticmethod
def _make_return_case(name):
return 'case %(name)s: return "%(name)s";' % {'name': name}
def make_append_case(self, name):
@staticmethod
def _make_append_case(name):
template = ('case %(name)s: '
'append(&buffer, buffer_size, &required_size, "%(name)s", %(length)d); '
'break;')
return template % {'name': name, 'length': len(name)}
def make_inner_append_case(self, name):
template = ('case %(name)s: '
'append(buffer, buffer_size, required_size, "%(name)s", %(length)d); '
'break;')
return template % {'name': name, 'length': len(name)}
def make_bit_test(self, var, flag):
return bit_test_template % {'var': var,
@staticmethod
def _make_bit_test(var, flag):
return BIT_TEST_TEMPLATE % {'var': var,
'flag': flag,
'length': len(flag)}
def make_status_cases(self):
return '\n '.join(map(self.make_return_case,
def _make_status_cases(self):
return '\n '.join(map(self._make_return_case,
sorted(self.statuses)))
def make_ecc_curve_cases(self):
return '\n '.join(map(self.make_return_case,
def _make_ecc_curve_cases(self):
return '\n '.join(map(self._make_return_case,
sorted(self.ecc_curves)))
def make_key_type_cases(self):
return '\n '.join(map(self.make_append_case,
def _make_dh_group_cases(self):
return '\n '.join(map(self._make_return_case,
sorted(self.dh_groups)))
def _make_key_type_cases(self):
return '\n '.join(map(self._make_append_case,
sorted(self.key_types)))
def make_key_type_from_curve_code(self, builder, tester):
return key_type_from_curve_template % {'builder': builder,
@staticmethod
def _make_key_type_from_curve_code(builder, tester):
return KEY_TYPE_FROM_CURVE_TEMPLATE % {'builder': builder,
'builder_length': len(builder),
'tester': tester}
def make_key_type_code(self):
@staticmethod
def _make_key_type_from_group_code(builder, tester):
return KEY_TYPE_FROM_GROUP_TEMPLATE % {'builder': builder,
'builder_length': len(builder),
'tester': tester}
def _make_ecc_key_type_code(self):
d = self.key_types_from_curve
make = self.make_key_type_from_curve_code
make = self._make_key_type_from_curve_code
return ''.join([make(k, d[k]) for k in sorted(d.keys())])
def make_hash_algorithm_cases(self):
return '\n '.join(map(self.make_return_case,
def _make_dh_key_type_code(self):
d = self.key_types_from_group
make = self._make_key_type_from_group_code
return ''.join([make(k, d[k]) for k in sorted(d.keys())])
def _make_hash_algorithm_cases(self):
return '\n '.join(map(self._make_return_case,
sorted(self.hash_algorithms)))
def make_algorithm_cases(self):
return '\n '.join(map(self.make_append_case,
def _make_ka_algorithm_cases(self):
return '\n '.join(map(self._make_return_case,
sorted(self.ka_algorithms)))
def _make_algorithm_cases(self):
return '\n '.join(map(self._make_append_case,
sorted(self.algorithms)))
def make_algorithm_from_hash_code(self, builder, tester):
return algorithm_from_hash_template % {'builder': builder,
@staticmethod
def _make_algorithm_from_hash_code(builder, tester):
return ALGORITHM_FROM_HASH_TEMPLATE % {'builder': builder,
'builder_length': len(builder),
'tester': tester}
def make_algorithm_code(self):
def _make_algorithm_code(self):
d = self.algorithms_from_hash
make = self.make_algorithm_from_hash_code
make = self._make_algorithm_from_hash_code
return ''.join([make(k, d[k]) for k in sorted(d.keys())])
def make_key_usage_code(self):
return '\n'.join([self.make_bit_test('usage', bit)
def _make_key_usage_code(self):
return '\n'.join([self._make_bit_test('usage', bit)
for bit in sorted(self.key_usages)])
def write_file(self, output_file):
"""Generate the pretty-printer function code from the gathered
constant definitions.
"""
data = {}
data['status_cases'] = self.make_status_cases()
data['ecc_curve_cases'] = self.make_ecc_curve_cases()
data['key_type_cases'] = self.make_key_type_cases()
data['key_type_code'] = self.make_key_type_code()
data['hash_algorithm_cases'] = self.make_hash_algorithm_cases()
data['algorithm_cases'] = self.make_algorithm_cases()
data['algorithm_code'] = self.make_algorithm_code()
data['key_usage_code'] = self.make_key_usage_code()
output_file.write(output_template % data)
data['status_cases'] = self._make_status_cases()
data['ecc_curve_cases'] = self._make_ecc_curve_cases()
data['dh_group_cases'] = self._make_dh_group_cases()
data['key_type_cases'] = self._make_key_type_cases()
data['key_type_code'] = (self._make_ecc_key_type_code() +
self._make_dh_key_type_code())
data['hash_algorithm_cases'] = self._make_hash_algorithm_cases()
data['ka_algorithm_cases'] = self._make_ka_algorithm_cases()
data['algorithm_cases'] = self._make_algorithm_cases()
data['algorithm_code'] = self._make_algorithm_code()
data['key_usage_code'] = self._make_key_usage_code()
output_file.write(OUTPUT_TEMPLATE % data)
def generate_psa_constants(header_file_names, output_file_name):
collector = MacroCollector()