1 /*
2 * t_cose_make_psa_test_key.c
3 *
4 * Copyright 2019-2020, Laurence Lundblade
5 * Copyright (c) 2021, Arm Limited. All rights reserved
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * See BSD-3-Clause license in README.md
10 */
11
12
13 #include "t_cose_make_test_pub_key.h" /* The interface implemented here */
14 #include "t_cose_standard_constants.h"
15 #include "psa/crypto.h"
16
17
18 /* Here's the auto-detect and manual override logic for managing PSA
19 * Crypto API compatibility.
20 *
21 * PSA_GENERATOR_UNBRIDLED_CAPACITY happens to be defined in MBed
22 * Crypto 1.1 and not in MBed Crypto 2.0 so it is what auto-detect
23 * hinges off of.
24 *
25 * T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO20 can be defined to force
26 * setting to MBed Crypto 2.0
27 *
28 * T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 can be defined to force
29 * setting to MBed Crypt 1.1. It is also what the code below hinges
30 * on.
31 */
32 #if defined(PSA_GENERATOR_UNBRIDLED_CAPACITY) && !defined(T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO20)
33 #define T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11
34 #endif
35
36
37 /*
38 * Some hard coded keys for the test cases here.
39 */
40 #define PRIVATE_KEY_prime256v1 \
41 0xf1, 0xb7, 0x14, 0x23, 0x43, 0x40, 0x2f, 0x3b, 0x5d, 0xe7, 0x31, 0x5e, 0xa8, \
42 0x94, 0xf9, 0xda, 0x5c, 0xf5, 0x03, 0xff, 0x79, 0x38, 0xa3, 0x7c, 0xa1, 0x4e, \
43 0xb0, 0x32, 0x86, 0x98, 0x84, 0x50
44
45 #define PRIVATE_KEY_secp384r1 \
46 0x03, 0xdf, 0x14, 0xf4, 0xb8, 0xa4, 0x3f, 0xd8, 0xab, 0x75, 0xa6, 0x04, 0x6b, \
47 0xd2, 0xb5, 0xea, 0xa6, 0xfd, 0x10, 0xb2, 0xb2, 0x03, 0xfd, 0x8a, 0x78, 0xd7, \
48 0x91, 0x6d, 0xe2, 0x0a, 0xa2, 0x41, 0xeb, 0x37, 0xec, 0x3d, 0x4c, 0x69, 0x3d, \
49 0x23, 0xba, 0x2b, 0x4f, 0x6e, 0x5b, 0x66, 0xf5, 0x7f
50
51 #define PRIVATE_KEY_secp521r1 \
52 0x00, 0x45, 0xd2, 0xd1, 0x43, 0x94, 0x35, 0xfa, 0xb3, 0x33, 0xb1, 0xc6, 0xc8, \
53 0xb5, 0x34, 0xf0, 0x96, 0x93, 0x96, 0xad, 0x64, 0xd5, 0xf5, 0x35, 0xd6, 0x5f, \
54 0x68, 0xf2, 0xa1, 0x60, 0x65, 0x90, 0xbb, 0x15, 0xfd, 0x53, 0x22, 0xfc, 0x97, \
55 0xa4, 0x16, 0xc3, 0x95, 0x74, 0x5e, 0x72, 0xc7, 0xc8, 0x51, 0x98, 0xc0, 0x92, \
56 0x1a, 0xb3, 0xb8, 0xe9, 0x2d, 0xd9, 0x01, 0xb5, 0xa4, 0x21, 0x59, 0xad, 0xac, \
57 0x6d
58
59
60 /*
61 * Public function, see t_cose_make_test_pub_key.h
62 */
make_ecdsa_key_pair(int32_t cose_algorithm_id,struct t_cose_key * key_pair)63 enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
64 struct t_cose_key *key_pair)
65 {
66 psa_key_type_t key_type;
67 psa_status_t crypto_result;
68 psa_key_handle_t key_handle;
69 psa_algorithm_t key_alg;
70 const uint8_t *private_key;
71 size_t private_key_len;
72
73 static const uint8_t private_key_256[] = {PRIVATE_KEY_prime256v1};
74 static const uint8_t private_key_384[] = {PRIVATE_KEY_secp384r1};
75 static const uint8_t private_key_521[] = {PRIVATE_KEY_secp521r1};
76
77 /* There is not a 1:1 mapping from alg to key type, but
78 * there is usually an obvious curve for an algorithm. That
79 * is what this does.
80 */
81
82 #ifdef T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11
83 #define PSA_KEY_TYPE_ECC_KEY_PAIR PSA_KEY_TYPE_ECC_KEYPAIR
84 #endif /* T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 */
85
86 switch(cose_algorithm_id) {
87 case COSE_ALGORITHM_ES256:
88 private_key = private_key_256;
89 private_key_len = sizeof(private_key_256);
90 key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
91 key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
92 break;
93
94 case COSE_ALGORITHM_ES384:
95 private_key = private_key_384;
96 private_key_len = sizeof(private_key_384);
97 key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
98 key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_384);
99 break;
100
101 case COSE_ALGORITHM_ES512:
102 private_key = private_key_521;
103 private_key_len = sizeof(private_key_521);
104 key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
105 key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_512);
106 break;
107
108 default:
109 return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
110 }
111
112
113 /* OK to call this multiple times */
114 crypto_result = psa_crypto_init();
115 if(crypto_result != PSA_SUCCESS) {
116 return T_COSE_ERR_FAIL;
117 }
118
119
120 /* When importing a key with the PSA API there are two main
121 * things to do.
122 *
123 * First you must tell it what type of key it is as this
124 * cannot be discovered from the raw data. The variable
125 * key_type contains that information including the EC curve. This is sufficient
126 * for psa_import_key() to succeed, but you probably want
127 * actually use the key.
128 *
129 * Second, you must say what algorithm(s) and operations
130 * the key can be used as the PSA Crypto Library has
131 * policy enforcement.
132 *
133 * How this is done varies quite a lot in the newer
134 * PSA Crypto API compared to the older.
135 */
136
137 #ifdef T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11
138 /* Allocate for the key pair in the Crypto service */
139 crypto_result = psa_allocate_key(&key_handle);
140 if (crypto_result != PSA_SUCCESS) {
141 return T_COSE_ERR_FAIL;
142 }
143
144 /* Say what algorithm and operations the key can be used with / for */
145 psa_key_policy_t policy = psa_key_policy_init();
146 psa_key_policy_set_usage(&policy,
147 PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH,
148 key_alg);
149 crypto_result = psa_set_key_policy(key_handle, &policy);
150 if (crypto_result != PSA_SUCCESS) {
151 return T_COSE_ERR_FAIL;
152 }
153
154 /* Import the private key. psa_import_key() automatically
155 * generates the public key from the private so no need to import
156 * more than the private key. (With ECDSA the public key is always
157 * deterministically derivable from the private key).
158 */
159 /* key_type has the type of key including the EC curve */
160 crypto_result = psa_import_key(key_handle,
161 key_type,
162 private_key,
163 private_key_len);
164
165 #else /* T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 */
166 psa_key_attributes_t key_attributes;
167
168 key_attributes = psa_key_attributes_init();
169
170 /* Say what algorithm and operations the key can be used with / for */
171 psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
172 psa_set_key_algorithm(&key_attributes, key_alg);
173
174 /* The type of key including the EC curve */
175 psa_set_key_type(&key_attributes, key_type);
176
177 /* Import the private key. psa_import_key() automatically
178 * generates the public key from the private so no need to import
179 * more than the private key. (With ECDSA the public key is always
180 * deterministically derivable from the private key).
181 */
182 crypto_result = psa_import_key(&key_attributes,
183 private_key,
184 private_key_len,
185 &key_handle);
186
187 #endif /* T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 */
188
189 if (crypto_result != PSA_SUCCESS) {
190 return T_COSE_ERR_FAIL;
191 }
192
193 key_pair->k.key_handle = key_handle;
194 key_pair->crypto_lib = T_COSE_CRYPTO_LIB_PSA;
195
196 return T_COSE_SUCCESS;
197 }
198
199
200 /*
201 * Public function, see t_cose_make_test_pub_key.h
202 */
free_ecdsa_key_pair(struct t_cose_key key_pair)203 void free_ecdsa_key_pair(struct t_cose_key key_pair)
204 {
205 psa_close_key((psa_key_handle_t)key_pair.k.key_handle);
206 }
207
208
209 /*
210 * Public function, see t_cose_make_test_pub_key.h
211 */
check_for_key_pair_leaks()212 int check_for_key_pair_leaks()
213 {
214 #if defined(T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11) || defined(T_COSE_USE_PSA_CRYPTO_FROM_TFM)
215 /* No way to check for leaks with:
216 * - MBED Crypto 1.1
217 * - TF-M Crypto service does not expose this interface
218 */
219 return 0;
220
221 #else
222 mbedtls_psa_stats_t stats;
223
224 mbedtls_psa_get_stats(&stats);
225
226 return (int)(stats.volatile_slots +
227 stats.persistent_slots +
228 stats.external_slots +
229 stats.half_filled_slots +
230 stats.cache_slots);
231
232 #endif /* T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 */
233 }
234
235