Threefish Block Cipher

Introduction

Threefish is a tweakable block cipher that was designed as part of the Skein cryptographic hash function submitted to the NIST SHA-3 competition in 2008. It supports block and key sizes of 256, 512, and 1024-bits. It’s designers are Niels Ferguson, Stefan Lucks, Bruce Schneier, Doug Whiting, Mihir Bellare, Tadayoshi Kohno, Jon Callas and Jesse Walker. Threefish uses an ARX(Add-Rotate-Xor) construction like ChaCha, Salsa, Speck, Chaskey, LEA and CHAM block ciphers to name a few. The choice of construction makes it suitable for a wide range of architectures and mitigates against cache timing attacks. Only Threefish-256/256 is implemented here and is not optimized for performance.

Encryption

mk should first point to a 256-bit master key followed by a 128-bit tweak value. data should point to a 256-bit block of data to be encrypted.

#define F(a,b)for(a=0;a<b;a++)
#define R(v,n)(((v)<<(n))|((v)>>(64-(n))))
typedef unsigned long long W;
typedef unsigned char B;

void threefish(void*mk, void*data) {
    W c[10],i,j,r,*x=(W*)data,t;
    
    t=0x1BD11BDAA9FC1A22ULL;
    
    // initialize key and tweak
    F(i,4)t^=c[i]=((W*)mk)[i]; c[4]=t;
    c[5]=((W*)mk)[4];c[6]=((W*)mk)[5];
    c[7]=c[5]^c[6];
    c[8]=0x203a2e190517340eULL;
    c[9]=0x20160c2125283910ULL;
    
    // apply 72 rounds
    for(i=0;;i++) {
      // add key every 4 rounds
      if((i&3)==0) {
        t=0;F(j,4)x[j]+=c[((i/4)+j)%5]+t,
        t=(j<2)?c[(((i/4)+j)%3)+5]:i/4;
      }
      if(i==72)break;
      // mixing function
      for(j=0;j<4;j+=2)
        r=((B*)c)[64+((i%8)+(j<<2))],x[j]+=x[j+1],
        x[j+1]=R(x[j+1],r),x[j+1]^=x[j];
      // permute
      t=x[1],x[1]=x[3],x[3]=t;
    }
}

AMD64 assembly

Threefish works on 64-bit integers and is therefore unsuitable for implementation on 32-bit architectures. If you are writing code for a 32-bit CPU, consider using a more suitable algorithm. Tested on 64-bit Linux. The parameters for 64-bit Windows are different.

; -----------------------------------------------
; Threefish-256/256 block cipher in AMD64 assembly (Encryption only)
;
; size: 205 bytes
;
; -----------------------------------------------

    bits 64
    
    %ifndef BIN
      global threefish
    %endif
    
threefish:
    push   rbx             ; save rbx
    push   rbp
    ; allocate 96-bytes of local memory
    push   96
    pop    rcx
    sub    rsp, rcx
    ; rbx = data
    push   rsi
    pop    rbx
    ; rsi = master key
    push   rdi
    pop    rsi
    ; rdi = &c[0]
    push   rsp
    pop    rdi
    ; copy 256-bit master key to local memory
    mov    cl, 4
    ; t = 0x1BD11BDAA9FC1A22;
    mov    rax, 0x1BD11BDAA9FC1A22
tx_L0:
    xor    rax, [rsi]       ; t ^= mk[i]
    movsq                   ; c[i] = mk[i]
    loop   tx_L0
    stosq                   ; c[4] = t
    ; copy 128-bit tweak to local memory
    mov    rax, [rsi]       ; t = mk[4]
    movsq                   ; c[5] = mk[4]
    xor    rax, [rsi]       ; t ^= mk[5]
    movsq                   ; c[6] = mk[5]
    stosq                   ; c[7] = c[5] ^ c[6]
    ; store rotational values
    ; c[8] = 0x203a2e190517340e
    mov    rax, 0x203a2e190517340e
    stosq
    ; c[9] = 0x20160c2125283910
    mov    rax, 0x20160c2125283910
    stosq
    push   rsp
    pop    rsi              ; rsi = &c[0]
    ; apply 72 rounds
    ; i=0
    xchg   eax, ecx
tf_main:
    ; add key every 4 rounds
    ; if (!(i & 3))
    test   al, 3
    je     add_key
tf_end:
    cdq                             ; j = 0
    cmp    al, 72                   ; if(i==72) break;
    jne    tf_mix
    
    add    rsp, 96
    pop    rbp
    pop    rbx
    ret
tf_mix:
    ; r=((B*)c)[8+(i%8)+(j<<2)], x[j] += x[j+1],
    mov    ecx, eax                 ; ecx = i % 8
    and    ecx, 7
    lea    ecx, [ecx+4*edx]         ; ecx += (j<<2)
    movzx  ecx, byte[rsi+rcx+64]    ; set r
    
    mov    rdi, [rbx+8*rdx+8]       ; rdi = x[j+1]
    add    [rbx+8*rdx], rdi         ; x[j] += rdi
    
    ; x[j+1] = R(x[j+1], r), x[j+1] ^= x[j];
    rol    rdi, cl                  ; rdi = R(rdi, cl)
    xor    rdi, [rbx+8*rdx]         ; rdi ^= x[j]
    mov    [rbx+8*rdx+8], rdi         ; x[j+1] = rdi
    
    add    dl, 2                    ; j += 2
    cmp    dl, 4                    ; j < 4
    jne    tf_mix
    
    ; permute
    ; t=x[1],x[1]=x[3],x[3]=t;
    mov    rdi, [rbx+8*1]           ;
    xchg   [rbx+8*3], rdi           ; X(x[1], x[3])
    mov    [rbx+8*1], rdi           ; 
    
    inc    al                       ; i++
    jmp    tf_main
    ; create subkey and add to block
add_key:
    xor    ecx, ecx                 ; j = 0
    xor    edi, edi                 ; t = 0
ak_L0:
    push   rax                      ; save i
    shr    eax, 2                   ; i /= 4
    push   rax                      ; save i/4
    ; x[j] += c[((i/4) + j) % 5] + t
    add    eax, ecx                 ; rax = (i/4) + j
    push   rax                      ; save (i/4) + j
    cdq                             ; rdx = 0
    push   5
    pop    rbp
    div    ebp                      ; 
    mov    rax, [rsi+8*rdx]         ; rax = c[(((i/4)+j)%5] 
    add    rax, rdi                 ; rax += t
    add    [rbx+8*rcx], rax         ; x[j] += rax
    ; t = (j < 2) ? c[(((i/4)+j) % 3) + 5] : i/4
    pop    rax                      ; restore (i/4) + j
    cdq
    push   3
    pop    rbp
    div    ebp
    pop    rdi                      ; restore i/4
    pop    rax                      ; restore i
    cmp    cl, 2                   
    cmovb  rdi, [rsi+8*rdx+5*8]     ; (j<2)
    inc    cl
    cmp    cl, 4
    jne    ak_L0
    jmp    tf_end
    

sources here.

Advertisements
This entry was posted in assembly, cryptography, encryption, programming and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s