**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); }