add benchmark sources

This commit is contained in:
Adam C. Foltzer 2015-08-12 14:41:44 -07:00
parent 4e6dcaa026
commit 32e55cc11f
2 changed files with 558 additions and 0 deletions

250
bench/data/AES.cry Normal file
View File

@ -0,0 +1,250 @@
// Cryptol AES Implementation
// Copyright (c) 2010-2013, Galois Inc.
// www.cryptol.net
// You can freely use this source code for educational purposes.
// This is a fairly close implementation of the FIPS-197 standard:
// http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
// Nk: Number of blocks in the key
// Must be one of 4 (AES128), 6 (AES192), or 8 (AES256)
// Aside from this line, no other code below needs to change for
// implementing AES128, AES192, or AES256
module AES where
type AES128 = 4
type AES192 = 6
type AES256 = 8
type Nk = AES128
// For Cryptol 2.x | x > 0
// NkValid: `Nk -> Bit
// property NkValid k = (k == `AES128) || (k == `AES192) || (k == `AES256)
// Number of blocks and Number of rounds
type Nb = 4
type Nr = 6 + Nk
type AESKeySize = (Nk*32)
// Helper type definitions
type GF28 = [8]
type State = [4][Nb]GF28
type RoundKey = State
type KeySchedule = (RoundKey, [Nr-1]RoundKey, RoundKey)
// GF28 operations
gf28Add : {n} (fin n) => [n]GF28 -> GF28
gf28Add ps = sums ! 0
where sums = [zero] # [ p ^ s | p <- ps | s <- sums ]
irreducible = <| x^^8 + x^^4 + x^^3 + x + 1 |>
gf28Mult : (GF28, GF28) -> GF28
gf28Mult (x, y) = pmod(pmult x y) irreducible
gf28Pow : (GF28, [8]) -> GF28
gf28Pow (n, k) = pow k
where sq x = gf28Mult (x, x)
odd x = x ! 0
pow i = if i == 0 then 1
else if odd i
then gf28Mult(n, sq (pow (i >> 1)))
else sq (pow (i >> 1))
gf28Inverse : GF28 -> GF28
gf28Inverse x = gf28Pow (x, 254)
gf28DotProduct : {n} (fin n) => ([n]GF28, [n]GF28) -> GF28
gf28DotProduct (xs, ys) = gf28Add [ gf28Mult (x, y) | x <- xs
| y <- ys ]
gf28VectorMult : {n, m} (fin n) => ([n]GF28, [m][n]GF28) -> [m]GF28
gf28VectorMult (v, ms) = [ gf28DotProduct(v, m) | m <- ms ]
gf28MatrixMult : {n, m, k} (fin m) => ([n][m]GF28, [m][k]GF28) -> [n][k]GF28
gf28MatrixMult (xss, yss) = [ gf28VectorMult(xs, yss') | xs <- xss ]
where yss' = transpose yss
// The affine transform and its inverse
xformByte : GF28 -> GF28
xformByte b = gf28Add [b, (b >>> 4), (b >>> 5), (b >>> 6), (b >>> 7), c]
where c = 0x63
xformByte' : GF28 -> GF28
xformByte' b = gf28Add [(b >>> 2), (b >>> 5), (b >>> 7), d] where d = 0x05
// The SubBytes transform and its inverse
SubByte : GF28 -> GF28
SubByte b = xformByte (gf28Inverse b)
SubByte' : GF28 -> GF28
SubByte' b = sbox@b
SubBytes : State -> State
SubBytes state = [ [ SubByte' b | b <- row ] | row <- state ]
InvSubByte : GF28 -> GF28
InvSubByte b = gf28Inverse (xformByte' b)
InvSubBytes : State -> State
InvSubBytes state =[ [ InvSubByte b | b <- row ] | row <- state ]
// The ShiftRows transform and its inverse
ShiftRows : State -> State
ShiftRows state = [ row <<< shiftAmount | row <- state
| shiftAmount <- [0 .. 3]
]
InvShiftRows : State -> State
InvShiftRows state = [ row >>> shiftAmount | row <- state
| shiftAmount <- [0 .. 3]
]
// The MixColumns transform and its inverse
MixColumns : State -> State
MixColumns state = gf28MatrixMult (m, state)
where m = [[2, 3, 1, 1],
[1, 2, 3, 1],
[1, 1, 2, 3],
[3, 1, 1, 2]]
InvMixColumns : State -> State
InvMixColumns state = gf28MatrixMult (m, state)
where m = [[0x0e, 0x0b, 0x0d, 0x09],
[0x09, 0x0e, 0x0b, 0x0d],
[0x0d, 0x09, 0x0e, 0x0b],
[0x0b, 0x0d, 0x09, 0x0e]]
// The AddRoundKey transform
AddRoundKey : (RoundKey, State) -> State
AddRoundKey (rk, s) = rk ^ s
// Key expansion
Rcon : [8] -> [4]GF28
Rcon i = [(gf28Pow (<| x |>, i-1)), 0, 0, 0]
SubWord : [4]GF28 -> [4]GF28
SubWord bs = [ SubByte b | b <- bs ]
RotWord : [4]GF28 -> [4]GF28
RotWord [a0, a1, a2, a3] = [a1, a2, a3, a0]
NextWord : ([8],[4][8],[4][8]) -> [4][8]
NextWord(i, prev, old) = old ^ mask
where mask = if i % `Nk == 0
then SubWord(RotWord(prev)) ^ Rcon (i / `Nk)
else if (`Nk > 6) && (i % `Nk == 4)
then SubWord(prev)
else prev
ExpandKeyForever : [Nk][4][8] -> [inf]RoundKey
ExpandKeyForever seed = [ transpose g | g <- groupBy`{4} (keyWS seed) ]
keyWS : [Nk][4][8] -> [inf][4][8]
keyWS seed = xs
where xs = seed # [ NextWord(i, prev, old)
| i <- [ `Nk ... ]
| prev <- drop`{Nk-1} xs
| old <- xs
]
checkKey = take`{16} (drop`{8} (keyWS ["abcd", "defg", "1234", "5678"]))
checkKey2 = [transpose g | g <- groupBy`{4}checkKey]
ExpandKey : [AESKeySize] -> KeySchedule
ExpandKey key = (keys @ 0, keys @@ [1 .. (Nr - 1)], keys @ `Nr)
where seed : [Nk][4][8]
seed = split (split key)
keys = ExpandKeyForever seed
fromKS : KeySchedule -> [Nr+1][4][32]
fromKS (f, ms, l) = [ formKeyWords (transpose k) | k <- [f] # ms # [l] ]
where formKeyWords bbs = [ join bs | bs <- bbs ]
// AES rounds and inverses
AESRound : (RoundKey, State) -> State
AESRound (rk, s) = AddRoundKey (rk, MixColumns (ShiftRows (SubBytes s)))
AESFinalRound : (RoundKey, State) -> State
AESFinalRound (rk, s) = AddRoundKey (rk, ShiftRows (SubBytes s))
AESInvRound : (RoundKey, State) -> State
AESInvRound (rk, s) =
InvMixColumns (AddRoundKey (rk, InvSubBytes (InvShiftRows s)))
AESFinalInvRound : (RoundKey, State) -> State
AESFinalInvRound (rk, s) = AddRoundKey (rk, InvSubBytes (InvShiftRows s))
// Converting a 128 bit message to a State and back
msgToState : [128] -> State
msgToState msg = transpose (split (split msg))
stateToMsg : State -> [128]
stateToMsg st = join (join (transpose st))
// AES Encryption
aesEncrypt : ([128], [AESKeySize]) -> [128]
aesEncrypt (pt, key) = stateToMsg (AESFinalRound (kFinal, rounds ! 0))
where (kInit, ks, kFinal) = ExpandKey key
state0 = AddRoundKey(kInit, msgToState pt)
rounds = [state0] # [ AESRound (rk, s) | rk <- ks
| s <- rounds
]
// AES Decryption
aesDecrypt : ([128], [AESKeySize]) -> [128]
aesDecrypt (ct, key) = stateToMsg (AESFinalInvRound (kFinal, rounds ! 0))
where (kFinal, ks, kInit) = ExpandKey key
state0 = AddRoundKey(kInit, msgToState ct)
rounds = [state0] # [ AESInvRound (rk, s)
| rk <- reverse ks
| s <- rounds
]
sbox : [256]GF28
sbox = [
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
0x54, 0xbb, 0x16]
// Test runs:
// cryptol> aesEncrypt (0x3243f6a8885a308d313198a2e0370734, \
// 0x2b7e151628aed2a6abf7158809cf4f3c)
// 0x3925841d02dc09fbdc118597196a0b32
// cryptol> aesEncrypt (0x00112233445566778899aabbccddeeff, \
// 0x000102030405060708090a0b0c0d0e0f)
// 0x69c4e0d86a7b0430d8cdb78070b4c55a
property AESCorrect msg key = aesDecrypt (aesEncrypt (msg, key), key) == msg
// Benchmark:
type nblocks = 128
bench_data : [128 * nblocks]
bench_data = random 0
bench : [128 * nblocks] -> [128 * nblocks]
bench data = join [ aesEncrypt (block, key) | block <- split data ]
where key = 0x3243f6a8885a308d313198a2e0370734

308
bench/data/ZUC.cry Normal file
View File

@ -0,0 +1,308 @@
// Copyright (c) 2011-2015 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 = False
// 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