LCOV - code coverage report
Current view: top level - src/eap_common - eap_eke_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 324 398 81.4 %
Date: 2015-09-27 Functions: 26 26 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP server/peer: EAP-EKE shared routines
       3             :  * Copyright (c) 2011-2013, 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/aes.h"
      13             : #include "crypto/aes_wrap.h"
      14             : #include "crypto/crypto.h"
      15             : #include "crypto/dh_groups.h"
      16             : #include "crypto/random.h"
      17             : #include "crypto/sha1.h"
      18             : #include "crypto/sha256.h"
      19             : #include "eap_common/eap_defs.h"
      20             : #include "eap_eke_common.h"
      21             : 
      22             : 
      23         168 : static int eap_eke_dh_len(u8 group)
      24             : {
      25         168 :         switch (group) {
      26             :         case EAP_EKE_DHGROUP_EKE_2:
      27           4 :                 return 128;
      28             :         case EAP_EKE_DHGROUP_EKE_5:
      29           0 :                 return 192;
      30             :         case EAP_EKE_DHGROUP_EKE_14:
      31          12 :                 return 256;
      32             :         case EAP_EKE_DHGROUP_EKE_15:
      33           4 :                 return 384;
      34             :         case EAP_EKE_DHGROUP_EKE_16:
      35         148 :                 return 512;
      36             :         }
      37             : 
      38           0 :         return -1;
      39             : }
      40             : 
      41             : 
      42         100 : static int eap_eke_dhcomp_len(u8 dhgroup, u8 encr)
      43             : {
      44             :         int dhlen;
      45             : 
      46         100 :         dhlen = eap_eke_dh_len(dhgroup);
      47         100 :         if (dhlen < 0)
      48           0 :                 return -1;
      49         100 :         if (encr != EAP_EKE_ENCR_AES128_CBC)
      50           0 :                 return -1;
      51         100 :         return AES_BLOCK_SIZE + dhlen;
      52             : }
      53             : 
      54             : 
      55         134 : static const struct dh_group * eap_eke_dh_group(u8 group)
      56             : {
      57         134 :         switch (group) {
      58             :         case EAP_EKE_DHGROUP_EKE_2:
      59           4 :                 return dh_groups_get(2);
      60             :         case EAP_EKE_DHGROUP_EKE_5:
      61           0 :                 return dh_groups_get(5);
      62             :         case EAP_EKE_DHGROUP_EKE_14:
      63           8 :                 return dh_groups_get(14);
      64             :         case EAP_EKE_DHGROUP_EKE_15:
      65           4 :                 return dh_groups_get(15);
      66             :         case EAP_EKE_DHGROUP_EKE_16:
      67         118 :                 return dh_groups_get(16);
      68             :         }
      69             : 
      70           0 :         return NULL;
      71             : }
      72             : 
      73             : 
      74          68 : static int eap_eke_dh_generator(u8 group)
      75             : {
      76          68 :         switch (group) {
      77             :         case EAP_EKE_DHGROUP_EKE_2:
      78           2 :                 return 5;
      79             :         case EAP_EKE_DHGROUP_EKE_5:
      80           0 :                 return 31;
      81             :         case EAP_EKE_DHGROUP_EKE_14:
      82           4 :                 return 11;
      83             :         case EAP_EKE_DHGROUP_EKE_15:
      84           2 :                 return 5;
      85             :         case EAP_EKE_DHGROUP_EKE_16:
      86          60 :                 return 5;
      87             :         }
      88             : 
      89           0 :         return -1;
      90             : }
      91             : 
      92             : 
      93         100 : static int eap_eke_pnonce_len(u8 mac)
      94             : {
      95             :         int mac_len;
      96             : 
      97         100 :         if (mac == EAP_EKE_MAC_HMAC_SHA1)
      98           8 :                 mac_len = SHA1_MAC_LEN;
      99          92 :         else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
     100          92 :                 mac_len = SHA256_MAC_LEN;
     101             :         else
     102           0 :                 return -1;
     103             : 
     104         100 :         return AES_BLOCK_SIZE + 16 + mac_len;
     105             : }
     106             : 
     107             : 
     108         100 : static int eap_eke_pnonce_ps_len(u8 mac)
     109             : {
     110             :         int mac_len;
     111             : 
     112         100 :         if (mac == EAP_EKE_MAC_HMAC_SHA1)
     113           8 :                 mac_len = SHA1_MAC_LEN;
     114          92 :         else if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
     115          92 :                 mac_len = SHA256_MAC_LEN;
     116             :         else
     117           0 :                 return -1;
     118             : 
     119         100 :         return AES_BLOCK_SIZE + 2 * 16 + mac_len;
     120             : }
     121             : 
     122             : 
     123         200 : static int eap_eke_prf_len(u8 prf)
     124             : {
     125         200 :         if (prf == EAP_EKE_PRF_HMAC_SHA1)
     126          16 :                 return 20;
     127         184 :         if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
     128         184 :                 return 32;
     129           0 :         return -1;
     130             : }
     131             : 
     132             : 
     133         100 : static int eap_eke_nonce_len(u8 prf)
     134             : {
     135             :         int prf_len;
     136             : 
     137         100 :         prf_len = eap_eke_prf_len(prf);
     138         100 :         if (prf_len < 0)
     139           0 :                 return -1;
     140             : 
     141         100 :         if (prf_len > 2 * 16)
     142           0 :                 return (prf_len + 1) / 2;
     143             : 
     144         100 :         return 16;
     145             : }
     146             : 
     147             : 
     148         100 : static int eap_eke_auth_len(u8 prf)
     149             : {
     150         100 :         switch (prf) {
     151             :         case EAP_EKE_PRF_HMAC_SHA1:
     152           8 :                 return SHA1_MAC_LEN;
     153             :         case EAP_EKE_PRF_HMAC_SHA2_256:
     154          92 :                 return SHA256_MAC_LEN;
     155             :         }
     156             : 
     157           0 :         return -1;
     158             : }
     159             : 
     160             : 
     161          68 : int eap_eke_dh_init(u8 group, u8 *ret_priv, u8 *ret_pub)
     162             : {
     163             :         int generator;
     164             :         u8 gen;
     165             :         const struct dh_group *dh;
     166             :         size_t pub_len, i;
     167             : 
     168          68 :         generator = eap_eke_dh_generator(group);
     169          68 :         if (generator < 0 || generator > 255)
     170           0 :                 return -1;
     171          68 :         gen = generator;
     172             : 
     173          68 :         dh = eap_eke_dh_group(group);
     174          68 :         if (dh == NULL)
     175           0 :                 return -1;
     176             : 
     177             :         /* x = random number 2 .. p-1 */
     178          68 :         if (random_get_bytes(ret_priv, dh->prime_len))
     179           0 :                 return -1;
     180          68 :         if (os_memcmp(ret_priv, dh->prime, dh->prime_len) > 0) {
     181             :                 /* Make sure private value is smaller than prime */
     182           0 :                 ret_priv[0] = 0;
     183             :         }
     184          68 :         for (i = 0; i < dh->prime_len - 1; i++) {
     185          68 :                 if (ret_priv[i])
     186          68 :                         break;
     187             :         }
     188          68 :         if (i == dh->prime_len - 1 && (ret_priv[i] == 0 || ret_priv[i] == 1))
     189           0 :                 return -1;
     190          68 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: DH private value",
     191             :                         ret_priv, dh->prime_len);
     192             : 
     193             :         /* y = g ^ x (mod p) */
     194          68 :         pub_len = dh->prime_len;
     195          68 :         if (crypto_mod_exp(&gen, 1, ret_priv, dh->prime_len,
     196             :                            dh->prime, dh->prime_len, ret_pub, &pub_len) < 0)
     197           0 :                 return -1;
     198          68 :         if (pub_len < dh->prime_len) {
     199           0 :                 size_t pad = dh->prime_len - pub_len;
     200           0 :                 os_memmove(ret_pub + pad, ret_pub, pub_len);
     201           0 :                 os_memset(ret_pub, 0, pad);
     202             :         }
     203             : 
     204          68 :         wpa_hexdump(MSG_DEBUG, "EAP-EKE: DH public value",
     205             :                     ret_pub, dh->prime_len);
     206             : 
     207          68 :         return 0;
     208             : }
     209             : 
     210             : 
     211         204 : static int eap_eke_prf(u8 prf, const u8 *key, size_t key_len, const u8 *data,
     212             :                        size_t data_len, const u8 *data2, size_t data2_len,
     213             :                        u8 *res)
     214             : {
     215             :         const u8 *addr[2];
     216             :         size_t len[2];
     217         204 :         size_t num_elem = 1;
     218             : 
     219         204 :         addr[0] = data;
     220         204 :         len[0] = data_len;
     221         204 :         if (data2) {
     222          66 :                 num_elem++;
     223          66 :                 addr[1] = data2;
     224          66 :                 len[1] = data2_len;
     225             :         }
     226             : 
     227         204 :         if (prf == EAP_EKE_PRF_HMAC_SHA1)
     228          12 :                 return hmac_sha1_vector(key, key_len, num_elem, addr, len, res);
     229         192 :         if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
     230         192 :                 return hmac_sha256_vector(key, key_len, num_elem, addr, len,
     231             :                                           res);
     232           0 :         return -1;
     233             : }
     234             : 
     235             : 
     236          12 : static int eap_eke_prf_hmac_sha1(const u8 *key, size_t key_len, const u8 *data,
     237             :                                  size_t data_len, u8 *res, size_t len)
     238             : {
     239             :         u8 hash[SHA1_MAC_LEN];
     240             :         u8 idx;
     241             :         const u8 *addr[3];
     242             :         size_t vlen[3];
     243             :         int ret;
     244             : 
     245          12 :         idx = 0;
     246          12 :         addr[0] = hash;
     247          12 :         vlen[0] = SHA1_MAC_LEN;
     248          12 :         addr[1] = data;
     249          12 :         vlen[1] = data_len;
     250          12 :         addr[2] = &idx;
     251          12 :         vlen[2] = 1;
     252             : 
     253          52 :         while (len > 0) {
     254          28 :                 idx++;
     255          28 :                 if (idx == 1)
     256          12 :                         ret = hmac_sha1_vector(key, key_len, 2, &addr[1],
     257             :                                                &vlen[1], hash);
     258             :                 else
     259          16 :                         ret = hmac_sha1_vector(key, key_len, 3, addr, vlen,
     260             :                                                hash);
     261          28 :                 if (ret < 0)
     262           0 :                         return -1;
     263          28 :                 if (len > SHA1_MAC_LEN) {
     264          16 :                         os_memcpy(res, hash, SHA1_MAC_LEN);
     265          16 :                         res += SHA1_MAC_LEN;
     266          16 :                         len -= SHA1_MAC_LEN;
     267             :                 } else {
     268          12 :                         os_memcpy(res, hash, len);
     269          12 :                         len = 0;
     270             :                 }
     271             :         }
     272             : 
     273          12 :         return 0;
     274             : }
     275             : 
     276             : 
     277         187 : static int eap_eke_prf_hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
     278             :                                    size_t data_len, u8 *res, size_t len)
     279             : {
     280             :         u8 hash[SHA256_MAC_LEN];
     281             :         u8 idx;
     282             :         const u8 *addr[3];
     283             :         size_t vlen[3];
     284             :         int ret;
     285             : 
     286         187 :         idx = 0;
     287         187 :         addr[0] = hash;
     288         187 :         vlen[0] = SHA256_MAC_LEN;
     289         187 :         addr[1] = data;
     290         187 :         vlen[1] = data_len;
     291         187 :         addr[2] = &idx;
     292         187 :         vlen[2] = 1;
     293             : 
     294         702 :         while (len > 0) {
     295         328 :                 idx++;
     296         328 :                 if (idx == 1)
     297         187 :                         ret = hmac_sha256_vector(key, key_len, 2, &addr[1],
     298             :                                                  &vlen[1], hash);
     299             :                 else
     300         141 :                         ret = hmac_sha256_vector(key, key_len, 3, addr, vlen,
     301             :                                                  hash);
     302         328 :                 if (ret < 0)
     303           0 :                         return -1;
     304         328 :                 if (len > SHA256_MAC_LEN) {
     305         141 :                         os_memcpy(res, hash, SHA256_MAC_LEN);
     306         141 :                         res += SHA256_MAC_LEN;
     307         141 :                         len -= SHA256_MAC_LEN;
     308             :                 } else {
     309         187 :                         os_memcpy(res, hash, len);
     310         187 :                         len = 0;
     311             :                 }
     312             :         }
     313             : 
     314         187 :         return 0;
     315             : }
     316             : 
     317             : 
     318         199 : static int eap_eke_prfplus(u8 prf, const u8 *key, size_t key_len,
     319             :                            const u8 *data, size_t data_len, u8 *res, size_t len)
     320             : {
     321         199 :         if (prf == EAP_EKE_PRF_HMAC_SHA1)
     322          12 :                 return eap_eke_prf_hmac_sha1(key, key_len, data, data_len, res,
     323             :                                              len);
     324         187 :         if (prf == EAP_EKE_PRF_HMAC_SHA2_256)
     325         187 :                 return eap_eke_prf_hmac_sha256(key, key_len, data, data_len,
     326             :                                                res, len);
     327           0 :         return -1;
     328             : }
     329             : 
     330             : 
     331          72 : int eap_eke_derive_key(struct eap_eke_session *sess,
     332             :                        const u8 *password, size_t password_len,
     333             :                        const u8 *id_s, size_t id_s_len, const u8 *id_p,
     334             :                        size_t id_p_len, u8 *key)
     335             : {
     336             :         u8 zeros[EAP_EKE_MAX_HASH_LEN];
     337             :         u8 temp[EAP_EKE_MAX_HASH_LEN];
     338          72 :         size_t key_len = 16; /* Only AES-128-CBC is used here */
     339             :         u8 *id;
     340             : 
     341             :         /* temp = prf(0+, password) */
     342          72 :         os_memset(zeros, 0, sess->prf_len);
     343          72 :         if (eap_eke_prf(sess->prf, zeros, sess->prf_len,
     344             :                         password, password_len, NULL, 0, temp) < 0)
     345           0 :                 return -1;
     346          72 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: temp = prf(0+, password)",
     347          72 :                         temp, sess->prf_len);
     348             : 
     349             :         /* key = prf+(temp, ID_S | ID_P) */
     350          72 :         id = os_malloc(id_s_len + id_p_len);
     351          72 :         if (id == NULL)
     352           2 :                 return -1;
     353          70 :         os_memcpy(id, id_s, id_s_len);
     354          70 :         os_memcpy(id + id_s_len, id_p, id_p_len);
     355          70 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: ID_S | ID_P",
     356             :                           id, id_s_len + id_p_len);
     357          70 :         if (eap_eke_prfplus(sess->prf, temp, sess->prf_len,
     358             :                             id, id_s_len + id_p_len, key, key_len) < 0) {
     359           0 :                 os_free(id);
     360           0 :                 return -1;
     361             :         }
     362          70 :         os_free(id);
     363          70 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: key = prf+(temp, ID_S | ID_P)",
     364             :                         key, key_len);
     365             : 
     366          70 :         return 0;
     367             : }
     368             : 
     369             : 
     370          68 : int eap_eke_dhcomp(struct eap_eke_session *sess, const u8 *key, const u8 *dhpub,
     371             :                    u8 *ret_dhcomp)
     372             : {
     373             :         u8 pub[EAP_EKE_MAX_DH_LEN];
     374             :         int dh_len;
     375             :         u8 iv[AES_BLOCK_SIZE];
     376             : 
     377          68 :         dh_len = eap_eke_dh_len(sess->dhgroup);
     378          68 :         if (dh_len < 0)
     379           0 :                 return -1;
     380             : 
     381             :         /*
     382             :          * DHComponent = Encr(key, y)
     383             :          *
     384             :          * All defined DH groups use primes that have length devisible by 16, so
     385             :          * no need to do extra padding for y (= pub).
     386             :          */
     387          68 :         if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
     388           0 :                 return -1;
     389          68 :         if (random_get_bytes(iv, AES_BLOCK_SIZE))
     390           0 :                 return -1;
     391          68 :         wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Encr(key, y)",
     392             :                     iv, AES_BLOCK_SIZE);
     393          68 :         os_memcpy(pub, dhpub, dh_len);
     394          68 :         if (aes_128_cbc_encrypt(key, iv, pub, dh_len) < 0)
     395           0 :                 return -1;
     396          68 :         os_memcpy(ret_dhcomp, iv, AES_BLOCK_SIZE);
     397          68 :         os_memcpy(ret_dhcomp + AES_BLOCK_SIZE, pub, dh_len);
     398          68 :         wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent = Encr(key, y)",
     399          68 :                     ret_dhcomp, AES_BLOCK_SIZE + dh_len);
     400             : 
     401          68 :         return 0;
     402             : }
     403             : 
     404             : 
     405          66 : int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key,
     406             :                           const u8 *dhpriv, const u8 *peer_dhcomp)
     407             : {
     408             :         u8 zeros[EAP_EKE_MAX_HASH_LEN];
     409             :         u8 peer_pub[EAP_EKE_MAX_DH_LEN];
     410             :         u8 modexp[EAP_EKE_MAX_DH_LEN];
     411             :         size_t len;
     412             :         const struct dh_group *dh;
     413             : 
     414          66 :         if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
     415           0 :                 return -1;
     416             : 
     417          66 :         dh = eap_eke_dh_group(sess->dhgroup);
     418          66 :         if (dh == NULL)
     419           0 :                 return -1;
     420             : 
     421             :         /* Decrypt peer DHComponent */
     422          66 :         os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len);
     423          66 :         if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) {
     424           0 :                 wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent");
     425           0 :                 return -1;
     426             :         }
     427          66 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey",
     428             :                         peer_pub, dh->prime_len);
     429             : 
     430             :         /* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */
     431          66 :         len = dh->prime_len;
     432          66 :         if (crypto_mod_exp(peer_pub, dh->prime_len, dhpriv, dh->prime_len,
     433             :                            dh->prime, dh->prime_len, modexp, &len) < 0)
     434           0 :                 return -1;
     435          66 :         if (len < dh->prime_len) {
     436           2 :                 size_t pad = dh->prime_len - len;
     437           2 :                 os_memmove(modexp + pad, modexp, len);
     438           2 :                 os_memset(modexp, 0, pad);
     439             :         }
     440             : 
     441          66 :         os_memset(zeros, 0, sess->auth_len);
     442          66 :         if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len,
     443          66 :                         NULL, 0, sess->shared_secret) < 0)
     444           0 :                 return -1;
     445         132 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret",
     446         132 :                         sess->shared_secret, sess->auth_len);
     447             : 
     448          66 :         return 0;
     449             : }
     450             : 
     451             : 
     452          66 : int eap_eke_derive_ke_ki(struct eap_eke_session *sess,
     453             :                          const u8 *id_s, size_t id_s_len,
     454             :                          const u8 *id_p, size_t id_p_len)
     455             : {
     456             :         u8 buf[EAP_EKE_MAX_KE_LEN + EAP_EKE_MAX_KI_LEN];
     457             :         size_t ke_len, ki_len;
     458             :         u8 *data;
     459             :         size_t data_len;
     460          66 :         const char *label = "EAP-EKE Keys";
     461             :         size_t label_len;
     462             : 
     463             :         /*
     464             :          * Ke | Ki = prf+(SharedSecret, "EAP-EKE Keys" | ID_S | ID_P)
     465             :          * Ke = encryption key
     466             :          * Ki = integrity protection key
     467             :          * Length of each key depends on the selected algorithms.
     468             :          */
     469             : 
     470          66 :         if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
     471          66 :                 ke_len = 16;
     472             :         else
     473           0 :                 return -1;
     474             : 
     475          66 :         if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
     476           4 :                 ki_len = 20;
     477          62 :         else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
     478          62 :                 ki_len = 32;
     479             :         else
     480           0 :                 return -1;
     481             : 
     482          66 :         label_len = os_strlen(label);
     483          66 :         data_len = label_len + id_s_len + id_p_len;
     484          66 :         data = os_malloc(data_len);
     485          66 :         if (data == NULL)
     486           2 :                 return -1;
     487          64 :         os_memcpy(data, label, label_len);
     488          64 :         os_memcpy(data + label_len, id_s, id_s_len);
     489          64 :         os_memcpy(data + label_len + id_s_len, id_p, id_p_len);
     490          64 :         if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
     491             :                             data, data_len, buf, ke_len + ki_len) < 0) {
     492           0 :                 os_free(data);
     493           0 :                 return -1;
     494             :         }
     495             : 
     496          64 :         os_memcpy(sess->ke, buf, ke_len);
     497          64 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ke", sess->ke, ke_len);
     498          64 :         os_memcpy(sess->ki, buf + ke_len, ki_len);
     499          64 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ki", sess->ki, ki_len);
     500             : 
     501          64 :         os_free(data);
     502          64 :         return 0;
     503             : }
     504             : 
     505             : 
     506          38 : int eap_eke_derive_ka(struct eap_eke_session *sess,
     507             :                       const u8 *id_s, size_t id_s_len,
     508             :                       const u8 *id_p, size_t id_p_len,
     509             :                       const u8 *nonce_p, const u8 *nonce_s)
     510             : {
     511             :         u8 *data, *pos;
     512             :         size_t data_len;
     513          38 :         const char *label = "EAP-EKE Ka";
     514             :         size_t label_len;
     515             : 
     516             :         /*
     517             :          * Ka = prf+(SharedSecret, "EAP-EKE Ka" | ID_S | ID_P | Nonce_P |
     518             :          *           Nonce_S)
     519             :          * Ka = authentication key
     520             :          * Length of the key depends on the selected algorithms.
     521             :          */
     522             : 
     523          38 :         label_len = os_strlen(label);
     524          38 :         data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
     525          38 :         data = os_malloc(data_len);
     526          38 :         if (data == NULL)
     527           2 :                 return -1;
     528          36 :         pos = data;
     529          36 :         os_memcpy(pos, label, label_len);
     530          36 :         pos += label_len;
     531          36 :         os_memcpy(pos, id_s, id_s_len);
     532          36 :         pos += id_s_len;
     533          36 :         os_memcpy(pos, id_p, id_p_len);
     534          36 :         pos += id_p_len;
     535          36 :         os_memcpy(pos, nonce_p, sess->nonce_len);
     536          36 :         pos += sess->nonce_len;
     537          36 :         os_memcpy(pos, nonce_s, sess->nonce_len);
     538          72 :         if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
     539          72 :                             data, data_len, sess->ka, sess->prf_len) < 0) {
     540           0 :                 os_free(data);
     541           0 :                 return -1;
     542             :         }
     543          36 :         os_free(data);
     544             : 
     545          36 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka", sess->ka, sess->prf_len);
     546             : 
     547          36 :         return 0;
     548             : }
     549             : 
     550             : 
     551          30 : int eap_eke_derive_msk(struct eap_eke_session *sess,
     552             :                        const u8 *id_s, size_t id_s_len,
     553             :                        const u8 *id_p, size_t id_p_len,
     554             :                        const u8 *nonce_p, const u8 *nonce_s,
     555             :                        u8 *msk, u8 *emsk)
     556             : {
     557             :         u8 *data, *pos;
     558             :         size_t data_len;
     559          30 :         const char *label = "EAP-EKE Exported Keys";
     560             :         size_t label_len;
     561             :         u8 buf[EAP_MSK_LEN + EAP_EMSK_LEN];
     562             : 
     563             :         /*
     564             :          * MSK | EMSK = prf+(SharedSecret, "EAP-EKE Exported Keys" | ID_S |
     565             :          *                   ID_P | Nonce_P | Nonce_S)
     566             :          */
     567             : 
     568          30 :         label_len = os_strlen(label);
     569          30 :         data_len = label_len + id_s_len + id_p_len + 2 * sess->nonce_len;
     570          30 :         data = os_malloc(data_len);
     571          30 :         if (data == NULL)
     572           1 :                 return -1;
     573          29 :         pos = data;
     574          29 :         os_memcpy(pos, label, label_len);
     575          29 :         pos += label_len;
     576          29 :         os_memcpy(pos, id_s, id_s_len);
     577          29 :         pos += id_s_len;
     578          29 :         os_memcpy(pos, id_p, id_p_len);
     579          29 :         pos += id_p_len;
     580          29 :         os_memcpy(pos, nonce_p, sess->nonce_len);
     581          29 :         pos += sess->nonce_len;
     582          29 :         os_memcpy(pos, nonce_s, sess->nonce_len);
     583          29 :         if (eap_eke_prfplus(sess->prf, sess->shared_secret, sess->prf_len,
     584             :                             data, data_len, buf, EAP_MSK_LEN + EAP_EMSK_LEN) <
     585             :             0) {
     586           0 :                 os_free(data);
     587           0 :                 return -1;
     588             :         }
     589          29 :         os_free(data);
     590             : 
     591          29 :         os_memcpy(msk, buf, EAP_MSK_LEN);
     592          29 :         os_memcpy(emsk, buf + EAP_MSK_LEN, EAP_EMSK_LEN);
     593          29 :         os_memset(buf, 0, sizeof(buf));
     594             : 
     595          29 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: MSK", msk, EAP_MSK_LEN);
     596          29 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: EMSK", msk, EAP_EMSK_LEN);
     597             : 
     598          29 :         return 0;
     599             : }
     600             : 
     601             : 
     602         133 : static int eap_eke_mac(u8 mac, const u8 *key, const u8 *data, size_t data_len,
     603             :                        u8 *res)
     604             : {
     605         133 :         if (mac == EAP_EKE_MAC_HMAC_SHA1)
     606           9 :                 return hmac_sha1(key, SHA1_MAC_LEN, data, data_len, res);
     607         124 :         if (mac == EAP_EKE_MAC_HMAC_SHA2_256)
     608         124 :                 return hmac_sha256(key, SHA256_MAC_LEN, data, data_len, res);
     609           0 :         return -1;
     610             : }
     611             : 
     612             : 
     613          72 : int eap_eke_prot(struct eap_eke_session *sess,
     614             :                  const u8 *data, size_t data_len,
     615             :                  u8 *prot, size_t *prot_len)
     616             : {
     617             :         size_t block_size, icv_len, pad;
     618             :         u8 *pos, *iv, *e;
     619             : 
     620          72 :         if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
     621          72 :                 block_size = AES_BLOCK_SIZE;
     622             :         else
     623           0 :                 return -1;
     624             : 
     625          72 :         if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
     626           5 :                 icv_len = SHA1_MAC_LEN;
     627          67 :         else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
     628          67 :                 icv_len = SHA256_MAC_LEN;
     629             :         else
     630           0 :                 return -1;
     631             : 
     632          72 :         pad = data_len % block_size;
     633          72 :         if (pad)
     634           0 :                 pad = block_size - pad;
     635             : 
     636          72 :         if (*prot_len < block_size + data_len + pad + icv_len) {
     637           0 :                 wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
     638             :         }
     639          72 :         pos = prot;
     640             : 
     641          72 :         if (random_get_bytes(pos, block_size))
     642           0 :                 return -1;
     643          72 :         iv = pos;
     644          72 :         wpa_hexdump(MSG_DEBUG, "EAP-EKE: IV for Prot()", iv, block_size);
     645          72 :         pos += block_size;
     646             : 
     647          72 :         e = pos;
     648          72 :         os_memcpy(pos, data, data_len);
     649          72 :         pos += data_len;
     650          72 :         if (pad) {
     651           0 :                 if (random_get_bytes(pos, pad))
     652           0 :                         return -1;
     653           0 :                 pos += pad;
     654             :         }
     655             : 
     656          72 :         if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0)
     657           0 :                 return -1;
     658             : 
     659          72 :         if (eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
     660           0 :                 return -1;
     661          72 :         pos += icv_len;
     662             : 
     663          72 :         *prot_len = pos - prot;
     664          72 :         return 0;
     665             : }
     666             : 
     667             : 
     668          61 : int eap_eke_decrypt_prot(struct eap_eke_session *sess,
     669             :                          const u8 *prot, size_t prot_len,
     670             :                          u8 *data, size_t *data_len)
     671             : {
     672             :         size_t block_size, icv_len;
     673             :         u8 icv[EAP_EKE_MAX_HASH_LEN];
     674             : 
     675          61 :         if (sess->encr == EAP_EKE_ENCR_AES128_CBC)
     676          61 :                 block_size = AES_BLOCK_SIZE;
     677             :         else
     678           0 :                 return -1;
     679             : 
     680          61 :         if (sess->mac == EAP_EKE_PRF_HMAC_SHA1)
     681           4 :                 icv_len = SHA1_MAC_LEN;
     682          57 :         else if (sess->mac == EAP_EKE_PRF_HMAC_SHA2_256)
     683          57 :                 icv_len = SHA256_MAC_LEN;
     684             :         else
     685           0 :                 return -1;
     686             : 
     687          61 :         if (prot_len < 2 * block_size + icv_len)
     688           0 :                 return -1;
     689          61 :         if ((prot_len - icv_len) % block_size)
     690           0 :                 return -1;
     691             : 
     692          61 :         if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
     693          61 :                         prot_len - block_size - icv_len, icv) < 0)
     694           0 :                 return -1;
     695          61 :         if (os_memcmp_const(icv, prot + prot_len - icv_len, icv_len) != 0) {
     696           3 :                 wpa_printf(MSG_INFO, "EAP-EKE: ICV mismatch in Prot() data");
     697           3 :                 return -1;
     698             :         }
     699             : 
     700          58 :         if (*data_len < prot_len - block_size - icv_len) {
     701           0 :                 wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for decrypted Prot() data");
     702           0 :                 return -1;
     703             :         }
     704             : 
     705          58 :         *data_len = prot_len - block_size - icv_len;
     706          58 :         os_memcpy(data, prot + block_size, *data_len);
     707          58 :         if (aes_128_cbc_decrypt(sess->ke, prot, data, *data_len) < 0) {
     708           0 :                 wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt Prot() data");
     709           0 :                 return -1;
     710             :         }
     711          58 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted Prot() data",
     712             :                         data, *data_len);
     713             : 
     714          58 :         return 0;
     715             : }
     716             : 
     717             : 
     718          66 : int eap_eke_auth(struct eap_eke_session *sess, const char *label,
     719             :                  const struct wpabuf *msgs, u8 *auth)
     720             : {
     721          66 :         wpa_printf(MSG_DEBUG, "EAP-EKE: Auth(%s)", label);
     722         132 :         wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Ka for Auth",
     723         132 :                         sess->ka, sess->auth_len);
     724          66 :         wpa_hexdump_buf(MSG_MSGDUMP, "EAP-EKE: Messages for Auth", msgs);
     725         132 :         return eap_eke_prf(sess->prf, sess->ka, sess->auth_len,
     726             :                            (const u8 *) label, os_strlen(label),
     727          66 :                            wpabuf_head(msgs), wpabuf_len(msgs), auth);
     728             : }
     729             : 
     730             : 
     731         100 : int eap_eke_session_init(struct eap_eke_session *sess, u8 dhgroup, u8 encr,
     732             :                          u8 prf, u8 mac)
     733             : {
     734         100 :         sess->dhgroup = dhgroup;
     735         100 :         sess->encr = encr;
     736         100 :         sess->prf = prf;
     737         100 :         sess->mac = mac;
     738             : 
     739         100 :         sess->prf_len = eap_eke_prf_len(prf);
     740         100 :         if (sess->prf_len < 0)
     741           0 :                 return -1;
     742         100 :         sess->nonce_len = eap_eke_nonce_len(prf);
     743         100 :         if (sess->nonce_len < 0)
     744           0 :                 return -1;
     745         100 :         sess->auth_len = eap_eke_auth_len(prf);
     746         100 :         if (sess->auth_len < 0)
     747           0 :                 return -1;
     748         100 :         sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
     749         100 :         if (sess->dhcomp_len < 0)
     750           0 :                 return -1;
     751         100 :         sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
     752         100 :         if (sess->pnonce_len < 0)
     753           0 :                 return -1;
     754         100 :         sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
     755         100 :         if (sess->pnonce_ps_len < 0)
     756           0 :                 return -1;
     757             : 
     758         100 :         return 0;
     759             : }
     760             : 
     761             : 
     762         185 : void eap_eke_session_clean(struct eap_eke_session *sess)
     763             : {
     764         185 :         os_memset(sess->shared_secret, 0, EAP_EKE_MAX_HASH_LEN);
     765         185 :         os_memset(sess->ke, 0, EAP_EKE_MAX_KE_LEN);
     766         185 :         os_memset(sess->ki, 0, EAP_EKE_MAX_KI_LEN);
     767         185 :         os_memset(sess->ka, 0, EAP_EKE_MAX_KA_LEN);
     768         185 : }

Generated by: LCOV version 1.10