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