mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-11-28 17:33:13 +03:00
add benchmark sources
This commit is contained in:
parent
4e6dcaa026
commit
32e55cc11f
250
bench/data/AES.cry
Normal file
250
bench/data/AES.cry
Normal 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
308
bench/data/ZUC.cry
Normal 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
|
Loading…
Reference in New Issue
Block a user