Online Presence
KapNuz - Easy News For You
Awesome Hosting Plans
Advertise Here

S-1

From CryptoDox, The Online Encyclopedia on Cryptography and Information Security

Jump to: navigation, search

S-1 was a block cipher posted in source code form on Usenet on 11 August 1995. Although incorrect security markings immediately indicated a hoax, there were several features of the code which suggested it might be leaked source code for the Skipjack encryption algorithm, which was still classified at the time.

However once David Wagner had discovered a severe design flaw, it was generally accepted as being a hoax - but one with an astonishing amount of work behind it. When Skipjack was eventually declassified in 1998, it was indeed found to be totally unlike S-1.

S-1 also was the United States's government codename for the atomic bomb. Throughout many government papers, Henry Stimson and others within the State Department referred to the bomb as S-1.

Source Code

The following code has been taken from its original Usenet posting[1]

/* TOP SECRET                                                    */
/* See label file for codeword restrictions                      */
 
/*****************************************************************/
/* TOP SECRET                                                    */
/* See label file for codeword restrictions                      */
/*                                                               */
/* S-1 CIPHER ALGORITHM software chip simulator                  */
/*                                                               */
/* NOT INTENDED FOR EXTERNAL, PRODUCTION, OR CONTRACTOR USE OR   */
/* DISCLOSURE.                                                   */
/* NOT CERTIFIED OR APPROVED FOR USE AS REFERENCE.               */
/* FOR SECONDARY ANALYTIC USE ONLY.                              */
/*                                                               */
/* Basic chip functions. Block encryption methods are not        */
/* implemented.                                                  */
/*                                                               */
/* SOFTWARE HISTORY:                                             */
/* 1 FEBRUARY 1989 --- Submitted to source control.              */
/* 31 JULY 1991 --- Moved UFV support into basic functions.      */
/*                                                               */
/* TOP SECRET                                                    */
/* See label file for codeword restrictions                      */
/*****************************************************************/
 
/* local declarations are for ANSI C */
#include <stdio.h>
#include <sys/types.h>
 
/* S-1 F table - these differ in the S-2 version */
static u_char F[4][256];
/* S-1 F selection (G) table */
static u_char G[2][256];
 
/* exported interface */
 
int S1_self_check(void);
int S1_zeroize(void);
int S1_load_key(int, u_char *);
int S1_encrypt_block(int, u_char *);
int S1_decrypt_block(int, u_char *);
int S1_create_key(u_char *, u_char *);
 
/* local functions */
static void f_initialize(void);
static void rotatekey(int, u_char *);
static u_char f(int,int);
static u_char g(int,int);
 
/* CHIP PARAMETERS */
 
#define KEYGEN_CHIP 1 /* delete this to simulate operational chipsets */
#define KEY_REGISTERS 4
#define INTEGRITY KEY_REGISTERS
 
/* user family vectors (UFV) */
static u_char clear_family[8] = {129,3,5,7,2,4,6,131};
static u_char cipher_family[8] = {1,254,253,252,128,129,130,8};
 
static u_char key_integrity_key[10] = {0,0,0,0,0,0,0,0,0,0};
 
static u_char key[KEY_REGISTERS+1][10];
static u_char fullkey[KEY_REGISTERS+1][32][6];  /* SOFTWARE ONLY */
 
static int initialized=0;
 
/* EXPORTED SIMULATED CHIP INTERFACE */
/* SEE NOTES FOR INTERFACE DESCRIPTIONS */
 
int S1_self_check()
{
        f_initialize();
        rotatekey(INTEGRITY,key_integrity_key);
        initialized=1;
        return 0;
 
}
 
int S1_zeroize()
{
        int i, j, k;
 
        i=0;
        while (i<KEY_REGISTERS+1) {
                j=0;
                while (j<10) {
                        key[i][j] = 0;
                        j=j+1;
                }
                j=0;
                while (j<32) {
                        k=0;
                        while (k<6) {
                                fullkey[i][j][k] = 0;
                                k++;
                        }
                        j=j+1;
                }
                i=i+1;
        }
        i=0;
        while (i<4) {
                j=0;
                while (j<256) {
                        F[i][j] = 0;
                        j++;
                }
                i++;
        }
        return 0;
 
}
 
int S1_load_key(int key_register, u_char *key_vector)
{
        u_char key_buffer[12];
 
        if (initialized == 0)
                return 1;
        if ((key_register < 0) || (key_register >= KEY_REGISTERS))
                return 9;
        memcpy(key_buffer,key_vector,12);
        S1_decrypt_block(INTEGRITY,key_buffer);
        S1_decrypt_block(INTEGRITY,key_buffer+4);
        if ((key_buffer[10] != 0) || (key_buffer[11] != 0))
                return 2;
        rotatekey(key_register,key_buffer);
        memcpy(key[key_register],key_buffer,10);
        return 0;
 
}
 
int S1_encrypt_block(int key_register, u_char *block)
{
        int r, startf, i;
 
        if (initialized == 0)
                return 1;
        i=0;
        while (i<8) {
                block[i] = block[i] ^ clear_family[i];
                i=i+1;
        }
        i=0;
        while (i<32) {
                r=i*2;
                startf = g(0,fullkey[key_register][r][0] ^ block[(r+4) % 8])
                       + g(1,fullkey[key_register][r][1] ^ block[(r+5) % 8])*2;
                block[(r+6) % 8] = block[(r+6) % 8]
                               ^ f(((startf+0) % 4),
                                   fullkey[key_register][r][2]
                                 ^ block[(r+2) % 8]);
                block[(r+6) % 8] = block[(r+6) % 8]
                               ^ (f(((startf+1) % 4),
                                   fullkey[key_register][r][3]
                                 ^ block[(r+3) % 8]) << 4);      
                block[(r+7) % 8] = block[(r+7) % 8]
                               ^ f(((startf+2) % 4),
                                   fullkey[key_register][r][4]
                                 ^ block[(r+0) % 8]);
                block[(r+7) % 8] = block[(r+7) % 8]
                               ^ (f(((startf+3) % 4),
                                   fullkey[key_register][r][5]
                                 ^ block[(r+1) % 8]) << 4);
                i = i+1;
        }
        i=0;
        while (i<8) {
                block[i] = block[i] ^ cipher_family[i];
                i=i+1;
        }
        return 0;
 
}
 
int S1_decrypt_block(int key_register, u_char *block)
{
        int r, startf, i;
 
        if (initialized == 0)
                return 1;
        i=0;
        while (i<8) {
                block[i] = block[i] ^ cipher_family[i];
                i=i+1;
        }
        i=32;
        while (i>0) {
                i = i-1;
                r=i*2;
                startf = g(0,fullkey[key_register][r][0] ^ block[(r+4) % 8])
                       + g(1,fullkey[key_register][r][1] ^ block[(r+5) % 8])*2;
                block[(r+6) % 8] = block[(r+6) % 8]
                               ^ f(((startf+0) % 4),
                                   fullkey[key_register][r][2]
                                 ^ block[(r+2) % 8]);
                block[(r+6) % 8] = block[(r+6) % 8]
                               ^ (f(((startf+1) % 4),
                                   fullkey[key_register][r][3]
                                 ^ block[(r+3) % 8]) << 4);      
                block[(r+7) % 8] = block[(r+7) % 8]
                               ^ f(((startf+2) % 4),
                                   fullkey[key_register][r][4]
                                 ^ block[(r+0) % 8]);
                block[(r+7) % 8] = block[(r+7) % 8]
                               ^ (f(((startf+3) % 4),
                                   fullkey[key_register][r][5]
                                 ^ block[(r+1) % 8]) << 4);
        }
        i=0;
        while (i<8) {
                block[i] = block[i] ^ clear_family[i];
                i=i+1;
        }
        return 0;
 
}
 
#ifdef KEYGEN_CHIP
/* WARNING: this feature is not implemented on all chip sets */
int S1_create_key(u_char *key_value, u_char *key_vector)
{
        if (initialized == 0)
                return 1;
        memcpy(key_vector,key_value,10);
        key_vector[10] = 0;
        key_vector[11] = 0;
        S1_encrypt_block(INTEGRITY,key_vector+4);
        S1_encrypt_block(INTEGRITY,key_vector);
        return 0;
}
 
#else
int S1_create_key(u_char *key_value, u_char *key_vector)
{
        return 7;
}
 
#endif
 
/* SUPPORT FUNCTIONS */
 
static void
rotatekey(int key_register, u_char *key_value)
{
        int i, j;
        int jshift[6] = {5, 8, 3, 1, 4, 0};
 
        key_register = key_register % KEY_REGISTERS;
        i=0;
        while (i<32) {
                j=0;
                while (j<6) {
                        fullkey[key_register][i][j] =
                            f(0,(key_value[(i*6+j+jshift[j]) % 10]))
                          ^ f(1,(key_value[(i*6+j+jshift[(j+1)%6]) % 10]))
                          ^ (f(2,(key_value[(i*6+j+jshift[(j+2)%6]) % 10]))<<4)
                          ^ (f(3,(key_value[(i*6+j+jshift[(j+3)%6]) % 10]))<<4);
                        j=j+1;
                }
                i=i+1;
        }
 
}
 
static void f_initialize() {
        /* NON-LINEAR (F0, F1, F2, F3) */
        F[0][0] = 07;
        F[0][1] = 02;
        F[0][2] = 011;
        F[0][3] = 014;
        F[0][4] = 010;
        F[0][5] = 016;
        F[0][6] = 01;
        F[0][7] = 06;
        F[0][8] = 015;
        F[0][9] = 02;
        F[0][10] = 00;
        F[0][11] = 04;
        F[0][12] = 017;
        F[0][13] = 07;
        F[0][14] = 03;
        F[0][15] = 017;
        F[0][16] = 010;
        F[0][17] = 017;
        F[0][18] = 012;
        F[0][19] = 05;
        F[0][20] = 013;
        F[0][21] = 00;
        F[0][22] = 017;
        F[0][23] = 02;
        F[0][24] = 05;
        F[0][25] = 015;
        F[0][26] = 017;
        F[0][27] = 017;
        F[0][28] = 011;
        F[0][29] = 011;
        F[0][30] = 06;
        F[0][31] = 014;
        F[0][32] = 07;
        F[0][33] = 017;
        F[0][34] = 012;
        F[0][35] = 016;
        F[0][36] = 012;
        F[0][37] = 06;
        F[0][38] = 04;
        F[0][39] = 04;
        F[0][40] = 014;
        F[0][41] = 04;
        F[0][42] = 017;
        F[0][43] = 013;
        F[0][44] = 03;
        F[0][45] = 014;
        F[0][46] = 014;
        F[0][47] = 06;
        F[0][48] = 06;
        F[0][49] = 00;
        F[0][50] = 02;
        F[0][51] = 010;
        F[0][52] = 012;
        F[0][53] = 012;
        F[0][54] = 03;
        F[0][55] = 015;
        F[0][56] = 013;
        F[0][57] = 014;
        F[0][58] = 017;
        F[0][59] = 05;
        F[0][60] = 05;
        F[0][61] = 00;
        F[0][62] = 07;
        F[0][63] = 014;
        F[0][64] = 016;
        F[0][65] = 011;
        F[0][66] = 03;
        F[0][67] = 011;
        F[0][68] = 010;
        F[0][69] = 014;
        F[0][70] = 012;
        F[0][71] = 014;
        F[0][72] = 017;
        F[0][73] = 05;
        F[0][74] = 07;
        F[0][75] = 05;
        F[0][76] = 07;
        F[0][77] = 016;
        F[0][78] = 03;
        F[0][79] = 02;
        F[0][80] = 011;
        F[0][81] = 014;
        F[0][82] = 04;
        F[0][83] = 00;
        F[0][84] = 010;
        F[0][85] = 016;
        F[0][86] = 02;
        F[0][87] = 03;
        F[0][88] = 02;
        F[0][89] = 016;
        F[0][90] = 013;
        F[0][91] = 04;
        F[0][92] = 010;
        F[0][93] = 01;
        F[0][94] = 06;
        F[0][95] = 013;
        F[0][96] = 016;
        F[0][97] = 010;
        F[0][98] = 017;
        F[0][99] = 014;
        F[0][100] = 00;
        F[0][101] = 02;
        F[0][102] = 00;
        F[0][103] = 01;
        F[0][104] = 01;
        F[0][105] = 013;
        F[0][106] = 016;
        F[0][107] = 00;
        F[0][108] = 02;
        F[0][109] = 013;
        F[0][110] = 017;
        F[0][111] = 013;
        F[0][112] = 016;
        F[0][113] = 016;
        F[0][114] = 02;
        F[0][115] = 05;
        F[0][116] = 02;
        F[0][117] = 00;
        F[0][118] = 016;
        F[0][119] = 01;
        F[0][120] = 010;
        F[0][121] = 013;
        F[0][122] = 011;
        F[0][123] = 06;
        F[0][124] = 01;
        F[0][125] = 05;
        F[0][126] = 07;
        F[0][127] = 07;
        F[0][128] = 016;
        F[0][129] = 014;
        F[0][130] = 012;
        F[0][131] = 011;
        F[0][132] = 011;
        F[0][133] = 016;
        F[0][134] = 07;
        F[0][135] = 014;
        F[0][136] = 011;
        F[0][137] = 015;
        F[0][138] = 012;
        F[0][139] = 00;
        F[0][140] = 010;
        F[0][141] = 00;
        F[0][142] = 07;
        F[0][143] = 012;
        F[0][144] = 015;
        F[0][145] = 013;
        F[0][146] = 00;
        F[0][147] = 012;
        F[0][148] = 04;
        F[0][149] = 017;
        F[0][150] = 05;
        F[0][151] = 00;
        F[0][152] = 015;
        F[0][153] = 02;
        F[0][154] = 016;
        F[0][155] = 03;
        F[0][156] = 03;
        F[0][157] = 013;
        F[0][158] = 06;
        F[0][159] = 011;
        F[0][160] = 014;
        F[0][161] = 03;
        F[0][