5 Copyright (C) 2005 Niels Möller
7 This file is part of GNU Nettle.
9 GNU Nettle is free software: you can redistribute it and/or
10 modify it under the terms of either:
12 * the GNU Lesser General Public License as published by the Free
13 Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
18 * the GNU General Public License as published by the Free
19 Software Foundation; either version 2 of the License, or (at your
20 option) any later version.
22 or both in parallel, as here.
24 GNU Nettle is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 General Public License for more details.
29 You should have received copies of the GNU General Public License and
30 the GNU Lesser General Public License along with this program. If
31 not, see http://www.gnu.org/licenses/.
44 #include "ctr-internal.h"
47 #include "nettle-internal.h"
49 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
52 ctr_fill (size_t block_size, uint8_t *ctr, size_t length, uint8_t *buffer)
55 for (i = 0; i + block_size <= length; i += block_size)
57 memcpy (buffer + i, ctr, block_size);
58 INCREMENT(block_size, ctr);
64 # define USE_CTR_CRYPT16 1
65 static nettle_fill16_func ctr_fill16;
67 ctr_fill16(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer)
71 hi = READ_UINT64(ctr);
72 lo = READ_UINT64(ctr + 8);
74 for (i = 0; i < blocks; i++)
76 buffer[i].u64[0] = hi;
77 buffer[i].u64[1] = lo;
80 WRITE_UINT64(ctr, hi);
81 WRITE_UINT64(ctr + 8, lo);
83 #else /* !WORDS_BIGENDIAN */
84 # if HAVE_BUILTIN_BSWAP64
85 # define USE_CTR_CRYPT16 1
86 static nettle_fill16_func ctr_fill16;
88 ctr_fill16(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer)
92 /* Read hi in native endianness */
93 hi = LE_READ_UINT64(ctr);
94 lo = READ_UINT64(ctr + 8);
96 for (i = 0; i < blocks; i++)
98 buffer[i].u64[0] = hi;
99 buffer[i].u64[1] = __builtin_bswap64(lo);
101 hi = __builtin_bswap64(__builtin_bswap64(hi) + 1);
103 LE_WRITE_UINT64(ctr, hi);
104 WRITE_UINT64(ctr + 8, lo);
106 # else /* ! HAVE_BUILTIN_BSWAP64 */
107 # define USE_CTR_CRYPT16 0
109 #endif /* !WORDS_BIGENDIAN */
112 ctr_crypt(const void *ctx, nettle_cipher_func *f,
113 size_t block_size, uint8_t *ctr,
114 size_t length, uint8_t *dst,
118 if (block_size == 16)
120 _ctr_crypt16(ctx, f, ctr_fill16, ctr, length, dst, src);
127 size_t filled = ctr_fill (block_size, ctr, length, dst);
129 f(ctx, filled, dst, dst);
130 memxor(dst, src, filled);
134 TMP_DECL(block, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
135 TMP_ALLOC(block, block_size);
137 f(ctx, block_size, block, ctr);
138 INCREMENT(block_size, ctr);
139 memxor3(dst + filled, src + filled, block, length - filled);
144 /* For in-place CTR, construct a buffer of consecutive counter
145 values, of size at most CTR_BUFFER_LIMIT. */
146 TMP_DECL(buffer, uint8_t, CTR_BUFFER_LIMIT);
149 if (length < block_size)
150 buffer_size = block_size;
151 else if (length <= CTR_BUFFER_LIMIT)
152 buffer_size = length;
154 buffer_size = CTR_BUFFER_LIMIT;
156 TMP_ALLOC(buffer, buffer_size);
158 while (length >= block_size)
161 = ctr_fill (block_size, ctr, MIN(buffer_size, length), buffer);
163 f(ctx, filled, buffer, buffer);
164 memxor(dst, buffer, filled);
169 /* Final, possibly partial, block. */
172 f(ctx, block_size, buffer, ctr);
173 INCREMENT(block_size, ctr);
174 memxor(dst, buffer, length);