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(¤t) == TEE_SUCCESS) 167 crypto_rng_add_event(sid, pnum, ¤t, 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