1 /* 2 * Copyright (c) 2017, Linaro Limited 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8 #include <crypto/internal_aes-gcm.h> 9 #include <crypto/ghash-ce-core.h> 10 #include <io.h> 11 #include <kernel/panic.h> 12 #include <kernel/thread.h> 13 #include <tomcrypt.h> 14 #include <types_ext.h> 15 16 static void get_be_block(void *dst, const void *src) 17 { 18 uint64_t *d = dst; 19 20 d[1] = get_be64(src); 21 d[0] = get_be64((const uint8_t *)src + 8); 22 } 23 24 static void put_be_block(void *dst, const void *src) 25 { 26 const uint64_t *s = src; 27 28 put_be64(dst, s[1]); 29 put_be64((uint8_t *)dst + 8, s[0]); 30 } 31 32 TEE_Result internal_aes_gcm_set_key(struct internal_aes_gcm_ctx *ctx, 33 const void *key, size_t key_len) 34 { 35 uint64_t k[2]; 36 uint64_t a; 37 uint64_t b; 38 39 if (aes_setup(key, key_len, 0, &ctx->skey)) 40 return TEE_ERROR_BAD_PARAMETERS; 41 42 internal_aes_gcm_encrypt_block(ctx, ctx->ctr, ctx->hash_subkey); 43 44 /* Store hash key in little endian and multiply by 'x' */ 45 b = get_be64(ctx->hash_subkey); 46 a = get_be64(ctx->hash_subkey + 8); 47 k[0] = (a << 1) | (b >> 63); 48 k[1] = (b << 1) | (a >> 63); 49 if (b >> 63) 50 k[1] ^= 0xc200000000000000UL; 51 52 memcpy(ctx->hash_subkey, k, TEE_AES_BLOCK_SIZE); 53 return TEE_SUCCESS; 54 } 55 56 void internal_aes_gcm_ghash_update(struct internal_aes_gcm_ctx *ctx, 57 const void *head, const void *data, 58 size_t num_blocks) 59 { 60 uint32_t vfp_state; 61 uint64_t dg[2]; 62 uint64_t *k; 63 64 get_be_block(dg, ctx->hash_state); 65 66 k = (void *)ctx->hash_subkey; 67 68 vfp_state = thread_kernel_enable_vfp(); 69 70 #ifdef CFG_HWSUPP_PMULL 71 pmull_ghash_update_p64(num_blocks, dg, data, k, head); 72 #else 73 pmull_ghash_update_p8(num_blocks, dg, data, k, head); 74 #endif 75 thread_kernel_disable_vfp(vfp_state); 76 77 put_be_block(ctx->hash_state, dg); 78 } 79 80 #ifdef ARM64 81 void internal_aes_gcm_encrypt_block(struct internal_aes_gcm_ctx *ctx, 82 const void *src, void *dst) 83 { 84 uint32_t vfp_state; 85 void *enc_key = ctx->skey.rijndael.eK; 86 size_t rounds = ctx->skey.rijndael.Nr; 87 88 vfp_state = thread_kernel_enable_vfp(); 89 90 pmull_gcm_load_round_keys(enc_key, rounds); 91 pmull_gcm_encrypt_block(dst, src, rounds); 92 93 thread_kernel_disable_vfp(vfp_state); 94 } 95 96 void 97 internal_aes_gcm_update_payload_block_aligned(struct internal_aes_gcm_ctx *ctx, 98 TEE_OperationMode m, 99 const void *src, 100 size_t num_blocks, void *dst) 101 { 102 uint32_t vfp_state; 103 uint64_t dg[2]; 104 uint64_t ctr[2]; 105 uint64_t *k; 106 void *enc_key = ctx->skey.rijndael.eK; 107 size_t rounds = ctx->skey.rijndael.Nr; 108 109 get_be_block(dg, ctx->hash_state); 110 get_be_block(ctr, ctx->ctr); 111 112 k = (void *)ctx->hash_subkey; 113 114 vfp_state = thread_kernel_enable_vfp(); 115 116 pmull_gcm_load_round_keys(enc_key, rounds); 117 118 if (m == TEE_MODE_ENCRYPT) 119 pmull_gcm_encrypt(num_blocks, dg, dst, src, k, ctr, rounds, 120 ctx->buf_cryp); 121 else 122 pmull_gcm_decrypt(num_blocks, dg, dst, src, k, ctr, rounds); 123 124 thread_kernel_disable_vfp(vfp_state); 125 126 put_be_block(ctx->ctr, ctr); 127 put_be_block(ctx->hash_state, dg); 128 } 129 #endif /*ARM64*/ 130