Files
openairinterface5g/openair-cn/OPENAIRHSS/auc/fx.c
T
Lionel Gauthier 242b2b1396 clean commented code
git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7485 818b1a75-f10b-46b9-bf7c-635c3b92a50f
2015-05-28 15:04:44 +00:00

299 lines
8.7 KiB
C

/*-------------------------------------------------------------------
* Example algorithms f1, f1*, f2, f3, f4, f5, f5*
*-------------------------------------------------------------------
*
* A sample implementation of the example 3GPP authentication and
* key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
* a byte-oriented implementation of the functions, and of the block
* cipher kernel function Rijndael.
*
* This has been coded for clarity, not necessarily for efficiency.
*
* The functions f2, f3, f4 and f5 share the same inputs and have
* been coded together as a single function. f1, f1* and f5* are
* all coded separately.
*
*-----------------------------------------------------------------*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "auc.h"
#include "hss_config.h"
extern hss_config_t hss_config;
/*--------- Operator Variant Algorithm Configuration Field --------*/
/*--------------------------- prototypes --------------------------*/
/*-------------------------------------------------------------------
*
*-------------------------------------------------------------------
*-----------------------------------------------------------------*/
void generate_autn(const uint8_t const sqn[6], const uint8_t const ak[6], const uint8_t const amf[2], const uint8_t const mac_a[8], uint8_t autn[16])
{
int i;
for (i = 0; i < 6; i++) {
autn[i] = sqn[i] ^ ak[i];
}
memcpy(&autn[6], amf, 2);
memcpy(&autn[8], mac_a, 8);
}
/*-------------------------------------------------------------------
* Algorithm f1
*-------------------------------------------------------------------
*
* Computes network authentication code MAC-A from key K, random
* challenge RAND, sequence number SQN and authentication management
* field AMF.
*
*-----------------------------------------------------------------*/
void f1 ( const uint8_t const opc[16], const uint8_t const k[16], const uint8_t const _rand[16], const uint8_t const sqn[6], const uint8_t const amf[2],
uint8_t mac_a[8] )
{
uint8_t temp[16];
uint8_t in1[16];
uint8_t out1[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule( k );
for (i=0; i<16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt( rijndaelInput, temp );
for (i=0; i<6; i++) {
in1[i] = sqn[i];
in1[i+8] = sqn[i];
}
for (i=0; i<2; i++) {
in1[i+6] = amf[i];
in1[i+14] = amf[i];
}
/* XOR op_c and in1, rotate by r1=64, and XOR *
* on the constant c1 (which is all zeroes) */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = in1[i] ^ opc[i];
/* XOR on the value temp computed before */
for (i=0; i<16; i++)
rijndaelInput[i] ^= temp[i];
RijndaelEncrypt( rijndaelInput, out1 );
for (i=0; i<16; i++)
out1[i] ^= opc[i];
for (i=0; i<8; i++)
mac_a[i] = out1[i];
return;
} /* end of function f1 */
/*-------------------------------------------------------------------
* Algorithms f2-f5
*-------------------------------------------------------------------
*
* Takes key K and random challenge RAND, and returns response RES,
* confidentiality key CK, integrity key IK and anonymity key AK.
*
*-----------------------------------------------------------------*/
void f2345 ( const uint8_t const opc[16], const uint8_t const k[16], const uint8_t const _rand[16],
uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6] )
{
uint8_t temp[16];
uint8_t out[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule( k );
for (i=0; i<16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt( rijndaelInput, temp );
/* To obtain output block OUT2: XOR OPc and TEMP, *
* rotate by r2=0, and XOR on the constant c2 (which *
* is all zeroes except that the last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[i] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 1;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= opc[i];
for (i=0; i<8; i++)
res[i] = out[i+8];
for (i=0; i<6; i++)
ak[i] = out[i];
/* To obtain output block OUT3: XOR OPc and TEMP, *
* rotate by r3=32, and XOR on the constant c3 (which *
* is all zeroes except that the next to last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+12) % 16] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 2;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= opc[i];
for (i=0; i<16; i++)
ck[i] = out[i];
/* To obtain output block OUT4: XOR OPc and TEMP, *
* rotate by r4=64, and XOR on the constant c4 (which *
* is all zeroes except that the 2nd from last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 4;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= opc[i];
for (i=0; i<16; i++)
ik[i] = out[i];
return;
} /* end of function f2345 */
/*-------------------------------------------------------------------
* Algorithm f1*
*-------------------------------------------------------------------
*
* Computes resynch authentication code MAC-S from key K, random
* challenge RAND, sequence number SQN and authentication management
* field AMF.
*
*-----------------------------------------------------------------*/
void f1star( const uint8_t const opc[16], const uint8_t const k[16], const uint8_t const _rand[16], const uint8_t const sqn[6], const uint8_t const amf[2],
uint8_t mac_s[8] )
{
uint8_t temp[16];
uint8_t in1[16];
uint8_t out1[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule( k );
for (i=0; i<16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt( rijndaelInput, temp );
for (i=0; i<6; i++) {
in1[i] = sqn[i];
in1[i+8] = sqn[i];
}
for (i=0; i<2; i++) {
in1[i+6] = amf[i];
in1[i+14] = amf[i];
}
/* XOR op_c and in1, rotate by r1=64, and XOR *
* on the constant c1 (which is all zeroes) */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = in1[i] ^ opc[i];
/* XOR on the value temp computed before */
for (i=0; i<16; i++)
rijndaelInput[i] ^= temp[i];
RijndaelEncrypt( rijndaelInput, out1 );
for (i=0; i<16; i++)
out1[i] ^= opc[i];
for (i=0; i<8; i++)
mac_s[i] = out1[i+8];
return;
} /* end of function f1star */
/*-------------------------------------------------------------------
* Algorithm f5*
*-------------------------------------------------------------------
*
* Takes key K and random challenge RAND, and returns resynch
* anonymity key AK.
*
*-----------------------------------------------------------------*/
void f5star( const uint8_t const opc[16], const uint8_t const k[16], const uint8_t const _rand[16],
uint8_t ak[6] )
{
uint8_t temp[16];
uint8_t out[16];
uint8_t rijndaelInput[16];
uint8_t i;
RijndaelKeySchedule( k );
for (i=0; i<16; i++)
rijndaelInput[i] = _rand[i] ^ opc[i];
RijndaelEncrypt( rijndaelInput, temp );
/* To obtain output block OUT5: XOR OPc and TEMP, *
* rotate by r5=96, and XOR on the constant c5 (which *
* is all zeroes except that the 3rd from last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+4) % 16] = temp[i] ^ opc[i];
rijndaelInput[15] ^= 8;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= opc[i];
for (i=0; i<6; i++)
ak[i] = out[i];
return;
} /* end of function f5star */
/*-------------------------------------------------------------------
* Function to compute OPc from OP and K.
*-----------------------------------------------------------------*/
void ComputeOPc( const uint8_t const kP[16], const uint8_t const opP[16], uint8_t opcP[16] )
{
uint8_t i;
RijndaelKeySchedule( kP );
printf("Compute opc:\n\tK:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
kP[0],kP[1],kP[2],kP[3],kP[4],kP[5],kP[6],kP[7],
kP[8],kP[9],kP[10],kP[11],kP[12],kP[13],kP[14],kP[15]);
RijndaelEncrypt( opP, opcP );
printf("\tIn:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n\tRinj:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
opP[0],opP[1],opP[2],opP[3],opP[4],opP[5],opP[6],opP[7],
opP[8],opP[9],opP[10],opP[11],opP[12],opP[13],opP[14],opP[15],
opcP[0],opcP[1],opcP[2],opcP[3],opcP[4],opcP[5],opcP[6],opcP[7],
opcP[8],opcP[9],opcP[10],opcP[11],opcP[12],opcP[13],opcP[14],opcP[15] );
for (i=0; i<16; i++)
opcP[i] ^= opP[i];
printf("\tOut:\t%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
opcP[0],opcP[1],opcP[2],opcP[3],opcP[4],opcP[5],opcP[6],opcP[7],
opcP[8],opcP[9],opcP[10],opcP[11],opcP[12],opcP[13],opcP[14],opcP[15] );
return;
} /* end of function ComputeOPc */