xref: /optee_os/core/tee/tee_cryp_utl.c (revision 4af447d4084e293800d4e463d65003c016b91f29)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, Linaro Limited
4  * Copyright (c) 2021, SumUp Services GmbH
5  */
6 
7 #include <crypto/crypto.h>
8 #include <initcall.h>
9 #include <kernel/panic.h>
10 #include <kernel/tee_time.h>
11 #include <rng_support.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 
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 
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 
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_CTR:
75 		*size = 16;
76 		break;
77 
78 	case TEE_ALG_DES_CBC_MAC_NOPAD:
79 	case TEE_ALG_DES_CBC_MAC_PKCS5:
80 	case TEE_ALG_DES_ECB_NOPAD:
81 	case TEE_ALG_DES_CBC_NOPAD:
82 	case TEE_ALG_DES3_CBC_MAC_NOPAD:
83 	case TEE_ALG_DES3_CBC_MAC_PKCS5:
84 	case TEE_ALG_DES3_ECB_NOPAD:
85 	case TEE_ALG_DES3_CBC_NOPAD:
86 	case TEE_ALG_DES3_CMAC:
87 		*size = 8;
88 		break;
89 
90 	default:
91 		return TEE_ERROR_NOT_SUPPORTED;
92 	}
93 
94 	return TEE_SUCCESS;
95 }
96 
97 TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo,
98 				TEE_OperationMode mode, bool last_block,
99 				const uint8_t *data, size_t len, uint8_t *dst)
100 {
101 	TEE_Result res;
102 	size_t block_size;
103 
104 	if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT)
105 		return TEE_ERROR_BAD_PARAMETERS;
106 
107 	/*
108 	 * Check that the block contains the correct number of data, apart
109 	 * for the last block in some XTS / CTR / XTS mode
110 	 */
111 	res = tee_cipher_get_block_size(algo, &block_size);
112 	if (res != TEE_SUCCESS)
113 		return res;
114 	if ((len % block_size) != 0) {
115 		if (!last_block && algo != TEE_ALG_AES_CTR)
116 			return TEE_ERROR_BAD_PARAMETERS;
117 
118 		switch (algo) {
119 		case TEE_ALG_AES_ECB_NOPAD:
120 		case TEE_ALG_DES_ECB_NOPAD:
121 		case TEE_ALG_DES3_ECB_NOPAD:
122 		case TEE_ALG_AES_CBC_NOPAD:
123 		case TEE_ALG_DES_CBC_NOPAD:
124 		case TEE_ALG_DES3_CBC_NOPAD:
125 		case TEE_ALG_SM4_ECB_NOPAD:
126 		case TEE_ALG_SM4_CBC_NOPAD:
127 			return TEE_ERROR_BAD_PARAMETERS;
128 
129 		case TEE_ALG_AES_CTR:
130 		case TEE_ALG_AES_XTS:
131 		case TEE_ALG_AES_CTS:
132 			/*
133 			 * These modes doesn't require padding for the last
134 			 * block.
135 			 *
136 			 * This isn't entirely true, both XTS and CTS can only
137 			 * encrypt minimum one block and also they need at least
138 			 * one complete block in the last update to finish the
139 			 * encryption. The algorithms are supposed to detect
140 			 * that, we're only making sure that all data fed up to
141 			 * that point consists of complete blocks.
142 			 */
143 			break;
144 
145 		default:
146 			return TEE_ERROR_NOT_SUPPORTED;
147 		}
148 	}
149 
150 	return crypto_cipher_update(ctx, mode, last_block, data, len, dst);
151 }
152 
153 /*
154  * Override this in your platform code to feed the PRNG platform-specific
155  * jitter entropy. This implementation does not efficiently deliver entropy
156  * and is here for backwards-compatibility.
157  */
158 __weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid,
159 					 unsigned int *pnum)
160 {
161 	TEE_Time current;
162 
163 #ifdef CFG_SECURE_TIME_SOURCE_REE
164 	if (CRYPTO_RNG_SRC_IS_QUICK(sid))
165 		return; /* Can't read REE time here */
166 #endif
167 
168 	if (tee_time_get_sys_time(&current) == TEE_SUCCESS)
169 		crypto_rng_add_event(sid, pnum, &current, sizeof(current));
170 }
171 
172 __weak void plat_rng_init(void)
173 {
174 	TEE_Result res = TEE_SUCCESS;
175 	TEE_Time t;
176 
177 #ifndef CFG_SECURE_TIME_SOURCE_REE
178 	/*
179 	 * This isn't much of a seed. Ideally we should either get a seed from
180 	 * a hardware RNG or from a previously saved seed.
181 	 *
182 	 * Seeding with hardware RNG is currently up to the platform to
183 	 * override this function.
184 	 *
185 	 * Seeding with a saved seed will require cooperation from normal
186 	 * world, this is still TODO.
187 	 */
188 	res = tee_time_get_sys_time(&t);
189 #else
190 	EMSG("Warning: seeding RNG with zeroes");
191 	memset(&t, 0, sizeof(t));
192 #endif
193 	if (!res)
194 		res = crypto_rng_init(&t, sizeof(t));
195 	if (res) {
196 		EMSG("Failed to initialize RNG: %#" PRIx32, res);
197 		panic();
198 	}
199 }
200 
201 static TEE_Result tee_cryp_init(void)
202 {
203 	TEE_Result res = crypto_init();
204 
205 	if (res) {
206 		EMSG("Failed to initialize crypto API: %#" PRIx32, res);
207 		panic();
208 	}
209 	plat_rng_init();
210 
211 	return TEE_SUCCESS;
212 }
213 service_init(tee_cryp_init);
214