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 1443382998 Lines: 85 127 66.9 %
Date: 2015-09-27 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         227 : void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
      20             : {
      21             :         struct pac_tlv_hdr hdr;
      22         227 :         hdr.type = host_to_be16(type);
      23         227 :         hdr.len = host_to_be16(len);
      24         227 :         wpabuf_put_data(buf, &hdr, sizeof(hdr));
      25         227 : }
      26             : 
      27             : 
      28          86 : void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data,
      29             :                              u16 len)
      30             : {
      31          86 :         eap_fast_put_tlv_hdr(buf, type, len);
      32          86 :         wpabuf_put_data(buf, data, len);
      33          86 : }
      34             : 
      35             : 
      36         117 : void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type,
      37             :                                  const struct wpabuf *data)
      38             : {
      39         117 :         eap_fast_put_tlv_hdr(buf, type, wpabuf_len(data));
      40         117 :         wpabuf_put_buf(buf, data);
      41         117 : }
      42             : 
      43             : 
      44         117 : struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf)
      45             : {
      46             :         struct wpabuf *e;
      47             : 
      48         117 :         if (buf == NULL)
      49           0 :                 return NULL;
      50             : 
      51             :         /* Encapsulate EAP packet in EAP-Payload TLV */
      52         117 :         wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV");
      53         117 :         e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf));
      54         117 :         if (e == NULL) {
      55           0 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory "
      56             :                            "for TLV encapsulation");
      57           0 :                 wpabuf_free(buf);
      58           0 :                 return NULL;
      59             :         }
      60         117 :         eap_fast_put_tlv_buf(e,
      61             :                              EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV,
      62             :                              buf);
      63         117 :         wpabuf_free(buf);
      64         117 :         return e;
      65             : }
      66             : 
      67             : 
      68          20 : 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          20 :         wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random",
      76             :                     client_random, TLS_RANDOM_LEN);
      77          20 :         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          20 :         os_memcpy(seed, server_random, TLS_RANDOM_LEN);
      86          20 :         os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN);
      87          20 :         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          20 :         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret",
      92             :                         master_secret, TLS_MASTER_SECRET_LEN);
      93          20 : }
      94             : 
      95             : 
      96          46 : u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
      97             :                          const char *label, size_t len)
      98             : {
      99             :         u8 *out;
     100             : 
     101          46 :         out = os_malloc(len);
     102          46 :         if (out == NULL)
     103           0 :                 return NULL;
     104             : 
     105          46 :         if (tls_connection_prf(ssl_ctx, conn, label, 1, 1, out, len)) {
     106           1 :                 os_free(out);
     107           1 :                 return NULL;
     108             :         }
     109             : 
     110          45 :         return out;
     111             : }
     112             : 
     113             : 
     114          33 : void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
     115             : {
     116             :         /*
     117             :          * RFC 4851, Section 5.4: EAP Master Session Key Generation
     118             :          * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64)
     119             :          */
     120             : 
     121          33 :         sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
     122             :                    "Session Key Generating Function", (u8 *) "", 0,
     123             :                    msk, EAP_FAST_KEY_LEN);
     124          33 :         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
     125             :                         msk, EAP_FAST_KEY_LEN);
     126          33 : }
     127             : 
     128             : 
     129          18 : void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk)
     130             : {
     131             :         /*
     132             :          * RFC 4851, Section 5.4: EAP Master Session Key Genreration
     133             :          * EMSK = T-PRF(S-IMCK[j],
     134             :          *        "Extended Session Key Generating Function", 64)
     135             :          */
     136             : 
     137          18 :         sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
     138             :                    "Extended Session Key Generating Function", (u8 *) "", 0,
     139             :                    emsk, EAP_EMSK_LEN);
     140          18 :         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
     141             :                         emsk, EAP_EMSK_LEN);
     142          18 : }
     143             : 
     144             : 
     145         271 : int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
     146             :                        int tlv_type, u8 *pos, size_t len)
     147             : {
     148         271 :         switch (tlv_type) {
     149             :         case EAP_TLV_EAP_PAYLOAD_TLV:
     150         117 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV",
     151             :                             pos, len);
     152         117 :                 if (tlv->eap_payload_tlv) {
     153           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     154             :                                    "EAP-Payload TLV in the message");
     155           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     156           0 :                         return -2;
     157             :                 }
     158         117 :                 tlv->eap_payload_tlv = pos;
     159         117 :                 tlv->eap_payload_tlv_len = len;
     160         117 :                 break;
     161             :         case EAP_TLV_RESULT_TLV:
     162          56 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len);
     163          56 :                 if (tlv->result) {
     164           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     165             :                                    "Result TLV in the message");
     166           0 :                         tlv->result = EAP_TLV_RESULT_FAILURE;
     167           0 :                         return -2;
     168             :                 }
     169          56 :                 if (len < 2) {
     170           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     171             :                                    "Result TLV");
     172           0 :                         tlv->result = EAP_TLV_RESULT_FAILURE;
     173           0 :                         break;
     174             :                 }
     175          56 :                 tlv->result = WPA_GET_BE16(pos);
     176          56 :                 if (tlv->result != EAP_TLV_RESULT_SUCCESS &&
     177           0 :                     tlv->result != EAP_TLV_RESULT_FAILURE) {
     178           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d",
     179             :                                    tlv->result);
     180           0 :                         tlv->result = EAP_TLV_RESULT_FAILURE;
     181             :                 }
     182          56 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s",
     183          56 :                            tlv->result == EAP_TLV_RESULT_SUCCESS ?
     184             :                            "Success" : "Failure");
     185          56 :                 break;
     186             :         case EAP_TLV_INTERMEDIATE_RESULT_TLV:
     187          14 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV",
     188             :                             pos, len);
     189          14 :                 if (len < 2) {
     190           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     191             :                                    "Intermediate-Result TLV");
     192           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     193           0 :                         break;
     194             :                 }
     195          14 :                 if (tlv->iresult) {
     196           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     197             :                                    "Intermediate-Result TLV in the message");
     198           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     199           0 :                         return -2;
     200             :                 }
     201          14 :                 tlv->iresult = WPA_GET_BE16(pos);
     202          14 :                 if (tlv->iresult != EAP_TLV_RESULT_SUCCESS &&
     203           0 :                     tlv->iresult != EAP_TLV_RESULT_FAILURE) {
     204           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate "
     205             :                                    "Result %d", tlv->iresult);
     206           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     207             :                 }
     208          14 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s",
     209          14 :                            tlv->iresult == EAP_TLV_RESULT_SUCCESS ?
     210             :                            "Success" : "Failure");
     211          14 :                 break;
     212             :         case EAP_TLV_CRYPTO_BINDING_TLV:
     213          44 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV",
     214             :                             pos, len);
     215          44 :                 if (tlv->crypto_binding) {
     216           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     217             :                                    "Crypto-Binding TLV in the message");
     218           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     219           0 :                         return -2;
     220             :                 }
     221          44 :                 tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len;
     222          44 :                 if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
     223           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     224             :                                    "Crypto-Binding TLV");
     225           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     226           0 :                         return -2;
     227             :                 }
     228          44 :                 tlv->crypto_binding = (struct eap_tlv_crypto_binding_tlv *)
     229             :                         (pos - sizeof(struct eap_tlv_hdr));
     230          44 :                 break;
     231             :         case EAP_TLV_REQUEST_ACTION_TLV:
     232           8 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV",
     233             :                             pos, len);
     234           8 :                 if (tlv->request_action) {
     235           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     236             :                                    "Request-Action TLV in the message");
     237           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     238           0 :                         return -2;
     239             :                 }
     240           8 :                 if (len < 2) {
     241           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
     242             :                                    "Request-Action TLV");
     243           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     244           0 :                         break;
     245             :                 }
     246           8 :                 tlv->request_action = WPA_GET_BE16(pos);
     247           8 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d",
     248             :                            tlv->request_action);
     249           8 :                 break;
     250             :         case EAP_TLV_PAC_TLV:
     251          32 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len);
     252          32 :                 if (tlv->pac) {
     253           0 :                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
     254             :                                    "PAC TLV in the message");
     255           0 :                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
     256           0 :                         return -2;
     257             :                 }
     258          32 :                 tlv->pac = pos;
     259          32 :                 tlv->pac_len = len;
     260          32 :                 break;
     261             :         default:
     262             :                 /* Unknown TLV */
     263           0 :                 return -1;
     264             :         }
     265             : 
     266         271 :         return 0;
     267             : }

Generated by: LCOV version 1.10