Arduino Cryptography Library
GCM.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "GCM.h"
24 #include "Crypto.h"
25 #include "utility/EndianUtil.h"
26 #include <string.h>
27 
45  : blockCipher(0)
46 {
47  state.authSize = 0;
48  state.dataSize = 0;
49  state.dataStarted = false;
50  state.posn = 16;
51 }
52 
57 {
58  clean(state);
59 }
60 
61 size_t GCMCommon::keySize() const
62 {
63  return blockCipher->keySize();
64 }
65 
66 size_t GCMCommon::ivSize() const
67 {
68  // The GCM specification recommends an IV size of 96 bits.
69  return 12;
70 }
71 
72 size_t GCMCommon::tagSize() const
73 {
74  return 16;
75 }
76 
77 bool GCMCommon::setKey(const uint8_t *key, size_t len)
78 {
79  // Set the encryption key for the block cipher.
80  return blockCipher->setKey(key, len);
81 }
82 
83 bool GCMCommon::setIV(const uint8_t *iv, size_t len)
84 {
85  // Format the counter block from the IV.
86  if (len == 12) {
87  // IV's of exactly 96 bits are used directly as the counter block.
88  memcpy(state.counter, iv, 12);
89  state.counter[12] = 0;
90  state.counter[13] = 0;
91  state.counter[14] = 0;
92  state.counter[15] = 1;
93  } else {
94  // IV's of other sizes are hashed to produce the counter block.
95  memset(state.nonce, 0, 16);
96  blockCipher->encryptBlock(state.nonce, state.nonce);
97  ghash.reset(state.nonce);
98  ghash.update(iv, len);
99  ghash.pad();
100  uint64_t sizes[2] = {0, htobe64(((uint64_t)len) * 8)};
101  ghash.update(sizes, sizeof(sizes));
102  clean(sizes);
103  ghash.finalize(state.counter, 16);
104  }
105 
106  // Reset the GCM object ready to process auth or payload data.
107  state.authSize = 0;
108  state.dataSize = 0;
109  state.dataStarted = false;
110  state.posn = 16;
111 
112  // Construct the hashing key by encrypting a zero block.
113  memset(state.nonce, 0, 16);
114  blockCipher->encryptBlock(state.nonce, state.nonce);
115  ghash.reset(state.nonce);
116 
117  // Replace the hash key in "nonce" with the encrypted counter.
118  // This value will be XOR'ed with the final authentication hash
119  // value in computeTag().
120  blockCipher->encryptBlock(state.nonce, state.counter);
121  return true;
122 }
123 
129 static inline void increment(uint8_t counter[16])
130 {
131  uint16_t carry = 1;
132  carry += counter[15];
133  counter[15] = (uint8_t)carry;
134  carry = (carry >> 8) + counter[14];
135  counter[14] = (uint8_t)carry;
136  carry = (carry >> 8) + counter[13];
137  counter[13] = (uint8_t)carry;
138  carry = (carry >> 8) + counter[12];
139  counter[12] = (uint8_t)carry;
140 }
141 
142 void GCMCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len)
143 {
144  // Finalize the authenticated data if necessary.
145  if (!state.dataStarted) {
146  ghash.pad();
147  state.dataStarted = true;
148  }
149 
150  // Encrypt the plaintext using the block cipher in counter mode.
151  uint8_t *out = output;
152  size_t size = len;
153  while (size > 0) {
154  // Create a new keystream block if necessary.
155  if (state.posn >= 16) {
156  increment(state.counter);
157  blockCipher->encryptBlock(state.stream, state.counter);
158  state.posn = 0;
159  }
160 
161  // Encrypt as many bytes as we can using the keystream block.
162  uint8_t temp = 16 - state.posn;
163  if (temp > size)
164  temp = size;
165  uint8_t *stream = state.stream + state.posn;
166  state.posn += temp;
167  size -= temp;
168  while (temp > 0) {
169  *out++ = *input++ ^ *stream++;
170  --temp;
171  }
172  }
173 
174  // Feed the ciphertext into the hash.
175  ghash.update(output, len);
176  state.dataSize += len;
177 }
178 
179 void GCMCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len)
180 {
181  // Finalize the authenticated data if necessary.
182  if (!state.dataStarted) {
183  ghash.pad();
184  state.dataStarted = true;
185  }
186 
187  // Feed the ciphertext into the hash before we decrypt it.
188  ghash.update(input, len);
189  state.dataSize += len;
190 
191  // Decrypt the plaintext using the block cipher in counter mode.
192  while (len > 0) {
193  // Create a new keystream block if necessary.
194  if (state.posn >= 16) {
195  increment(state.counter);
196  blockCipher->encryptBlock(state.stream, state.counter);
197  state.posn = 0;
198  }
199 
200  // Decrypt as many bytes as we can using the keystream block.
201  uint8_t temp = 16 - state.posn;
202  if (temp > len)
203  temp = len;
204  uint8_t *stream = state.stream + state.posn;
205  state.posn += temp;
206  len -= temp;
207  while (temp > 0) {
208  *output++ = *input++ ^ *stream++;
209  --temp;
210  }
211  }
212 }
213 
214 void GCMCommon::addAuthData(const void *data, size_t len)
215 {
216  if (!state.dataStarted) {
217  ghash.update(data, len);
218  state.authSize += len;
219  }
220 }
221 
222 void GCMCommon::computeTag(void *tag, size_t len)
223 {
224  // Pad the hashed data and add the sizes.
225  ghash.pad();
226  uint64_t sizes[2] = {
227  htobe64(state.authSize * 8),
228  htobe64(state.dataSize * 8)
229  };
230  ghash.update(sizes, sizeof(sizes));
231  clean(sizes);
232 
233  // Get the finalized hash, encrypt it with the nonce, and return the tag.
234  ghash.finalize(state.stream, 16);
235  for (uint8_t posn = 0; posn < 16; ++posn)
236  state.stream[posn] ^= state.nonce[posn];
237  if (len > 16)
238  len = 16;
239  memcpy(tag, state.stream, len);
240 }
241 
242 bool GCMCommon::checkTag(const void *tag, size_t len)
243 {
244  // Can never match if the expected tag length is too long.
245  if (len > 16)
246  return false;
247 
248  // Compute the tag and check it.
249  computeTag(state.counter, 16);
250  return secure_compare(state.counter, tag, len);
251 }
252 
254 {
255  blockCipher->clear();
256  ghash.clear();
257  clean(state);
258  state.posn = 16;
259 }
260 
virtual void clear()=0
Clears all security-sensitive state from this block cipher.
virtual bool setKey(const uint8_t *key, size_t len)=0
Sets the key to use for future encryption and decryption operations.
virtual void encryptBlock(uint8_t *output, const uint8_t *input)=0
Encrypts a single block using this cipher.
virtual size_t keySize() const =0
Default size of the key for this block cipher, in bytes.
void encrypt(uint8_t *output, const uint8_t *input, size_t len)
Encrypts an input buffer and writes the ciphertext to an output buffer.
Definition: GCM.cpp:142
void clear()
Clears all security-sensitive state from this cipher.
Definition: GCM.cpp:253
virtual ~GCMCommon()
Destroys this cipher object after clearing sensitive information.
Definition: GCM.cpp:56
size_t keySize() const
Default size of the key for this cipher, in bytes.
Definition: GCM.cpp:61
GCMCommon()
Constructs a new cipher in GCM mode.
Definition: GCM.cpp:44
bool setIV(const uint8_t *iv, size_t len)
Sets the initialization vector to use for future encryption and decryption operations.
Definition: GCM.cpp:83
size_t ivSize() const
Size of the initialization vector for this cipher, in bytes.
Definition: GCM.cpp:66
size_t tagSize() const
Returns the size of the authentication tag.
Definition: GCM.cpp:72
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: GCM.cpp:77
void computeTag(void *tag, size_t len)
Finalizes the encryption process and computes the authentication tag.
Definition: GCM.cpp:222
void decrypt(uint8_t *output, const uint8_t *input, size_t len)
Decrypts an input buffer and writes the plaintext to an output buffer.
Definition: GCM.cpp:179
bool checkTag(const void *tag, size_t len)
Finalizes the decryption process and checks the authentication tag.
Definition: GCM.cpp:242
void addAuthData(const void *data, size_t len)
Adds extra data that will be authenticated but not encrypted.
Definition: GCM.cpp:214
void update(const void *data, size_t len)
Updates the message authenticator with more data.
Definition: GHASH.cpp:85
void reset(const void *key)
Resets the GHASH message authenticator for a new session.
Definition: GHASH.cpp:67
void clear()
Clears the authenticator's state, removing all sensitive data.
Definition: GHASH.cpp:150
void pad()
Pads the input stream with zero bytes to a multiple of 16.
Definition: GHASH.cpp:137
void finalize(void *token, size_t len)
Finalizes the authentication process and returns the token.
Definition: GHASH.cpp:121