LCOV - code coverage report
Current view: top level - src/eap_common - eap_gpsk_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 192 209 91.9 %
Date: 2016-10-02 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP server/peer: EAP-GPSK shared routines
       3             :  * Copyright (c) 2006-2007, 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_wrap.h"
      13             : #include "crypto/sha256.h"
      14             : #include "eap_defs.h"
      15             : #include "eap_gpsk_common.h"
      16             : 
      17             : 
      18             : /**
      19             :  * eap_gpsk_supported_ciphersuite - Check whether ciphersuite is supported
      20             :  * @vendor: CSuite/Vendor
      21             :  * @specifier: CSuite/Specifier
      22             :  * Returns: 1 if ciphersuite is support, or 0 if not
      23             :  */
      24        1074 : int eap_gpsk_supported_ciphersuite(int vendor, int specifier)
      25             : {
      26        1074 :         if (vendor == EAP_GPSK_VENDOR_IETF &&
      27             :             specifier == EAP_GPSK_CIPHER_AES)
      28         714 :                 return 1;
      29             : #ifdef EAP_GPSK_SHA256
      30         360 :         if (vendor == EAP_GPSK_VENDOR_IETF &&
      31             :             specifier == EAP_GPSK_CIPHER_SHA256)
      32         359 :                 return 1;
      33             : #endif /* EAP_GPSK_SHA256 */
      34           1 :         return 0;
      35             : }
      36             : 
      37             : 
      38        2019 : static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */,
      39             :                               const u8 *data /* Z */, size_t data_len,
      40             :                               u8 *buf, size_t len /* X */)
      41             : {
      42             :         u8 *opos;
      43             :         size_t i, n, hashlen, left, clen;
      44             :         u8 ibuf[2], hash[16];
      45             :         const u8 *addr[2];
      46             :         size_t vlen[2];
      47             : 
      48        2019 :         hashlen = sizeof(hash);
      49             :         /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */
      50        2019 :         addr[0] = ibuf;
      51        2019 :         vlen[0] = sizeof(ibuf);
      52        2019 :         addr[1] = data;
      53        2019 :         vlen[1] = data_len;
      54             : 
      55        2019 :         opos = buf;
      56        2019 :         left = len;
      57        2019 :         n = (len + hashlen - 1) / hashlen;
      58       10091 :         for (i = 1; i <= n; i++) {
      59        8076 :                 WPA_PUT_BE16(ibuf, i);
      60        8076 :                 if (omac1_aes_128_vector(psk, 2, addr, vlen, hash))
      61           4 :                         return -1;
      62        8072 :                 clen = left > hashlen ? hashlen : left;
      63        8072 :                 os_memcpy(opos, hash, clen);
      64        8072 :                 opos += clen;
      65        8072 :                 left -= clen;
      66             :         }
      67             : 
      68        2015 :         return 0;
      69             : }
      70             : 
      71             : 
      72             : #ifdef EAP_GPSK_SHA256
      73          12 : static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */,
      74             :                                 const u8 *data /* Z */, size_t data_len,
      75             :                                 u8 *buf, size_t len /* X */)
      76             : {
      77             :         u8 *opos;
      78             :         size_t i, n, hashlen, left, clen;
      79             :         u8 ibuf[2], hash[SHA256_MAC_LEN];
      80             :         const u8 *addr[2];
      81             :         size_t vlen[2];
      82             : 
      83          12 :         hashlen = SHA256_MAC_LEN;
      84             :         /* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */
      85          12 :         addr[0] = ibuf;
      86          12 :         vlen[0] = sizeof(ibuf);
      87          12 :         addr[1] = data;
      88          12 :         vlen[1] = data_len;
      89             : 
      90          12 :         opos = buf;
      91          12 :         left = len;
      92          12 :         n = (len + hashlen - 1) / hashlen;
      93          43 :         for (i = 1; i <= n; i++) {
      94          32 :                 WPA_PUT_BE16(ibuf, i);
      95          32 :                 if (hmac_sha256_vector(psk, 32, 2, addr, vlen, hash))
      96           1 :                         return -1;
      97          31 :                 clen = left > hashlen ? hashlen : left;
      98          31 :                 os_memcpy(opos, hash, clen);
      99          31 :                 opos += clen;
     100          31 :                 left -= clen;
     101             :         }
     102             : 
     103          11 :         return 0;
     104             : }
     105             : #endif /* EAP_GPSK_SHA256 */
     106             : 
     107             : 
     108         681 : static int eap_gpsk_derive_keys_helper(u32 csuite_specifier,
     109             :                                        u8 *kdf_out, size_t kdf_out_len,
     110             :                                        const u8 *psk, size_t psk_len,
     111             :                                        const u8 *seed, size_t seed_len,
     112             :                                        u8 *msk, u8 *emsk,
     113             :                                        u8 *sk, size_t sk_len,
     114             :                                        u8 *pk, size_t pk_len)
     115             : {
     116             :         u8 mk[32], *pos, *data;
     117             :         size_t data_len, mk_len;
     118             :         int (*gkdf)(const u8 *_psk, const u8 *_data, size_t _data_len,
     119             :                     u8 *buf, size_t len);
     120             : 
     121         681 :         gkdf = NULL;
     122         681 :         switch (csuite_specifier) {
     123             :         case EAP_GPSK_CIPHER_AES:
     124         677 :                 gkdf = eap_gpsk_gkdf_cmac;
     125         677 :                 mk_len = 16;
     126         677 :                 break;
     127             : #ifdef EAP_GPSK_SHA256
     128             :         case EAP_GPSK_CIPHER_SHA256:
     129           4 :                 gkdf = eap_gpsk_gkdf_sha256;
     130           4 :                 mk_len = SHA256_MAC_LEN;
     131           4 :                 break;
     132             : #endif /* EAP_GPSK_SHA256 */
     133             :         default:
     134           0 :                 return -1;
     135             :         }
     136             : 
     137         681 :         if (psk_len < mk_len)
     138           1 :                 return -1;
     139             : 
     140         680 :         data_len = 2 + psk_len + 6 + seed_len;
     141         680 :         data = os_malloc(data_len);
     142         680 :         if (data == NULL)
     143           1 :                 return -1;
     144         679 :         pos = data;
     145         679 :         WPA_PUT_BE16(pos, psk_len);
     146         679 :         pos += 2;
     147         679 :         os_memcpy(pos, psk, psk_len);
     148         679 :         pos += psk_len;
     149         679 :         WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */
     150         679 :         pos += 4;
     151         679 :         WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */
     152         679 :         pos += 2;
     153         679 :         os_memcpy(pos, seed, seed_len); /* inputString */
     154         679 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation",
     155             :                         data, data_len);
     156             : 
     157         679 :         if (gkdf(psk, data, data_len, mk, mk_len) < 0) {
     158           2 :                 os_free(data);
     159           2 :                 return -1;
     160             :         }
     161         677 :         os_free(data);
     162         677 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len);
     163             : 
     164         677 :         if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0)
     165           0 :                 return -1;
     166             : 
     167         677 :         pos = kdf_out;
     168         677 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN);
     169         677 :         os_memcpy(msk, pos, EAP_MSK_LEN);
     170         677 :         pos += EAP_MSK_LEN;
     171             : 
     172         677 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN);
     173         677 :         os_memcpy(emsk, pos, EAP_EMSK_LEN);
     174         677 :         pos += EAP_EMSK_LEN;
     175             : 
     176         677 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len);
     177         677 :         os_memcpy(sk, pos, sk_len);
     178         677 :         pos += sk_len;
     179             : 
     180         677 :         if (pk) {
     181         673 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len);
     182         673 :                 os_memcpy(pk, pos, pk_len);
     183             :         }
     184             : 
     185         677 :         return 0;
     186             : }
     187             : 
     188             : 
     189         677 : static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len,
     190             :                                     const u8 *seed, size_t seed_len,
     191             :                                     u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len,
     192             :                                     u8 *pk, size_t *pk_len)
     193             : {
     194             : #define EAP_GPSK_SK_LEN_AES 16
     195             : #define EAP_GPSK_PK_LEN_AES 16
     196             :         u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES +
     197             :                    EAP_GPSK_PK_LEN_AES];
     198             : 
     199             :         /*
     200             :          * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
     201             :          *            (= seed)
     202             :          * KS = 16, PL = psk_len, CSuite_Sel = 0x00000000 0x0001
     203             :          * MK = GKDF-16 (PSK[0..15], PL || PSK || CSuite_Sel || inputString)
     204             :          * MSK = GKDF-160 (MK, inputString)[0..63]
     205             :          * EMSK = GKDF-160 (MK, inputString)[64..127]
     206             :          * SK = GKDF-160 (MK, inputString)[128..143]
     207             :          * PK = GKDF-160 (MK, inputString)[144..159]
     208             :          * zero = 0x00 || 0x00 || ... || 0x00 (16 times)
     209             :          * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
     210             :          *                      CSuite_Sel || inputString)
     211             :          */
     212             : 
     213         677 :         *sk_len = EAP_GPSK_SK_LEN_AES;
     214         677 :         *pk_len = EAP_GPSK_PK_LEN_AES;
     215             : 
     216         677 :         return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_AES,
     217             :                                            kdf_out, sizeof(kdf_out),
     218             :                                            psk, psk_len, seed, seed_len,
     219             :                                            msk, emsk, sk, *sk_len,
     220             :                                            pk, *pk_len);
     221             : }
     222             : 
     223             : 
     224             : #ifdef EAP_GPSK_SHA256
     225           4 : static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len,
     226             :                                        const u8 *seed, size_t seed_len,
     227             :                                        u8 *msk, u8 *emsk,
     228             :                                        u8 *sk, size_t *sk_len)
     229             : {
     230             : #define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN
     231             : #define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN
     232             :         u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 +
     233             :                    EAP_GPSK_PK_LEN_SHA256];
     234             : 
     235             :         /*
     236             :          * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
     237             :          *            (= seed)
     238             :          * KS = 32, PL = psk_len, CSuite_Sel = 0x00000000 0x0002
     239             :          * MK = GKDF-32 (PSK[0..31], PL || PSK || CSuite_Sel || inputString)
     240             :          * MSK = GKDF-160 (MK, inputString)[0..63]
     241             :          * EMSK = GKDF-160 (MK, inputString)[64..127]
     242             :          * SK = GKDF-160 (MK, inputString)[128..159]
     243             :          * zero = 0x00 || 0x00 || ... || 0x00 (32 times)
     244             :          * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
     245             :          *                      CSuite_Sel || inputString)
     246             :          */
     247             : 
     248           4 :         *sk_len = EAP_GPSK_SK_LEN_SHA256;
     249             : 
     250           4 :         return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_SHA256,
     251             :                                            kdf_out, sizeof(kdf_out),
     252             :                                            psk, psk_len, seed, seed_len,
     253             :                                            msk, emsk, sk, *sk_len,
     254             :                                            NULL, 0);
     255             : }
     256             : #endif /* EAP_GPSK_SHA256 */
     257             : 
     258             : 
     259             : /**
     260             :  * eap_gpsk_derive_keys - Derive EAP-GPSK keys
     261             :  * @psk: Pre-shared key
     262             :  * @psk_len: Length of psk in bytes
     263             :  * @vendor: CSuite/Vendor
     264             :  * @specifier: CSuite/Specifier
     265             :  * @rand_peer: 32-byte RAND_Peer
     266             :  * @rand_server: 32-byte RAND_Server
     267             :  * @id_peer: ID_Peer
     268             :  * @id_peer_len: Length of ID_Peer
     269             :  * @id_server: ID_Server
     270             :  * @id_server_len: Length of ID_Server
     271             :  * @msk: Buffer for 64-byte MSK
     272             :  * @emsk: Buffer for 64-byte EMSK
     273             :  * @sk: Buffer for SK (at least EAP_GPSK_MAX_SK_LEN bytes)
     274             :  * @sk_len: Buffer for returning length of SK
     275             :  * @pk: Buffer for PK (at least EAP_GPSK_MAX_PK_LEN bytes)
     276             :  * @pk_len: Buffer for returning length of PK
     277             :  * Returns: 0 on success, -1 on failure
     278             :  */
     279         682 : int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor,
     280             :                          int specifier,
     281             :                          const u8 *rand_peer, const u8 *rand_server,
     282             :                          const u8 *id_peer, size_t id_peer_len,
     283             :                          const u8 *id_server, size_t id_server_len,
     284             :                          u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len,
     285             :                          u8 *pk, size_t *pk_len)
     286             : {
     287             :         u8 *seed, *pos;
     288             :         int ret;
     289             : 
     290         682 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving keys (%d:%d)",
     291             :                    vendor, specifier);
     292             : 
     293         682 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     294           0 :                 return -1;
     295             : 
     296         682 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
     297             : 
     298             :         /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */
     299         682 :         seed = os_malloc(2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len);
     300         682 :         if (seed == NULL) {
     301           1 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
     302             :                            "for key derivation");
     303           1 :                 return -1;
     304             :         }
     305             : 
     306         681 :         pos = seed;
     307         681 :         os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN);
     308         681 :         pos += EAP_GPSK_RAND_LEN;
     309         681 :         os_memcpy(pos, id_peer, id_peer_len);
     310         681 :         pos += id_peer_len;
     311         681 :         os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN);
     312         681 :         pos += EAP_GPSK_RAND_LEN;
     313         681 :         os_memcpy(pos, id_server, id_server_len);
     314         681 :         pos += id_server_len;
     315         681 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, pos - seed);
     316             : 
     317         681 :         switch (specifier) {
     318             :         case EAP_GPSK_CIPHER_AES:
     319         677 :                 ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, pos - seed,
     320             :                                                msk, emsk, sk, sk_len,
     321             :                                                pk, pk_len);
     322         677 :                 break;
     323             : #ifdef EAP_GPSK_SHA256
     324             :         case EAP_GPSK_CIPHER_SHA256:
     325           4 :                 ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed,
     326           4 :                                                   pos - seed,
     327             :                                                   msk, emsk, sk, sk_len);
     328           4 :                 break;
     329             : #endif /* EAP_GPSK_SHA256 */
     330             :         default:
     331           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in "
     332             :                            "key derivation", vendor, specifier);
     333           0 :                 ret = -1;
     334           0 :                 break;
     335             :         }
     336             : 
     337         681 :         os_free(seed);
     338             : 
     339         681 :         return ret;
     340             : }
     341             : 
     342             : 
     343         676 : static int eap_gpsk_derive_mid_helper(u32 csuite_specifier,
     344             :                                       u8 *kdf_out, size_t kdf_out_len,
     345             :                                       const u8 *psk, const u8 *seed,
     346             :                                       size_t seed_len, u8 method_type)
     347             : {
     348             :         u8 *pos, *data;
     349             :         size_t data_len;
     350             :         int (*gkdf)(const u8 *_psk, const u8 *_data, size_t _data_len,
     351             :                     u8 *buf, size_t len);
     352             : 
     353         676 :         gkdf = NULL;
     354         676 :         switch (csuite_specifier) {
     355             :         case EAP_GPSK_CIPHER_AES:
     356         672 :                 gkdf = eap_gpsk_gkdf_cmac;
     357         672 :                 break;
     358             : #ifdef EAP_GPSK_SHA256
     359             :         case EAP_GPSK_CIPHER_SHA256:
     360           4 :                 gkdf = eap_gpsk_gkdf_sha256;
     361           4 :                 break;
     362             : #endif /* EAP_GPSK_SHA256 */
     363             :         default:
     364           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d used in "
     365             :                            "Session-Id derivation", csuite_specifier);
     366           0 :                 return -1;
     367             :         }
     368             : 
     369             : #define SID_LABEL "Method ID"
     370             :         /* "Method ID" || EAP_Method_Type || CSuite_Sel || inputString */
     371         676 :         data_len = strlen(SID_LABEL) + 1 + 6 + seed_len;
     372         676 :         data = os_malloc(data_len);
     373         676 :         if (data == NULL)
     374           1 :                 return -1;
     375         675 :         pos = data;
     376         675 :         os_memcpy(pos, SID_LABEL, strlen(SID_LABEL));
     377         675 :         pos += strlen(SID_LABEL);
     378             : #undef SID_LABEL
     379         675 :         os_memcpy(pos, &method_type, 1);
     380         675 :         pos += 1;
     381         675 :         WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */
     382         675 :         pos += 4;
     383         675 :         WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */
     384         675 :         pos += 2;
     385         675 :         os_memcpy(pos, seed, seed_len); /* inputString */
     386         675 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Data to Method ID derivation",
     387             :                     data, data_len);
     388             : 
     389         675 :         if (gkdf(psk, data, data_len, kdf_out, kdf_out_len) < 0) {
     390           3 :                 os_free(data);
     391           3 :                 return -1;
     392             :         }
     393         672 :         os_free(data);
     394         672 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Method ID", kdf_out, kdf_out_len);
     395             : 
     396         672 :         return 0;
     397             : }
     398             : 
     399             : 
     400             : /**
     401             :  * eap_gpsk_session_id - Derive EAP-GPSK Session ID
     402             :  * @psk: Pre-shared key
     403             :  * @psk_len: Length of psk in bytes
     404             :  * @vendor: CSuite/Vendor
     405             :  * @specifier: CSuite/Specifier
     406             :  * @rand_peer: 32-byte RAND_Peer
     407             :  * @rand_server: 32-byte RAND_Server
     408             :  * @id_peer: ID_Peer
     409             :  * @id_peer_len: Length of ID_Peer
     410             :  * @id_server: ID_Server
     411             :  * @id_server_len: Length of ID_Server
     412             :  * @method_type: EAP Authentication Method Type
     413             :  * @sid: Buffer for 17-byte Session ID
     414             :  * @sid_len: Buffer for returning length of Session ID
     415             :  * Returns: 0 on success, -1 on failure
     416             :  */
     417         677 : int eap_gpsk_derive_session_id(const u8 *psk, size_t psk_len, int vendor,
     418             :                                int specifier,
     419             :                                const u8 *rand_peer, const u8 *rand_server,
     420             :                                const u8 *id_peer, size_t id_peer_len,
     421             :                                const u8 *id_server, size_t id_server_len,
     422             :                                u8 method_type, u8 *sid, size_t *sid_len)
     423             : {
     424             :         u8 *seed, *pos;
     425             :         u8 kdf_out[16];
     426             :         int ret;
     427             : 
     428         677 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving Session ID(%d:%d)",
     429             :                    vendor, specifier);
     430             : 
     431         677 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     432           0 :                 return -1;
     433             : 
     434         677 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
     435             : 
     436             :         /*
     437             :          * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
     438             :          *            (= seed)
     439             :          * KS = 16, CSuite_Sel = 0x00000000 0x0001
     440             :          * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
     441             :          *                      CSuite_Sel || inputString)
     442             :          */
     443         677 :         seed = os_malloc(2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len);
     444         677 :         if (seed == NULL) {
     445           1 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
     446             :                            "for Session-Id derivation");
     447           1 :                 return -1;
     448             :         }
     449             : 
     450         676 :         pos = seed;
     451         676 :         os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN);
     452         676 :         pos += EAP_GPSK_RAND_LEN;
     453         676 :         os_memcpy(pos, id_peer, id_peer_len);
     454         676 :         pos += id_peer_len;
     455         676 :         os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN);
     456         676 :         pos += EAP_GPSK_RAND_LEN;
     457         676 :         os_memcpy(pos, id_server, id_server_len);
     458         676 :         pos += id_server_len;
     459         676 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, pos - seed);
     460             : 
     461        1352 :         ret = eap_gpsk_derive_mid_helper(specifier,
     462             :                                          kdf_out, sizeof(kdf_out),
     463         676 :                                          psk, seed, pos - seed,
     464             :                                          method_type);
     465             : 
     466         676 :         sid[0] = method_type;
     467         676 :         os_memcpy(sid + 1, kdf_out, sizeof(kdf_out));
     468         676 :         *sid_len = 1 + sizeof(kdf_out);
     469             : 
     470         676 :         os_free(seed);
     471             : 
     472         676 :         return ret;
     473             : }
     474             : 
     475             : 
     476             : /**
     477             :  * eap_gpsk_mic_len - Get the length of the MIC
     478             :  * @vendor: CSuite/Vendor
     479             :  * @specifier: CSuite/Specifier
     480             :  * Returns: MIC length in bytes
     481             :  */
     482        1961 : size_t eap_gpsk_mic_len(int vendor, int specifier)
     483             : {
     484        1961 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     485           0 :                 return 0;
     486             : 
     487        1961 :         switch (specifier) {
     488             :         case EAP_GPSK_CIPHER_AES:
     489        1953 :                 return 16;
     490             : #ifdef EAP_GPSK_SHA256
     491             :         case EAP_GPSK_CIPHER_SHA256:
     492           8 :                 return 32;
     493             : #endif /* EAP_GPSK_SHA256 */
     494             :         default:
     495           0 :                 return 0;
     496             :         }
     497             : }
     498             : 
     499             : 
     500        1940 : static int eap_gpsk_compute_mic_aes(const u8 *sk, size_t sk_len,
     501             :                                     const u8 *data, size_t len, u8 *mic)
     502             : {
     503        1940 :         if (sk_len != 16) {
     504           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid SK length %lu for "
     505             :                            "AES-CMAC MIC", (unsigned long) sk_len);
     506           0 :                 return -1;
     507             :         }
     508             : 
     509        1940 :         return omac1_aes_128(sk, data, len, mic);
     510             : }
     511             : 
     512             : 
     513             : /**
     514             :  * eap_gpsk_compute_mic - Compute EAP-GPSK MIC for an EAP packet
     515             :  * @sk: Session key SK from eap_gpsk_derive_keys()
     516             :  * @sk_len: SK length in bytes from eap_gpsk_derive_keys()
     517             :  * @vendor: CSuite/Vendor
     518             :  * @specifier: CSuite/Specifier
     519             :  * @data: Input data to MIC
     520             :  * @len: Input data length in bytes
     521             :  * @mic: Buffer for the computed MIC, eap_gpsk_mic_len(cipher) bytes
     522             :  * Returns: 0 on success, -1 on failure
     523             :  */
     524        1947 : int eap_gpsk_compute_mic(const u8 *sk, size_t sk_len, int vendor,
     525             :                          int specifier, const u8 *data, size_t len, u8 *mic)
     526             : {
     527             :         int ret;
     528             : 
     529        1947 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     530           0 :                 return -1;
     531             : 
     532        1947 :         switch (specifier) {
     533             :         case EAP_GPSK_CIPHER_AES:
     534        1940 :                 ret = eap_gpsk_compute_mic_aes(sk, sk_len, data, len, mic);
     535        1940 :                 break;
     536             : #ifdef EAP_GPSK_SHA256
     537             :         case EAP_GPSK_CIPHER_SHA256:
     538           7 :                 ret = hmac_sha256(sk, sk_len, data, len, mic);
     539           7 :                 break;
     540             : #endif /* EAP_GPSK_SHA256 */
     541             :         default:
     542           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in "
     543             :                            "MIC computation", vendor, specifier);
     544           0 :                 ret = -1;
     545           0 :                 break;
     546             :         }
     547             : 
     548        1947 :         if (ret)
     549           4 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Could not compute MIC");
     550             : 
     551        1947 :         return ret;
     552             : }

Generated by: LCOV version 1.10