1 | // Copyright 2018-2024 Brian Smith. |
2 | // |
3 | // Permission to use, copy, modify, and/or distribute this software for any |
4 | // purpose with or without fee is hereby granted, provided that the above |
5 | // copyright notice and this permission notice appear in all copies. |
6 | // |
7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | |
15 | #![cfg (any( |
16 | all(target_arch = "aarch64" , target_endian = "little" ), |
17 | target_arch = "x86" , |
18 | target_arch = "x86_64" |
19 | ))] |
20 | |
21 | use super::{ffi::KeyValue, HTable, UpdateBlock, Xi}; |
22 | use crate::aead::gcm::ffi::BLOCK_LEN; |
23 | use crate::cpu; |
24 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
25 | use {super::UpdateBlocks, crate::polyfill::slice::AsChunks}; |
26 | |
27 | #[cfg (all(target_arch = "aarch64" , target_endian = "little" ))] |
28 | pub(in super::super) type RequiredCpuFeatures = cpu::arm::PMull; |
29 | |
30 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
31 | pub(in super::super) type RequiredCpuFeatures = (cpu::intel::ClMul, cpu::intel::Ssse3); |
32 | |
33 | #[derive (Clone)] |
34 | pub struct Key { |
35 | h_table: HTable, |
36 | } |
37 | |
38 | impl Key { |
39 | pub(in super::super) fn new(value: KeyValue, _cpu: RequiredCpuFeatures) -> Self { |
40 | Self { |
41 | h_table: unsafe { htable_new!(gcm_init_clmul, value) }, |
42 | } |
43 | } |
44 | |
45 | #[cfg (target_arch = "aarch64" )] |
46 | pub(super) fn inner(&self) -> &HTable { |
47 | &self.h_table |
48 | } |
49 | } |
50 | |
51 | impl UpdateBlock for Key { |
52 | #[cfg (target_arch = "aarch64" )] |
53 | fn update_block(&self, xi: &mut Xi, a: [u8; BLOCK_LEN]) { |
54 | prefixed_extern! { |
55 | fn gcm_gmult_clmul(xi: &mut Xi, Htable: &HTable); |
56 | } |
57 | xi.bitxor_assign(a); |
58 | unsafe { self.h_table.gmult(gcm_gmult_clmul, xi) }; |
59 | } |
60 | |
61 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
62 | fn update_block(&self, xi: &mut Xi, a: [u8; BLOCK_LEN]) { |
63 | self.update_blocks(xi, (&a).into()) |
64 | } |
65 | } |
66 | |
67 | #[cfg (any(target_arch = "x86" , target_arch = "x86_64" ))] |
68 | impl UpdateBlocks for Key { |
69 | fn update_blocks(&self, xi: &mut Xi, input: AsChunks<u8, { BLOCK_LEN }>) { |
70 | unsafe { ghash!(gcm_ghash_clmul, xi, &self.h_table, input) } |
71 | } |
72 | } |
73 | |