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 1401264779 Lines: 177 207 85.5 %
Date: 2014-05-28 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          65 : int eap_gpsk_supported_ciphersuite(int vendor, int specifier)
      25             : {
      26          65 :         if (vendor == EAP_GPSK_VENDOR_IETF &&
      27             :             specifier == EAP_GPSK_CIPHER_AES)
      28          42 :                 return 1;
      29             : #ifdef EAP_GPSK_SHA256
      30          23 :         if (vendor == EAP_GPSK_VENDOR_IETF &&
      31             :             specifier == EAP_GPSK_CIPHER_SHA256)
      32          23 :                 return 1;
      33             : #endif /* EAP_GPSK_SHA256 */
      34           0 :         return 0;
      35             : }
      36             : 
      37             : 
      38          95 : 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          95 :         hashlen = sizeof(hash);
      49             :         /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */
      50          95 :         addr[0] = ibuf;
      51          95 :         vlen[0] = sizeof(ibuf);
      52          95 :         addr[1] = data;
      53          95 :         vlen[1] = data_len;
      54             : 
      55          95 :         opos = buf;
      56          95 :         left = len;
      57          95 :         n = (len + hashlen - 1) / hashlen;
      58         532 :         for (i = 1; i <= n; i++) {
      59         437 :                 WPA_PUT_BE16(ibuf, i);
      60         437 :                 if (omac1_aes_128_vector(psk, 2, addr, vlen, hash))
      61           0 :                         return -1;
      62         437 :                 clen = left > hashlen ? hashlen : left;
      63         437 :                 os_memcpy(opos, hash, clen);
      64         437 :                 opos += clen;
      65         437 :                 left -= clen;
      66             :         }
      67             : 
      68          95 :         return 0;
      69             : }
      70             : 
      71             : 
      72             : #ifdef EAP_GPSK_SHA256
      73           5 : 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           5 :         hashlen = SHA256_MAC_LEN;
      84             :         /* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */
      85           5 :         addr[0] = ibuf;
      86           5 :         vlen[0] = sizeof(ibuf);
      87           5 :         addr[1] = data;
      88           5 :         vlen[1] = data_len;
      89             : 
      90           5 :         opos = buf;
      91           5 :         left = len;
      92           5 :         n = (len + hashlen - 1) / hashlen;
      93          20 :         for (i = 1; i <= n; i++) {
      94          15 :                 WPA_PUT_BE16(ibuf, i);
      95          15 :                 hmac_sha256_vector(psk, 32, 2, addr, vlen, hash);
      96          15 :                 clen = left > hashlen ? hashlen : left;
      97          15 :                 os_memcpy(opos, hash, clen);
      98          15 :                 opos += clen;
      99          15 :                 left -= clen;
     100             :         }
     101             : 
     102           5 :         return 0;
     103             : }
     104             : #endif /* EAP_GPSK_SHA256 */
     105             : 
     106             : 
     107          40 : 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          40 :         gkdf = NULL;
     121          40 :         switch (csuite_specifier) {
     122             :         case EAP_GPSK_CIPHER_AES:
     123          38 :                 gkdf = eap_gpsk_gkdf_cmac;
     124          38 :                 mk_len = 16;
     125          38 :                 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          40 :         if (psk_len < mk_len)
     137           0 :                 return -1;
     138             : 
     139          40 :         data_len = 2 + psk_len + 6 + seed_len;
     140          40 :         data = os_malloc(data_len);
     141          40 :         if (data == NULL)
     142           0 :                 return -1;
     143          40 :         pos = data;
     144          40 :         WPA_PUT_BE16(pos, psk_len);
     145          40 :         pos += 2;
     146          40 :         os_memcpy(pos, psk, psk_len);
     147          40 :         pos += psk_len;
     148          40 :         WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */
     149          40 :         pos += 4;
     150          40 :         WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */
     151          40 :         pos += 2;
     152          40 :         os_memcpy(pos, seed, seed_len); /* inputString */
     153          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation",
     154             :                         data, data_len);
     155             : 
     156          40 :         if (gkdf(psk, data, data_len, mk, mk_len) < 0) {
     157           0 :                 os_free(data);
     158           0 :                 return -1;
     159             :         }
     160          40 :         os_free(data);
     161          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len);
     162             : 
     163          40 :         if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0)
     164           0 :                 return -1;
     165             : 
     166          40 :         pos = kdf_out;
     167          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN);
     168          40 :         os_memcpy(msk, pos, EAP_MSK_LEN);
     169          40 :         pos += EAP_MSK_LEN;
     170             : 
     171          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN);
     172          40 :         os_memcpy(emsk, pos, EAP_EMSK_LEN);
     173          40 :         pos += EAP_EMSK_LEN;
     174             : 
     175          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len);
     176          40 :         os_memcpy(sk, pos, sk_len);
     177          40 :         pos += sk_len;
     178             : 
     179          40 :         if (pk) {
     180          38 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len);
     181          38 :                 os_memcpy(pk, pos, pk_len);
     182             :         }
     183             : 
     184          40 :         return 0;
     185             : }
     186             : 
     187             : 
     188          38 : 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          38 :         *sk_len = EAP_GPSK_SK_LEN_AES;
     213          38 :         *pk_len = EAP_GPSK_PK_LEN_AES;
     214             : 
     215          38 :         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          40 : 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             :         size_t seed_len;
     288             :         int ret;
     289             : 
     290          40 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving keys (%d:%d)",
     291             :                    vendor, specifier);
     292             : 
     293          40 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     294           0 :                 return -1;
     295             : 
     296          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
     297             : 
     298             :         /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */
     299          40 :         seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len;
     300          40 :         seed = os_malloc(seed_len);
     301          40 :         if (seed == NULL) {
     302           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
     303             :                            "for key derivation");
     304           0 :                 return -1;
     305             :         }
     306             : 
     307          40 :         pos = seed;
     308          40 :         os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN);
     309          40 :         pos += EAP_GPSK_RAND_LEN;
     310          40 :         os_memcpy(pos, id_peer, id_peer_len);
     311          40 :         pos += id_peer_len;
     312          40 :         os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN);
     313          40 :         pos += EAP_GPSK_RAND_LEN;
     314          40 :         os_memcpy(pos, id_server, id_server_len);
     315          40 :         pos += id_server_len;
     316          40 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len);
     317             : 
     318          40 :         switch (specifier) {
     319             :         case EAP_GPSK_CIPHER_AES:
     320          38 :                 ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, seed_len,
     321             :                                                msk, emsk, sk, sk_len,
     322             :                                                pk, pk_len);
     323          38 :                 break;
     324             : #ifdef EAP_GPSK_SHA256
     325             :         case EAP_GPSK_CIPHER_SHA256:
     326           2 :                 ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len,
     327             :                                                   msk, emsk, sk, sk_len);
     328           2 :                 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          40 :         os_free(seed);
     338             : 
     339          40 :         return ret;
     340             : }
     341             : 
     342             : 
     343          20 : 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          20 :         gkdf = NULL;
     354          20 :         switch (csuite_specifier) {
     355             :         case EAP_GPSK_CIPHER_AES:
     356          19 :                 gkdf = eap_gpsk_gkdf_cmac;
     357          19 :                 break;
     358             : #ifdef EAP_GPSK_SHA256
     359             :         case EAP_GPSK_CIPHER_SHA256:
     360           1 :                 gkdf = eap_gpsk_gkdf_sha256;
     361           1 :                 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          20 :         data_len = strlen(SID_LABEL) + 1 + 6 + seed_len;
     372          20 :         data = os_malloc(data_len);
     373          20 :         if (data == NULL)
     374           0 :                 return -1;
     375          20 :         pos = data;
     376          20 :         os_memcpy(pos, SID_LABEL, strlen(SID_LABEL));
     377          20 :         pos += strlen(SID_LABEL);
     378             : #undef SID_LABEL
     379          20 :         os_memcpy(pos, &method_type, 1);
     380          20 :         pos += 1;
     381          20 :         WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */
     382          20 :         pos += 4;
     383          20 :         WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */
     384          20 :         pos += 2;
     385          20 :         os_memcpy(pos, seed, seed_len); /* inputString */
     386          20 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Data to Method ID derivation",
     387             :                     data, data_len);
     388             : 
     389          20 :         if (gkdf(psk, data, data_len, kdf_out, kdf_out_len) < 0) {
     390           0 :                 os_free(data);
     391           0 :                 return -1;
     392             :         }
     393          20 :         os_free(data);
     394          20 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Method ID", kdf_out, kdf_out_len);
     395             : 
     396          20 :         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          20 : 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             :         size_t seed_len;
     427             :         int ret;
     428             : 
     429          20 :         wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving Session ID(%d:%d)",
     430             :                    vendor, specifier);
     431             : 
     432          20 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     433           0 :                 return -1;
     434             : 
     435          20 :         wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
     436             : 
     437             :         /*
     438             :          * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
     439             :          *            (= seed)
     440             :          * KS = 16, CSuite_Sel = 0x00000000 0x0001
     441             :          * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
     442             :          *                      CSuite_Sel || inputString)
     443             :          */
     444          20 :         seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len;
     445          20 :         seed = os_malloc(seed_len);
     446          20 :         if (seed == NULL) {
     447           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
     448             :                            "for Session-Id derivation");
     449           0 :                 return -1;
     450             :         }
     451             : 
     452          20 :         pos = seed;
     453          20 :         os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN);
     454          20 :         pos += EAP_GPSK_RAND_LEN;
     455          20 :         os_memcpy(pos, id_peer, id_peer_len);
     456          20 :         pos += id_peer_len;
     457          20 :         os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN);
     458          20 :         pos += EAP_GPSK_RAND_LEN;
     459          20 :         os_memcpy(pos, id_server, id_server_len);
     460          20 :         pos += id_server_len;
     461          20 :         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len);
     462             : 
     463          20 :         ret = eap_gpsk_derive_mid_helper(specifier,
     464             :                                          kdf_out, sizeof(kdf_out),
     465             :                                          psk, seed, seed_len,
     466             :                                          method_type);
     467             : 
     468          20 :         sid[0] = method_type;
     469          20 :         os_memcpy(sid + 1, kdf_out, sizeof(kdf_out));
     470          20 :         *sid_len = 1 + sizeof(kdf_out);
     471             : 
     472          20 :         os_free(seed);
     473             : 
     474          20 :         return ret;
     475             : }
     476             : 
     477             : 
     478             : /**
     479             :  * eap_gpsk_mic_len - Get the length of the MIC
     480             :  * @vendor: CSuite/Vendor
     481             :  * @specifier: CSuite/Specifier
     482             :  * Returns: MIC length in bytes
     483             :  */
     484         116 : size_t eap_gpsk_mic_len(int vendor, int specifier)
     485             : {
     486         116 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     487           0 :                 return 0;
     488             : 
     489         116 :         switch (specifier) {
     490             :         case EAP_GPSK_CIPHER_AES:
     491         110 :                 return 16;
     492             : #ifdef EAP_GPSK_SHA256
     493             :         case EAP_GPSK_CIPHER_SHA256:
     494           6 :                 return 32;
     495             : #endif /* EAP_GPSK_SHA256 */
     496             :         default:
     497           0 :                 return 0;
     498             :         }
     499             : }
     500             : 
     501             : 
     502         110 : static int eap_gpsk_compute_mic_aes(const u8 *sk, size_t sk_len,
     503             :                                     const u8 *data, size_t len, u8 *mic)
     504             : {
     505         110 :         if (sk_len != 16) {
     506           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid SK length %lu for "
     507             :                            "AES-CMAC MIC", (unsigned long) sk_len);
     508           0 :                 return -1;
     509             :         }
     510             : 
     511         110 :         return omac1_aes_128(sk, data, len, mic);
     512             : }
     513             : 
     514             : 
     515             : /**
     516             :  * eap_gpsk_compute_mic - Compute EAP-GPSK MIC for an EAP packet
     517             :  * @sk: Session key SK from eap_gpsk_derive_keys()
     518             :  * @sk_len: SK length in bytes from eap_gpsk_derive_keys()
     519             :  * @vendor: CSuite/Vendor
     520             :  * @specifier: CSuite/Specifier
     521             :  * @data: Input data to MIC
     522             :  * @len: Input data length in bytes
     523             :  * @mic: Buffer for the computed MIC, eap_gpsk_mic_len(cipher) bytes
     524             :  * Returns: 0 on success, -1 on failure
     525             :  */
     526         116 : int eap_gpsk_compute_mic(const u8 *sk, size_t sk_len, int vendor,
     527             :                          int specifier, const u8 *data, size_t len, u8 *mic)
     528             : {
     529             :         int ret;
     530             : 
     531         116 :         if (vendor != EAP_GPSK_VENDOR_IETF)
     532           0 :                 return -1;
     533             : 
     534         116 :         switch (specifier) {
     535             :         case EAP_GPSK_CIPHER_AES:
     536         110 :                 ret = eap_gpsk_compute_mic_aes(sk, sk_len, data, len, mic);
     537         110 :                 break;
     538             : #ifdef EAP_GPSK_SHA256
     539             :         case EAP_GPSK_CIPHER_SHA256:
     540           6 :                 hmac_sha256(sk, sk_len, data, len, mic);
     541           6 :                 ret = 0;
     542           6 :                 break;
     543             : #endif /* EAP_GPSK_SHA256 */
     544             :         default:
     545           0 :                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in "
     546             :                            "MIC computation", vendor, specifier);
     547           0 :                 ret = -1;
     548           0 :                 break;
     549             :         }
     550             : 
     551         116 :         return ret;
     552             : }

Generated by: LCOV version 1.10