idea.c
Go to the documentation of this file.
1 /**
2  * @file idea.c
3  * @brief IDEA encryption algorithm
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "cipher/idea.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (IDEA_SUPPORT == ENABLED)
41 
42 //Common interface for encryption algorithms
44 {
45  "IDEA",
46  sizeof(IdeaContext),
50  NULL,
51  NULL,
54 };
55 
56 
57 /**
58  * @brief Modular multiplication
59  * @param[in] a First operand
60  * @param[in] b Second operand
61  * @return Resulting value
62  **/
63 
64 static uint16_t ideaMul(uint16_t a, uint16_t b)
65 {
66  uint32_t c;
67 
68  //Perform multiplication modulo 2^16 - 1
69  c = a * b;
70 
71  if(c != 0)
72  {
73  c = ((ROL32(c, 16) - c) >> 16) + 1;
74  }
75  else
76  {
77  c = 1 - a - b;
78  }
79 
80  //Return the result
81  return c & 0xFFFF;
82 }
83 
84 
85 /**
86  * @brief Compute modular inverse
87  * @param[in] a Operand
88  * @return Resulting value
89  **/
90 
91 static uint16_t ideaInv(uint16_t a)
92 {
93  uint32_t b;
94  uint32_t q;
95  uint32_t r;
96  int32_t t;
97  int32_t u;
98  int32_t v;
99 
100  //Compute the multiplicative inverse modulo 2^16 - 1
101  b = 0x10001;
102  u = 0;
103  v = 1;
104 
105  while(a > 0)
106  {
107  q = b / a;
108  r = b % a;
109 
110  b = a;
111  a = r;
112 
113  t = v;
114  v = u - q * v;
115  u = t;
116  }
117 
118  if(u < 0)
119  {
120  u += 0x10001;
121  }
122 
123  //Return the result
124  return u;
125 }
126 
127 
128 /**
129  * @brief Initialize a IDEA context using the supplied key
130  * @param[in] context Pointer to the IDEA context to initialize
131  * @param[in] key Pointer to the key
132  * @param[in] keyLen Length of the key
133  * @return Error code
134  **/
135 
136 error_t ideaInit(IdeaContext *context, const uint8_t *key, size_t keyLen)
137 {
138  uint_t i;
139  uint16_t *ek;
140  uint16_t *dk;
141 
142  //Check parameters
143  if(context == NULL || key == NULL)
145 
146  //Invalid key length?
147  if(keyLen != 16)
149 
150  //Point to the encryption and decryption subkeys
151  ek = context->ek;
152  dk = context->dk;
153 
154  //First, the 128-bit key is partitioned into eight 16-bit sub-blocks
155  for(i = 0; i < 8; i++)
156  {
157  ek[i] = LOAD16BE(key + i * 2);
158  }
159 
160  //Expand encryption subkeys
161  for(i = 8; i < 52; i++)
162  {
163  if((i % 8) == 6)
164  {
165  ek[i] = (ek[i - 7] << 9) | (ek[i - 14] >> 7);
166  }
167  else if((i % 8) == 7)
168  {
169  ek[i] = (ek[i - 15] << 9) | (ek[i - 14] >> 7);
170  }
171  else
172  {
173  ek[i] = (ek[i - 7] << 9) | (ek[i - 6] >> 7);
174  }
175  }
176 
177  //Generate subkeys for decryption
178  for(i = 0; i < 52; i += 6)
179  {
180  dk[i] = ideaInv(ek[48 - i]);
181 
182  if(i == 0 || i == 48)
183  {
184  dk[i + 1] = -ek[49 - i];
185  dk[i + 2] = -ek[50 - i];
186  }
187  else
188  {
189  dk[i + 1] = -ek[50 - i];
190  dk[i + 2] = -ek[49 - i];
191  }
192 
193  dk[i + 3] = ideaInv(ek[51 - i]);
194 
195  if(i < 48)
196  {
197  dk[i + 4] = ek[46 - i];
198  dk[i + 5] = ek[47 - i];
199  }
200  }
201 
202  //No error to report
203  return NO_ERROR;
204 }
205 
206 
207 /**
208  * @brief Encrypt a 16-byte block using IDEA algorithm
209  * @param[in] context Pointer to the IDEA context
210  * @param[in] input Plaintext block to encrypt
211  * @param[out] output Ciphertext block resulting from encryption
212  **/
213 
214 void ideaEncryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
215 {
216  uint_t i;
217  uint16_t e;
218  uint16_t f;
219  uint16_t *k;
220 
221  //The plaintext is divided into four 16-bit registers
222  uint16_t a = LOAD16BE(input + 0);
223  uint16_t b = LOAD16BE(input + 2);
224  uint16_t c = LOAD16BE(input + 4);
225  uint16_t d = LOAD16BE(input + 6);
226 
227  //Point to the key schedule
228  k = context->ek;
229 
230  //The process consists of eight identical encryption steps
231  for(i = 0; i < 8; i++)
232  {
233  //Apply a round
234  a = ideaMul(a, k[0]);
235  b += k[1];
236  c += k[2];
237  d = ideaMul(d, k[3]);
238 
239  e = a ^ c;
240  f = b ^ d;
241 
242  e = ideaMul(e, k[4]);
243  f += e;
244  f = ideaMul(f, k[5]);
245  e += f;
246 
247  a ^= f;
248  d ^= e;
249  e ^= b;
250  f ^= c;
251 
252  b = f;
253  c = e;
254 
255  //Advance current location in key schedule
256  k += 6;
257  }
258 
259  //The four 16-bit values produced at the end of the 8th encryption
260  //round are combined with the last four of the 52 key sub-blocks
261  a = ideaMul(a, k[0]);
262  c += k[1];
263  b += k[2];
264  d = ideaMul(d, k[3]);
265 
266  //The resulting value is the ciphertext
267  STORE16BE(a, output + 0);
268  STORE16BE(c, output + 2);
269  STORE16BE(b, output + 4);
270  STORE16BE(d, output + 6);
271 }
272 
273 
274 /**
275  * @brief Decrypt a 16-byte block using IDEA algorithm
276  * @param[in] context Pointer to the IDEA context
277  * @param[in] input Ciphertext block to decrypt
278  * @param[out] output Plaintext block resulting from decryption
279  **/
280 
281 void ideaDecryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
282 {
283  uint_t i;
284  uint16_t e;
285  uint16_t f;
286  uint16_t *k;
287 
288  //The ciphertext is divided into four 16-bit registers
289  uint16_t a = LOAD16BE(input + 0);
290  uint16_t b = LOAD16BE(input + 2);
291  uint16_t c = LOAD16BE(input + 4);
292  uint16_t d = LOAD16BE(input + 6);
293 
294  //Point to the key schedule
295  k = context->dk;
296 
297  //The computational process used for decryption of the ciphertext is
298  //essentially the same as that used for encryption of the plaintext
299  for(i = 0; i < 8; i++)
300  {
301  //Apply a round
302  a = ideaMul(a, k[0]);
303  b += k[1];
304  c += k[2];
305  d = ideaMul(d, k[3]);
306 
307  e = a ^ c;
308  f = b ^ d;
309 
310  e = ideaMul(e, k[4]);
311  f += e;
312  f = ideaMul(f, k[5]);
313  e += f;
314 
315  a ^= f;
316  d ^= e;
317  e ^= b;
318  f ^= c;
319 
320  b = f;
321  c = e;
322 
323  //Advance current location in key schedule
324  k += 6;
325  }
326 
327  //The four 16-bit values produced at the end of the 8th encryption
328  //round are combined with the last four of the 52 key sub-blocks
329  a = ideaMul(a, k[0]);
330  c += k[1];
331  b += k[2];
332  d = ideaMul(d, k[3]);
333 
334  //The resulting value is the plaintext
335  STORE16BE(a, output + 0);
336  STORE16BE(c, output + 2);
337  STORE16BE(b, output + 4);
338  STORE16BE(d, output + 6);
339 }
340 
341 #endif
uint8_t a
Definition: ndp.h:410
void(* CipherAlgoEncryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1103
#define IDEA_BLOCK_SIZE
Definition: idea.h:38
uint8_t b[6]
Definition: dtls_misc.h:139
@ CIPHER_ALGO_TYPE_BLOCK
Definition: crypto.h:1069
uint32_t r
Definition: ndp.h:345
uint8_t t
Definition: llmnr_common.h:81
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:42
void(* CipherAlgoDecryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1104
#define STORE16BE(a, p)
Definition: cpu_endian.h:246
uint16_t dk[52]
Definition: idea.h:55
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:105
General definitions for cryptographic algorithms.
IDEA encryption algorithm.
uint16_t ek[52]
Definition: idea.h:54
error_t(* CipherAlgoInit)(void *context, const uint8_t *key, size_t keyLen)
Definition: crypto.h:1100
void ideaDecryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using IDEA algorithm.
Definition: idea.c:281
#define ROL32(a, n)
Definition: crypto.h:917
IDEA algorithm context.
Definition: idea.h:52
void ideaEncryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using IDEA algorithm.
Definition: idea.c:214
Common interface for encryption algorithms.
Definition: crypto.h:1150
const CipherAlgo ideaCipherAlgo
Definition: idea.c:43
unsigned int uint_t
Definition: compiler_port.h:45
#define LOAD16BE(p)
Definition: cpu_endian.h:170
error_t ideaInit(IdeaContext *context, const uint8_t *key, size_t keyLen)
Initialize a IDEA context using the supplied key.
Definition: idea.c:136
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
Debugging facilities.