milenage.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*-------------------------------------------------------------------
  2. * Example algorithms f1, f1*, f2, f3, f4, f5, f5*
  3. *-------------------------------------------------------------------
  4. *
  5. * A sample implementation of the example 3GPP authentication and
  6. * key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
  7. * a byte-oriented implementation of the functions, and of the block
  8. * cipher kernel function Rijndael.
  9. *
  10. * This has been coded for clarity, not necessarily for efficiency.
  11. *
  12. * The functions f2, f3, f4 and f5 share the same inputs and have
  13. * been coded together as a single function. f1, f1* and f5* are
  14. * all coded separately.
  15. *
  16. *-----------------------------------------------------------------*/
  17. #include "milenage.h"
  18. #include "rijndael.h"
  19. /*--------------------------- prototypes --------------------------*/
  20. /*-------------------------------------------------------------------
  21. * Algorithm f1
  22. *-------------------------------------------------------------------
  23. *
  24. * Computes network authentication code MAC-A from key K, random
  25. * challenge RAND, sequence number SQN and authentication management
  26. * field AMF.
  27. *
  28. *-----------------------------------------------------------------*/
  29. void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
  30. u8 mac_a[8], u8 op[16] )
  31. {
  32. u8 op_c[16];
  33. u8 temp[16];
  34. u8 in1[16];
  35. u8 out1[16];
  36. u8 rijndaelInput[16];
  37. u8 i;
  38. RijndaelKeySchedule( k );
  39. ComputeOPc( op_c, op );
  40. for (i=0; i<16; i++)
  41. rijndaelInput[i] = rand[i] ^ op_c[i];
  42. RijndaelEncrypt( rijndaelInput, temp );
  43. for (i=0; i<6; i++)
  44. {
  45. in1[i] = sqn[i];
  46. in1[i+8] = sqn[i];
  47. }
  48. for (i=0; i<2; i++)
  49. {
  50. in1[i+6] = amf[i];
  51. in1[i+14] = amf[i];
  52. }
  53. /* XOR op_c and in1, rotate by r1=64, and XOR *
  54. * on the constant c1 (which is all zeroes) */
  55. for (i=0; i<16; i++)
  56. rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
  57. /* XOR on the value temp computed before */
  58. for (i=0; i<16; i++)
  59. rijndaelInput[i] ^= temp[i];
  60. RijndaelEncrypt( rijndaelInput, out1 );
  61. for (i=0; i<16; i++)
  62. out1[i] ^= op_c[i];
  63. for (i=0; i<8; i++)
  64. mac_a[i] = out1[i];
  65. return;
  66. } /* end of function f1 */
  67. /*-------------------------------------------------------------------
  68. * Algorithms f2-f5
  69. *-------------------------------------------------------------------
  70. *
  71. * Takes key K and random challenge RAND, and returns response RES,
  72. * confidentiality key CK, integrity key IK and anonymity key AK.
  73. *
  74. *-----------------------------------------------------------------*/
  75. void f2345 ( u8 k[16], u8 rand[16],
  76. u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6], u8 op[16] )
  77. {
  78. u8 op_c[16];
  79. u8 temp[16];
  80. u8 out[16];
  81. u8 rijndaelInput[16];
  82. u8 i;
  83. RijndaelKeySchedule( k );
  84. ComputeOPc( op_c, op );
  85. for (i=0; i<16; i++)
  86. rijndaelInput[i] = rand[i] ^ op_c[i];
  87. RijndaelEncrypt( rijndaelInput, temp );
  88. /* To obtain output block OUT2: XOR OPc and TEMP, *
  89. * rotate by r2=0, and XOR on the constant c2 (which *
  90. * is all zeroes except that the last bit is 1). */
  91. for (i=0; i<16; i++)
  92. rijndaelInput[i] = temp[i] ^ op_c[i];
  93. rijndaelInput[15] ^= 1;
  94. RijndaelEncrypt( rijndaelInput, out );
  95. for (i=0; i<16; i++)
  96. out[i] ^= op_c[i];
  97. for (i=0; i<8; i++)
  98. res[i] = out[i+8];
  99. for (i=0; i<6; i++)
  100. ak[i] = out[i];
  101. /* To obtain output block OUT3: XOR OPc and TEMP, *
  102. * rotate by r3=32, and XOR on the constant c3 (which *
  103. * is all zeroes except that the next to last bit is 1). */
  104. for (i=0; i<16; i++)
  105. rijndaelInput[(i+12) % 16] = temp[i] ^ op_c[i];
  106. rijndaelInput[15] ^= 2;
  107. RijndaelEncrypt( rijndaelInput, out );
  108. for (i=0; i<16; i++)
  109. out[i] ^= op_c[i];
  110. for (i=0; i<16; i++)
  111. ck[i] = out[i];
  112. /* To obtain output block OUT4: XOR OPc and TEMP, *
  113. * rotate by r4=64, and XOR on the constant c4 (which *
  114. * is all zeroes except that the 2nd from last bit is 1). */
  115. for (i=0; i<16; i++)
  116. rijndaelInput[(i+8) % 16] = temp[i] ^ op_c[i];
  117. rijndaelInput[15] ^= 4;
  118. RijndaelEncrypt( rijndaelInput, out );
  119. for (i=0; i<16; i++)
  120. out[i] ^= op_c[i];
  121. for (i=0; i<16; i++)
  122. ik[i] = out[i];
  123. return;
  124. } /* end of function f2345 */
  125. /*-------------------------------------------------------------------
  126. * Algorithm f1*
  127. *-------------------------------------------------------------------
  128. *
  129. * Computes resynch authentication code MAC-S from key K, random
  130. * challenge RAND, sequence number SQN and authentication management
  131. * field AMF.
  132. *
  133. *-----------------------------------------------------------------*/
  134. void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
  135. u8 mac_s[8], u8 op[16] )
  136. {
  137. u8 op_c[16];
  138. u8 temp[16];
  139. u8 in1[16];
  140. u8 out1[16];
  141. u8 rijndaelInput[16];
  142. u8 i;
  143. RijndaelKeySchedule( k );
  144. ComputeOPc( op_c, op );
  145. for (i=0; i<16; i++)
  146. rijndaelInput[i] = rand[i] ^ op_c[i];
  147. RijndaelEncrypt( rijndaelInput, temp );
  148. for (i=0; i<6; i++)
  149. {
  150. in1[i] = sqn[i];
  151. in1[i+8] = sqn[i];
  152. }
  153. for (i=0; i<2; i++)
  154. {
  155. in1[i+6] = amf[i];
  156. in1[i+14] = amf[i];
  157. }
  158. /* XOR op_c and in1, rotate by r1=64, and XOR *
  159. * on the constant c1 (which is all zeroes) */
  160. for (i=0; i<16; i++)
  161. rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
  162. /* XOR on the value temp computed before */
  163. for (i=0; i<16; i++)
  164. rijndaelInput[i] ^= temp[i];
  165. RijndaelEncrypt( rijndaelInput, out1 );
  166. for (i=0; i<16; i++)
  167. out1[i] ^= op_c[i];
  168. for (i=0; i<8; i++)
  169. mac_s[i] = out1[i+8];
  170. return;
  171. } /* end of function f1star */
  172. /*-------------------------------------------------------------------
  173. * Algorithm f5*
  174. *-------------------------------------------------------------------
  175. *
  176. * Takes key K and random challenge RAND, and returns resynch
  177. * anonymity key AK.
  178. *
  179. *-----------------------------------------------------------------*/
  180. void f5star( u8 k[16], u8 rand[16],
  181. u8 ak[6], u8 op[16] )
  182. {
  183. u8 op_c[16];
  184. u8 temp[16];
  185. u8 out[16];
  186. u8 rijndaelInput[16];
  187. u8 i;
  188. RijndaelKeySchedule( k );
  189. ComputeOPc( op_c, op );
  190. for (i=0; i<16; i++)
  191. rijndaelInput[i] = rand[i] ^ op_c[i];
  192. RijndaelEncrypt( rijndaelInput, temp );
  193. /* To obtain output block OUT5: XOR OPc and TEMP, *
  194. * rotate by r5=96, and XOR on the constant c5 (which *
  195. * is all zeroes except that the 3rd from last bit is 1). */
  196. for (i=0; i<16; i++)
  197. rijndaelInput[(i+4) % 16] = temp[i] ^ op_c[i];
  198. rijndaelInput[15] ^= 8;
  199. RijndaelEncrypt( rijndaelInput, out );
  200. for (i=0; i<16; i++)
  201. out[i] ^= op_c[i];
  202. for (i=0; i<6; i++)
  203. ak[i] = out[i];
  204. return;
  205. } /* end of function f5star */
  206. /*-------------------------------------------------------------------
  207. * Function to compute OPc from OP and K. Assumes key schedule has
  208. already been performed.
  209. *-----------------------------------------------------------------*/
  210. void ComputeOPc( u8 op_c[16], u8 op[16] )
  211. {
  212. u8 i;
  213. RijndaelEncrypt( op, op_c );
  214. for (i=0; i<16; i++)
  215. op_c[i] ^= op[i];
  216. return;
  217. } /* end of function ComputeOPc */