Remove src/crypto from default include path
[libeap.git] / src / eap_common / eap_sim_common.c
index 9d1bf2c..56b4ded 100644 (file)
 #include "includes.h"
 
 #include "common.h"
-#include "eap_common/eap_defs.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "crypto.h"
-#include "aes_wrap.h"
 #include "wpabuf.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "eap_common/eap_defs.h"
 #include "eap_common/eap_sim_common.h"
 
 
@@ -233,7 +233,7 @@ void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac,
 }
 
 
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
 static void prf_prime(const u8 *k, const char *seed1,
                      const u8 *seed2, size_t seed2_len,
                      const u8 *seed3, size_t seed3_len,
@@ -426,7 +426,77 @@ void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len,
        wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC",
                    mac, EAP_SIM_MAC_LEN);
 }
-#endif /* EAP_AKA_PRIME */
+
+
+void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
+                                     const u8 *network_name,
+                                     size_t network_name_len)
+{
+       u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN];
+       u8 hash[SHA256_MAC_LEN];
+       const u8 *addr[5];
+       size_t len[5];
+       u8 fc;
+       u8 l0[2], l1[2];
+
+       /* 3GPP TS 33.402 V8.0.0
+        * (CK', IK') = F(CK, IK, <access network identity>)
+        */
+       /* TODO: CK', IK' generation should really be moved into the actual
+        * AKA procedure with network name passed in there and option to use
+        * AMF separation bit = 1 (3GPP TS 33.401). */
+
+       /* Change Request 33.402 CR 0033 to version 8.1.1 from
+        * 3GPP TSG-SA WG3 Meeting #53 in September 2008:
+        *
+        * CK' || IK' = HMAC-SHA-256(Key, S)
+        * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
+        * Key = CK || IK
+        * FC = 0x20
+        * P0 = access network identity (3GPP TS 24.302)
+        * L0 = length of acceess network identity (2 octets, big endian)
+        * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0
+        * L1 = 0x00 0x06
+        */
+
+       fc = 0x20;
+
+       wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)");
+       wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN);
+       wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN);
+       wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc);
+       wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity",
+                         network_name, network_name_len);
+       wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6);
+
+       os_memcpy(key, ck, EAP_AKA_CK_LEN);
+       os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN);
+       wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK",
+                       key, sizeof(key));
+
+       addr[0] = &fc;
+       len[0] = 1;
+       addr[1] = network_name;
+       len[1] = network_name_len;
+       WPA_PUT_BE16(l0, network_name_len);
+       addr[2] = l0;
+       len[2] = 2;
+       addr[3] = sqn_ak;
+       len[3] = 6;
+       WPA_PUT_BE16(l1, 6);
+       addr[4] = l1;
+       len[4] = 2;
+
+       hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash);
+       wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')",
+                       hash, sizeof(hash));
+
+       os_memcpy(ck, hash, EAP_AKA_CK_LEN);
+       os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN);
+       wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN);
+       wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN);
+}
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
 
 
 int eap_sim_parse_attr(const u8 *start, const u8 *end,
@@ -788,7 +858,7 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
                        wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND");
                        attr->result_ind = 1;
                        break;
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
                case EAP_SIM_AT_KDF_INPUT:
                        if (aka != 2) {
                                wpa_printf(MSG_INFO, "EAP-AKA: Unexpected "
@@ -833,7 +903,17 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
                        attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
                        attr->kdf_count++;
                        break;
-#endif /* EAP_AKA_PRIME */
+               case EAP_SIM_AT_BIDDING:
+                       wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING");
+                       if (alen != 2) {
+                               wpa_printf(MSG_INFO, "EAP-AKA: Invalid "
+                                          "AT_BIDDING (len %lu)",
+                                          (unsigned long) alen);
+                               return -1;
+                       }
+                       attr->bidding = apos;
+                       break;
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
                default:
                        if (pos[0] < 128) {
                                wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
@@ -943,14 +1023,14 @@ struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut,
        eap = wpabuf_mhead(msg->buf);
        eap->length = host_to_be16(wpabuf_len(msg->buf));
 
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
        if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) {
                eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf),
                                       wpabuf_len(msg->buf),
                                       (u8 *) wpabuf_mhead(msg->buf) +
                                       msg->mac, extra, extra_len);
        } else
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
        if (k_aut && msg->mac) {
                eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf),
                                wpabuf_len(msg->buf),