RC5 Block Cipher

RC5 is a symmetric block cipher designed in 1994 by Ronald Rivest.

It uses 128-bit keys, processes 64-bit blocks of data using 12 rounds of encryption/decryption.

Key setup

void rc5_setkey (RC5_CTX *key, void *input)
{  
  uint32_t i, j, k, A, B, T, L[4], *kptr=(uint32_t*)input; 
  
  // initialize L with key
  for (i=0; i<4; i++) {
    L[i] = kptr[i];
  }
  
  A=RC5_P;
  
  // initialize S with constants
  for (i=0; i<RC5_KR; i++) { 
    key->S[i] = A;
    A += RC5_Q;
  }
  
  A=B=i=j=k=0;
  
  // mix with key
  for (; k < RC5_KR*3; k++) { 
    A = key->S[i] = ROTL(key->S[i] + A+B, 3);  
    B = L[j]      = ROTL(L[j] + A+B, A+B);
    
    i++;
    i %= RC5_KR;
    
    j++;
    j %= RC5_KEYLEN/4;
  } 
}

This function was originally optimized by Peter Ferrie.

%define RC5_ENCRYPT 1
%define RC5_DECRYPT 0

%define RC5_BLK_LEN 8
%define RC5_ROUNDS  12
%define RC5_KEYLEN  16

%define RC5_KR      (2*(RC5_ROUNDS+1))
%define RC5_P       0xB7E15163
%define RC5_Q       0x9E3779B9

_rc5_setkeyx:
rc5_setkey:
    pushad
    mov    eax, [esp+32+4] ; rc5 ctx
    mov    esi, [esp+32+8] ; key
    push   16
    pop    ecx
    sub    esp, ecx
    mov    edi, esp
    rep    movsb

    xchg   esi, eax
    mov    edi, esi
    
    mov    eax, RC5_P
    mov    cl, RC5_KR
sk_l1:
    stosd
    add    eax, RC5_Q
    loop   sk_l1
    
    xor    ebp, ebp    ; j=0
    xchg   ecx, eax    ; A=0
    cdq                ; B=0
    mov    ch, (-RC5_KR*3) & 255

sk_l2:
    xor    edi, edi    ; i=0
sk_l3:
    cmp    edi, RC5_KR
    je     sk_l2
    
    ; A = key->x[i] = ROTL32(key->x[i] + A+B, 3); 
    add    eax, edx
    add    eax, [esi+edi*4]
    rol    eax, 3
    mov    [esi+edi*4], eax
    ; B = L[j] = ROTL32(L[j] + A+B, A+B);
    add    edx, eax
    mov    cl, dl
    add    edx, [esp+4*ebp]
    rol    edx, cl
    mov    [esp+4*ebp], edx
    ; i++
    inc    edi 
    ; j++
    inc    ebp       
    ; j %= RC5_KEYLEN/4
    and    ebp, 3
sk_l4:
    inc    ch
    jnz    sk_l3
      
    add    esp, 16
    popad
    ret

Encryption

void rc5_crypt (RC5_CTX *key, void* input, void* output, int enc)
{
  rc5_blk *in, *out;
  uint32_t *k=(uint32_t*)key->x;
  uint32_t A, B, T, i;
  
  in=input;
  out=output;
  
  A=in->v32[0];
  B=in->v32[1];
  
  if (enc==RC5_ENCRYPT) {
    A += *k; k++;
    B += *k; k++;
  } else {
    k += RC5_KR - 1;
  }
  
  for (i=0; i<RC5_KR-2; i++)
  {
    if (enc==RC5_ENCRYPT) {
      A = ROTL32(A ^ B, B) + *k; k++;
    } else {
      B = ROTR32(B - *k, A) ^ A; k--;
    }
    // swap
    T = B;
    B = A;
    A = T;
  }
  if (enc==RC5_DECRYPT) {
    B -= *k; k--;
    A -= *k; k--;
  }
  out->v32[0]=A;
  out->v32[1]=B;
}
%define A ebx
%define B ebp
 
_rc5_cryptx:
rc5_crypt:
    pushad
    lea    esi, [esp+32+4]   
    lodsd
    push   eax               ; save rc5 ctx
    lodsd
    push   eax               ; save input
    lodsd                    ; 
    xchg   eax, edi          ; output
    lodsd
    cdq
    xchg   eax, ecx          ; enc
    pop    esi               ; esi=input
    lodsd                    ; eax = A
    xchg   eax, A
    lodsd                    ; eax = B
    xchg   eax, B
    pop    esi               ; esi=rc5 ctx
    ; -------------          ; 
    mov    dl, RC5_KR-2
    jecxz  r5_l0             ; do decryption
    lodsd
    add    A, eax
    lodsd
    add    B, eax
    jmp    r5_l2
r5_l0:
    std                      ; move backwards
    lea    esi, [esi+4*edx+4]  ; advance key to end
r5_l2:
    push   ecx
    lodsd
    ; if ecx==0 do decryption
    jecxz r5_l3
    ; A = ROTL(A^B,B) + key->x[i+2];
    xor   A, B
    mov   ecx, B
    rol   A, cl
    add   A, eax
    jmp   r5_l4
r5_l3:
    ; B = ROTR(B - key->x[i+1], A) ^ A;
    sub   B, eax
    mov   ecx, A
    ror   B, cl
    xor   B, A
r5_l4:
    xchg  A, B
    dec   edx
    pop   ecx
    jnz   r5_l2
    ; -----------
    dec   ecx
    jz    r5_l5
    ; -----------
    lodsd
    sub   B, eax
    lodsd
    sub   A, eax
r5_l5:
    cld
    xchg  eax, A
    stosd
    xchg  eax, B
    stosd
    popad
    ret

Results

See sources here

architecture size
x86 167
x64 190
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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s