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-2017 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 <wolfcrypt/settings.h> 00028 00029 #ifdef HAVE_IDEA 00030 00031 #include <wolfcrypt/idea.h> 00032 00033 #include <wolfcrypt/error-crypt.h> 00034 #include <wolfcrypt/logging.h> 00035 00036 #ifdef NO_INLINE 00037 #include <wolfcrypt/misc.h> 00038 #else 00039 #define WOLFSSL_MISC_INCLUDED 00040 #include <wolfcrypt/src/misc.c> 00041 #endif 00042 00043 /* multiplication of x and y modulo 2^16+1 00044 * IDEA specify a special case when an entry value is 0 ( x or y) 00045 * then it must be replaced by 2^16 00046 */ 00047 static WC_INLINE word16 idea_mult(word16 x, word16 y) 00048 { 00049 long mul, res; 00050 00051 mul = (long)x * (long)y; 00052 if (mul) { 00053 res = (mul & IDEA_MASK) - ((word32)mul >> 16); 00054 if (res <= 0) 00055 res += IDEA_MODULO; 00056 00057 return (word16) (res & IDEA_MASK); 00058 } 00059 00060 if (!x) 00061 return ((IDEA_MODULO - y) & IDEA_MASK); 00062 00063 /* !y */ 00064 return ((IDEA_MODULO - x) & IDEA_MASK); 00065 } 00066 00067 /* compute 1/a modulo 2^16+1 using Extended euclidean algorithm 00068 * adapted from fp_invmod */ 00069 static WC_INLINE word16 idea_invmod(word16 x) 00070 { 00071 int u, v, b, d; 00072 00073 if (x <= 1) 00074 return x; 00075 00076 u = IDEA_MODULO; 00077 v = x; 00078 d = 1; 00079 b = 0; 00080 00081 do { 00082 while (!(u & 1)) { 00083 u >>= 1; 00084 if (b & 1) 00085 b -= IDEA_MODULO; 00086 b >>= 1; 00087 } 00088 00089 while (!(v & 1)) { 00090 v >>= 1; 00091 if (d & 1) { 00092 d -= IDEA_MODULO; 00093 } 00094 d >>= 1; 00095 } 00096 00097 if (u >= v) { 00098 u -= v; 00099 b -= d; 00100 } else { 00101 v -= u; 00102 d -= b; 00103 } 00104 } while (u != 0); 00105 00106 /* d is now the inverse, put positive value if required */ 00107 while (d < 0) 00108 d += IDEA_MODULO; 00109 00110 /* d must be < IDEA_MODULO */ 00111 while (d >= (int)IDEA_MODULO) 00112 d -= IDEA_MODULO; 00113 00114 return (word16)(d & IDEA_MASK); 00115 } 00116 00117 /* generate the 52 16-bits key sub-blocks from the 128 key */ 00118 int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz, 00119 const byte *iv, int dir) 00120 { 00121 word16 idx = 0; 00122 word32 t; 00123 short i; 00124 00125 if (idea == NULL || key == NULL || keySz != IDEA_KEY_SIZE || 00126 (dir != IDEA_ENCRYPTION && dir != IDEA_DECRYPTION)) 00127 return BAD_FUNC_ARG; 00128 00129 /* initial key schedule for 0 -> 7 */ 00130 for (i = 0; i < IDEA_ROUNDS; i++) { 00131 idea->skey[i] = (word16)key[idx++] << 8; 00132 idea->skey[i] |= (word16)key[idx++]; 00133 } 00134 00135 /* shift phase key schedule for 8 -> 51 */ 00136 for (i = IDEA_ROUNDS; i < IDEA_SK_NUM; i++) { 00137 t = (word32)idea->skey[((i+1) & 7) ? i-7 : i-15] << 9; 00138 t |= (word32)idea->skey[((i+2) & 7) < 2 ? i-14 : i-6] >> 7; 00139 idea->skey[i] = (word16)(t & IDEA_MASK); 00140 } 00141 00142 /* compute decryption key from encryption key */ 00143 if (dir == IDEA_DECRYPTION) { 00144 word16 enckey[IDEA_SK_NUM]; 00145 00146 /* put encryption key in tmp buffer */ 00147 XMEMCPY(enckey, idea->skey, sizeof(idea->skey)); 00148 00149 idx = 0; 00150 00151 idea->skey[6*IDEA_ROUNDS] = idea_invmod(enckey[idx++]); 00152 idea->skey[6*IDEA_ROUNDS+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00153 idea->skey[6*IDEA_ROUNDS+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00154 idea->skey[6*IDEA_ROUNDS+3] = idea_invmod(enckey[idx++]); 00155 00156 for (i = 6*(IDEA_ROUNDS-1); i >= 0; i -= 6) { 00157 idea->skey[i+4] = enckey[idx++]; 00158 idea->skey[i+5] = enckey[idx++]; 00159 00160 idea->skey[i] = idea_invmod(enckey[idx++]); 00161 if (i) { 00162 idea->skey[i+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00163 idea->skey[i+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00164 } 00165 else { 00166 idea->skey[1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00167 idea->skey[2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; 00168 } 00169 00170 idea->skey[i+3] = idea_invmod(enckey[idx++]); 00171 } 00172 00173 /* erase temporary buffer */ 00174 ForceZero(enckey, sizeof(enckey)); 00175 } 00176 00177 /* set the iv */ 00178 return wc_IdeaSetIV(idea, iv); 00179 } 00180 00181 /* set the IV in the Idea key structure */ 00182 int wc_IdeaSetIV(Idea *idea, const byte* iv) 00183 { 00184 if (idea == NULL) 00185 return BAD_FUNC_ARG; 00186 00187 if (iv != NULL) 00188 XMEMCPY(idea->reg, iv, IDEA_BLOCK_SIZE); 00189 else 00190 XMEMSET(idea->reg, 0, IDEA_BLOCK_SIZE); 00191 00192 return 0; 00193 } 00194 00195 /* encryption/decryption for a block (64 bits) 00196 */ 00197 int wc_IdeaCipher(Idea *idea, byte* out, const byte* in) 00198 { 00199 word32 t1, t2; 00200 word16 i, skey_idx = 0, idx = 0; 00201 word16 x[4]; 00202 00203 if (idea == NULL || out == NULL || in == NULL) { 00204 return BAD_FUNC_ARG; 00205 } 00206 00207 /* put input byte block in word16 */ 00208 for (i = 0; i < IDEA_BLOCK_SIZE/2; i++) { 00209 x[i] = (word16)in[idx++] << 8; 00210 x[i] |= (word16)in[idx++]; 00211 } 00212 00213 for (i = 0; i < IDEA_ROUNDS; i++) { 00214 x[0] = idea_mult(x[0], idea->skey[skey_idx++]); 00215 x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00216 x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00217 x[3] = idea_mult(x[3], idea->skey[skey_idx++]); 00218 00219 t2 = x[0] ^ x[2]; 00220 t2 = idea_mult((word16)t2, idea->skey[skey_idx++]); 00221 t1 = (t2 + (x[1] ^ x[3])) & IDEA_MASK; 00222 t1 = idea_mult((word16)t1, idea->skey[skey_idx++]); 00223 t2 = (t1 + t2) & IDEA_MASK; 00224 00225 x[0] ^= t1; 00226 x[3] ^= t2; 00227 00228 t2 ^= x[1]; 00229 x[1] = x[2] ^ (word16)t1; 00230 x[2] = (word16)t2; 00231 } 00232 00233 x[0] = idea_mult(x[0], idea->skey[skey_idx++]); 00234 out[0] = (x[0] >> 8) & 0xFF; 00235 out[1] = x[0] & 0xFF; 00236 00237 x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00238 out[2] = (x[2] >> 8) & 0xFF; 00239 out[3] = x[2] & 0xFF; 00240 00241 x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00242 out[4] = (x[1] >> 8) & 0xFF; 00243 out[5] = x[1] & 0xFF; 00244 00245 x[3] = idea_mult(x[3], idea->skey[skey_idx++]); 00246 out[6] = (x[3] >> 8) & 0xFF; 00247 out[7] = x[3] & 0xFF; 00248 00249 return 0; 00250 } 00251 00252 int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) 00253 { 00254 int blocks; 00255 int ret; 00256 00257 if (idea == NULL || out == NULL || in == NULL) 00258 return BAD_FUNC_ARG; 00259 00260 blocks = len / IDEA_BLOCK_SIZE; 00261 while (blocks--) { 00262 xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE); 00263 ret = wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg); 00264 if (ret != 0) { 00265 return ret; 00266 } 00267 00268 XMEMCPY(out, idea->reg, IDEA_BLOCK_SIZE); 00269 00270 out += IDEA_BLOCK_SIZE; 00271 in += IDEA_BLOCK_SIZE; 00272 } 00273 00274 return 0; 00275 } 00276 00277 int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len) 00278 { 00279 int blocks; 00280 int ret; 00281 00282 if (idea == NULL || out == NULL || in == NULL) 00283 return BAD_FUNC_ARG; 00284 00285 blocks = len / IDEA_BLOCK_SIZE; 00286 while (blocks--) { 00287 XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE); 00288 ret = wc_IdeaCipher(idea, out, (byte*)idea->tmp); 00289 if (ret != 0) { 00290 return ret; 00291 } 00292 00293 xorbuf(out, (byte*)idea->reg, IDEA_BLOCK_SIZE); 00294 XMEMCPY(idea->reg, idea->tmp, IDEA_BLOCK_SIZE); 00295 00296 out += IDEA_BLOCK_SIZE; 00297 in += IDEA_BLOCK_SIZE; 00298 } 00299 00300 return 0; 00301 } 00302 00303 #endif /* HAVE_IDEA */ 00304
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2