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  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/crypto.h"
34 #include "cipher/idea.h"
35 #include "debug.h"
36 
37 //Check crypto library configuration
38 #if (IDEA_SUPPORT == ENABLED)
39 
40 //Common interface for encryption algorithms
42 {
43  "IDEA",
44  sizeof(IdeaContext),
48  NULL,
49  NULL,
52 };
53 
54 
55 /**
56  * @brief Modular multiplication
57  * @param[in] a First operand
58  * @param[in] b Second operand
59  * @return Resulting value
60  **/
61 
62 static uint16_t ideaMul(uint16_t a, uint16_t b)
63 {
64  uint32_t c = a * b;
65 
66  if(c)
67  {
68  c = (ROL32(c, 16) - c) >> 16;
69  return (c + 1) & 0xFFFF;
70  }
71  else
72  {
73  return (1 - a - b) & 0xFFFF;
74  }
75 }
76 
77 
78 /**
79  * @brief Compute modular inverse
80  * @param[in] a Operand
81  * @return Resulting value
82  **/
83 
84 static uint16_t ideaInv(uint16_t a)
85 {
86  uint32_t b;
87  uint32_t q;
88  uint32_t r;
89  int32_t t;
90  int32_t u;
91  int32_t v;
92 
93  b = 0x10001;
94  u = 0;
95  v = 1;
96 
97  while(a > 0)
98  {
99  q = b / a;
100  r = b % a;
101 
102  b = a;
103  a = r;
104 
105  t = v;
106  v = u - q * v;
107  u = t;
108  }
109 
110  if(u < 0)
111  u += 0x10001;
112 
113  return u;
114 }
115 
116 
117 /**
118  * @brief Initialize a IDEA context using the supplied key
119  * @param[in] context Pointer to the IDEA context to initialize
120  * @param[in] key Pointer to the key
121  * @param[in] keyLen Length of the key
122  * @return Error code
123  **/
124 
125 error_t ideaInit(IdeaContext *context, const uint8_t *key, size_t keyLen)
126 {
127  uint_t i;
128  uint16_t *ek;
129  uint16_t *dk;
130 
131  //Invalid key length?
132  if(keyLen != 16)
134 
135  //Point to the encryption and decryption subkeys
136  ek = context->ek;
137  dk = context->dk;
138 
139  //First, the 128-bit key is partitioned into eight 16-bit sub-blocks
140  for(i = 0; i < 8; i++)
141  ek[i] = LOAD16BE(key + i * 2);
142 
143  //Expand encryption subkeys
144  for(i = 8; i < 52; i++)
145  {
146  if((i % 8) == 6)
147  ek[i] = (ek[i - 7] << 9) | (ek[i - 14] >> 7);
148  else if((i % 8) == 7)
149  ek[i] = (ek[i - 15] << 9) | (ek[i - 14] >> 7);
150  else
151  ek[i] = (ek[i - 7] << 9) | (ek[i - 6] >> 7);
152  }
153 
154  //Generate subkeys for decryption
155  for(i = 0; i < 52; i += 6)
156  {
157  dk[i] = ideaInv(ek[48 - i]);
158 
159  if(i == 0 || i == 48)
160  {
161  dk[i + 1] = -ek[49 - i];
162  dk[i + 2] = -ek[50 - i];
163  }
164  else
165  {
166  dk[i + 1] = -ek[50 - i];
167  dk[i + 2] = -ek[49 - i];
168  }
169 
170  dk[i + 3] = ideaInv(ek[51 - i]);
171 
172  if(i < 48)
173  {
174  dk[i + 4] = ek[46 - i];
175  dk[i + 5] = ek[47 - i];
176  }
177  }
178 
179  //No error to report
180  return NO_ERROR;
181 }
182 
183 
184 /**
185  * @brief Encrypt a 16-byte block using IDEA algorithm
186  * @param[in] context Pointer to the IDEA context
187  * @param[in] input Plaintext block to encrypt
188  * @param[out] output Ciphertext block resulting from encryption
189  **/
190 
191 void ideaEncryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
192 {
193  uint_t i;
194  uint16_t e;
195  uint16_t f;
196  uint16_t *k;
197 
198  //The plaintext is divided into four 16-bit registers
199  uint16_t a = LOAD16BE(input + 0);
200  uint16_t b = LOAD16BE(input + 2);
201  uint16_t c = LOAD16BE(input + 4);
202  uint16_t d = LOAD16BE(input + 6);
203 
204  //Point to the key schedule
205  k = context->ek;
206 
207  //The process consists of eight identical encryption steps
208  for(i = 0; i < 8; i++)
209  {
210  //Apply a round
211  a = ideaMul(a, k[0]);
212  b += k[1];
213  c += k[2];
214  d = ideaMul(d, k[3]);
215 
216  e = a ^ c;
217  f = b ^ d;
218 
219  e = ideaMul(e, k[4]);
220  f += e;
221  f = ideaMul(f, k[5]);
222  e += f;
223 
224  a ^= f;
225  d ^= e;
226  e ^= b;
227  f ^= c;
228 
229  b = f;
230  c = e;
231 
232  //Advance current location in key schedule
233  k += 6;
234  }
235 
236  //The four 16-bit values produced at the end of the 8th encryption
237  //round are combined with the last four of the 52 key sub-blocks
238  a = ideaMul(a, k[0]);
239  c += k[1];
240  b += k[2];
241  d = ideaMul(d, k[3]);
242 
243  //The resulting value is the ciphertext
244  STORE16BE(a, output + 0);
245  STORE16BE(c, output + 2);
246  STORE16BE(b, output + 4);
247  STORE16BE(d, output + 6);
248 }
249 
250 
251 /**
252  * @brief Decrypt a 16-byte block using IDEA algorithm
253  * @param[in] context Pointer to the IDEA context
254  * @param[in] input Ciphertext block to decrypt
255  * @param[out] output Plaintext block resulting from decryption
256  **/
257 
258 void ideaDecryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
259 {
260  uint_t i;
261  uint16_t e;
262  uint16_t f;
263  uint16_t *k;
264 
265  //The ciphertext is divided into four 16-bit registers
266  uint16_t a = LOAD16BE(input + 0);
267  uint16_t b = LOAD16BE(input + 2);
268  uint16_t c = LOAD16BE(input + 4);
269  uint16_t d = LOAD16BE(input + 6);
270 
271  //Point to the key schedule
272  k = context->dk;
273 
274  //The computational process used for decryption of the ciphertext is
275  //essentially the same as that used for encryption of the plaintext
276  for(i = 0; i < 8; i++)
277  {
278  //Apply a round
279  a = ideaMul(a, k[0]);
280  b += k[1];
281  c += k[2];
282  d = ideaMul(d, k[3]);
283 
284  e = a ^ c;
285  f = b ^ d;
286 
287  e = ideaMul(e, k[4]);
288  f += e;
289  f = ideaMul(f, k[5]);
290  e += f;
291 
292  a ^= f;
293  d ^= e;
294  e ^= b;
295  f ^= c;
296 
297  b = f;
298  c = e;
299 
300  //Advance current location in key schedule
301  k += 6;
302  }
303 
304  //The four 16-bit values produced at the end of the 8th encryption
305  //round are combined with the last four of the 52 key sub-blocks
306  a = ideaMul(a, k[0]);
307  c += k[1];
308  b += k[2];
309  d = ideaMul(d, k[3]);
310 
311  //The resulting value is the plaintext
312  STORE16BE(a, output + 0);
313  STORE16BE(c, output + 2);
314  STORE16BE(b, output + 4);
315  STORE16BE(d, output + 6);
316 }
317 
318 #endif
#define ROL32(a, n)
Definition: crypto.h:849
IDEA algorithm context.
Definition: idea.h:50
uint8_t c
Definition: ndp.h:510
uint16_t dk[52]
Definition: idea.h:53
const CipherAlgo ideaCipherAlgo
Definition: idea.c:41
Debugging facilities.
void(* CipherAlgoDecryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1030
General definitions for cryptographic algorithms.
Common interface for encryption algorithms.
Definition: crypto.h:1073
error_t ideaInit(IdeaContext *context, const uint8_t *key, size_t keyLen)
Initialize a IDEA context using the supplied key.
Definition: idea.c:125
uint8_t a
Definition: ndp.h:407
uint16_t ek[52]
Definition: idea.h:52
error_t(* CipherAlgoInit)(void *context, const uint8_t *key, size_t keyLen)
Definition: crypto.h:1026
void ideaDecryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using IDEA algorithm.
Definition: idea.c:258
#define LOAD16BE(p)
Definition: cpu_endian.h:168
void ideaEncryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using IDEA algorithm.
Definition: idea.c:191
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
#define STORE16BE(a, p)
Definition: cpu_endian.h:244
void(* CipherAlgoEncryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1029
uint32_t r
Definition: ndp.h:342
#define IDEA_BLOCK_SIZE
Definition: idea.h:36
uint8_t b[6]
Definition: dtls_misc.h:130
IDEA encryption algorithm.