mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-16 20:03:27 +03:00
246 lines
10 KiB
Plaintext
246 lines
10 KiB
Plaintext
/*
|
|
* Cryptol spec of the MISTY1 cipher. Based on RFC 2994, available at
|
|
* https://tools.ietf.org/rfc/rfc2994.txt
|
|
*
|
|
* Author: Adrian Herrera
|
|
*/
|
|
|
|
module MISTY1 where
|
|
|
|
//
|
|
// Key scheduling part
|
|
//
|
|
|
|
keySchedule : [16][8] -> [32][16]
|
|
keySchedule K = EK_1 # EK_2 # EK_3 # EK_4
|
|
where EK_1 = split (join K)
|
|
EK_2 = [ FI ek_1 ek_1_shifted
|
|
| ek_1 <- EK_1
|
|
| ek_1_shifted <- EK_1 <<< 1
|
|
]
|
|
EK_3 = [extend (drop`{7} ek_2) | ek_2 <- EK_2]
|
|
EK_4 = [extend (take`{7} ek_2) | ek_2 <- EK_2]
|
|
|
|
//
|
|
// Data randomizing part
|
|
//
|
|
|
|
FO : [32] -> [8] -> [32][16] -> [32]
|
|
FO FO_IN k EK = (FO_OUT ! 0).1 # (FO_OUT ! 0).0
|
|
where FO_OUT = [(take FO_IN, drop FO_IN)] # [ f t0 t1
|
|
| f <- funcs
|
|
| (t0, t1) <- FO_OUT
|
|
]
|
|
// t0, t1 as 16-bit integers
|
|
funcs : [_]([16] -> [16] -> ([16], [16]))
|
|
funcs = [\t0 t1 -> (t0 ^ (EK @ k), t1),
|
|
\t0 t1 -> (FI t0 (EK @ ((k + 5) % 8 + 8)), t1),
|
|
\t0 t1 -> (t0 ^ t1, t1),
|
|
\t0 t1 -> (t0, t1 ^ (EK @ ((k + 2) % 8))),
|
|
\t0 t1 -> (t0, FI t1 (EK @ ((k + 1) % 8 + 8))),
|
|
\t0 t1 -> (t0, t1 ^ t0),
|
|
\t0 t1 -> (t0 ^ EK @ ((k + 7) % 8), t1),
|
|
\t0 t1 -> (FI t0 (EK @ ((k + 3) % 8 + 8)), t1),
|
|
\t0 t1 -> (t0 ^ t1, t1),
|
|
\t0 t1 -> (t0, t1 ^ EK @ ((k + 4) % 8))
|
|
]
|
|
|
|
FI : [16] -> [16] -> [16]
|
|
FI FI_IN FI_KEY = (FI_OUT ! 0).1 # (FI_OUT ! 0).0
|
|
where FI_OUT = [(take FI_IN, drop FI_IN)] # [ f d9 d7
|
|
| f <- funcs
|
|
| (d9, d7) <- FI_OUT
|
|
]
|
|
// d9 as 9-bit integer
|
|
// d7 as 7-bit integer
|
|
funcs : [_]([9] -> [7] -> ([9], [7]))
|
|
funcs = [\d9 d7 -> ((S9 @ d9) ^ (extend d7), d7),
|
|
\d9 d7 -> (d9, drop (extend (S7 @ d7) ^ d9)),
|
|
\d9 d7 -> (d9, d7 ^ drop (FI_KEY >> 9)),
|
|
\d9 d7 -> (d9 ^ drop FI_KEY, d7),
|
|
\d9 d7 -> ((S9 @ d9) ^ (extend d7), d7)
|
|
]
|
|
|
|
S7 : [_][7]
|
|
S7 = [27, 50, 51, 90, 59, 16, 23, 84, 91, 26, 114, 115, 107,
|
|
44, 102, 73, 31, 36, 19, 108, 55, 46, 63, 74, 93, 15,
|
|
64, 86, 37, 81, 28, 4, 11, 70, 32, 13, 123, 53, 68,
|
|
66, 43, 30, 65, 20, 75, 121, 21, 111, 14, 85, 9, 54,
|
|
116, 12, 103, 83, 40, 10, 126, 56, 2, 7, 96, 41, 25,
|
|
18, 101, 47, 48, 57, 8, 104, 95, 120, 42, 76, 100, 69,
|
|
117, 61, 89, 72, 3, 87, 124, 79, 98, 60, 29, 33, 94,
|
|
39, 106, 112, 77, 58, 1, 109, 110, 99, 24, 119, 35, 5,
|
|
38, 118, 0, 49, 45, 122, 127, 97, 80, 34, 17, 6, 71,
|
|
22, 82, 78, 113, 62, 105, 67, 52, 92, 88, 125]
|
|
|
|
S9 : [_][9]
|
|
S9 = [451, 203, 339, 415, 483, 233, 251, 53, 385, 185, 279, 491, 307,
|
|
9, 45, 211, 199, 330, 55, 126, 235, 356, 403, 472, 163, 286,
|
|
85, 44, 29, 418, 355, 280, 331, 338, 466, 15, 43, 48, 314,
|
|
229, 273, 312, 398, 99, 227, 200, 500, 27, 1, 157, 248, 416,
|
|
365, 499, 28, 326, 125, 209, 130, 490, 387, 301, 244, 414, 467,
|
|
221, 482, 296, 480, 236, 89, 145, 17, 303, 38, 220, 176, 396,
|
|
271, 503, 231, 364, 182, 249, 216, 337, 257, 332, 259, 184, 340,
|
|
299, 430, 23, 113, 12, 71, 88, 127, 420, 308, 297, 132, 349,
|
|
413, 434, 419, 72, 124, 81, 458, 35, 317, 423, 357, 59, 66,
|
|
218, 402, 206, 193, 107, 159, 497, 300, 388, 250, 406, 481, 361,
|
|
381, 49, 384, 266, 148, 474, 390, 318, 284, 96, 373, 463, 103,
|
|
281, 101, 104, 153, 336, 8, 7, 380, 183, 36, 25, 222, 295,
|
|
219, 228, 425, 82, 265, 144, 412, 449, 40, 435, 309, 362, 374,
|
|
223, 485, 392, 197, 366, 478, 433, 195, 479, 54, 238, 494, 240,
|
|
147, 73, 154, 438, 105, 129, 293, 11, 94, 180, 329, 455, 372,
|
|
62, 315, 439, 142, 454, 174, 16, 149, 495, 78, 242, 509, 133,
|
|
253, 246, 160, 367, 131, 138, 342, 155, 316, 263, 359, 152, 464,
|
|
489, 3, 510, 189, 290, 137, 210, 399, 18, 51, 106, 322, 237,
|
|
368, 283, 226, 335, 344, 305, 327, 93, 275, 461, 121, 353, 421,
|
|
377, 158, 436, 204, 34, 306, 26, 232, 4, 391, 493, 407, 57,
|
|
447, 471, 39, 395, 198, 156, 208, 334, 108, 52, 498, 110, 202,
|
|
37, 186, 401, 254, 19, 262, 47, 429, 370, 475, 192, 267, 470,
|
|
245, 492, 269, 118, 276, 427, 117, 268, 484, 345, 84, 287, 75,
|
|
196, 446, 247, 41, 164, 14, 496, 119, 77, 378, 134, 139, 179,
|
|
369, 191, 270, 260, 151, 347, 352, 360, 215, 187, 102, 462, 252,
|
|
146, 453, 111, 22, 74, 161, 313, 175, 241, 400, 10, 426, 323,
|
|
379, 86, 397, 358, 212, 507, 333, 404, 410, 135, 504, 291, 167,
|
|
440, 321, 60, 505, 320, 42, 341, 282, 417, 408, 213, 294, 431,
|
|
97, 302, 343, 476, 114, 394, 170, 150, 277, 239, 69, 123, 141,
|
|
325, 83, 95, 376, 178, 46, 32, 469, 63, 457, 487, 428, 68,
|
|
56, 20, 177, 363, 171, 181, 90, 386, 456, 468, 24, 375, 100,
|
|
207, 109, 256, 409, 304, 346, 5, 288, 443, 445, 224, 79, 214,
|
|
319, 452, 298, 21, 6, 255, 411, 166, 67, 136, 80, 351, 488,
|
|
289, 115, 382, 188, 194, 201, 371, 393, 501, 116, 460, 486, 424,
|
|
405, 31, 65, 13, 442, 50, 61, 465, 128, 168, 87, 441, 354,
|
|
328, 217, 261, 98, 122, 33, 511, 274, 264, 448, 169, 285, 432,
|
|
422, 205, 243, 92, 258, 91, 473, 324, 502, 173, 165, 58, 459,
|
|
310, 383, 70, 225, 30, 477, 230, 311, 506, 389, 140, 143, 64,
|
|
437, 190, 120, 0, 172, 272, 350, 292, 2, 444, 162, 234, 112,
|
|
508, 278, 348, 76, 450]
|
|
|
|
FL : [32] -> [8] -> [32][16] -> [32]
|
|
FL FL_IN k EK =
|
|
if isEven k then
|
|
d0_even # d1_even
|
|
where d1_even = d1 ^ (d0 && (EK @ (k / 2)))
|
|
d0_even = d0 ^ (d1_even || (EK @ ((k / 2 + 6) % 8 + 8)))
|
|
else
|
|
d0_odd # d1_odd
|
|
where d1_odd = d1 ^ (d0 && (EK @ (((k - 1) / 2 + 2) % 8 + 8)))
|
|
d0_odd = d0 ^ (d1_odd || (EK @ (((k - 1) / 2 + 4) % 8)))
|
|
where // d0 as 16-bit integer
|
|
d0 : [16]
|
|
d0 = take FL_IN
|
|
// d1 as 16-bit integer
|
|
d1 : [16]
|
|
d1 = drop FL_IN
|
|
|
|
FLINV : [32] -> [8] -> [32][16] -> [32]
|
|
FLINV FL_IN k EK =
|
|
if isEven k then
|
|
d0_even # d1_even
|
|
where d0_even = d0 ^ (d1 || (EK @ ((k / 2 + 6) % 8 + 8)))
|
|
d1_even = d1 ^ (d0_even && (EK @ (k / 2)))
|
|
else
|
|
d0_odd # d1_odd
|
|
where d0_odd = d0 ^ (d1 || (EK @ (((k - 1) / 2 + 4) % 8)))
|
|
d1_odd = d1 ^ (d0_odd && (EK @ (((k - 1) / 2 + 2) % 8 + 8)))
|
|
where // d0 as 16-bit integer
|
|
d0 : [16]
|
|
d0 = take FL_IN
|
|
// d1 as 16-bit integer
|
|
d1 : [16]
|
|
d1 = drop FL_IN
|
|
|
|
//
|
|
// Encrypt/decrypt
|
|
//
|
|
|
|
misty1Encrypt : [64] -> [32][16] -> [64]
|
|
misty1Encrypt P EK = (C ! 0).1 # (C ! 0).0
|
|
where
|
|
// 64-bit plaintext P is divided into the leftmost 32-bit D0 and the
|
|
// rightmost 32-bit D1
|
|
C = [(take P, drop P)] # [ f D0 D1
|
|
| f <- funcs
|
|
| (D0, D1) <- C
|
|
]
|
|
funcs : [_]([32] -> [32] -> ([32], [32]))
|
|
funcs = [// 0 round
|
|
\D0 D1 -> (FL D0 0 EK, D1),
|
|
\D0 D1 -> (D0, FL D1 1 EK),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 0 EK)),
|
|
// 1 round
|
|
\D0 D1 -> (D0 ^ (FO D1 1 EK), D1),
|
|
// 2 round
|
|
\D0 D1 -> (FL D0 2 EK, D1),
|
|
\D0 D1 -> (D0, FL D1 3 EK),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 2 EK)),
|
|
// 3 round
|
|
\D0 D1 -> (D0 ^ (FO D1 3 EK), D1),
|
|
// 4 round
|
|
\D0 D1 -> (FL D0 4 EK, D1),
|
|
\D0 D1 -> (D0, FL D1 5 EK),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 4 EK)),
|
|
// 5 round
|
|
\D0 D1 -> (D0 ^ (FO D1 5 EK), D1),
|
|
// 6 round
|
|
\D0 D1 -> (FL D0 6 EK, D1),
|
|
\D0 D1 -> (D0, FL D1 7 EK),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 6 EK)),
|
|
// 7 round
|
|
\D0 D1 -> (D0 ^ (FO D1 7 EK), D1),
|
|
// final
|
|
\D0 D1 -> (FL D0 8 EK, D1),
|
|
\D0 D1 -> (D0, FL D1 9 EK)
|
|
]
|
|
|
|
misty1Decrypt : [64] -> [32][16] -> [64]
|
|
misty1Decrypt C EK = (P ! 0).0 # (P ! 0).1
|
|
where P = [(drop C, take C)] # [ f D0 D1
|
|
| f <- funcs
|
|
| (D0, D1) <- P
|
|
]
|
|
funcs : [_]([32] -> [32] -> ([32], [32]))
|
|
funcs = [\D0 D1 -> (FLINV D0 8 EK, D1),
|
|
\D0 D1 -> (D0, FLINV D1 9 EK),
|
|
\D0 D1 -> (D0 ^ (FO D1 7 EK), D1),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 6 EK)),
|
|
\D0 D1 -> (FLINV D0 6 EK, D1),
|
|
\D0 D1 -> (D0, FLINV D1 7 EK),
|
|
\D0 D1 -> (D0 ^ (FO D1 5 EK), D1),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 4 EK)),
|
|
\D0 D1 -> (FLINV D0 4 EK, D1),
|
|
\D0 D1 -> (D0, FLINV D1 5 EK),
|
|
\D0 D1 -> (D0 ^ (FO D1 3 EK), D1),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 2 EK)),
|
|
\D0 D1 -> (FLINV D0 2 EK, D1),
|
|
\D0 D1 -> (D0, FLINV D1 3 EK),
|
|
\D0 D1 -> (D0 ^ (FO D1 1 EK), D1),
|
|
\D0 D1 -> (D0, D1 ^ (FO D0 0 EK)),
|
|
\D0 D1 -> (FLINV D0 0 EK, D1),
|
|
\D0 D1 -> (D0, FLINV D1 1 EK)
|
|
]
|
|
|
|
//
|
|
// Helper functions
|
|
//
|
|
|
|
extend : {total, n} (fin total, fin n, total >= n) => [n] -> [total]
|
|
extend n = zero # n
|
|
|
|
isEven : {a} (fin a) => [a] -> Bool
|
|
isEven n = ~(n ! zero)
|
|
|
|
//
|
|
// Examples
|
|
//
|
|
|
|
property testMisty1Encrypt = [ misty1Encrypt block EK
|
|
| block <- plaintext
|
|
] == ciphertext
|
|
where EK = keySchedule key
|
|
key = [0x00, 0x11 .. 0xff]
|
|
plaintext = [0x0123456789abcdef, 0xfedcba9876543210]
|
|
ciphertext = [0x8b1da5f56ab3d07c, 0x04b68240b13be95d]
|
|
|
|
property misty1Correct pt key = misty1Decrypt (misty1Encrypt pt EK) EK == pt
|
|
where EK = keySchedule key
|