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_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 			/*
134 			 * These modes doesn't require padding for the last
135 			 * block.
136 			 *
137 			 * This isn't entirely true, both XTS and CTS can only
138 			 * encrypt minimum one block and also they need at least
139 			 * one complete block in the last update to finish the
140 			 * encryption. The algorithms are supposed to detect
141 			 * that, we're only making sure that all data fed up to
142 			 * that point consists of complete blocks.
143 			 */
144 			break;
145 
146 		default:
147 			return TEE_ERROR_NOT_SUPPORTED;
148 		}
149 	}
150 
151 	return crypto_cipher_update(ctx, mode, last_block, data, len, dst);
152 }
153 
154 /*
155  * Override this in your platform code to feed the PRNG platform-specific
156  * jitter entropy. This implementation does not efficiently deliver entropy
157  * and is here for backwards-compatibility.
158  */
plat_prng_add_jitter_entropy(enum crypto_rng_src sid,unsigned int * pnum)159 __weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid,
160 					 unsigned int *pnum)
161 {
162 	TEE_Time current;
163 
164 #ifdef CFG_SECURE_TIME_SOURCE_REE
165 	if (CRYPTO_RNG_SRC_IS_QUICK(sid))
166 		return; /* Can't read REE time here */
167 #endif
168 
169 	if (tee_time_get_sys_time(&current) == TEE_SUCCESS)
170 		crypto_rng_add_event(sid, pnum, &current, sizeof(current));
171 }
172 
plat_rng_init(void)173 __weak void plat_rng_init(void)
174 {
175 	TEE_Result res = TEE_SUCCESS;
176 	TEE_Time t;
177 
178 #ifndef CFG_SECURE_TIME_SOURCE_REE
179 	/*
180 	 * This isn't much of a seed. Ideally we should either get a seed from
181 	 * a hardware RNG or from a previously saved seed.
182 	 *
183 	 * Seeding with hardware RNG is currently up to the platform to
184 	 * override this function.
185 	 *
186 	 * Seeding with a saved seed will require cooperation from normal
187 	 * world, this is still TODO.
188 	 */
189 	res = tee_time_get_sys_time(&t);
190 #else
191 	EMSG("Warning: seeding RNG with zeroes");
192 	memset(&t, 0, sizeof(t));
193 #endif
194 	if (!res)
195 		res = crypto_rng_init(&t, sizeof(t));
196 	if (res) {
197 		EMSG("Failed to initialize RNG: %#" PRIx32, res);
198 		panic();
199 	}
200 }
201 
tee_cryp_init(void)202 static TEE_Result tee_cryp_init(void)
203 {
204 	TEE_Result res = crypto_init();
205 
206 	if (res) {
207 		EMSG("Failed to initialize crypto API: %#" PRIx32, res);
208 		panic();
209 	}
210 	plat_rng_init();
211 
212 	dt_driver_crypt_init_complete();
213 
214 	return TEE_SUCCESS;
215 }
216 service_init(tee_cryp_init);
217