X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/symm/rc5.c diff --git a/symm/rc5.c b/symm/rc5.c new file mode 100644 index 0000000..634f0b7 --- /dev/null +++ b/symm/rc5.c @@ -0,0 +1,230 @@ +/* -*-c-*- + * + * The RC5-32/12 block cipher + * + * (c) 1999 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 +#include +#include + +#include +#include + +#include "arena.h" +#include "blkc.h" +#include "gcipher.h" +#include "rc5.h" + +/*----- Global variables --------------------------------------------------*/ + +const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 }; + +/*----- Internal magical constants ----------------------------------------*/ + +#define T ((RC5_ROUNDS + 1) * 2) +#define P 0xb7e15163 +#define Q 0x9e3779b9 + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @rc5_init@ --- * + * + * Arguments: @rc5_ctx *k@ = pointer to a key block + * @const void *sbuf@ = pointer to key material + * @size_t sz@ = size of the key material + * + * Returns: --- + * + * Use: Initializes an RC5 key block. + */ + +void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz) +{ + uint32 *l; + size_t w; + + /* --- Set up the @L@ table --- * + * + * This is slightly unfortunately defined. + */ + + KSZ_ASSERT(rc5, sz); + + { + int i; + const octet *p = sbuf; + + /* --- Create the buffer --- */ + + w = (sz + 3) / 4; + l = XS_ALLOC(w * sizeof(uint32)); + + /* --- Extract the key material --- */ + + for (i = 0; sz > 3; i++) { + l[i] = LOAD32_L(p); + p += 4; + sz -= 4; + } + + /* --- Fix up the tail end --- */ + + if (sz) { + uint32 x = U8(*p++); + if (sz > 1) x |= (U8(*p++) << 8); + if (sz > 2) x |= (U8(*p++) << 16); + l[i] = x; + } + } + + /* --- Initialize the @S@ table --- */ + + { + int i; + + k->s[0] = P; + for (i = 1; i < T; i++) + k->s[i] = k->s[i - 1] + Q; + } + + /* --- Mix in the key --- */ + + { + int m = 3 * (w > T ? w : T); + int i, j, c; + uint32 a, b; + + for (c = i = j = a = b = 0; c < m; c++) { + uint32 x; + + x = k->s[i] + a + b; + k->s[i] = a = ROL32(x, 3); + i++; if (i >= T) i = 0; + + x = l[j] + a + b; + l[j] = b = ROL32(x, a + b); + j++; if (j >= w) j = 0; + } + } + + memset(l, 0, w * sizeof(uint32)); + XS_FREE(l); +} + +/* --- @EROUND@, @DROUND@ --- */ + +#define EROUND(x, y, k) do { \ + uint32 _x; \ + _x = x ^ y; x = ROL32(_x, y) + k[0]; \ + _x = y ^ x; y = ROL32(_x, x) + k[1]; \ + k += 2; \ +} while (0) + +#define DROUND(x, y, k) do { \ + uint32 _x; \ + k -= 2; \ + _x = y - k[1]; y = ROR32(_x, x) ^ x; \ + _x = x - k[0]; x = ROR32(_x, y) ^ y; \ +} while (0) + +/* --- @EBLK@, @DBLK@ --- */ + +#define EBLK(a, b, c, d, k) do { \ + uint32 _l, _r; \ + const uint32 *_k = (k)->s; \ + \ + _l = (a) + _k[0]; \ + _r = (b) + _k[1]; \ + _k += 2; \ + \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + EROUND(_l, _r, _k); \ + (c) = _l; \ + (d) = _r; \ +} while (0) + +#define DBLK(a, b, c, d, k) do { \ + uint32 _l, _r; \ + const uint32 *_k = (k)->s + T; \ + \ + _l = (a); \ + _r = (b); \ + \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + DROUND(_l, _r, _k); \ + \ + _k -= 2; \ + (d) = _r - _k[1]; \ + (c) = _l - _k[0]; \ +} while (0) + +/* --- @rc5_eblk@, @rc5_dblk@ --- * + * + * Arguments: @const rc5_ctx *k@ = pointer to RC5 context block + * @const uint32 s[2]@ = pointer to source block + * @uint32 *d[2]@ = pointer to destination block + * + * Returns: --- + * + * Use: Low level block encryption and decryption. + */ + +void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d) +{ + EBLK(s[0], s[1], d[0], d[1], k); +} + +void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d) +{ + DBLK(s[0], s[1], d[0], d[1], k); +} + +/* --- Test rig --- */ + +BLKC_TEST(RC5, rc5) + +/*----- That's all, folks -------------------------------------------------*/