Skip to content

Instantly share code, notes, and snippets.

@ryancdotorg
Last active January 10, 2020 03:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryancdotorg/52e9c5d0301a409da868ac9b40aa3157 to your computer and use it in GitHub Desktop.
Save ryancdotorg/52e9c5d0301a409da868ac9b40aa3157 to your computer and use it in GitHub Desktop.
SipHash-2-4 in x86_64 assembly, hand optimized for size
// SipHash-2-4 in x86_64 assembly, hand optimized for size (183 bytes)
// Written by Ryan Castellucci
// Disclaimer: Don't use this.
.global siphash
.global end_siphash
.text
// uint64_t siphash(const void *src, uint32_t src_sz, const uint8_t key[16])
// %rdi = src, %rsi = src_sz, %rdx = key
siphash:
// initialize the internal state
movabs $0x736f6d6570736575,%r8
movabs $0x646f72616e646f6d,%r9
movabs $0x6c7967656e657261,%rcx
movabs $0x7465646279746573,%rax
// v0 ^= k0; v2 ^= k2
xor (%rdx), %r8
xor (%rdx), %rcx
// v1 ^= k1; v3 ^= k1
xor 8(%rdx), %r9
xor 8(%rdx), %rax
// we no longer need the key address
// push b (sz << 56) on the stack for later
mov %esi, %edx
shl $56, %rdx
push %rdx
siphash_blocks:
// set count for siphash_rounds (we will be back here before loop exit)
mov $2, %dl
// exit loop once sz < 8
cmp $7, %esi
jbe siphash_bytes_entry
// v3 ^= *in
xor (%rdi), %rax
// siphash_rounds(2), dl set above
callq siphash_rounds
// v0 ^= *in
xor (%rdi), %r8
// sz -= 8; *in +=8
sub $8, %esi
add $8, %rdi
jmp siphash_blocks
siphash_bytes:
// copy a byte of message data to the stack
mov (%rdi,%rsi,1),%dh
mov %dh,(%rsp,%rsi,1)
siphash_bytes_entry:
// t is (%rsp)
dec %esi
// sign bit will be set when we underflow
jns siphash_bytes
// we no longer need rdi or rsi
siphash_finalize:
// pop b off the stack
pop %rdi
// v3 ^= b
xor %rdi, %rax
// siphash_rounds(2) dl set at top of siphash_blocks
callq siphash_rounds
// safe to use rdx again
// v0 ^= b
xor %rdi, %r8
// v2 ^= 0xff
xor $0xff, %cl
// siphash_rounds(4)
mov $4, %dl
callq siphash_rounds
// produce output
xor %r8, %rax
xor %r9, %rax
xor %rcx, %rax
// return
retq
// do %dl full rounds of siphash
siphash_rounds:
// half round, a=r8, b=r9, c=rcx, d=rax, s=13, t=16
add %r9, %r8
add %rax, %rcx
rol $13, %r9
xor %r8, %r9
rol $16, %rax
xor %rcx, %rax
rol $32, %r8
// half round a=rcx, b=r9, c=r8, d=rax, s=17, t=21
add %r9, %rcx
add %rax, %r8
rol $17, %r9
xor %rcx, %r9
rol $21, %rax
xor %r8, %rax
rol $32, %rcx
dec %dl
jnz siphash_rounds
retq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment