blob: 45d2572818baf8c371e83498a7258ad2ea4e221c [file] [log] [blame]
Maulik Patel28c16e42022-11-29 15:34:23 +00001/*
Mathias Brossard6cff9c22025-02-19 22:25:51 -06002 * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
Maulik Patel28c16e42022-11-29 15:34:23 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "psa_adac_sdm.h"
9
10#if defined(MBEDTLS_FS_IO)
Maulik Patel6ed91802023-02-06 14:57:00 +000011#define mbedtls_free free
12
Maulik Patel28c16e42022-11-29 15:34:23 +000013#include "psa_adac.h"
14#include "psa_adac_crypto_api.h"
15#include "psa_adac_cryptosystems.h"
16#include "psa_adac_debug.h"
17
18#include "mbedtls/pk.h"
19#include "mbedtls/base64.h"
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#define MAX_BUFFER_SIZE 4096 /* for RSA 4096 bit key */
25
26static size_t word_padded(size_t input)
27{
28 return (input + 3) & ~((size_t)3);
29}
30
31int split_tlv_static(uint32_t *input, size_t input_size, psa_tlv_t **tlvs,
32 size_t max_tlvs, size_t *tlv_count)
33{
34 psa_tlv_t *current;
35 size_t ext_size;
36 size_t left = input_size;
37 uint8_t *cur_input = (uint8_t *) input;
38 size_t count = 0;
39
40 while (left > 0 && count < max_tlvs) {
41 current = (psa_tlv_t *) cur_input;
42 if (sizeof(psa_tlv_t) > left) {
43 return -1;
44 }
45 ext_size = word_padded(sizeof(psa_tlv_t) + current->length_in_bytes);
46 if (ext_size > left) {
47 PSA_ADAC_LOG_ERR("sdm", "Extension size inconsistency (ext_size = %ld, left = %ld)\n",
48 ext_size, left);
49 return -1;
50 }
51 left -= ext_size;
52 cur_input += ext_size;
53 count += 1;
54 }
55
56 if (left != 0) {
57 PSA_ADAC_LOG_ERR("sdm", "Extension size inconsistency (left = %ld)\n", left);
58 return -1;
59 }
60
61 cur_input = (uint8_t *) input;
62 for (size_t i = 0; i < count; i++) {
63 current = (psa_tlv_t *) cur_input;
64 tlvs[i] = current;
65 cur_input += word_padded(sizeof(psa_tlv_t) + current->length_in_bytes);
66 }
67 *tlv_count = count;
68 return 0;
69}
70
71int split_extensions(uint32_t *input, size_t input_size, psa_tlv_t **extensions[],
72 size_t *extension_count)
73{
74 psa_tlv_t *current;
75 int count = 0;
76 size_t left = input_size;
77 uint8_t *cur_input = (uint8_t *) input;
78
79 while (left > 0) {
80 current = (psa_tlv_t *) cur_input;
81 if (sizeof(psa_tlv_t) > left) {
82 return -1;
83 }
84 size_t ext_size = word_padded(sizeof(psa_tlv_t) + current->length_in_bytes);
85
86 if (ext_size > left) {
87 PSA_ADAC_LOG_ERR("sdm", "Extension size inconsistency (ext_size = %ld, left = %ld)\n",
88 ext_size, left);
89 return -1;
90 }
91 left -= ext_size;
92 cur_input += ext_size;
93 count += 1;
94 }
95
96 if (left != 0) {
97 PSA_ADAC_LOG_ERR("sdm", "Extension size inconsistency (left = %ld)\n", left);
98 return -1;
99 }
100
101 *extensions = (psa_tlv_t **) malloc(sizeof(psa_tlv_t *) * count);
102 cur_input = (uint8_t *) input;
103 for (int i = 0; i < count; i++) {
104 psa_tlv_t *current = (psa_tlv_t *) cur_input;
105 (*extensions)[i] = current;
106 cur_input += word_padded(sizeof(psa_tlv_t) + current->length_in_bytes);
107 }
108 *extension_count = count;
109 return 0;
110}
111
112int load_secret_key(const char *key_file, uint8_t type, uint8_t **key, size_t *key_size) {
113 unsigned char *base64;
114 size_t base64_size, bits;
115 psa_key_type_t key_type = 0;
116
117 int rc = mbedtls_pk_load_file(key_file, &base64, &base64_size);
118 if (rc != 0) {
119 PSA_ADAC_LOG_ERR("sdm", "Error calling mbedtls_pk_load_file(%s)\n", key_file);
120 return rc;
121 }
122
123 *key = malloc(base64_size);
124 if (*key != NULL) {
125 *key_size = 0;
126 rc = mbedtls_base64_decode(*key, base64_size, key_size, base64, base64_size);
127 if (rc != 0) {
128 PSA_ADAC_LOG_ERR("sdm", "Error calling mbedtls_base64_decode, error code %d\n", rc);
129 free(*key);
130 }
131 } else {
132 rc = -1;
133 }
134
135 mbedtls_free(base64);
136 return rc;
137}
138
139int import_private_key(const char *key_file, uint8_t *type, psa_key_handle_t *handle)
140{
141 mbedtls_pk_context pk;
142 psa_status_t crypto_ret;
143 int rc;
144 uint8_t buffer[MAX_BUFFER_SIZE];
145 int key_type, bit_len, key_len;
146 int p_size, offset = 0;
147 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
148
149 mbedtls_pk_init(&pk);
150
151 rc = mbedtls_pk_parse_keyfile(&pk, key_file, NULL);
152 if (rc < 0) {
153 PSA_ADAC_LOG_ERR("sdm", "Error loading key file '%s'\n", key_file);
154 return rc;
155 }
156
157 key_type = mbedtls_pk_get_type(&pk);
158 bit_len = mbedtls_pk_get_bitlen(&pk);
159 key_len = mbedtls_pk_write_key_der(&pk, buffer, sizeof(buffer));
160 if (key_len < 0) {
161 PSA_ADAC_LOG_ERR("sdm", "Error serializing key\n");
162 return rc;
163 }
164
165 if (key_type == MBEDTLS_PK_RSA) {
166 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
167 psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
168 psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH));
169 psa_set_key_bits(&attributes, bit_len);
170
171 if (bit_len == 3072) {
172 PSA_ADAC_LOG_DEBUG("sdm", "Importing RSA 3072-bit key\n");
173 *type = RSA_3072_SHA256;
174 } else if (bit_len == 4096) {
175 PSA_ADAC_LOG_DEBUG("sdm", "Importing RSA 4096-bit key\n");
176 *type = RSA_4096_SHA256;
177 } else {
178 PSA_ADAC_LOG_ERR("sdm", "Invalid key size (%d)\n", bit_len);
179 return -1;
180 }
181
182 /* mbedtls_pk_write_key_der function write from the end of the data buffer,
183 * hence key is end-aligned to the buffer
184 */
185 crypto_ret = psa_import_key(&attributes, buffer + sizeof(buffer) - key_len, key_len, handle);
186 } else if ((key_type == MBEDTLS_PK_ECKEY) || (key_type == MBEDTLS_PK_ECDSA)) {
187 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
188 psa_set_key_bits(&attributes, bit_len);
189
190 if (bit_len == 256) {
191 PSA_ADAC_LOG_DEBUG("sdm", "Importing EC P-256 key\n");
192 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
193 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
194 p_size = 32;
195 offset = 7;
196 *type = ECDSA_P256_SHA256;
Mathias Brossard6cff9c22025-02-19 22:25:51 -0600197 } else if (bit_len == 384) {
198 PSA_ADAC_LOG_DEBUG("sdm", "Importing EC P-384 key\n");
199 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
200 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384));
201 p_size = 48;
202 offset = 8;
203 *type = ECDSA_P384_SHA384;
Maulik Patel28c16e42022-11-29 15:34:23 +0000204 } else if (bit_len == 521) {
205 PSA_ADAC_LOG_DEBUG("sdm", "Importing EC P-521 key\n");
206 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
207 psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512));
208 psa_set_key_bits(&attributes, 521);
209 p_size = 66;
210 offset = 8;
211 *type = ECDSA_P521_SHA512;
212 } else {
213 PSA_ADAC_LOG_ERR("sdm", "Invalid curve size (%d)\n", bit_len);
214 return -1;
215 }
216
217 /* Use below while debug -
218 * PSA_ADAC_LOG_DUMP("sdm", "key", buffer + sizeof(buffer) - key_len + offset, p_size);
219 */
220 /* mbedtls_pk_write_key_der function write from the end of the data buffer,
221 * hence key is end-aligned to the buffer
222 */
223 crypto_ret = psa_import_key(&attributes, buffer + sizeof(buffer) - key_len + offset,
224 p_size, handle);
225 } else {
226 PSA_ADAC_LOG_ERR("sdm", "Unsupported algorithm\n");
227 return -1;
228 }
229
230 return crypto_ret;
231}
232
233int load_trust_chain(const char *chain_file, uint8_t **chain, size_t *chain_size) {
234 unsigned char *base64;
235 size_t base64_size;
236 int rc;
237
238 rc = mbedtls_pk_load_file(chain_file, &base64, &base64_size);
239 if (rc != 0) {
240 PSA_ADAC_LOG_ERR("sdm", "Error calling mbedtls_pk_load_file(%s)\n", chain_file);
241 return rc;
242 }
243
244 *chain = malloc(base64_size);
245 if (*chain != NULL) {
246 *chain_size = 0;
247 rc = mbedtls_base64_decode(*chain, base64_size, chain_size, base64, base64_size);
248 if (rc != 0) {
249 PSA_ADAC_LOG_ERR("sdm", "Error calling mbedtls_base64_decode, error code %d\n", rc);
250 free(*chain);
251 }
252 } else {
253 rc = -1;
254 }
255
256 mbedtls_free(base64);
257 return rc;
258}
259
260int load_trust_rotpk(const char *chain_file, psa_algorithm_t alg,
261 uint8_t *rotpk, size_t buffer_size, size_t *rotpk_size, uint8_t *rotpk_type) {
262 size_t chain_size, root_size = 0, pubkey_size = 0, exts_count = 0;
263 uint8_t *root = NULL, *pubkey = NULL, key_type;
264 uint32_t *chain;
265 psa_tlv_t **exts;
266 psa_status_t status;
267
268 int rc = load_trust_chain(chain_file, (uint8_t **) &chain, &chain_size);
269 if (rc != 0) {
270 PSA_ADAC_LOG_ERR("sdm", "Error loading trust chain (%s)\n", chain_file);
271 exit(-1);
272 }
273
274 if (split_extensions(chain, chain_size, &exts, &exts_count) < 0) {
275 return -1;
276 }
277
278 for (size_t i = 0; i < exts_count; i++) {
279 if (exts[i]->type_id == 0x0201) {
280 root = exts[i]->value;
281 root_size = exts[i]->length_in_bytes;
282 break;
283 } else {
284 PSA_ADAC_LOG_ERR("sdm", "Ignoring unknown certificate format (0x%04x)\n",
285 exts[i]->type_id);
286 }
287 }
288
289 status = psa_adac_extract_public_key(root, root_size, &key_type, &pubkey, &pubkey_size);
290
291 if (status == PSA_SUCCESS) {
292 status = psa_adac_hash(alg, pubkey, pubkey_size, rotpk, buffer_size, rotpk_size);
293 if (rotpk_type != NULL) {
294 *rotpk_type = key_type;
295 }
296 } else if ((key_type == CMAC_AES) || (key_type == HMAC_SHA256)) {
297 /* FIXME: Work-around for symmetric keys on server */
298 *rotpk_size = (key_type == HMAC_SHA256) ? 32 : 16;
299 memset(rotpk, 0, *rotpk_size);
300 *rotpk_type = key_type;
301 status = PSA_SUCCESS;
302 }
303
304 free(exts);
305 return status;
306}
307
308#endif /* #if defined(MBEDTLS_FS_IO) */