mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-13 12:01:16 +03:00
309 lines
11 KiB
Plaintext
309 lines
11 KiB
Plaintext
// 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.
|
|
//
|
|
// Use a solver other than CVC4; Z3 and Boolector do it quickly.
|
|
property ZUC_isResistantToCollisionAttack k iv1 iv2 =
|
|
if iv1 != iv2
|
|
then InitializeZUC (k, iv1) @ 1 != InitializeZUC (k, iv2) @ 1
|
|
else True
|