📄 rc5m.nc
字号:
/*
* "Copyright (c) 2000-2002 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Authors: Naveen Sastry
* Date: 9/29/02
*/
includes crypto;
#define rol32(a, n) ( a = (((a) << (n)) | ((a) >> (32-(n)))))
#define ror32(a, n) ( a = (((a) >> (n)) | ((a) << (32-(n)))))
#define fastrol32 rol32
#define fastror32 ror32
// convert a 4byte char array to a unsigned long
// [assumes least significant byte of char array is first]
#define c2l(c,l) (l =((unsigned long)(*((c)))), \
l|=((unsigned long)(*((c+1))))<< 8L, \
l|=((unsigned long)(*((c+2))))<<16L, \
l|=((unsigned long)(*((c+3))))<<24L)
// convert an unsigned long to a 4 byte char array
// [assumes least significant byte of char array is first]
#define l2c(l,c) (*((c)) =(unsigned char)(((l) )&0xff), \
*((c+1))=(unsigned char)(((l)>> 8L)&0xff), \
*((c+2))=(unsigned char)(((l)>>16L)&0xff), \
*((c+3))=(unsigned char)(((l)>>24L)&0xff))
// convert a 2 byte char array to an unsigned short:
// [assumes MOST significant byte is first]
#define c2sM(c, s) (s = ((unsigned short)(*((c)))) <<8L , \
s|= ((unsigned short)(*((c+1)))))
// convert a unsigned short to a 2 byte char array
// [assumes MOST significant byte is first]
#define s2cM(s, c) (*((c)) = (unsigned short)(((s) >> 8L)&0xff), \
*((c+1)) = (unsigned short)(((s) ) &0xff))
#define RC5_32_P 0xB7E15163L
#define RC5_32_Q 0x9E3779B9L
#define RC5_32_MASK 0xffffffffL
#define RC5_ROUNDS 12
#define rotl32(a,b) fastrol32((a), (b))
#define rotr32(a,b) fastror32((a), (b))
module RC5M {
provides interface BlockCipher;
provides interface BlockCipherInfo;
}
implementation
{
// 2 * (ROUNDS +1) * 4
// 2 * 13 * 4 = 104 bytes
typedef struct RC5Context {
uint32_t skey [2* (RC5_ROUNDS + 1) ];
} RC5Context;
enum { BSIZE = 8 };
result_t setupKey (CipherContext * context, uint8_t * key);
void dumpBuffer (char * bufName, uint8_t * buf, uint8_t size)
{
#ifdef O
uint8_t i = 0;
// fixme watch buffer overrun
char tmp[512];
for (; i < size; i++) {
sprintf (tmp + i * 3, "%2x ", (char)buf[i] & 0xff);
}
dbg(DBG_CRYPTO, "%s: {%s}\n", bufName, tmp);
#endif
}
/**
* Initialize the BlockCipher.
*
* @return Whether initialization was successful. The command may be
* unsuccessful if the key size or blockSize are not valid for the
* given cipher implementation.
*/
command result_t BlockCipher.init(CipherContext * context, uint8_t blockSize,
uint8_t keySize, uint8_t * key)
{
// 8 byte blocks only
if (blockSize != BSIZE) {
return FAIL;
}
return setupKey (context, key);
}
/**
* Encrypts a single block (of blockSize) using the key in the keySize.
*
* PROLOGUE: 24 cycles
* INIT: 48 cycles
* LOOP: 1680 cycles (12 + fastrol [= 42] + 16) * 2 * RC5_ROUNDS
* CLOSE: 24 cycles
* =====================
* 1776 cycles (avg case)
*
* @param plainBlock a plaintext block of blockSize
* @param cipherBlock the resulting ciphertext block of blockSize
*
* @return Whether the encryption was successful. Possible failure reasons
* include not calling init().
*/
command result_t BlockCipher.encrypt(CipherContext * context,
uint8_t * block, uint8_t * cipherBlock)
{
register uint32_t l;
register uint32_t r;
register uint32_t *s = ((RC5Context*) context->context)->skey;
uint8_t i, tmp;
c2l(block, l);
block += 4;
c2l(block, r);
l += *s++;
r += *s++;
for (i = RC5_ROUNDS; i > 0; i--) {
l ^= r; 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 SUCCESS;
}
/**
* Decrypts a single block (of blockSize) using the key in the keySize. Not
* all ciphers will implement this function (since providing encryption
* is a useful primitive).
*
* @param cipherBlock a ciphertext block of blockSize
* @param plainBlock the resulting plaintext block of blockSize
*
* @return Whether the decryption was successful. Possible failure reasons
* include not calling init() or an unimplimented decrypt function.
*/
command result_t BlockCipher.decrypt(CipherContext * context,
uint8_t * cipherBlock,
uint8_t * plainBlock)
{
register uint32_t l;
register uint32_t r;
register uint32_t *s = ((RC5Context*) context->context)->skey +
(2 * RC5_ROUNDS) + 1;
uint8_t i, tmp;
c2l(cipherBlock, l);
cipherBlock += 4;
c2l(cipherBlock, r);
for (i = RC5_ROUNDS; i> 0; i--) {
r -= *s--; 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 SUCCESS;
}
/**
* Performs the key expansion on the real secret.
*
* @param secret key
*/
result_t setupKey (CipherContext * context, uint8_t * key)
{
uint32_t *L,l,A,B,*S,k;
uint8_t ii,jj, m;
int8_t i;
uint8_t tmp[8];
S= ((RC5Context*)context->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= ((RC5Context*)context->context)->skey;
for (i=3*(2*RC5_ROUNDS + 2) - 1; i>=0; i--) {
k=(*S+A+B)&RC5_32_MASK;
rotl32((k), (3));
A=*S= k;
S++;
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= ((RC5Context*)context->context)->skey; }
jj ^= 4;
L = (uint32_t *) (&tmp[jj]);
}
dumpBuffer ("RC5M: setupKey S",
(uint8_t*)((RC5Context*)context->context)->skey,
2 * (RC5_ROUNDS + 1) * 4);
return SUCCESS;
}
/**
* Returns the preferred block size that this cipher operates with. It is
* always safe to call this function before the init() call has been made.
*
* @return the preferred block size for this cipher. In the case where the
* cipher operates with multiple block sizes, this will pick one
* particular size (deterministically).
*/
command uint8_t BlockCipherInfo.getPreferredBlockSize()
{
return BSIZE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -