From 4622a1d17761fba8bba5bd326f15d4e8f72e2886 Mon Sep 17 00:00:00 2001 From: "Adam C. Foltzer" Date: Thu, 4 Sep 2014 11:05:13 -0700 Subject: [PATCH] add ZUC example, translated from Cryptol 1 --- examples/ZUC.cry | 306 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 examples/ZUC.cry diff --git a/examples/ZUC.cry b/examples/ZUC.cry new file mode 100644 index 00000000..ec7ab09c --- /dev/null +++ b/examples/ZUC.cry @@ -0,0 +1,306 @@ +// Copyright (c) 2011, 2014 Galois, Inc. +// An implementation of ZUC, Version 1.5 + +// Version info: If the following variable is set to True, then we implement +// Version 1.5 of ZUC. Otherwise, version 1.4 is implemented. There are +// precisely two points in the implementation where the difference matters, +// search for occurrences of version1_5 to spot them. + +// Note that the ZUC test vectors below will not work for version 1.4, as the +// old test vectors are no longer published. + +version1_5 : Bit +version1_5 = True + +// addition in GF(2^31-1) over a list of terms +add : {a} (fin a) => [a][31] -> [31] +add xs = + sums ! 0 + where + sums = + [0] # + [plus (s, x) | s <- sums + | x <- xs] + // the binary addition specified in the note at the end of section 3.2 + plus : ([31], [31]) -> [31] + plus (a, b) = + if sab @ 0 then sab' + 1 else sab' + where + sab : [32] + sab = ((zero : [1]) # a) + ((zero : [1]) # b) + sab' : [31] + sab' = drop sab + +// The ZUC LFSR is 16 31-bit words +type LFSR = [16][31] + +// Section 3.2 +LFSRWithInitializationMode : ([31], LFSR) -> LFSR +LFSRWithInitializationMode (u, ss) = + ss @@ [1 .. 15] # [s16] + where + v = add [s <<< c | s <- ss @@ [15, 13, 10, 4, 0, 0] + | c <- [15, 17, 21, 20, 8, 0]] + vu = if version1_5 then add [v, u] else v ^ u + s16 = if vu == 0 then `0x7FFFFFFF else vu + +// Section 3.2 +LFSRWithWorkMode : LFSR -> LFSR +LFSRWithWorkMode ss = + ss @@ [1 .. 15] # [s16] + where + v = add [s <<< c | s <- ss @@ [15, 13, 10, 4, 0, 0] + | c <- [15, 17, 21, 20, 8, 0]] + s16 = if v == 0 then `0x7FFFFFFF else v + +// Section 3.3 +BitReorganization : LFSR -> [4][32] +BitReorganization ss = + [ hi s15 # lo s14 + , lo s11 # hi s9 + , lo s7 # hi s5 + , lo s2 # hi s0] + where + lo : [31] -> [16] + hi : [31] -> [16] + lo x = x @@ [15 .. 30] + hi x = x @@ [0 .. 15] + [s0, s2, s5, s7, s9, s11, s14, s15] = ss @@ [0, 2, 5, 7, 9, 11, 14, 15] + +// Section 3.4 +F : ([3][32], [2][32]) -> ([32], [2][32]) +F ([X0, X1, X2], [R1, R2]) = + (W, [R1', R2']) + where + W = (X0 ^ R1) + R2 + W1 = R1 + X1 + W2 = R2 ^ X2 + [W1H, W1L] = split W1 + [W2H, W2L] = split W2 + R1' = S (L1 (W1L # W2H)) + R2' = S (L2 (W2L # W1H)) + +// Section 3.4.1 +S : [32] -> [32] +S X = + Y0 # Y1 # Y2 # Y3 + where + [X0, X1, X2, X3] = split X + [Y0, Y1, Y2, Y3] = [S0 X0, S1 X1, S2 X2, S3 X3] + +// Example 8 +property example8 = S(0x12345678) == 0xF9C05A4E + +S0 : [8] -> [8] +S1 : [8] -> [8] +S2 : [8] -> [8] +S3 : [8] -> [8] +S0 x = S0Table @ x +S1 x = S1Table @ x +S2 = S0 +S3 = S1 + +// Table 3.1 +S0Table : [256][8] +S0Table = + [0x3E, 0x72, 0x5B, 0x47, 0xCA, 0xE0, 0x00, 0x33, 0x04, 0xD1, 0x54, + 0x98, 0x09, 0xB9, 0x6D, 0xCB, 0x7B, 0x1B, 0xF9, 0x32, 0xAF, 0x9D, + 0x6A, 0xA5, 0xB8, 0x2D, 0xFC, 0x1D, 0x08, 0x53, 0x03, 0x90, 0x4D, + 0x4E, 0x84, 0x99, 0xE4, 0xCE, 0xD9, 0x91, 0xDD, 0xB6, 0x85, 0x48, + 0x8B, 0x29, 0x6E, 0xAC, 0xCD, 0xC1, 0xF8, 0x1E, 0x73, 0x43, 0x69, + 0xC6, 0xB5, 0xBD, 0xFD, 0x39, 0x63, 0x20, 0xD4, 0x38, 0x76, 0x7D, + 0xB2, 0xA7, 0xCF, 0xED, 0x57, 0xC5, 0xF3, 0x2C, 0xBB, 0x14, 0x21, + 0x06, 0x55, 0x9B, 0xE3, 0xEF, 0x5E, 0x31, 0x4F, 0x7F, 0x5A, 0xA4, + 0x0D, 0x82, 0x51, 0x49, 0x5F, 0xBA, 0x58, 0x1C, 0x4A, 0x16, 0xD5, + 0x17, 0xA8, 0x92, 0x24, 0x1F, 0x8C, 0xFF, 0xD8, 0xAE, 0x2E, 0x01, + 0xD3, 0xAD, 0x3B, 0x4B, 0xDA, 0x46, 0xEB, 0xC9, 0xDE, 0x9A, 0x8F, + 0x87, 0xD7, 0x3A, 0x80, 0x6F, 0x2F, 0xC8, 0xB1, 0xB4, 0x37, 0xF7, + 0x0A, 0x22, 0x13, 0x28, 0x7C, 0xCC, 0x3C, 0x89, 0xC7, 0xC3, 0x96, + 0x56, 0x07, 0xBF, 0x7E, 0xF0, 0x0B, 0x2B, 0x97, 0x52, 0x35, 0x41, + 0x79, 0x61, 0xA6, 0x4C, 0x10, 0xFE, 0xBC, 0x26, 0x95, 0x88, 0x8A, + 0xB0, 0xA3, 0xFB, 0xC0, 0x18, 0x94, 0xF2, 0xE1, 0xE5, 0xE9, 0x5D, + 0xD0, 0xDC, 0x11, 0x66, 0x64, 0x5C, 0xEC, 0x59, 0x42, 0x75, 0x12, + 0xF5, 0x74, 0x9C, 0xAA, 0x23, 0x0E, 0x86, 0xAB, 0xBE, 0x2A, 0x02, + 0xE7, 0x67, 0xE6, 0x44, 0xA2, 0x6C, 0xC2, 0x93, 0x9F, 0xF1, 0xF6, + 0xFA, 0x36, 0xD2, 0x50, 0x68, 0x9E, 0x62, 0x71, 0x15, 0x3D, 0xD6, + 0x40, 0xC4, 0xE2, 0x0F, 0x8E, 0x83, 0x77, 0x6B, 0x25, 0x05, 0x3F, + 0x0C, 0x30, 0xEA, 0x70, 0xB7, 0xA1, 0xE8, 0xA9, 0x65, 0x8D, 0x27, + 0x1A, 0xDB, 0x81, 0xB3, 0xA0, 0xF4, 0x45, 0x7A, 0x19, 0xDF, 0xEE, + 0x78, 0x34, 0x60] + +// Table 3.2 +S1Table : [256][8] +S1Table = + [0x55, 0xC2, 0x63, 0x71, 0x3B, 0xC8, 0x47, 0x86, 0x9F, 0x3C, 0xDA, + 0x5B, 0x29, 0xAA, 0xFD, 0x77, 0x8C, 0xC5, 0x94, 0x0C, 0xA6, 0x1A, + 0x13, 0x00, 0xE3, 0xA8, 0x16, 0x72, 0x40, 0xF9, 0xF8, 0x42, 0x44, + 0x26, 0x68, 0x96, 0x81, 0xD9, 0x45, 0x3E, 0x10, 0x76, 0xC6, 0xA7, + 0x8B, 0x39, 0x43, 0xE1, 0x3A, 0xB5, 0x56, 0x2A, 0xC0, 0x6D, 0xB3, + 0x05, 0x22, 0x66, 0xBF, 0xDC, 0x0B, 0xFA, 0x62, 0x48, 0xDD, 0x20, + 0x11, 0x06, 0x36, 0xC9, 0xC1, 0xCF, 0xF6, 0x27, 0x52, 0xBB, 0x69, + 0xF5, 0xD4, 0x87, 0x7F, 0x84, 0x4C, 0xD2, 0x9C, 0x57, 0xA4, 0xBC, + 0x4F, 0x9A, 0xDF, 0xFE, 0xD6, 0x8D, 0x7A, 0xEB, 0x2B, 0x53, 0xD8, + 0x5C, 0xA1, 0x14, 0x17, 0xFB, 0x23, 0xD5, 0x7D, 0x30, 0x67, 0x73, + 0x08, 0x09, 0xEE, 0xB7, 0x70, 0x3F, 0x61, 0xB2, 0x19, 0x8E, 0x4E, + 0xE5, 0x4B, 0x93, 0x8F, 0x5D, 0xDB, 0xA9, 0xAD, 0xF1, 0xAE, 0x2E, + 0xCB, 0x0D, 0xFC, 0xF4, 0x2D, 0x46, 0x6E, 0x1D, 0x97, 0xE8, 0xD1, + 0xE9, 0x4D, 0x37, 0xA5, 0x75, 0x5E, 0x83, 0x9E, 0xAB, 0x82, 0x9D, + 0xB9, 0x1C, 0xE0, 0xCD, 0x49, 0x89, 0x01, 0xB6, 0xBD, 0x58, 0x24, + 0xA2, 0x5F, 0x38, 0x78, 0x99, 0x15, 0x90, 0x50, 0xB8, 0x95, 0xE4, + 0xD0, 0x91, 0xC7, 0xCE, 0xED, 0x0F, 0xB4, 0x6F, 0xA0, 0xCC, 0xF0, + 0x02, 0x4A, 0x79, 0xC3, 0xDE, 0xA3, 0xEF, 0xEA, 0x51, 0xE6, 0x6B, + 0x18, 0xEC, 0x1B, 0x2C, 0x80, 0xF7, 0x74, 0xE7, 0xFF, 0x21, 0x5A, + 0x6A, 0x54, 0x1E, 0x41, 0x31, 0x92, 0x35, 0xC4, 0x33, 0x07, 0x0A, + 0xBA, 0x7E, 0x0E, 0x34, 0x88, 0xB1, 0x98, 0x7C, 0xF3, 0x3D, 0x60, + 0x6C, 0x7B, 0xCA, 0xD3, 0x1F, 0x32, 0x65, 0x04, 0x28, 0x64, 0xBE, + 0x85, 0x9B, 0x2F, 0x59, 0x8A, 0xD7, 0xB0, 0x25, 0xAC, 0xAF, 0x12, + 0x03, 0xE2, 0xF2] + +// Section 3.4.2 +L1 : [32] -> [32] +L1 X = X ^ X <<< 2 ^ X <<< 10 ^ X <<< 18 ^ X <<< 24 + +// Section 3.4.2 +L2 : [32] -> [32] +L2 X = X ^ X <<< 8 ^ X <<< 14 ^ X <<< 22 ^ X <<< 30 + +// Section 3.5 +LoadKey : ([128], [128]) -> LFSR +LoadKey (key, iv) = + [k # d # i | k <- ks + | i <- is + | d <- ds] + where + ks : [16][8] + ks = split key + is : [16][8] + is = split iv + ds : [16][15] + ds = + [ 0b100010011010111, 0b010011010111100 + , 0b110001001101011, 0b001001101011110 + , 0b101011110001001, 0b011010111100010 + , 0b111000100110101, 0b000100110101111 + , 0b100110101111000, 0b010111100010011 + , 0b110101111000100, 0b001101011110001 + , 0b101111000100110, 0b011110001001101 + , 0b111100010011010, 0b100011110101100 + ] + +type ZUC = (LFSR, [32], [32]) + +// Return an infinite sequence of ZUC states by applying the initialization step +// repeatedly. This is a generalization of section 3.6.1 +InitializeZUC : ([128], [128]) -> [inf]ZUC +InitializeZUC (key, iv) = + outs + where + initLFSR = LoadKey (key, iv) + outs = [(initLFSR, 0, 0)] # [step out | out <- outs] + step (lfsr, R1, R2) = + (LFSRWithInitializationMode (drop (w >> 1), lfsr), R1', R2') + where + [X0, X1, X2, X3] = BitReorganization lfsr + (w', [R1', R2']) = F ([X0, X1, X2], [R1, R2]) + w = if version1_5 then w' else w' ^ X3 + +// Section 3.6.2 +WorkingStage : ZUC -> ZUC +WorkingStage (lfsr, R1, R2) = + (lfsr', R1', R2') + where + [X0, X1, X2, _] = BitReorganization lfsr + (_, [R1', R2']) = F ([X0, X1, X2], [R1, R2]) + lfsr' = LFSRWithWorkMode lfsr + +// Section 3.6.2 +ProductionStage : ZUC -> ([32], ZUC) +ProductionStage (lfsr, R1, R2) = + (w ^ X3, (lfsr', R1', R2')) + where + [X0, X1, X2, X3] = BitReorganization lfsr + (w, [R1', R2']) = F ([X0, X1, X2], [R1, R2]) + lfsr' = LFSRWithWorkMode lfsr + +// ZUC API +ZUC : [128] -> [128] -> [inf][32] +ZUC key iv = + tail [w | (w, _) <- zucs] + where + initZuc = WorkingStage (InitializeZUC (key, iv) @ 32) + zucs = [(zero, initZuc)] # [ProductionStage zuc | (_, zuc) <- zucs] + +// Test vectors +property ZUC_TestVectors = + t1 && t2 && t3 && t4 + where + t1 = take (ZUC zero zero ) == [0x27BEDE74, 0x018082DA] + t2 = take (ZUC (~zero) (~zero)) == [0x0657CFA0, 0x7096398B] + t3 = take (ZUC (join [ 0x3D, 0x4C, 0x4B, 0xE9, 0x6A, 0x82, 0xFD, 0xAE + , 0xB5, 0x8F, 0x64, 0x1D, 0xB1, 0x7B, 0x45, 0x5B + ]) + (join [ 0x84, 0x31, 0x9A, 0xA8, 0xDE, 0x69, 0x15, 0xCA + , 0x1F, 0x6B, 0xDA, 0x6B, 0xFB, 0xD8, 0xC7, 0x66 + ])) == [0x14F1C272, 0x3279C419] + t4 = take ks # [ks @ 1999] == [0xED4400E7, 0x0633E5C5, 0x7A574CDB] + where + ks = ZUC (join [ 0x4D, 0x32, 0x0B, 0xFA, 0xD4, 0xC2, 0x85, 0xBF + , 0xD6, 0xB8, 0xBD, 0x00, 0xF3, 0x9D, 0x8B, 0x41 + ]) + (join [ 0x52, 0x95, 0x9D, 0xAB, 0xA0, 0xBF, 0x17, 0x6E + , 0xCE, 0x2D, 0xC3, 0x15, 0x04, 0x9E, 0xB5, 0x74 + ]) + +// 3.3-3.6 of the implementor's test data document lists "LFSR-state at the +// beginning", which is immediately after running LoadKey. +property LoadKey_TestVectors = + [ LoadKey(k, iv) == lfsr0 + | k <- ks + | iv <- ivs + | lfsr0 <- lfsr0s + ] == ~0 + where + ks = [ 0 + , ~0 + , 0x3d4c4be96a82fdaeb58f641db17b455b + , 0x4d320bfad4c285bfd6b8bd00f39d8b41 + ] + ivs = [ 0 + , ~0 + , 0x84319aa8de6915ca1f6bda6bfbd8c766 + , 0x52959daba0bf176ece2dc315049eb574 + ] + lfsr0s = [ [ `0x0044d700, `0x0026bc00, `0x00626b00, `0x00135e00 + , `0x00578900, `0x0035e200, `0x00713500, `0x0009af00 + , `0x004d7800, `0x002f1300, `0x006bc400, `0x001af100 + , `0x005e2600, `0x003c4d00, `0x00789a00, `0x0047ac00 + ] + , [ `0x7fc4d7ff, `0x7fa6bcff, `0x7fe26bff, `0x7f935eff + , `0x7fd789ff, `0x7fb5e2ff, `0x7ff135ff, `0x7f89afff + , `0x7fcd78ff, `0x7faf13ff, `0x7febc4ff, `0x7f9af1ff + , `0x7fde26ff, `0x7fbc4dff, `0x7ff89aff, `0x7fc7acff + ] + , [ `0x1ec4d784, `0x2626bc31, `0x25e26b9a, `0x74935ea8 + , `0x355789de, `0x4135e269, `0x7ef13515, `0x5709afca + , `0x5acd781f, `0x47af136b, `0x326bc4da, `0x0e9af16b + , `0x58de26fb, `0x3dbc4dd8, `0x22f89ac7, `0x2dc7ac66 + ] + , [ `0x26c4d752, `0x1926bc95, `0x05e26b9d, `0x7d135eab + , `0x6a5789a0, `0x6135e2bf, `0x42f13517, `0x5f89af6e + , `0x6b4d78ce, `0x5c2f132d, `0x5eebc4c3, `0x001af115 + , `0x79de2604, `0x4ebc4d9e, `0x45f89ab5, `0x20c7ac74 + ] + ] + + +// Collision attack on ZUC. Only version1.5 is resistant to it. Thus, the +// following theorem holds only when version1_5 is set to True. +// +// NB. We only compare the first output of the InitializeZUC sequence, as it +// cuts down on the problem size and is sufficient to ensure the iv's will be +// the same. That is, if this theorem fails, then so would the final iv's used +// by ZUC. +property ZUC_isResistantToCollisionAttack (k, iv1, iv2) = + if iv1 != iv2 + then InitializeZUC (k, iv1) @ 1 != InitializeZUC (k, iv2) @ 1 + else True