summaryrefslogtreecommitdiff
path: root/scripts/mbedtls_dev/crypto_knowledge.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mbedtls_dev/crypto_knowledge.py')
-rw-r--r--scripts/mbedtls_dev/crypto_knowledge.py568
1 files changed, 0 insertions, 568 deletions
diff --git a/scripts/mbedtls_dev/crypto_knowledge.py b/scripts/mbedtls_dev/crypto_knowledge.py
deleted file mode 100644
index ebfd55cdb32..00000000000
--- a/scripts/mbedtls_dev/crypto_knowledge.py
+++ /dev/null
@@ -1,568 +0,0 @@
-"""Knowledge about cryptographic mechanisms implemented in Mbed TLS.
-
-This module is entirely based on the PSA API.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import enum
-import re
-from typing import FrozenSet, Iterable, List, Optional, Tuple, Dict
-
-from .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|DH_FAMILY|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_MAC_MODES = frozenset(['CBC_MAC', 'CMAC'])
-BLOCK_CIPHER_MODES = frozenset([
- 'CTR', 'CFB', 'OFB', 'XTS', 'CCM_STAR_NO_TAG',
- 'ECB_NO_PADDING', 'CBC_NO_PADDING', 'CBC_PKCS7',
-])
-BLOCK_AEAD_MODES = frozenset(['CCM', 'GCM'])
-
-class EllipticCurveCategory(enum.Enum):
- """Categorization of elliptic curve families.
-
- The category of a curve determines what algorithms are defined over it.
- """
-
- SHORT_WEIERSTRASS = 0
- MONTGOMERY = 1
- TWISTED_EDWARDS = 2
-
- @staticmethod
- def from_family(family: str) -> 'EllipticCurveCategory':
- if family == 'PSA_ECC_FAMILY_MONTGOMERY':
- return EllipticCurveCategory.MONTGOMERY
- if family == 'PSA_ECC_FAMILY_TWISTED_EDWARDS':
- return EllipticCurveCategory.TWISTED_EDWARDS
- # Default to SW, which most curves belong to.
- return EllipticCurveCategory.SHORT_WEIERSTRASS
-
-
-class KeyType:
- """Knowledge about a PSA key type."""
-
- def __init__(self, name: str, params: Optional[Iterable[str]] = None) -> None:
- """Analyze a key type.
-
- The key type must be specified in PSA syntax. In its simplest form,
- `name` is a string 'PSA_KEY_TYPE_xxx' which is the name of a PSA key
- type macro. For key types that take arguments, the arguments can
- be passed either through the optional argument `params` or by
- passing an expression of the form 'PSA_KEY_TYPE_xxx(param1, ...)'
- in `name` as a string.
- """
-
- self.name = name.strip()
- """The key type macro name (``PSA_KEY_TYPE_xxx``).
-
- For key types constructed from a macro with arguments, this is the
- name of the macro, and the arguments are in `self.params`.
- """
- if params is None:
- if '(' in self.name:
- m = re.match(r'(\w+)\s*\((.*)\)\Z', self.name)
- assert m is not None
- self.name = m.group(1)
- params = m.group(2).split(',')
- self.params = (None if params is None else
- [param.strip() for param in params])
- """The parameters of the key type, if there are any.
-
- None if the key type is a macro without arguments.
- """
- assert re.match(r'PSA_KEY_TYPE_\w+\Z', self.name)
-
- self.expression = self.name
- """A C expression whose value is the key type encoding."""
- if self.params is not None:
- self.expression += '(' + ', '.join(self.params) + ')'
-
- m = re.match(r'PSA_KEY_TYPE_(\w+)', self.name)
- assert m
- self.head = re.sub(r'_(?:PUBLIC_KEY|KEY_PAIR)\Z', r'', m.group(1))
- """The key type macro name, with common prefixes and suffixes stripped."""
-
- self.private_type = re.sub(r'_PUBLIC_KEY\Z', r'_KEY_PAIR', self.name)
- """The key type macro name for the corresponding key pair type.
-
- For everything other than a public key type, this is the same as
- `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:
- """Whether the key type is for public keys."""
- return self.name.endswith('_PUBLIC_KEY')
-
- DH_KEY_SIZES = {
- 'PSA_DH_FAMILY_RFC7919': (2048, 3072, 4096, 6144, 8192),
- } # type: Dict[str, Tuple[int, ...]]
- ECC_KEY_SIZES = {
- 'PSA_ECC_FAMILY_SECP_K1': (192, 225, 256),
- 'PSA_ECC_FAMILY_SECP_R1': (224, 256, 384, 521),
- 'PSA_ECC_FAMILY_SECP_R2': (160,),
- 'PSA_ECC_FAMILY_SECT_K1': (163, 233, 239, 283, 409, 571),
- 'PSA_ECC_FAMILY_SECT_R1': (163, 233, 283, 409, 571),
- 'PSA_ECC_FAMILY_SECT_R2': (163,),
- 'PSA_ECC_FAMILY_BRAINPOOL_P_R1': (160, 192, 224, 256, 320, 384, 512),
- 'PSA_ECC_FAMILY_MONTGOMERY': (255, 448),
- 'PSA_ECC_FAMILY_TWISTED_EDWARDS': (255, 448),
- } # type: Dict[str, Tuple[int, ...]]
- KEY_TYPE_SIZES = {
- 'PSA_KEY_TYPE_AES': (128, 192, 256), # exhaustive
- 'PSA_KEY_TYPE_ARIA': (128, 192, 256), # exhaustive
- 'PSA_KEY_TYPE_CAMELLIA': (128, 192, 256), # exhaustive
- 'PSA_KEY_TYPE_CHACHA20': (256,), # exhaustive
- 'PSA_KEY_TYPE_DERIVE': (120, 128), # sample
- 'PSA_KEY_TYPE_DES': (64, 128, 192), # exhaustive
- 'PSA_KEY_TYPE_HMAC': (128, 160, 224, 256, 384, 512), # standard size for each supported hash
- 'PSA_KEY_TYPE_PASSWORD': (48, 168, 336), # sample
- 'PSA_KEY_TYPE_PASSWORD_HASH': (128, 256), # sample
- 'PSA_KEY_TYPE_PEPPER': (128, 256), # sample
- 'PSA_KEY_TYPE_RAW_DATA': (8, 40, 128), # sample
- 'PSA_KEY_TYPE_RSA_KEY_PAIR': (1024, 1536), # small sample
- } # type: Dict[str, Tuple[int, ...]]
- def sizes_to_test(self) -> Tuple[int, ...]:
- """Return a tuple of key sizes to test.
-
- For key types that only allow a single size, or only a small set of
- sizes, these are all the possible sizes. For key types that allow a
- wide range of sizes, these are a representative sample of sizes,
- excluding large sizes for which a typical resource-constrained platform
- may run out of memory.
- """
- if self.private_type == 'PSA_KEY_TYPE_ECC_KEY_PAIR':
- assert self.params is not None
- return self.ECC_KEY_SIZES[self.params[0]]
- if self.private_type == 'PSA_KEY_TYPE_DH_KEY_PAIR':
- assert self.params is not None
- return self.DH_KEY_SIZES[self.params[0]]
- return self.KEY_TYPE_SIZES[self.private_type]
-
- # "48657265006973206b6579a064617461"
- DATA_BLOCK = b'Here\000is key\240data'
- def key_material(self, bits: int) -> bytes:
- """Return a byte string containing suitable key material with the given bit length.
-
- Use the PSA export representation. The resulting byte string is one that
- can be obtained with the following code:
- ```
- psa_set_key_type(&attributes, `self.expression`);
- psa_set_key_bits(&attributes, `bits`);
- psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
- psa_generate_key(&attributes, &id);
- psa_export_key(id, `material`, ...);
- ```
- """
- if self.expression in ASYMMETRIC_KEY_DATA:
- if bits not in ASYMMETRIC_KEY_DATA[self.expression]:
- raise ValueError('No key data for {}-bit {}'
- .format(bits, self.expression))
- return ASYMMETRIC_KEY_DATA[self.expression][bits]
- if bits % 8 != 0:
- raise ValueError('Non-integer number of bytes: {} bits for {}'
- .format(bits, self.expression))
- length = bits // 8
- if self.name == 'PSA_KEY_TYPE_DES':
- # "644573206b457901644573206b457902644573206b457904"
- des3 = b'dEs kEy\001dEs kEy\002dEs kEy\004'
- return des3[:length]
- return b''.join([self.DATA_BLOCK] * (length // len(self.DATA_BLOCK)) +
- [self.DATA_BLOCK[:length % len(self.DATA_BLOCK)]])
-
- def can_do(self, alg: 'Algorithm') -> bool:
- """Whether this key type can be used for operations with the given algorithm.
-
- This function does not currently handle key derivation or PAKE.
- """
- #pylint: disable=too-many-branches,too-many-return-statements
- if not alg.is_valid_for_operation():
- return False
- if self.head == 'HMAC' and alg.head == 'HMAC':
- 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 \
- alg.head in frozenset.union(BLOCK_MAC_MODES,
- BLOCK_CIPHER_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
- if self.head == 'CHACHA20' and alg.head == 'CHACHA20_POLY1305':
- return True
- if self.head in {'ARC4', 'CHACHA20'} and \
- alg.head == 'STREAM_CIPHER':
- return True
- if self.head == 'RSA' and alg.head.startswith('RSA_'):
- 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 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])
- if alg.head == 'ECDH' and \
- eccc in {EllipticCurveCategory.SHORT_WEIERSTRASS,
- EllipticCurveCategory.MONTGOMERY}:
- return True
- if alg.head == 'ECDSA' and \
- eccc == EllipticCurveCategory.SHORT_WEIERSTRASS:
- return True
- if alg.head in {'PURE_EDDSA', 'EDDSA_PREHASH'} and \
- eccc == EllipticCurveCategory.TWISTED_EDWARDS:
- return True
- if self.head == 'DH' and alg.head == 'FFDH':
- return True
- return False
-
-
-class AlgorithmCategory(enum.Enum):
- """PSA algorithm categories."""
- # The numbers are aligned with the category bits in numerical values of
- # algorithms.
- HASH = 2
- MAC = 3
- CIPHER = 4
- AEAD = 5
- SIGN = 6
- ASYMMETRIC_ENCRYPTION = 7
- KEY_DERIVATION = 8
- KEY_AGREEMENT = 9
- PAKE = 10
-
- def requires_key(self) -> bool:
- """Whether operations in this category are set up with a key."""
- return self not in {self.HASH, self.KEY_DERIVATION}
-
- def is_asymmetric(self) -> bool:
- """Whether operations in this category involve asymmetric keys."""
- return self in {
- self.SIGN,
- self.ASYMMETRIC_ENCRYPTION,
- self.KEY_AGREEMENT
- }
-
-
-class AlgorithmNotRecognized(Exception):
- def __init__(self, expr: str) -> None:
- super().__init__('Algorithm not recognized: ' + expr)
- self.expr = expr
-
-
-class Algorithm:
- """Knowledge about a PSA algorithm."""
-
- @staticmethod
- def determine_base(expr: str) -> str:
- """Return an expression for the "base" of the algorithm.
-
- This strips off variants of algorithms such as MAC truncation.
-
- This function does not attempt to detect invalid inputs.
- """
- m = re.match(r'PSA_ALG_(?:'
- r'(?:TRUNCATED|AT_LEAST_THIS_LENGTH)_MAC|'
- r'AEAD_WITH_(?:SHORTENED|AT_LEAST_THIS_LENGTH)_TAG'
- r')\((.*),[^,]+\)\Z', expr)
- if m:
- expr = m.group(1)
- return expr
-
- @staticmethod
- def determine_head(expr: str) -> str:
- """Return the head of an algorithm expression.
-
- The head is the first (outermost) constructor, without its PSA_ALG_
- prefix, and with some normalization of similar algorithms.
- """
- m = re.match(r'PSA_ALG_(?:DETERMINISTIC_)?(\w+)', expr)
- if not m:
- raise AlgorithmNotRecognized(expr)
- head = m.group(1)
- if head == 'KEY_AGREEMENT':
- m = re.match(r'PSA_ALG_KEY_AGREEMENT\s*\(\s*PSA_ALG_(\w+)', expr)
- if not m:
- raise AlgorithmNotRecognized(expr)
- head = m.group(1)
- head = re.sub(r'_ANY\Z', r'', head)
- if re.match(r'ED[0-9]+PH\Z', head):
- head = 'EDDSA_PREHASH'
- return head
-
- CATEGORY_FROM_HEAD = {
- 'SHA': AlgorithmCategory.HASH,
- 'SHAKE256_512': AlgorithmCategory.HASH,
- 'MD': AlgorithmCategory.HASH,
- 'RIPEMD': AlgorithmCategory.HASH,
- 'ANY_HASH': AlgorithmCategory.HASH,
- 'HMAC': AlgorithmCategory.MAC,
- 'STREAM_CIPHER': AlgorithmCategory.CIPHER,
- 'CHACHA20_POLY1305': AlgorithmCategory.AEAD,
- 'DSA': AlgorithmCategory.SIGN,
- 'ECDSA': AlgorithmCategory.SIGN,
- 'EDDSA': AlgorithmCategory.SIGN,
- 'PURE_EDDSA': AlgorithmCategory.SIGN,
- 'RSA_PSS': AlgorithmCategory.SIGN,
- 'RSA_PKCS1V15_SIGN': AlgorithmCategory.SIGN,
- 'RSA_PKCS1V15_CRYPT': AlgorithmCategory.ASYMMETRIC_ENCRYPTION,
- 'RSA_OAEP': AlgorithmCategory.ASYMMETRIC_ENCRYPTION,
- 'HKDF': AlgorithmCategory.KEY_DERIVATION,
- 'TLS12_PRF': AlgorithmCategory.KEY_DERIVATION,
- 'TLS12_PSK_TO_MS': AlgorithmCategory.KEY_DERIVATION,
- 'TLS12_ECJPAKE_TO_PMS': AlgorithmCategory.KEY_DERIVATION,
- 'PBKDF': AlgorithmCategory.KEY_DERIVATION,
- 'ECDH': AlgorithmCategory.KEY_AGREEMENT,
- 'FFDH': AlgorithmCategory.KEY_AGREEMENT,
- # KEY_AGREEMENT(...) is a key derivation with a key agreement component
- 'KEY_AGREEMENT': AlgorithmCategory.KEY_DERIVATION,
- 'JPAKE': AlgorithmCategory.PAKE,
- }
- for x in BLOCK_MAC_MODES:
- CATEGORY_FROM_HEAD[x] = AlgorithmCategory.MAC
- for x in BLOCK_CIPHER_MODES:
- CATEGORY_FROM_HEAD[x] = AlgorithmCategory.CIPHER
- for x in BLOCK_AEAD_MODES:
- CATEGORY_FROM_HEAD[x] = AlgorithmCategory.AEAD
-
- def determine_category(self, expr: str, head: str) -> AlgorithmCategory:
- """Return the category of the given algorithm expression.
-
- This function does not attempt to detect invalid inputs.
- """
- prefix = head
- while prefix:
- if prefix in self.CATEGORY_FROM_HEAD:
- return self.CATEGORY_FROM_HEAD[prefix]
- if re.match(r'.*[0-9]\Z', prefix):
- prefix = re.sub(r'_*[0-9]+\Z', r'', prefix)
- else:
- prefix = re.sub(r'_*[^_]*\Z', r'', prefix)
- raise AlgorithmNotRecognized(expr)
-
- @staticmethod
- def determine_wildcard(expr) -> bool:
- """Whether the given algorithm expression is a wildcard.
-
- This function does not attempt to detect invalid inputs.
- """
- if re.search(r'\bPSA_ALG_ANY_HASH\b', expr):
- return True
- if re.search(r'_AT_LEAST_', expr):
- return True
- return False
-
- def __init__(self, expr: str) -> None:
- """Analyze an algorithm value.
-
- The algorithm must be expressed as a C expression containing only
- calls to PSA algorithm constructor macros and numeric literals.
-
- This class is only programmed to handle valid expressions. Invalid
- expressions may result in exceptions or in nonsensical results.
- """
- self.expression = re.sub(r'\s+', r'', expr)
- self.base_expression = self.determine_base(self.expression)
- self.head = self.determine_head(self.base_expression)
- self.category = self.determine_category(self.base_expression, self.head)
- self.is_wildcard = self.determine_wildcard(self.expression)
-
- 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 None
- m = re.match(r'PSA_ALG_KEY_AGREEMENT\(\w+,\s*(.*)\)\Z', self.expression)
- if not m:
- return None
- kdf_alg = m.group(1)
- # Assume kdf_alg is either a valid KDF or 0.
- 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.
-
- 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 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_valid_key_agreement_with_derivation():
- return True
- 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]