LCOV - code coverage report
Current view: top level - src/eap_common - eap_fast_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 128 129 99.2 %
Date: 2016-10-02 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP-FAST common helper functions (RFC 4851)
       3             :  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/sha1.h"
      13             : #include "crypto/tls.h"
      14             : #include "eap_defs.h"
      15             : #include "eap_tlv_common.h"
      16             : #include "eap_fast_common.h"
      17             : 
      18             : 
      19        1037 : void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
      20             : {
      21             :         struct pac_tlv_hdr hdr;
      22        1037 :         hdr.type = host_to_be16(type);
      23        1037 :         hdr.len = host_to_be16(len);
      24        1037 :         wpabuf_put_data(buf, &hdr, sizeof(hdr));
      25        1037 : }
      26             : 
      27             : 
      28         411 : void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data,
      29             :                              u16 len)
      30             : {
      31         411 :         eap_fast_put_tlv_hdr(buf, type, len);
      32         411 :         wpabuf_put_data(buf, data, len);
      33         411 : }
      34             : 
      35             : 
      36         518 : void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type,
      37             :                                  const struct wpabuf *data)
      38             : {
      39         518 :         eap_fast_put_tlv_hdr(buf, type, wpabuf_len(data));
      40         518 :         wpabuf_put_buf(buf, data);
      41         518 : }
      42             : 
      43             : 
      44         519 : struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf)
      45             : {
      46             :         struct wpabuf *e;
      47             : 
      48         519 :         if (buf == NULL)
      49           0 :                 return NULL;
      50             : 
      51             :         /* Encapsulate EAP packet in EAP-Payload TLV */
      52         519 :         wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV");
      53         519 :         e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf));
      54         519 :         if (e == NULL) {
      55           1 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory "
      56             :                            "for TLV encapsulation");
      57           1 :                 wpabuf_free(buf);
      58           1 :                 return NULL;
      59             :         }
      60         518 :         eap_fast_put_tlv_buf(e,
      61             :                              EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV,
      62             :                              buf);
      63         518 :         wpabuf_free(buf);
      64         518 :         return e;
      65             : }
      66             : 
      67             : 
      68          72 : void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random,
      69             :                                    const u8 *client_random, u8 *master_secret)
      70             : {
      71             : #define TLS_RANDOM_LEN 32
      72             : #define TLS_MASTER_SECRET_LEN 48
      73             :         u8 seed[2 * TLS_RANDOM_LEN];
      74             : 
      75          72 :         wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random",
      76             :                     client_random, TLS_RANDOM_LEN);
      77          72 :         wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random",
      78             :                     server_random, TLS_RANDOM_LEN);
      79             : 
      80             :         /*
      81             :          * RFC 4851, Section 5.1:
      82             :          * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", 
      83             :          *                       server_random + client_random, 48)
      84             :          */
      85          72 :         os_memcpy(seed, server_random, TLS_RANDOM_LEN);
      86          72 :         os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN);
      87          72 :         sha1_t_prf(pac_key, EAP_FAST_PAC_KEY_LEN,
      88             :                    "PAC to master secret label hash",
      89             :                    seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN);
      90             : 
      91          72 :         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret",
      92             :                         master_secret, TLS_MASTER_SECRET_LEN);
      93          72 : }
      94             : 
      95             : 
      96         233 : u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, size_t len)
      97             : {
      98             :         u8 *out;
      99             : 
     100         233 :         out = os_malloc(len);
     101         233 :         if (out == NULL)
     102           2 :                 return NULL;
     103             : 
     104         231 :         if (tls_connection_get_eap_fast_key(ssl_ctx, conn, out, len)) {
     105           1 :                 os_free(out);
     106           1 :                 return NULL;
     107             :         }
     108             : 
     109         230 :         return out;
     110             : }
     111             : 
     112             : 
     113         102 : int eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
     114             : {
     115             :         /*
     116             :          * RFC 4851, Section 5.4: EAP Master Session Key Generation
     117             :          * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64)
     118             :          */
     119             : 
     120         102 :         if (sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
     121             :                        "Session Key Generating Function", (u8 *) "", 0,
     122             :                        msk, EAP_FAST_KEY_LEN) < 0)
     123           1 :                 return -1;
     124         101 :         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
     125             :                         msk, EAP_FAST_KEY_LEN);
     126         101 :         return 0;
     127             : }
     128             : 
     129             : 
     130          56 : int eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk)
     131             : {
     132             :         /*
     133             :          * RFC 4851, Section 5.4: EAP Master Session Key Genreration
     134             :          * EMSK = T-PRF(S-IMCK[j],
     135             :          *        "Extended Session Key Generating Function", 64)
     136             :          */
     137             : 
     138          56 :         if (sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
     139             :                        "Extended Session Key Generating Function", (u8 *) "", 0,
     140             :                        emsk, EAP_EMSK_LEN) < 0)
     141           1 :                 return -1;
     142          55 :         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
     143             :                         emsk, EAP_EMSK_LEN);
     144          55 :         return 0;
     145             : }
     146             : 
     147             : 
     148        1170 : int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
     149             :                        int tlv_type, u8 *pos, size_t len)
     150             : {
     151        1170 :         switch (tlv_type) {
     152             :         case EAP_TLV_EAP_PAYLOAD_TLV:
     153         521 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV",
     154             :                             pos, len);
     155         521 :                 if (tlv->eap_payload_tlv) {
     156           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     157             :                                    "EAP-Payload TLV in the message");
     158           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     159           1 :                         return -2;
     160             :                 }
     161         520 :                 tlv->eap_payload_tlv = pos;
     162         520 :                 tlv->eap_payload_tlv_len = len;
     163         520 :                 break;
     164             :         case EAP_TLV_RESULT_TLV:
     165         218 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len);
     166         218 :                 if (tlv->result) {
     167           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     168             :                                    "Result TLV in the message");
     169           1 :                         tlv->result = EAP_TLV_RESULT_FAILURE;
     170           1 :                         return -2;
     171             :                 }
     172         217 :                 if (len < 2) {
     173           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     174             :                                    "Result TLV");
     175           1 :                         tlv->result = EAP_TLV_RESULT_FAILURE;
     176           1 :                         break;
     177             :                 }
     178         216 :                 tlv->result = WPA_GET_BE16(pos);
     179         222 :                 if (tlv->result != EAP_TLV_RESULT_SUCCESS &&
     180           6 :                     tlv->result != EAP_TLV_RESULT_FAILURE) {
     181           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d",
     182             :                                    tlv->result);
     183           1 :                         tlv->result = EAP_TLV_RESULT_FAILURE;
     184             :                 }
     185         216 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s",
     186         216 :                            tlv->result == EAP_TLV_RESULT_SUCCESS ?
     187             :                            "Success" : "Failure");
     188         216 :                 break;
     189             :         case EAP_TLV_INTERMEDIATE_RESULT_TLV:
     190          85 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV",
     191             :                             pos, len);
     192          85 :                 if (len < 2) {
     193           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     194             :                                    "Intermediate-Result TLV");
     195           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     196           1 :                         break;
     197             :                 }
     198          84 :                 if (tlv->iresult) {
     199           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     200             :                                    "Intermediate-Result TLV in the message");
     201           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     202           1 :                         return -2;
     203             :                 }
     204          83 :                 tlv->iresult = WPA_GET_BE16(pos);
     205          85 :                 if (tlv->iresult != EAP_TLV_RESULT_SUCCESS &&
     206           2 :                     tlv->iresult != EAP_TLV_RESULT_FAILURE) {
     207           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate "
     208             :                                    "Result %d", tlv->iresult);
     209           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     210             :                 }
     211          83 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s",
     212          83 :                            tlv->iresult == EAP_TLV_RESULT_SUCCESS ?
     213             :                            "Success" : "Failure");
     214          83 :                 break;
     215             :         case EAP_TLV_CRYPTO_BINDING_TLV:
     216         185 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV",
     217             :                             pos, len);
     218         185 :                 if (tlv->crypto_binding) {
     219           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     220             :                                    "Crypto-Binding TLV in the message");
     221           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     222           1 :                         return -2;
     223             :                 }
     224         184 :                 tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len;
     225         184 :                 if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
     226           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     227             :                                    "Crypto-Binding TLV");
     228           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     229           1 :                         return -2;
     230             :                 }
     231         183 :                 tlv->crypto_binding = (struct eap_tlv_crypto_binding_tlv *)
     232             :                         (pos - sizeof(struct eap_tlv_hdr));
     233         183 :                 break;
     234             :         case EAP_TLV_REQUEST_ACTION_TLV:
     235          25 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV",
     236             :                             pos, len);
     237          25 :                 if (tlv->request_action) {
     238           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     239             :                                    "Request-Action TLV in the message");
     240           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     241           1 :                         return -2;
     242             :                 }
     243          24 :                 if (len < 2) {
     244           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     245             :                                    "Request-Action TLV");
     246           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     247           1 :                         break;
     248             :                 }
     249          23 :                 tlv->request_action = WPA_GET_BE16(pos);
     250          23 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d",
     251             :                            tlv->request_action);
     252          23 :                 break;
     253             :         case EAP_TLV_PAC_TLV:
     254         133 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len);
     255         133 :                 if (tlv->pac) {
     256           1 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     257             :                                    "PAC TLV in the message");
     258           1 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     259           1 :                         return -2;
     260             :                 }
     261         132 :                 tlv->pac = pos;
     262         132 :                 tlv->pac_len = len;
     263         132 :                 break;
     264             :         default:
     265             :                 /* Unknown TLV */
     266           3 :                 return -1;
     267             :         }
     268             : 
     269        1160 :         return 0;
     270             : }

Generated by: LCOV version 1.10