kdf.c 4.38 KB
Newer Older
Lionel Gauthier's avatar
GPLv3  
Lionel Gauthier committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*******************************************************************************
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface 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.


    OpenAirInterface 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 OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

 *******************************************************************************/
winckel's avatar
 
winckel committed
29 30 31 32 33 34 35 36 37 38
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include <gmp.h>
#include <nettle/hmac.h>

#include "auc.h"
39
#include "hss_config.h"
winckel's avatar
 
winckel committed
40

Lionel Gauthier's avatar
Lionel Gauthier committed
41
#define DEBUG_AUC_KDF 1
42
extern hss_config_t hss_config;
Lionel Gauthier's avatar
Lionel Gauthier committed
43

winckel's avatar
 
winckel committed
44 45 46 47 48 49 50 51 52 53 54 55
/*
 * @param key the input key
 * @param key_len length of the key
 * @param s string for key derivation as defined in 3GPP TS.33401 Annex A
 * @param s_len length of s
 * @param out buffer to place the output of kdf
 * @param ou_len expected length for the output key
 */
inline
void kdf(uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out,
         uint16_t out_len)
{
56
  struct hmac_sha256_ctx ctx;
winckel's avatar
 
winckel committed
57

58
  memset(&ctx, 0, sizeof(ctx));
winckel's avatar
 
winckel committed
59

60 61 62
  hmac_sha256_set_key(&ctx, key_len, key);
  hmac_sha256_update(&ctx, s_len, s);
  hmac_sha256_digest(&ctx, out_len, out);
winckel's avatar
 
winckel committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
}

/*
 * Derive the Kasme using the KDF (key derive function).
 * See 3GPP TS.33401 Annex A.2
 * The input String S to the KDF is composed of 14 bytes:
 * FC = 0x10
 * P0 = SN id = PLMN
 * L0 = length(SN id) = 0x00 0x03
 * P1 = SQN xor AK
 * L1 = length(P1) = 0x00 0x06
 */
inline
void derive_kasme(uint8_t ck[16], uint8_t ik[16], uint8_t plmn[3], uint8_t sqn[6],
                  uint8_t ak[6], uint8_t *kasme)
{
79 80 81
  uint8_t s[14];
  int i;
  uint8_t key[32];
winckel's avatar
 
winckel committed
82

83 84 85
  /* The input key is equal to the concatenation of CK and IK */
  memcpy(&key[0], ck, 16);
  memcpy(&key[16], ik, 16);
winckel's avatar
 
winckel committed
86

87
  /*if (hss_config.valid_opc == 0) {
88
    SetOP(hss_config.operator_key);
89
  }*/
winckel's avatar
 
winckel committed
90

91 92
  /* FC */
  s[0] = 0x10;
winckel's avatar
 
winckel committed
93

94 95 96 97 98 99 100
  /* SN id is composed of MCC and MNC
   * Octets:
   *   1      MCC digit 2 | MCC digit 1
   *   2      MNC digit 3 | MCC digit 3
   *   3      MNC digit 2 | MNC digit 1
   */
  memcpy(&s[1], plmn, 3);
winckel's avatar
 
winckel committed
101

102 103 104
  /* L0 */
  s[4] = 0x00;
  s[5] = 0x03;
winckel's avatar
 
winckel committed
105

106 107 108 109
  /* P1 */
  for (i = 0; i < 6; i++) {
    s[6 + i] = sqn[i] ^ ak[i];
  }
winckel's avatar
 
winckel committed
110

111 112 113
  /* L1 */
  s[12] = 0x00;
  s[13] = 0x06;
winckel's avatar
 
winckel committed
114 115

#if defined(DEBUG_AUC_KDF)
116 117 118 119 120 121 122 123 124 125

  for (i = 0; i < 32; i++)
    printf("0x%02x ", key[i]);

  printf("\n");

  for (i = 0; i < 14; i++)
    printf("0x%02x ", s[i]);

  printf("\n");
winckel's avatar
 
winckel committed
126 127
#endif

128
  kdf(key, 32, s, 14, kasme, 32);
winckel's avatar
 
winckel committed
129 130
}

131
int generate_vector(const uint8_t const opc[16], uint64_t imsi, uint8_t key[16], uint8_t plmn[3],
winckel's avatar
 
winckel committed
132 133
                    uint8_t sqn[6], auc_vector_t *vector)
{
134 135 136 137 138 139 140
  /* in E-UTRAN an authentication vector is composed of:
   * - RAND
   * - XRES
   * - AUTN
   * - KASME
   */

Lionel Gauthier's avatar
Lionel Gauthier committed
141
  uint8_t amf[] = { 0x80, 0x00 };
142 143 144 145 146 147 148 149 150 151
  uint8_t mac_a[8];
  uint8_t ck[16];
  uint8_t ik[16];
  uint8_t ak[6];

  if (vector == NULL) {
    return EINVAL;
  }

  /* Compute MAC */
152
  f1(opc, key, vector->rand, sqn, amf, mac_a);
153 154 155 156 157 158

  print_buffer("MAC_A   : ", mac_a, 8);
  print_buffer("SQN     : ", sqn, 6);
  print_buffer("RAND    : ", vector->rand, 16);

  /* Compute XRES, CK, IK, AK */
159
  f2345(opc, key, vector->rand, vector->xres, ck, ik, ak);
160 161 162 163 164 165 166 167 168 169 170 171 172 173
  print_buffer("AK      : ", ak, 6);
  print_buffer("CK      : ", ck, 16);
  print_buffer("IK      : ", ik, 16);
  print_buffer("XRES    : ", vector->xres, 8);

  /* AUTN = SQN ^ AK || AMF || MAC */
  generate_autn(sqn, ak, amf, mac_a, vector->autn);

  print_buffer("AUTN    : ", vector->autn, 16);

  derive_kasme(ck, ik, plmn, sqn, ak, vector->kasme);
  print_buffer("KASME   : ", vector->kasme, 32);

  return 0;
winckel's avatar
 
winckel committed
174
}