diff options
Diffstat (limited to 'tinySIP/src/authentication/tsip_milenage.c')
-rw-r--r-- | tinySIP/src/authentication/tsip_milenage.c | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/tinySIP/src/authentication/tsip_milenage.c b/tinySIP/src/authentication/tsip_milenage.c new file mode 100644 index 0000000..3fd19e2 --- /dev/null +++ b/tinySIP/src/authentication/tsip_milenage.c @@ -0,0 +1,350 @@ +/* +* Partial Copyright (C) 2010-2011 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file tsip_milenage.c +* @brief 3GPP authentication and key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. +* +* @section DESCRIPTION +* +* @sa 3G Security +* <a href="http://www.3gpp.org/ftp/Specs/html-info/35205.htm"> 3GPP TS 35.205 </a> +* <a href="http://www.3gpp.org/ftp/Specs/html-info/35206.htm"> 3GPP TS 35.206 </a> +* <a href="http://www.3gpp.org/ftp/Specs/html-info/35207.htm"> 3GPP TS 35.207 </a> +* <a href="http://www.3gpp.org/ftp/Specs/html-info/35208.htm"> 3GPP TS 35.208 </a> +* <a href="http://www.3gpp.org/ftp/Specs/html-info/35909.htm"> 3GPP TS 35.909 </a> +*------------------------------------------------------------------- +* 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 "tinysip/authentication/tsip_milenage.h" +#include "tinysip/authentication/tsip_rijndael.h" + +/*--------- Operator Variant Algorithm Configuration Field --------*/ + +/*------- Insert your value of OP here -------*/ +//uint8_t OP[16] = {0x63, 0xbf, 0xa5, 0x0e, 0xe6, 0x52, 0x33, 0x65, +// 0xff, 0x14, 0xc1, 0xf4, 0x5f, 0x88, 0x73, 0x7d}; +/*------- Insert your value of OP here -------*/ +uint8_t OP[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/*------------------------------------------------------------------- +* Algorithm f1 +*------------------------------------------------------------------- +* +* Computes network authentication code MAC-A from key K, random +* challenge RAND, sequence number SQN and authentication management +* field AMF. +* +*-----------------------------------------------------------------*/ + +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 */ + + + +/*------------------------------------------------------------------- +* 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 ( uint8_t k[16], uint8_t rand[16], + uint8_t res[8], uint8_t ck[16], uint8_t ik[16], uint8_t ak[6] ) +{ + uint8_t op_c[16]; + uint8_t temp[16]; + uint8_t out[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 ); + + /* 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[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] ^ 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[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] ^ 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[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( uint8_t k[16], uint8_t rand[16], uint8_t sqn[6], uint8_t amf[2], + uint8_t mac_s[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_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( uint8_t k[16], uint8_t rand[16], + uint8_t ak[6] ) +{ + uint8_t op_c[16]; + uint8_t temp[16]; + uint8_t out[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 ); + + /* 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 */ + + +/*------------------------------------------------------------------- +* Function to compute OPc from OP and K. Assumes key schedule has +already been performed. +*-----------------------------------------------------------------*/ + +void ComputeOPc( uint8_t op_c[16] ) +{ + uint8_t i; + + RijndaelEncrypt( OP, op_c ); + for (i=0; i<16; i++){ + op_c[i] ^= OP[i]; + } + + return; +} /* end of function ComputeOPc */ + +void ComputeOP( uint8_t op[16] ){ + int i; + for(i=0;i<16;i++){ + OP[i]=op[i]; + } +} |