lib/crypto: optimize aes_gcm_128
[Samba.git] / lib / crypto / aes_gcm_128.c
blobbfbf176e53dc26d9a6d8e6f0811141a74e0de971
1 /*
2 AES-GCM-128
4 Copyright (C) Stefan Metzmacher 2014
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "replace.h"
21 #include "../lib/crypto/crypto.h"
22 #include "lib/util/byteorder.h"
24 static inline void aes_gcm_128_inc32(uint8_t inout[AES_BLOCK_SIZE])
26 uint32_t v;
28 v = RIVAL(inout, AES_BLOCK_SIZE - 4);
29 v += 1;
30 RSIVAL(inout, AES_BLOCK_SIZE - 4, v);
33 static inline void aes_gcm_128_mul(const uint8_t x[AES_BLOCK_SIZE],
34 const uint8_t y[AES_BLOCK_SIZE],
35 uint8_t v[AES_BLOCK_SIZE],
36 uint8_t z[AES_BLOCK_SIZE])
38 uint8_t i;
39 /* 11100001 || 0^120 */
40 static const uint8_t r[AES_BLOCK_SIZE] = {
41 0xE1, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00,
47 memset(z, 0, AES_BLOCK_SIZE);
48 memcpy(v, y, AES_BLOCK_SIZE);
50 for (i = 0; i < AES_BLOCK_SIZE; i++) {
51 uint8_t mask;
52 for (mask = 0x80; mask != 0 ; mask >>= 1) {
53 uint8_t v_lsb = v[AES_BLOCK_SIZE-1] & 1;
54 if (x[i] & mask) {
55 aes_block_xor(z, v, z);
58 aes_block_rshift(v, v);
59 if (v_lsb != 0) {
60 aes_block_xor(v, r, v);
66 static inline void aes_gcm_128_ghash_block(struct aes_gcm_128_context *ctx,
67 const uint8_t in[AES_BLOCK_SIZE])
69 aes_block_xor(ctx->Y, in, ctx->y.block);
70 aes_gcm_128_mul(ctx->y.block, ctx->H, ctx->v.block, ctx->Y);
73 void aes_gcm_128_init(struct aes_gcm_128_context *ctx,
74 const uint8_t K[AES_BLOCK_SIZE],
75 const uint8_t IV[AES_GCM_128_IV_SIZE])
77 ZERO_STRUCTP(ctx);
79 AES_set_encrypt_key(K, 128, &ctx->aes_key);
82 * Step 1: generate H (ctx->Y is the zero block here)
84 AES_encrypt(ctx->Y, ctx->H, &ctx->aes_key);
87 * Step 2: generate J0
89 memcpy(ctx->J0, IV, AES_GCM_128_IV_SIZE);
90 aes_gcm_128_inc32(ctx->J0);
93 * We need to prepare CB with J0.
95 memcpy(ctx->CB, ctx->J0, AES_BLOCK_SIZE);
96 ctx->c.ofs = AES_BLOCK_SIZE;
99 static inline void aes_gcm_128_update_tmp(struct aes_gcm_128_context *ctx,
100 struct aes_gcm_128_tmp *tmp,
101 const uint8_t *v, size_t v_len)
103 tmp->total += v_len;
105 if (tmp->ofs > 0) {
106 size_t copy = MIN(AES_BLOCK_SIZE - tmp->ofs, v_len);
108 memcpy(tmp->block + tmp->ofs, v, copy);
109 tmp->ofs += copy;
110 v += copy;
111 v_len -= copy;
114 if (tmp->ofs == AES_BLOCK_SIZE) {
115 aes_gcm_128_ghash_block(ctx, tmp->block);
116 tmp->ofs = 0;
119 while (v_len >= AES_BLOCK_SIZE) {
120 aes_gcm_128_ghash_block(ctx, v);
121 v += AES_BLOCK_SIZE;
122 v_len -= AES_BLOCK_SIZE;
125 if (v_len == 0) {
126 return;
129 ZERO_STRUCT(tmp->block);
130 memcpy(tmp->block, v, v_len);
131 tmp->ofs = v_len;
134 void aes_gcm_128_updateA(struct aes_gcm_128_context *ctx,
135 const uint8_t *a, size_t a_len)
137 aes_gcm_128_update_tmp(ctx, &ctx->A, a, a_len);
140 void aes_gcm_128_updateC(struct aes_gcm_128_context *ctx,
141 const uint8_t *c, size_t c_len)
143 if (ctx->A.ofs > 0) {
144 aes_gcm_128_ghash_block(ctx, ctx->A.block);
145 ctx->A.ofs = 0;
148 aes_gcm_128_update_tmp(ctx, &ctx->C, c, c_len);
151 static inline void aes_gcm_128_crypt_tmp(struct aes_gcm_128_context *ctx,
152 struct aes_gcm_128_tmp *tmp,
153 uint8_t *m, size_t m_len)
155 tmp->total += m_len;
157 while (m_len > 0) {
158 if (tmp->ofs == AES_BLOCK_SIZE) {
159 aes_gcm_128_inc32(ctx->CB);
160 AES_encrypt(ctx->CB, tmp->block, &ctx->aes_key);
161 tmp->ofs = 0;
164 if (likely(tmp->ofs == 0 && m_len >= AES_BLOCK_SIZE)) {
165 aes_block_xor(m, tmp->block, m);
166 m += AES_BLOCK_SIZE;
167 m_len -= AES_BLOCK_SIZE;
168 aes_gcm_128_inc32(ctx->CB);
169 AES_encrypt(ctx->CB, tmp->block, &ctx->aes_key);
170 continue;
173 m[0] ^= tmp->block[tmp->ofs];
174 m += 1;
175 m_len -= 1;
176 tmp->ofs += 1;
180 void aes_gcm_128_crypt(struct aes_gcm_128_context *ctx,
181 uint8_t *m, size_t m_len)
183 aes_gcm_128_crypt_tmp(ctx, &ctx->c, m, m_len);
186 void aes_gcm_128_digest(struct aes_gcm_128_context *ctx,
187 uint8_t T[AES_BLOCK_SIZE])
189 if (ctx->A.ofs > 0) {
190 aes_gcm_128_ghash_block(ctx, ctx->A.block);
191 ctx->A.ofs = 0;
194 if (ctx->C.ofs > 0) {
195 aes_gcm_128_ghash_block(ctx, ctx->C.block);
196 ctx->C.ofs = 0;
199 RSBVAL(ctx->AC, 0, ctx->A.total * 8);
200 RSBVAL(ctx->AC, 8, ctx->C.total * 8);
201 aes_gcm_128_ghash_block(ctx, ctx->AC);
203 AES_encrypt(ctx->J0, ctx->c.block, &ctx->aes_key);
204 aes_block_xor(ctx->c.block, ctx->Y, T);
206 ZERO_STRUCTP(ctx);