aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-06-30 20:35:02 +0200
committerHarald Welte <laforge@gnumonks.org>2010-06-30 20:35:02 +0200
commit73998b6cf33f5adabb42bde4bf77a9445d685bd8 (patch)
tree3099ab63bcc57380a5533788b2a54c6e3ac68b32
parentc42335fffbf5a786972097d0f62a2ed2d6b0856e (diff)
import more sources from GSM/3GPP spec
-rw-r--r--src/a53f.c124
-rw-r--r--src/a53f.h8
-rw-r--r--src/kasumi.c2
-rw-r--r--src/kasumi.h22
-rw-r--r--src/kgcore.c79
5 files changed, 230 insertions, 5 deletions
diff --git a/src/a53f.c b/src/a53f.c
new file mode 100644
index 0000000..2932d6d
--- /dev/null
+++ b/src/a53f.c
@@ -0,0 +1,124 @@
+/*---------------------------------------------------------
+ * A5/3
+ *---------------------------------------------------------
+ *
+ * A sample implementation of A5/3, the functions of the
+ * A5/3 algorithm set.
+ *
+ * This has been coded for clarity, not necessarily for
+ * efficiency.
+ *
+ * This will compile and run correctly on both Intel
+ * (little endian) and Sparc (big endian) machines.
+ *
+ * Version 0.1 13 March 2002
+ *
+ *---------------------------------------------------------*/
+#include "kasumi.h"
+#include <stdlib.h>
+void KGcore( u8 ca, u8 cb, u32 cc, u8 cd, u8 *ck, u8 *co, int cl );
+
+/*---------------------------------------------------------
+ * BuildKey()
+ * The KGcore() function expects a 128-bit key. This
+ * function builds that key from shorter length keys.
+ *---------------------------------------------------------*/
+static u8 *BuildKey( u8 *k, int len )
+{
+ static u8 ck[16]; /* Where the key is built */
+ int i, n, sf;
+ u8 mask[]={0x1,0x3,0x7,0xF,0x1F,0x3F,0x7F,0xFF};
+ i = (len+7)/8; /* Round to nearest byte */
+ if (i > 16 )
+ i = 16; /* limit to 128 bits */
+ for( n=0; n<i; ++n ) /* copy over the key */
+ ck[n] = k[n];
+ sf = len%8; /* Any odd key length? */
+ /* If the key is less than 128-bits we need to replicate *
+ * it as many times as is necessary to fill the key. */
+ if( len < 128 )
+ {
+ n = 0;
+ if( sf ) /* Doesn't align to byte boundaries */
+ {
+ ck[i-1] &= mask[sf];
+ ck[i-1] += ck[0]<<sf;
+ while( i<16 )
+ {
+ ck[i] = (ck[n]>>(8-sf)) + (ck[n+1]<<sf);
+ ++n;
+ ++i;
+ }
+ }
+ else
+ while( i<16 )
+ ck[i++] = ck[n++];
+ }
+ return( ck );
+}
+
+/*---------------------------------------------------------
+ * The basic A5/3 functions.
+ * These follow a standard layout:
+ * - From the supplied key build the 128-bit required by
+ * KGcore()
+ * - Call the KGcora() function with te appropriate
+ * parameters
+ * - Take the generated Keystream and repackage it
+ * in the required format.
+ */
+/*---------------------------------------------------------
+ * The standard GSM function
+ *---------------------------------------------------------*/
+void GSM( u8 *key, int klen, int count, u8 *block1, u8 *block2 )
+{
+ u8 *ck, data[32];
+ int i;
+ ck=BuildKey( key, klen );
+ KGcore( 0x0F, 0, count, 0, ck, data, 228 );
+ for( i=0; i<15; ++i )
+ {
+ block1[i] = data[i];
+ block2[i] = (data[i+14]<<2) + (data[i+15]>>6);
+ }
+ block1[14] &= 0xC0;
+ block2[14] &= 0xC0;
+}
+
+/*---------------------------------------------------------
+ * The standard GSM ECSD function
+ *---------------------------------------------------------*/
+void ECSD( u8 *key, int klen, int count, u8 *block1, u8 *block2 )
+{
+ u8 *ck, data[87];
+ int i;
+ ck=BuildKey( key, klen );
+ KGcore( 0xF0, 0, count, 0, ck, data, 696 );
+ for( i=0; i<44; ++i )
+ {
+ block1[i] = data[i];
+ block2[i] = (data[i+43]<<4) + (data[i+44]>>4);
+ }
+ block1[43] &= 0xF0;
+ block2[43] &= 0xF0;
+}
+
+/*---------------------------------------------------------
+ * The standard GEA3 function
+ *---------------------------------------------------------*/
+void GEA3( u8 *key, int klen, u32 input, u8 direction, u8 *block, int m )
+{
+ u8 *ck, *data;
+ int i;
+ data = malloc( m );
+ ck=BuildKey( key, klen );
+ KGcore( 0xFF, 0, input, direction, ck, data, m*8 );
+ for( i=0; i<m; ++i )
+ block[i] = data[i];
+ free( data );
+}
+
+/*---------------------------------------------------------
+ * E n d o f A 5 3 f . c
+ *---------------------------------------------------------*/
+
diff --git a/src/a53f.h b/src/a53f.h
new file mode 100644
index 0000000..14c8a4f
--- /dev/null
+++ b/src/a53f.h
@@ -0,0 +1,8 @@
+#ifndef A53_F_H
+#define A53_F_H
+
+void GSM( u8 *key, int klen, int count, u8 *block1, u8 *block2 );
+void ECSD( u8 *key, int klen, int count, u8 *block1, u8 *block2 );
+void GEA3( u8 *key, int klen, u32 input, u8 direction, u8 *block, int m );
+
+#endif
diff --git a/src/kasumi.c b/src/kasumi.c
index 7f2c43b..56e4224 100644
--- a/src/kasumi.c
+++ b/src/kasumi.c
@@ -14,7 +14,7 @@
*
*-----------------------------------------------------------------------*/
-#include "Kasumi.h"
+#include "kasumi.h"
/*--------- 16 bit rotate left ------------------------------------------*/
diff --git a/src/kasumi.h b/src/kasumi.h
index 0c007d7..1aca3d1 100644
--- a/src/kasumi.h
+++ b/src/kasumi.h
@@ -1,10 +1,24 @@
+#ifndef KASUMI_H
+#define KASUMI_H
+
+#include <stdint.h>
+
/*---------------------------------------------------------
- * Kasumi.h
+ * Kasumi.h
*---------------------------------------------------------*/
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned long u32;
+/*----- a 64-bit structure to help with endian issues -----*/
+typedef union {
+ u32 b32[2];
+ u16 b16[4];
+ u8 b8[8];
+} REGISTER64;
+/*------------- prototypes --------------------------------*/
void KeySchedule( u8 *key );
void Kasumi( u8 *data );
+
+#endif /* KASUMI_H */
diff --git a/src/kgcore.c b/src/kgcore.c
new file mode 100644
index 0000000..f20889f
--- /dev/null
+++ b/src/kgcore.c
@@ -0,0 +1,79 @@
+/*---------------------------------------------------------
+ * KGCORE
+ *---------------------------------------------------------
+ *
+ * A sample implementation of KGCORE, the heart of the
+ * A5/3 algorithm set.
+ *
+ * This has been coded for clarity, not necessarily for
+ * efficiency.
+ *
+ * This will compile and run correctly on both Intel
+ * (little endian) and Sparc (big endian) machines.
+ *
+ * Version 0.1 13 March 2002
+ *
+ *---------------------------------------------------------*/
+#include "kasumi.h"
+#include <stdio.h>
+#include <stdint.h>
+
+/*---------------------------------------------------------
+ * KGcore()
+ * Given ca, cb, cc, cd, ck, cl generate c0
+ *---------------------------------------------------------*/
+void KGcore( u8 ca, u8 cb, u32 cc, u8 cd, u8 *ck, u8 *co, int cl )
+{
+ REGISTER64 A; /* the modifier */
+ REGISTER64 temp; /* The working register */
+ int i, n;
+ u8 key[16],ModKey[16]; /* Modified key */
+ u16 blkcnt; /* The block counter */
+ /* Copy over the key */
+ for( i=0; i<16; ++i )
+ key[i] = ck[i];
+ /* Start by building our global modifier */
+ temp.b32[0] = temp.b32[1] = 0;
+ A.b32[0] = A.b32[1] = 0;
+ /* initialise register in an endian correct manner*/
+ A.b8[0] = (u8) (cc>>24);
+ A.b8[1] = (u8) (cc>>16);
+ A.b8[2] = (u8) (cc>>8);
+ A.b8[3] = (u8) (cc);
+ A.b8[4] = (u8) (cb<<3);
+ A.b8[4] |= (u8) (cd<<2);
+ A.b8[5] = (u8) ca;
+ /* Construct the modified key and then "kasumi" A */
+ for( n=0; n<16; ++n )
+ ModKey[n] = (u8)(ck[n] ^ 0x55);
+ KeySchedule( ModKey );
+ Kasumi( A.b8 ); /* First encryption to create modifier */
+ /* Final initialisation steps */
+ blkcnt = 0;
+ KeySchedule( key );
+ /* Now run the key stream generator */
+ while( cl > 0 )
+ {
+ /* First we calculate the next 64-bits of keystream */
+ /* XOR in A and BLKCNT to last value */
+ temp.b32[0] ^= A.b32[0];
+ temp.b32[1] ^= A.b32[1];
+ temp.b8[7] ^= blkcnt;
+ /* KASUMI it to produce the next block of keystream */
+ Kasumi( temp.b8 );
+ /* Set <n> to the number of bytes of input data *
+ * we have to modify. (=8 if length <= 64) */
+ if( cl >= 64 )
+ n = 8;
+ else
+ n = (cl+7)/8;
+ /* copy out the keystream */
+ for( i=0; i<n; ++i )
+ *co++ = temp.b8[i];
+ cl -= 64; /* done another 64 bits */
+ ++blkcnt; /* increment BLKCNT */
+ }
+}
+/*-----------------------------------------------------------
+ * e n d o f K G c o r e . c
+ *-----------------------------------------------------------*/