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