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

Generated by: LCOV version 1.10