blob: c0016416f6fa4a34eda86be5d22ff803663c3aae [file] [log] [blame]
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "f9.h"
/* The code has been referred from
* 1.https://www.gsma.com/aboutus/wp-content/uploads/2014/12/uea2uia2d1v21.pdf
* 2.https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf
*
*/
/* MUL64x.
* Input V: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.2
* (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf)
* for more details.
*/
u64 MUL64x(u64 V, u64 c)
{
if ( V & 0x8000000000000000 )
return (V << 1) ^ c;
else
return V << 1;
}
/* MUL64xPOW.
* Input V: a 64-bit input.
* Input i: a positive integer.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
function.
* See section 4.3.3
* (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf)
* for more details.
*/
u64 MUL64xPOW(u64 V, u8 i, u64 c)
{
if ( i == 0)
return V;
else
return MUL64x( MUL64xPOW(V,i-1,c) , c);
return V;
}
/* MUL64.
* Input V: a 64-bit input.
* Input P: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.4
* (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf)
* for more details.
*/
u64 MUL64(u64 V, u64 P, u64 c)
{
u64 result = 0;
int i = 0;
for ( i=0; i<64; i++)
{
if( ( P>>i ) & 0x1 )
result ^= MUL64xPOW(V,i,c);
}
return result;
}
/* mask8bit.
* Input n: an integer in 1-7.
* Output : an 8 bit mask.
* Prepares an 8 bit mask with required number of 1 bits on the MSB side.
*/
u8 mask8bit(int n)
{
return 0xFF ^ ((1<<(8-n)) - 1);
}
/* f9.
* Input key: 128 bit Integrity Key.
* Input count:32-bit Count, Frame dependent input.
* Input fresh: 32-bit Random number.
* Input dir:1 bit, direction of transmission (in the LSB).
* Input data: length number of bits, input bit stream.
* Input length: 64 bit Length, i.e., the number of bits to be MAC'd.
* Output : 32 bit block used as MAC
* Generates 32-bit MAC using UIA2 algorithm as defined in Section 4.
*/
u8* f9( u8* key, u32 count, u32 fresh, u32 dir, u8 *data, u64 length)
{
u32 K[4],IV[4], z[5];
u32 i=0,D;
static u8 MAC_I[4] = {0,0,0,0}; /* static memory for the result */
u64 EVAL;
u64 V;
u64 P;
u64 Q;
u64 c;
u64 M_D_2;
int rem_bits = 0;
/* Load the Integrity Key for SNOW3G initialization as in section 4.4. */
for (i=0; i<4; i++)
K[3-i] = (key[4*i] << 24) ^ (key[4*i+1] << 16) ^ (key[4*i+2] << 8) ^
(key[4*i+3]);
/* Prepare the Initialization Vector (IV) for SNOW3G initialization as in
section 4.4 of
(https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf).
*/
IV[3] = count;
IV[2] = fresh;
IV[1] = count ^ ( dir << 31 ) ;
IV[0] = fresh ^ (dir << 15);
z[0] = z[1] = z[2] = z[3] = z[4] = 0;
/* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */
Initialize(K,IV);
GenerateKeystream(5,z);
P = (u64)z[0] << 32 | (u64)z[1];
Q = (u64)z[2] << 32 | (u64)z[3];
/* Calculation */
if ((length % 64) == 0)
D = (length>>6) + 1;
else
D = (length>>6) + 2;
EVAL = 0;
c = 0x1b;
/* for 0 <= i <= D-3 */
for (i=0;i<D-2;i++)
{
V = EVAL ^ ( (u64)data[8*i ]<<56 | (u64)data[8*i+1]<<48 |
(u64)data[8*i+2]<<40 | (u64)data[8*i+3]<<32 |
(u64)data[8*i+4]<<24 | (u64)data[8*i+5]<<16 |
(u64)data[8*i+6]<< 8 | (u64)data[8*i+7] );
EVAL = MUL64(V,P,c);
}
/* for D-2 */
rem_bits = length % 64;
if (rem_bits == 0)
rem_bits = 64;
M_D_2 = 0;
i = 0;
while (rem_bits > 7)
{
M_D_2 |= (u64)data[8*(D-2)+i] << (8*(7-i));
rem_bits -= 8;
i++;
}
if (rem_bits > 0)
M_D_2 |= (u64)(data[8*(D-2)+i] & mask8bit(rem_bits)) << (8*(7-i));
V = EVAL ^ M_D_2;
EVAL = MUL64(V,P,c);
/* for D-1 */
EVAL ^= length;
/* Multiply by Q */
EVAL = MUL64(EVAL,Q,c);
for (i=0; i<4; i++) {
/* GSLab-Intel modification to the specs reference code
* https://www.gsma.com/aboutus/wp-content/uploads/2014/12/uea2uia2d1v21.pdf
* which forgot to XOR z[5]
*/
MAC_I[i] = ((EVAL >> (8 * (7-i))) ^ (z[4] >> (8 * (3-i)))) & 0xff;
}
return MAC_I;
}
/* End of f9.c */
/*------------------------------------------------------------------------*/