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.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s