1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/crypto/rc5.c
2015-07-22 19:18:34 +02:00

177 lines
3.9 KiB
C

/*
* 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 <nicolai.schmittberger@fu-berlin.de>
* @author Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
* @author Naveen Sastry
*
* @}
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#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;
}