siv.c
Go to the documentation of this file.
1 /**
2  * @file siv.c
3  * @brief Synthetic Initialization Vector (SIV)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * SIV (Synthetic Initialization Vector) is an authenticated encryption
30  * algorithm designed to provide nonce misuse resistance. Refer to RFC 5297
31  * for more details
32  *
33  * @author Oryx Embedded SARL (www.oryx-embedded.com)
34  * @version 2.4.4
35  **/
36 
37 //Switch to the appropriate trace level
38 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
39 
40 //Dependencies
41 #include "core/crypto.h"
42 #include "aead/siv.h"
43 #include "mac/cmac.h"
44 #include "cipher_modes/ctr.h"
45 #include "debug.h"
46 
47 //Check crypto library configuration
48 #if (SIV_SUPPORT == ENABLED)
49 
50 
51 /**
52  * @brief Authenticated encryption using SIV
53  * @param[in] cipher Cipher algorithm
54  * @param[in] k Pointer to the secret key
55  * @param[in] kLen Length of the secret key
56  * @param[in] ad Vector of associated data
57  * @param[in] adLen Number of components in the vector of associated data
58  * @param[in] p Plaintext to be encrypted
59  * @param[out] c Ciphertext resulting from the encryption
60  * @param[in] length Total number of data bytes to be encrypted
61  * @param[out] v Synthetic IV (16 bytes)
62  * @return Error code
63  **/
64 
65 error_t sivEncrypt(const CipherAlgo *cipher, const uint8_t *k, size_t kLen,
66  const DataChunk *ad, uint_t adLen, const uint8_t *p, uint8_t *c,
67  size_t length, uint8_t *v)
68 {
69  const uint8_t *k1;
70  const uint8_t *k2;
71  uint8_t q[16];
72  CipherContext cipherContext;
73 
74  //Check parameters
75  if(cipher == NULL || k == NULL)
77 
78  //SIV supports only symmetric block ciphers whose block size is 128 bits
79  if(cipher->type != CIPHER_ALGO_TYPE_BLOCK || cipher->blockSize != 16)
81 
82  //SIV takes as input a key K of length 256, 384, or 512 bits
83  if(kLen != 32 && kLen != 48 && kLen != 64)
85 
86  //The number of components in the vector is not greater than 126 (refer to
87  //RFC 5297, section 2.6)
88  if(adLen > 126)
90 
91  //The key is split into equal halves. K1 is used for S2V and K2 is used
92  //for CTR
93  kLen /= 2;
94  k1 = k;
95  k2 = k + kLen;
96 
97  //Compute V = S2V(K1, AD, P)
98  s2v(cipher, k1, kLen, ad, adLen, p, length, v);
99 
100  //The output of S2V is a synthetic IV that represents the initial counter
101  //to CTR
102  osMemcpy(q, v, 16);
103 
104  //The 31st and 63rd bit (where the rightmost bit is the 0th) of the counter
105  //are zeroed out just prior to being used by CTR for optimization purposes
106  q[8] &= 0x7F;
107  q[12] &= 0x7F;
108 
109  //K2 is used for CTR
110  cipher->init(&cipherContext, k2, kLen);
111  //Encrypt plaintext
112  ctrEncrypt(cipher, &cipherContext, 128, q, p, c, length);
113 
114  //Successful processing
115  return NO_ERROR;
116 }
117 
118 
119 /**
120  * @brief Authenticated decryption using SIV
121  * @param[in] cipher Cipher algorithm
122  * @param[in] k Pointer to the secret key
123  * @param[in] kLen Length of the secret key
124  * @param[in] ad Vector of associated data
125  * @param[in] adLen Number of components in the vector of associated data
126  * @param[in] c Ciphertext to be decrypted
127  * @param[out] p Plaintext resulting from the decryption
128  * @param[in] length Total number of data bytes to be decrypted
129  * @param[in] v Synthetic IV (16 bytes)
130  * @return Error code
131  **/
132 
133 error_t sivDecrypt(const CipherAlgo *cipher, const uint8_t *k, size_t kLen,
134  const DataChunk *ad, uint_t adLen, const uint8_t *c, uint8_t *p,
135  size_t length, const uint8_t *v)
136 {
137  size_t i;
138  uint8_t mask;
139  const uint8_t *k1;
140  const uint8_t *k2;
141  uint8_t q[16];
142  uint8_t t[16];
143  CipherContext cipherContext;
144 
145  //Check parameters
146  if(cipher == NULL || k == NULL)
148 
149  //SIV supports only symmetric block ciphers whose block size is 128 bits
150  if(cipher->type != CIPHER_ALGO_TYPE_BLOCK || cipher->blockSize != 16)
152 
153  //SIV takes as input a key K of length 256, 384, or 512 bits
154  if(kLen != 32 && kLen != 48 && kLen != 64)
156 
157  //The number of components in the vector is not greater than 126 (refer to
158  //RFC 5297, section 2.7)
159  if(adLen > 126)
161 
162  //The key is split into equal halves. K1 is used for S2V and K2 is used
163  //for CTR
164  kLen /= 2;
165  k1 = k;
166  k2 = k + kLen;
167 
168  //the synthetic IV that represents the initial counter to CTR
169  osMemcpy(q, v, 16);
170 
171  //The 31st and 63rd bit (where the rightmost bit is the 0th) of the counter
172  //are zeroed out just prior to being used by CTR for optimization purposes
173  q[8] &= 0x7F;
174  q[12] &= 0x7F;
175 
176  //K2 is used for CTR
177  cipher->init(&cipherContext, k2, kLen);
178  //Decrypt ciphertext
179  ctrDecrypt(cipher, &cipherContext, 128, q, c, p, length);
180 
181  //T = S2V(K1, AD1, ..., ADn, P)
182  s2v(cipher, k1, kLen, ad, adLen, p, length, t);
183 
184  //The calculated syntetic IV is bitwise compared to the received IV. The
185  //message is authenticated if and only if the IVs match
186  for(mask = 0, i = 0; i < 16; i++)
187  {
188  mask |= t[i] ^ v[i];
189  }
190 
191  //Return status code
192  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
193 }
194 
195 
196 /**
197  * @brief S2V operation
198  * @param[in] cipher Cipher algorithm
199  * @param[in] key Pointer to the S2V key
200  * @param[in] kLen Length of the S2V key
201  * @param[in] ad Vector of associated data
202  * @param[in] adLen Number of components in the vector of associated data
203  * @param[in] p Payload data
204  * @param[in] pLen Length of the payload data
205  * @param[out] v synthetic IV
206  **/
207 
208 void s2v(const CipherAlgo *cipher, const uint8_t *k, size_t kLen,
209  const DataChunk *ad, uint_t adLen, const uint8_t *p, size_t pLen,
210  uint8_t *v)
211 {
212  uint_t i;
213  uint8_t d[16];
214  uint8_t t[16];
215  CmacContext cmacContext;
216 
217  //The S2V operation is bootstrapped by performing CMAC on a 128-bit
218  //string of zeros
219  osMemset(t, 0, 16);
220 
221  //Compute D = AES-CMAC(K, <zero>)
222  cmacInit(&cmacContext, cipher, k, kLen);
223  cmacUpdate(&cmacContext, t, 16);
224  cmacFinal(&cmacContext, d, 16);
225 
226  //Process the vector of associated data
227  for(i = 0; i < adLen; i++)
228  {
229  //Perform doubling
230  cmacMul(d, d, 16, 0x87);
231 
232  //Compute AES-CMAC(K, Si)
233  cmacReset(&cmacContext);
234  cmacUpdate(&cmacContext, ad[i].buffer, ad[i].length);
235  cmacFinal(&cmacContext, t, 16);
236 
237  //Compute D = dbl(D) xor AES-CMAC(K, Si)
238  cmacXorBlock(d, d, t, 16);
239  }
240 
241  //Initialize CMAC computation
242  cmacReset(&cmacContext);
243 
244  //If the length of the final string is less than 128 bits, the output of
245  //the double/xor chain is doubled once more and it is xored with the final
246  //string padded using the padding function pad(X)
247  if(pLen < 16)
248  {
249  //Perform doubling
250  cmacMul(t, d, 16, 0x87);
251 
252  //Calcuate T = dbl(D) xor pad(Sn)
253  cmacXorBlock(t, t, p, pLen);
254  t[pLen] ^= 0x80;
255  }
256  else
257  {
258  //Update CMAC computation
259  cmacUpdate(&cmacContext, p, pLen - 16);
260 
261  //Calculate T = Sn xorend D
262  cmacXorBlock(t, p + pLen - 16, d, 16);
263  }
264 
265  //That result is input to a final CMAC operation to produce the output V
266  cmacUpdate(&cmacContext, t, 16);
267  cmacFinal(&cmacContext, v, 16);
268 }
269 
270 #endif
uint8_t p
Definition: ndp.h:300
@ CIPHER_ALGO_TYPE_BLOCK
Definition: crypto.h:953
uint8_t t
Definition: lldp_ext_med.h:212
Generic cipher algorithm context.
size_t blockSize
Definition: crypto.h:1072
error_t ctrDecrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *c, uint8_t *p, size_t length)
CTR decryption.
Definition: ctr.c:122
void s2v(const CipherAlgo *cipher, const uint8_t *k, size_t kLen, const DataChunk *ad, uint_t adLen, const uint8_t *p, size_t pLen, uint8_t *v)
S2V operation.
Definition: siv.c:208
void cmacMul(uint8_t *x, const uint8_t *a, size_t n, uint8_t rb)
Multiplication by x in GF(2^128)
Definition: cmac.c:318
CipherAlgoInit init
Definition: crypto.h:1073
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
CipherAlgoType type
Definition: crypto.h:1071
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
__weak_func error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
CTR encryption.
Definition: ctr.c:62
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:319
uint8_t length
Definition: tcp.h:368
CMAC algorithm context.
Definition: cmac.h:54
void cmacXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
XOR operation.
Definition: cmac.c:349
Data chunk descriptor.
Definition: crypto.h:981
void cmacReset(CmacContext *context)
Reset CMAC context.
Definition: cmac.c:172
Synthetic Initialization Vector (SIV)
error_t sivDecrypt(const CipherAlgo *cipher, const uint8_t *k, size_t kLen, const DataChunk *ad, uint_t adLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *v)
Authenticated decryption using SIV.
Definition: siv.c:133
Common interface for encryption algorithms.
Definition: crypto.h:1068
error_t cmacInit(CmacContext *context, const CipherAlgo *cipher, const void *key, size_t keyLen)
Initialize CMAC calculation.
Definition: cmac.c:107
void cmacUpdate(CmacContext *context, const void *data, size_t dataLen)
Update the CMAC context with a portion of the message being hashed.
Definition: cmac.c:191
error_t sivEncrypt(const CipherAlgo *cipher, const uint8_t *k, size_t kLen, const DataChunk *ad, uint_t adLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *v)
Authenticated encryption using SIV.
Definition: siv.c:65
CMAC (Cipher-based Message Authentication Code)
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
error_t cmacFinal(CmacContext *context, uint8_t *mac, size_t macLen)
Finish the CMAC calculation.
Definition: cmac.c:237
Counter(CTR) mode.
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.