Line data Source code
1 : #ifndef HEADER_fd_src_ballet_aes_fd_aes_gcm_h
2 : #define HEADER_fd_src_ballet_aes_fd_aes_gcm_h
3 :
4 : #include "../fd_ballet_base.h"
5 :
6 : /* AES-GCM ************************************************************/
7 :
8 : /* fd_aes_gcm are APIs for authenticated AES-GCM encryption of messages.
9 : Compatible with TLS 1.3 and QUIC.
10 :
11 : AES-GCM is an extension of the AES-CTR stream cipher, adding the
12 : ability to detect malicious tampering of the ciphertext. (Henceforth
13 : referred to as 'authentication'.) Additionally, can protect a
14 : variable-sz unencrypted 'additional data' blob.
15 :
16 : ### Optimization Notes
17 :
18 : Currently supports 'all-in-one' API only, wherein the entire plain-
19 : text is encrypted/decrypted in a single blocking call. API may
20 : change in the future to support a batched 'multi block' API or
21 : streaming mode of operation.
22 :
23 : AES-GCM offers opportunity for processing of multiple AES blocks in
24 : parallel. However, the computation of the auth tag is a sequential
25 : chain with depth of block count of message. In QUIC, the max
26 : AES-GCM msg sz is limited by the packet MTU. Thus, auth tag
27 : processing can still be vectorized by processing independent packets
28 : in parallel. */
29 :
30 : /* Reference backend internals ****************************************/
31 :
32 : #include "fd_aes_gcm_ref.h"
33 :
34 : /* AES-NI backend internals *******************************************/
35 :
36 : /* FD_AES_GCM_ALIGN: minimum alignment of fd_aes_gcm_t.
37 : Large enough to satisfy alignment requirements on all architectures. */
38 : #define FD_AES_GCM_ALIGN (64UL)
39 :
40 : struct fd_aes_gcm_aesni_key {
41 : uchar key_enc[ 240 ];
42 : uchar key_dec[ 240 ];
43 : uint key_sz; /* 16, 24, or 32 */
44 : };
45 : typedef struct fd_aes_gcm_aesni_key fd_aes_gcm_aesni_key_t;
46 :
47 : /* Do not change. These offsets are hardcoded in fd_aes_gcm_aesni.S. */
48 : struct __attribute__((aligned(FD_AES_GCM_ALIGN))) fd_aes_gcm_aesni_state {
49 : fd_aes_gcm_aesni_key_t key;
50 : uchar pad1[ 12 ];
51 : uchar gcm [ 208 ];
52 : uchar iv [ 12 ];
53 : uchar pad2[ 52 ];
54 : };
55 : typedef struct fd_aes_gcm_aesni_state fd_aes_gcm_aesni_t;
56 :
57 : /* AVX10 backend internals ********************************************/
58 :
59 : /* Do not change. These offsets are hardcoded in fd_aes_gcm_avx10.S. */
60 : struct __attribute__((aligned(FD_AES_GCM_ALIGN))) fd_aes_gcm_avx10_state {
61 : fd_aes_gcm_aesni_key_t key;
62 : uchar pad1[ 28 ];
63 : uchar gcm [ 320 ];
64 : uchar iv [ 12 ];
65 : uchar pad2[ 52 ];
66 : };
67 : typedef struct fd_aes_gcm_avx10_state fd_aes_gcm_avx10_t;
68 :
69 : /* Backend selection **************************************************/
70 :
71 : #if FD_HAS_AVX512 && FD_HAS_GFNI && FD_HAS_AESNI
72 : #define FD_AES_GCM_IMPL 3 /* AVX10.1/512, VAES, VPCLMUL */
73 : #elif FD_HAS_AVX && FD_HAS_AESNI
74 : #define FD_AES_GCM_IMPL 2 /* AVX2, VAES */
75 : #elif FD_HAS_AESNI
76 : #define FD_AES_GCM_IMPL 1 /* AESNI */
77 : #else
78 : #define FD_AES_GCM_IMPL 0 /* Portable */
79 : #endif
80 :
81 : #if FD_AES_GCM_IMPL == 0
82 :
83 : typedef fd_aes_gcm_ref_t fd_aes_gcm_t;
84 4220575 : #define fd_aes_gcm_init fd_aes_gcm_init_ref
85 2105729 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_ref
86 2105244 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_ref
87 :
88 : #elif FD_AES_GCM_IMPL == 1
89 :
90 : typedef fd_aes_gcm_aesni_t fd_aes_gcm_t;
91 : #define fd_aes_gcm_init fd_aes_gcm_init_aesni
92 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_aesni
93 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_aesni
94 :
95 : #elif FD_AES_GCM_IMPL == 2
96 :
97 : typedef fd_aes_gcm_aesni_t fd_aes_gcm_t;
98 15100973 : #define fd_aes_gcm_init fd_aes_gcm_init_avx2
99 7545927 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_avx2
100 7545442 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_avx2
101 :
102 : #elif FD_AES_GCM_IMPL == 3
103 :
104 : typedef fd_aes_gcm_avx10_t fd_aes_gcm_t;
105 16766381 : #define fd_aes_gcm_init fd_aes_gcm_init_avx10_512
106 8378631 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_avx10_512
107 8378146 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_avx10_512
108 :
109 : #endif
110 :
111 : /* Public API *********************************************************/
112 :
113 : #define FD_AES_GCM_TAG_SZ (16UL)
114 97572 : #define FD_AES_GCM_IV_SZ (12UL)
115 :
116 : FD_PROTOTYPES_BEGIN
117 :
118 : /* fd_aes_gcm_init initializes an fd_aes_gcm_t object for encrypt or
119 : decrypt use. key_sz is in bytes, 16/24/32 for AES-128/192/256 */
120 :
121 : void
122 : fd_aes_gcm_init( fd_aes_gcm_t * aes_gcm,
123 : uchar const * key,
124 : ulong key_sz,
125 : uchar const iv[ 12 ] );
126 :
127 : static inline void
128 : fd_aes_128_gcm_init( fd_aes_gcm_t * aes_gcm,
129 : uchar const key[ 16 ],
130 36087913 : uchar const iv [ 12 ] ) {
131 36087913 : fd_aes_gcm_init( aes_gcm, key, 16UL, iv );
132 36087913 : }
133 :
134 : static inline void
135 : fd_aes_256_gcm_init( fd_aes_gcm_t * aes_gcm,
136 : uchar const key[ 32 ],
137 6 : uchar const iv [ 12 ] ) {
138 6 : fd_aes_gcm_init( aes_gcm, key, 32UL, iv );
139 6 : }
140 :
141 : /* fd_aes_gcm_aead_{encrypt,decrypt} implements the AES-GCM AEAD cipher
142 : c points to the ciphertext buffer. p points to the plaintext buffer.
143 : sz is the length of the p and c buffers. p,c,sz do not have align-
144 : ment requirements. iv points to the 12 byte initialization vector.
145 : aad points to the 'associated data' buffer (with size aad_sz). tag
146 : points to the 16 byte authentication tag (written by both decrypt and
147 : encrypt).
148 :
149 : (AAD serves to mix in arbitrary additional data into the auth tag,
150 : such that tampering with the AAD results in a decryption failure)
151 :
152 : fd_aes_gcm_encrypt reads plaintext from p, writes ciphertext to
153 : c, and writes the auth tag to 'tag'. encrypt cannot fail.
154 :
155 : fd_aes_gcm_decrypt reads the expected auth tag and ciphertext,
156 : and writes the decrypted plaintext to p. Ciphertext and auth tag are
157 : usually transmitted as-is over a network packet. Returns 1 on
158 : success, or 0 on failure. Reasons for failure include: Corrupt
159 : ciphertext, corrupt sz, corrupt AAD, or corrupt tag (could be due to
160 : network corruption or malicious tampering). */
161 :
162 : void
163 : fd_aes_gcm_encrypt( fd_aes_gcm_t * aes_gcm,
164 : uchar * c,
165 : uchar const * p,
166 : ulong sz,
167 : uchar const * aad,
168 : ulong aad_sz,
169 : uchar tag[ 16 ] );
170 :
171 : int
172 : fd_aes_gcm_decrypt( fd_aes_gcm_t * aes_gcm,
173 : uchar const * c,
174 : uchar * p,
175 : ulong sz,
176 : uchar const * aad,
177 : ulong aad_sz,
178 : uchar const tag[ 16 ] );
179 :
180 : #define FD_AES_GCM_DECRYPT_FAIL (0)
181 : #define FD_AES_GCM_DECRYPT_OK (1)
182 :
183 : FD_PROTOTYPES_END
184 :
185 : #endif /* HEADER_fd_src_ballet_aes_fd_aes_gcm_h */
|