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 : #define fd_aes_gcm_init fd_aes_gcm_init_ref
85 : #define fd_aes_gcm_set_iv fd_aes_gcm_set_iv_ref
86 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_ref
87 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_ref
88 :
89 : #elif FD_AES_GCM_IMPL == 1
90 :
91 : typedef fd_aes_gcm_aesni_t fd_aes_gcm_t;
92 : #define fd_aes_gcm_init fd_aes_gcm_init_aesni
93 : #define fd_aes_gcm_set_iv fd_aes_gcm_set_iv_aesni
94 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_aesni
95 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_aesni
96 :
97 : #elif FD_AES_GCM_IMPL == 2
98 :
99 : typedef fd_aes_gcm_aesni_t fd_aes_gcm_t;
100 : #define fd_aes_gcm_init fd_aes_gcm_init_avx2
101 : #define fd_aes_gcm_set_iv fd_aes_gcm_set_iv_avx2
102 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_avx2
103 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_avx2
104 :
105 : #elif FD_AES_GCM_IMPL == 3
106 :
107 : typedef fd_aes_gcm_avx10_t fd_aes_gcm_t;
108 0 : #define fd_aes_gcm_init fd_aes_gcm_init_avx10_512
109 0 : #define fd_aes_gcm_set_iv fd_aes_gcm_set_iv_avx10_512
110 0 : #define fd_aes_gcm_encrypt fd_aes_gcm_encrypt_avx10_512
111 0 : #define fd_aes_gcm_decrypt fd_aes_gcm_decrypt_avx10_512
112 :
113 : #endif
114 :
115 : /* Public API *********************************************************/
116 :
117 0 : #define FD_AES_GCM_TAG_SZ (16UL)
118 0 : #define FD_AES_GCM_IV_SZ (12UL)
119 :
120 : FD_PROTOTYPES_BEGIN
121 :
122 : /* fd_aes_gcm_init initializes an fd_aes_gcm_t object for encrypt or
123 : decrypt use. key_sz is in bytes, 16/24/32 for AES-128/192/256 */
124 :
125 : void
126 : fd_aes_gcm_init( fd_aes_gcm_t * aes_gcm,
127 : uchar const * key,
128 : ulong key_sz,
129 : uchar const iv[ 12 ] );
130 :
131 : /* fd_aes_gcm_set_iv replaces the IV of an initialized fd_aes_gcm_t,
132 : keeping the key schedule and GHASH tables. */
133 :
134 : void
135 : fd_aes_gcm_set_iv( fd_aes_gcm_t * aes_gcm,
136 : uchar const iv[ 12 ] );
137 :
138 : static inline void
139 : fd_aes_128_gcm_init( fd_aes_gcm_t * aes_gcm,
140 : uchar const key[ 16 ],
141 0 : uchar const iv [ 12 ] ) {
142 0 : fd_aes_gcm_init( aes_gcm, key, 16UL, iv );
143 0 : }
144 :
145 : static inline void
146 : fd_aes_256_gcm_init( fd_aes_gcm_t * aes_gcm,
147 : uchar const key[ 32 ],
148 0 : uchar const iv [ 12 ] ) {
149 0 : fd_aes_gcm_init( aes_gcm, key, 32UL, iv );
150 0 : }
151 :
152 : /* fd_aes_gcm_aead_{encrypt,decrypt} implements the AES-GCM AEAD cipher
153 : c points to the ciphertext buffer. p points to the plaintext buffer.
154 : sz is the length of the p and c buffers. p,c,sz do not have align-
155 : ment requirements. iv points to the 12 byte initialization vector.
156 : aad points to the 'associated data' buffer (with size aad_sz). tag
157 : points to the 16 byte authentication tag (written by both decrypt and
158 : encrypt).
159 :
160 : (AAD serves to mix in arbitrary additional data into the auth tag,
161 : such that tampering with the AAD results in a decryption failure)
162 :
163 : fd_aes_gcm_encrypt reads plaintext from p, writes ciphertext to
164 : c, and writes the auth tag to 'tag'. encrypt cannot fail.
165 :
166 : fd_aes_gcm_decrypt reads the expected auth tag and ciphertext,
167 : and writes the decrypted plaintext to p. Ciphertext and auth tag are
168 : usually transmitted as-is over a network packet. Returns 1 on
169 : success, or 0 on failure. Reasons for failure include: Corrupt
170 : ciphertext, corrupt sz, corrupt AAD, or corrupt tag (could be due to
171 : network corruption or malicious tampering). */
172 :
173 : void
174 : fd_aes_gcm_encrypt( fd_aes_gcm_t * aes_gcm,
175 : uchar * c,
176 : uchar const * p,
177 : ulong sz,
178 : uchar const * aad,
179 : ulong aad_sz,
180 : uchar tag[ 16 ] );
181 :
182 : int
183 : fd_aes_gcm_decrypt( fd_aes_gcm_t * aes_gcm,
184 : uchar const * c,
185 : uchar * p,
186 : ulong sz,
187 : uchar const * aad,
188 : ulong aad_sz,
189 : uchar const tag[ 16 ] );
190 :
191 : #define FD_AES_GCM_DECRYPT_FAIL (0)
192 : #define FD_AES_GCM_DECRYPT_OK (1)
193 :
194 : FD_PROTOTYPES_END
195 :
196 : #endif /* HEADER_fd_src_ballet_aes_fd_aes_gcm_h */
|