Line | Count | Source (jump to first uncovered line) |
1 | | /* gcm.c |
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 | | |
9 | | Copyright (C) 2011 Katholieke Universiteit Leuven |
10 | | Copyright (C) 2011, 2013, 2018 Niels Möller |
11 | | Copyright (C) 2018 Red Hat, Inc. |
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 | | */ |
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 | | |
52 | | #include "ghash-internal.h" |
53 | | #include "memxor.h" |
54 | | #include "nettle-internal.h" |
55 | | #include "macros.h" |
56 | | #include "ctr-internal.h" |
57 | | #include "block-internal.h" |
58 | | #include "bswap-internal.h" |
59 | | |
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 |
66 | | gcm_set_key(struct gcm_key *key, |
67 | | const void *cipher, nettle_cipher_func *f) |
68 | 0 | { |
69 | 0 | static const union nettle_block16 zero_block; |
70 | 0 | union nettle_block16 key_block; |
71 | 0 | f (cipher, GCM_BLOCK_SIZE, key_block.b, zero_block.b); |
72 | |
|
73 | 0 | _ghash_set_key (key, &key_block); |
74 | 0 | } |
75 | | |
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 | 0 | size_t length, const uint8_t *data) { |
80 | 0 | data = _ghash_update (key, x, length / GCM_BLOCK_SIZE, data); |
81 | 0 | length &= (GCM_BLOCK_SIZE - 1); |
82 | 0 | if (length > 0) |
83 | 0 | { |
84 | 0 | union nettle_block16 block; |
85 | 0 | block16_zero (&block); |
86 | 0 | memcpy (block.b, data, length); |
87 | 0 | _ghash_update (key, x, 1, block.b); |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | static void |
92 | | gcm_hash_sizes(const struct gcm_key *key, union nettle_block16 *x, |
93 | | uint64_t auth_size, uint64_t data_size) |
94 | 0 | { |
95 | 0 | union nettle_block16 buffer; |
96 | |
|
97 | 0 | data_size *= 8; |
98 | 0 | auth_size *= 8; |
99 | |
|
100 | 0 | buffer.u64[0] = bswap64_if_le (auth_size); |
101 | 0 | buffer.u64[1] = bswap64_if_le (data_size); |
102 | |
|
103 | 0 | _ghash_update (key, x, 1, buffer.b); |
104 | 0 | } |
105 | | |
106 | | /* NOTE: The key is needed only if length != GCM_IV_SIZE */ |
107 | | void |
108 | | gcm_set_iv(struct gcm_ctx *ctx, const struct gcm_key *key, |
109 | | size_t length, const uint8_t *iv) |
110 | 0 | { |
111 | 0 | if (length == GCM_IV_SIZE) |
112 | 0 | { |
113 | 0 | memcpy (ctx->iv.b, iv, GCM_BLOCK_SIZE - 4); |
114 | 0 | ctx->iv.b[GCM_BLOCK_SIZE - 4] = 0; |
115 | 0 | ctx->iv.b[GCM_BLOCK_SIZE - 3] = 0; |
116 | 0 | ctx->iv.b[GCM_BLOCK_SIZE - 2] = 0; |
117 | 0 | ctx->iv.b[GCM_BLOCK_SIZE - 1] = 1; |
118 | 0 | } |
119 | 0 | else |
120 | 0 | { |
121 | 0 | block16_zero(&ctx->iv); |
122 | 0 | gcm_hash(key, &ctx->iv, length, iv); |
123 | 0 | gcm_hash_sizes(key, &ctx->iv, 0, length); |
124 | 0 | } |
125 | |
|
126 | 0 | ctx->ctr = ctx->iv; |
127 | | /* Increment the rightmost 32 bits. */ |
128 | 0 | INCREMENT (4, ctx->ctr.b + GCM_BLOCK_SIZE - 4); |
129 | | |
130 | | /* Reset the rest of the message-dependent state. */ |
131 | 0 | block16_zero(&ctx->x); |
132 | 0 | ctx->auth_size = ctx->data_size = 0; |
133 | 0 | } |
134 | | |
135 | | void |
136 | | gcm_update(struct gcm_ctx *ctx, const struct gcm_key *key, |
137 | | size_t length, const uint8_t *data) |
138 | 0 | { |
139 | 0 | assert(ctx->auth_size % GCM_BLOCK_SIZE == 0); |
140 | 0 | assert(ctx->data_size == 0); |
141 | | |
142 | 0 | gcm_hash(key, &ctx->x, length, data); |
143 | |
|
144 | 0 | ctx->auth_size += length; |
145 | 0 | } |
146 | | |
147 | | static nettle_fill16_func gcm_fill; |
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 | 0 | { |
172 | 0 | uint64_t hi, mid; |
173 | 0 | uint32_t lo; |
174 | 0 | size_t i; |
175 | 0 | hi = LE_READ_UINT64(ctr); |
176 | 0 | mid = LE_READ_UINT32(ctr + 8); |
177 | 0 | lo = READ_UINT32(ctr + 12); |
178 | |
|
179 | 0 | for (i = 0; i < blocks; i++) |
180 | 0 | { |
181 | 0 | buffer[i].u64[0] = hi; |
182 | 0 | buffer[i].u64[1] = mid + ((uint64_t)__builtin_bswap32(lo) << 32); |
183 | 0 | lo++; |
184 | 0 | } |
185 | 0 | WRITE_UINT32(ctr + 12, lo); |
186 | 0 | } |
187 | | #else |
188 | | static void |
189 | | gcm_fill(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer) |
190 | | { |
191 | | uint32_t c; |
192 | | |
193 | | c = READ_UINT32(ctr + GCM_BLOCK_SIZE - 4); |
194 | | |
195 | | for (; blocks-- > 0; buffer++, c++) |
196 | | { |
197 | | memcpy(buffer->b, ctr, GCM_BLOCK_SIZE - 4); |
198 | | WRITE_UINT32(buffer->b + GCM_BLOCK_SIZE - 4, c); |
199 | | } |
200 | | |
201 | | WRITE_UINT32(ctr + GCM_BLOCK_SIZE - 4, c); |
202 | | } |
203 | | #endif |
204 | | |
205 | | void |
206 | | gcm_encrypt (struct gcm_ctx *ctx, const struct gcm_key *key, |
207 | | const void *cipher, nettle_cipher_func *f, |
208 | | size_t length, uint8_t *dst, const uint8_t *src) |
209 | 0 | { |
210 | 0 | assert(ctx->data_size % GCM_BLOCK_SIZE == 0); |
211 | | |
212 | 0 | _nettle_ctr_crypt16(cipher, f, gcm_fill, ctx->ctr.b, length, dst, src); |
213 | 0 | gcm_hash(key, &ctx->x, length, dst); |
214 | |
|
215 | 0 | ctx->data_size += length; |
216 | 0 | } |
217 | | |
218 | | void |
219 | | gcm_decrypt(struct gcm_ctx *ctx, const struct gcm_key *key, |
220 | | const void *cipher, nettle_cipher_func *f, |
221 | | size_t length, uint8_t *dst, const uint8_t *src) |
222 | 0 | { |
223 | 0 | assert(ctx->data_size % GCM_BLOCK_SIZE == 0); |
224 | | |
225 | 0 | gcm_hash(key, &ctx->x, length, src); |
226 | 0 | _nettle_ctr_crypt16(cipher, f, gcm_fill, ctx->ctr.b, length, dst, src); |
227 | |
|
228 | 0 | ctx->data_size += length; |
229 | 0 | } |
230 | | |
231 | | void |
232 | | gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key, |
233 | | const void *cipher, nettle_cipher_func *f, |
234 | | size_t length, uint8_t *digest) |
235 | 0 | { |
236 | 0 | union nettle_block16 buffer; |
237 | |
|
238 | 0 | assert (length <= GCM_BLOCK_SIZE); |
239 | | |
240 | 0 | gcm_hash_sizes(key, &ctx->x, ctx->auth_size, ctx->data_size); |
241 | |
|
242 | 0 | f (cipher, GCM_BLOCK_SIZE, buffer.b, ctx->iv.b); |
243 | 0 | block16_xor (&buffer, &ctx->x); |
244 | 0 | memcpy (digest, buffer.b, length); |
245 | |
|
246 | 0 | return; |
247 | 0 | } |