forked from rweather/arduinolibs
-
Notifications
You must be signed in to change notification settings - Fork 4
/
CTR.cpp
220 lines (203 loc) · 6.65 KB
/
CTR.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
* Copyright (C) 2015 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "CTR.h"
#include "Crypto.h"
#include <string.h>
/**
* \class CTRCommon CTR.h <CTR.h>
* \brief Concrete base class to assist with implementing CTR mode for
* 128-bit block ciphers.
*
* Reference: http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
*
* \sa CTR
*/
/**
* \brief Constructs a new cipher in CTR mode.
*
* This constructor should be followed by a call to setBlockCipher().
*/
CTRCommon::CTRCommon()
: blockCipher(0)
, posn(16)
, counterStart(0)
{
}
CTRCommon::~CTRCommon()
{
// It is assumed that the subclass will clear sensitive
// information in the block cipher.
clean(counter);
clean(state);
}
size_t CTRCommon::keySize() const
{
return blockCipher->keySize();
}
size_t CTRCommon::ivSize() const
{
return 16;
}
/**
* \brief Sets the counter size for the IV.
*
* \param size The number of bytes on the end of the counter block
* that are relevant when incrementing, between 1 and 16.
* \return Returns false if the \a size value is not between 1 and 16.
*
* When the counter is incremented during encrypt(), only the last
* \a size bytes are considered relevant. This can be useful
* to improve performance when the higher level protocol specifies that
* only the least significant N bytes "count". The high level protocol
* should explicitly generate a new initial counter value and key long
* before the \a size bytes overflow and wrap around.
*
* By default, the counter size is 16 which is the same as the block size
* of the underlying block cipher.
*
* \sa setIV()
*/
bool CTRCommon::setCounterSize(size_t size)
{
if (size < 1 || size > 16)
return false;
counterStart = 16 - size;
return true;
}
bool CTRCommon::setKey(const uint8_t *key, size_t len)
{
// Verify the cipher's block size, just in case.
if (blockCipher->blockSize() != 16)
return false;
// Set the key on the underlying block cipher.
return blockCipher->setKey(key, len);
}
/**
* \brief Sets the initial counter value to use for future encryption and
* decryption operations.
*
* \param iv The initial counter value which must contain exactly 16 bytes.
* \param len The length of the counter value, which mut be 16.
* \return Returns false if \a len is not exactly 16.
*
* The precise method to generate the initial counter is not defined by
* this class. Usually higher level protocols like SSL/TLS and SSH
* specify how to construct the initial counter value. This class merely
* increments the counter every time a new block of keystream data is needed.
*
* \sa encrypt(), setCounterSize()
*/
bool CTRCommon::setIV(const uint8_t *iv, size_t len)
{
if (len != 16)
return false;
memcpy(counter, iv, len);
posn = 16;
return true;
}
void CTRCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len)
{
while (len > 0) {
if (posn >= 16) {
// Generate a new encrypted counter block.
blockCipher->encryptBlock(state, counter);
posn = 0;
// Increment the counter, taking care not to reveal
// any timing information about the starting value.
// We iterate through the entire counter region even
// if we could stop earlier because a byte is non-zero.
uint16_t temp = 1;
uint8_t index = 16;
while (index > counterStart) {
--index;
temp += counter[index];
counter[index] = (uint8_t)temp;
temp >>= 8;
}
}
uint8_t templen = 16 - posn;
if (templen > len)
templen = len;
len -= templen;
while (templen > 0) {
*output++ = *input++ ^ state[posn++];
--templen;
}
}
}
void CTRCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len)
{
encrypt(output, input, len);
}
void CTRCommon::clear()
{
blockCipher->clear();
clean(counter);
clean(state);
posn = 16;
}
/**
* \fn void CTRCommon::setBlockCipher(BlockCipher *cipher)
* \brief Sets the block cipher to use for this CTR object.
*
* \param cipher The block cipher to use to implement CTR mode,
* which must have a block size of 16 bytes (128 bits).
*
* \note This class only works with block ciphers whose block size is
* 16 bytes (128 bits). If the \a cipher has a different block size,
* then setKey() will fail and return false.
*/
/**
* \class CTR CTR.h <CTR.h>
* \brief Implementation of the Counter (CTR) mode for 128-bit block ciphers.
*
* Counter mode converts a block cipher into a stream cipher. The specific
* block cipher is passed as the template parameter T and the key is
* specified via the setKey() function.
*
* Keystream blocks are generated by encrypting an increasing counter value
* and XOR'ing it with each byte of input. The encrypt() and decrypt()
* operations are identical.
*
* The template parameter T must be a concrete subclass of BlockCipher
* indicating the specific block cipher to use. For example, the following
* creates a CTR object using AES256 as the underlying cipher:
*
* \code
* CTR<AES256> ctr;
* ctr.setKey(key, 32);
* ctr.setIV(iv, 16);
* ctr.setCounterSize(4);
* ctr.encrypt(output, input, len);
* \endcode
*
* In this example, the last 4 bytes of the IV are incremented to count
* blocks. The remaining bytes are left unchanged from block to block.
*
* Reference: http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
*
* \sa CFB, OFB, CBC
*/
/**
* \fn CTR::CTR()
* \brief Constructs a new CTR object for the 128-bit block cipher T.
*/