mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-03-04 13:29:39 +00:00
Merge pull request #5754 from gilles-peskine-arm/psa-storage-format-test-exercise-2.28
Backport 2.28: PSA storage format: exercise key
This commit is contained in:
commit
9aa892b833
3
ChangeLog.d/psa-rc4.txt
Normal file
3
ChangeLog.d/psa-rc4.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Bugfix
|
||||||
|
* Fix PSA cipher multipart operations using ARC4. Previously, an IV was
|
||||||
|
required but discarded. Now, an IV is rejected, as it should be.
|
|
@ -272,7 +272,6 @@ extern "C" {
|
||||||
#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \
|
#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \
|
||||||
(defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \
|
(defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \
|
||||||
(defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \
|
(defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \
|
||||||
(defined(PSA_WANT_ALG_XTS) && !defined(MBEDTLS_PSA_ACCEL_ALG_XTS)) || \
|
|
||||||
defined(PSA_WANT_ALG_ECB_NO_PADDING) || \
|
defined(PSA_WANT_ALG_ECB_NO_PADDING) || \
|
||||||
(defined(PSA_WANT_ALG_CBC_NO_PADDING) && \
|
(defined(PSA_WANT_ALG_CBC_NO_PADDING) && \
|
||||||
!defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \
|
!defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \
|
||||||
|
@ -401,14 +400,6 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#endif /* PSA_WANT_ALG_OFB */
|
#endif /* PSA_WANT_ALG_OFB */
|
||||||
|
|
||||||
#if defined(PSA_WANT_ALG_XTS)
|
|
||||||
#if !defined(MBEDTLS_PSA_ACCEL_ALG_XTS) || \
|
|
||||||
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
|
|
||||||
#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1
|
|
||||||
#define MBEDTLS_CIPHER_MODE_XTS
|
|
||||||
#endif
|
|
||||||
#endif /* PSA_WANT_ALG_XTS */
|
|
||||||
|
|
||||||
#if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \
|
#if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \
|
||||||
!defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)
|
!defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)
|
||||||
#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
|
#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
|
||||||
|
@ -760,11 +751,6 @@ extern "C" {
|
||||||
#define PSA_WANT_ALG_OFB 1
|
#define PSA_WANT_ALG_OFB 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
|
||||||
#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1
|
|
||||||
#define PSA_WANT_ALG_XTS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
|
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
|
||||||
#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1
|
#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1
|
||||||
#define PSA_WANT_ECC_BRAINPOOL_P_R1_256
|
#define PSA_WANT_ECC_BRAINPOOL_P_R1_256
|
||||||
|
|
|
@ -103,7 +103,6 @@ typedef struct
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \
|
defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \
|
defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
|
defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_XTS) || \
|
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
|
defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
|
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
|
||||||
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
|
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
|
||||||
|
|
|
@ -86,7 +86,9 @@
|
||||||
#define PSA_WANT_ALG_STREAM_CIPHER 1
|
#define PSA_WANT_ALG_STREAM_CIPHER 1
|
||||||
#define PSA_WANT_ALG_TLS12_PRF 1
|
#define PSA_WANT_ALG_TLS12_PRF 1
|
||||||
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
|
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
|
||||||
#define PSA_WANT_ALG_XTS 1
|
/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
|
||||||
|
* Note: when adding support, also adjust include/mbedtls/config_psa.h */
|
||||||
|
//#define PSA_WANT_ALG_XTS 1
|
||||||
|
|
||||||
#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1
|
#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1
|
||||||
#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1
|
#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1
|
||||||
|
|
|
@ -440,9 +440,9 @@
|
||||||
* Camellia block cipher. */
|
* Camellia block cipher. */
|
||||||
#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403)
|
#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403)
|
||||||
|
|
||||||
/** Key for the RC4 stream cipher.
|
/** Key for the ARC4 stream cipher (also known as RC4 or ARCFOUR).
|
||||||
*
|
*
|
||||||
* Note that RC4 is weak and deprecated and should only be used in
|
* Note that ARC4 is weak and deprecated and should only be used in
|
||||||
* legacy protocols. */
|
* legacy protocols. */
|
||||||
#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002)
|
#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002)
|
||||||
|
|
||||||
|
|
|
@ -3359,6 +3359,8 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
|
||||||
operation->iv_set = 0;
|
operation->iv_set = 0;
|
||||||
if( alg == PSA_ALG_ECB_NO_PADDING )
|
if( alg == PSA_ALG_ECB_NO_PADDING )
|
||||||
operation->iv_required = 0;
|
operation->iv_required = 0;
|
||||||
|
else if( slot->attr.type == PSA_KEY_TYPE_ARC4 )
|
||||||
|
operation->iv_required = 0;
|
||||||
else
|
else
|
||||||
operation->iv_required = 1;
|
operation->iv_required = 1;
|
||||||
operation->default_iv_length = PSA_CIPHER_IV_LENGTH( slot->attr.type, alg );
|
operation->default_iv_length = PSA_CIPHER_IV_LENGTH( slot->attr.type, alg );
|
||||||
|
|
|
@ -20,11 +20,34 @@ This module is entirely based on the PSA API.
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import re
|
import re
|
||||||
from typing import Dict, Iterable, Optional, Pattern, Tuple
|
from typing import FrozenSet, Iterable, List, Optional, Tuple
|
||||||
|
|
||||||
from mbedtls_dev.asymmetric_key_data import ASYMMETRIC_KEY_DATA
|
from mbedtls_dev.asymmetric_key_data import ASYMMETRIC_KEY_DATA
|
||||||
|
|
||||||
|
|
||||||
|
def short_expression(original: str, level: int = 0) -> str:
|
||||||
|
"""Abbreviate the expression, keeping it human-readable.
|
||||||
|
|
||||||
|
If `level` is 0, just remove parts that are implicit from context,
|
||||||
|
such as a leading ``PSA_KEY_TYPE_``.
|
||||||
|
For larger values of `level`, also abbreviate some names in an
|
||||||
|
unambiguous, but ad hoc way.
|
||||||
|
"""
|
||||||
|
short = original
|
||||||
|
short = re.sub(r'\bPSA_(?:ALG|ECC_FAMILY|KEY_[A-Z]+)_', r'', short)
|
||||||
|
short = re.sub(r' +', r'', short)
|
||||||
|
if level >= 1:
|
||||||
|
short = re.sub(r'PUBLIC_KEY\b', r'PUB', short)
|
||||||
|
short = re.sub(r'KEY_PAIR\b', r'PAIR', short)
|
||||||
|
short = re.sub(r'\bBRAINPOOL_P', r'BP', short)
|
||||||
|
short = re.sub(r'\bMONTGOMERY\b', r'MGM', short)
|
||||||
|
short = re.sub(r'AEAD_WITH_SHORTENED_TAG\b', r'AEAD_SHORT', short)
|
||||||
|
short = re.sub(r'\bDETERMINISTIC_', r'DET_', short)
|
||||||
|
short = re.sub(r'\bKEY_AGREEMENT\b', r'KA', short)
|
||||||
|
short = re.sub(r'_PSK_TO_MS\b', r'_PSK2MS', short)
|
||||||
|
return short
|
||||||
|
|
||||||
|
|
||||||
BLOCK_CIPHERS = frozenset(['AES', 'ARIA', 'CAMELLIA', 'DES'])
|
BLOCK_CIPHERS = frozenset(['AES', 'ARIA', 'CAMELLIA', 'DES'])
|
||||||
BLOCK_MAC_MODES = frozenset(['CBC_MAC', 'CMAC'])
|
BLOCK_MAC_MODES = frozenset(['CBC_MAC', 'CMAC'])
|
||||||
BLOCK_CIPHER_MODES = frozenset([
|
BLOCK_CIPHER_MODES = frozenset([
|
||||||
|
@ -104,6 +127,13 @@ class KeyType:
|
||||||
`self.name`.
|
`self.name`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def short_expression(self, level: int = 0) -> str:
|
||||||
|
"""Abbreviate the expression, keeping it human-readable.
|
||||||
|
|
||||||
|
See `crypto_knowledge.short_expression`.
|
||||||
|
"""
|
||||||
|
return short_expression(self.expression, level=level)
|
||||||
|
|
||||||
def is_public(self) -> bool:
|
def is_public(self) -> bool:
|
||||||
"""Whether the key type is for public keys."""
|
"""Whether the key type is for public keys."""
|
||||||
return self.name.endswith('_PUBLIC_KEY')
|
return self.name.endswith('_PUBLIC_KEY')
|
||||||
|
@ -176,35 +206,31 @@ class KeyType:
|
||||||
return b''.join([self.DATA_BLOCK] * (length // len(self.DATA_BLOCK)) +
|
return b''.join([self.DATA_BLOCK] * (length // len(self.DATA_BLOCK)) +
|
||||||
[self.DATA_BLOCK[:length % len(self.DATA_BLOCK)]])
|
[self.DATA_BLOCK[:length % len(self.DATA_BLOCK)]])
|
||||||
|
|
||||||
KEY_TYPE_FOR_SIGNATURE = {
|
|
||||||
'PSA_KEY_USAGE_SIGN_HASH': re.compile('.*KEY_PAIR'),
|
|
||||||
'PSA_KEY_USAGE_VERIFY_HASH': re.compile('.*KEY.*')
|
|
||||||
} #type: Dict[str, Pattern]
|
|
||||||
"""Use a regexp to determine key types for which signature is possible
|
|
||||||
when using the actual usage flag.
|
|
||||||
"""
|
|
||||||
def is_valid_for_signature(self, usage: str) -> bool:
|
|
||||||
"""Determine if the key type is compatible with the specified
|
|
||||||
signitute type.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# This is just temporaly solution for the implicit usage flags.
|
|
||||||
return re.match(self.KEY_TYPE_FOR_SIGNATURE[usage], self.name) is not None
|
|
||||||
|
|
||||||
def can_do(self, alg: 'Algorithm') -> bool:
|
def can_do(self, alg: 'Algorithm') -> bool:
|
||||||
"""Whether this key type can be used for operations with the given algorithm.
|
"""Whether this key type can be used for operations with the given algorithm.
|
||||||
|
|
||||||
This function does not currently handle key derivation or PAKE.
|
This function does not currently handle key derivation or PAKE.
|
||||||
"""
|
"""
|
||||||
#pylint: disable=too-many-return-statements
|
#pylint: disable=too-many-branches,too-many-return-statements
|
||||||
if alg.is_wildcard:
|
if alg.is_wildcard:
|
||||||
return False
|
return False
|
||||||
|
if alg.is_invalid_truncation():
|
||||||
|
return False
|
||||||
if self.head == 'HMAC' and alg.head == 'HMAC':
|
if self.head == 'HMAC' and alg.head == 'HMAC':
|
||||||
return True
|
return True
|
||||||
|
if self.head == 'DES':
|
||||||
|
# 64-bit block ciphers only allow a reduced set of modes.
|
||||||
|
return alg.head in [
|
||||||
|
'CBC_NO_PADDING', 'CBC_PKCS7',
|
||||||
|
'ECB_NO_PADDING',
|
||||||
|
]
|
||||||
if self.head in BLOCK_CIPHERS and \
|
if self.head in BLOCK_CIPHERS and \
|
||||||
alg.head in frozenset.union(BLOCK_MAC_MODES,
|
alg.head in frozenset.union(BLOCK_MAC_MODES,
|
||||||
BLOCK_CIPHER_MODES,
|
BLOCK_CIPHER_MODES,
|
||||||
BLOCK_AEAD_MODES):
|
BLOCK_AEAD_MODES):
|
||||||
|
if alg.head in ['CMAC', 'OFB'] and \
|
||||||
|
self.head in ['ARIA', 'CAMELLIA']:
|
||||||
|
return False # not implemented in Mbed TLS
|
||||||
return True
|
return True
|
||||||
if self.head == 'CHACHA20' and alg.head == 'CHACHA20_POLY1305':
|
if self.head == 'CHACHA20' and alg.head == 'CHACHA20_POLY1305':
|
||||||
return True
|
return True
|
||||||
|
@ -213,6 +239,13 @@ class KeyType:
|
||||||
return True
|
return True
|
||||||
if self.head == 'RSA' and alg.head.startswith('RSA_'):
|
if self.head == 'RSA' and alg.head.startswith('RSA_'):
|
||||||
return True
|
return True
|
||||||
|
if alg.category == AlgorithmCategory.KEY_AGREEMENT and \
|
||||||
|
self.is_public():
|
||||||
|
# The PSA API does not use public key objects in key agreement
|
||||||
|
# operations: it imports the public key as a formatted byte string.
|
||||||
|
# So a public key object with a key agreement algorithm is not
|
||||||
|
# a valid combination.
|
||||||
|
return False
|
||||||
if self.head == 'ECC':
|
if self.head == 'ECC':
|
||||||
assert self.params is not None
|
assert self.params is not None
|
||||||
eccc = EllipticCurveCategory.from_family(self.params[0])
|
eccc = EllipticCurveCategory.from_family(self.params[0])
|
||||||
|
@ -389,11 +422,113 @@ class Algorithm:
|
||||||
# Assume kdf_alg is either a valid KDF or 0.
|
# Assume kdf_alg is either a valid KDF or 0.
|
||||||
return not re.match(r'(?:0[Xx])?0+\s*\Z', kdf_alg)
|
return not re.match(r'(?:0[Xx])?0+\s*\Z', kdf_alg)
|
||||||
|
|
||||||
|
|
||||||
|
def short_expression(self, level: int = 0) -> str:
|
||||||
|
"""Abbreviate the expression, keeping it human-readable.
|
||||||
|
|
||||||
|
See `crypto_knowledge.short_expression`.
|
||||||
|
"""
|
||||||
|
return short_expression(self.expression, level=level)
|
||||||
|
|
||||||
|
HASH_LENGTH = {
|
||||||
|
'PSA_ALG_MD5': 16,
|
||||||
|
'PSA_ALG_SHA_1': 20,
|
||||||
|
}
|
||||||
|
HASH_LENGTH_BITS_RE = re.compile(r'([0-9]+)\Z')
|
||||||
|
@classmethod
|
||||||
|
def hash_length(cls, alg: str) -> int:
|
||||||
|
"""The length of the given hash algorithm, in bytes."""
|
||||||
|
if alg in cls.HASH_LENGTH:
|
||||||
|
return cls.HASH_LENGTH[alg]
|
||||||
|
m = cls.HASH_LENGTH_BITS_RE.search(alg)
|
||||||
|
if m:
|
||||||
|
return int(m.group(1)) // 8
|
||||||
|
raise ValueError('Unknown hash length for ' + alg)
|
||||||
|
|
||||||
|
PERMITTED_TAG_LENGTHS = {
|
||||||
|
'PSA_ALG_CCM': frozenset([4, 6, 8, 10, 12, 14, 16]),
|
||||||
|
'PSA_ALG_CHACHA20_POLY1305': frozenset([16]),
|
||||||
|
'PSA_ALG_GCM': frozenset([4, 8, 12, 13, 14, 15, 16]),
|
||||||
|
}
|
||||||
|
MAC_LENGTH = {
|
||||||
|
'PSA_ALG_CBC_MAC': 16, # actually the block cipher length
|
||||||
|
'PSA_ALG_CMAC': 16, # actually the block cipher length
|
||||||
|
}
|
||||||
|
HMAC_RE = re.compile(r'PSA_ALG_HMAC\((.*)\)\Z')
|
||||||
|
@classmethod
|
||||||
|
def permitted_truncations(cls, base: str) -> FrozenSet[int]:
|
||||||
|
"""Permitted output lengths for the given MAC or AEAD base algorithm.
|
||||||
|
|
||||||
|
For a MAC algorithm, this is the set of truncation lengths that
|
||||||
|
Mbed TLS supports.
|
||||||
|
For an AEAD algorithm, this is the set of truncation lengths that
|
||||||
|
are permitted by the algorithm specification.
|
||||||
|
"""
|
||||||
|
if base in cls.PERMITTED_TAG_LENGTHS:
|
||||||
|
return cls.PERMITTED_TAG_LENGTHS[base]
|
||||||
|
max_length = cls.MAC_LENGTH.get(base, None)
|
||||||
|
if max_length is None:
|
||||||
|
m = cls.HMAC_RE.match(base)
|
||||||
|
if m:
|
||||||
|
max_length = cls.hash_length(m.group(1))
|
||||||
|
if max_length is None:
|
||||||
|
raise ValueError('Unknown permitted lengths for ' + base)
|
||||||
|
return frozenset(range(4, max_length + 1))
|
||||||
|
|
||||||
|
TRUNCATED_ALG_RE = re.compile(
|
||||||
|
r'(?P<face>PSA_ALG_(?:AEAD_WITH_SHORTENED_TAG|TRUNCATED_MAC))'
|
||||||
|
r'\((?P<base>.*),'
|
||||||
|
r'(?P<length>0[Xx][0-9A-Fa-f]+|[1-9][0-9]*|0[0-7]*)[LUlu]*\)\Z')
|
||||||
|
def is_invalid_truncation(self) -> bool:
|
||||||
|
"""False for a MAC or AEAD algorithm truncated to an invalid length.
|
||||||
|
|
||||||
|
True for a MAC or AEAD algorithm truncated to a valid length or to
|
||||||
|
a length that cannot be determined. True for anything other than
|
||||||
|
a truncated MAC or AEAD.
|
||||||
|
"""
|
||||||
|
m = self.TRUNCATED_ALG_RE.match(self.expression)
|
||||||
|
if m:
|
||||||
|
base = m.group('base')
|
||||||
|
to_length = int(m.group('length'), 0)
|
||||||
|
permitted_lengths = self.permitted_truncations(base)
|
||||||
|
if to_length not in permitted_lengths:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def can_do(self, category: AlgorithmCategory) -> bool:
|
def can_do(self, category: AlgorithmCategory) -> bool:
|
||||||
"""Whether this algorithm fits the specified operation category."""
|
"""Whether this algorithm can perform operations in the given category.
|
||||||
|
"""
|
||||||
if category == self.category:
|
if category == self.category:
|
||||||
return True
|
return True
|
||||||
if category == AlgorithmCategory.KEY_DERIVATION and \
|
if category == AlgorithmCategory.KEY_DERIVATION and \
|
||||||
self.is_key_agreement_with_derivation():
|
self.is_key_agreement_with_derivation():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def usage_flags(self, public: bool = False) -> List[str]:
|
||||||
|
"""The list of usage flags describing operations that can perform this algorithm.
|
||||||
|
|
||||||
|
If public is true, only return public-key operations, not private-key operations.
|
||||||
|
"""
|
||||||
|
if self.category == AlgorithmCategory.HASH:
|
||||||
|
flags = []
|
||||||
|
elif self.category == AlgorithmCategory.MAC:
|
||||||
|
flags = ['SIGN_HASH', 'SIGN_MESSAGE',
|
||||||
|
'VERIFY_HASH', 'VERIFY_MESSAGE']
|
||||||
|
elif self.category == AlgorithmCategory.CIPHER or \
|
||||||
|
self.category == AlgorithmCategory.AEAD:
|
||||||
|
flags = ['DECRYPT', 'ENCRYPT']
|
||||||
|
elif self.category == AlgorithmCategory.SIGN:
|
||||||
|
flags = ['VERIFY_HASH', 'VERIFY_MESSAGE']
|
||||||
|
if not public:
|
||||||
|
flags += ['SIGN_HASH', 'SIGN_MESSAGE']
|
||||||
|
elif self.category == AlgorithmCategory.ASYMMETRIC_ENCRYPTION:
|
||||||
|
flags = ['ENCRYPT']
|
||||||
|
if not public:
|
||||||
|
flags += ['DECRYPT']
|
||||||
|
elif self.category == AlgorithmCategory.KEY_DERIVATION or \
|
||||||
|
self.category == AlgorithmCategory.KEY_AGREEMENT:
|
||||||
|
flags = ['DERIVE']
|
||||||
|
else:
|
||||||
|
raise AlgorithmNotRecognized(self.expression)
|
||||||
|
return ['PSA_KEY_USAGE_' + flag for flag in flags]
|
||||||
|
|
|
@ -185,7 +185,7 @@ class PSAMacroEnumerator:
|
||||||
for value in argument_lists[i][1:]:
|
for value in argument_lists[i][1:]:
|
||||||
arguments[i] = value
|
arguments[i] = value
|
||||||
yield self._format_arguments(name, arguments)
|
yield self._format_arguments(name, arguments)
|
||||||
arguments[i] = argument_lists[0][0]
|
arguments[i] = argument_lists[i][0]
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
raise Exception('distribute_arguments({})'.format(name)) from e
|
raise Exception('distribute_arguments({})'.format(name)) from e
|
||||||
|
|
||||||
|
@ -398,10 +398,26 @@ enumerate
|
||||||
'other_algorithm': [],
|
'other_algorithm': [],
|
||||||
'lifetime': [self.lifetimes],
|
'lifetime': [self.lifetimes],
|
||||||
} #type: Dict[str, List[Set[str]]]
|
} #type: Dict[str, List[Set[str]]]
|
||||||
self.arguments_for['mac_length'] += ['1', '63']
|
mac_lengths = [str(n) for n in [
|
||||||
self.arguments_for['min_mac_length'] += ['1', '63']
|
1, # minimum expressible
|
||||||
self.arguments_for['tag_length'] += ['1', '63']
|
4, # minimum allowed by policy
|
||||||
self.arguments_for['min_tag_length'] += ['1', '63']
|
13, # an odd size in a plausible range
|
||||||
|
14, # an even non-power-of-two size in a plausible range
|
||||||
|
16, # same as full size for at least one algorithm
|
||||||
|
63, # maximum expressible
|
||||||
|
]]
|
||||||
|
self.arguments_for['mac_length'] += mac_lengths
|
||||||
|
self.arguments_for['min_mac_length'] += mac_lengths
|
||||||
|
aead_lengths = [str(n) for n in [
|
||||||
|
1, # minimum expressible
|
||||||
|
4, # minimum allowed by policy
|
||||||
|
13, # an odd size in a plausible range
|
||||||
|
14, # an even non-power-of-two size in a plausible range
|
||||||
|
16, # same as full size for at least one algorithm
|
||||||
|
63, # maximum expressible
|
||||||
|
]]
|
||||||
|
self.arguments_for['tag_length'] += aead_lengths
|
||||||
|
self.arguments_for['min_tag_length'] += aead_lengths
|
||||||
|
|
||||||
def add_numerical_values(self) -> None:
|
def add_numerical_values(self) -> None:
|
||||||
"""Add numerical values that are not supported to the known identifiers."""
|
"""Add numerical values that are not supported to the known identifiers."""
|
||||||
|
|
|
@ -1609,6 +1609,10 @@ component_test_psa_crypto_config_accel_ecdsa () {
|
||||||
# partial support for cipher operations in the driver test library.
|
# partial support for cipher operations in the driver test library.
|
||||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
|
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
|
||||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
|
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
|
||||||
|
# Disable obsolete hashes (alternatively we could enable support for them
|
||||||
|
# in the driver test library).
|
||||||
|
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD2
|
||||||
|
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD4
|
||||||
|
|
||||||
# SHA384 needed for some ECDSA signature tests.
|
# SHA384 needed for some ECDSA signature tests.
|
||||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
|
scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
|
||||||
|
|
|
@ -143,7 +143,7 @@ def test_case_for_key_type_not_supported(
|
||||||
"""
|
"""
|
||||||
hack_dependencies_not_implemented(dependencies)
|
hack_dependencies_not_implemented(dependencies)
|
||||||
tc = test_case.TestCase()
|
tc = test_case.TestCase()
|
||||||
short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
|
short_key_type = crypto_knowledge.short_expression(key_type)
|
||||||
adverb = 'not' if dependencies else 'never'
|
adverb = 'not' if dependencies else 'never'
|
||||||
if param_descr:
|
if param_descr:
|
||||||
adverb = param_descr + ' ' + adverb
|
adverb = param_descr + ' ' + adverb
|
||||||
|
@ -204,7 +204,7 @@ class NotSupported:
|
||||||
continue
|
continue
|
||||||
# For public key we expect that key generation fails with
|
# For public key we expect that key generation fails with
|
||||||
# INVALID_ARGUMENT. It is handled by KeyGenerate class.
|
# INVALID_ARGUMENT. It is handled by KeyGenerate class.
|
||||||
if not kt.name.endswith('_PUBLIC_KEY'):
|
if not kt.is_public():
|
||||||
yield test_case_for_key_type_not_supported(
|
yield test_case_for_key_type_not_supported(
|
||||||
'generate', kt.expression, bits,
|
'generate', kt.expression, bits,
|
||||||
finish_family_dependencies(generate_dependencies, bits),
|
finish_family_dependencies(generate_dependencies, bits),
|
||||||
|
@ -241,7 +241,7 @@ def test_case_for_key_generation(
|
||||||
"""
|
"""
|
||||||
hack_dependencies_not_implemented(dependencies)
|
hack_dependencies_not_implemented(dependencies)
|
||||||
tc = test_case.TestCase()
|
tc = test_case.TestCase()
|
||||||
short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
|
short_key_type = crypto_knowledge.short_expression(key_type)
|
||||||
tc.set_description('PSA {} {}-bit'
|
tc.set_description('PSA {} {}-bit'
|
||||||
.format(short_key_type, bits))
|
.format(short_key_type, bits))
|
||||||
tc.set_dependencies(dependencies)
|
tc.set_dependencies(dependencies)
|
||||||
|
@ -333,7 +333,7 @@ class OpFail:
|
||||||
"""Construct a failure test case for a one-key or keyless operation."""
|
"""Construct a failure test case for a one-key or keyless operation."""
|
||||||
#pylint: disable=too-many-arguments,too-many-locals
|
#pylint: disable=too-many-arguments,too-many-locals
|
||||||
tc = test_case.TestCase()
|
tc = test_case.TestCase()
|
||||||
pretty_alg = re.sub(r'PSA_ALG_', r'', alg.expression)
|
pretty_alg = alg.short_expression()
|
||||||
if reason == self.Reason.NOT_SUPPORTED:
|
if reason == self.Reason.NOT_SUPPORTED:
|
||||||
short_deps = [re.sub(r'PSA_WANT_ALG_', r'', dep)
|
short_deps = [re.sub(r'PSA_WANT_ALG_', r'', dep)
|
||||||
for dep in not_deps]
|
for dep in not_deps]
|
||||||
|
@ -342,7 +342,7 @@ class OpFail:
|
||||||
pretty_reason = reason.name.lower()
|
pretty_reason = reason.name.lower()
|
||||||
if kt:
|
if kt:
|
||||||
key_type = kt.expression
|
key_type = kt.expression
|
||||||
pretty_type = re.sub(r'PSA_KEY_TYPE_', r'', key_type)
|
pretty_type = kt.short_expression()
|
||||||
else:
|
else:
|
||||||
key_type = ''
|
key_type = ''
|
||||||
pretty_type = ''
|
pretty_type = ''
|
||||||
|
@ -454,7 +454,7 @@ class StorageKey(psa_storage.Key):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
usage: str,
|
usage: Iterable[str],
|
||||||
without_implicit_usage: Optional[bool] = False,
|
without_implicit_usage: Optional[bool] = False,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -463,13 +463,16 @@ class StorageKey(psa_storage.Key):
|
||||||
* `usage` : The usage flags used for the key.
|
* `usage` : The usage flags used for the key.
|
||||||
* `without_implicit_usage`: Flag to defide to apply the usage extension
|
* `without_implicit_usage`: Flag to defide to apply the usage extension
|
||||||
"""
|
"""
|
||||||
super().__init__(usage=usage, **kwargs)
|
usage_flags = set(usage)
|
||||||
|
|
||||||
if not without_implicit_usage:
|
if not without_implicit_usage:
|
||||||
for flag, implicit in self.IMPLICIT_USAGE_FLAGS.items():
|
for flag in sorted(usage_flags):
|
||||||
if self.usage.value() & psa_storage.Expr(flag).value() and \
|
if flag in self.IMPLICIT_USAGE_FLAGS:
|
||||||
self.usage.value() & psa_storage.Expr(implicit).value() == 0:
|
usage_flags.add(self.IMPLICIT_USAGE_FLAGS[flag])
|
||||||
self.usage = psa_storage.Expr(self.usage.string + ' | ' + implicit)
|
if usage_flags:
|
||||||
|
usage_expression = ' | '.join(sorted(usage_flags))
|
||||||
|
else:
|
||||||
|
usage_expression = '0'
|
||||||
|
super().__init__(usage=usage_expression, **kwargs)
|
||||||
|
|
||||||
class StorageTestData(StorageKey):
|
class StorageTestData(StorageKey):
|
||||||
"""Representation of test case data for storage format testing."""
|
"""Representation of test case data for storage format testing."""
|
||||||
|
@ -477,7 +480,7 @@ class StorageTestData(StorageKey):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
description: str,
|
description: str,
|
||||||
expected_usage: Optional[str] = None,
|
expected_usage: Optional[List[str]] = None,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Prepare to generate test data
|
"""Prepare to generate test data
|
||||||
|
@ -489,7 +492,12 @@ class StorageTestData(StorageKey):
|
||||||
"""
|
"""
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.description = description #type: str
|
self.description = description #type: str
|
||||||
self.expected_usage = expected_usage if expected_usage else self.usage.string #type: str
|
if expected_usage is None:
|
||||||
|
self.expected_usage = self.usage #type: psa_storage.Expr
|
||||||
|
elif expected_usage:
|
||||||
|
self.expected_usage = psa_storage.Expr(' | '.join(expected_usage))
|
||||||
|
else:
|
||||||
|
self.expected_usage = psa_storage.Expr(0)
|
||||||
|
|
||||||
class StorageFormat:
|
class StorageFormat:
|
||||||
"""Storage format stability test cases."""
|
"""Storage format stability test cases."""
|
||||||
|
@ -508,6 +516,50 @@ class StorageFormat:
|
||||||
self.version = version #type: int
|
self.version = version #type: int
|
||||||
self.forward = forward #type: bool
|
self.forward = forward #type: bool
|
||||||
|
|
||||||
|
RSA_OAEP_RE = re.compile(r'PSA_ALG_RSA_OAEP\((.*)\)\Z')
|
||||||
|
BRAINPOOL_RE = re.compile(r'PSA_KEY_TYPE_\w+\(PSA_ECC_FAMILY_BRAINPOOL_\w+\)\Z')
|
||||||
|
@classmethod
|
||||||
|
def exercise_key_with_algorithm(
|
||||||
|
cls,
|
||||||
|
key_type: psa_storage.Expr, bits: int,
|
||||||
|
alg: psa_storage.Expr
|
||||||
|
) -> bool:
|
||||||
|
"""Whether to the given key with the given algorithm.
|
||||||
|
|
||||||
|
Normally only the type and algorithm matter for compatibility, and
|
||||||
|
this is handled in crypto_knowledge.KeyType.can_do(). This function
|
||||||
|
exists to detect exceptional cases. Exceptional cases detected here
|
||||||
|
are not tested in OpFail and should therefore have manually written
|
||||||
|
test cases.
|
||||||
|
"""
|
||||||
|
# Some test keys have the RAW_DATA type and attributes that don't
|
||||||
|
# necessarily make sense. We do this to validate numerical
|
||||||
|
# encodings of the attributes.
|
||||||
|
# Raw data keys have no useful exercise anyway so there is no
|
||||||
|
# loss of test coverage.
|
||||||
|
if key_type.string == 'PSA_KEY_TYPE_RAW_DATA':
|
||||||
|
return False
|
||||||
|
# Mbed TLS only supports 128-bit keys for RC4.
|
||||||
|
if key_type.string == 'PSA_KEY_TYPE_ARC4' and bits != 128:
|
||||||
|
return False
|
||||||
|
# OAEP requires room for two hashes plus wrapping
|
||||||
|
m = cls.RSA_OAEP_RE.match(alg.string)
|
||||||
|
if m:
|
||||||
|
hash_alg = m.group(1)
|
||||||
|
hash_length = crypto_knowledge.Algorithm.hash_length(hash_alg)
|
||||||
|
key_length = (bits + 7) // 8
|
||||||
|
# Leave enough room for at least one byte of plaintext
|
||||||
|
return key_length > 2 * hash_length + 2
|
||||||
|
# There's nothing wrong with ECC keys on Brainpool curves,
|
||||||
|
# but operations with them are very slow. So we only exercise them
|
||||||
|
# with a single algorithm, not with all possible hashes. We do
|
||||||
|
# exercise other curves with all algorithms so test coverage is
|
||||||
|
# perfectly adequate like this.
|
||||||
|
m = cls.BRAINPOOL_RE.match(key_type.string)
|
||||||
|
if m and alg.string != 'PSA_ALG_ECDSA_ANY':
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
|
def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
|
||||||
"""Construct a storage format test case for the given key.
|
"""Construct a storage format test case for the given key.
|
||||||
|
|
||||||
|
@ -519,10 +571,10 @@ class StorageFormat:
|
||||||
"""
|
"""
|
||||||
verb = 'save' if self.forward else 'read'
|
verb = 'save' if self.forward else 'read'
|
||||||
tc = test_case.TestCase()
|
tc = test_case.TestCase()
|
||||||
tc.set_description('PSA storage {}: {}'.format(verb, key.description))
|
tc.set_description(verb + ' ' + key.description)
|
||||||
dependencies = automatic_dependencies(
|
dependencies = automatic_dependencies(
|
||||||
key.lifetime.string, key.type.string,
|
key.lifetime.string, key.type.string,
|
||||||
key.expected_usage, key.alg.string, key.alg2.string,
|
key.alg.string, key.alg2.string,
|
||||||
)
|
)
|
||||||
dependencies = finish_family_dependencies(dependencies, key.bits)
|
dependencies = finish_family_dependencies(dependencies, key.bits)
|
||||||
tc.set_dependencies(dependencies)
|
tc.set_dependencies(dependencies)
|
||||||
|
@ -531,19 +583,15 @@ class StorageFormat:
|
||||||
extra_arguments = []
|
extra_arguments = []
|
||||||
else:
|
else:
|
||||||
flags = []
|
flags = []
|
||||||
# Some test keys have the RAW_DATA type and attributes that don't
|
if self.exercise_key_with_algorithm(key.type, key.bits, key.alg):
|
||||||
# necessarily make sense. We do this to validate numerical
|
|
||||||
# encodings of the attributes.
|
|
||||||
# Raw data keys have no useful exercise anyway so there is no
|
|
||||||
# loss of test coverage.
|
|
||||||
if key.type.string != 'PSA_KEY_TYPE_RAW_DATA':
|
|
||||||
flags.append('TEST_FLAG_EXERCISE')
|
flags.append('TEST_FLAG_EXERCISE')
|
||||||
if 'READ_ONLY' in key.lifetime.string:
|
if 'READ_ONLY' in key.lifetime.string:
|
||||||
flags.append('TEST_FLAG_READ_ONLY')
|
flags.append('TEST_FLAG_READ_ONLY')
|
||||||
extra_arguments = [' | '.join(flags) if flags else '0']
|
extra_arguments = [' | '.join(flags) if flags else '0']
|
||||||
tc.set_arguments([key.lifetime.string,
|
tc.set_arguments([key.lifetime.string,
|
||||||
key.type.string, str(key.bits),
|
key.type.string, str(key.bits),
|
||||||
key.expected_usage, key.alg.string, key.alg2.string,
|
key.expected_usage.string,
|
||||||
|
key.alg.string, key.alg2.string,
|
||||||
'"' + key.material.hex() + '"',
|
'"' + key.material.hex() + '"',
|
||||||
'"' + key.hex() + '"',
|
'"' + key.hex() + '"',
|
||||||
*extra_arguments])
|
*extra_arguments])
|
||||||
|
@ -557,12 +605,12 @@ class StorageFormat:
|
||||||
short = lifetime
|
short = lifetime
|
||||||
short = re.sub(r'PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION',
|
short = re.sub(r'PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION',
|
||||||
r'', short)
|
r'', short)
|
||||||
short = re.sub(r'PSA_KEY_[A-Z]+_', r'', short)
|
short = crypto_knowledge.short_expression(short)
|
||||||
description = 'lifetime: ' + short
|
description = 'lifetime: ' + short
|
||||||
key = StorageTestData(version=self.version,
|
key = StorageTestData(version=self.version,
|
||||||
id=1, lifetime=lifetime,
|
id=1, lifetime=lifetime,
|
||||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||||
usage='PSA_KEY_USAGE_EXPORT', alg=0, alg2=0,
|
usage=['PSA_KEY_USAGE_EXPORT'], alg=0, alg2=0,
|
||||||
material=b'L',
|
material=b'L',
|
||||||
description=description)
|
description=description)
|
||||||
return key
|
return key
|
||||||
|
@ -588,19 +636,21 @@ class StorageFormat:
|
||||||
test_implicit_usage: Optional[bool] = True
|
test_implicit_usage: Optional[bool] = True
|
||||||
) -> StorageTestData:
|
) -> StorageTestData:
|
||||||
"""Construct a test key for the given key usage."""
|
"""Construct a test key for the given key usage."""
|
||||||
usage = ' | '.join(usage_flags) if usage_flags else '0'
|
|
||||||
if short is None:
|
|
||||||
short = re.sub(r'\bPSA_KEY_USAGE_', r'', usage)
|
|
||||||
extra_desc = ' without implication' if test_implicit_usage else ''
|
extra_desc = ' without implication' if test_implicit_usage else ''
|
||||||
description = 'usage' + extra_desc + ': ' + short
|
description = 'usage' + extra_desc + ': '
|
||||||
key1 = StorageTestData(version=self.version,
|
key1 = StorageTestData(version=self.version,
|
||||||
id=1, lifetime=0x00000001,
|
id=1, lifetime=0x00000001,
|
||||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||||
expected_usage=usage,
|
expected_usage=usage_flags,
|
||||||
without_implicit_usage=not test_implicit_usage,
|
without_implicit_usage=not test_implicit_usage,
|
||||||
usage=usage, alg=0, alg2=0,
|
usage=usage_flags, alg=0, alg2=0,
|
||||||
material=b'K',
|
material=b'K',
|
||||||
description=description)
|
description=description)
|
||||||
|
if short is None:
|
||||||
|
usage_expr = key1.expected_usage.string
|
||||||
|
key1.description += crypto_knowledge.short_expression(usage_expr)
|
||||||
|
else:
|
||||||
|
key1.description += short
|
||||||
return key1
|
return key1
|
||||||
|
|
||||||
def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
|
def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
|
||||||
|
@ -621,49 +671,70 @@ class StorageFormat:
|
||||||
yield from self.generate_keys_for_usage_flags()
|
yield from self.generate_keys_for_usage_flags()
|
||||||
yield from self.generate_key_for_all_usage_flags()
|
yield from self.generate_key_for_all_usage_flags()
|
||||||
|
|
||||||
|
def key_for_type_and_alg(
|
||||||
|
self,
|
||||||
|
kt: crypto_knowledge.KeyType,
|
||||||
|
bits: int,
|
||||||
|
alg: Optional[crypto_knowledge.Algorithm] = None,
|
||||||
|
) -> StorageTestData:
|
||||||
|
"""Construct a test key of the given type.
|
||||||
|
|
||||||
|
If alg is not None, this key allows it.
|
||||||
|
"""
|
||||||
|
usage_flags = ['PSA_KEY_USAGE_EXPORT']
|
||||||
|
alg1 = 0 #type: psa_storage.Exprable
|
||||||
|
alg2 = 0
|
||||||
|
if alg is not None:
|
||||||
|
alg1 = alg.expression
|
||||||
|
usage_flags += alg.usage_flags(public=kt.is_public())
|
||||||
|
key_material = kt.key_material(bits)
|
||||||
|
description = 'type: {} {}-bit'.format(kt.short_expression(1), bits)
|
||||||
|
if alg is not None:
|
||||||
|
description += ', ' + alg.short_expression(1)
|
||||||
|
key = StorageTestData(version=self.version,
|
||||||
|
id=1, lifetime=0x00000001,
|
||||||
|
type=kt.expression, bits=bits,
|
||||||
|
usage=usage_flags, alg=alg1, alg2=alg2,
|
||||||
|
material=key_material,
|
||||||
|
description=description)
|
||||||
|
return key
|
||||||
|
|
||||||
def keys_for_type(
|
def keys_for_type(
|
||||||
self,
|
self,
|
||||||
key_type: str,
|
key_type: str,
|
||||||
params: Optional[Iterable[str]] = None
|
all_algorithms: List[crypto_knowledge.Algorithm],
|
||||||
) -> Iterator[StorageTestData]:
|
) -> Iterator[StorageTestData]:
|
||||||
"""Generate test keys for the given key type.
|
"""Generate test keys for the given key type."""
|
||||||
|
kt = crypto_knowledge.KeyType(key_type)
|
||||||
For key types that depend on a parameter (e.g. elliptic curve family),
|
|
||||||
`param` is the parameter to pass to the constructor. Only a single
|
|
||||||
parameter is supported.
|
|
||||||
"""
|
|
||||||
kt = crypto_knowledge.KeyType(key_type, params)
|
|
||||||
for bits in kt.sizes_to_test():
|
for bits in kt.sizes_to_test():
|
||||||
usage_flags = 'PSA_KEY_USAGE_EXPORT'
|
# Test a non-exercisable key, as well as exercisable keys for
|
||||||
alg = 0
|
# each compatible algorithm.
|
||||||
alg2 = 0
|
# To do: test reading a key from storage with an incompatible
|
||||||
key_material = kt.key_material(bits)
|
# or unsupported algorithm.
|
||||||
short_expression = re.sub(r'\bPSA_(?:KEY_TYPE|ECC_FAMILY)_',
|
yield self.key_for_type_and_alg(kt, bits)
|
||||||
r'',
|
compatible_algorithms = [alg for alg in all_algorithms
|
||||||
kt.expression)
|
if kt.can_do(alg)]
|
||||||
description = 'type: {} {}-bit'.format(short_expression, bits)
|
for alg in compatible_algorithms:
|
||||||
key = StorageTestData(version=self.version,
|
yield self.key_for_type_and_alg(kt, bits, alg)
|
||||||
id=1, lifetime=0x00000001,
|
|
||||||
type=kt.expression, bits=bits,
|
|
||||||
usage=usage_flags, alg=alg, alg2=alg2,
|
|
||||||
material=key_material,
|
|
||||||
description=description)
|
|
||||||
yield key
|
|
||||||
|
|
||||||
def all_keys_for_types(self) -> Iterator[StorageTestData]:
|
def all_keys_for_types(self) -> Iterator[StorageTestData]:
|
||||||
"""Generate test keys covering key types and their representations."""
|
"""Generate test keys covering key types and their representations."""
|
||||||
key_types = sorted(self.constructors.key_types)
|
key_types = sorted(self.constructors.key_types)
|
||||||
|
all_algorithms = [crypto_knowledge.Algorithm(alg)
|
||||||
|
for alg in self.constructors.generate_expressions(
|
||||||
|
sorted(self.constructors.algorithms)
|
||||||
|
)]
|
||||||
for key_type in self.constructors.generate_expressions(key_types):
|
for key_type in self.constructors.generate_expressions(key_types):
|
||||||
yield from self.keys_for_type(key_type)
|
yield from self.keys_for_type(key_type, all_algorithms)
|
||||||
|
|
||||||
def keys_for_algorithm(self, alg: str) -> Iterator[StorageTestData]:
|
def keys_for_algorithm(self, alg: str) -> Iterator[StorageTestData]:
|
||||||
"""Generate test keys for the specified algorithm."""
|
"""Generate test keys for the encoding of the specified algorithm."""
|
||||||
# For now, we don't have information on the compatibility of key
|
# These test cases only validate the encoding of algorithms, not
|
||||||
# types and algorithms. So we just test the encoding of algorithms,
|
# whether the key read from storage is suitable for an operation.
|
||||||
# and not that operations can be performed with them.
|
# `keys_for_types` generate read tests with an algorithm and a
|
||||||
descr = re.sub(r'PSA_ALG_', r'', alg)
|
# compatible key.
|
||||||
descr = re.sub(r',', r', ', re.sub(r' +', r'', descr))
|
descr = crypto_knowledge.short_expression(alg, 1)
|
||||||
usage = 'PSA_KEY_USAGE_EXPORT'
|
usage = ['PSA_KEY_USAGE_EXPORT']
|
||||||
key1 = StorageTestData(version=self.version,
|
key1 = StorageTestData(version=self.version,
|
||||||
id=1, lifetime=0x00000001,
|
id=1, lifetime=0x00000001,
|
||||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||||
|
@ -736,17 +807,14 @@ class StorageFormatV0(StorageFormat):
|
||||||
"""
|
"""
|
||||||
bits = key_type.sizes_to_test()[0]
|
bits = key_type.sizes_to_test()[0]
|
||||||
implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
|
implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
|
||||||
usage_flags = 'PSA_KEY_USAGE_EXPORT'
|
usage_flags = ['PSA_KEY_USAGE_EXPORT']
|
||||||
material_usage_flags = usage_flags + ' | ' + implyer_usage
|
material_usage_flags = usage_flags + [implyer_usage]
|
||||||
expected_usage_flags = material_usage_flags + ' | ' + implicit_usage
|
expected_usage_flags = material_usage_flags + [implicit_usage]
|
||||||
alg2 = 0
|
alg2 = 0
|
||||||
key_material = key_type.key_material(bits)
|
key_material = key_type.key_material(bits)
|
||||||
usage_expression = re.sub(r'PSA_KEY_USAGE_', r'', implyer_usage)
|
usage_expression = crypto_knowledge.short_expression(implyer_usage, 1)
|
||||||
alg_expression = re.sub(r'PSA_ALG_', r'', alg)
|
alg_expression = crypto_knowledge.short_expression(alg, 1)
|
||||||
alg_expression = re.sub(r',', r', ', re.sub(r' +', r'', alg_expression))
|
key_type_expression = key_type.short_expression(1)
|
||||||
key_type_expression = re.sub(r'\bPSA_(?:KEY_TYPE|ECC_FAMILY)_',
|
|
||||||
r'',
|
|
||||||
key_type.expression)
|
|
||||||
description = 'implied by {}: {} {} {}-bit'.format(
|
description = 'implied by {}: {} {} {}-bit'.format(
|
||||||
usage_expression, alg_expression, key_type_expression, bits)
|
usage_expression, alg_expression, key_type_expression, bits)
|
||||||
key = StorageTestData(version=self.version,
|
key = StorageTestData(version=self.version,
|
||||||
|
@ -820,8 +888,10 @@ class StorageFormatV0(StorageFormat):
|
||||||
for key_type in sorted(alg_with_keys[alg]):
|
for key_type in sorted(alg_with_keys[alg]):
|
||||||
# The key types must be filtered to fit the specific usage flag.
|
# The key types must be filtered to fit the specific usage flag.
|
||||||
kt = crypto_knowledge.KeyType(key_type)
|
kt = crypto_knowledge.KeyType(key_type)
|
||||||
if kt.is_valid_for_signature(usage):
|
if kt.is_public() and '_SIGN_' in usage:
|
||||||
yield self.keys_for_implicit_usage(usage, alg, kt)
|
# Can't sign with a public key
|
||||||
|
continue
|
||||||
|
yield self.keys_for_implicit_usage(usage, alg, kt)
|
||||||
|
|
||||||
def generate_all_keys(self) -> Iterator[StorageTestData]:
|
def generate_all_keys(self) -> Iterator[StorageTestData]:
|
||||||
yield from super().generate_all_keys()
|
yield from super().generate_all_keys()
|
||||||
|
|
|
@ -77,6 +77,22 @@ def normalize(expr: str) -> str:
|
||||||
"""
|
"""
|
||||||
return re.sub(NORMALIZE_STRIP_RE, '', expr)
|
return re.sub(NORMALIZE_STRIP_RE, '', expr)
|
||||||
|
|
||||||
|
ALG_TRUNCATED_TO_SELF_RE = \
|
||||||
|
re.compile(r'PSA_ALG_AEAD_WITH_SHORTENED_TAG\('
|
||||||
|
r'PSA_ALG_(?:CCM|CHACHA20_POLY1305|GCM)'
|
||||||
|
r', *16\)\Z')
|
||||||
|
|
||||||
|
def is_simplifiable(expr: str) -> bool:
|
||||||
|
"""Determine whether an expression is simplifiable.
|
||||||
|
|
||||||
|
Simplifiable expressions can't be output in their input form, since
|
||||||
|
the output will be the simple form. Therefore they must be excluded
|
||||||
|
from testing.
|
||||||
|
"""
|
||||||
|
if ALG_TRUNCATED_TO_SELF_RE.match(expr):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def collect_values(inputs: InputsForTest,
|
def collect_values(inputs: InputsForTest,
|
||||||
type_word: str,
|
type_word: str,
|
||||||
include_path: Optional[str] = None,
|
include_path: Optional[str] = None,
|
||||||
|
@ -87,7 +103,9 @@ def collect_values(inputs: InputsForTest,
|
||||||
value is a string representation of its integer value.
|
value is a string representation of its integer value.
|
||||||
"""
|
"""
|
||||||
names = inputs.get_names(type_word)
|
names = inputs.get_names(type_word)
|
||||||
expressions = sorted(inputs.generate_expressions(names))
|
expressions = sorted(expr
|
||||||
|
for expr in inputs.generate_expressions(names)
|
||||||
|
if not is_simplifiable(expr))
|
||||||
values = run_c(type_word, expressions,
|
values = run_c(type_word, expressions,
|
||||||
include_path=include_path, keep_c=keep_c)
|
include_path=include_path, keep_c=keep_c)
|
||||||
return expressions, values
|
return expressions, values
|
||||||
|
|
|
@ -164,20 +164,29 @@ static int exercise_cipher_key( mbedtls_svc_key_id_t key,
|
||||||
psa_algorithm_t alg )
|
psa_algorithm_t alg )
|
||||||
{
|
{
|
||||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||||
unsigned char iv[16] = {0};
|
unsigned char iv[PSA_CIPHER_IV_MAX_SIZE] = {0};
|
||||||
size_t iv_length = sizeof( iv );
|
size_t iv_length;
|
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
psa_key_type_t key_type;
|
||||||
const unsigned char plaintext[16] = "Hello, world...";
|
const unsigned char plaintext[16] = "Hello, world...";
|
||||||
unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
|
unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
|
||||||
size_t ciphertext_length = sizeof( ciphertext );
|
size_t ciphertext_length = sizeof( ciphertext );
|
||||||
unsigned char decrypted[sizeof( ciphertext )];
|
unsigned char decrypted[sizeof( ciphertext )];
|
||||||
size_t part_length;
|
size_t part_length;
|
||||||
|
|
||||||
|
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||||
|
key_type = psa_get_key_type( &attributes );
|
||||||
|
iv_length = PSA_CIPHER_IV_LENGTH( key_type, alg );
|
||||||
|
|
||||||
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
||||||
{
|
{
|
||||||
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
||||||
PSA_ASSERT( psa_cipher_generate_iv( &operation,
|
if( iv_length != 0 )
|
||||||
iv, sizeof( iv ),
|
{
|
||||||
&iv_length ) );
|
PSA_ASSERT( psa_cipher_generate_iv( &operation,
|
||||||
|
iv, sizeof( iv ),
|
||||||
|
&iv_length ) );
|
||||||
|
}
|
||||||
PSA_ASSERT( psa_cipher_update( &operation,
|
PSA_ASSERT( psa_cipher_update( &operation,
|
||||||
plaintext, sizeof( plaintext ),
|
plaintext, sizeof( plaintext ),
|
||||||
ciphertext, sizeof( ciphertext ),
|
ciphertext, sizeof( ciphertext ),
|
||||||
|
@ -195,18 +204,14 @@ static int exercise_cipher_key( mbedtls_svc_key_id_t key,
|
||||||
int maybe_invalid_padding = 0;
|
int maybe_invalid_padding = 0;
|
||||||
if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
|
if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
|
||||||
{
|
{
|
||||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
||||||
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
|
||||||
/* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
|
|
||||||
* have this macro yet. */
|
|
||||||
iv_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(
|
|
||||||
psa_get_key_type( &attributes ) );
|
|
||||||
maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
|
maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
|
||||||
psa_reset_key_attributes( &attributes );
|
|
||||||
}
|
}
|
||||||
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
|
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
|
||||||
PSA_ASSERT( psa_cipher_set_iv( &operation,
|
if( iv_length != 0 )
|
||||||
iv, iv_length ) );
|
{
|
||||||
|
PSA_ASSERT( psa_cipher_set_iv( &operation,
|
||||||
|
iv, iv_length ) );
|
||||||
|
}
|
||||||
PSA_ASSERT( psa_cipher_update( &operation,
|
PSA_ASSERT( psa_cipher_update( &operation,
|
||||||
ciphertext, ciphertext_length,
|
ciphertext, ciphertext_length,
|
||||||
decrypted, sizeof( decrypted ),
|
decrypted, sizeof( decrypted ),
|
||||||
|
@ -229,6 +234,7 @@ static int exercise_cipher_key( mbedtls_svc_key_id_t key,
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
psa_cipher_abort( &operation );
|
psa_cipher_abort( &operation );
|
||||||
|
psa_reset_key_attributes( &attributes );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +242,10 @@ static int exercise_aead_key( mbedtls_svc_key_id_t key,
|
||||||
psa_key_usage_t usage,
|
psa_key_usage_t usage,
|
||||||
psa_algorithm_t alg )
|
psa_algorithm_t alg )
|
||||||
{
|
{
|
||||||
unsigned char nonce[16] = {0};
|
unsigned char nonce[PSA_AEAD_NONCE_MAX_SIZE] = {0};
|
||||||
size_t nonce_length = sizeof( nonce );
|
size_t nonce_length;
|
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
psa_key_type_t key_type;
|
||||||
unsigned char plaintext[16] = "Hello, world...";
|
unsigned char plaintext[16] = "Hello, world...";
|
||||||
unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
|
unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
|
||||||
size_t ciphertext_length = sizeof( ciphertext );
|
size_t ciphertext_length = sizeof( ciphertext );
|
||||||
|
@ -249,19 +257,9 @@ static int exercise_aead_key( mbedtls_svc_key_id_t key,
|
||||||
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) );
|
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default IV length for AES-GCM is 12 bytes */
|
PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
|
||||||
if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
|
key_type = psa_get_key_type( &attributes );
|
||||||
PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
|
nonce_length = PSA_AEAD_NONCE_LENGTH( key_type, alg );
|
||||||
{
|
|
||||||
nonce_length = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IV length for CCM needs to be between 7 and 13 bytes */
|
|
||||||
if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
|
|
||||||
PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ) )
|
|
||||||
{
|
|
||||||
nonce_length = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
if( usage & PSA_KEY_USAGE_ENCRYPT )
|
||||||
{
|
{
|
||||||
|
@ -291,9 +289,21 @@ static int exercise_aead_key( mbedtls_svc_key_id_t key,
|
||||||
return( 1 );
|
return( 1 );
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
psa_reset_key_attributes( &attributes );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int can_sign_or_verify_message( psa_key_usage_t usage,
|
||||||
|
psa_algorithm_t alg )
|
||||||
|
{
|
||||||
|
/* Sign-the-unspecified-hash algorithms can only be used with
|
||||||
|
* {sign,verify}_hash, not with {sign,verify}_message. */
|
||||||
|
if( alg == PSA_ALG_ECDSA_ANY || alg == PSA_ALG_RSA_PKCS1V15_SIGN_RAW )
|
||||||
|
return( 0 );
|
||||||
|
return( usage & ( PSA_KEY_USAGE_SIGN_MESSAGE |
|
||||||
|
PSA_KEY_USAGE_VERIFY_MESSAGE ) );
|
||||||
|
}
|
||||||
|
|
||||||
static int exercise_signature_key( mbedtls_svc_key_id_t key,
|
static int exercise_signature_key( mbedtls_svc_key_id_t key,
|
||||||
psa_key_usage_t usage,
|
psa_key_usage_t usage,
|
||||||
psa_algorithm_t alg )
|
psa_algorithm_t alg )
|
||||||
|
@ -344,7 +354,7 @@ static int exercise_signature_key( mbedtls_svc_key_id_t key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( usage & ( PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE ) )
|
if( can_sign_or_verify_message( usage, alg ) )
|
||||||
{
|
{
|
||||||
unsigned char message[256] = "Hello, world...";
|
unsigned char message[256] = "Hello, world...";
|
||||||
unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
|
unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
|
||||||
|
@ -613,15 +623,39 @@ static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
|
||||||
psa_algorithm_t alg )
|
psa_algorithm_t alg )
|
||||||
{
|
{
|
||||||
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
|
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
|
||||||
|
unsigned char input[1];
|
||||||
unsigned char output[1];
|
unsigned char output[1];
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
|
psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg );
|
||||||
|
|
||||||
if( usage & PSA_KEY_USAGE_DERIVE )
|
if( usage & PSA_KEY_USAGE_DERIVE )
|
||||||
{
|
{
|
||||||
/* We need two keys to exercise key agreement. Exercise the
|
/* We need two keys to exercise key agreement. Exercise the
|
||||||
* private key against its own public key. */
|
* private key against its own public key. */
|
||||||
PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
|
PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
|
||||||
|
if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
|
||||||
|
PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
|
||||||
|
{
|
||||||
|
PSA_ASSERT( psa_key_derivation_input_bytes(
|
||||||
|
&operation, PSA_KEY_DERIVATION_INPUT_SEED,
|
||||||
|
input, sizeof( input ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
|
PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
|
||||||
|
|
||||||
|
if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
|
||||||
|
PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
|
||||||
|
{
|
||||||
|
PSA_ASSERT( psa_key_derivation_input_bytes(
|
||||||
|
&operation, PSA_KEY_DERIVATION_INPUT_LABEL,
|
||||||
|
input, sizeof( input ) ) );
|
||||||
|
}
|
||||||
|
else if( PSA_ALG_IS_HKDF( kdf_alg ) )
|
||||||
|
{
|
||||||
|
PSA_ASSERT( psa_key_derivation_input_bytes(
|
||||||
|
&operation, PSA_KEY_DERIVATION_INPUT_INFO,
|
||||||
|
input, sizeof( input ) ) );
|
||||||
|
}
|
||||||
PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
|
PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
|
||||||
output,
|
output,
|
||||||
sizeof( output ) ) );
|
sizeof( output ) ) );
|
||||||
|
|
|
@ -1541,23 +1541,27 @@ cipher_encrypt_fail:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf
|
||||||
|
|
||||||
PSA symmetric encrypt: AES-ECB, 0 bytes, good
|
PSA symmetric encrypt: AES-ECB, 0 bytes, good
|
||||||
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
||||||
cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":""
|
cipher_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":""
|
||||||
|
|
||||||
PSA symmetric encrypt: AES-ECB, 16 bytes, good
|
PSA symmetric encrypt: AES-ECB, 16 bytes, good
|
||||||
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
||||||
cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"3ad77bb40d7a3660a89ecaf32466ef97"
|
cipher_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"3ad77bb40d7a3660a89ecaf32466ef97"
|
||||||
|
|
||||||
PSA symmetric encrypt: AES-ECB, 32 bytes, good
|
PSA symmetric encrypt: AES-ECB, 32 bytes, good
|
||||||
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
||||||
cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1"
|
cipher_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1"
|
||||||
|
|
||||||
PSA symmetric encrypt: 2-key 3DES-ECB, 8 bytes, good
|
PSA symmetric encrypt: 2-key 3DES-ECB, 8 bytes, good
|
||||||
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
|
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
|
||||||
cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"c78e2b38139610e3":"5d0652429c5b0ac7"
|
cipher_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"c78e2b38139610e3":"5d0652429c5b0ac7"
|
||||||
|
|
||||||
PSA symmetric encrypt: 3-key 3DES-ECB, 8 bytes, good
|
PSA symmetric encrypt: 3-key 3DES-ECB, 8 bytes, good
|
||||||
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
|
depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
|
||||||
cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"c78e2b38139610e3":"817ca7d69b80d86a"
|
cipher_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"c78e2b38139610e3":"817ca7d69b80d86a"
|
||||||
|
|
||||||
|
PSA symmetric encrypt: 128-bit ARC4, 16 bytes, good
|
||||||
|
depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_alg_without_iv:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_ARC4:"0102030405060708090a0b0c0d0e0f10":"00000000000000000000000000000000":"9ac7cc9a609d1ef7b2932899cde41b97"
|
||||||
|
|
||||||
PSA symmetric encrypt validation: AES-CBC-nopad, 16 bytes, good
|
PSA symmetric encrypt validation: AES-CBC-nopad, 16 bytes, good
|
||||||
depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
|
||||||
|
|
|
@ -2592,54 +2592,116 @@ exit:
|
||||||
/* END_CASE */
|
/* END_CASE */
|
||||||
|
|
||||||
/* BEGIN_CASE */
|
/* BEGIN_CASE */
|
||||||
void cipher_encrypt_alg_without_iv( int alg_arg,
|
void cipher_alg_without_iv( int alg_arg, int key_type_arg, data_t *key_data,
|
||||||
int key_type_arg,
|
data_t *plaintext, data_t *ciphertext )
|
||||||
data_t *key_data,
|
|
||||||
data_t *input,
|
|
||||||
data_t *expected_output )
|
|
||||||
{
|
{
|
||||||
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
|
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
|
||||||
psa_key_type_t key_type = key_type_arg;
|
psa_key_type_t key_type = key_type_arg;
|
||||||
psa_algorithm_t alg = alg_arg;
|
psa_algorithm_t alg = alg_arg;
|
||||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||||
uint8_t iv[1] = { 0x5a };
|
uint8_t iv[1] = { 0x5a };
|
||||||
size_t iv_length;
|
|
||||||
unsigned char *output = NULL;
|
unsigned char *output = NULL;
|
||||||
size_t output_buffer_size = 0;
|
size_t output_buffer_size = 0;
|
||||||
size_t output_length = 0;
|
size_t output_length, length;
|
||||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
|
||||||
PSA_ASSERT( psa_crypto_init( ) );
|
PSA_ASSERT( psa_crypto_init( ) );
|
||||||
|
|
||||||
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
|
/* Validate size macros */
|
||||||
|
TEST_ASSERT( ciphertext->len <=
|
||||||
|
PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, plaintext->len ) );
|
||||||
|
TEST_ASSERT( PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, plaintext->len ) <=
|
||||||
|
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( plaintext->len ) );
|
||||||
|
TEST_ASSERT( plaintext->len <=
|
||||||
|
PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, ciphertext->len ) );
|
||||||
|
TEST_ASSERT( PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, ciphertext->len ) <=
|
||||||
|
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( ciphertext->len ) );
|
||||||
|
|
||||||
|
|
||||||
|
/* Set up key and output buffer */
|
||||||
|
psa_set_key_usage_flags( &attributes,
|
||||||
|
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
|
||||||
psa_set_key_algorithm( &attributes, alg );
|
psa_set_key_algorithm( &attributes, alg );
|
||||||
psa_set_key_type( &attributes, key_type );
|
psa_set_key_type( &attributes, key_type );
|
||||||
|
|
||||||
output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
|
|
||||||
ASSERT_ALLOC( output, output_buffer_size );
|
|
||||||
|
|
||||||
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
|
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
|
||||||
&key ) );
|
&key ) );
|
||||||
|
output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg,
|
||||||
|
plaintext->len );
|
||||||
|
ASSERT_ALLOC( output, output_buffer_size );
|
||||||
|
|
||||||
|
/* set_iv() is not allowed */
|
||||||
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
||||||
TEST_EQUAL( psa_cipher_set_iv( &operation, iv, sizeof( iv ) ),
|
TEST_EQUAL( psa_cipher_set_iv( &operation, iv, sizeof( iv ) ),
|
||||||
PSA_ERROR_BAD_STATE );
|
PSA_ERROR_BAD_STATE );
|
||||||
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
|
||||||
TEST_EQUAL( psa_cipher_generate_iv( &operation, iv, sizeof( iv ),
|
TEST_EQUAL( psa_cipher_set_iv( &operation, iv, sizeof( iv ) ),
|
||||||
&iv_length ),
|
|
||||||
PSA_ERROR_BAD_STATE );
|
PSA_ERROR_BAD_STATE );
|
||||||
|
|
||||||
PSA_ASSERT( psa_cipher_encrypt( key, alg, input->x, input->len, output,
|
/* generate_iv() is not allowed */
|
||||||
output_buffer_size, &output_length ) );
|
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
||||||
TEST_ASSERT( output_length <=
|
TEST_EQUAL( psa_cipher_generate_iv( &operation, iv, sizeof( iv ),
|
||||||
PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len ) );
|
&length ),
|
||||||
TEST_ASSERT( output_length <=
|
PSA_ERROR_BAD_STATE );
|
||||||
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
|
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
|
||||||
|
TEST_EQUAL( psa_cipher_generate_iv( &operation, iv, sizeof( iv ),
|
||||||
|
&length ),
|
||||||
|
PSA_ERROR_BAD_STATE );
|
||||||
|
|
||||||
ASSERT_COMPARE( expected_output->x, expected_output->len,
|
/* Multipart encryption */
|
||||||
|
PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
|
||||||
|
output_length = 0;
|
||||||
|
length = ~0;
|
||||||
|
PSA_ASSERT( psa_cipher_update( &operation,
|
||||||
|
plaintext->x, plaintext->len,
|
||||||
|
output, output_buffer_size,
|
||||||
|
&length ) );
|
||||||
|
TEST_ASSERT( length <= output_buffer_size );
|
||||||
|
output_length += length;
|
||||||
|
PSA_ASSERT( psa_cipher_finish( &operation,
|
||||||
|
output + output_length,
|
||||||
|
output_buffer_size - output_length,
|
||||||
|
&length ) );
|
||||||
|
output_length += length;
|
||||||
|
ASSERT_COMPARE( ciphertext->x, ciphertext->len,
|
||||||
output, output_length );
|
output, output_length );
|
||||||
|
|
||||||
|
/* Multipart encryption */
|
||||||
|
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
|
||||||
|
output_length = 0;
|
||||||
|
length = ~0;
|
||||||
|
PSA_ASSERT( psa_cipher_update( &operation,
|
||||||
|
ciphertext->x, ciphertext->len,
|
||||||
|
output, output_buffer_size,
|
||||||
|
&length ) );
|
||||||
|
TEST_ASSERT( length <= output_buffer_size );
|
||||||
|
output_length += length;
|
||||||
|
PSA_ASSERT( psa_cipher_finish( &operation,
|
||||||
|
output + output_length,
|
||||||
|
output_buffer_size - output_length,
|
||||||
|
&length ) );
|
||||||
|
output_length += length;
|
||||||
|
ASSERT_COMPARE( plaintext->x, plaintext->len,
|
||||||
|
output, output_length );
|
||||||
|
|
||||||
|
/* One-shot encryption */
|
||||||
|
output_length = ~0;
|
||||||
|
PSA_ASSERT( psa_cipher_encrypt( key, alg, plaintext->x, plaintext->len,
|
||||||
|
output, output_buffer_size,
|
||||||
|
&output_length ) );
|
||||||
|
ASSERT_COMPARE( ciphertext->x, ciphertext->len,
|
||||||
|
output, output_length );
|
||||||
|
|
||||||
|
/* One-shot decryption */
|
||||||
|
output_length = ~0;
|
||||||
|
PSA_ASSERT( psa_cipher_decrypt( key, alg, ciphertext->x, ciphertext->len,
|
||||||
|
output, output_buffer_size,
|
||||||
|
&output_length ) );
|
||||||
|
ASSERT_COMPARE( plaintext->x, plaintext->len,
|
||||||
|
output, output_length );
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
mbedtls_free( output );
|
mbedtls_free( output );
|
||||||
|
psa_cipher_abort( &operation );
|
||||||
psa_destroy_key( key );
|
psa_destroy_key( key );
|
||||||
PSA_DONE( );
|
PSA_DONE( );
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,15 +1,45 @@
|
||||||
# Most operation failure test cases are automatically generated in
|
# Most operation failure test cases are automatically generated in
|
||||||
# test_suite_psa_crypto_op_fail.generated.data. The manually written
|
# test_suite_psa_crypto_op_fail.generated.data. The manually written
|
||||||
# test cases in this file are only intended to help with debugging the
|
# test cases in this file cover some edge cases, plus a few to help with
|
||||||
# test code.
|
# with debugging the test code.
|
||||||
|
|
||||||
|
# Redundant, to help debugging the test code
|
||||||
PSA hash: invalid algorithm
|
PSA hash: invalid algorithm
|
||||||
hash_fail:PSA_ALG_ECDSA_ANY:PSA_ERROR_INVALID_ARGUMENT
|
hash_fail:PSA_ALG_ECDSA_ANY:PSA_ERROR_INVALID_ARGUMENT
|
||||||
|
|
||||||
|
# For ARC4, Mbed TLS only supports 128-bit keys. PSA allows 40 to 2048 bits.
|
||||||
|
# The ARC4 construction allows any whole number of bytes from 1 to 256 bytes
|
||||||
|
# (8 to 2048 bits).
|
||||||
|
PSA cipher STREAM_CIPHER: 8-bit ARC4 never supported
|
||||||
|
depends_on:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_fail:PSA_KEY_TYPE_ARC4:"41":PSA_ALG_STREAM_CIPHER:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
||||||
|
PSA cipher STREAM_CIPHER: 40-bit ARC4 never supported
|
||||||
|
depends_on:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_fail:PSA_KEY_TYPE_ARC4:"4152433420":PSA_ALG_STREAM_CIPHER:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
||||||
|
PSA cipher STREAM_CIPHER: 120-bit ARC4 never supported
|
||||||
|
depends_on:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_fail:PSA_KEY_TYPE_ARC4:"41524334206b657941524334206b65":PSA_ALG_STREAM_CIPHER:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
||||||
|
PSA cipher STREAM_CIPHER: 136-bit ARC4 never supported
|
||||||
|
depends_on:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_fail:PSA_KEY_TYPE_ARC4:"41524334206b657941524334206b657941":PSA_ALG_STREAM_CIPHER:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
||||||
|
PSA cipher STREAM_CIPHER: 256-bit ARC4 never supported
|
||||||
|
depends_on:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_fail:PSA_KEY_TYPE_ARC4:"41524334206b657941524334206b657941524334206b657941524334206b6579":PSA_ALG_STREAM_CIPHER:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
||||||
|
PSA cipher STREAM_CIPHER: 2048-bit ARC4 never supported
|
||||||
|
depends_on:PSA_WANT_KEY_TYPE_ARC4
|
||||||
|
cipher_fail:PSA_KEY_TYPE_ARC4:"41524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b657941524334206b6579":PSA_ALG_STREAM_CIPHER:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
||||||
|
# Redundant, to help debugging the test code
|
||||||
PSA sign RSA_PSS(SHA_256): incompatible key type
|
PSA sign RSA_PSS(SHA_256): incompatible key type
|
||||||
depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
|
depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
|
||||||
sign_fail:PSA_KEY_TYPE_AES:"48657265006973206b6579a064617461":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_ERROR_INVALID_ARGUMENT
|
sign_fail:PSA_KEY_TYPE_AES:"48657265006973206b6579a064617461":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_ERROR_INVALID_ARGUMENT
|
||||||
|
|
||||||
|
# Redundant, to help debugging the test code
|
||||||
PSA sign RSA_PSS(SHA_256): RSA_PSS not enabled, key pair
|
PSA sign RSA_PSS(SHA_256): RSA_PSS not enabled, key pair
|
||||||
depends_on:!PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
|
depends_on:!PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
|
||||||
sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_ERROR_NOT_SUPPORTED
|
sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_ERROR_NOT_SUPPORTED
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -60,6 +60,163 @@ static int can_export( const psa_key_attributes_t *attributes )
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
|
||||||
|
static int is_accelerated_rsa( psa_algorithm_t alg )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)
|
||||||
|
if ( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
|
||||||
|
if( PSA_ALG_IS_RSA_PSS( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)
|
||||||
|
if( PSA_ALG_IS_RSA_OAEP( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
(void) alg;
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Whether the algorithm is implemented as a builtin, i.e. not accelerated,
|
||||||
|
* and calls mbedtls_md() functions that require the hash algorithm to
|
||||||
|
* also be built-in. */
|
||||||
|
static int is_builtin_calling_md( psa_algorithm_t alg )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
|
||||||
|
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
|
||||||
|
if( PSA_ALG_IS_RSA_PSS( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
|
||||||
|
if( PSA_ALG_IS_RSA_OAEP( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
|
||||||
|
if( PSA_ALG_IS_DETERMINISTIC_ECDSA( alg ) )
|
||||||
|
return( 1 );
|
||||||
|
#endif
|
||||||
|
(void) alg;
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int has_builtin_hash( psa_algorithm_t alg )
|
||||||
|
{
|
||||||
|
#if !defined(MBEDTLS_MD2_C)
|
||||||
|
if( alg == PSA_ALG_MD2 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_MD4_C)
|
||||||
|
if( alg == PSA_ALG_MD4 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_MD5_C)
|
||||||
|
if( alg == PSA_ALG_MD5 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_RIPEMD160_C)
|
||||||
|
if( alg == PSA_ALG_RIPEMD160 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_SHA1_C)
|
||||||
|
if( alg == PSA_ALG_SHA_1 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_SHA224_C)
|
||||||
|
if( alg == PSA_ALG_SHA_224 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_SHA256_C)
|
||||||
|
if( alg == PSA_ALG_SHA_256 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_SHA384_C)
|
||||||
|
if( alg == PSA_ALG_SHA_384 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
#if !defined(MBEDTLS_SHA512_C)
|
||||||
|
if( alg == PSA_ALG_SHA_512 )
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
(void) alg;
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Mbed TLS doesn't support certain combinations of key type and algorithm
|
||||||
|
* in certain configurations. */
|
||||||
|
static int can_exercise( const psa_key_attributes_t *attributes )
|
||||||
|
{
|
||||||
|
psa_key_type_t key_type = psa_get_key_type( attributes );
|
||||||
|
psa_algorithm_t alg = psa_get_key_algorithm( attributes );
|
||||||
|
psa_algorithm_t hash_alg =
|
||||||
|
PSA_ALG_IS_HASH_AND_SIGN( alg ) ? PSA_ALG_SIGN_GET_HASH( alg ) :
|
||||||
|
PSA_ALG_IS_RSA_OAEP( alg ) ? PSA_ALG_RSA_OAEP_GET_HASH( alg ) :
|
||||||
|
PSA_ALG_NONE;
|
||||||
|
psa_key_usage_t usage = psa_get_key_usage_flags( attributes );
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
|
||||||
|
/* We test some configurations using drivers where the driver doesn't
|
||||||
|
* support certain hash algorithms, but declares that it supports
|
||||||
|
* compound algorithms that use those hashes. Until this is fixed,
|
||||||
|
* in those configurations, don't try to actually perform operations.
|
||||||
|
*
|
||||||
|
* Hash-and-sign algorithms where the asymmetric part doesn't use
|
||||||
|
* a hash operation are ok. So randomized ECDSA signature is fine,
|
||||||
|
* ECDSA verification is fine, but deterministic ECDSA signature is
|
||||||
|
* affected. All RSA signatures are affected except raw PKCS#1v1.5.
|
||||||
|
* OAEP is also affected.
|
||||||
|
*/
|
||||||
|
if( PSA_ALG_IS_DETERMINISTIC_ECDSA( alg ) &&
|
||||||
|
! ( usage & ( PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE ) ) )
|
||||||
|
{
|
||||||
|
/* Verification only. Verification doesn't use the hash algorithm. */
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
|
||||||
|
if( PSA_ALG_IS_DETERMINISTIC_ECDSA( alg ) &&
|
||||||
|
( hash_alg == PSA_ALG_MD5 ||
|
||||||
|
hash_alg == PSA_ALG_RIPEMD160 ||
|
||||||
|
hash_alg == PSA_ALG_SHA_1 ) )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if( is_accelerated_rsa( alg ) &&
|
||||||
|
( hash_alg == PSA_ALG_RIPEMD160 || hash_alg == PSA_ALG_SHA_384 ) )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)
|
||||||
|
if( PSA_ALG_IS_RSA_OAEP( alg ) &&
|
||||||
|
( hash_alg == PSA_ALG_RIPEMD160 || hash_alg == PSA_ALG_SHA_384 ) )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The built-in implementation of asymmetric algorithms that use a
|
||||||
|
* hash internally only dispatch to the internal md module, not to
|
||||||
|
* PSA. Until this is supported, don't try to actually perform
|
||||||
|
* operations when the operation is built-in and the hash isn't. */
|
||||||
|
if( is_builtin_calling_md( alg ) && ! has_builtin_hash( hash_alg ) )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */
|
||||||
|
|
||||||
|
(void) key_type;
|
||||||
|
(void) alg;
|
||||||
|
(void) hash_alg;
|
||||||
|
(void) usage;
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
/** Write a key with the given representation to storage, then check
|
/** Write a key with the given representation to storage, then check
|
||||||
* that it has the given attributes and (if exportable) key material.
|
* that it has the given attributes and (if exportable) key material.
|
||||||
*
|
*
|
||||||
|
@ -108,7 +265,7 @@ static int test_read_key( const psa_key_attributes_t *expected_attributes,
|
||||||
exported_material, length );
|
exported_material, length );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( flags & TEST_FLAG_EXERCISE )
|
if( ( flags & TEST_FLAG_EXERCISE ) && can_exercise( &actual_attributes ) )
|
||||||
{
|
{
|
||||||
TEST_ASSERT( mbedtls_test_psa_exercise_key(
|
TEST_ASSERT( mbedtls_test_psa_exercise_key(
|
||||||
key_id,
|
key_id,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue