RC5 Block Cipher

Introduction

RC5 is a 64-bit block cipher with support for 128-bit keys. It was designed in 1994 by Ronald Rivest and licensed by RSA security. As of 2019, the patent has expired. It is one of the earliest examples of an add-rotate-xor (ARX) construction being used in a cipher. 12-round RC5 (with 64-bit blocks) is susceptible to a differential attack using 2^{44} chosen plaintexts. 20 rounds are suggested as sufficient protection.

Compact code

The following function combines key scheduling and encryption in one call. This is obviously slower that seperating the two. mk should point to a 128-bit master key. data should point to a 64-bit block of plaintext to be encrypted.

#define RC5_R 12
#define RC5_K (2*(RC5_R+1))

void rc5(void *mk, void *data) {
    W A=0xB7E15163,B,i,*k,X,S[RC5_K],L[4],*x=data,*K=mk;

    // copy 128-bit key to local buffer
    F(i,4)L[i]=K[i];
    
    // initialize S
    F(i,RC5_K)S[i]=A,A+=0x9E3779B9;
    A=B=0; k=S;
    
    // create subkeys
    F(i,RC5_K*3)
      A=S[i%RC5_K]=R(S[i%RC5_K]+(A+B),3),
      B=L[i%4]=R(L[i%4]+(A+B),(A+B));
    
    // add first two subkeys to 64-bits of plaintext
    A=x[0]+*k++;B=x[1]+*k++;
    // do 12 rounds on each 32-bit word
    F(i,RC5_K-2)X=R(A^B,B&255)+*k++,A=B,B=X;
    // store ciphertext
    x[0]=A; x[1]=B;
}

x86 assembly

; -----------------------------------------------
; RC5 in x86 assembly (just encryption)
;
; https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf
;
; size: 120 bytes for single call
;
; global calls use cdecl convention
;
; -----------------------------------------------

  bits 32
  
  %ifndef BIN
    global rc5
    global _rc5
  %endif

  %define RC5_R 12            ; 20 to increase strength of cipher
  %define RC5_K (2*(RC5_R+1)) ; how many sub keys required
  
; rc5(void *mk, void *data) 
_rc5:
rc5:
    pushad
    mov    esi, [esp+32+4]    ; esi = mk
    mov    ebx, [esp+32+8]    ; ebx = data
    xor    ecx, ecx           ; ecx = 0
    mov    cl, RC5_K*4+16     ; L[4], S[26]
    sub    esp, ecx           ; esp = S
    ; copy 128-bit key to local buffer
    ; F(i,4)L[i]=K[i];
    mov    edi, esp           ; edi = L[4]
    mov    cl, 4
    rep    movsd
    ; initialize S
    ; F(i,RC5_K)S[i]=A,A+=0x9E3779B9;
    push   edi                 ; save S
    mov    eax, 0xB7E15163     ; eax = P
    mov    cl, RC5_K    
r5_L0:
    stosd                      ; S[i] = A
    add    eax, 0x9E3779B9     ; A += Q
    loop   r5_L0
    pop    edi                 ; restore S
    ; A = B = 0; k=S;
    mov    esi, ebx            ; esi = data
    mul    ecx                 ; eax = 0, edx = 0
    xor    ebx, ebx            ; ebx = 0
    ; F(i,RC5_K*3)
r5_L1:    
    xor    ebp, ebp            ; i % 26    
r5_L2:
    cmp    ebp, RC5_K
    je     r5_L1    

    ; A=S[i%RC5_K]=R(S[i%RC5_K]+(A+B),3) 
    add    eax, ebx            ; A += B
    add    eax, [edi+ebp*4]    ; A += S[i%26]
    rol    eax, 3              ; A  = R(A, 3)
    mov    [edi+ebp*4], eax    ; S[i%26] = A
    
    ; B=L[i% 4]=R(L[i%4]+(A+B),(A+B))
    add    ebx, eax            ; B += A
    mov    ecx, ebx            ; save A+B in ecx
    push   edx                 ; save i
    and    dl, 3               ; %= 4
    add    ebx, [edi+edx*4-16] ; B += L[i%4]    
    rol    ebx, cl             ; B = ROTL32(B, A+B)
    mov    [edi+edx*4-16], ebx ; L[i%4] = B    
    pop    edx                 ; restore i    
    inc    ebp
    inc    edx                 ; i++
    cmp    dl, RC5_K*3
    jnz    r5_L2    
    
    ; A=x[0]+*k++;B=x[1]+*k++;
    push   esi                 ; save ptr to data    
    lodsd                      ; A = x[0] + *k++;
    add    eax, [edi]
    scasd
    xchg   eax, ebx            ; X(A, B);
    lodsd                      ; A = x[1]
    mov    dl, RC5_K - 1   
    jmp    r5_L4
r5_L3:
    ; F(i,RC5_K-2)X=R(A^B,B&255)+*k++,A=B,B=X;
    xor   eax, ebx             ; A ^= B 
    mov   ecx, ebx             ; ecx = B 
    rol   eax, cl              ; A = R(A ^ B, B)
r5_L4:     
    add   eax, [edi]           ; A += *k; k++;
    scasd
    xchg  eax, ebx             ; X(A, B);
    dec   edx
    jnz   r5_L3    
    
    pop   esp                  ; restore ptr to data    
    xchg  esp, edi
    ; store ciphertext
    ; x[0]=A; x[1]=B;
    stosd                      ; x[0] = A
    xchg  eax, ebx
    stosd                      ; x[1] = B         
    popad
    ret

Sources here.

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