DES Block Cipher

Introduction

DES is a 64-bit block cipher with support for 56-bit keys. It was originally designed and written by a team of computer scientists working at IBM along with the NSA and published by NIST in January 1977. Although obsolete due to AES, DES continues to be used for various reasons and will not disappear anytime soon. From encryption protocols to password algorithms, DES is still part of everyday life. I searched for small versions of DES and found 1 by Christopher Hertel and another by Daniel Otte, the latter of which was modified for the C/assembly version presented here. The assembly code is currently 1,045 bytes and was joint effort between Peter Ferrie and myself.

Permutation

The bulk of DES ROM is taken up by permutation tables which are used a lot in both encryption and key scheduling.

```void permute (void *perm, void *in, void *out) {
uint8_t i, j, x, t, len;
uint8_t *p=(uint8_t*)perm;

len = *p++;

for (i=0; i<len; i++) {
t=0;
for (j=0; j<8; j++) {
x = *p++;
t <<= 1;
if ((((uint8_t*)in)[x/8]) & (0x80 >> (x & 7))) {
t |= 0x01;
}
}
((uint8_t*)out)[i]=t;
}
}
```

Key Expansion

Sixteen 48-bit round keys are created for encryption.

```void des_set_key (void *mk, uint8_t rk[128]) {
uint32_t i,r, t=0x7EFC;
uint8_t  *k, k1[8], k2[8];

// permute master key
permute(pc1,mk,k1);

// create 16 round keys
for(r=0;r<128;r+=8,t>>=1) {
permute(shiftkey,k1,k2);
k=k2;

// shift key
if(t & 1) {
permute(shiftkey,k2,k1);
k=k1;
}
permute(pc2,k,&rk[r]);
for(i=0;i<8;i++) k1[i]=k[i];
}
}
```

The F Round

This is the main function which provides diffusion by mixing input with sub keys and subsituting bytes with sbox tables.

```uint32_t des_f (uint32_t *x, w64_t *key) {
uint8_t  i, x0, x1;
uint32_t t=0;
uint8_t  *sbp;
w64_t  t0, t1;

// permute 1 half of data
permute (e_permtab, x, &t0);

// mix key with data
for (i=0; i<7; i++) {
t0.b[i] ^= key->b[i];
}

permute (splitin6bitword_permtab, &t0, &t1);
sbp=sbox;

for (i=0; i<8; ++i) {
x0   = t1.b[i];
x1   = sbp[x0 >> 1];
x1   = (x0 & 1) ? x1 & 0x0F : x1 >> 4;
t  <<= 4;
t   |= x1;
sbp += 32;
}
t = rev32(t);

permute (p_permtab, &t, &t0);
return t0.w[0];
}
```

This function only performs encryption. I would normally suggest using CTR mode, but you probably shouldn’t be using DES at all.

```// encrypt 64-bits of data
void des_enc (void *data, uint8_t ks[128]) {
int      rnd, ofs=1;
w64_t    p, *key=(w64_t*)ks;
uint32_t L, R, t;

// apply initial permutation to input
permute (ip_permtab, data, &p);

L = p.w[0]; R = p.w[1];

for (rnd=0; rnd<16; rnd++) {
L ^= des_f (&R, key);
// swap
X(L, R);
key += ofs;
}
p.w[0] = R; p.w[1] = L;

// apply inverse permutation
permute (inv_ip_permtab, &p, data);
}
```

Sources here.

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