wiki:DSC-Reversing

Reversing the DECT Standard Cipher

The DECT Standard Cipher is a stream cipher used by DECT devices to encrypt communications.

Currently, we assume that the algorithm is implemented in a chip used on the COM-ON-AIR PCMCIA Type II and Type III cards, and that it looks like this:

sc14421 chipshot dsc

DSC Implementation

We managed to reverse engineer the cipher completely. Here is a C implementation:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define R1_LEN                  17
#define R2_LEN                  19
#define R3_LEN                  21
#define R4_LEN                  23

#define R1_MASK                 0x010020 /* tap bits: 5, 16 */
#define R2_MASK                 0x04100C /* tap bits: 2, 3, 12, 18 */
#define R3_MASK                 0x100002 /* tap bits: 1, 20 */
#define R4_MASK                 0x400100 /* tap bits: 8, 22 */

#define R1_CLKBIT               8
#define R2_CLKBIT               9
#define R3_CLKBIT               10
#define R1_R4_CLKBIT            0
#define R2_R4_CLKBIT            1
#define R3_R4_CLKBIT            2

#define OUTPUT_LEN              90 /* 720 bits */
#define TESTBIT(R, n)           (((R) & (1 << (n))) != 0)

uint32_t clock(uint32_t lfsr, uint32_t mask) {
  return (lfsr >> 1) ^ (-(lfsr&1)&mask);
}

uint32_t combine(uint32_t c, uint32_t r1, uint32_t r2, uint32_t r3) {
  uint32_t x10, x11, x20, x21, x30, x31;

  x10 = r1 & 1;
  x11 = (r1 >> 1) & 1;
  x20 = r2 & 1;
  x21 = (r2 >> 1) & 1;
  x30 = r3 & 1;
  x31 = (r3 >> 1) & 1;

  return ((x11&x10&c) ^ (x20&x11&x10) ^ (x21&x10&c) ^ (x21&x20&x10) ^ 
          (x30&x10&c) ^ (x30&x20&x10) ^ (x11&c) ^ (x11&x10) ^ (x20&x11) ^ 
          (x30&c) ^ (x31&c) ^ (x31&x10) ^ (x21) ^ (x31));
}

void dsc_keystream(uint8_t *key, uint32_t iv, uint8_t *output) {

  uint8_t input[16];
  uint32_t R1, R2, R3, R4, N1, N2, N3, COMB;
  int i, keybit;

  memset(output, 0, OUTPUT_LEN);

  input[0] = iv&0xff;
  input[1] = (iv>>8)&0xff;
  input[2] = (iv>>16)&0xff;
  for (i = 3; i < 8; i++) {
        input[i] = 0;
  }
  for (i = 0; i < 8; i++) {
        input[i+8] = key[i];
  }
        
  R1 = R2 = R3 = R4 = COMB = 0;

  /* load IV || KEY */
  for (i = 0; i < 128; i++) {
    keybit = (input[i/8] >> ((i)&7)) & 1;
    R1 = clock(R1, R1_MASK) ^ (keybit<<(R1_LEN-1));
    R2 = clock(R2, R2_MASK) ^ (keybit<<(R2_LEN-1));
    R3 = clock(R3, R3_MASK) ^ (keybit<<(R3_LEN-1));
    R4 = clock(R4, R4_MASK) ^ (keybit<<(R4_LEN-1));
  }

  for (i = 0; i < 40 + (OUTPUT_LEN*8); i++) {
    /* check whether any registers are zero after 11 pre-ciphering steps.
     * if a register is all-zero after 11 steps, set input bit to one
     * (see U.S. patent 5608802)
     */
    if (i == 11) {
      if (!R1) R1 ^= (1<<(R1_LEN-1));
      if (!R2) R2 ^= (1<<(R2_LEN-1));
      if (!R3) R3 ^= (1<<(R3_LEN-1));
      if (!R4) R4 ^= (1<<(R4_LEN-1));
    }

    N1 = R1;
    N2 = R2;
    N3 = R3;
    COMB = combine(COMB, R1, R2, R3);

    if (TESTBIT(R2, R2_CLKBIT) ^ TESTBIT(R3, R3_CLKBIT) ^ 
        TESTBIT(R4, R1_R4_CLKBIT))
      N1 = clock(R1, R1_MASK);
    if (TESTBIT(R1, R1_CLKBIT) ^ TESTBIT(R3, R3_CLKBIT) ^
        TESTBIT(R4, R2_R4_CLKBIT))
      N2 = clock(R2, R2_MASK);
    if (TESTBIT(R1, R1_CLKBIT) ^ TESTBIT(R2, R2_CLKBIT) ^ 
        TESTBIT(R4, R3_R4_CLKBIT))
      N3 = clock(R3, R3_MASK);

    R1 = clock(clock(N1, R1_MASK), R1_MASK);
    R2 = clock(clock(N2, R2_MASK), R2_MASK);
    R3 = clock(clock(N3, R3_MASK), R3_MASK);

    R4 = clock(clock(clock(R4, R4_MASK), R4_MASK), R4_MASK);

    if(i >= 40) {
      output[(i-40)/8] |= ((COMB) << ( 7-((i-40)&7)));
    }
  }
}

int main(int argc, char**argv) {
  uint8_t key[8];
  uint8_t output[OUTPUT_LEN];

  if (argc != 2) {
    fprintf(stderr, "usage: %s iv\n", argv[0]);
    exit(1);
  }

  if (read(STDIN_FILENO, key, 8) < 8) {
    fprintf(stderr, "short read\n");
    exit(1);
  }

  dsc_keystream(key, atoi(argv[1]), output);
  
  write(STDOUT_FILENO, output, 2048);
  return 0;
}
Last modified 9 years ago Last modified on Feb 1, 2010, 1:55:22 AM

Attachments (2)

Download all attachments as: .zip