]>
Commit | Line | Data |
---|---|---|
018d8bcd | 1 | /* gcm.c |
90112edb NM |
2 | |
3 | Galois counter mode, specified by NIST, | |
4 | http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf | |
5 | ||
6 | See also the gcm paper at | |
7 | http://www.cryptobarn.com/papers/gcm-spec.pdf. | |
8 | ||
90112edb | 9 | Copyright (C) 2011 Katholieke Universiteit Leuven |
4ff20685 NM |
10 | Copyright (C) 2011, 2013, 2018 Niels Möller |
11 | Copyright (C) 2018 Red Hat, Inc. | |
90112edb NM |
12 | |
13 | Contributed by Nikos Mavrogiannopoulos | |
14 | ||
15 | This file is part of GNU Nettle. | |
16 | ||
17 | GNU Nettle is free software: you can redistribute it and/or | |
18 | modify it under the terms of either: | |
19 | ||
20 | * the GNU Lesser General Public License as published by the Free | |
21 | Software Foundation; either version 3 of the License, or (at your | |
22 | option) any later version. | |
23 | ||
24 | or | |
25 | ||
26 | * the GNU General Public License as published by the Free | |
27 | Software Foundation; either version 2 of the License, or (at your | |
28 | option) any later version. | |
29 | ||
30 | or both in parallel, as here. | |
31 | ||
32 | GNU Nettle is distributed in the hope that it will be useful, | |
33 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
35 | General Public License for more details. | |
36 | ||
37 | You should have received copies of the GNU General Public License and | |
38 | the GNU Lesser General Public License along with this program. If | |
39 | not, see http://www.gnu.org/licenses/. | |
40 | */ | |
342ad32a NM |
41 | |
42 | #if HAVE_CONFIG_H | |
43 | # include "config.h" | |
44 | #endif | |
45 | ||
46 | #include <assert.h> | |
47 | #include <stdlib.h> | |
48 | #include <string.h> | |
49 | ||
50 | #include "gcm.h" | |
51 | ||
1d438ad4 | 52 | #include "ghash-internal.h" |
342ad32a NM |
53 | #include "memxor.h" |
54 | #include "nettle-internal.h" | |
55 | #include "macros.h" | |
4ff20685 | 56 | #include "ctr-internal.h" |
508908b1 | 57 | #include "block-internal.h" |
ff660604 | 58 | #include "bswap-internal.h" |
23f75f58 | 59 | |
342ad32a NM |
60 | /* Initialization of GCM. |
61 | * @ctx: The context of GCM | |
62 | * @cipher: The context of the underlying block cipher | |
63 | * @f: The underlying cipher encryption function | |
64 | */ | |
65 | void | |
5f07c78b | 66 | gcm_set_key(struct gcm_key *key, |
a9b47a42 | 67 | const void *cipher, nettle_cipher_func *f) |
342ad32a | 68 | { |
23f75f58 NM |
69 | static const union nettle_block16 zero_block; |
70 | union nettle_block16 key_block; | |
71 | f (cipher, GCM_BLOCK_SIZE, key_block.b, zero_block.b); | |
56691ae4 | 72 | |
1d438ad4 | 73 | _ghash_set_key (key, &key_block); |
342ad32a NM |
74 | } |
75 | ||
1d438ad4 NM |
76 | /* Call _ghash_update, with zero padding of any partial final block. */ |
77 | static void | |
78 | gcm_hash (const struct gcm_key *key, union nettle_block16 *x, | |
79 | size_t length, const uint8_t *data) { | |
80 | data = _ghash_update (key, x, length / GCM_BLOCK_SIZE, data); | |
81 | length &= (GCM_BLOCK_SIZE - 1); | |
342ad32a NM |
82 | if (length > 0) |
83 | { | |
1d438ad4 NM |
84 | union nettle_block16 block; |
85 | block16_zero (&block); | |
86 | memcpy (block.b, data, length); | |
87 | _ghash_update (key, x, 1, block.b); | |
342ad32a NM |
88 | } |
89 | } | |
90 | ||
9924966a | 91 | static void |
61d9a6a0 | 92 | gcm_hash_sizes(const struct gcm_key *key, union nettle_block16 *x, |
890b2365 | 93 | uint64_t auth_size, uint64_t data_size) |
9924966a | 94 | { |
1d438ad4 | 95 | union nettle_block16 buffer; |
9924966a NM |
96 | |
97 | data_size *= 8; | |
98 | auth_size *= 8; | |
99 | ||
ff660604 NM |
100 | buffer.u64[0] = bswap64_if_le (auth_size); |
101 | buffer.u64[1] = bswap64_if_le (data_size); | |
9924966a | 102 | |
1d438ad4 | 103 | _ghash_update (key, x, 1, buffer.b); |
9924966a NM |
104 | } |
105 | ||
187631fa | 106 | /* NOTE: The key is needed only if length != GCM_IV_SIZE */ |
9924966a NM |
107 | void |
108 | gcm_set_iv(struct gcm_ctx *ctx, const struct gcm_key *key, | |
3eb603d0 | 109 | size_t length, const uint8_t *iv) |
9924966a NM |
110 | { |
111 | if (length == GCM_IV_SIZE) | |
112 | { | |
113 | memcpy (ctx->iv.b, iv, GCM_BLOCK_SIZE - 4); | |
114 | ctx->iv.b[GCM_BLOCK_SIZE - 4] = 0; | |
115 | ctx->iv.b[GCM_BLOCK_SIZE - 3] = 0; | |
116 | ctx->iv.b[GCM_BLOCK_SIZE - 2] = 0; | |
117 | ctx->iv.b[GCM_BLOCK_SIZE - 1] = 1; | |
118 | } | |
119 | else | |
120 | { | |
1d438ad4 NM |
121 | block16_zero(&ctx->iv); |
122 | gcm_hash(key, &ctx->iv, length, iv); | |
9924966a NM |
123 | gcm_hash_sizes(key, &ctx->iv, 0, length); |
124 | } | |
125 | ||
1d438ad4 NM |
126 | ctx->ctr = ctx->iv; |
127 | /* Increment the rightmost 32 bits. */ | |
128 | INCREMENT (4, ctx->ctr.b + GCM_BLOCK_SIZE - 4); | |
9924966a NM |
129 | |
130 | /* Reset the rest of the message-dependent state. */ | |
1d438ad4 | 131 | block16_zero(&ctx->x); |
9924966a NM |
132 | ctx->auth_size = ctx->data_size = 0; |
133 | } | |
134 | ||
342ad32a | 135 | void |
4961af0a | 136 | gcm_update(struct gcm_ctx *ctx, const struct gcm_key *key, |
b8bfc32f | 137 | size_t length, const uint8_t *data) |
342ad32a NM |
138 | { |
139 | assert(ctx->auth_size % GCM_BLOCK_SIZE == 0); | |
4961af0a | 140 | assert(ctx->data_size == 0); |
342ad32a | 141 | |
1d438ad4 | 142 | gcm_hash(key, &ctx->x, length, data); |
342ad32a NM |
143 | |
144 | ctx->auth_size += length; | |
145 | } | |
146 | ||
4ff20685 | 147 | static nettle_fill16_func gcm_fill; |
b62e5f5e NM |
148 | #if WORDS_BIGENDIAN |
149 | static void | |
150 | gcm_fill(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer) | |
151 | { | |
152 | uint64_t hi, mid; | |
153 | uint32_t lo; | |
154 | size_t i; | |
155 | hi = READ_UINT64(ctr); | |
156 | mid = (uint64_t) READ_UINT32(ctr + 8) << 32; | |
157 | lo = READ_UINT32(ctr + 12); | |
158 | ||
159 | for (i = 0; i < blocks; i++) | |
160 | { | |
161 | buffer[i].u64[0] = hi; | |
162 | buffer[i].u64[1] = mid + lo++; | |
163 | } | |
164 | WRITE_UINT32(ctr + 12, lo); | |
165 | ||
166 | } | |
167 | #elif HAVE_BUILTIN_BSWAP64 | |
168 | /* Assume __builtin_bswap32 is also available */ | |
169 | static void | |
170 | gcm_fill(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer) | |
171 | { | |
172 | uint64_t hi, mid; | |
173 | uint32_t lo; | |
174 | size_t i; | |
175 | hi = LE_READ_UINT64(ctr); | |
176 | mid = LE_READ_UINT32(ctr + 8); | |
177 | lo = READ_UINT32(ctr + 12); | |
178 | ||
179 | for (i = 0; i < blocks; i++) | |
180 | { | |
181 | buffer[i].u64[0] = hi; | |
182 | buffer[i].u64[1] = mid + ((uint64_t)__builtin_bswap32(lo) << 32); | |
183 | lo++; | |
184 | } | |
185 | WRITE_UINT32(ctr + 12, lo); | |
186 | } | |
187 | #else | |
342ad32a | 188 | static void |
4ff20685 | 189 | gcm_fill(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer) |
342ad32a | 190 | { |
4ff20685 | 191 | uint32_t c; |
342ad32a | 192 | |
4ff20685 NM |
193 | c = READ_UINT32(ctr + GCM_BLOCK_SIZE - 4); |
194 | ||
195 | for (; blocks-- > 0; buffer++, c++) | |
342ad32a | 196 | { |
4ff20685 NM |
197 | memcpy(buffer->b, ctr, GCM_BLOCK_SIZE - 4); |
198 | WRITE_UINT32(buffer->b + GCM_BLOCK_SIZE - 4, c); | |
342ad32a | 199 | } |
4ff20685 NM |
200 | |
201 | WRITE_UINT32(ctr + GCM_BLOCK_SIZE - 4, c); | |
342ad32a | 202 | } |
b62e5f5e | 203 | #endif |
342ad32a NM |
204 | |
205 | void | |
5f07c78b | 206 | gcm_encrypt (struct gcm_ctx *ctx, const struct gcm_key *key, |
a9b47a42 | 207 | const void *cipher, nettle_cipher_func *f, |
3eb603d0 | 208 | size_t length, uint8_t *dst, const uint8_t *src) |
342ad32a NM |
209 | { |
210 | assert(ctx->data_size % GCM_BLOCK_SIZE == 0); | |
211 | ||
5ebf7703 | 212 | _nettle_ctr_crypt16(cipher, f, gcm_fill, ctx->ctr.b, length, dst, src); |
1d438ad4 | 213 | gcm_hash(key, &ctx->x, length, dst); |
342ad32a NM |
214 | |
215 | ctx->data_size += length; | |
216 | } | |
217 | ||
218 | void | |
5f07c78b | 219 | gcm_decrypt(struct gcm_ctx *ctx, const struct gcm_key *key, |
a9b47a42 | 220 | const void *cipher, nettle_cipher_func *f, |
3eb603d0 | 221 | size_t length, uint8_t *dst, const uint8_t *src) |
342ad32a NM |
222 | { |
223 | assert(ctx->data_size % GCM_BLOCK_SIZE == 0); | |
224 | ||
1d438ad4 | 225 | gcm_hash(key, &ctx->x, length, src); |
5ebf7703 | 226 | _nettle_ctr_crypt16(cipher, f, gcm_fill, ctx->ctr.b, length, dst, src); |
342ad32a NM |
227 | |
228 | ctx->data_size += length; | |
229 | } | |
230 | ||
231 | void | |
5f07c78b | 232 | gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key, |
a9b47a42 | 233 | const void *cipher, nettle_cipher_func *f, |
b8bfc32f | 234 | size_t length, uint8_t *digest) |
342ad32a | 235 | { |
1d438ad4 | 236 | union nettle_block16 buffer; |
342ad32a NM |
237 | |
238 | assert (length <= GCM_BLOCK_SIZE); | |
239 | ||
9924966a | 240 | gcm_hash_sizes(key, &ctx->x, ctx->auth_size, ctx->data_size); |
342ad32a | 241 | |
1d438ad4 | 242 | f (cipher, GCM_BLOCK_SIZE, buffer.b, ctx->iv.b); |
d382fcc0 | 243 | block16_xor (&buffer, &ctx->x); |
1d438ad4 | 244 | memcpy (digest, buffer.b, length); |
342ad32a NM |
245 | |
246 | return; | |
247 | } |