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