Webserver+3d print
Diff: cyclone_crypto/rc6.c
- Revision:
- 0:8918a71cdbe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cyclone_crypto/rc6.c Sat Feb 04 18:15:49 2017 +0000 @@ -0,0 +1,244 @@ +/** + * @file rc6.c + * @brief RC6-32/20 block cipher + * + * @section License + * + * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCrypto Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * RC6 is a symmetric key block cipher derived from RC5 + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 1.7.6 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include <string.h> +#include "crypto.h" +#include "rc6.h" + +//Check crypto library configuration +#if (RC6_SUPPORT == ENABLED) + +//RC6 magic constants +#define P32 0xB7E15163 +#define Q32 0x9E3779B9 + +//Common interface for encryption algorithms +const CipherAlgo rc6CipherAlgo = +{ + "RC6", + sizeof(Rc6Context), + CIPHER_ALGO_TYPE_BLOCK, + RC6_BLOCK_SIZE, + (CipherAlgoInit) rc6Init, + NULL, + NULL, + (CipherAlgoEncryptBlock) rc6EncryptBlock, + (CipherAlgoDecryptBlock) rc6DecryptBlock +}; + + +/** + * @brief Initialize a RC6 context using the supplied key + * @param[in] context Pointer to the RC6 context to initialize + * @param[in] key Pointer to the key + * @param[in] keyLength Length of the key + * @return Error code + **/ + +error_t rc6Init(Rc6Context *context, const uint8_t *key, size_t keyLength) +{ + uint_t c; + uint_t i; + uint_t j; + uint_t s; + uint_t v; + uint32_t a; + uint32_t b; + + //Invalid key length? + if(keyLength > RC6_MAX_KEY_SIZE) + return ERROR_INVALID_KEY_LENGTH; + + //Convert the secret key from bytes to words + memset(context->l, 0, RC6_MAX_KEY_SIZE); + memcpy(context->l, key, keyLength); + + //Calculate the length of the key in words + c = (keyLength > 0) ? (keyLength + 3) / 4 : 1; + + //Initialize the first element of S + context->s[0] = P32; + + //Initialize array S to a particular fixed pseudo random bit pattern + for(i = 1; i < (2 * RC6_NB_ROUNDS + 4); i++) + context->s[i] = context->s[i - 1] + Q32; + + //Initialize variables + i = 0; + j = 0; + a = 0; + b = 0; + + //Number of iterations + v = 3 * MAX(c, 2 * RC6_NB_ROUNDS + 4); + + //Key expansion + for(s = 0; s < v; s++) + { + context->s[i] += a + b; + context->s[i] = ROL32(context->s[i], 3); + a = context->s[i]; + + context->l[j] += a + b; + context->l[j] = ROL32(context->l[j], (a + b) % 32); + b = context->l[j]; + + if(++i >= (2 * RC6_NB_ROUNDS + 4)) + i = 0; + if(++j >= c) + j = 0; + } + + //No error to report + return NO_ERROR; +} + + +/** + * @brief Encrypt a 16-byte block using RC6 algorithm + * @param[in] context Pointer to the RC6 context + * @param[in] input Plaintext block to encrypt + * @param[out] output Ciphertext block resulting from encryption + **/ + +void rc6EncryptBlock(Rc6Context *context, const uint8_t *input, uint8_t *output) +{ + uint_t i; + uint32_t t; + uint32_t u; + + //Load the 4 working registers with the plaintext + uint32_t a = LOAD32LE(input + 0); + uint32_t b = LOAD32LE(input + 4); + uint32_t c = LOAD32LE(input + 8); + uint32_t d = LOAD32LE(input + 12); + + //First, update B and D + b += context->s[0]; + d += context->s[1]; + + //Apply 20 rounds + for(i = 1; i <= RC6_NB_ROUNDS; i++) + { + t = (b * (2 * b + 1)); + t = ROL32(t, 5); + + u = (d * (2 * d + 1)); + u = ROL32(u, 5); + + a ^= t; + a = ROL32(a, u % 32) + context->s[2 * i]; + + c ^= u; + c = ROL32(c, t % 32) + context->s[2 * i + 1]; + + t = a; + a = b; + b = c; + c = d; + d = t; + } + + //Update A and C + a += context->s[2 * RC6_NB_ROUNDS + 2]; + c += context->s[2 * RC6_NB_ROUNDS + 3]; + + //The resulting value is the ciphertext + STORE32LE(a, output + 0); + STORE32LE(b, output + 4); + STORE32LE(c, output + 8); + STORE32LE(d, output + 12); +} + + +/** + * @brief Decrypt a 16-byte block using RC6 algorithm + * @param[in] context Pointer to the RC6 context + * @param[in] input Ciphertext block to decrypt + * @param[out] output Plaintext block resulting from decryption + **/ + +void rc6DecryptBlock(Rc6Context *context, const uint8_t *input, uint8_t *output) +{ + uint_t i; + uint32_t t; + uint32_t u; + + //Load the 4 working registers with the ciphertext + uint32_t a = LOAD32LE(input + 0); + uint32_t b = LOAD32LE(input + 4); + uint32_t c = LOAD32LE(input + 8); + uint32_t d = LOAD32LE(input + 12); + + //First, update C and A + c -= context->s[2 * RC6_NB_ROUNDS + 3]; + a -= context->s[2 * RC6_NB_ROUNDS + 2]; + + //Apply 20 rounds + for(i = RC6_NB_ROUNDS; i > 0; i--) + { + t = d; + d = c; + c = b; + b = a; + a = t; + + u = (d * (2 * d + 1)); + u = ROL32(u, 5); + + t = (b * (2 * b + 1)); + t = ROL32(t, 5); + + c -= context->s[2 * i + 1]; + c = ROR32(c, t % 32) ^ u; + + a -= context->s[2 * i]; + a = ROR32(a, u % 32) ^ t; + } + + //Update D and B + d -= context->s[1]; + b -= context->s[0]; + + //The resulting value is the plaintext + STORE32LE(a, output + 0); + STORE32LE(b, output + 4); + STORE32LE(c, output + 8); + STORE32LE(d, output + 12); +} + +#endif +