initial implementation of RC2-CBC

pull/3397/head
Chris Conlon 2020-09-30 17:16:47 -06:00
parent 4c75037bdb
commit a6923ff100
3 changed files with 274 additions and 18 deletions

View File

@ -79,6 +79,25 @@ static const byte pitable[256] = {
0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
};
/**
Sets RC2 IV, for use with CBC mode.
rc2 RC2 structure to load IV into
iv IV, of size RC2_BLOCK_SIZE octets
return 0 on success, negative on error
*/
int wc_Rc2SetIV(RC2* rc2, const byte* iv)
{
if (rc2 == NULL)
return BAD_FUNC_ARG;
if (iv)
XMEMCPY(rc2->reg, iv, RC2_BLOCK_SIZE);
else
XMEMSET(rc2->reg, 0, RC2_BLOCK_SIZE);
return 0;
}
/**
Set RC2 key, performing key expansion operation
rc2 RC2 structure to load expanded key into
@ -87,7 +106,8 @@ static const byte pitable[256] = {
bits Effective RC2 key length in bits (max 1024 bits)
return 0 on success, negative on error
*/
int wc_Rc2SetKey(RC2* rc2, const byte* key, word32 length, word32 bits)
int wc_Rc2SetKey(RC2* rc2, const byte* key, word32 length,
const byte* iv, word32 bits)
{
int i;
unsigned int T8, TM;
@ -102,6 +122,8 @@ int wc_Rc2SetKey(RC2* rc2, const byte* key, word32 length, word32 bits)
}
rc2->keylen = length;
rc2->bits = bits;
L = (byte*)rc2->key;
XMEMCPY(L, key, length);
@ -127,7 +149,7 @@ int wc_Rc2SetKey(RC2* rc2, const byte* key, word32 length, word32 bits)
rc2->key[i] = (word16)L[2*i] + ((word16)L[2*i+1] << 8);
}
return 0;
return wc_Rc2SetIV(rc2, iv);
}
/**
@ -260,21 +282,51 @@ int wc_Rc2EcbDecrypt(RC2* rc2, byte* out, const byte* in, word32 sz)
int wc_Rc2CbcEncrypt(RC2* rc2, byte* out, const byte* in, word32 sz)
{
/* STUB */
(void)rc2;
(void)out;
(void)in;
(void)sz;
word32 blocks = (sz / RC2_BLOCK_SIZE);
if (rc2 == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (sz == 0) {
return 0;
}
while (blocks--) {
xorbuf((byte*)rc2->reg, in, RC2_BLOCK_SIZE);
wc_Rc2EcbEncrypt(rc2, (byte*)rc2->reg, (byte*)rc2->reg, RC2_BLOCK_SIZE);
XMEMCPY(out, rc2->reg, RC2_BLOCK_SIZE);
out += RC2_BLOCK_SIZE;
in += RC2_BLOCK_SIZE;
}
return 0;
}
int wc_Rc2CbcDecrypt(RC2* rc2, byte* out, const byte* in, word32 sz)
{
/* STUB */
(void)rc2;
(void)out;
(void)in;
(void)sz;
word32 blocks = (sz / RC2_BLOCK_SIZE);
if (rc2 == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (sz == 0) {
return 0;
}
while (blocks--) {
XMEMCPY(rc2->tmp, in, RC2_BLOCK_SIZE);
wc_Rc2EcbDecrypt(rc2, out, (byte*)rc2->tmp, RC2_BLOCK_SIZE);
xorbuf(out, (byte*)rc2->reg, RC2_BLOCK_SIZE);
/* store iv for next call */
XMEMCPY(rc2->reg, rc2->tmp, RC2_BLOCK_SIZE);
out += RC2_BLOCK_SIZE;
in += RC2_BLOCK_SIZE;
}
return 0;
}

View File

@ -4272,14 +4272,15 @@ static int hmac_sha3_test(void)
typedef struct rc2TestVector {
const char* input;
const char* output;
const char* key;
const char* key; /* Key, variable up to 128 bytes */
const char* iv; /* IV, 8-bytes */
int inLen;
int outLen;
int keyLen;
int effectiveKeyBits;
int effectiveKeyBits; /* Up to 1024 bits supported */
} rc2TestVector;
int rc2_test(void)
static int rc2_ecb_test(void)
{
int ret = 0;
byte cipher[RC2_BLOCK_SIZE];
@ -4376,7 +4377,7 @@ int rc2_test(void)
XMEMSET(plain, 0, RC2_BLOCK_SIZE);
ret = wc_Rc2SetKey(&enc, (byte*)test_rc2[i].key, test_rc2[i].keyLen,
test_rc2[i].effectiveKeyBits);
NULL, test_rc2[i].effectiveKeyBits);
if (ret != 0) {
return -4106;
}
@ -4405,6 +4406,200 @@ int rc2_test(void)
return 0;
}
static int rc2_cbc_test(void)
{
int ret = 0;
byte cipher[128];
byte plain[128];
rc2TestVector a, b, c, d, e, f, g, h, i;
rc2TestVector test_rc2[9];
int times = sizeof(test_rc2) / sizeof(rc2TestVector), j;
/* key length = 7, effective key bits = 63 */
a.input = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
a.output = "\xEB\xB7\x73\xF9\x93\x27\x8E\xFF"
"\xF0\x51\x77\x8B\x65\xDB\x13\x57";
a.key = "\x00\x00\x00\x00\x00\x00\x00\x00";
a.iv = "\x00\x00\x00\x00\x00\x00\x00\x00";
a.inLen = RC2_BLOCK_SIZE*2;
a.outLen = RC2_BLOCK_SIZE*2;
a.keyLen = 8;
a.effectiveKeyBits = 63;
/* key length = 8, effective key bits = 64, all 0xFF */
b.input = "\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff";
b.output = "\xA3\xA1\x12\x65\x4F\x81\xC5\xCD"
"\xB6\x94\x3E\xEA\x3E\x8B\x9D\x1F";
b.key = "\xff\xff\xff\xff\xff\xff\xff\xff";
b.iv = "\xff\xff\xff\xff\xff\xff\xff\xff";
b.inLen = RC2_BLOCK_SIZE*2;
b.outLen = RC2_BLOCK_SIZE*2;
b.keyLen = 8;
b.effectiveKeyBits = 64;
/* key length = 8, effective key bits = 64 */
c.input = "\x10\x00\x00\x00\x00\x00\x00\x01"
"\x10\x00\x00\x00\x00\x00\x00\x01";
c.output = "\x30\x64\x9e\xdf\x9b\xe7\xd2\xc2";
c.output = "\xB5\x70\x14\xA2\x5F\x40\xE3\x6D"
"\x81\x99\x8D\xE0\xB5\xD5\x3A\x05";
c.key = "\x30\x00\x00\x00\x00\x00\x00\x00";
c.iv = "\x30\x00\x00\x00\x00\x00\x00\x00";
c.inLen = RC2_BLOCK_SIZE*2;
c.outLen = RC2_BLOCK_SIZE*2;
c.keyLen = 8;
c.effectiveKeyBits = 64;
/* key length = 1, effective key bits = 64 */
d.input = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
d.output = "\x61\xA8\xA2\x44\xAD\xAC\xCC\xF0"
"\x6D\x19\xE8\xF1\xFC\xE7\x38\x87";
d.key = "\x88";
d.iv = "\x00\x00\x00\x00\x00\x00\x00\x00";
d.inLen = RC2_BLOCK_SIZE*2;
d.outLen = RC2_BLOCK_SIZE*2;
d.keyLen = 1;
d.effectiveKeyBits = 64;
/* key length = 7, effective key bits = 64 */
e.input = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
e.output = "\x6C\xCF\x43\x08\x97\x4C\x26\x7F"
"\xCC\x3C\x53\x57\x7C\xA1\xA4\x4B";
e.key = "\x88\xbc\xa9\x0e\x90\x87\x5a";
e.iv = "\x00\x00\x00\x00\x00\x00\x00\x00";
e.inLen = RC2_BLOCK_SIZE*2;
e.outLen = RC2_BLOCK_SIZE*2;
e.keyLen = 7;
e.effectiveKeyBits = 64;
/* key length = 16, effective key bits = 64 */
f.input = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
f.output = "\x1A\x80\x7D\x27\x2B\xBE\x5D\xB1"
"\x64\xEF\xE1\xC3\xB8\xAD\xFB\xBA";
f.key = "\x88\xbc\xa9\x0e\x90\x87\x5a\x7f"
"\x0f\x79\xc3\x84\x62\x7b\xaf\xb2";
f.iv = "\x00\x00\x00\x00\x00\x00\x00\x00";
f.inLen = RC2_BLOCK_SIZE*2;
f.outLen = RC2_BLOCK_SIZE*2;
f.keyLen = 16;
f.effectiveKeyBits = 64;
/* key length = 16, effective bits = 128 */
g.input = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
g.output = "\x22\x69\x55\x2A\xB0\xF8\x5C\xA6"
"\x53\x6E\xFD\x2D\x89\xE1\x2A\x73";
g.key = "\x88\xbc\xa9\x0e\x90\x87\x5a\x7f"
"\x0f\x79\xc3\x84\x62\x7b\xaf\xb2";
g.iv = "\x00\x00\x00\x00\x00\x00\x00\x00";
g.inLen = RC2_BLOCK_SIZE*2;
g.outLen = RC2_BLOCK_SIZE*2;
g.keyLen = 16;
g.effectiveKeyBits = 128;
/* key length = 33, effective bits = 129 */
h.input = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
h.output = "\x5B\x78\xD3\xA4\x3D\xFF\xF1\xF1"
"\x45\x30\xA8\xD5\xC7\x7C\x46\x19";
h.key = "\x88\xbc\xa9\x0e\x90\x87\x5a\x7f"
"\x0f\x79\xc3\x84\x62\x7b\xaf\xb2"
"\x16\xf8\x0a\x6f\x85\x92\x05\x84"
"\xc4\x2f\xce\xb0\xbe\x25\x5d\xaf"
"\x1e";
h.iv = "\x00\x00\x00\x00\x00\x00\x00\x00";
h.inLen = RC2_BLOCK_SIZE*2;
h.outLen = RC2_BLOCK_SIZE*2;
h.keyLen = 33;
h.effectiveKeyBits = 129;
/* key length = 10, effective bits = 40 */
i.input = "\x11\x22\x33\x44\x55\x66\x77\x88"
"\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00"
"\x11\x22\x33\x44\x55\x66\x77\x88"
"\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00";
i.output = "\x71\x2D\x11\x99\xC9\xA0\x78\x4F"
"\xCD\xF1\x1E\x3D\xFD\x21\x7E\xDB"
"\xB2\x6E\x0D\xA4\x72\xBC\x31\x51"
"\x48\xEF\x4E\x68\x3B\xDC\xCD\x7D";
i.key = "\x26\x1E\x57\x8E\xC9\x62\xBF\xB8"
"\x3E\x96";
i.iv = "\x01\x02\x03\x04\x05\x06\x07\x08";
i.inLen = RC2_BLOCK_SIZE*4;
i.outLen = RC2_BLOCK_SIZE*4;
i.keyLen = 10;
i.effectiveKeyBits = 40;
test_rc2[0] = a;
test_rc2[1] = b;
test_rc2[2] = c;
test_rc2[3] = d;
test_rc2[4] = e;
test_rc2[5] = f;
test_rc2[6] = g;
test_rc2[7] = h;
test_rc2[8] = i;
for (j = 0; j < times; ++j) {
RC2 rc2;
XMEMSET(cipher, 0, sizeof(cipher));
XMEMSET(plain, 0, sizeof(plain));
ret = wc_Rc2SetKey(&rc2, (byte*)test_rc2[j].key, test_rc2[j].keyLen,
(byte*)test_rc2[j].iv, test_rc2[j].effectiveKeyBits);
if (ret != 0) {
return -4111;
}
ret = wc_Rc2CbcEncrypt(&rc2, cipher, (byte*)test_rc2[j].input,
test_rc2[j].inLen);
if (ret != 0) {
return -4112;
}
if (XMEMCMP(cipher, (byte*)test_rc2[j].output, test_rc2[j].outLen)) {
return -4113;
}
/* reset IV for decrypt, since overriden by encrypt operation */
ret = wc_Rc2SetIV(&rc2, (byte*)test_rc2[j].iv);
if (ret != 0) {
return -4114;
}
ret = wc_Rc2CbcDecrypt(&rc2, plain, cipher, test_rc2[j].outLen);
if (ret != 0) {
return -4115;
}
if (XMEMCMP(plain, (byte*)test_rc2[j].input, test_rc2[j].inLen)) {
return -4116;
}
}
return 0;
}
int rc2_test(void)
{
int ret = 0;
ret = rc2_ecb_test();
if (ret != 0) {
return ret;
}
return rc2_cbc_test();
}
#endif

View File

@ -37,15 +37,24 @@ enum {
/* RC2 encryption and decryption */
typedef struct RC2 {
word32 keylen;
word32 keylen; /* key length, octets */
word32 bits; /* effective key length, bits */
ALIGN16 word16 key[RC2_MAX_KEY_SIZE/2];
ALIGN16 word32 reg[RC2_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
ALIGN16 word32 tmp[RC2_BLOCK_SIZE / sizeof(word32)]; /* same */
} RC2;
WOLFSSL_API int wc_Rc2SetKey(RC2*, const byte*, word32, word32);
WOLFSSL_API int wc_Rc2SetKey(RC2* rc2, const byte* key, word32 length,
const byte* iv, word32 bits);
WOLFSSL_API int wc_Rc2SetIV(RC2* rc2, const byte* iv);
/* RC2-ECB */
WOLFSSL_API int wc_Rc2EcbEncrypt(RC2* rc2, byte* out,
const byte* in, word32 sz);
WOLFSSL_API int wc_Rc2EcbDecrypt(RC2* rc2, byte* out,
const byte* in, word32 sz);
/* RC2-CBC */
WOLFSSL_API int wc_Rc2CbcEncrypt(RC2* rc2, byte* out,
const byte* in, word32 sz);
WOLFSSL_API int wc_Rc2CbcDecrypt(RC2* rc2, byte* out,