LCOV - code coverage report
Current view: top level - src/eap_common - ikev2_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 322 373 86.3 %
Date: 2016-10-02 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /*
       2             :  * IKEv2 common routines for initiator and responder
       3             :  * Copyright (c) 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/crypto.h"
      13             : #include "crypto/md5.h"
      14             : #include "crypto/sha1.h"
      15             : #include "crypto/random.h"
      16             : #include "ikev2_common.h"
      17             : 
      18             : 
      19             : static const struct ikev2_integ_alg ikev2_integ_algs[] = {
      20             :         { AUTH_HMAC_SHA1_96, 20, 12 },
      21             :         { AUTH_HMAC_MD5_96, 16, 12 }
      22             : };
      23             : 
      24             : #define NUM_INTEG_ALGS ARRAY_SIZE(ikev2_integ_algs)
      25             : 
      26             : 
      27             : static const struct ikev2_prf_alg ikev2_prf_algs[] = {
      28             :         { PRF_HMAC_SHA1, 20, 20 },
      29             :         { PRF_HMAC_MD5, 16, 16 }
      30             : };
      31             : 
      32             : #define NUM_PRF_ALGS ARRAY_SIZE(ikev2_prf_algs)
      33             : 
      34             : 
      35             : static const struct ikev2_encr_alg ikev2_encr_algs[] = {
      36             :         { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */
      37             :         { ENCR_3DES, 24, 8 }
      38             : };
      39             : 
      40             : #define NUM_ENCR_ALGS ARRAY_SIZE(ikev2_encr_algs)
      41             : 
      42             : 
      43         458 : const struct ikev2_integ_alg * ikev2_get_integ(int id)
      44             : {
      45             :         size_t i;
      46             : 
      47         481 :         for (i = 0; i < NUM_INTEG_ALGS; i++) {
      48         480 :                 if (ikev2_integ_algs[i].id == id)
      49         457 :                         return &ikev2_integ_algs[i];
      50             :         }
      51             : 
      52           1 :         return NULL;
      53             : }
      54             : 
      55             : 
      56         260 : int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
      57             :                      size_t data_len, u8 *hash)
      58             : {
      59             :         u8 tmphash[IKEV2_MAX_HASH_LEN];
      60             : 
      61         260 :         switch (alg) {
      62             :         case AUTH_HMAC_SHA1_96:
      63         255 :                 if (key_len != 20)
      64           0 :                         return -1;
      65         255 :                 if (hmac_sha1(key, key_len, data, data_len, tmphash) < 0)
      66           3 :                         return -1;
      67         252 :                 os_memcpy(hash, tmphash, 12);
      68         252 :                 break;
      69             :         case AUTH_HMAC_MD5_96:
      70           5 :                 if (key_len != 16)
      71           0 :                         return -1;
      72           5 :                 if (hmac_md5(key, key_len, data, data_len, tmphash) < 0)
      73           0 :                         return -1;
      74           5 :                 os_memcpy(hash, tmphash, 12);
      75           5 :                 break;
      76             :         default:
      77           0 :                 return -1;
      78             :         }
      79             : 
      80         257 :         return 0;
      81             : }
      82             : 
      83             : 
      84         458 : const struct ikev2_prf_alg * ikev2_get_prf(int id)
      85             : {
      86             :         size_t i;
      87             : 
      88         477 :         for (i = 0; i < NUM_PRF_ALGS; i++) {
      89         477 :                 if (ikev2_prf_algs[i].id == id)
      90         458 :                         return &ikev2_prf_algs[i];
      91             :         }
      92             : 
      93           0 :         return NULL;
      94             : }
      95             : 
      96             : 
      97        1025 : int ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
      98             :                    size_t num_elem, const u8 *addr[], const size_t *len,
      99             :                    u8 *hash)
     100             : {
     101        1025 :         switch (alg) {
     102             :         case PRF_HMAC_SHA1:
     103         989 :                 return hmac_sha1_vector(key, key_len, num_elem, addr, len,
     104             :                                         hash);
     105             :         case PRF_HMAC_MD5:
     106          36 :                 return hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
     107             :         default:
     108           0 :                 return -1;
     109             :         }
     110             : }
     111             : 
     112             : 
     113         105 : int ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
     114             :                    const u8 *data, size_t data_len,
     115             :                    u8 *out, size_t out_len)
     116             : {
     117             :         u8 hash[IKEV2_MAX_HASH_LEN];
     118             :         size_t hash_len;
     119             :         u8 iter, *pos, *end;
     120             :         const u8 *addr[3];
     121             :         size_t len[3];
     122             :         const struct ikev2_prf_alg *prf;
     123             :         int res;
     124             : 
     125         105 :         prf = ikev2_get_prf(alg);
     126         105 :         if (prf == NULL)
     127           0 :                 return -1;
     128         105 :         hash_len = prf->hash_len;
     129             : 
     130         105 :         addr[0] = hash;
     131         105 :         len[0] = hash_len;
     132         105 :         addr[1] = data;
     133         105 :         len[1] = data_len;
     134         105 :         addr[2] = &iter;
     135         105 :         len[2] = 1;
     136             : 
     137         105 :         pos = out;
     138         105 :         end = out + out_len;
     139         105 :         iter = 1;
     140         907 :         while (pos < end) {
     141             :                 size_t clen;
     142         706 :                 if (iter == 1)
     143         105 :                         res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1],
     144             :                                              &len[1], hash);
     145             :                 else
     146         601 :                         res = ikev2_prf_hash(alg, key, key_len, 3, addr, len,
     147             :                                              hash);
     148         706 :                 if (res < 0)
     149           9 :                         return -1;
     150         697 :                 clen = hash_len;
     151         697 :                 if ((int) clen > end - pos)
     152          92 :                         clen = end - pos;
     153         697 :                 os_memcpy(pos, hash, clen);
     154         697 :                 pos += clen;
     155         697 :                 iter++;
     156             :         }
     157             : 
     158          96 :         return 0;
     159             : }
     160             : 
     161             : 
     162         357 : const struct ikev2_encr_alg * ikev2_get_encr(int id)
     163             : {
     164             :         size_t i;
     165             : 
     166         376 :         for (i = 0; i < NUM_ENCR_ALGS; i++) {
     167         376 :                 if (ikev2_encr_algs[i].id == id)
     168         357 :                         return &ikev2_encr_algs[i];
     169             :         }
     170             : 
     171           0 :         return NULL;
     172             : }
     173             : 
     174             : 
     175          86 : int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
     176             :                        const u8 *plain, u8 *crypt, size_t len)
     177             : {
     178             :         struct crypto_cipher *cipher;
     179             :         int encr_alg;
     180             : 
     181          86 :         switch (alg) {
     182             :         case ENCR_3DES:
     183           4 :                 encr_alg = CRYPTO_CIPHER_ALG_3DES;
     184           4 :                 break;
     185             :         case ENCR_AES_CBC:
     186          82 :                 encr_alg = CRYPTO_CIPHER_ALG_AES;
     187          82 :                 break;
     188             :         default:
     189           0 :                 wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
     190           0 :                 return -1;
     191             :         }
     192             : 
     193          86 :         cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
     194          86 :         if (cipher == NULL) {
     195           3 :                 wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
     196           3 :                 return -1;
     197             :         }
     198             : 
     199          83 :         if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) {
     200           0 :                 wpa_printf(MSG_INFO, "IKEV2: Encryption failed");
     201           0 :                 crypto_cipher_deinit(cipher);
     202           0 :                 return -1;
     203             :         }
     204          83 :         crypto_cipher_deinit(cipher);
     205             : 
     206          83 :         return 0;
     207             : }
     208             : 
     209             : 
     210          73 : int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
     211             :                        const u8 *crypt, u8 *plain, size_t len)
     212             : {
     213             :         struct crypto_cipher *cipher;
     214             :         int encr_alg;
     215             : 
     216          73 :         switch (alg) {
     217             :         case ENCR_3DES:
     218           0 :                 encr_alg = CRYPTO_CIPHER_ALG_3DES;
     219           0 :                 break;
     220             :         case ENCR_AES_CBC:
     221          73 :                 encr_alg = CRYPTO_CIPHER_ALG_AES;
     222          73 :                 break;
     223             :         default:
     224           0 :                 wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
     225           0 :                 return -1;
     226             :         }
     227             : 
     228          73 :         cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
     229          73 :         if (cipher == NULL) {
     230           2 :                 wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
     231           2 :                 return -1;
     232             :         }
     233             : 
     234          71 :         if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) {
     235           0 :                 wpa_printf(MSG_INFO, "IKEV2: Decryption failed");
     236           0 :                 crypto_cipher_deinit(cipher);
     237           0 :                 return -1;
     238             :         }
     239          71 :         crypto_cipher_deinit(cipher);
     240             : 
     241          71 :         return 0;
     242             : }
     243             : 
     244             : 
     245         240 : int ikev2_parse_payloads(struct ikev2_payloads *payloads,
     246             :                          u8 next_payload, const u8 *pos, const u8 *end)
     247             : {
     248             :         const struct ikev2_payload_hdr *phdr;
     249             : 
     250         240 :         os_memset(payloads, 0, sizeof(*payloads));
     251             : 
     252         988 :         while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) {
     253             :                 unsigned int plen, pdatalen, left;
     254             :                 const u8 *pdata;
     255         512 :                 wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u",
     256             :                            next_payload);
     257         512 :                 if (end < pos)
     258           0 :                         return -1;
     259         512 :                 left = end - pos;
     260         512 :                 if (left < sizeof(*phdr)) {
     261           1 :                         wpa_printf(MSG_INFO, "IKEV2:   Too short message for "
     262             :                                    "payload header (left=%ld)",
     263             :                                    (long) (end - pos));
     264           1 :                         return -1;
     265             :                 }
     266         511 :                 phdr = (const struct ikev2_payload_hdr *) pos;
     267         511 :                 plen = WPA_GET_BE16(phdr->payload_length);
     268         511 :                 if (plen < sizeof(*phdr) || plen > left) {
     269           2 :                         wpa_printf(MSG_INFO, "IKEV2:   Invalid payload header "
     270             :                                    "length %d", plen);
     271           2 :                         return -1;
     272             :                 }
     273             : 
     274        1018 :                 wpa_printf(MSG_DEBUG, "IKEV2:   Next Payload: %u  Flags: 0x%x"
     275             :                            "  Payload Length: %u",
     276        1018 :                            phdr->next_payload, phdr->flags, plen);
     277             : 
     278         509 :                 pdata = (const u8 *) (phdr + 1);
     279         509 :                 pdatalen = plen - sizeof(*phdr);
     280             : 
     281         509 :                 switch (next_payload) {
     282             :                 case IKEV2_PAYLOAD_SA:
     283         120 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Security "
     284             :                                    "Association");
     285         120 :                         payloads->sa = pdata;
     286         120 :                         payloads->sa_len = pdatalen;
     287         120 :                         break;
     288             :                 case IKEV2_PAYLOAD_KEY_EXCHANGE:
     289         103 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Key "
     290             :                                    "Exchange");
     291         103 :                         payloads->ke = pdata;
     292         103 :                         payloads->ke_len = pdatalen;
     293         103 :                         break;
     294             :                 case IKEV2_PAYLOAD_IDi:
     295          26 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: IDi");
     296          26 :                         payloads->idi = pdata;
     297          26 :                         payloads->idi_len = pdatalen;
     298          26 :                         break;
     299             :                 case IKEV2_PAYLOAD_IDr:
     300          44 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: IDr");
     301          44 :                         payloads->idr = pdata;
     302          44 :                         payloads->idr_len = pdatalen;
     303          44 :                         break;
     304             :                 case IKEV2_PAYLOAD_CERTIFICATE:
     305           1 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Certificate");
     306           1 :                         payloads->cert = pdata;
     307           1 :                         payloads->cert_len = pdatalen;
     308           1 :                         break;
     309             :                 case IKEV2_PAYLOAD_AUTHENTICATION:
     310          38 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: "
     311             :                                    "Authentication");
     312          38 :                         payloads->auth = pdata;
     313          38 :                         payloads->auth_len = pdatalen;
     314          38 :                         break;
     315             :                 case IKEV2_PAYLOAD_NONCE:
     316          99 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Nonce");
     317          99 :                         payloads->nonce = pdata;
     318          99 :                         payloads->nonce_len = pdatalen;
     319          99 :                         break;
     320             :                 case IKEV2_PAYLOAD_ENCRYPTED:
     321          75 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Encrypted");
     322          75 :                         payloads->encrypted = pdata;
     323          75 :                         payloads->encrypted_len = pdatalen;
     324          75 :                         break;
     325             :                 case IKEV2_PAYLOAD_NOTIFICATION:
     326           1 :                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: "
     327             :                                    "Notification");
     328           1 :                         payloads->notification = pdata;
     329           1 :                         payloads->notification_len = pdatalen;
     330           1 :                         break;
     331             :                 default:
     332           2 :                         if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) {
     333           1 :                                 wpa_printf(MSG_INFO, "IKEV2:   Unsupported "
     334             :                                            "critical payload %u - reject the "
     335             :                                            "entire message", next_payload);
     336           1 :                                 return -1;
     337             :                         } else {
     338           1 :                                 wpa_printf(MSG_DEBUG, "IKEV2:   Skipped "
     339             :                                            "unsupported payload %u",
     340             :                                            next_payload);
     341             :                         }
     342             :                 }
     343             : 
     344         583 :                 if (next_payload == IKEV2_PAYLOAD_ENCRYPTED &&
     345          75 :                     pos + plen == end) {
     346             :                         /*
     347             :                          * Next Payload in the case of Encrypted Payload is
     348             :                          * actually the payload type for the first embedded
     349             :                          * payload.
     350             :                          */
     351          75 :                         payloads->encr_next_payload = phdr->next_payload;
     352          75 :                         next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD;
     353             :                 } else
     354         433 :                         next_payload = phdr->next_payload;
     355             : 
     356         508 :                 pos += plen;
     357             :         }
     358             : 
     359         236 :         if (pos != end) {
     360           1 :                 wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after "
     361             :                            "payloads");
     362           1 :                 return -1;
     363             :         }
     364             : 
     365         235 :         return 0;
     366             : }
     367             : 
     368             : 
     369          83 : int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
     370             :                            const u8 *ID, size_t ID_len, u8 ID_type,
     371             :                            struct ikev2_keys *keys, int initiator,
     372             :                            const u8 *shared_secret, size_t shared_secret_len,
     373             :                            const u8 *nonce, size_t nonce_len,
     374             :                            const u8 *key_pad, size_t key_pad_len,
     375             :                            u8 *auth_data)
     376             : {
     377             :         size_t sign_len, buf_len;
     378             :         u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN];
     379             :         const struct ikev2_prf_alg *prf;
     380          83 :         const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr;
     381             : 
     382          83 :         prf = ikev2_get_prf(prf_alg);
     383          83 :         if (sign_msg == NULL || ID == NULL || SK_p == NULL ||
     384          83 :             shared_secret == NULL || nonce == NULL || prf == NULL)
     385           0 :                 return -1;
     386             : 
     387             :         /* prf(SK_pi/r,IDi/r') */
     388          83 :         buf_len = 4 + ID_len;
     389          83 :         buf = os_zalloc(buf_len);
     390          83 :         if (buf == NULL)
     391           3 :                 return -1;
     392          80 :         buf[0] = ID_type;
     393          80 :         os_memcpy(buf + 4, ID, ID_len);
     394          80 :         if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len,
     395             :                            1, (const u8 **) &buf, &buf_len, hash) < 0) {
     396           2 :                 os_free(buf);
     397           2 :                 return -1;
     398             :         }
     399          78 :         os_free(buf);
     400             : 
     401             :         /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */
     402          78 :         sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len;
     403          78 :         sign_data = os_malloc(sign_len);
     404          78 :         if (sign_data == NULL)
     405           0 :                 return -1;
     406          78 :         pos = sign_data;
     407          78 :         os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg));
     408          78 :         pos += wpabuf_len(sign_msg);
     409          78 :         os_memcpy(pos, nonce, nonce_len);
     410          78 :         pos += nonce_len;
     411          78 :         os_memcpy(pos, hash, prf->hash_len);
     412             : 
     413             :         /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */
     414          78 :         if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1,
     415          77 :                            &key_pad, &key_pad_len, hash) < 0 ||
     416          77 :             ikev2_prf_hash(prf->id, hash, prf->hash_len, 1,
     417             :                            (const u8 **) &sign_data, &sign_len, auth_data) < 0)
     418             :         {
     419           2 :                 os_free(sign_data);
     420           2 :                 return -1;
     421             :         }
     422          76 :         os_free(sign_data);
     423             : 
     424          76 :         return 0;
     425             : }
     426             : 
     427             : 
     428          75 : u8 * ikev2_decrypt_payload(int encr_id, int integ_id,
     429             :                            struct ikev2_keys *keys, int initiator,
     430             :                            const struct ikev2_hdr *hdr,
     431             :                            const u8 *encrypted, size_t encrypted_len,
     432             :                            size_t *res_len)
     433             : {
     434             :         size_t iv_len;
     435             :         const u8 *pos, *end, *iv, *integ;
     436             :         u8 hash[IKEV2_MAX_HASH_LEN], *decrypted;
     437             :         size_t decrypted_len, pad_len;
     438             :         const struct ikev2_integ_alg *integ_alg;
     439             :         const struct ikev2_encr_alg *encr_alg;
     440          75 :         const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
     441          75 :         const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
     442             : 
     443          75 :         if (encrypted == NULL) {
     444           0 :                 wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH");
     445           0 :                 return NULL;
     446             :         }
     447             : 
     448          75 :         encr_alg = ikev2_get_encr(encr_id);
     449          75 :         if (encr_alg == NULL) {
     450           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
     451           0 :                 return NULL;
     452             :         }
     453          75 :         iv_len = encr_alg->block_size;
     454             : 
     455          75 :         integ_alg = ikev2_get_integ(integ_id);
     456          75 :         if (integ_alg == NULL) {
     457           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
     458           0 :                 return NULL;
     459             :         }
     460             : 
     461          75 :         if (encrypted_len < iv_len + 1 + integ_alg->hash_len) {
     462           0 :                 wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity "
     463             :                           "Checksum");
     464           0 :                 return NULL;
     465             :         }
     466             : 
     467          75 :         iv = encrypted;
     468          75 :         pos = iv + iv_len;
     469          75 :         end = encrypted + encrypted_len;
     470          75 :         integ = end - integ_alg->hash_len;
     471             : 
     472          75 :         if (SK_a == NULL) {
     473           0 :                 wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
     474           0 :                 return NULL;
     475             :         }
     476          75 :         if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
     477             :                              (const u8 *) hdr,
     478          75 :                              integ - (const u8 *) hdr, hash) < 0) {
     479           1 :                 wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity "
     480             :                            "hash");
     481           1 :                 return NULL;
     482             :         }
     483          74 :         if (os_memcmp_const(integ, hash, integ_alg->hash_len) != 0) {
     484           0 :                 wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
     485             :                            "Data");
     486           0 :                 return NULL;
     487             :         }
     488             : 
     489          74 :         if (SK_e == NULL) {
     490           0 :                 wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
     491           0 :                 return NULL;
     492             :         }
     493             : 
     494          74 :         decrypted_len = integ - pos;
     495          74 :         decrypted = os_malloc(decrypted_len);
     496          74 :         if (decrypted == NULL)
     497           1 :                 return NULL;
     498             : 
     499          73 :         if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos,
     500             :                                decrypted, decrypted_len) < 0) {
     501           2 :                 os_free(decrypted);
     502           2 :                 return NULL;
     503             :         }
     504             : 
     505          71 :         pad_len = decrypted[decrypted_len - 1];
     506          71 :         if (decrypted_len < pad_len + 1) {
     507           0 :                 wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted "
     508             :                            "payload");
     509           0 :                 os_free(decrypted);
     510           0 :                 return NULL;
     511             :         }
     512             : 
     513          71 :         decrypted_len -= pad_len + 1;
     514             : 
     515          71 :         *res_len = decrypted_len;
     516          71 :         return decrypted;
     517             : }
     518             : 
     519             : 
     520         189 : void ikev2_update_hdr(struct wpabuf *msg)
     521             : {
     522             :         struct ikev2_hdr *hdr;
     523             : 
     524             :         /* Update lenth field in HDR */
     525         189 :         hdr = wpabuf_mhead(msg);
     526         189 :         WPA_PUT_BE32(hdr->length, wpabuf_len(msg));
     527         189 : }
     528             : 
     529             : 
     530          87 : int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
     531             :                           int initiator, struct wpabuf *msg,
     532             :                           struct wpabuf *plain, u8 next_payload)
     533             : {
     534             :         struct ikev2_payload_hdr *phdr;
     535             :         size_t plen;
     536             :         size_t iv_len, pad_len;
     537             :         u8 *icv, *iv;
     538             :         const struct ikev2_integ_alg *integ_alg;
     539             :         const struct ikev2_encr_alg *encr_alg;
     540          87 :         const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
     541          87 :         const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
     542             : 
     543          87 :         wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload");
     544             : 
     545             :         /* Encr - RFC 4306, Sect. 3.14 */
     546             : 
     547          87 :         encr_alg = ikev2_get_encr(encr_id);
     548          87 :         if (encr_alg == NULL) {
     549           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
     550           0 :                 return -1;
     551             :         }
     552          87 :         iv_len = encr_alg->block_size;
     553             : 
     554          87 :         integ_alg = ikev2_get_integ(integ_id);
     555          87 :         if (integ_alg == NULL) {
     556           0 :                 wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
     557           0 :                 return -1;
     558             :         }
     559             : 
     560          87 :         if (SK_e == NULL) {
     561           0 :                 wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
     562           0 :                 return -1;
     563             :         }
     564             : 
     565          87 :         if (SK_a == NULL) {
     566           0 :                 wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
     567           0 :                 return -1;
     568             :         }
     569             : 
     570          87 :         phdr = wpabuf_put(msg, sizeof(*phdr));
     571          87 :         phdr->next_payload = next_payload;
     572          87 :         phdr->flags = 0;
     573             : 
     574          87 :         iv = wpabuf_put(msg, iv_len);
     575          87 :         if (random_get_bytes(iv, iv_len)) {
     576           1 :                 wpa_printf(MSG_INFO, "IKEV2: Could not generate IV");
     577           1 :                 return -1;
     578             :         }
     579             : 
     580          86 :         pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len;
     581          86 :         if (pad_len == iv_len)
     582           0 :                 pad_len = 0;
     583          86 :         wpabuf_put(plain, pad_len);
     584          86 :         wpabuf_put_u8(plain, pad_len);
     585             : 
     586         172 :         if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv,
     587          86 :                                wpabuf_head(plain), wpabuf_mhead(plain),
     588             :                                wpabuf_len(plain)) < 0)
     589           3 :                 return -1;
     590             : 
     591          83 :         wpabuf_put_buf(msg, plain);
     592             : 
     593             :         /* Need to update all headers (Length fields) prior to hash func */
     594          83 :         icv = wpabuf_put(msg, integ_alg->hash_len);
     595          83 :         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
     596          83 :         WPA_PUT_BE16(phdr->payload_length, plen);
     597             : 
     598          83 :         ikev2_update_hdr(msg);
     599             : 
     600         166 :         return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
     601          83 :                                 wpabuf_head(msg),
     602          83 :                                 wpabuf_len(msg) - integ_alg->hash_len, icv);
     603             : 
     604             :         return 0;
     605             : }
     606             : 
     607             : 
     608          74 : int ikev2_keys_set(struct ikev2_keys *keys)
     609             : {
     610         296 :         return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei &&
     611         222 :                 keys->SK_er && keys->SK_pi && keys->SK_pr;
     612             : }
     613             : 
     614             : 
     615         266 : void ikev2_free_keys(struct ikev2_keys *keys)
     616             : {
     617         266 :         os_free(keys->SK_d);
     618         266 :         os_free(keys->SK_ai);
     619         266 :         os_free(keys->SK_ar);
     620         266 :         os_free(keys->SK_ei);
     621         266 :         os_free(keys->SK_er);
     622         266 :         os_free(keys->SK_pi);
     623         266 :         os_free(keys->SK_pr);
     624         266 :         keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er =
     625         266 :                 keys->SK_pi = keys->SK_pr = NULL;
     626         266 : }
     627             : 
     628             : 
     629          83 : int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
     630             :                          const struct ikev2_integ_alg *integ,
     631             :                          const struct ikev2_encr_alg *encr,
     632             :                          const u8 *skeyseed, const u8 *data, size_t data_len,
     633             :                          struct ikev2_keys *keys)
     634             : {
     635             :         u8 *keybuf, *pos;
     636             :         size_t keybuf_len;
     637             : 
     638             :         /*
     639             :          * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } =
     640             :          *      prf+(SKEYSEED, Ni | Nr | SPIi | SPIr )
     641             :          */
     642          83 :         ikev2_free_keys(keys);
     643          83 :         keys->SK_d_len = prf->key_len;
     644          83 :         keys->SK_integ_len = integ->key_len;
     645          83 :         keys->SK_encr_len = encr->key_len;
     646          83 :         keys->SK_prf_len = prf->key_len;
     647             : 
     648         249 :         keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
     649         166 :                 2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
     650          83 :         keybuf = os_malloc(keybuf_len);
     651          83 :         if (keybuf == NULL)
     652           1 :                 return -1;
     653             : 
     654          82 :         if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len,
     655             :                            data, data_len, keybuf, keybuf_len)) {
     656           8 :                 os_free(keybuf);
     657           8 :                 return -1;
     658             :         }
     659             : 
     660          74 :         pos = keybuf;
     661             : 
     662          74 :         keys->SK_d = os_malloc(keys->SK_d_len);
     663          74 :         if (keys->SK_d) {
     664          74 :                 os_memcpy(keys->SK_d, pos, keys->SK_d_len);
     665         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d",
     666          74 :                                 keys->SK_d, keys->SK_d_len);
     667             :         }
     668          74 :         pos += keys->SK_d_len;
     669             : 
     670          74 :         keys->SK_ai = os_malloc(keys->SK_integ_len);
     671          74 :         if (keys->SK_ai) {
     672          74 :                 os_memcpy(keys->SK_ai, pos, keys->SK_integ_len);
     673         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai",
     674          74 :                                 keys->SK_ai, keys->SK_integ_len);
     675             :         }
     676          74 :         pos += keys->SK_integ_len;
     677             : 
     678          74 :         keys->SK_ar = os_malloc(keys->SK_integ_len);
     679          74 :         if (keys->SK_ar) {
     680          74 :                 os_memcpy(keys->SK_ar, pos, keys->SK_integ_len);
     681         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar",
     682          74 :                                 keys->SK_ar, keys->SK_integ_len);
     683             :         }
     684          74 :         pos += keys->SK_integ_len;
     685             : 
     686          74 :         keys->SK_ei = os_malloc(keys->SK_encr_len);
     687          74 :         if (keys->SK_ei) {
     688          74 :                 os_memcpy(keys->SK_ei, pos, keys->SK_encr_len);
     689         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei",
     690          74 :                                 keys->SK_ei, keys->SK_encr_len);
     691             :         }
     692          74 :         pos += keys->SK_encr_len;
     693             : 
     694          74 :         keys->SK_er = os_malloc(keys->SK_encr_len);
     695          74 :         if (keys->SK_er) {
     696          74 :                 os_memcpy(keys->SK_er, pos, keys->SK_encr_len);
     697         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er",
     698          74 :                                 keys->SK_er, keys->SK_encr_len);
     699             :         }
     700          74 :         pos += keys->SK_encr_len;
     701             : 
     702          74 :         keys->SK_pi = os_malloc(keys->SK_prf_len);
     703          74 :         if (keys->SK_pi) {
     704          74 :                 os_memcpy(keys->SK_pi, pos, keys->SK_prf_len);
     705         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi",
     706          74 :                                 keys->SK_pi, keys->SK_prf_len);
     707             :         }
     708          74 :         pos += keys->SK_prf_len;
     709             : 
     710          74 :         keys->SK_pr = os_malloc(keys->SK_prf_len);
     711          74 :         if (keys->SK_pr) {
     712          74 :                 os_memcpy(keys->SK_pr, pos, keys->SK_prf_len);
     713         148 :                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr",
     714          74 :                                 keys->SK_pr, keys->SK_prf_len);
     715             :         }
     716             : 
     717          74 :         os_free(keybuf);
     718             : 
     719          74 :         if (!ikev2_keys_set(keys)) {
     720           0 :                 ikev2_free_keys(keys);
     721           0 :                 return -1;
     722             :         }
     723             : 
     724          74 :         return 0;
     725             : }

Generated by: LCOV version 1.10