Skip to content

Instantly share code, notes, and snippets.

@rmmh
Last active December 13, 2015 23:19
Show Gist options
  • Save rmmh/4991108 to your computer and use it in GitHub Desktop.
Save rmmh/4991108 to your computer and use it in GitHub Desktop.
DCPU16 Hummingbird-2 Implementation
SET A, plain
SET B, 8
SET C, key
SET X, iv
JSR crypt_hummingbird2_enc
SET A, plain
SET B, 8
SET C, key
SET X, iv
JSR crypt_hummingbird2_dec
SET A, A
SET PC, 0
dat 0
:key dat 0x2301, 0x6745, 0xAB89, 0xEFCD, 0xDCFE, 0x98BA, 0x5476, 0x1032
dat 0
:iv dat 0x3412, 0x7856, 0xBC9A, 0xF0DE
dat 0
:plain dat 0x1100, 0x3322, 0x5544, 0x7766, 0x9988, 0xBBAA, 0xDDCC, 0xFFEE
dat 0
; Hummingbird-2 Lightweight Authenticated Encryption
; ( http://eprint.iacr.org/2011/126.pdf )
; In: A = address of message to encrypt/decrypt
; B = number of words to encrypt/decrypt
; C = address of 128-bit key
; X = address of 64-bit nonce
:crypt_hummingbird2_enc
SET PUSH, I
SET PUSH, J
SET PUSH, Y
SET PUSH, Z
SUB SP, 8 ; allocate 128-bit round state
SET Y, SP
ADD B, A
SET PUSH, B
SET PUSH, A
jsr _hum2_init
SET X, POP
:_hum2_encrypt_iter
SET A, [X] ; A = Plaintext Word
; t1 = WD16(R1 + P, K1, K2, K3, K4)
SET PUSH, [C+3] ; K4
SET PUSH, [C+2] ; K3
SET PUSH, [C+1] ; K2
SET PUSH, [C] ; K1
ADD A, [Y] ; R1 + P
JSR _hum2_wd16_ABZIJ
SET PUSH, A
; t2 = WD16(R2 + t1, K5 ^ R5, K6 ^ R6, K7 ^ R7, K8 ^ R8)
SET I, C
ADD I, 7
SET J, Y
ADD J, 8
STD PUSH, [I] ; K8 ^ R8
XOR PEEK, [J]
STD PUSH, [I] ; K7 ^ R7
XOR PEEK, [J]
STD PUSH, [I] ; K6 ^ R6
XOR PEEK, [J]
STD PUSH, [I] ; K5 ^ R5
XOR PEEK, [J]
ADD A, [Y+1] ; R2 + t1
JSR _hum2_wd16_ABZIJ
SET PUSH, A
; t3 = WD16(R3 + t2, K1 ^ R5, K2 ^ R6, K3 ^ R7, K4 ^ R8)
SET I, C
ADD I, 3
SET J, Y
ADD J, 8
STD PUSH, [I] ; K4 ^ R8
XOR PEEK, [J]
STD PUSH, [I] ; K3 ^ R7
XOR PEEK, [J]
STD PUSH, [I] ; K2 ^ R6
XOR PEEK, [J]
STD PUSH, [I] ; K1 ^ R5
XOR PEEK, [J]
ADD A, [Y+2] ; R3 + t2
JSR _hum2_wd16_ABZIJ
SET PUSH, A
; C = WD16(R4 + t3, K5, K6, K7, K8) + R1
SET PUSH, [C+7] ; K8
SET PUSH, [C+6] ; K7
SET PUSH, [C+5] ; K6
SET PUSH, [C+4] ; K5
ADD A, [Y+3] ; R4 + t3
JSR _hum2_wd16_ABZIJ
ADD A, [Y]
SET [X], A ; write back ciphertext
JSR _hum2_update_AB
ADD X, 1
IFN X, PEEK
SET PC, _hum2_encrypt_iter
SET B, POP
ADD SP, 8
SET Z, POP
SET Y, POP
SET J, POP
SET I, POP
SET PC, POP
; Decryption is simply encryption in reverse
:crypt_hummingbird2_dec
SET PUSH, I
SET PUSH, J
SET PUSH, Y
SET PUSH, Z
SUB SP, 8 ; allocate 128-bit round state
SET Y, SP
ADD B, A
SET PUSH, B
SET PUSH, A
jsr _hum2_init
SET X, POP
:_hum2_dec_iter
SET A, [X] ; A = Plaintext Word
; enc: C = WD16(R4 + t3, K5, K6, K7, K8) + R1
; dec: t3 = WD16inv(C - R1, K8, K7, K6, K5) - R4
SUB A, [Y]
SET PUSH, [C+4] ; K5
SET PUSH, [C+5] ; K6
SET PUSH, [C+6] ; K7
SET PUSH, [C+7] ; K8
JSR _hum2_wd16inv_ABZIJ
SUB A, [Y+3] ; - R4
SET PUSH, A ; t3
; enc: t3 = WD16(R3 + t2, K1 ^ R5, K2 ^ R6, K3 ^ R7, K4 ^ R8)
; dec: t2 = WD16inv(t3, K4 ^ R8, K3 ^ R7, K2 ^ R6, K1 ^ R5) - R3
SET I, C
SET J, Y
ADD J, 3
STI PUSH, [I] ; K1 ^ R5
XOR PEEK, [J]
STI PUSH, [I] ; K2 ^ R6
XOR PEEK, [J]
STI PUSH, [I] ; K3 ^ R7
XOR PEEK, [J]
STI PUSH, [I] ; K4 ^ R8
XOR PEEK, [J]
JSR _hum2_wd16inv_ABZIJ
SUB A, [Y+2] ; - R3
SET PUSH, A ; t2
; enc: t2 = WD16(R2 + t1, K5 ^ R5, K6 ^ R6, K7 ^ R7, K8 ^ R8)
; dec: t1 = WD16inv(t2, K8 ^ R8, K7 ^ R7, K6 ^ R6, K5 ^ R5) - R2
SET I, C
ADD I, 4
SET J, Y
ADD J, 3
STI PUSH, [I] ; K5 ^ R5
XOR PEEK, [J]
STI PUSH, [I] ; K6 ^ R6
XOR PEEK, [J]
STI PUSH, [I] ; K7 ^ R7
XOR PEEK, [J]
STI PUSH, [I] ; K8 ^ R8
XOR PEEK, [J]
JSR _hum2_wd16inv_ABZIJ
SUB A, [Y+1] ; - R2
SET PUSH, A ; t1
; enc: t1 = WD16(R1 + P, K1, K2, K3, K4)
; dec: P = WD16inv(t1, K4, K3, K2, K1) - R1
SET PUSH, [C] ; K1
SET PUSH, [C+1] ; K2
SET PUSH, [C+2] ; K3
SET PUSH, [C+3] ; K4
JSR _hum2_wd16inv_ABZIJ
SUB A, [Y] ; - R1
SET [X], A ; write back plaintext
; shuffle the stack around so hum2update works
; it expects SP+1 to be t3, and SP+3 to be t1
; right now that's reversed
SET A, PEEK
SET PEEK, PICK 2
SET PICK 2, A
JSR _hum2_update_AB
ADD X, 1
IFN X, PEEK
SET PC, _hum2_dec_iter
SET B, POP
ADD SP, 8
SET Z, POP
SET Y, POP
SET J, POP
SET I, POP
SET PC, POP
; Hummingbird2 Initialization:
; Clobbers ABYZIJ
; R(0) = (IV_1 .. IV_4; IV_1 .. IV_4)
:_hum2_init
SET I, Y
SET J, X
STI [I], [J]
STI [I], [J]
STI [I], [J]
STI [I], [J]
SUB J, 4
STI [I], [J]
STI [I], [J]
STI [I], [J]
STI [I], [J]
SET X, 0
:_hum2_init_iter
; t1 = WD16(R1 + i, K1, K2, K3, K4)
SET PUSH, [C+3] ; K4
SET PUSH, [C+2] ; K3
SET PUSH, [C+1] ; K2
SET PUSH, [C] ; K1
SET A, [Y] ; R1 + i
ADD A, X
JSR _hum2_wd16_ABZIJ
SET PUSH, A
; t2 = WD16(R2 + t1, K5, K6, K7, K8)
SET PUSH, [C+7] ; K8
SET PUSH, [C+6] ; K7
SET PUSH, [C+5] ; K6
SET PUSH, [C+4] ; K5
ADD A, [Y+1] ; R2 + t1
JSR _hum2_wd16_ABZIJ
SET PUSH, A
; t3 = WD16(R3 + t2, K1, K2, K3, K4)
SET PUSH, [C+3] ; K4
SET PUSH, [C+2] ; K3
SET PUSH, [C+1] ; K2
SET PUSH, [C] ; K1
ADD A, [Y+2] ; R3 + t2
JSR _hum2_wd16_ABZIJ
SET PUSH, A
; t4 = WD16(R4 + t3, K5, K6, K7, K8)
SET PUSH, [C+7] ; K8
SET PUSH, [C+6] ; K7
SET PUSH, [C+5] ; K6
SET PUSH, [C+4] ; K5
ADD A, [Y+3] ; R4 + t3
JSR _hum2_wd16_ABZIJ
; update the internal state
; R1' = (R1 + t4) <<< 3
SET I, Y
ADD [I], A
SHL [I], 3
BOR [I], EX
; R4' = (R4 + t3) <<< 1
ADD I, 3
ADD [I], POP
SHL [I], 1
BOR [I], EX
; R3' = (R3 + t2) <<< 8
SUB I, 1
ADD [I], POP
SHL [I], 8
BOR [I], EX
; R2' = (R2 + t1) >>> 1
SUB I, 1
ADD [I], POP
SHR [I], 1
BOR [I], EX
XOR [Y+4], [Y] ; R5' = R5 ^ R1'
XOR [Y+5], [Y+1] ; R6' = R6 ^ R2'
XOR [Y+6], [Y+2] ; R7' = R7 ^ R3'
XOR [Y+7], [Y+3] ; R8' = R8 ^ R4'
ADD X, 1
IFN X, 4
SET PC, _hum2_init_iter
SET PC, POP
; Hummingbird2 state update
; In: [SP+1..SP+3] = t3..t1
; Out: nothing
:_hum2_update_AB
SET B, POP ; return address
ADD [Y], POP ; R1' = R1 + t3
ADD [Y+2], POP ; R3' = R3 + t2
SET A, POP ; A = t1
ADD [Y+1], A ; R2' = R2 + t1
ADD [Y+3], [Y] ; R4' = R4 + R1 + t3 + t1
ADD [Y+3], A ; = R4 + R1' + t1
XOR [Y+4], [Y] ; R5' = R5 ^ R1'
XOR [Y+5], [Y+1] ; R6' = R6 ^ R2'
XOR [Y+6], [Y+2] ; R7' = R7 ^ R3'
XOR [Y+7], [Y+3] ; R8' = R8 ^ R4'
SET PC, B
; WD16(x,a,b,c,d) -- keyed permutation
; In: A = x
; [SP+1..SP+4] = a..d
; Out: A = result
;
; Clobbers A, B, Z, I, J
;
; WD16(x,a,b,c,d) = f(f(f(f(x^a)^b)^c)^d)
; f(x) = L(S(x))
; L(x) = x ^ (x <<< 6) ^ (x <<< 10) (<<< is left rotate)
; (note: here, | means binary concatenation, not bitwise or)
; S(x) = S12(x0 | x1) | S34(x2 | x3)
:_hum2_wd16_ABZIJ
SET Z, POP ; return address
; throughout, A is the current x value
SET I, 8 ; LOL
SET J, _hum2_wd16_fiter
:_hum2_wd16_fiter
XOR A, POP ; x ^ {a, b, c, d}
; S(x) = S12(x0 | x1) | S34(x2 | x3)
SHR A, 8 ; A = x0 | x1
SET B, EX ; B = x2 | x3
SHR B, 8
SET A, [_hum2_sbox_enc + A] ; A = S12(x0 | x1)
SHL A, 8
SET B, [_hum2_sbox_enc + B] ; B = S34(x2 | x3)
SHR B, 8
BOR A, B
; L(x) = x ^ (x <<< 6) ^ (x <<< 10)
SET B, A
SHL B, 6 ; ^ (x <<< 6)
BOR B, EX
XOR A, B
SHL B, 4 ; ^ (x <<< 10) -- already shifted 6
BOR B, EX
XOR A, B
SHR I, 1
IFN I, 0
SET PC, J
SET PC, Z ; return
; WD16Inv(r,d,c,b,a) = keyed inverse permutation
;
; In: A = r
; [SP+1..SP+4] = d..a
; Out: A = result
;
; Clobbers A, B, Z, I, J
;
; WD16inv(r,d,c,b,a) = f^-1(f^-1(f^-1(f^-1(r)^d)^c)^b)^a
; f^-1(x) = S^-1(L^-1(x))
; L^-1(x) = x ^ (x <<< 2) ^ (x <<< 4) ^ (x <<< 12) ^ (x <<< 14) (<<< is left rotate)
; S-1(x) = S12^-1(x0 | x1) | S34^-1(x2 | x3)
:_hum2_wd16inv_ABZIJ
SET Z, POP ; return address
; throughout, A is the current x value
SET I, 8 ; LOL
SET J, _hum2_wd16inv_fiter
:_hum2_wd16inv_fiter
; L^-1(x) = x ^ (x <<< 2) ^ (x <<< 4) ^ (x <<< 12) ^ (x <<< 14)
SET B, A
; ^ (x <<< 2)
SHL B, 2
BOR B, EX
XOR A, B
; ^ (x <<< 4)
SHL B, 2 ; 4 - 2
BOR B, EX
XOR A, B
; ^ (x <<< 12)
SHL B, 8 ; 12 - 4
BOR B, EX
XOR A, B
; ^ (x <<< 14)
SHL B, 2 ; 14 - 12
BOR B, EX
XOR A, B
; S-1(x) = S12^-1(x0 | x1) | S34^-1(x2 | x3)
SHR A, 8 ; A = x0 | x1
SET B, EX ; B = x2 | x3
SHR B, 8
SET A, [_hum2_sbox_dec + A] ; A = S12^-1(x0 | x1)
SHL A, 8
SET B, [_hum2_sbox_dec + B] ; B = S34^-1(x2 | x3)
SHR B, 8
BOR A, B
XOR A, POP ; x ^ {d, b, c, a}
SHR I, 1
IFN I, 0
SET PC, J
SET PC, Z ; return
; S(x) = S1(x0) | S2(x1) | S3(x2) | S4(x3)
; x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
; -----------------------------------------------------
; S1(x) 7 12 14 9 2 1 5 15 11 6 13 0 4 8 10 3
; S2(x) 4 10 1 6 8 15 7 12 3 0 14 13 5 9 11 2
; S3(x) 2 15 12 1 5 6 10 13 14 8 3 4 0 11 9 7
; S4(x) 15 4 5 8 9 7 2 1 10 3 0 14 6 12 13 11
;
; The bytes are transposed to make the code slightly faster
;
:_hum2_sbox_enc ; S34(x0 | x1) | S12(x0 | x1)
dat 0x2f74,0x247a,0x2571,0x2876,0x2978,0x277f,0x2277,0x217c,0x2a73,0x2370,0x207e,0x2e7d,0x2675,0x2c79,0x2d7b,0x2b72
dat 0xffc4,0xf4ca,0xf5c1,0xf8c6,0xf9c8,0xf7cf,0xf2c7,0xf1cc,0xfac3,0xf3c0,0xf0ce,0xfecd,0xf6c5,0xfcc9,0xfdcb,0xfbc2
dat 0xcfe4,0xc4ea,0xc5e1,0xc8e6,0xc9e8,0xc7ef,0xc2e7,0xc1ec,0xcae3,0xc3e0,0xc0ee,0xceed,0xc6e5,0xcce9,0xcdeb,0xcbe2
dat 0x1f94,0x149a,0x1591,0x1896,0x1998,0x179f,0x1297,0x119c,0x1a93,0x1390,0x109e,0x1e9d,0x1695,0x1c99,0x1d9b,0x1b92
dat 0x5f24,0x542a,0x5521,0x5826,0x5928,0x572f,0x5227,0x512c,0x5a23,0x5320,0x502e,0x5e2d,0x5625,0x5c29,0x5d2b,0x5b22
dat 0x6f14,0x641a,0x6511,0x6816,0x6918,0x671f,0x6217,0x611c,0x6a13,0x6310,0x601e,0x6e1d,0x6615,0x6c19,0x6d1b,0x6b12
dat 0xaf54,0xa45a,0xa551,0xa856,0xa958,0xa75f,0xa257,0xa15c,0xaa53,0xa350,0xa05e,0xae5d,0xa655,0xac59,0xad5b,0xab52
dat 0xdff4,0xd4fa,0xd5f1,0xd8f6,0xd9f8,0xd7ff,0xd2f7,0xd1fc,0xdaf3,0xd3f0,0xd0fe,0xdefd,0xd6f5,0xdcf9,0xddfb,0xdbf2
dat 0xefb4,0xe4ba,0xe5b1,0xe8b6,0xe9b8,0xe7bf,0xe2b7,0xe1bc,0xeab3,0xe3b0,0xe0be,0xeebd,0xe6b5,0xecb9,0xedbb,0xebb2
dat 0x8f64,0x846a,0x8561,0x8866,0x8968,0x876f,0x8267,0x816c,0x8a63,0x8360,0x806e,0x8e6d,0x8665,0x8c69,0x8d6b,0x8b62
dat 0x3fd4,0x34da,0x35d1,0x38d6,0x39d8,0x37df,0x32d7,0x31dc,0x3ad3,0x33d0,0x30de,0x3edd,0x36d5,0x3cd9,0x3ddb,0x3bd2
dat 0x4f04,0x440a,0x4501,0x4806,0x4908,0x470f,0x4207,0x410c,0x4a03,0x4300,0x400e,0x4e0d,0x4605,0x4c09,0x4d0b,0x4b02
dat 0x0f44,0x044a,0x0541,0x0846,0x0948,0x074f,0x0247,0x014c,0x0a43,0x0340,0x004e,0x0e4d,0x0645,0x0c49,0x0d4b,0x0b42
dat 0xbf84,0xb48a,0xb581,0xb886,0xb988,0xb78f,0xb287,0xb18c,0xba83,0xb380,0xb08e,0xbe8d,0xb685,0xbc89,0xbd8b,0xbb82
dat 0x9fa4,0x94aa,0x95a1,0x98a6,0x99a8,0x97af,0x92a7,0x91ac,0x9aa3,0x93a0,0x90ae,0x9ead,0x96a5,0x9ca9,0x9dab,0x9ba2
dat 0x7f34,0x743a,0x7531,0x7836,0x7938,0x773f,0x7237,0x713c,0x7a33,0x7330,0x703e,0x7e3d,0x7635,0x7c39,0x7d3b,0x7b32
:_hum2_sbox_dec ; S34^-1(x0 | x1) | S12^-1(x0 | x1)
dat 0xcab9,0xc7b2,0xc6bf,0xc9b8,0xc1b0,0xc2bc,0xccb3,0xc5b6,0xc3b4,0xc4bd,0xc8b1,0xcfbe,0xcdb7,0xcebb,0xcbba,0xc0b5
dat 0x3a59,0x3752,0x365f,0x3958,0x3150,0x325c,0x3c53,0x3556,0x3354,0x345d,0x3851,0x3f5e,0x3d57,0x3e5b,0x3b5a,0x3055
dat 0x0a49,0x0742,0x064f,0x0948,0x0140,0x024c,0x0c43,0x0546,0x0344,0x044d,0x0841,0x0f4e,0x0d47,0x0e4b,0x0b4a,0x0045
dat 0xaaf9,0xa7f2,0xa6ff,0xa9f8,0xa1f0,0xa2fc,0xacf3,0xa5f6,0xa3f4,0xa4fd,0xa8f1,0xaffe,0xadf7,0xaefb,0xabfa,0xa0f5
dat 0xbac9,0xb7c2,0xb6cf,0xb9c8,0xb1c0,0xb2cc,0xbcc3,0xb5c6,0xb3c4,0xb4cd,0xb8c1,0xbfce,0xbdc7,0xbecb,0xbbca,0xb0c5
dat 0x4a69,0x4762,0x466f,0x4968,0x4160,0x426c,0x4c63,0x4566,0x4364,0x446d,0x4861,0x4f6e,0x4d67,0x4e6b,0x4b6a,0x4065
dat 0x5a99,0x5792,0x569f,0x5998,0x5190,0x529c,0x5c93,0x5596,0x5394,0x549d,0x5891,0x5f9e,0x5d97,0x5e9b,0x5b9a,0x5095
dat 0xfa09,0xf702,0xf60f,0xf908,0xf100,0xf20c,0xfc03,0xf506,0xf304,0xf40d,0xf801,0xff0e,0xfd07,0xfe0b,0xfb0a,0xf005
dat 0x9ad9,0x97d2,0x96df,0x99d8,0x91d0,0x92dc,0x9cd3,0x95d6,0x93d4,0x94dd,0x98d1,0x9fde,0x9dd7,0x9edb,0x9bda,0x90d5
dat 0xea39,0xe732,0xe63f,0xe938,0xe130,0xe23c,0xec33,0xe536,0xe334,0xe43d,0xe831,0xef3e,0xed37,0xee3b,0xeb3a,0xe035
dat 0x6ae9,0x67e2,0x66ef,0x69e8,0x61e0,0x62ec,0x6ce3,0x65e6,0x63e4,0x64ed,0x68e1,0x6fee,0x6de7,0x6eeb,0x6bea,0x60e5
dat 0xda89,0xd782,0xd68f,0xd988,0xd180,0xd28c,0xdc83,0xd586,0xd384,0xd48d,0xd881,0xdf8e,0xdd87,0xde8b,0xdb8a,0xd085
dat 0x2a19,0x2712,0x261f,0x2918,0x2110,0x221c,0x2c13,0x2516,0x2314,0x241d,0x2811,0x2f1e,0x2d17,0x2e1b,0x2b1a,0x2015
dat 0x7aa9,0x77a2,0x76af,0x79a8,0x71a0,0x72ac,0x7ca3,0x75a6,0x73a4,0x74ad,0x78a1,0x7fae,0x7da7,0x7eab,0x7baa,0x70a5
dat 0x8a29,0x8722,0x862f,0x8928,0x8120,0x822c,0x8c23,0x8526,0x8324,0x842d,0x8821,0x8f2e,0x8d27,0x8e2b,0x8b2a,0x8025
dat 0x1a79,0x1772,0x167f,0x1978,0x1170,0x127c,0x1c73,0x1576,0x1374,0x147d,0x1871,0x1f7e,0x1d77,0x1e7b,0x1b7a,0x1075
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment