Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
idea.c
00001 /* idea.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #ifdef HAVE_IDEA 00030 00031 #include <wolfssl/wolfcrypt/idea.h> 00032 00033 #include <wolfssl/wolfcrypt/error-crypt.h> 00034 #include <wolfssl/wolfcrypt/logging.h> 00035 00036 #ifdef NO_INLINE 00037 #include <wolfssl/wolfcrypt/misc.h> 00038 #else 00039 #include <wolfcrypt/src/misc.c> 00040 #endif 00041 00042 /* multiplication of x and y modulo 2^16+1 00043 * IDEA specify a special case when an entry value is 0 ( x or y) 00044 * then it must be replaced by 2^16 00045 */ 00046 static INLINE word16 idea_mult(word16 x, word16 y) 00047 { 00048 long mul, res; 00049 00050 mul = (long)x * (long)y; 00051 if (mul) { 00052 res = (mul & IDEA_MASK) - ((word32)mul >> 16); 00053 if (res <= 0) 00054 res += IDEA_MODULO; 00055 00056 return (word16) (res & IDEA_MASK); 00057 } 00058 00059 if (!x) 00060 return ((IDEA_MODULO - y) & IDEA_MASK); 00061 00062 /* !y */ 00063 return ((IDEA_MODULO - x) & IDEA_MASK); 00064 } 00065 00066 /* compute 1/a modulo 2^16+1 using Extended euclidean algorithm 00067 * adapted from fp_invmod */ 00068 static INLINE word16 idea_invmod(word16 x) 00069 { 00070 int u, v, b, d; 00071 00072 if (x <= 1) 00073 return x; 00074 00075 u = IDEA_MODULO; 00076 v = x; 00077 d = 1; 00078 b = 0; 00079 00080 do { 00081 while (!(u & 1)) { 00082 u >>= 1; 00083 if (b & 1) 00084 b -= IDEA_MODULO; 00085 b >>= 1; 00086 } 00087 00088 while (!(v & 1)) { 00089 v >>= 1; 00090 if (d & 1) { 00091 d -= IDEA_MODULO; 00092 } 00093 d >>= 1; 00094 } 00095 00096 if (u >= v) { 00097 u -= v; 00098 b -= d; 00099 } else { 00100 v -= u; 00101 d -= b; 00102 } 00103 } while (u != 0); 00104 00105 /* d is now the inverse, put positive value if required */ 00106 while (d < 0) 00107 d += IDEA_MODULO; 00108 00109 /* d must be < IDEA_MODULO */ 00110 while (d >= (int)IDEA_MODULO) 00111 d -= IDEA_MODULO; 00112 00113 return (word16)(d & IDEA_MASK); 00114 } 00115 00116 /* generate the 52 16-bits key sub-blocks from the 128 key */ 00117 int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz, 00118 const byte *iv, int dir) 00119 { 00120 word16 idx = 0; 00121 word32 t; 00122 short i; 00123 00124 if (idea == NULL || key == NULL || keySz != IDEA_KEY_SIZE || 00125 (dir != IDEA_ENCRYPTION && dir != IDEA_DECRYPTION)) 00126 return BAD_FUNC_ARG; 00127 00128 /* initial key schedule for 0 -> 7 */ 00129 for (i = 0; i < IDEA_ROUNDS; i++) { 00130 idea->skey[i] = (word16)key[idx++] << 8; 00131 idea->skey[i] |= (word16)key[idx++]; 00132 } 00133 00134 /* shift phase key schedule for 8 -> 51 */ 00135 for (i = IDEA_ROUNDS; i < IDEA_SK_NUM; i++) { 00136 t = (word32)idea->skey[((i+1) & 7) ? i-7 : i-15] << 9; 00137 t |= (word32)idea->skey[((i+2) & 7) < 2 ? i-14 : i-6] >> 7; 00138 idea->skey[i] = (word16)(t & IDEA_MASK); 00139 } 00140 00141 /* compute decryption key from encryption key */ 00142 if (dir == IDEA_DECRYPTION) { 00143 word16 enckey[IDEA_SK_NUM]; 00144 00145 /* put encryption key in tmp buffer */ 00146 XMEMCPY(enckey, idea->skey, sizeof(idea->skey)); 00147 00148 idx = 0; 00149 00150 idea->skey[6*IDEA_ROUNDS] = idea_invmod(enckey[idx++]); 00151 idea->skey[6*IDEA_ROUNDS+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00152 idea->skey[6*IDEA_ROUNDS+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00153 idea->skey[6*IDEA_ROUNDS+3] = idea_invmod(enckey[idx++]); 00154 00155 for (i = 6*(IDEA_ROUNDS-1); i >= 0; i -= 6) { 00156 idea->skey[i+4] = enckey[idx++]; 00157 idea->skey[i+5] = enckey[idx++]; 00158 00159 idea->skey[i] = idea_invmod(enckey[idx++]); 00160 if (i) { 00161 idea->skey[i+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00162 idea->skey[i+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00163 } 00164 else { 00165 idea->skey[1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00166 idea->skey[2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00167 } 00168 00169 idea->skey[i+3] = idea_invmod(enckey[idx++]); 00170 } 00171 00172 /* erase temporary buffer */ 00173 ForceZero(enckey, sizeof(enckey)); 00174 } 00175 00176 /* set the iv */ 00177 return wc_IdeaSetIV(idea, iv); 00178 } 00179 00180 /* set the IV in the Idea key structure */ 00181 int wc_IdeaSetIV(Idea *idea, const byte* iv) 00182 { 00183 if (idea == NULL) 00184 return BAD_FUNC_ARG; 00185 00186 if (iv != NULL) 00187 XMEMCPY(idea->reg, iv, IDEA_BLOCK_SIZE); 00188 else 00189 XMEMSET(idea->reg, 0, IDEA_BLOCK_SIZE); 00190 00191 return 0; 00192 } 00193 00194 /* encryption/decryption for a block (64 bits) 00195 */ 00196 void wc_IdeaCipher(Idea *idea, byte* out, const byte* in) 00197 { 00198 word32 t1, t2; 00199 word16 i, skey_idx = 0, idx = 0; 00200 word16 x[4]; 00201 00202 /* put input byte block in word16 */ 00203 for (i = 0; i < IDEA_BLOCK_SIZE/2; i++) { 00204 x[i] = (word16)in[idx++] << 8; 00205 x[i] |= (word16)in[idx++]; 00206 } 00207 00208 for (i = 0; i < IDEA_ROUNDS; i++) { 00209 x[0] = idea_mult(x[0], idea->skey[skey_idx++]); 00210 x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00211 x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00212 x[3] = idea_mult(x[3], idea->skey[skey_idx++]); 00213 00214 t2 = x[0] ^ x[2]; 00215 t2 = idea_mult((word16)t2, idea->skey[skey_idx++]); 00216 t1 = (t2 + (x[1] ^ x[3])) & IDEA_MASK; 00217 t1 = idea_mult((word16)t1, idea->skey[skey_idx++]); 00218 t2 = (t1 + t2) & IDEA_MASK; 00219 00220 x[0] ^= t1; 00221 x[3] ^= t2; 00222 00223 t2 ^= x[1]; 00224 x[1] = x[2] ^ (word16)t1; 00225 x[2] = (word16)t2; 00226 } 00227 00228 x[0] = idea_mult(x[0], idea->skey[skey_idx++]); 00229 out[0] = (x[0] >> 8) & 0xFF; 00230 out[1] = x[0] & 0xFF; 00231 00232 x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00233 out[2] = (x[2] >> 8) & 0xFF; 00234 out[3] = x[2] & 0xFF; 00235 00236 x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00237 out[4] = (x[1] >> 8) & 0xFF; 00238 out[5] = x[1] & 0xFF; 00239 00240 x[3] = idea_mult(x[3], idea->skey[skey_idx++]); 00241 out[6] = (x[3] >> 8) & 0xFF; 00242 out[7] = x[3] & 0xFF; 00243 } 00244 00245 int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) 00246 { 00247 int blocks; 00248 00249 if (idea == NULL || out == NULL || in == NULL) 00250 return BAD_FUNC_ARG; 00251 00252 blocks = len / IDEA_BLOCK_SIZE; 00253 while (blocks--) { 00254 xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE); 00255 wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg); 00256 XMEMCPY(out, idea->reg, IDEA_BLOCK_SIZE); 00257 00258 out += IDEA_BLOCK_SIZE; 00259 in += IDEA_BLOCK_SIZE; 00260 } 00261 00262 return 0; 00263 } 00264 00265 int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len) 00266 { 00267 int blocks; 00268 00269 if (idea == NULL || out == NULL || in == NULL) 00270 return BAD_FUNC_ARG; 00271 00272 blocks = len / IDEA_BLOCK_SIZE; 00273 while (blocks--) { 00274 XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE); 00275 wc_IdeaCipher(idea, out, (byte*)idea->tmp); 00276 xorbuf(out, (byte*)idea->reg, IDEA_BLOCK_SIZE); 00277 XMEMCPY(idea->reg, idea->tmp, IDEA_BLOCK_SIZE); 00278 00279 out += IDEA_BLOCK_SIZE; 00280 in += IDEA_BLOCK_SIZE; 00281 } 00282 00283 return 0; 00284 } 00285 00286 #endif /* HAVE_IDEA */ 00287
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2