Merge pull request #6802 from gilles-peskine-arm/test_suite_psa_crypto_metadata-20221215
Add metadata tests for CCM* and TLS1.2-ECJPAKE-to-PMS
This commit is contained in:
commit
169d9e6eb4
9 changed files with 106 additions and 13 deletions
3
ChangeLog.d/crypto_config_ccm_star.txt
Normal file
3
ChangeLog.d/crypto_config_ccm_star.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Bugfix
|
||||
* List PSA_WANT_ALG_CCM_STAR_NO_TAG in psa/crypto_config.h so that it can
|
||||
be toggled with config.py.
|
4
ChangeLog.d/psa_alg_tls12_ecjpake_to_pms-reject_ka.txt
Normal file
4
ChangeLog.d/psa_alg_tls12_ecjpake_to_pms-reject_ka.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Bugfix
|
||||
* The key derivation algorithm PSA_ALG_TLS12_ECJPAKE_TO_PMS cannot be
|
||||
used on a shared secret from a key agreement since its input must be
|
||||
an ECC public key. Reject this properly.
|
|
@ -843,6 +843,8 @@ extern "C" {
|
|||
|
||||
/* These features are always enabled. */
|
||||
#define PSA_WANT_KEY_TYPE_DERIVE 1
|
||||
#define PSA_WANT_KEY_TYPE_PASSWORD 1
|
||||
#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
|
||||
#define PSA_WANT_KEY_TYPE_RAW_DATA 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#define PSA_WANT_ALG_CBC_NO_PADDING 1
|
||||
#define PSA_WANT_ALG_CBC_PKCS7 1
|
||||
#define PSA_WANT_ALG_CCM 1
|
||||
#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1
|
||||
#define PSA_WANT_ALG_CMAC 1
|
||||
#define PSA_WANT_ALG_CFB 1
|
||||
#define PSA_WANT_ALG_CHACHA20_POLY1305 1
|
||||
|
@ -115,6 +116,8 @@
|
|||
#define PSA_WANT_ECC_SECP_R1_521 1
|
||||
|
||||
#define PSA_WANT_KEY_TYPE_DERIVE 1
|
||||
#define PSA_WANT_KEY_TYPE_PASSWORD 1
|
||||
#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
|
||||
#define PSA_WANT_KEY_TYPE_HMAC 1
|
||||
#define PSA_WANT_KEY_TYPE_AES 1
|
||||
#define PSA_WANT_KEY_TYPE_ARIA 1
|
||||
|
|
|
@ -5168,6 +5168,18 @@ static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg)
|
|||
(void) alg;
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int psa_key_derivation_allows_free_form_secret_input(
|
||||
psa_algorithm_t kdf_alg)
|
||||
{
|
||||
#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
|
||||
if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
(void) kdf_alg;
|
||||
return 1;
|
||||
}
|
||||
#endif /* AT_LEAST_ONE_BUILTIN_KDF */
|
||||
|
||||
psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation,
|
||||
|
@ -5189,6 +5201,9 @@ psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation,
|
|||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
status = psa_key_derivation_setup_kdf(operation, kdf_alg);
|
||||
#else
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
|
|
|
@ -214,9 +214,7 @@ class KeyType:
|
|||
This function does not currently handle key derivation or PAKE.
|
||||
"""
|
||||
#pylint: disable=too-many-branches,too-many-return-statements
|
||||
if alg.is_wildcard:
|
||||
return False
|
||||
if alg.is_invalid_truncation():
|
||||
if not alg.is_valid_for_operation():
|
||||
return False
|
||||
if self.head == 'HMAC' and alg.head == 'HMAC':
|
||||
return True
|
||||
|
@ -248,6 +246,8 @@ class KeyType:
|
|||
# So a public key object with a key agreement algorithm is not
|
||||
# a valid combination.
|
||||
return False
|
||||
if alg.is_invalid_key_agreement_with_derivation():
|
||||
return False
|
||||
if self.head == 'ECC':
|
||||
assert self.params is not None
|
||||
eccc = EllipticCurveCategory.from_family(self.params[0])
|
||||
|
@ -414,17 +414,38 @@ class Algorithm:
|
|||
self.category = self.determine_category(self.base_expression, self.head)
|
||||
self.is_wildcard = self.determine_wildcard(self.expression)
|
||||
|
||||
def is_key_agreement_with_derivation(self) -> bool:
|
||||
"""Whether this is a combined key agreement and key derivation algorithm."""
|
||||
def get_key_agreement_derivation(self) -> Optional[str]:
|
||||
"""For a combined key agreement and key derivation algorithm, get the derivation part.
|
||||
|
||||
For anything else, return None.
|
||||
"""
|
||||
if self.category != AlgorithmCategory.KEY_AGREEMENT:
|
||||
return False
|
||||
return None
|
||||
m = re.match(r'PSA_ALG_KEY_AGREEMENT\(\w+,\s*(.*)\)\Z', self.expression)
|
||||
if not m:
|
||||
return False
|
||||
return None
|
||||
kdf_alg = m.group(1)
|
||||
# Assume kdf_alg is either a valid KDF or 0.
|
||||
return not re.match(r'(?:0[Xx])?0+\s*\Z', kdf_alg)
|
||||
if re.match(r'(?:0[Xx])?0+\s*\Z', kdf_alg):
|
||||
return None
|
||||
return kdf_alg
|
||||
|
||||
KEY_DERIVATIONS_INCOMPATIBLE_WITH_AGREEMENT = frozenset([
|
||||
'PSA_ALG_TLS12_ECJPAKE_TO_PMS', # secret input in specific format
|
||||
])
|
||||
def is_valid_key_agreement_with_derivation(self) -> bool:
|
||||
"""Whether this is a valid combined key agreement and key derivation algorithm."""
|
||||
kdf_alg = self.get_key_agreement_derivation()
|
||||
if kdf_alg is None:
|
||||
return False
|
||||
return kdf_alg not in self.KEY_DERIVATIONS_INCOMPATIBLE_WITH_AGREEMENT
|
||||
|
||||
def is_invalid_key_agreement_with_derivation(self) -> bool:
|
||||
"""Whether this is an invalid combined key agreement and key derivation algorithm."""
|
||||
kdf_alg = self.get_key_agreement_derivation()
|
||||
if kdf_alg is None:
|
||||
return False
|
||||
return kdf_alg in self.KEY_DERIVATIONS_INCOMPATIBLE_WITH_AGREEMENT
|
||||
|
||||
def short_expression(self, level: int = 0) -> str:
|
||||
"""Abbreviate the expression, keeping it human-readable.
|
||||
|
@ -498,13 +519,26 @@ class Algorithm:
|
|||
return True
|
||||
return False
|
||||
|
||||
def is_valid_for_operation(self) -> bool:
|
||||
"""Whether this algorithm construction is valid for an operation.
|
||||
|
||||
This function assumes that the algorithm is constructed in a
|
||||
"grammatically" correct way, and only rejects semantically invalid
|
||||
combinations.
|
||||
"""
|
||||
if self.is_wildcard:
|
||||
return False
|
||||
if self.is_invalid_truncation():
|
||||
return False
|
||||
return True
|
||||
|
||||
def can_do(self, category: AlgorithmCategory) -> bool:
|
||||
"""Whether this algorithm can perform operations in the given category.
|
||||
"""
|
||||
if category == self.category:
|
||||
return True
|
||||
if category == AlgorithmCategory.KEY_DERIVATION and \
|
||||
self.is_key_agreement_with_derivation():
|
||||
self.is_valid_key_agreement_with_derivation():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
|
|
@ -151,14 +151,16 @@ def test_case_for_key_type_not_supported(
|
|||
tc.set_arguments([key_type] + list(args))
|
||||
return tc
|
||||
|
||||
class NotSupported:
|
||||
"""Generate test cases for when something is not supported."""
|
||||
class KeyTypeNotSupported:
|
||||
"""Generate test cases for when a key type is not supported."""
|
||||
|
||||
def __init__(self, info: Information) -> None:
|
||||
self.constructors = info.constructors
|
||||
|
||||
ALWAYS_SUPPORTED = frozenset([
|
||||
'PSA_KEY_TYPE_DERIVE',
|
||||
'PSA_KEY_TYPE_PASSWORD',
|
||||
'PSA_KEY_TYPE_PASSWORD_HASH',
|
||||
'PSA_KEY_TYPE_RAW_DATA',
|
||||
'PSA_KEY_TYPE_HMAC'
|
||||
])
|
||||
|
@ -522,7 +524,7 @@ class StorageFormat:
|
|||
key_type: psa_storage.Expr, bits: int,
|
||||
alg: psa_storage.Expr
|
||||
) -> bool:
|
||||
"""Whether to the given key with the given algorithm.
|
||||
"""Whether to exercise 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
|
||||
|
@ -900,7 +902,7 @@ class PSATestGenerator(test_data_generation.TestGenerator):
|
|||
'test_suite_psa_crypto_generate_key.generated':
|
||||
lambda info: KeyGenerate(info).test_cases_for_key_generation(),
|
||||
'test_suite_psa_crypto_not_supported.generated':
|
||||
lambda info: NotSupported(info).test_cases_for_not_supported(),
|
||||
lambda info: KeyTypeNotSupported(info).test_cases_for_not_supported(),
|
||||
'test_suite_psa_crypto_op_fail.generated':
|
||||
lambda info: OpFail(info).all_test_cases(),
|
||||
'test_suite_psa_crypto_storage_format.current':
|
||||
|
|
|
@ -5080,6 +5080,22 @@ PSA key derivation: ECDH on P256 with HKDF-SHA256, missing info
|
|||
depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
|
||||
derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
|
||||
|
||||
PSA key derivation: TLS12_ECJPAKE_TO_PMS, good input, output too short
|
||||
depends_on:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
|
||||
derive_input:PSA_ALG_TLS12_ECJPAKE_TO_PMS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"04aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_SUCCESS:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_INVALID_ARGUMENT
|
||||
|
||||
PSA key derivation: TLS12_ECJPAKE_TO_PMS, input[0]=0x02
|
||||
depends_on:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
|
||||
derive_input:PSA_ALG_TLS12_ECJPAKE_TO_PMS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ERROR_INVALID_ARGUMENT:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
|
||||
|
||||
PSA key derivation: TLS12_ECJPAKE_TO_PMS, input too short
|
||||
depends_on:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
|
||||
derive_input:PSA_ALG_TLS12_ECJPAKE_TO_PMS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"04aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ERROR_INVALID_ARGUMENT:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
|
||||
|
||||
PSA key derivation: TLS12_ECJPAKE_TO_PMS, input too long
|
||||
depends_on:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
|
||||
derive_input:PSA_ALG_TLS12_ECJPAKE_TO_PMS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"04aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ERROR_INVALID_ARGUMENT:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
|
||||
|
||||
PSA key derivation over capacity: HKDF
|
||||
depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
|
||||
derive_over_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256)
|
||||
|
|
|
@ -118,6 +118,10 @@ Cipher: XTS
|
|||
depends_on:PSA_WANT_ALG_XTS:MBEDTLS_CIPHER_C
|
||||
cipher_algorithm:PSA_ALG_XTS:0
|
||||
|
||||
Cipher: CCM*
|
||||
depends_on:PSA_WANT_ALG_CCM_STAR_NO_TAG
|
||||
cipher_algorithm:PSA_ALG_CCM_STAR_NO_TAG:ALG_IS_STREAM_CIPHER
|
||||
|
||||
AEAD: CCM-AES-128
|
||||
depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CCM
|
||||
aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:128
|
||||
|
@ -286,6 +290,10 @@ Key derivation: HKDF-Expand using SHA-384
|
|||
depends_on:PSA_WANT_ALG_HKDF_EXPAND:PSA_WANT_ALG_SHA_384
|
||||
key_derivation_algorithm:PSA_ALG_HKDF_EXPAND( PSA_ALG_SHA_384 ):ALG_IS_HKDF_EXPAND
|
||||
|
||||
Key derivation: TLS1.2 ECJPAKE-to-PMS
|
||||
depends_on:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
|
||||
key_derivation_algorithm:PSA_ALG_TLS12_ECJPAKE_TO_PMS:0
|
||||
|
||||
Key derivation: TLS 1.2 PRF using SHA-256
|
||||
depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
|
||||
key_derivation_algorithm:PSA_ALG_TLS12_PRF( PSA_ALG_SHA_256 ):ALG_IS_TLS12_PRF
|
||||
|
@ -339,6 +347,12 @@ key_type:PSA_KEY_TYPE_HMAC:KEY_TYPE_IS_UNSTRUCTURED
|
|||
Key type: secret for key derivation
|
||||
key_type:PSA_KEY_TYPE_DERIVE:KEY_TYPE_IS_UNSTRUCTURED
|
||||
|
||||
Key type: password
|
||||
key_type:PSA_KEY_TYPE_PASSWORD:KEY_TYPE_IS_UNSTRUCTURED
|
||||
|
||||
Key type: password hash
|
||||
key_type:PSA_KEY_TYPE_PASSWORD_HASH:KEY_TYPE_IS_UNSTRUCTURED
|
||||
|
||||
Block cipher key type: AES
|
||||
depends_on:PSA_WANT_KEY_TYPE_AES
|
||||
block_cipher_key_type:PSA_KEY_TYPE_AES:16
|
||||
|
|
Loading…
Reference in a new issue