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

Generated by: LCOV version 1.10