import more sources from GSM/3GPP spec
This commit is contained in:
parent
c42335fffb
commit
73998b6cf3
|
@ -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
|
||||
*---------------------------------------------------------*/
|
||||
|
|
@ -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
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
#include "Kasumi.h"
|
||||
#include "kasumi.h"
|
||||
|
||||
/*--------- 16 bit rotate left ------------------------------------------*/
|
||||
|
||||
|
|
22
src/kasumi.h
22
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 */
|
||||
|
|
|
@ -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
|
||||
*-----------------------------------------------------------*/
|
Reference in New Issue