Browse Source

Merge pull request #3963 from Kijewski/drop-skipjack

crypto: remove skipjack support
dev/timer
Oleg Hahm 7 years ago
parent
commit
dad04d7635
  1. 1
      sys/crypto/doc.txt
  2. 348
      sys/crypto/skipjack.c
  3. 5
      sys/include/crypto/ciphers.h
  4. 141
      sys/include/crypto/skipjack.h

1
sys/crypto/doc.txt

@ -19,7 +19,6 @@
* * AES-128
* * 3DES
* * Twofish
* * Skipjack
* * NULL
*
* You can use them directly by adding "crypto" to your USEMODULE-List.

348
sys/crypto/skipjack.c

@ -1,348 +0,0 @@
/*
* 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 SkipJack Cipher-Algorithm
*
* @author Freie Universitaet Berlin, Computer Systems & Telematics
* @author Nicolai Schmittberger <nicolai.schmittberger@fu-berlin.de>
* @author Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
* @author Naveen Sastry
*
* @}
*/
/*
* From the NIST description of SkipJack.
*/
// our context: we just expand the key to 20 bytes.
//
// we have two options for the expansion:
// 1. no expansion. advantage: 10byte context. disadvantage: mucks up
// the G box code with ifs / mods. Alternatively adds lots of code and
// muckiness.
// 2. expand key to 128 bytes. Makes G boxes easy to write, and minimal
// code expansion. disadvantage: wasted memory
// 3. expand key to 20 bytes. G boxes still simple, the encode and decode
// functions are a little more complicated, but still more or less
// managable. this is what we've implemented.
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "crypto/ciphers.h"
#include "crypto/skipjack.h"
/**
* @brief Define a fixed block size of 8 bytes
*/
#define BLOCK_SIZE (8U)
/**
* @brief Interface to the skipjack cipher
*/
static const cipher_interface_t skipjack_interface = {
BLOCK_SIZE,
CIPHERS_MAX_KEY_SIZE,
skipjack_init,
skipjack_encrypt,
skipjack_decrypt
};
const cipher_id_t CIPHER_SKIPJACK = &skipjack_interface;
// F-BOX
// It can live in either RAM (faster access) or program memory (save ram,
// but slower access). The type CRYPTO_TABLE_TYPE, defined in crypto.h
// defines where we drop the table and how we access it. This is necessary
// to compile for the PC target since it doesn't support tables in
// program memory the same way.
static const uint8_t SJ_F[] /*__attribute__((C))*/ = {
0xA3, 0xD7, 0x09, 0x83, 0xF8, 0x48, 0xF6, 0xF4, 0xB3, 0x21, 0x15, 0x78,
0x99, 0xB1, 0xAF, 0xF9, 0xE7, 0x2D, 0x4D, 0x8A, 0xCE, 0x4C, 0xCA, 0x2E,
0x52, 0x95, 0xD9, 0x1E, 0x4E, 0x38, 0x44, 0x28, 0x0A, 0xDF, 0x02, 0xA0,
0x17, 0xF1, 0x60, 0x68, 0x12, 0xB7, 0x7A, 0xC3, 0xE9, 0xFA, 0x3D, 0x53,
0x96, 0x84, 0x6B, 0xBA, 0xF2, 0x63, 0x9A, 0x19, 0x7C, 0xAE, 0xE5, 0xF5,
0xF7, 0x16, 0x6A, 0xA2, 0x39, 0xB6, 0x7B, 0x0F, 0xC1, 0x93, 0x81, 0x1B,
0xEE, 0xB4, 0x1A, 0xEA, 0xD0, 0x91, 0x2F, 0xB8, 0x55, 0xB9, 0xDA, 0x85,
0x3F, 0x41, 0xBF, 0xE0, 0x5A, 0x58, 0x80, 0x5F, 0x66, 0x0B, 0xD8, 0x90,
0x35, 0xD5, 0xC0, 0xA7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56,
0x6D, 0x98, 0x9B, 0x76, 0x97, 0xFC, 0xB2, 0xC2, 0xB0, 0xFE, 0xDB, 0x20,
0xE1, 0xEB, 0xD6, 0xE4, 0xDD, 0x47, 0x4A, 0x1D, 0x42, 0xED, 0x9E, 0x6E,
0x49, 0x3C, 0xCD, 0x43, 0x27, 0xD2, 0x07, 0xD4, 0xDE, 0xC7, 0x67, 0x18,
0x89, 0xCB, 0x30, 0x1F, 0x8D, 0xC6, 0x8F, 0xAA, 0xC8, 0x74, 0xDC, 0xC9,
0x5D, 0x5C, 0x31, 0xA4, 0x70, 0x88, 0x61, 0x2C, 0x9F, 0x0D, 0x2B, 0x87,
0x50, 0x82, 0x54, 0x64, 0x26, 0x7D, 0x03, 0x40, 0x34, 0x4B, 0x1C, 0x73,
0xD1, 0xC4, 0xFD, 0x3B, 0xCC, 0xFB, 0x7F, 0xAB, 0xE6, 0x3E, 0x5B, 0xA5,
0xAD, 0x04, 0x23, 0x9C, 0x14, 0x51, 0x22, 0xF0, 0x29, 0x79, 0x71, 0x7E,
0xFF, 0x8C, 0x0E, 0xE2, 0x0C, 0xEF, 0xBC, 0x72, 0x75, 0x6F, 0x37, 0xA1,
0xEC, 0xD3, 0x8E, 0x62, 0x8B, 0x86, 0x10, 0xE8, 0x08, 0x77, 0x11, 0xBE,
0x92, 0x4F, 0x24, 0xC5, 0x32, 0x36, 0x9D, 0xCF, 0xF3, 0xA6, 0xBB, 0xAC,
0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3, 0xBD, 0xA8, 0x3A, 0x01,
0x05, 0x59, 0x2A, 0x46
};
/**
* @brief convert 2x uint8_t to uint16_t
*
* @param c pointer to the 2x uint8_t input
* @param s pointer to the resulting uint16_t
*
*/
static void c2sM(const uint8_t *c, uint16_t *s)
{
memcpy(s, c, sizeof(uint16_t));
return;
}
/**
* @brief convert one uint16_t to 2x uint8_t
*
* @param s pointer to the uint16_t input
* @param c pointer to the first resulting uint8_ts
*/
static void s2cM(const uint16_t s, uint8_t *c)
{
memcpy(c, &s, sizeof(uint16_t));
return;
}
int skipjack_encrypt(const cipher_context_t *context, const uint8_t *plainBlock,
uint8_t *cipherBlock)
{
// prologue 10 pushs = 20 cycles
/*register*/ uint8_t counter = 1;
cipher_context_t *skipjack_context = (cipher_context_t *)context->context;
/*register*/ uint8_t *skey = skipjack_context->context;
/*register*/ uint16_t w1, w2, w3, w4, tmp;
/*register*/ uint8_t bLeft, bRight;
//dumpBuffer("SkipJack.encrypt: plainBlock", plainBlock, 8);
c2sM(plainBlock, &w1);
plainBlock += 2;
c2sM(plainBlock, &w2);
plainBlock += 2;
c2sM(plainBlock, &w3);
plainBlock += 2;
c2sM(plainBlock, &w4);
plainBlock += 2;
/*
* code if we had expanded key to 128 bytes. this is what the code below
* does, but after every 5 operations, it resets the where we are
* in the key back to the beginning of the skey. so our loops end up
* looking a little funny.
*
* while (counter < 9)
* RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
* while (counter < 17)
* RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
* while (counter < 25)
* RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
* while (counter < 33)
* RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
*/
while (counter < 6) { // 5x
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context;
while (counter < 9) { // 3x
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
while (counter < 11) { // 2x
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context;
while (counter < 16) { // 5x
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context;
// 1x
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
while (counter < 21) { // 4x
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context;
while (counter < 25) { // 4x
RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
// 1x
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
skey = skipjack_context->context;
while (counter < 31) { // 5x
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context;
while (counter < 33) { // 2x
RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
s2cM(w1, cipherBlock);
cipherBlock += 2;
s2cM(w2, cipherBlock);
cipherBlock += 2;
s2cM(w3, cipherBlock);
cipherBlock += 2;
s2cM(w4, cipherBlock);
/* cppcheck: may introduce timing bias if left out */
/* cppcheck-suppress uselessAssignmentPtrArg */
cipherBlock += 2;
return 1;
}
int skipjack_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
uint8_t *plainBlock)
{
/*register*/ uint8_t counter = 32;
cipher_context_t *skipjack_context = (cipher_context_t *)context->context;
/*register*/ uint8_t *skey = skipjack_context->context + 4;
/*register*/ uint16_t w1, w2, w3, w4, tmp;
/*register*/ uint8_t bLeft, bRight;
//dumpBuffer("SkipJack.decrypt: cipherBlock", cipherBlock, 8);
c2sM(cipherBlock, &w1);
cipherBlock += 2;
c2sM(cipherBlock, &w2);
cipherBlock += 2;
c2sM(cipherBlock, &w3);
cipherBlock += 2;
c2sM(cipherBlock, &w4);
/*
// code if we had expanded key to 128 bytes. this is what the code below
// does, but after every 5 operations, it resets the where we are
// in the key back to the beginning of the skey. so our loops end up
// looking a little funny.
while (counter > 24)
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
while (counter > 16)
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
while (counter > 8)
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
while (counter > 0)
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
*/
while (counter > 30) { //2x
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context + 16;
while (counter > 25) { //5x
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context + 16;
//1x
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
while (counter > 20) { //4x
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context + 16;
while (counter > 16) { //4x
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
//1x
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
skey = skipjack_context->context + 16;
while (counter > 10) { //5x
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context + 16;
while (counter > 8) { // 2x
RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
while (counter > 5) { // 3x
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
skey = skipjack_context->context + 16;
while (counter > 0) { // 5x
RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight);
}
s2cM(w1, plainBlock);
plainBlock += 2;
s2cM(w2, plainBlock);
plainBlock += 2;
s2cM(w3, plainBlock);
plainBlock += 2;
s2cM(w4, plainBlock);
return 1;
}
int skipjack_init(cipher_context_t *context, const uint8_t *key, uint8_t keysize)
{
int i = 0;
// Make sure that context is large enough. If this is not the case,
// you should build with -DSKIPJACK.
if(CIPHER_MAX_CONTEXT_SIZE < SKIPJACK_CONTEXT_SIZE) {
return 0;
}
cipher_context_t *skipjack_context = (cipher_context_t *)context->context;
uint8_t *skey = skipjack_context->context;
// for keys which are smaller than 160 bits, concatenate until they reach
// 160 bits in size. Note that key expansion is just concatenation.
if (keysize < CIPHERS_MAX_KEY_SIZE) {
//fill up by concatenating key to as long as needed
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
skey[i] = key[(i % keysize)];
}
}
else {
for (i = 0; i < CIPHERS_MAX_KEY_SIZE; i++) {
skey[i] = key[i];
}
}
return 1;
}

5
sys/include/crypto/ciphers.h

@ -36,7 +36,6 @@ extern "C" {
// #define CRYPTO_THREEDES
// #define CRYPTO_AES
// #define CRYPTO_TWOFISH
// #define CRYPTO_SKIPJACK
/** @brief the length of keys in bytes */
#define CIPHERS_MAX_KEY_SIZE 20
@ -50,7 +49,6 @@ extern "C" {
* threedes needs 24 bytes <br>
* aes needs CIPHERS_MAX_KEY_SIZE bytes <br>
* twofish needs CIPHERS_MAX_KEY_SIZE bytes <br>
* skipjack needs 20 bytes
*/
#if defined(CRYPTO_THREEDES)
#define CIPHER_MAX_CONTEXT_SIZE 24
@ -58,8 +56,6 @@ extern "C" {
#define CIPHER_MAX_CONTEXT_SIZE CIPHERS_MAX_KEY_SIZE
#elif defined(CRYPTO_TWOFISH)
#define CIPHER_MAX_CONTEXT_SIZE CIPHERS_MAX_KEY_SIZE
#elif defined(CRYPTO_SKIPJACK)
#define CIPHER_MAX_CONTEXT_SIZE 20
#else
// 0 is not a possibility because 0-sized arrays are not allowed in ISO C
#define CIPHER_MAX_CONTEXT_SIZE 1
@ -109,7 +105,6 @@ typedef const cipher_interface_t *cipher_id_t;
extern const cipher_id_t CIPHER_3DES;
extern const cipher_id_t CIPHER_AES_128;
extern const cipher_id_t CIPHER_TWOFISH;
extern const cipher_id_t CIPHER_SKIPJACK;
/**

141
sys/include/crypto/skipjack.h

@ -1,141 +0,0 @@
/*
* 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 Headers for the implementation of the SkipJack cipher-algorithm
*
* @author Freie Universitaet Berlin, Computer Systems & Telematics
* @author Nicolai Schmittberger <nicolai.schmittberger@fu-berlin.de>
* @author Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
*/
#ifndef SKIPJACK_H_
#define SKIPJACK_H_
#include "crypto/ciphers.h"
#ifdef __cplusplus
extern "C" {
#endif
#define F(addr) /*CRYPTO_TABLE_ACCESS( &SJ_F[addr])*/ (SJ_F[addr])
// G-Permutation: 4 round feistel structure
#define G(key, b, bLeft, bRight) \
( \
bLeft = b, \
bRight = (b >> 8), \
bLeft ^= F(bRight ^ key[0]), \
bRight ^= F(bLeft ^ key[1]), \
bLeft ^= F(bRight ^ key[2]), \
bRight ^= F(bLeft ^ key[3]), \
((bRight << 8) | bLeft))
#define G_INV(key, b, bLeft, bRight) \
( bLeft = b, \
bRight = (b >> 8), \
bRight ^= F(bLeft ^ key[3]), \
bLeft ^= F(bRight ^ key[2]), \
bRight ^= F(bLeft ^ key[1]), \
bLeft ^= F(bRight ^ key[0]), \
((bRight << 8) | bLeft))
// A-RULE:
#define RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight ) { \
tmp = w4; \
w4 = w3; \
w3 = w2; \
w2 = G(skey, w1, bLeft, bRight); \
w1 = ((tmp ^ w2) ^ counter); \
counter++; \
skey += 4; }
#define RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight) { \
tmp = w4; \
w4 = (w1 ^ w2 ^ counter); \
w1 = G_INV(skey, w2, bLeft, bRight); \
w2 = w3; \
w3 = tmp; \
counter--; \
skey -= 4; } \
// B-RULE:
#define RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight ) { \
tmp = w1; \
w1 = w4; \
w4 = w3; \
w3 = (tmp ^ w2 ^ counter); \
w2 = G(skey, tmp, bLeft, bRight); \
counter++; \
skey += 4; }
#define RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight ) { \
tmp = w1; \
w1 = G_INV(skey, w2, bLeft, bRight); \
w2 = (w1 ^ w3 ^ counter); \
w3 = w4; \
w4 = tmp; \
counter--; \
skey -= 4; }
/** 2 times keysize. makes unrolling keystream easier / efficient */
#define SKIPJACK_CONTEXT_SIZE 20
/**
* @brief Initialize the SkipJack-BlockCipher context.
*
* @param context structure to hold the opaque data from this
* initialization call. It should be passed to future
* invocations of this module which use this particular
* key.
* @param keySize key size in bytes
* @param key pointer to the key
*
* @return Whether initialization was successful. The command may be
* unsuccessful if the key size is not valid.
*/
int skipjack_init(cipher_context_t *context, const uint8_t *key, uint8_t keySize);
/**
* @brief Encrypts a single block (of blockSize) using the passed context.
*
* @param context holds the module specific opaque data related to the
* key (perhaps key expansions).
* @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().
*/
int skipjack_encrypt(const cipher_context_t *context, const uint8_t *plainBlock,
uint8_t *cipherBlock);
/**
* @brief Decrypts a single block (of blockSize) using the passed context.
*
* @param context holds the module specific opaque data related to the
* key (perhaps key expansions).
* @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()
*/
int skipjack_decrypt(const cipher_context_t *context, const uint8_t *cipherBlock,
uint8_t *plainBlock);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* SKIPJACK_H_ */
Loading…
Cancel
Save