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