Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 1 | """Knowledge about cryptographic mechanisms implemented in Mbed TLS. |
| 2 | |
| 3 | This module is entirely based on the PSA API. |
| 4 | """ |
| 5 | |
| 6 | # Copyright The Mbed TLS Contributors |
| 7 | # SPDX-License-Identifier: Apache-2.0 |
| 8 | # |
| 9 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 10 | # not use this file except in compliance with the License. |
| 11 | # You may obtain a copy of the License at |
| 12 | # |
| 13 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 14 | # |
| 15 | # Unless required by applicable law or agreed to in writing, software |
| 16 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 17 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 18 | # See the License for the specific language governing permissions and |
| 19 | # limitations under the License. |
| 20 | |
| 21 | import re |
Gilles Peskine | f8223ab | 2021-03-10 15:07:16 +0100 | [diff] [blame] | 22 | from typing import Iterable, Optional, Tuple |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 23 | |
Gilles Peskine | 6f6483f | 2021-01-27 12:43:24 +0100 | [diff] [blame] | 24 | from mbedtls_dev.asymmetric_key_data import ASYMMETRIC_KEY_DATA |
| 25 | |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 26 | class KeyType: |
| 27 | """Knowledge about a PSA key type.""" |
| 28 | |
Gilles Peskine | f8223ab | 2021-03-10 15:07:16 +0100 | [diff] [blame] | 29 | def __init__(self, name: str, params: Optional[Iterable[str]] = None): |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 30 | """Analyze a key type. |
| 31 | |
| 32 | The key type must be specified in PSA syntax. In its simplest form, |
Gilles Peskine | fa3c69a | 2021-02-16 14:29:22 +0100 | [diff] [blame] | 33 | `name` is a string 'PSA_KEY_TYPE_xxx' which is the name of a PSA key |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 34 | type macro. For key types that take arguments, the arguments can |
| 35 | be passed either through the optional argument `params` or by |
| 36 | passing an expression of the form 'PSA_KEY_TYPE_xxx(param1, param2)' |
Gilles Peskine | fa3c69a | 2021-02-16 14:29:22 +0100 | [diff] [blame] | 37 | in `name` as a string. |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 38 | """ |
Gilles Peskine | d75adfc | 2021-02-17 18:04:28 +0100 | [diff] [blame] | 39 | |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 40 | self.name = name.strip() |
Gilles Peskine | fa3c69a | 2021-02-16 14:29:22 +0100 | [diff] [blame] | 41 | """The key type macro name (``PSA_KEY_TYPE_xxx``). |
| 42 | |
| 43 | For key types constructed from a macro with arguments, this is the |
| 44 | name of the macro, and the arguments are in `self.params`. |
| 45 | """ |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 46 | if params is None: |
| 47 | if '(' in self.name: |
| 48 | m = re.match(r'(\w+)\s*\((.*)\)\Z', self.name) |
| 49 | assert m is not None |
| 50 | self.name = m.group(1) |
| 51 | params = ','.split(m.group(2)) |
Gilles Peskine | fa3c69a | 2021-02-16 14:29:22 +0100 | [diff] [blame] | 52 | self.params = (None if params is None else |
| 53 | [param.strip() for param in params]) |
| 54 | """The parameters of the key type, if there are any. |
| 55 | |
| 56 | None if the key type is a macro without arguments. |
| 57 | """ |
Gilles Peskine | d75adfc | 2021-02-17 18:04:28 +0100 | [diff] [blame] | 58 | assert re.match(r'PSA_KEY_TYPE_\w+\Z', self.name) |
| 59 | |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 60 | self.expression = self.name |
Gilles Peskine | fa3c69a | 2021-02-16 14:29:22 +0100 | [diff] [blame] | 61 | """A C expression whose value is the key type encoding.""" |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 62 | if self.params is not None: |
| 63 | self.expression += '(' + ', '.join(self.params) + ')' |
Gilles Peskine | d75adfc | 2021-02-17 18:04:28 +0100 | [diff] [blame] | 64 | |
Gilles Peskine | 0156a15 | 2021-01-26 21:23:56 +0100 | [diff] [blame] | 65 | self.private_type = re.sub(r'_PUBLIC_KEY\Z', r'_KEY_PAIR', self.name) |
Gilles Peskine | fa3c69a | 2021-02-16 14:29:22 +0100 | [diff] [blame] | 66 | """The key type macro name for the corresponding key pair type. |
| 67 | |
| 68 | For everything other than a public key type, this is the same as |
| 69 | `self.name`. |
| 70 | """ |
Gilles Peskine | df63968 | 2021-01-26 21:25:34 +0100 | [diff] [blame] | 71 | |
| 72 | ECC_KEY_SIZES = { |
| 73 | 'PSA_ECC_FAMILY_SECP_K1': (192, 224, 256), |
Gilles Peskine | 0ac258e | 2021-01-27 13:11:59 +0100 | [diff] [blame] | 74 | 'PSA_ECC_FAMILY_SECP_R1': (225, 256, 384, 521), |
Gilles Peskine | df63968 | 2021-01-26 21:25:34 +0100 | [diff] [blame] | 75 | 'PSA_ECC_FAMILY_SECP_R2': (160,), |
| 76 | 'PSA_ECC_FAMILY_SECT_K1': (163, 233, 239, 283, 409, 571), |
| 77 | 'PSA_ECC_FAMILY_SECT_R1': (163, 233, 283, 409, 571), |
| 78 | 'PSA_ECC_FAMILY_SECT_R2': (163,), |
| 79 | 'PSA_ECC_FAMILY_BRAINPOOL_P_R1': (160, 192, 224, 256, 320, 384, 512), |
| 80 | 'PSA_ECC_FAMILY_MONTGOMERY': (255, 448), |
| 81 | } |
| 82 | KEY_TYPE_SIZES = { |
| 83 | 'PSA_KEY_TYPE_AES': (128, 192, 256), # exhaustive |
| 84 | 'PSA_KEY_TYPE_ARC4': (8, 128, 2048), # extremes + sensible |
| 85 | 'PSA_KEY_TYPE_ARIA': (128, 192, 256), # exhaustive |
| 86 | 'PSA_KEY_TYPE_CAMELLIA': (128, 192, 256), # exhaustive |
| 87 | 'PSA_KEY_TYPE_CHACHA20': (256,), # exhaustive |
| 88 | 'PSA_KEY_TYPE_DERIVE': (120, 128), # sample |
| 89 | 'PSA_KEY_TYPE_DES': (64, 128, 192), # exhaustive |
| 90 | 'PSA_KEY_TYPE_HMAC': (128, 160, 224, 256, 384, 512), # standard size for each supported hash |
| 91 | 'PSA_KEY_TYPE_RAW_DATA': (8, 40, 128), # sample |
| 92 | 'PSA_KEY_TYPE_RSA_KEY_PAIR': (1024, 1536), # small sample |
| 93 | } |
| 94 | def sizes_to_test(self) -> Tuple[int, ...]: |
| 95 | """Return a tuple of key sizes to test. |
| 96 | |
| 97 | For key types that only allow a single size, or only a small set of |
| 98 | sizes, these are all the possible sizes. For key types that allow a |
| 99 | wide range of sizes, these are a representative sample of sizes, |
| 100 | excluding large sizes for which a typical resource-constrained platform |
| 101 | may run out of memory. |
| 102 | """ |
| 103 | if self.private_type == 'PSA_KEY_TYPE_ECC_KEY_PAIR': |
| 104 | assert self.params is not None |
| 105 | return self.ECC_KEY_SIZES[self.params[0]] |
| 106 | return self.KEY_TYPE_SIZES[self.private_type] |
Gilles Peskine | 397b028 | 2021-01-26 21:26:26 +0100 | [diff] [blame] | 107 | |
| 108 | # "48657265006973206b6579a064617461" |
| 109 | DATA_BLOCK = b'Here\000is key\240data' |
| 110 | def key_material(self, bits: int) -> bytes: |
| 111 | """Return a byte string containing suitable key material with the given bit length. |
| 112 | |
| 113 | Use the PSA export representation. The resulting byte string is one that |
| 114 | can be obtained with the following code: |
| 115 | ``` |
| 116 | psa_set_key_type(&attributes, `self.expression`); |
| 117 | psa_set_key_bits(&attributes, `bits`); |
| 118 | psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); |
| 119 | psa_generate_key(&attributes, &id); |
| 120 | psa_export_key(id, `material`, ...); |
| 121 | ``` |
| 122 | """ |
Gilles Peskine | 6f6483f | 2021-01-27 12:43:24 +0100 | [diff] [blame] | 123 | if self.expression in ASYMMETRIC_KEY_DATA: |
| 124 | if bits not in ASYMMETRIC_KEY_DATA[self.expression]: |
| 125 | raise ValueError('No key data for {}-bit {}' |
| 126 | .format(bits, self.expression)) |
| 127 | return ASYMMETRIC_KEY_DATA[self.expression][bits] |
Gilles Peskine | 397b028 | 2021-01-26 21:26:26 +0100 | [diff] [blame] | 128 | if bits % 8 != 0: |
Gilles Peskine | 6f6483f | 2021-01-27 12:43:24 +0100 | [diff] [blame] | 129 | raise ValueError('Non-integer number of bytes: {} bits for {}' |
| 130 | .format(bits, self.expression)) |
Gilles Peskine | 397b028 | 2021-01-26 21:26:26 +0100 | [diff] [blame] | 131 | length = bits // 8 |
| 132 | if self.name == 'PSA_KEY_TYPE_DES': |
| 133 | # "644573206b457901644573206b457902644573206b457904" |
| 134 | des3 = b'dEs kEy\001dEs kEy\002dEs kEy\004' |
| 135 | return des3[:length] |
Gilles Peskine | 397b028 | 2021-01-26 21:26:26 +0100 | [diff] [blame] | 136 | return b''.join([self.DATA_BLOCK] * (length // len(self.DATA_BLOCK)) + |
| 137 | [self.DATA_BLOCK[:length % len(self.DATA_BLOCK)]]) |