xref: /optee_os/core/pta/veraison_attestation/sign.c (revision 900bf7c6b0b2a2dc120a1286c5efa414974078f9)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2024, Institute of Information Security (IISEC)
4  */
5 
6 #include <crypto/crypto.h>
7 #include <crypto/crypto_impl.h>
8 #include <stdlib_ext.h>
9 #include <string.h>
10 #include <utee_defines.h>
11 
12 #include "sign.h"
13 
14 #define KEY_SIZE 32
15 #define KEY_SIZE_BIT (KEY_SIZE * 8)
16 
17 static struct ecc_keypair *key;
18 static struct ecc_public_key *pubkey;
19 
20 #ifdef CFG_VERAISON_ATTESTATION_PTA_TEST_KEY
21 /*
22  * FIXME: Currently, keys are directly embedded within the code. From a security
23  * standpoint these keys should be stored in a secure location and properly
24  * loaded during program execution in a production environment.
25  * The key information has been extracted using the command:
26  *   $ echo "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4=" | base64 -d | xxd -p
27  * (and similar steps for obtaining the x, y, d values).
28  *
29  * {
30  *   "kty": "EC",
31  *   "crv": "P-256",
32  *   "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
33  *   "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
34  *   "d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE"
35  * }
36  */
37 
38 /* clang-format off */
39 #define PUBLIC_KEY_X {                                             \
40 		0x30, 0xa0, 0x42, 0x4c, 0xd2, 0x1c, 0x29, 0x44,    \
41 		0x83, 0x8a, 0x2d, 0x75, 0xc9, 0x2b, 0x37, 0xe7,    \
42 		0x6e, 0xa2, 0x0d, 0x9f, 0x00, 0x89, 0x3a, 0x3b,    \
43 		0x4e, 0xee, 0x8a, 0x3c, 0x0a, 0xaf, 0xec, 0x3e     \
44 	}
45 #define PUBLIC_KEY_Y {                                             \
46 		0xe0, 0x4b, 0x65, 0xe9, 0x24, 0x56, 0xd9, 0x88,    \
47 		0x8b, 0x52, 0xb3, 0x79, 0xbd, 0xfb, 0xd5, 0x1e,    \
48 		0xe8, 0x69, 0xef, 0x1f, 0x0f, 0xc6, 0x5b, 0x66,    \
49 		0x59, 0x69, 0x5b, 0x6c, 0xce, 0x08, 0x17, 0x23     \
50 	}
51 #define PRIVATE_KEY {                                              \
52 		0xf3, 0xbd, 0x0c, 0x07, 0xa8, 0x1f, 0xb9, 0x32,    \
53 		0x78, 0x1e, 0xd5, 0x27, 0x52, 0xf6, 0x0c, 0xc8,    \
54 		0x9a, 0x6b, 0xe5, 0xe5, 0x19, 0x34, 0xfe, 0x01,    \
55 		0x93, 0x8d, 0xdb, 0x55, 0xd8, 0xf7, 0x78, 0x01     \
56 	}
57 /* clang-format on */
58 #else
59 #error "This is experimental code, requires " \
60 	"CFG_VERAISON_ATTESTATION_PTA_TEST_KEY=y"
61 #endif
62 
hash_sha256(const uint8_t * msg,size_t msg_len,uint8_t * hash)63 static TEE_Result hash_sha256(const uint8_t *msg, size_t msg_len, uint8_t *hash)
64 {
65 	TEE_Result res = TEE_SUCCESS;
66 	void *ctx = NULL;
67 
68 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
69 	if (res != TEE_SUCCESS)
70 		return res;
71 	res = crypto_hash_init(ctx);
72 	if (res != TEE_SUCCESS)
73 		goto out;
74 	res = crypto_hash_update(ctx, msg, msg_len);
75 	if (res != TEE_SUCCESS)
76 		goto out;
77 	res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE);
78 
79 out:
80 	crypto_hash_free_ctx(ctx);
81 	return res;
82 }
83 
free_keypair(void)84 static void free_keypair(void)
85 {
86 	if (!key)
87 		return;
88 
89 	crypto_bignum_free(&key->d);
90 	crypto_bignum_free(&key->x);
91 	crypto_bignum_free(&key->y);
92 
93 	free_wipe(key);
94 	key = NULL;
95 }
96 
free_pubkey(void)97 static void free_pubkey(void)
98 {
99 	if (!pubkey)
100 		return;
101 
102 	crypto_bignum_free(&pubkey->x);
103 	crypto_bignum_free(&pubkey->y);
104 
105 	free_wipe(pubkey);
106 	pubkey = NULL;
107 }
108 
generate_key(void)109 static TEE_Result generate_key(void)
110 {
111 	TEE_Result res = TEE_SUCCESS;
112 	const uint8_t private_key[] = PRIVATE_KEY;
113 	const uint8_t public_key_x[] = PUBLIC_KEY_X;
114 	const uint8_t public_key_y[] = PUBLIC_KEY_Y;
115 
116 	/* Allocate a private key storage */
117 	assert(!key);
118 	key = calloc(1, sizeof(*key));
119 	if (!key)
120 		return TEE_ERROR_OUT_OF_MEMORY;
121 	res = crypto_acipher_alloc_ecc_keypair(key, TEE_TYPE_ECDSA_KEYPAIR,
122 					       KEY_SIZE_BIT);
123 	if (res != TEE_SUCCESS)
124 		goto free_keypair;
125 	key->curve = TEE_ECC_CURVE_NIST_P256;
126 
127 	/* Copy the private key */
128 	res = crypto_bignum_bin2bn(private_key, KEY_SIZE, key->d);
129 	if (res != TEE_SUCCESS)
130 		goto free_keypair;
131 
132 	/* Allocate a public key storage */
133 	assert(!pubkey);
134 	pubkey = calloc(1, sizeof(*pubkey));
135 	if (!pubkey) {
136 		res = TEE_ERROR_OUT_OF_MEMORY;
137 		goto free_keypair;
138 	}
139 	res = crypto_acipher_alloc_ecc_public_key(pubkey,
140 						  TEE_TYPE_ECDSA_PUBLIC_KEY,
141 						  KEY_SIZE_BIT);
142 	if (res != TEE_SUCCESS)
143 		goto free_pubkey;
144 	pubkey->curve = TEE_ECC_CURVE_NIST_P256;
145 
146 	/* Copy the public key */
147 	res = crypto_bignum_bin2bn(public_key_x, KEY_SIZE, pubkey->x);
148 	if (res != TEE_SUCCESS)
149 		goto free_pubkey;
150 
151 	res = crypto_bignum_bin2bn(public_key_y, KEY_SIZE, pubkey->y);
152 	if (res != TEE_SUCCESS)
153 		goto free_pubkey;
154 
155 	return TEE_SUCCESS;
156 
157 free_pubkey:
158 	free_pubkey();
159 free_keypair:
160 	free_keypair();
161 
162 	return res;
163 }
164 
sign_ecdsa_sha256(const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)165 TEE_Result sign_ecdsa_sha256(const uint8_t *msg, size_t msg_len, uint8_t *sig,
166 			     size_t *sig_len)
167 {
168 	TEE_Result res = TEE_SUCCESS;
169 	uint8_t hash_msg[TEE_SHA256_HASH_SIZE] = { };
170 
171 	/* Allocate the key pair*/
172 	res = generate_key();
173 	if (res != TEE_SUCCESS)
174 		return res;
175 
176 	/* Hash the msg */
177 	res = hash_sha256(msg, msg_len, hash_msg);
178 	if (res != TEE_SUCCESS)
179 		goto free;
180 
181 	/* Sign the hashed msg by the key pair*/
182 	res = crypto_acipher_ecc_sign(TEE_ALG_ECDSA_SHA256, key, hash_msg,
183 				      TEE_SHA256_HASH_SIZE, sig, sig_len);
184 	if (res != TEE_SUCCESS)
185 		goto free;
186 
187 	/* Verify the signature */
188 	res = crypto_acipher_ecc_verify(TEE_ALG_ECDSA_SHA256, pubkey, hash_msg,
189 					TEE_SHA256_HASH_SIZE, sig, *sig_len);
190 	if (res == TEE_SUCCESS)
191 		DMSG("Success to verify");
192 	else
193 		DMSG("Failed to verify");
194 
195 free:
196 	free_pubkey();
197 	assert(!pubkey);
198 	free_keypair();
199 	assert(!key);
200 
201 	return res;
202 }
203