blob: c0756683625d5f3841fc6dd5129c071de7b166d3 [file] [log] [blame]
Tamas Ban28aeec32019-01-09 16:53:26 +00001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "attestation_key.h"
9#include <stdint.h>
10#include <stddef.h>
11#include "tfm_crypto_defs.h"
12#include "psa_crypto.h"
13#include "psa_crypto_platform.h"
14#include "psa_initial_attestation_api.h"
15#include "platform/include/tfm_plat_defs.h"
16#include "platform/include/tfm_plat_crypto_keys.h"
17
18/*!
19 * \var private_key_registered
20 *
21 * \brief Indicates whether the private part of the attestation key pair was
22 * registered to crypto service or not.
23 */
24static uint32_t private_key_registered = 0;
25
26/*!
27 * \var public_key_registered
28 *
29 * \brief Indicates whether the public part of the attestation key pair was
30 * registered to crypto service or not.
31 */
32static uint32_t public_key_registered = 0;
33
34/**
35 * \brief Map the curve type definition by RFC8152 (COSE) to PSA curve types
36 *
37 * \param[in] cose_curve COSE curve type definition \ref ecc_curve_t.
38 *
39 * \return Return PSA curve type according to \ref psa_ecc_curve_t. If
40 * mapping is not possible then return with USHRT_MAX.
41 */
42static inline psa_ecc_curve_t
43attest_map_elliptic_curve_type(enum ecc_curve_t cose_curve)
44{
45 psa_ecc_curve_t psa_curve;
46
47 /*FixMe: Mapping is not complete, missing ones: ED25519, ED448 */
48 switch (cose_curve) {
49 case P_256:
50 psa_curve = PSA_ECC_CURVE_SECP256R1;
51 break;
52 case P_384:
53 psa_curve = PSA_ECC_CURVE_SECP384R1;
54 break;
55 case P_521:
56 psa_curve = PSA_ECC_CURVE_SECP521R1;
57 break;
58 case X25519:
59 psa_curve = PSA_ECC_CURVE_CURVE25519;
60 break;
61 case X448:
62 psa_curve = PSA_ECC_CURVE_CURVE448;
63 break;
64 default:
65 psa_curve = USHRT_MAX;
66 }
67
68 return psa_curve;
69}
70
71enum psa_attest_err_t
72attest_register_initial_attestation_key(void)
73{
74 enum tfm_plat_err_t plat_res;
75 psa_ecc_curve_t psa_curve;
76 enum ecc_curve_t cose_curve;
77 struct ecc_key_t attest_key = {0};
78 uint8_t key_buf[ECC_P_256_KEY_SIZE];
79 psa_key_type_t attest_key_type;
80 size_t public_key_size;
81 psa_status_t crypto_res;
82 psa_key_policy_t policy;
83
84 /* Key(s) should be unregistered at this point */
85 if (private_key_registered != 0 || public_key_registered != 0) {
86 return PSA_ATTEST_ERR_GENERAL;
87 }
88
89 /* Get the initial attestation key */
90 plat_res = tfm_plat_get_initial_attest_key(key_buf, sizeof(key_buf),
91 &attest_key, &cose_curve);
92
93 /* Check the availability of the private key */
94 if (plat_res != TFM_PLAT_ERR_SUCCESS || attest_key.priv_key == NULL) {
95 return PSA_ATTEST_ERR_GENERAL;
96 }
97
98 /* Mapping of COSE curve type to PSA curve types */
99 psa_curve = attest_map_elliptic_curve_type(cose_curve);
100 if (psa_curve == USHRT_MAX) {
101 return PSA_ATTEST_ERR_GENERAL;
102 }
103
104 /* Setup the key policy for private key */
105 psa_key_policy_init(&policy);
106 psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_SIGN, 0); /* FixMe: alg */
107 crypto_res = psa_set_key_policy((psa_key_slot_t)ATTEST_PRIVATE_KEY_SLOT,
108 &policy);
109 if (crypto_res != PSA_SUCCESS) {
110 return PSA_ATTEST_ERR_GENERAL;
111 }
112
113 /* Set key type for private key */
114 /* FixMe: Use PSA_KEY_TYPE_ECC_KEYPAIR(psa_curve) when ECC key type will be
115 * supported in Crypto service
116 */
117 attest_key_type = PSA_KEY_TYPE_RAW_DATA;
118
119 /* Register private key to crypto service */
120 crypto_res = psa_import_key((psa_key_slot_t)ATTEST_PRIVATE_KEY_SLOT,
121 attest_key_type,
122 attest_key.priv_key,
123 attest_key.priv_key_size);
124
125 if (crypto_res != PSA_SUCCESS) {
126 return PSA_ATTEST_ERR_GENERAL;
127 }
128 private_key_registered = 1;
129
130 /* Check whether public key is available, not mandatory */
131 if (attest_key.pubx_key == NULL) {
132 return PSA_ATTEST_ERR_SUCCESS;
133 }
134
135 /* Setup the key policy for public key */
136 psa_key_policy_init(&policy);
137 psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_VERIFY, 0); /* FixMe: alg */
138 crypto_res = psa_set_key_policy((psa_key_slot_t)ATTEST_PUBLIC_KEY_SLOT,
139 &policy);
140 if (crypto_res != PSA_SUCCESS) {
141 return PSA_ATTEST_ERR_GENERAL;
142 }
143
144 /* Set key type for public key */
145 /* FixMe: Use PSA_KEY_TYPE_ECC_PUBLIC_KEY(psa_curve) when ECC key type will
146 * be supported in Crypto service
147 */
148 attest_key_type = PSA_KEY_TYPE_RAW_DATA;
149
150 /* Register public key to crypto service */
151 public_key_size = attest_key.pubx_key_size + attest_key.puby_key_size;
152
153 crypto_res = psa_import_key((psa_key_slot_t)ATTEST_PUBLIC_KEY_SLOT,
154 attest_key_type,
155 attest_key.pubx_key,
156 public_key_size);
157
158 if (crypto_res != PSA_SUCCESS) {
159 return PSA_ATTEST_ERR_GENERAL;
160 }
161 public_key_registered = 1;
162
163 return PSA_ATTEST_ERR_SUCCESS;
164}
165
166enum psa_attest_err_t
167attest_unregister_initial_attestation_key(void)
168{
169 psa_status_t crypto_res;
170
171 /* Only private key is mandatory */
172 if (private_key_registered != 1) {
173 return PSA_ATTEST_ERR_GENERAL;
174 }
175
176 crypto_res = psa_destroy_key((psa_key_slot_t)ATTEST_PRIVATE_KEY_SLOT);
177 if (crypto_res != PSA_SUCCESS) {
178 return PSA_ATTEST_ERR_GENERAL;
179 }
180 private_key_registered = 0;
181
182 if (public_key_registered) {
183 crypto_res = psa_destroy_key((psa_key_slot_t)ATTEST_PUBLIC_KEY_SLOT);
184 if (crypto_res != PSA_SUCCESS) {
185 return PSA_ATTEST_ERR_GENERAL;
186 }
187 public_key_registered = 0;
188 }
189
190 return PSA_ATTEST_ERR_SUCCESS;
191}