## Bel-T Block Cipher

### Introduction

Bel-T is a 128-bit block cipher that was adopted as a standard by the Republic of Belarus in 2011 and defined in STB 34.101.31-2011. It takes 128-bits of data and encrypts using an N-bit key (where N can be 128, 192 or 256). It uses 8 rounds of a function based on the Lai-Massey scheme also used by IDEA and IDEA-NXT. There’s a key schedule procedure, but because it’s only relevant for 128 and 192-bit keys, it’s not included here. If you’re interested in the key scheduling function, you can find it in this implementation written by Philipp Jovanovic. This implementation only performs encryption and is optimized for size rather than speed.

### Compact code

```#define R(v,n)(((v)<<(n))|((v)>>(32-(n))))
#define X(u,v)t=u,u=v,v=t
#define F(n)for(i=0;i<n;i++)
typedef unsigned char B;
typedef unsigned int W;

#ifdef LUT
// sbox
B H[256] =
{ 0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B,
0x36, 0x6D, 0x00, 0x8E, 0x58, 0x4A, 0x5D, 0xE4,
0x85, 0x04, 0xFA, 0x9D, 0x1B, 0xB6, 0xC7, 0xAC,
0x25, 0x2E, 0x72, 0xC2, 0x02, 0xFD, 0xCE, 0x0D,
0x5B, 0xE3, 0xD6, 0x12, 0x17, 0xB9, 0x61, 0x81,
0xFE, 0x67, 0x86, 0xAD, 0x71, 0x6B, 0x89, 0x0B,
0x5C, 0xB0, 0xC0, 0xFF, 0x33, 0xC3, 0x56, 0xB8,
0x35, 0xC4, 0x05, 0xAE, 0xD8, 0xE0, 0x7F, 0x99,
0xE1, 0x2B, 0xDC, 0x1A, 0xE2, 0x82, 0x57, 0xEC,
0x70, 0x3F, 0xCC, 0xF0, 0x95, 0xEE, 0x8D, 0xF1,
0xC1, 0xAB, 0x76, 0x38, 0x9F, 0xE6, 0x78, 0xCA,
0xF7, 0xC6, 0xF8, 0x60, 0xD5, 0xBB, 0x9C, 0x4F,
0xF3, 0x3C, 0x65, 0x7B, 0x63, 0x7C, 0x30, 0x6A,
0xDD, 0x4E, 0xA7, 0x79, 0x9E, 0xB2, 0x3D, 0x31,
0x3E, 0x98, 0xB5, 0x6E, 0x27, 0xD3, 0xBC, 0xCF,
0x59, 0x1E, 0x18, 0x1F, 0x4C, 0x5A, 0xB7, 0x93,
0xE9, 0xDE, 0xE7, 0x2C, 0x8F, 0x0C, 0x0F, 0xA6,
0x2D, 0xDB, 0x49, 0xF4, 0x6F, 0x73, 0x96, 0x47,
0x06, 0x07, 0x53, 0x16, 0xED, 0x24, 0x7A, 0x37,
0x39, 0xCB, 0xA3, 0x83, 0x03, 0xA9, 0x8B, 0xF6,
0x92, 0xBD, 0x9B, 0x1C, 0xE5, 0xD1, 0x41, 0x01,
0x54, 0x45, 0xFB, 0xC9, 0x5E, 0x4D, 0x0E, 0xF2,
0x68, 0x20, 0x80, 0xAA, 0x22, 0x7D, 0x64, 0x2F,
0x26, 0x87, 0xF9, 0x34, 0x90, 0x40, 0x55, 0x11,
0xBE, 0x32, 0x97, 0x13, 0x43, 0xFC, 0x9A, 0x48,
0xA0, 0x2A, 0x88, 0x5F, 0x19, 0x4B, 0x09, 0xA1,
0x7E, 0xCD, 0xA4, 0xD0, 0x15, 0x44, 0xAF, 0x8C,
0xA5, 0x84, 0x50, 0xBF, 0x66, 0xD2, 0xE8, 0x8A,
0xA2, 0xD7, 0x46, 0x52, 0x42, 0xA8, 0xDF, 0xB3,
0x69, 0x74, 0xC5, 0x51, 0xEB, 0x23, 0x29, 0x21,
0xD4, 0xEF, 0xD9, 0xB4, 0x3A, 0x62, 0x28, 0x75,
0x91, 0x14, 0x10, 0xEA, 0x77, 0x6C, 0xDA, 0x1D };
#else
B H(B x) {
W i, j;
B t = 0x1d, w;

if(x==10) return 0;
if(x<10) x++;

do {
j=116;
do {
w=t&99,
w^=w>>1,w^=w>>2,w^=w>>4,
t=t>>1|w<<7;
} while(--j);
} while (--x);
return t;
}
#endif

// non-linear + linear layer
W G(W x, W *key, int idx, int r) {
W i, w;

w=key[idx%8]+x;
F(4)w=(w&-256)|
#ifdef LUT
H[w&255],
#else
H(w&255),
#endif
w=R(w,8);
return R(w, r);
}

void belt(void*mk,void*data) {
W a,b,c,d,i,j,t,e,*x=(W*)data,*k=(W*)mk;

a=x[0],b=x[1],c=x[2],d=x[3];

for(i=0,j=0;i<8;) {
b^=G(a,k,j++, 5),c^=G(d,k,j++,  21),
a-=G(b,k,j++,13),e =G(b+c,k,j++,21),
e^=++i,b+=e,c-=e,d+=G(c,k,j++,  13),
b^=G(a,k,j++,21),c^=G(d,k,j++,   5),
X(a,b),X(c,d),X(b,c);
}
x[0]=b,x[1]=d,x[2]=a,x[3]=c;
}
```

### x86 assembly

```; -----------------------------------------------
; Bel-T block cipher in x86 assembly (encryption only)
;
; size: 210 bytes
;
; global calls use cdecl convention
;
; -----------------------------------------------

bits 32

%ifndef BIN
global belt
global _belt
%endif

_edi dd ?
_esi dd ?
_ebp dd ?
_esp dd ?
_ebx dd ?
_edx dd ?
_ecx dd ?
_eax dd ?
.size:
endstruc

%define t   eax

%define a   ebx
%define b   ecx
%define c   edx
%define d   esi
%define e   edi

%define G   ebp

belt:
_belt:
mov    edi, [esp+32+4]   ; k = mk
mov    esi, [esp+32+8]   ; x = data
xor    eax, eax

push   esi               ; save x
push   eax               ; save j
push   edi               ; save k
push   eax               ; save i

lodsd
xchg   a, eax            ; a = x[0]
lodsd
xchg   b, eax            ; b = x[1]
lodsd
xchg   c, eax            ; c = x[2]
lodsd
xchg   d, eax            ; d = x[3]
call   b_L0
; ------------------------
; G function
; ------------------------
mov    esi, [esp+_esp]   ; esi=esp
lodsd                    ; edx=x
xchg   eax, edx          ;
lodsd                    ; eax=r
push   eax               ; save r
lodsd                    ; eax=i
lodsd                    ; eax=k
xchg   eax, edi          ; edi=k
lodsd                    ; eax=j
inc    dword[esi-4]      ; j++
and    eax, 7            ; j &= 7
add    edx, [edi+eax*4]  ; x += k[j&7]
mov    al, 4
g_H0:
; if (x==10) return 0;
sub    dl, 10
jz     g_H3
; if (x<10) x++;
movzx  ecx, dl
; t = 0x1d;
mov    dl, 0x1d
g_H1:
push   ecx
; j = 116;
mov    cl, 116
g_H2:
; w = t & 99;
mov    bl, dl
and    bl, 99
; w ^= (w >> 1)
mov    bh, bl
shr    bh, 1
xor    bl, bh
; w ^= (w >> 2)
mov    bh, bl
shr    bh, 2
xor    bl, bh
; w ^= (w >> 4)
mov    bh, bl
shr    bh, 4
xor    bl, bh
; t = t >> 1 | w << 7
shl    bl, 7
shr    dl, 1
or     dl, bl
loop   g_H2
pop    ecx
loop   g_H1
g_H3:
ror    edx, 8     ; u.w = ROTR(u.w, 8)
dec    eax
jnz    g_H0

pop    ecx        ; ecx=r
rol    edx, cl    ; return ROTL32(u.w, r);
mov    [esp+_eax], edx
retn   2*4
; -----------------------
b_L0:
pop    G
b_L1:
push   5
push   a
call   G
xor    b, t       ; b ^= G(a, k, j+0, 5);

push   21
push   d
call   G
xor    c, t       ; c ^= G(d, k, j+1,21);

push   13
push   b
call   G
sub    a, t       ; a -= G(b, k, j+2,13);

push   21
lea    t, [b + c]
push   t
call   G          ; e  = G(b + c, k, j+3,21);
xchg   t, e

pop    t          ; t = i
inc    t          ; i++
push   t          ; save i

xor    e, t       ; e ^= i;
add    b, e       ; b += e;
sub    c, e       ; c -= e;

push   13
push   c
call   G
add    d, t       ; d += G(c, k, j+4,13);

push   21
push   a
call   G
xor    b, t       ; b ^= G(a, k, j+5,21);

push   5
push   d
call   G
xor    c, t       ; c ^= G(d, k, j+6, 5);

xchg   a, b
xchg   c, d
xchg   b, c

pop    eax
push   eax
cmp    al, 8
jnz    b_L1

pop    eax       ; remove i
pop    eax       ; remove k
pop    eax       ; remove j
pop    edi       ; restore x

xchg   eax, b
stosd            ; x[0] = b
xchg   eax, d
stosd            ; x[1] = d
xchg   eax, a
stosd            ; x[2] = a
xchg   eax, c
stosd            ; x[3] = c