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