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.
rc6.c
00001 /** 00002 * @file rc6.c 00003 * @brief RC6-32/20 block cipher 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 * @section Description 00026 * 00027 * RC6 is a symmetric key block cipher derived from RC5 00028 * 00029 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00030 * @version 1.7.6 00031 **/ 00032 00033 //Switch to the appropriate trace level 00034 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL 00035 00036 //Dependencies 00037 #include <string.h> 00038 #include "crypto.h" 00039 #include "rc6.h" 00040 00041 //Check crypto library configuration 00042 #if (RC6_SUPPORT == ENABLED) 00043 00044 //RC6 magic constants 00045 #define P32 0xB7E15163 00046 #define Q32 0x9E3779B9 00047 00048 //Common interface for encryption algorithms 00049 const CipherAlgo rc6CipherAlgo = 00050 { 00051 "RC6", 00052 sizeof(Rc6Context), 00053 CIPHER_ALGO_TYPE_BLOCK, 00054 RC6_BLOCK_SIZE, 00055 (CipherAlgoInit) rc6Init, 00056 NULL, 00057 NULL, 00058 (CipherAlgoEncryptBlock) rc6EncryptBlock, 00059 (CipherAlgoDecryptBlock) rc6DecryptBlock 00060 }; 00061 00062 00063 /** 00064 * @brief Initialize a RC6 context using the supplied key 00065 * @param[in] context Pointer to the RC6 context to initialize 00066 * @param[in] key Pointer to the key 00067 * @param[in] keyLength Length of the key 00068 * @return Error code 00069 **/ 00070 00071 error_t rc6Init(Rc6Context *context, const uint8_t *key, size_t keyLength) 00072 { 00073 uint_t c; 00074 uint_t i; 00075 uint_t j; 00076 uint_t s; 00077 uint_t v; 00078 uint32_t a; 00079 uint32_t b; 00080 00081 //Invalid key length? 00082 if(keyLength > RC6_MAX_KEY_SIZE) 00083 return ERROR_INVALID_KEY_LENGTH; 00084 00085 //Convert the secret key from bytes to words 00086 memset(context->l, 0, RC6_MAX_KEY_SIZE); 00087 memcpy(context->l, key, keyLength); 00088 00089 //Calculate the length of the key in words 00090 c = (keyLength > 0) ? (keyLength + 3) / 4 : 1; 00091 00092 //Initialize the first element of S 00093 context->s[0] = P32; 00094 00095 //Initialize array S to a particular fixed pseudo random bit pattern 00096 for(i = 1; i < (2 * RC6_NB_ROUNDS + 4); i++) 00097 context->s[i] = context->s[i - 1] + Q32; 00098 00099 //Initialize variables 00100 i = 0; 00101 j = 0; 00102 a = 0; 00103 b = 0; 00104 00105 //Number of iterations 00106 v = 3 * MAX(c, 2 * RC6_NB_ROUNDS + 4); 00107 00108 //Key expansion 00109 for(s = 0; s < v; s++) 00110 { 00111 context->s[i] += a + b; 00112 context->s[i] = ROL32(context->s[i], 3); 00113 a = context->s[i]; 00114 00115 context->l[j] += a + b; 00116 context->l[j] = ROL32(context->l[j], (a + b) % 32); 00117 b = context->l[j]; 00118 00119 if(++i >= (2 * RC6_NB_ROUNDS + 4)) 00120 i = 0; 00121 if(++j >= c) 00122 j = 0; 00123 } 00124 00125 //No error to report 00126 return NO_ERROR; 00127 } 00128 00129 00130 /** 00131 * @brief Encrypt a 16-byte block using RC6 algorithm 00132 * @param[in] context Pointer to the RC6 context 00133 * @param[in] input Plaintext block to encrypt 00134 * @param[out] output Ciphertext block resulting from encryption 00135 **/ 00136 00137 void rc6EncryptBlock(Rc6Context *context, const uint8_t *input, uint8_t *output) 00138 { 00139 uint_t i; 00140 uint32_t t; 00141 uint32_t u; 00142 00143 //Load the 4 working registers with the plaintext 00144 uint32_t a = LOAD32LE(input + 0); 00145 uint32_t b = LOAD32LE(input + 4); 00146 uint32_t c = LOAD32LE(input + 8); 00147 uint32_t d = LOAD32LE(input + 12); 00148 00149 //First, update B and D 00150 b += context->s[0]; 00151 d += context->s[1]; 00152 00153 //Apply 20 rounds 00154 for(i = 1; i <= RC6_NB_ROUNDS; i++) 00155 { 00156 t = (b * (2 * b + 1)); 00157 t = ROL32(t, 5); 00158 00159 u = (d * (2 * d + 1)); 00160 u = ROL32(u, 5); 00161 00162 a ^= t; 00163 a = ROL32(a, u % 32) + context->s[2 * i]; 00164 00165 c ^= u; 00166 c = ROL32(c, t % 32) + context->s[2 * i + 1]; 00167 00168 t = a; 00169 a = b; 00170 b = c; 00171 c = d; 00172 d = t; 00173 } 00174 00175 //Update A and C 00176 a += context->s[2 * RC6_NB_ROUNDS + 2]; 00177 c += context->s[2 * RC6_NB_ROUNDS + 3]; 00178 00179 //The resulting value is the ciphertext 00180 STORE32LE(a, output + 0); 00181 STORE32LE(b, output + 4); 00182 STORE32LE(c, output + 8); 00183 STORE32LE(d, output + 12); 00184 } 00185 00186 00187 /** 00188 * @brief Decrypt a 16-byte block using RC6 algorithm 00189 * @param[in] context Pointer to the RC6 context 00190 * @param[in] input Ciphertext block to decrypt 00191 * @param[out] output Plaintext block resulting from decryption 00192 **/ 00193 00194 void rc6DecryptBlock(Rc6Context *context, const uint8_t *input, uint8_t *output) 00195 { 00196 uint_t i; 00197 uint32_t t; 00198 uint32_t u; 00199 00200 //Load the 4 working registers with the ciphertext 00201 uint32_t a = LOAD32LE(input + 0); 00202 uint32_t b = LOAD32LE(input + 4); 00203 uint32_t c = LOAD32LE(input + 8); 00204 uint32_t d = LOAD32LE(input + 12); 00205 00206 //First, update C and A 00207 c -= context->s[2 * RC6_NB_ROUNDS + 3]; 00208 a -= context->s[2 * RC6_NB_ROUNDS + 2]; 00209 00210 //Apply 20 rounds 00211 for(i = RC6_NB_ROUNDS; i > 0; i--) 00212 { 00213 t = d; 00214 d = c; 00215 c = b; 00216 b = a; 00217 a = t; 00218 00219 u = (d * (2 * d + 1)); 00220 u = ROL32(u, 5); 00221 00222 t = (b * (2 * b + 1)); 00223 t = ROL32(t, 5); 00224 00225 c -= context->s[2 * i + 1]; 00226 c = ROR32(c, t % 32) ^ u; 00227 00228 a -= context->s[2 * i]; 00229 a = ROR32(a, u % 32) ^ t; 00230 } 00231 00232 //Update D and B 00233 d -= context->s[1]; 00234 b -= context->s[0]; 00235 00236 //The resulting value is the plaintext 00237 STORE32LE(a, output + 0); 00238 STORE32LE(b, output + 4); 00239 STORE32LE(c, output + 8); 00240 STORE32LE(d, output + 12); 00241 } 00242 00243 #endif 00244
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2