Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers idea.c Source File

idea.c

Go to the documentation of this file.
00001 /**
00002  * @file idea.c
00003  * @brief IDEA encryption algorithm
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <string.h>
00034 #include "crypto.h"
00035 #include "idea.h"
00036 #include "debug.h"
00037 
00038 //Check crypto library configuration
00039 #if (IDEA_SUPPORT == ENABLED)
00040 
00041 //Common interface for encryption algorithms
00042 const CipherAlgo ideaCipherAlgo =
00043 {
00044    "IDEA",
00045    sizeof(IdeaContext),
00046    CIPHER_ALGO_TYPE_BLOCK,
00047    IDEA_BLOCK_SIZE,
00048    (CipherAlgoInit) ideaInit,
00049    NULL,
00050    NULL,
00051    (CipherAlgoEncryptBlock) ideaEncryptBlock,
00052    (CipherAlgoDecryptBlock) ideaDecryptBlock
00053 };
00054 
00055 
00056 /**
00057  * @brief Modular multiplication
00058  * @param[in] a First operand
00059  * @param[in] b Second operand
00060  * @return Resulting value
00061  **/
00062 
00063 static uint16_t ideaMul(uint16_t a, uint16_t b)
00064 {
00065    uint32_t c = a * b;
00066 
00067    if(c)
00068    {
00069       c = (ROL32(c, 16) - c) >> 16;
00070       return (c + 1) & 0xFFFF;
00071    }
00072    else
00073    {
00074       return (1 - a - b) & 0xFFFF;
00075    }
00076 }
00077 
00078 
00079 /**
00080  * @brief Compute modular inverse
00081  * @param[in] a Operand
00082  * @return Resulting value
00083  **/
00084 
00085 static uint16_t ideaInv(uint16_t a)
00086 {
00087    uint32_t b;
00088    uint32_t q;
00089    uint32_t r;
00090    int32_t t;
00091    int32_t u;
00092    int32_t v;
00093 
00094    b = 0x10001;
00095    u = 0;
00096    v = 1;
00097 
00098    while(a > 0)
00099    {
00100       q = b / a;
00101       r = b % a;
00102 
00103       b = a;
00104       a = r;
00105 
00106       t = v;
00107       v = u - q * v;
00108       u = t;
00109    }
00110 
00111    if(u < 0)
00112       u += 0x10001;
00113 
00114    return u;
00115 }
00116 
00117 
00118 /**
00119  * @brief Initialize a IDEA context using the supplied key
00120  * @param[in] context Pointer to the IDEA context to initialize
00121  * @param[in] key Pointer to the key
00122  * @param[in] keyLength Length of the key
00123  * @return Error code
00124  **/
00125 
00126 error_t ideaInit(IdeaContext *context, const uint8_t *key, size_t keyLength)
00127 {
00128    uint_t i;
00129    uint16_t *ek;
00130    uint16_t *dk;
00131 
00132    //Invalid key length?
00133    if(keyLength != 16)
00134       return ERROR_INVALID_KEY_LENGTH;
00135 
00136    //Point to the encryption and decryption subkeys
00137    ek = context->ek;
00138    dk = context->dk;
00139 
00140    //First, the 128-bit key is partitioned into eight 16-bit sub-blocks
00141    for(i = 0; i < 8; i++)
00142       ek[i] = LOAD16BE(key + i * 2);
00143 
00144    //Expand encryption subkeys
00145    for(i = 8; i < 52; i++)
00146    {
00147       if((i % 8) == 6)
00148          ek[i] = (ek[i - 7] << 9) | (ek[i - 14] >> 7);
00149       else if((i % 8) == 7)
00150          ek[i] = (ek[i - 15] << 9) | (ek[i - 14] >> 7);
00151       else
00152          ek[i] = (ek[i - 7] << 9) | (ek[i - 6] >> 7);
00153    }
00154 
00155    //Generate subkeys for decryption
00156    for(i = 0; i < 52; i += 6)
00157    {
00158       dk[i] = ideaInv(ek[48 - i]);
00159 
00160       if(i == 0 || i == 48)
00161       {
00162          dk[i + 1] = -ek[49 - i];
00163          dk[i + 2] = -ek[50 - i];
00164       }
00165       else
00166       {
00167          dk[i + 1] = -ek[50 - i];
00168          dk[i + 2] = -ek[49 - i];
00169       }
00170 
00171       dk[i + 3] = ideaInv(ek[51 - i]);
00172 
00173       if(i < 48)
00174       {
00175          dk[i + 4] = ek[46 - i];
00176          dk[i + 5] = ek[47 - i];
00177       }
00178    }
00179 
00180    //No error to report
00181    return NO_ERROR;
00182 }
00183 
00184 
00185 /**
00186  * @brief Encrypt a 16-byte block using IDEA algorithm
00187  * @param[in] context Pointer to the IDEA context
00188  * @param[in] input Plaintext block to encrypt
00189  * @param[out] output Ciphertext block resulting from encryption
00190  **/
00191 
00192 void ideaEncryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
00193 {
00194    uint_t i;
00195    uint16_t e;
00196    uint16_t f;
00197    uint16_t *k;
00198 
00199    //The plaintext is divided into four 16-bit registers
00200    uint16_t a = LOAD16BE(input + 0);
00201    uint16_t b = LOAD16BE(input + 2);
00202    uint16_t c = LOAD16BE(input + 4);
00203    uint16_t d = LOAD16BE(input + 6);
00204 
00205    //Point to the key schedule
00206    k = context->ek;
00207 
00208    //The process consists of eight identical encryption steps
00209    for(i = 0; i < 8; i++)
00210    {
00211       //Apply a round
00212       a = ideaMul(a, k[0]);
00213       b += k[1];
00214       c += k[2];
00215       d = ideaMul(d, k[3]);
00216 
00217       e = a ^ c;
00218       f = b ^ d;
00219 
00220       e = ideaMul(e, k[4]);
00221       f += e;
00222       f = ideaMul(f, k[5]);
00223       e += f;
00224 
00225       a ^= f;
00226       d ^= e;
00227       e ^= b;
00228       f ^= c;
00229 
00230       b = f;
00231       c = e;
00232 
00233       //Advance current location in key schedule
00234       k += 6;
00235    }
00236 
00237    //The four 16-bit values produced at the end of the 8th encryption
00238    //round are combined with the last four of the 52 key sub-blocks
00239    a = ideaMul(a, k[0]);
00240    c += k[1];
00241    b += k[2];
00242    d = ideaMul(d, k[3]);
00243 
00244    //The resulting value is the ciphertext
00245    STORE16BE(a, output + 0);
00246    STORE16BE(c, output + 2);
00247    STORE16BE(b, output + 4);
00248    STORE16BE(d, output + 6);
00249 }
00250 
00251 
00252 /**
00253  * @brief Decrypt a 16-byte block using IDEA algorithm
00254  * @param[in] context Pointer to the IDEA context
00255  * @param[in] input Ciphertext block to decrypt
00256  * @param[out] output Plaintext block resulting from decryption
00257  **/
00258 
00259 void ideaDecryptBlock(IdeaContext *context, const uint8_t *input, uint8_t *output)
00260 {
00261    uint_t i;
00262    uint16_t e;
00263    uint16_t f;
00264    uint16_t *k;
00265 
00266    //The plaintext is divided into four 16-bit registers
00267    uint16_t a = LOAD16BE(input + 0);
00268    uint16_t b = LOAD16BE(input + 2);
00269    uint16_t c = LOAD16BE(input + 4);
00270    uint16_t d = LOAD16BE(input + 6);
00271 
00272    //Point to the key schedule
00273    k = context->dk;
00274 
00275    //The computational process used for decryption of the ciphertext is
00276    //essentially the same as that used for encryption of the plaintext
00277    for(i = 0; i < 8; i++)
00278    {
00279       //Apply a round
00280       a = ideaMul(a, k[0]);
00281       b += k[1];
00282       c += k[2];
00283       d = ideaMul(d, k[3]);
00284 
00285       e = a ^ c;
00286       f = b ^ d;
00287 
00288       e = ideaMul(e, k[4]);
00289       f += e;
00290       f = ideaMul(f, k[5]);
00291       e += f;
00292 
00293       a ^= f;
00294       d ^= e;
00295       e ^= b;
00296       f ^= c;
00297 
00298       b = f;
00299       c = e;
00300 
00301       //Advance current location in key schedule
00302       k += 6;
00303    }
00304 
00305    //The four 16-bit values produced at the end of the 8th encryption
00306    //round are combined with the last four of the 52 key sub-blocks
00307    a = ideaMul(a, k[0]);
00308    c += k[1];
00309    b += k[2];
00310    d = ideaMul(d, k[3]);
00311 
00312    //The resulting value is the plaintext
00313    STORE16BE(a, output + 0);
00314    STORE16BE(c, output + 2);
00315    STORE16BE(b, output + 4);
00316    STORE16BE(d, output + 6);
00317 }
00318 
00319 #endif
00320