+++ /dev/null
-/* -*-c-*-
- *
- * $Id: safer.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
- *
- * The SAFER block cipher
- *
- * (c) 2001 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Catacomb.
- *
- * Catacomb is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * Catacomb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with Catacomb; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <mLib/bits.h>
-
-#include "blkc.h"
-#include "gcipher.h"
-#include "paranoia.h"
-#include "safer.h"
-#include "safer-tab.h"
-
-/*----- Global variables --------------------------------------------------*/
-
-const octet safer_keysz[] = { KSZ_SET, 8, 16, 0 };
-
-/*----- Important tables --------------------------------------------------*/
-
-static const octet s[265] = SAFER_S, si[256] = SAFER_SI;
-
-/*----- Main code ---------------------------------------------------------*/
-
-/* --- @safer_setup@ --- *
- *
- * Arguments: @safer_ctx *k@ = pointer to context to initialize
- * @unsigned r@ = number of rounds wanted
- * @unsigned f@ = various other flags
- * @const void *buf@ = pointer to key material
- * @size_t sz@ = size of key material in bytes
- *
- * Returns: ---
- *
- * Use: Initializes an SAFER expanded key. A default number of
- * rounds is chosen, based on the key length.
- */
-
-struct ksched {
- unsigned i;
- octet x[9];
-};
-
-static void init(struct ksched *t, const octet *k)
-{
- memcpy(t->x, k, 8);
- t->i = 1;
-}
-
-static void init_sk(struct ksched *t, const octet *k)
-{
- unsigned i;
- octet x;
- memcpy(t->x, k, 8);
- for (x = 0, i = 0; i < 8; x ^= k[i++])
- ;
- t->x[8] = x;
- t->i = 1;
-}
-
-static void next(struct ksched *t, octet *k)
-{
- unsigned i;
- if (k) {
- memcpy(k, t->x, 8);
- if (t->i > 1) {
- for (i = 0; i < 8; i++)
- k[i] += s[s[U8(9*t->i + i + 1)]];
- }
- }
- for (i = 0; i < 8; i++)
- t->x[i] = ROL8(t->x[i], 3);
- t->i++;
-}
-
-static void next_sk(struct ksched *t, octet *k)
-{
- unsigned i;
- i = (t->i - 1)%9;
- if (k) {
- if (i < 2)
- memcpy(k, t->x + i, 8);
- else {
- memcpy(k, t->x + i, 9 - i);
- memcpy(k + 9 - i, t->x, i - 1);
- }
- if (t->i > 1) {
- for (i = 0; i < 8; i++)
- k[i] += s[s[U8(9*t->i + i + 1)]];
- }
- }
- for (i = 0; i < 9; i++)
- t->x[i] = ROL8(t->x[i], 3);
- t->i++;
-}
-
-void safer_setup(safer_ctx *k, unsigned r, unsigned f,
- const void *buf, size_t sz)
-{
- struct ksched ka, kb;
- void (*in)(struct ksched *, const octet *);
- void (*nx)(struct ksched *, octet *);
- octet *kk;
-
- assert(r <= SAFER_MAXROUNDS);
- KSZ_ASSERT(safer, sz);
-
- if (f & SAFER_SK) {
- in = init_sk;
- nx = next_sk;
- } else {
- in = init;
- nx = next;
- }
-
- in(&kb, buf);
- in(&ka, sz == 8 ? buf : (const octet *)buf + 8);
-
- k->r = r;
- kk = k->k;
- while (r) {
- nx(&ka, kk); nx(&kb, 0); kk += 8;
- nx(&kb, kk); nx(&ka, 0); kk += 8;
- r--;
- }
- nx(&ka, kk); kk += 8;
-}
-
-/* --- @safer_init@, @safersk_init@ --- *
- *
- * Arguments: @safer_ctx *k@ = pointer to context to initialize
- * @const void *buf@ = pointer to key material
- * @size_t sz@ = size of key material in bytes
- *
- * Returns: ---
- *
- * Use: Initializes an SAFER expanded key. A default number of
- * rounds is chosen, based on the key length.
- */
-
-void safer_init(safer_ctx *k, const void *buf, size_t sz)
-{
- safer_setup(k, sz == 8 ? 6 : 10, 0, buf, sz);
-}
-
-void safersk_init(safer_ctx *k, const void *buf, size_t sz)
-{
- safer_setup(k, sz == 8 ? 8 : 10, SAFER_SK, buf, sz);
-}
-
-/* --- @safer_eblk@, @safer_dblk@ --- *
- *
- * Arguments: @const safer_ctx *k@ = pointer to SAFER context
- * @const uint32 s[2]@ = pointer to source block
- * @const uint32 d[2]@ = pointer to destination block
- *
- * Returns: ---
- *
- * Use: Low-level block encryption and decryption.
- */
-
-#define UNPACK(src, a, b, c, d, e, f, g, h) do { \
- a = U8(src[0] >> 24); b = U8(src[0] >> 16); \
- c = U8(src[0] >> 8); d = U8(src[0] >> 0); \
- e = U8(src[1] >> 24); f = U8(src[1] >> 16); \
- g = U8(src[1] >> 8); h = U8(src[1] >> 0); \
-} while (0)
-
-#define PACK(dst, a, b, c, d, e, f, g, h) do { \
- dst[0] = (U8(a) << 24) | (U8(b) << 16) | (U8(c) << 8) | U8(d); \
- dst[1] = (U8(e) << 24) | (U8(f) << 16) | (U8(g) << 8) | U8(h); \
-} while (0)
-
-#define F(x, y) y += x, x += y
-#define G(x, y) x -= y, y -= x
-
-#define PHT(a, b, c, d, e, f, g, h) do { \
- F(a, b); F(c, d); F(e, f); F(g, h); \
- F(a, c); F(e, g); F(b, d); F(f, h); \
- F(a, e); F(b, f); F(c, g); F(d, h); \
-} while (0)
- #define IPHT(a, b, c, d, e, f, g, h) do { \
- G(a, e); G(b, f); G(c, g); G(d, h); \
- G(a, c); G(e, g); G(b, d); G(f, h); \
- G(a, b); G(c, d); G(e, f); G(g, h); \
-} while (0)
-
-#define KXA(k, a, b, c, d, e, f, g, h) do { \
- a ^= *k++; b += *k++; c += *k++; d ^= *k++; \
- e ^= *k++; f += *k++; g += *k++; h ^= *k++; \
-} while (0)
-#define SUB(a, b, c, d, e, f, g, h) do { \
- a = s[U8(a)]; b = si[U8(b)]; c = si[U8(c)]; d = s[U8(d)]; \
- e = s[U8(e)]; f = si[U8(f)]; g = si[U8(g)]; h = s[U8(h)]; \
-} while (0)
-#define KAX(k, a, b, c, d, e, f, g, h) do { \
- a += *k++; b ^= *k++; c ^= *k++; d += *k++; \
- e += *k++; f ^= *k++; g ^= *k++; h += *k++; \
-} while (0)
-
-#define KXS(k, a, b, c, d, e, f, g, h) do { \
- h ^= *--k; g -= *--k; f -= *--k; e ^= *--k; \
- d ^= *--k; c -= *--k; b -= *--k; a ^= *--k; \
-} while (0)
-#define ISUB(a, b, c, d, e, f, g, h) do { \
- a = si[U8(a)]; b = s[U8(b)]; c = s[U8(c)]; d = si[U8(d)]; \
- e = si[U8(e)]; f = s[U8(f)]; g = s[U8(g)]; h = si[U8(h)]; \
-} while (0)
-#define KSX(k, a, b, c, d, e, f, g, h) do { \
- h -= *--k; g ^= *--k; f ^= *--k; e -= *--k; \
- d -= *--k; c ^= *--k; b ^= *--k; a -= *--k; \
-} while (0)
-
-#define EROUND(k, a, b, c, d, e, f, g, h) do { \
- KXA(k, a, b, c, d, e, f, g, h); \
- SUB(a, b, c, d, e, f, g, h); \
- KAX(k, a, b, c, d, e, f, g, h); \
- PHT(a, b, c, d, e, f, g, h); \
-} while (0)
-
-#define DROUND(k, a, b, c, d, e, f, g, h) do { \
- IPHT(a, b, c, d, e, f, g, h); \
- KSX(k, a, b, c, d, e, f, g, h); \
- ISUB(a, b, c, d, e, f, g, h); \
- KXS(k, a, b, c, d, e, f, g, h); \
-} while (0)
-
-
-void safer_eblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
-{
- octet a, b, c, d, e, f, g, h;
- unsigned r = k->r;
- const octet *kk = k->k;
-
- UNPACK(src, a, b, c, d, e, f, g, h);
- while (r >= 3) {
- EROUND(kk, a, b, c, d, e, f, g, h);
- EROUND(kk, a, e, b, f, c, g, d, h);
- EROUND(kk, a, c, e, g, b, d, f, h);
- r -= 3;
- }
- switch (r) {
- case 0:
- KXA(kk, a, b, c, d, e, f, g, h);
- PACK(dst, a, b, c, d, e, f, g ,h);
- break;
- case 1:
- EROUND(kk, a, b, c, d, e, f, g, h);
- KXA(kk, a, e, b, f, c, g, d, h);
- PACK(dst, a, e, b, f, c, g, d, h);
- break;
- case 2:
- EROUND(kk, a, b, c, d, e, f, g, h);
- EROUND(kk, a, e, b, f, c, g, d, h);
- KXA(kk, a, c, e, g, b, d, f, h);
- PACK(dst, a, c, e, g, b, d, f, h);
- break;
- }
-}
-
-void safer_dblk(const safer_ctx *k, const uint32 *src, uint32 *dst)
-{
- octet a, b, c, d, e, f, g, h;
- unsigned r = k->r;
- const octet *kk = k->k + 16 * r + 8;
- switch (r%3) {
- default:
- case 0:
- UNPACK(src, a, b, c, d, e, f, g, h);
- KXS(kk, a, b, c, d, e, f, g, h);
- break;
- case 1:
- UNPACK(src, a, e, b, f, c, g, d, h);
- KXS(kk, a, e, b, f, c, g, d, h);
- r--;
- goto one_round;
- case 2:
- UNPACK(src, a, c, e, g, b, d, f, h);
- KXS(kk, a, c, e, g, b, d, f, h);
- r -= 2;
- DROUND(kk, a, e, b, f, c, g, d, h);
- one_round:
- DROUND(kk, a, b, c, d, e, f, g, h);
- break;
- }
- while (r) {
- DROUND(kk, a, c, e, g, b, d, f, h);
- DROUND(kk, a, e, b, f, c, g, d, h);
- DROUND(kk, a, b, c, d, e, f, g, h);
- r -= 3;
- }
- PACK(dst, a, b, c, d, e, f, g, h);
-}
-
-BLKC_TEST(SAFER, safer)
-
-/*----- That's all, folks -------------------------------------------------*/