/* * Copyright (C) 2013 Freie Universität Berlin, Computer Systems & Telematics * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @ingroup sys_crypto * @{ * * @file * @brief implementation of the RC5 cipher-algorithm * * @author Nicolai Schmittberger * @author Zakaria Kasmi * @author Naveen Sastry * * @} */ #include #include #include #include #include #include "crypto/rc5.h" #include "crypto/ciphers.h" /** * Define a fixed blocksize of 8 bytes */ #define BLOCK_SIZE (8U) /** * @brief Interface to the rc5 cipher */ static const cipher_interface_t rc5_interface = { BLOCK_SIZE, CIPHERS_MAX_KEY_SIZE, rc5_init, rc5_encrypt, rc5_decrypt }; const cipher_id_t CIPHER_RC5 = &rc5_interface; int rc5_encrypt(const cipher_context_t *context, const uint8_t *block, uint8_t *cipherBlock) { register uint32_t l; register uint32_t r; rc5_context_t *rc5_context = (rc5_context_t *) context->context; register uint32_t *s = rc5_context->skey; uint8_t i; c2l(block, l); block += 4; c2l(block, r); l += *s++; r += *s++; for (i = RC5_ROUNDS; i > 0; i--) { l ^= r; uint8_t tmp = r; tmp &= 0x1f; rotl32(l, tmp); l += *s++; r ^= l; tmp = l; tmp &= 0x1f; rotl32(r, tmp); r += *s++; } l2c(l, cipherBlock); cipherBlock += 4; l2c(r, cipherBlock); return 1; } int rc5_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock, uint8_t *plainBlock) { register uint32_t l; register uint32_t r; rc5_context_t *rc5_context = (rc5_context_t *) context->context; register uint32_t *s = rc5_context->skey + (2 * RC5_ROUNDS) + 1; uint8_t i; c2l(cipherBlock, l); cipherBlock += 4; c2l(cipherBlock, r); for (i = RC5_ROUNDS; i > 0; i--) { r -= *s--; uint8_t tmp = l; tmp &= 0x1f; rotr32(r, tmp); r ^= l; l -= *s--; tmp = r; tmp &= 0x1f; rotr32(l, tmp); l ^= r; } r -= *s--; l -= *s; l2c(l, plainBlock); plainBlock += 4; l2c(r, plainBlock); return 1; } int rc5_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize) { (void) keySize; uint32_t *L, l, A, B, *S; uint8_t ii, jj; int8_t i; uint8_t tmp[8]; // Make sure that context is large enough. If this is not the case, // you should build with -DRC5. if(CIPHER_MAX_CONTEXT_SIZE < RC5_CONTEXT_SIZE) { return 0; } rc5_context_t *rc5_context = (rc5_context_t *) context->context; S = rc5_context->skey; //dumpBuffer ("RC5M:setupKey K", (uint8_t *)key, 8); c2l(key, l); L = (uint32_t *) tmp; L[0] = l; key += 4; c2l(key, l); L[1] = l; S[0] = RC5_32_P; //dumpBuffer ("RC5M:setupKey L", (uint8_t *)L, 8); for (i = 1; i < 2 * RC5_ROUNDS + 2; i++) { S[i] = (S[i - 1] + RC5_32_Q); /* sum =(*S+RC5_32_Q)&RC5_32_MASK; * S++; * S = sum; */ } //dumpBuffer ("RC5M: setupKey S", (uint8_t *)S, 2 * (RC5_ROUNDS +1) * 4); ii = jj = 0; A = B = 0; S = rc5_context->skey; for (i = 3 * (2 * RC5_ROUNDS + 2) - 1; i >= 0; i--) { uint32_t k = (*S + A + B)&RC5_32_MASK; rotl32((k), (3)); A = *S = k; S++; uint8_t m = ((char)(A + B)) & 0x1f; k = (*L + A + B)&RC5_32_MASK; rotl32((k), (m)); B = *L = k; if (++ii >= 2 * RC5_ROUNDS + 2) { ii = 0; S = rc5_context->skey; } jj ^= 4; L = (uint32_t *)(&tmp[jj]); } return 1; }