## SIMECK Block Cipher

### Introduction

The Simeck Family of Lightweight Block Ciphers written by Gangqiang Yang, Bo Zhu, Valentin Suder, Mark D. Aagaard, and Guang Gong was published in 2015. According to the authors, SIMECK combines the good design components of both SIMON and SPECK, in order to devise more compact and efficient block ciphers. There are three variants.

• Simeck32/64
• Simeck48/96
• Simeck64/128

Only the 64/128 version of encryption is implemented here because it has the most potential to be used in applications. Reference implementations for all variants by Bo Zhu can be found here.

### Compact code

The following combines key scheduling and encryption in one function. mk should point to a 128-bit master key while data should point to a 64-bit block of plaintext to encrypt. The value 0x938BCA3083F used for the key schedule is exactly 44 bits, and because there are 44 rounds of encryption, it’s also used as the loop counter.

```#define R(v,n)(((v)<<(n))|((v)>>(32-(n))))
#define X(a,b)(t)=(a),(a)=(b),(b)=(t)

void simeck(void*mk,void*p){
unsigned int t,k0,k1,k2,k3,l,r,*k=mk,*x=p;
unsigned long long s=0x938BCA3083F;

k0=k[0];k1=k[1];k2=k[2];k3=k[3];
r=x[0];l=x[1];

do{
r^=R(l,1)^(R(l,5)&l)^k0;
X(l,r);
t=(s&1)-4;
k0^=R(k1,1)^(R(k1,5)&k1)^t;
X(k0,k1);X(k1,k2);X(k2,k3);
} while(s>>=1);
x[0]=r; x[1]=l;
}
```

### x86 assembly

```; -----------------------------------------------
; SIMECK64/128 Block Cipher in x86 assembly
;
; size: 97 bytes
;
; global calls use cdecl convention
;
; -----------------------------------------------
bits 32

%ifndef BIN
global _simeck
%endif

_edi resd 1
_esi resd 1
_ebp resd 1
_esp resd 1
_ebx resd 1
_edx resd 1
_ecx resd 1
_eax resd 1
.size:
endstruc

%define x0 ebx
%define x1 eax

%define k0 ecx
%define k1 edx
%define k2 edi
%define k3 ebp

%define t0 esi
%define s0 dword[esp+_edi+4]
%define s1 dword[esp+_esi+4]

_simeck:
mov    edi, 0xBCA3083F
mov    esi, 0x938
mov    esi, [esp+64+4] ; esi=mk
lodsd
xchg   eax, k0
lodsd
xchg   eax, k1
lodsd
xchg   eax, k2
lodsd
xchg   eax, k3
mov    esi, [esp+64+8] ; esi=x
push   esi
lodsd
xchg   eax, x0
lodsd
sm_l0:
xor    x0, k0  ; x[0]^=k[0];
mov    t0, x1  ; x[0]^=R(x[1],1);
rol    t0, 1   ;
xor    x0, t0  ;
rol    t0, 4   ; x[0]^=(R(x[1],5)&x[1]);
and    t0, x1  ;
xor    x0, t0  ;

xchg   x0, x1  ; X(x[0],x[1]);

; t0 = (s & 1) - 4;
xor    t0, t0
shr    s1, 1
rcr    s0, 1

xor    k0, t0  ; k[0]^=t0;
mov    t0, k1  ; k[0]^=R(k[1],1);
rol    t0, 1   ;
xor    k0, t0  ;
rol    t0, 4   ; k[0]^=(R(k[1],5)&k[1]);
and    t0, k1  ;
xor    k0, t0  ;

xchg   k0, k1  ; X(k[0],k[1]);
xchg   k1, k2  ; X(k[1],k[2]);
xchg   k2, k3  ; X(x[0],k[0]);

cmp    s0, 0
jnz    sm_l0

pop    edi
xchg   eax, x0
stosd          ; x[0]=x0;
xchg   eax, x0
stosd          ; x[1]=x1;

ret
```

### ARM assembly

```//
.arm
.arch armv6
.text
.align  2

.global simeck

k  .req r0
p  .req r1

r  .req r2
l  .req r3

k0 .req r4
k1 .req r5
k2 .req r6
k3 .req r7

t0 .req r8
t1 .req r9

sx .req r10
sy .req r11

simeck:
// save registers
push   {r0-r12, lr}

// unsigned long long s=0x938BCA3083F;
ldr    sx, =#0xBCA3083F
ldr    sy, =#0x938

// k0=k[0]; k1=k[1]; k2=k[2]; k3=k[3];
ldm    k, {k0,k1,k2,k3}

// r=x[0]; l=x[1];
ldm    p, {r,l}
sm_l0:
// r ^= R(l,1) ^ (R(l,5) & l) ^ k0;
eor    t0, k0, l,ror #31
and    t1, l, l, ror #27
eor    t0, t1
mov    t1, l
eor    l, r, t0
mov    r, t1

// t1 = (s & 1) - 4;
and    t1, sx, #1
sub    t1, #4

// k0 ^= R(k1,1) ^ (R(k1,5) & k1) ^ t1;
// X(k0,k1); X(k1,k2); X(k2,k3);
eor    k0, k0, k1, ror #31
and    t0, k1, k1, ror #27
eor    t0, k0
mov    k0, k1
mov    k1, k2
mov    k2, k3
eor    k3, t0, t1

// s >>= 1
movs   sy, sy, lsr #1
movs   sx, sx, rrx
bne    sm_l0

// x[0]=r; x[1]=l;
stm    p, {r,l}
// restore registers, and return
pop    {r0-r12, pc}
```

### ARM64 / AArch64 assembly

```// SIMECK in ARM64 assembly
// 100 bytes

.arch armv8-a
.text
.global simeck

simeck:
// unsigned long long s = 0x938BCA3083F;
movz    x2, 0x083F
movk    x2, 0xBCA3, lsl 16
movk    x2, 0x0938, lsl 32

ldp     w3, w4, [x0]
ldp     w5, w6, [x0, 8]

ldp     w8, w7, [x1]
L0:
// r ^= R(l,1) ^ (R(l,5) & l) ^ k0;
eor     w9, w3, w7, ror 31
and     w10, w7, w7, ror 27
eor     w9, w9, w10
mov     w10, w7
eor     w7, w8, w9
mov     w8, w10

// t1 = (s & 1) - 4;
// k0 ^= R(k1,1) ^ (R(k1,5) & k1) ^ t1;
// X(k0,k1); X(k1,k2); X(k2,k3);
eor     w3, w3, w4, ror 31
and     w9, w4, w4, ror 27
eor     w9, w9, w3
mov     w3, w4
mov     w4, w5
mov     w5, w6
and     x10, x2, 1
sub     x10, x10, 4
eor     w6, w9, w10

// s >>= 1
lsr     x2, x2, 1
cbnz    x2, L0

// save 64-bit ciphertext
stp     w8, w7, [x1]
ret
```

Sources here.