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.
Fork of wolfSSL by
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 #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 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 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 void 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 /* put input byte block in word16 */ 00204 for (i = 0; i < IDEA_BLOCK_SIZE/2; i++) { 00205 x[i] = (word16)in[idx++] << 8; 00206 x[i] |= (word16)in[idx++]; 00207 } 00208 00209 for (i = 0; i < IDEA_ROUNDS; i++) { 00210 x[0] = idea_mult(x[0], idea->skey[skey_idx++]); 00211 x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00212 x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00213 x[3] = idea_mult(x[3], idea->skey[skey_idx++]); 00214 00215 t2 = x[0] ^ x[2]; 00216 t2 = idea_mult((word16)t2, idea->skey[skey_idx++]); 00217 t1 = (t2 + (x[1] ^ x[3])) & IDEA_MASK; 00218 t1 = idea_mult((word16)t1, idea->skey[skey_idx++]); 00219 t2 = (t1 + t2) & IDEA_MASK; 00220 00221 x[0] ^= t1; 00222 x[3] ^= t2; 00223 00224 t2 ^= x[1]; 00225 x[1] = x[2] ^ (word16)t1; 00226 x[2] = (word16)t2; 00227 } 00228 00229 x[0] = idea_mult(x[0], idea->skey[skey_idx++]); 00230 out[0] = (x[0] >> 8) & 0xFF; 00231 out[1] = x[0] & 0xFF; 00232 00233 x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00234 out[2] = (x[2] >> 8) & 0xFF; 00235 out[3] = x[2] & 0xFF; 00236 00237 x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; 00238 out[4] = (x[1] >> 8) & 0xFF; 00239 out[5] = x[1] & 0xFF; 00240 00241 x[3] = idea_mult(x[3], idea->skey[skey_idx++]); 00242 out[6] = (x[3] >> 8) & 0xFF; 00243 out[7] = x[3] & 0xFF; 00244 } 00245 00246 int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) 00247 { 00248 int blocks; 00249 00250 if (idea == NULL || out == NULL || in == NULL) 00251 return BAD_FUNC_ARG; 00252 00253 blocks = len / IDEA_BLOCK_SIZE; 00254 while (blocks--) { 00255 xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE); 00256 wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg); 00257 XMEMCPY(out, idea->reg, IDEA_BLOCK_SIZE); 00258 00259 out += IDEA_BLOCK_SIZE; 00260 in += IDEA_BLOCK_SIZE; 00261 } 00262 00263 return 0; 00264 } 00265 00266 int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len) 00267 { 00268 int blocks; 00269 00270 if (idea == NULL || out == NULL || in == NULL) 00271 return BAD_FUNC_ARG; 00272 00273 blocks = len / IDEA_BLOCK_SIZE; 00274 while (blocks--) { 00275 XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE); 00276 wc_IdeaCipher(idea, out, (byte*)idea->tmp); 00277 xorbuf(out, (byte*)idea->reg, IDEA_BLOCK_SIZE); 00278 XMEMCPY(idea->reg, idea->tmp, IDEA_BLOCK_SIZE); 00279 00280 out += IDEA_BLOCK_SIZE; 00281 in += IDEA_BLOCK_SIZE; 00282 } 00283 00284 return 0; 00285 } 00286 00287 #endif /* HAVE_IDEA */ 00288
Generated on Tue Jul 12 2022 23:30:55 by
1.7.2
