| 1 | /* -*-c-*- |
| 2 | * |
| 3 | * The MARS block cipher |
| 4 | * |
| 5 | * (c) 2001 Straylight/Edgeware |
| 6 | */ |
| 7 | |
| 8 | /*----- Licensing notice --------------------------------------------------* |
| 9 | * |
| 10 | * This file is part of Catacomb. |
| 11 | * |
| 12 | * Catacomb is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of the GNU Library General Public License as |
| 14 | * published by the Free Software Foundation; either version 2 of the |
| 15 | * License, or (at your option) any later version. |
| 16 | * |
| 17 | * Catacomb is distributed in the hope that it will be useful, |
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 20 | * GNU Library General Public License for more details. |
| 21 | * |
| 22 | * You should have received a copy of the GNU Library General Public |
| 23 | * License along with Catacomb; if not, write to the Free |
| 24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
| 25 | * MA 02111-1307, USA. |
| 26 | */ |
| 27 | |
| 28 | /*----- Header files ------------------------------------------------------*/ |
| 29 | |
| 30 | #include <assert.h> |
| 31 | #include <stdio.h> |
| 32 | |
| 33 | #include <mLib/bits.h> |
| 34 | |
| 35 | #include "blkc.h" |
| 36 | #include "gcipher.h" |
| 37 | #include "mars.h" |
| 38 | #include "paranoia.h" |
| 39 | |
| 40 | /*----- Global variables --------------------------------------------------*/ |
| 41 | |
| 42 | const octet mars_keysz[] = { KSZ_RANGE, MARS_KEYSZ, 0, 56, 4 }; |
| 43 | |
| 44 | /*----- Useful tables -----------------------------------------------------*/ |
| 45 | |
| 46 | extern const uint32 mars_s[512]; |
| 47 | #define s0 (mars_s + 0) |
| 48 | #define s1 (mars_s + 256) |
| 49 | #define bb (mars_s + 265) |
| 50 | |
| 51 | /*----- Main code ---------------------------------------------------------*/ |
| 52 | |
| 53 | /* --- @mars_init@ --- * |
| 54 | * |
| 55 | * Arguments: @mars_ctx *k@ = pointer to key block to fill in |
| 56 | * @const void *buf@ = pointer to buffer of key material |
| 57 | * @size_t sz@ = size of key material |
| 58 | * |
| 59 | * Returns: --- |
| 60 | * |
| 61 | * Use: Initializes a MARS key buffer. MARS accepts key sizes |
| 62 | * between 128 and 448 bits which are a multiple of 32 bits. |
| 63 | */ |
| 64 | |
| 65 | void mars_init(mars_ctx *k, const void *buf, size_t sz) |
| 66 | { |
| 67 | uint32 t[15]; |
| 68 | uint32 *kk = k->k; |
| 69 | const octet *p; |
| 70 | unsigned i, j, ii; |
| 71 | |
| 72 | KSZ_ASSERT(mars, sz); |
| 73 | |
| 74 | /* --- Copy the key into the temporary buffer --- */ |
| 75 | |
| 76 | p = buf; |
| 77 | for (i = 0; i < sz/4; i++) { |
| 78 | t[i] = LOAD32_L(p); |
| 79 | p += 4; |
| 80 | } |
| 81 | t[i++] = sz/4; |
| 82 | for (; i < 15; i++) |
| 83 | t[i] = 0; |
| 84 | |
| 85 | /* --- Now spit out the actual key material --- */ |
| 86 | |
| 87 | for (j = 0; j < 4; j++) { |
| 88 | uint32 x; |
| 89 | |
| 90 | /* --- Do the linear mixing stage --- */ |
| 91 | |
| 92 | for (i = 0; i < 15; i++) { |
| 93 | x = t[(i + 8)%15] ^ t[(i + 13)%15]; |
| 94 | t[i] ^= ROL32(x, 3) ^ ((i << 2) | j); |
| 95 | } |
| 96 | |
| 97 | /* --- Now do the Feistel stirring stage --- */ |
| 98 | |
| 99 | x = t[14]; |
| 100 | for (ii = 0; ii < 4; ii++) { |
| 101 | for (i = 0; i < 15; i++) { |
| 102 | x = t[i] + mars_s[x & 511u]; |
| 103 | t[i] = x = ROL32(x, 9); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | /* --- And spit out the key material --- */ |
| 108 | |
| 109 | for (i = 0; i < 10; i++) |
| 110 | *kk++ = t[(4 * i)%15]; |
| 111 | } |
| 112 | |
| 113 | /* --- Finally, fix up the multiplicative entries --- */ |
| 114 | |
| 115 | for (i = 5; i < 37; i += 2) { |
| 116 | uint32 w, m, x; |
| 117 | j = k->k[i] & 3u; |
| 118 | w = k->k[i] | 3u; |
| 119 | |
| 120 | /* --- Compute the magic mask value --- */ |
| 121 | |
| 122 | m = 0; |
| 123 | for (ii = 0; ii <= 22; ii++) { |
| 124 | x = w >> ii; |
| 125 | if ((x & 0x3ff) == 0x3ff || (x & 0x3ff) == 0) |
| 126 | m |= 0x3ff << ii; |
| 127 | } |
| 128 | m &= ~(((w ^ (w << 1)) | (w ^ (w >> 1))) | 0x80000003); |
| 129 | |
| 130 | /* --- Add in the bias entry to fix up the key --- */ |
| 131 | |
| 132 | x = ROL32(bb[j], k->k[i - 1]); |
| 133 | k->k[i] = w ^ (x & m); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | /* --- @mars_eblk@, @mars_dblk@ --- * |
| 138 | * |
| 139 | * Arguments: @const mars_ctx *k@ = pointer to key block |
| 140 | * @const uint32 s[4]@ = pointer to source block |
| 141 | * @uint32 d[4]@ = pointer to destination block |
| 142 | * |
| 143 | * Returns: --- |
| 144 | * |
| 145 | * Use: Low-level block encryption and decryption. |
| 146 | */ |
| 147 | |
| 148 | #define KADD(k, a, b, c, d) a += *k++, b += *k++, c += *k++, d += *k++ |
| 149 | #define KSUB(k, a, b, c, d) a -= *k++, b -= *k++, c -= *k++, d -= *k++ |
| 150 | #define IKADD(k, a, b, c, d) d += *--k, c += *--k, b += *--k, a += *--k |
| 151 | #define IKSUB(k, a, b, c, d) d -= *--k, c -= *--k, b -= *--k, a -= *--k |
| 152 | |
| 153 | #define MIX(a, b, c, d) do { \ |
| 154 | b ^= s0[(a >> 0) & 0xff]; \ |
| 155 | b += s1[(a >> 8) & 0xff]; \ |
| 156 | c += s0[(a >> 16) & 0xff]; \ |
| 157 | d ^= s1[(a >> 24) & 0xff]; \ |
| 158 | a = ROL32(a, 8); \ |
| 159 | } while (0) |
| 160 | |
| 161 | #define IMIX(a, b, c, d) do { \ |
| 162 | a = ROR32(a, 8); \ |
| 163 | d ^= s1[(a >> 24) & 0xff]; \ |
| 164 | c -= s0[(a >> 16) & 0xff]; \ |
| 165 | b -= s1[(a >> 8) & 0xff]; \ |
| 166 | b ^= s0[(a >> 0) & 0xff]; \ |
| 167 | } while (0) |
| 168 | |
| 169 | #define E(x, y, z, k, a) do { \ |
| 170 | uint32 kx = *k++, ky = *k++; \ |
| 171 | y = a + kx; \ |
| 172 | a = ROL32(a, 13); z = a * ky; z = ROL32(z, 5); \ |
| 173 | x = mars_s[y & 511u] ^ z; y = ROL32(y, z); \ |
| 174 | z = ROL32(z, 5); x ^= z; x = ROL32(x, z); \ |
| 175 | } while (0) |
| 176 | |
| 177 | #define IE(x, y, z, k, a) do { \ |
| 178 | uint32 ky = *--k, kx = *--k; \ |
| 179 | z = a * ky; \ |
| 180 | a = ROR32(a, 13); y = a + kx; z = ROL32(z, 5); \ |
| 181 | x = mars_s[y & 511u] ^ z; y = ROL32(y, z); \ |
| 182 | z = ROL32(z, 5); x ^= z; x = ROL32(x, z); \ |
| 183 | } while (0) |
| 184 | |
| 185 | #define ROUND(k, a, b, c, d) do { \ |
| 186 | uint32 x, y, z; \ |
| 187 | E(x, y, z, k, a); \ |
| 188 | b += x; c += y; d ^= z; \ |
| 189 | } while (0) |
| 190 | |
| 191 | #define IROUND(k, a, b, c, d) do { \ |
| 192 | uint32 x, y, z; \ |
| 193 | IE(x, y, z, k, a); \ |
| 194 | b -= x; c -= y; d ^= z; \ |
| 195 | } while (0) |
| 196 | |
| 197 | void mars_eblk(const mars_ctx *k, const uint32 *src, uint32 *dst) |
| 198 | { |
| 199 | uint32 a, b, c, d; |
| 200 | const uint32 *kk = k->k; |
| 201 | |
| 202 | a = src[0], b = src[1], c = src[2], d = src[3]; |
| 203 | KADD(kk, a, b, c, d); |
| 204 | |
| 205 | MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c; |
| 206 | MIX(c, d, a, b); MIX(d, a, b, c); |
| 207 | MIX(a, b, c, d); a += d; MIX(b, c, d, a); b += c; |
| 208 | MIX(c, d, a, b); MIX(d, a, b, c); |
| 209 | |
| 210 | ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a); |
| 211 | ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c); |
| 212 | ROUND(kk, a, b, c, d); ROUND(kk, b, c, d, a); |
| 213 | ROUND(kk, c, d, a, b); ROUND(kk, d, a, b, c); |
| 214 | |
| 215 | ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c); |
| 216 | ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a); |
| 217 | ROUND(kk, a, d, c, b); ROUND(kk, b, a, d, c); |
| 218 | ROUND(kk, c, b, a, d); ROUND(kk, d, c, b, a); |
| 219 | |
| 220 | IMIX(a, d, c, b); IMIX(b, a, d, c); |
| 221 | c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a); |
| 222 | IMIX(a, d, c, b); IMIX(b, a, d, c); |
| 223 | c -= b; IMIX(c, b, a, d); d -= a; IMIX(d, c, b, a); |
| 224 | |
| 225 | KSUB(kk, a, b, c, d); |
| 226 | dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; |
| 227 | } |
| 228 | |
| 229 | void mars_dblk(const mars_ctx *k, const uint32 *src, uint32 *dst) |
| 230 | { |
| 231 | uint32 a, b, c, d; |
| 232 | const uint32 *kk = k->k + 40; |
| 233 | |
| 234 | a = src[0], b = src[1], c = src[2], d = src[3]; |
| 235 | IKADD(kk, a, b, c, d); |
| 236 | |
| 237 | MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b; |
| 238 | MIX(b, a, d, c); MIX(a, d, c, b); |
| 239 | MIX(d, c, b, a); d += a; MIX(c, b, a, d); c += b; |
| 240 | MIX(b, a, d, c); MIX(a, d, c, b); |
| 241 | |
| 242 | IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d); |
| 243 | IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b); |
| 244 | IROUND(kk, d, c, b, a); IROUND(kk, c, b, a, d); |
| 245 | IROUND(kk, b, a, d, c); IROUND(kk, a, d, c, b); |
| 246 | |
| 247 | IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b); |
| 248 | IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d); |
| 249 | IROUND(kk, d, a, b, c); IROUND(kk, c, d, a, b); |
| 250 | IROUND(kk, b, c, d, a); IROUND(kk, a, b, c, d); |
| 251 | |
| 252 | IMIX(d, a, b, c); IMIX(c, d, a, b); |
| 253 | b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d); |
| 254 | IMIX(d, a, b, c); IMIX(c, d, a, b); |
| 255 | b -= c; IMIX(b, c, d, a); a -= d; IMIX(a, b, c, d); |
| 256 | |
| 257 | IKSUB(kk, a, b, c, d); |
| 258 | dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; |
| 259 | } |
| 260 | |
| 261 | BLKC_TEST(MARS, mars) |
| 262 | |
| 263 | /*----- That's all, folks -------------------------------------------------*/ |