1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014-2021, Linaro Limited
4 * Copyright (c) 2021, SumUp Services GmbH
5 */
6
7 #include <crypto/crypto.h>
8 #include <initcall.h>
9 #include <kernel/dt_driver.h>
10 #include <kernel/panic.h>
11 #include <kernel/tee_time.h>
12 #include <stdlib.h>
13 #include <string_ext.h>
14 #include <string.h>
15 #include <tee/tee_cryp_utl.h>
16 #include <trace.h>
17 #include <utee_defines.h>
18
tee_alg_get_digest_size(uint32_t algo,size_t * size)19 TEE_Result tee_alg_get_digest_size(uint32_t algo, size_t *size)
20 {
21 size_t digest_size = TEE_ALG_GET_DIGEST_SIZE(algo);
22
23 if (!digest_size)
24 return TEE_ERROR_NOT_SUPPORTED;
25
26 *size = digest_size;
27
28 return TEE_SUCCESS;
29 }
30
tee_hash_createdigest(uint32_t algo,const uint8_t * data,size_t datalen,uint8_t * digest,size_t digestlen)31 TEE_Result tee_hash_createdigest(uint32_t algo, const uint8_t *data,
32 size_t datalen, uint8_t *digest,
33 size_t digestlen)
34 {
35 TEE_Result res;
36 void *ctx = NULL;
37
38 res = crypto_hash_alloc_ctx(&ctx, algo);
39 if (res)
40 return res;
41
42 res = crypto_hash_init(ctx);
43 if (res)
44 goto out;
45
46 if (datalen != 0) {
47 res = crypto_hash_update(ctx, data, datalen);
48 if (res)
49 goto out;
50 }
51
52 res = crypto_hash_final(ctx, digest, digestlen);
53 out:
54 crypto_hash_free_ctx(ctx);
55
56 return res;
57 }
58
tee_cipher_get_block_size(uint32_t algo,size_t * size)59 TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size)
60 {
61 switch (algo) {
62 case TEE_ALG_AES_CBC_MAC_NOPAD:
63 case TEE_ALG_AES_CBC_MAC_PKCS5:
64 case TEE_ALG_AES_CMAC:
65 case TEE_ALG_AES_ECB_NOPAD:
66 case TEE_ALG_AES_CBC_NOPAD:
67 case TEE_ALG_AES_CTR:
68 case TEE_ALG_AES_CTS:
69 case TEE_ALG_AES_XTS:
70 case TEE_ALG_AES_CCM:
71 case TEE_ALG_AES_GCM:
72 case TEE_ALG_SM4_ECB_NOPAD:
73 case TEE_ALG_SM4_CBC_NOPAD:
74 case TEE_ALG_SM4_XTS:
75 case TEE_ALG_SM4_CTR:
76 *size = 16;
77 break;
78
79 case TEE_ALG_DES_CBC_MAC_NOPAD:
80 case TEE_ALG_DES_CBC_MAC_PKCS5:
81 case TEE_ALG_DES_ECB_NOPAD:
82 case TEE_ALG_DES_CBC_NOPAD:
83 case TEE_ALG_DES3_CBC_MAC_NOPAD:
84 case TEE_ALG_DES3_CBC_MAC_PKCS5:
85 case TEE_ALG_DES3_ECB_NOPAD:
86 case TEE_ALG_DES3_CBC_NOPAD:
87 case TEE_ALG_DES3_CMAC:
88 *size = 8;
89 break;
90
91 default:
92 return TEE_ERROR_NOT_SUPPORTED;
93 }
94
95 return TEE_SUCCESS;
96 }
97
tee_do_cipher_update(void * ctx,uint32_t algo,TEE_OperationMode mode,bool last_block,const uint8_t * data,size_t len,uint8_t * dst)98 TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo,
99 TEE_OperationMode mode, bool last_block,
100 const uint8_t *data, size_t len, uint8_t *dst)
101 {
102 TEE_Result res;
103 size_t block_size;
104
105 if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT)
106 return TEE_ERROR_BAD_PARAMETERS;
107
108 /*
109 * Check that the block contains the correct number of data, apart
110 * for the last block in some XTS / CTR / XTS mode
111 */
112 res = tee_cipher_get_block_size(algo, &block_size);
113 if (res != TEE_SUCCESS)
114 return res;
115 if ((len % block_size) != 0) {
116 if (!last_block && algo != TEE_ALG_AES_CTR)
117 return TEE_ERROR_BAD_PARAMETERS;
118
119 switch (algo) {
120 case TEE_ALG_AES_ECB_NOPAD:
121 case TEE_ALG_DES_ECB_NOPAD:
122 case TEE_ALG_DES3_ECB_NOPAD:
123 case TEE_ALG_AES_CBC_NOPAD:
124 case TEE_ALG_DES_CBC_NOPAD:
125 case TEE_ALG_DES3_CBC_NOPAD:
126 case TEE_ALG_SM4_ECB_NOPAD:
127 case TEE_ALG_SM4_CBC_NOPAD:
128 return TEE_ERROR_BAD_PARAMETERS;
129
130 case TEE_ALG_AES_CTR:
131 case TEE_ALG_AES_XTS:
132 case TEE_ALG_AES_CTS:
133 case TEE_ALG_SM4_XTS:
134 /*
135 * These modes doesn't require padding for the last
136 * block.
137 *
138 * This isn't entirely true, both XTS and CTS can only
139 * encrypt minimum one block and also they need at least
140 * one complete block in the last update to finish the
141 * encryption. The algorithms are supposed to detect
142 * that, we're only making sure that all data fed up to
143 * that point consists of complete blocks.
144 */
145 break;
146
147 default:
148 return TEE_ERROR_NOT_SUPPORTED;
149 }
150 }
151
152 return crypto_cipher_update(ctx, mode, last_block, data, len, dst);
153 }
154
155 /*
156 * Override this in your platform code to feed the PRNG platform-specific
157 * jitter entropy. This implementation does not efficiently deliver entropy
158 * and is here for backwards-compatibility.
159 */
plat_prng_add_jitter_entropy(enum crypto_rng_src sid,unsigned int * pnum)160 __weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid,
161 unsigned int *pnum)
162 {
163 TEE_Time current;
164
165 #ifdef CFG_SECURE_TIME_SOURCE_REE
166 if (CRYPTO_RNG_SRC_IS_QUICK(sid))
167 return; /* Can't read REE time here */
168 #endif
169
170 if (tee_time_get_sys_time(¤t) == TEE_SUCCESS)
171 crypto_rng_add_event(sid, pnum, ¤t, sizeof(current));
172 }
173
__plat_rng_init(void)174 void __plat_rng_init(void)
175 {
176 TEE_Result res = TEE_SUCCESS;
177 TEE_Time t;
178
179 #ifndef CFG_SECURE_TIME_SOURCE_REE
180 /*
181 * This isn't much of a seed. Ideally we should either get a seed from
182 * a hardware RNG or from a previously saved seed.
183 *
184 * Seeding with hardware RNG is currently up to the platform to
185 * override this function.
186 *
187 * Seeding with a saved seed will require cooperation from normal
188 * world, this is still TODO.
189 */
190 res = tee_time_get_sys_time(&t);
191 #else
192 EMSG("Warning: seeding RNG with zeroes");
193 memset(&t, 0, sizeof(t));
194 #endif
195 if (!res)
196 res = crypto_rng_init(&t, sizeof(t));
197 if (res) {
198 EMSG("Failed to initialize RNG: %#" PRIx32, res);
199 panic();
200 }
201 }
202
203 /*
204 * Override this in your platform code. This default implementation only seeds
205 * the random number generator from an easily predictable timestamp value or a
206 * constant value. It is not suitable for a secure environment.
207 */
208 #ifdef CFG_INSECURE
209 void plat_rng_init(void) __weak __alias("__plat_rng_init");
210 #endif
211
tee_cryp_init(void)212 static TEE_Result tee_cryp_init(void)
213 {
214 TEE_Result res = crypto_init();
215
216 if (res) {
217 EMSG("Failed to initialize crypto API: %#" PRIx32, res);
218 panic();
219 }
220 plat_rng_init();
221
222 dt_driver_crypt_init_complete();
223
224 return TEE_SUCCESS;
225 }
226 service_init_crypto(tee_cryp_init);
227