1 /*
2 * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <stdint.h>
9
10 #include <common/debug.h>
11 #include <drivers/auth/crypto_mod.h>
12 #include <drivers/measured_boot/event_log/tcg.h>
13
14 /* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */
15
16 /*
17 * The crypto module is responsible for verifying digital signatures and hashes.
18 * It relies on a crypto library to perform the cryptographic operations.
19 *
20 * The crypto module itself does not impose any specific format on signatures,
21 * signature algorithm, keys or hashes, but most cryptographic libraries will
22 * take the parameters as the following DER encoded ASN.1 structures:
23 *
24 * AlgorithmIdentifier ::= SEQUENCE {
25 * algorithm OBJECT IDENTIFIER,
26 * parameters ANY DEFINED BY algorithm OPTIONAL
27 * }
28 *
29 * DigestInfo ::= SEQUENCE {
30 * digestAlgorithm AlgorithmIdentifier,
31 * digest OCTET STRING
32 * }
33 *
34 * SubjectPublicKeyInfo ::= SEQUENCE {
35 * algorithm AlgorithmIdentifier,
36 * subjectPublicKey BIT STRING
37 * }
38 *
39 * SignatureAlgorithm ::= AlgorithmIdentifier
40 *
41 * SignatureValue ::= BIT STRING
42 */
43
44 /*
45 * Perform some static checking and call the library initialization function
46 */
crypto_mod_init(void)47 void crypto_mod_init(void)
48 {
49 assert(crypto_lib_desc.name != NULL);
50 assert(crypto_lib_desc.init != NULL);
51 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
52 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
53 assert(crypto_lib_desc.verify_signature != NULL);
54 assert(crypto_lib_desc.verify_hash != NULL);
55 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
56 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
57
58 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
59 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
60 assert(crypto_lib_desc.calc_hash != NULL);
61 #endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
62 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
63
64 /* Initialize the cryptographic library */
65 crypto_lib_desc.init();
66 INFO("Using crypto library '%s'\n", crypto_lib_desc.name);
67 }
68
69 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
70 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
71 /*
72 * Function to verify a digital signature
73 *
74 * Parameters:
75 *
76 * data_ptr, data_len: signed data
77 * sig_ptr, sig_len: the digital signature
78 * sig_alg_ptr, sig_alg_len: the digital signature algorithm
79 * pk_ptr, pk_len: the public key
80 */
crypto_mod_verify_signature(void * data_ptr,unsigned int data_len,void * sig_ptr,unsigned int sig_len,void * sig_alg_ptr,unsigned int sig_alg_len,void * pk_ptr,unsigned int pk_len)81 int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
82 void *sig_ptr, unsigned int sig_len,
83 void *sig_alg_ptr, unsigned int sig_alg_len,
84 void *pk_ptr, unsigned int pk_len)
85 {
86 assert(data_ptr != NULL);
87 assert(data_len != 0);
88 assert(sig_ptr != NULL);
89 assert(sig_len != 0);
90 assert(sig_alg_ptr != NULL);
91 assert(sig_alg_len != 0);
92 assert(pk_ptr != NULL);
93 assert(pk_len != 0);
94
95 return crypto_lib_desc.verify_signature(data_ptr, data_len,
96 sig_ptr, sig_len,
97 sig_alg_ptr, sig_alg_len,
98 pk_ptr, pk_len);
99 }
100
101 /*
102 * Verify a hash by comparison
103 *
104 * Parameters:
105 *
106 * data_ptr, data_len: data to be hashed
107 * digest_info_ptr, digest_info_len: hash to be compared
108 */
crypto_mod_verify_hash(void * data_ptr,unsigned int data_len,void * digest_info_ptr,unsigned int digest_info_len)109 int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
110 void *digest_info_ptr, unsigned int digest_info_len)
111 {
112 assert(data_ptr != NULL);
113 assert(data_len != 0);
114 assert(digest_info_ptr != NULL);
115 assert(digest_info_len != 0);
116
117 return crypto_lib_desc.verify_hash(data_ptr, data_len,
118 digest_info_ptr, digest_info_len);
119 }
120 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
121 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
122
123 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
124 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
125 /*
126 * Calculate a hash
127 *
128 * Parameters:
129 *
130 * alg: message digest algorithm
131 * data_ptr, data_len: data to be hashed
132 * output: resulting hash
133 */
crypto_mod_calc_hash(enum crypto_md_algo alg,void * data_ptr,unsigned int data_len,unsigned char output[CRYPTO_MD_MAX_SIZE])134 int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
135 unsigned int data_len,
136 unsigned char output[CRYPTO_MD_MAX_SIZE])
137 {
138 assert(data_ptr != NULL);
139 assert(data_len != 0);
140 assert(output != NULL);
141
142 return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output);
143 }
144
crypto_mod_tcg_hash(uint32_t alg_id,void * data_ptr,unsigned int data_len,uint8_t * digest)145 int crypto_mod_tcg_hash(uint32_t alg_id, void *data_ptr, unsigned int data_len,
146 uint8_t *digest)
147 {
148 enum crypto_md_algo crypto_alg_id;
149
150 assert(data_ptr != NULL);
151 assert(data_len != 0U);
152 assert(digest != NULL);
153
154 switch (alg_id) {
155 case TPM_ALG_SHA256:
156 crypto_alg_id = CRYPTO_MD_SHA256;
157 break;
158 case TPM_ALG_SHA384:
159 crypto_alg_id = CRYPTO_MD_SHA384;
160 break;
161 case TPM_ALG_SHA512:
162 crypto_alg_id = CRYPTO_MD_SHA512;
163 break;
164 default:
165 ERROR("Unsupported TCG algorithm ID %u.\n", alg_id);
166 return -1;
167 }
168
169 return crypto_mod_calc_hash(crypto_alg_id, data_ptr, data_len, digest);
170 }
171 #endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
172 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
173
crypto_mod_convert_pk(void * full_pk_ptr,unsigned int full_pk_len,void ** hashed_pk_ptr,unsigned int * hashed_pk_len)174 int crypto_mod_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
175 void **hashed_pk_ptr, unsigned int *hashed_pk_len)
176 {
177 if (crypto_lib_desc.convert_pk != NULL) {
178 return crypto_lib_desc.convert_pk(full_pk_ptr, full_pk_len,
179 hashed_pk_ptr, hashed_pk_len);
180 }
181
182 *hashed_pk_ptr = full_pk_ptr;
183 *hashed_pk_len = full_pk_len;
184
185 return 0;
186 }
187
188 /*
189 * Authenticated decryption of data
190 *
191 * Parameters:
192 *
193 * dec_algo: authenticated decryption algorithm
194 * data_ptr, len: data to be decrypted (inout param)
195 * key, key_len, key_flags: symmetric decryption key
196 * iv, iv_len: initialization vector
197 * tag, tag_len: authentication tag
198 */
crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo,void * data_ptr,size_t len,const void * key,unsigned int key_len,unsigned int key_flags,const void * iv,unsigned int iv_len,const void * tag,unsigned int tag_len)199 int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
200 size_t len, const void *key, unsigned int key_len,
201 unsigned int key_flags, const void *iv,
202 unsigned int iv_len, const void *tag,
203 unsigned int tag_len)
204 {
205 assert(crypto_lib_desc.auth_decrypt != NULL);
206 assert(data_ptr != NULL);
207 assert(len != 0U);
208 assert(key != NULL);
209 assert(key_len != 0U);
210 assert(iv != NULL);
211 assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE));
212 assert(tag != NULL);
213 assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE));
214
215 return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key,
216 key_len, key_flags, iv, iv_len, tag,
217 tag_len);
218 }
219
220 /* Perform end of psa crypto usage calls to finish */
crypto_mod_finish(void)221 void crypto_mod_finish(void)
222 {
223 if (crypto_lib_desc.finish != NULL) {
224 crypto_lib_desc.finish();
225 INFO("Finished using crypto library '%s'\n", crypto_lib_desc.name);
226 }
227 }
228