LCOV - code coverage report
Current view: top level - src/eap_common - eap_fast_common.c (source / functions) Hit Total Coverage
Test: hostapd/hlr_auc_gw (AS) hwsim test run 1388167526 Lines: 87 149 58.4 %
Date: 2013-12-27 Functions: 8 9 88.9 %
Branches: 23 55 41.8 %

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

Generated by: LCOV version 1.9