void f5star( u8 k[16], u8 rand[16], u8 ak[6], u8 op[16] ) { u8 op_c[16]; u8 temp[16]; u8 out[16]; u8 rijndaelInput[16]; u8 i; RijndaelKeySchedule( k ); ComputeOPc( op_c, op ); for (i=0; i<16; i++) rijndaelInput[i] = rand[i] ^ op_c[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] ^ op_c[i]; rijndaelInput[15] ^= 8; RijndaelEncrypt( rijndaelInput, out ); for (i=0; i<16; i++) out[i] ^= op_c[i]; for (i=0; i<6; i++) ak[i] = out[i]; return; } /* end of function f5star */
/*------------------------------------------------------------------- * 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 */
void f1 ( uint8_t k[16], uint8_t rand[16], uint8_t sqn[6], uint8_t amf[2], uint8_t mac_a[8] ) { uint8_t op_c[16]; uint8_t temp[16]; uint8_t in1[16]; uint8_t out1[16]; uint8_t rijndaelInput[16]; uint8_t i; RijndaelKeySchedule( k ); ComputeOPc( op_c ); for (i=0; i<16; i++){ rijndaelInput[i] = rand[i] ^ op_c[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] ^ op_c[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] ^= op_c[i]; } for (i=0; i<8; i++){ mac_a[i] = out1[i]; } return; } /* end of function f1 */
void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2], u8 mac_a[8], u8 op[16] ) { u8 op_c[16]; u8 temp[16]; u8 in1[16]; u8 out1[16]; u8 rijndaelInput[16]; u8 i; RijndaelKeySchedule( k ); ComputeOPc( op_c, op ); for (i=0; i<16; i++) rijndaelInput[i] = rand[i] ^ op_c[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] ^ op_c[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] ^= op_c[i]; for (i=0; i<8; i++) mac_a[i] = out1[i]; return; } /* end of function f1 */
/*------------------------------------------------------------------- * 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 */
/*------------------------------------------------------------------- * 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 */
/*------------------------------------------------------------------- * 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 */
/*------------------------------------------------------------------- * 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 ( u8 k_pP[16], u8 rand_pP[16], u8 res_pP[8], u8 ck_pP[16], u8 ik_pP[16], u8 ak_pP[6] ) { u8 op_c[16]; u8 temp[16]; u8 out[16]; u8 rijndaelInput[16]; u8 i; LOG_TRACE(DEBUG, "USIM-API - f2345 : in k[0..15]=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", k_pP[0],k_pP[1],k_pP[2], k_pP[3], k_pP[4], k_pP[5], k_pP[6], k_pP[7], k_pP[8],k_pP[9],k_pP[10],k_pP[11],k_pP[12],k_pP[13],k_pP[14],k_pP[15]); LOG_TRACE(DEBUG, "USIM-API - f2345 : in rand[0..15]=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", rand_pP[0],rand_pP[1],rand_pP[2], rand_pP[3], rand_pP[4], rand_pP[5], rand_pP[6], rand_pP[7], rand_pP[8],rand_pP[9],rand_pP[10],rand_pP[11],rand_pP[12],rand_pP[13],rand_pP[14],rand_pP[15]); RijndaelKeySchedule( k_pP ); ComputeOPc( op_c ); for (i=0; i<16; i++) rijndaelInput[i] = rand_pP[i] ^ op_c[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] ^ op_c[i]; rijndaelInput[15] ^= 1; RijndaelEncrypt( rijndaelInput, out ); for (i=0; i<16; i++) out[i] ^= op_c[i]; for (i=0; i<8; i++) res_pP[i] = out[i+8]; for (i=0; i<6; i++) ak_pP[i] = out[i]; LOG_TRACE(DEBUG, "USIM-API - f2345 : out f2 res[0..7]=%02X%02X%02X%02X%02X%02X%02X%02X", res_pP[0],res_pP[1],res_pP[2], res_pP[3], res_pP[4], res_pP[5], res_pP[6], res_pP[7]); LOG_TRACE(DEBUG, "USIM-API - f2345 : out f5 ak[0..5]=%02X%02X%02X%02X%02X%02X", ak_pP[0],ak_pP[1],ak_pP[2], ak_pP[3], ak_pP[4], ak_pP[5]); /* 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] ^ op_c[i]; rijndaelInput[15] ^= 2; RijndaelEncrypt( rijndaelInput, out ); for (i=0; i<16; i++) out[i] ^= op_c[i]; for (i=0; i<16; i++) ck_pP[i] = out[i]; LOG_TRACE(DEBUG, "USIM-API - f2345 : out f3 ck_pP[0..7]=%02X%02X%02X%02X%02X%02X%02X%02X", ck_pP[0],ck_pP[1],ck_pP[2], ck_pP[3], ck_pP[4], ck_pP[5], ck_pP[6], ck_pP[7]); /* 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] ^ op_c[i]; rijndaelInput[15] ^= 4; RijndaelEncrypt( rijndaelInput, out ); for (i=0; i<16; i++) out[i] ^= op_c[i]; for (i=0; i<16; i++) ik_pP[i] = out[i]; LOG_TRACE(DEBUG, "USIM-API - f2345 : out f4 ik_pP[0..15]=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", ik_pP[0],ik_pP[1],ik_pP[2], ik_pP[3], ik_pP[4], ik_pP[5], ik_pP[6], ik_pP[7], ik_pP[8],ik_pP[9],ik_pP[10],ik_pP[11],ik_pP[12],ik_pP[13],ik_pP[14],ik_pP[15]); return; } /* end of function f2345 */