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