ikev2_common.c
Go to the documentation of this file.
00001 /*
00002  * IKEv2 common routines for initiator and responder
00003  * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "crypto/crypto.h"
00019 #include "crypto/md5.h"
00020 #include "crypto/sha1.h"
00021 #include "ikev2_common.h"
00022 
00023 
00024 static struct ikev2_integ_alg ikev2_integ_algs[] = {
00025         { AUTH_HMAC_SHA1_96, 20, 12 },
00026         { AUTH_HMAC_MD5_96, 16, 12 }
00027 };
00028 
00029 #define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0]))
00030 
00031 
00032 static struct ikev2_prf_alg ikev2_prf_algs[] = {
00033         { PRF_HMAC_SHA1, 20, 20 },
00034         { PRF_HMAC_MD5, 16, 16 }
00035 };
00036 
00037 #define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0]))
00038 
00039 
00040 static struct ikev2_encr_alg ikev2_encr_algs[] = {
00041         { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */
00042         { ENCR_3DES, 24, 8 }
00043 };
00044 
00045 #define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0]))
00046 
00047 
00048 const struct ikev2_integ_alg * ikev2_get_integ(int id)
00049 {
00050         size_t i;
00051 
00052         for (i = 0; i < NUM_INTEG_ALGS; i++) {
00053                 if (ikev2_integ_algs[i].id == id)
00054                         return &ikev2_integ_algs[i];
00055         }
00056 
00057         return NULL;
00058 }
00059 
00060 
00061 int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data,
00062                      size_t data_len, u8 *hash)
00063 {
00064         u8 tmphash[IKEV2_MAX_HASH_LEN];
00065 
00066         switch (alg) {
00067         case AUTH_HMAC_SHA1_96:
00068                 if (key_len != 20)
00069                         return -1;
00070                 hmac_sha1(key, key_len, data, data_len, tmphash);
00071                 os_memcpy(hash, tmphash, 12);
00072                 break;
00073         case AUTH_HMAC_MD5_96:
00074                 if (key_len != 16)
00075                         return -1;
00076                 hmac_md5(key, key_len, data, data_len, tmphash);
00077                 os_memcpy(hash, tmphash, 12);
00078                 break;
00079         default:
00080                 return -1;
00081         }
00082 
00083         return 0;
00084 }
00085 
00086 
00087 const struct ikev2_prf_alg * ikev2_get_prf(int id)
00088 {
00089         size_t i;
00090 
00091         for (i = 0; i < NUM_PRF_ALGS; i++) {
00092                 if (ikev2_prf_algs[i].id == id)
00093                         return &ikev2_prf_algs[i];
00094         }
00095 
00096         return NULL;
00097 }
00098 
00099 
00100 int ikev2_prf_hash(int alg, const u8 *key, size_t key_len,
00101                    size_t num_elem, const u8 *addr[], const size_t *len,
00102                    u8 *hash)
00103 {
00104         switch (alg) {
00105         case PRF_HMAC_SHA1:
00106                 hmac_sha1_vector(key, key_len, num_elem, addr, len, hash);
00107                 break;
00108         case PRF_HMAC_MD5:
00109                 hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
00110                 break;
00111         default:
00112                 return -1;
00113         }
00114 
00115         return 0;
00116 }
00117 
00118 
00119 int ikev2_prf_plus(int alg, const u8 *key, size_t key_len,
00120                    const u8 *data, size_t data_len,
00121                    u8 *out, size_t out_len)
00122 {
00123         u8 hash[IKEV2_MAX_HASH_LEN];
00124         size_t hash_len;
00125         u8 iter, *pos, *end;
00126         const u8 *addr[3];
00127         size_t len[3];
00128         const struct ikev2_prf_alg *prf;
00129         int res;
00130 
00131         prf = ikev2_get_prf(alg);
00132         if (prf == NULL)
00133                 return -1;
00134         hash_len = prf->hash_len;
00135 
00136         addr[0] = hash;
00137         len[0] = hash_len;
00138         addr[1] = data;
00139         len[1] = data_len;
00140         addr[2] = &iter;
00141         len[2] = 1;
00142 
00143         pos = out;
00144         end = out + out_len;
00145         iter = 1;
00146         while (pos < end) {
00147                 size_t clen;
00148                 if (iter == 1)
00149                         res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1],
00150                                              &len[1], hash);
00151                 else
00152                         res = ikev2_prf_hash(alg, key, key_len, 3, addr, len,
00153                                              hash);
00154                 if (res < 0)
00155                         return -1;
00156                 clen = hash_len;
00157                 if ((int) clen > end - pos)
00158                         clen = end - pos;
00159                 os_memcpy(pos, hash, clen);
00160                 pos += clen;
00161                 iter++;
00162         }
00163 
00164         return 0;
00165 }
00166 
00167 
00168 const struct ikev2_encr_alg * ikev2_get_encr(int id)
00169 {
00170         size_t i;
00171 
00172         for (i = 0; i < NUM_ENCR_ALGS; i++) {
00173                 if (ikev2_encr_algs[i].id == id)
00174                         return &ikev2_encr_algs[i];
00175         }
00176 
00177         return NULL;
00178 }
00179 
00180 
00181 #ifdef CCNS_PL
00182 /* from des.c */
00183 struct des3_key_s {
00184         u32 ek[3][32];
00185         u32 dk[3][32];
00186 };
00187 
00188 void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
00189 void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
00190 void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
00191 #endif /* CCNS_PL */
00192 
00193 
00194 int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
00195                        const u8 *plain, u8 *crypt, size_t len)
00196 {
00197         struct crypto_cipher *cipher;
00198         int encr_alg;
00199 
00200 #ifdef CCNS_PL
00201         if (alg == ENCR_3DES) {
00202                 struct des3_key_s des3key;
00203                 size_t i, blocks;
00204                 u8 *pos;
00205 
00206                 /* ECB mode is used incorrectly for 3DES!? */
00207                 if (key_len != 24) {
00208                         wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
00209                         return -1;
00210                 }
00211                 des3_key_setup(key, &des3key);
00212 
00213                 blocks = len / 8;
00214                 pos = crypt;
00215                 for (i = 0; i < blocks; i++) {
00216                         des3_encrypt(pos, &des3key, pos);
00217                         pos += 8;
00218                 }
00219         } else {
00220 #endif /* CCNS_PL */
00221         switch (alg) {
00222         case ENCR_3DES:
00223                 encr_alg = CRYPTO_CIPHER_ALG_3DES;
00224                 break;
00225         case ENCR_AES_CBC:
00226                 encr_alg = CRYPTO_CIPHER_ALG_AES;
00227                 break;
00228         default:
00229                 wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
00230                 return -1;
00231         }
00232 
00233         cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
00234         if (cipher == NULL) {
00235                 wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
00236                 return -1;
00237         }
00238 
00239         if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) {
00240                 wpa_printf(MSG_INFO, "IKEV2: Encryption failed");
00241                 crypto_cipher_deinit(cipher);
00242                 return -1;
00243         }
00244         crypto_cipher_deinit(cipher);
00245 #ifdef CCNS_PL
00246         }
00247 #endif /* CCNS_PL */
00248 
00249         return 0;
00250 }
00251 
00252 
00253 int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv,
00254                        const u8 *crypt, u8 *plain, size_t len)
00255 {
00256         struct crypto_cipher *cipher;
00257         int encr_alg;
00258 
00259 #ifdef CCNS_PL
00260         if (alg == ENCR_3DES) {
00261                 struct des3_key_s des3key;
00262                 size_t i, blocks;
00263 
00264                 /* ECB mode is used incorrectly for 3DES!? */
00265                 if (key_len != 24) {
00266                         wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length");
00267                         return -1;
00268                 }
00269                 des3_key_setup(key, &des3key);
00270 
00271                 if (len % 8) {
00272                         wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted "
00273                                    "length");
00274                         return -1;
00275                 }
00276                 blocks = len / 8;
00277                 for (i = 0; i < blocks; i++) {
00278                         des3_decrypt(crypt, &des3key, plain);
00279                         plain += 8;
00280                         crypt += 8;
00281                 }
00282         } else {
00283 #endif /* CCNS_PL */
00284         switch (alg) {
00285         case ENCR_3DES:
00286                 encr_alg = CRYPTO_CIPHER_ALG_3DES;
00287                 break;
00288         case ENCR_AES_CBC:
00289                 encr_alg = CRYPTO_CIPHER_ALG_AES;
00290                 break;
00291         default:
00292                 wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg);
00293                 return -1;
00294         }
00295 
00296         cipher = crypto_cipher_init(encr_alg, iv, key, key_len);
00297         if (cipher == NULL) {
00298                 wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher");
00299                 return -1;
00300         }
00301 
00302         if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) {
00303                 wpa_printf(MSG_INFO, "IKEV2: Decryption failed");
00304                 crypto_cipher_deinit(cipher);
00305                 return -1;
00306         }
00307         crypto_cipher_deinit(cipher);
00308 #ifdef CCNS_PL
00309         }
00310 #endif /* CCNS_PL */
00311 
00312         return 0;
00313 }
00314 
00315 
00316 int ikev2_parse_payloads(struct ikev2_payloads *payloads,
00317                          u8 next_payload, const u8 *pos, const u8 *end)
00318 {
00319         const struct ikev2_payload_hdr *phdr;
00320 
00321         os_memset(payloads, 0, sizeof(*payloads));
00322 
00323         while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) {
00324                 int plen, pdatalen;
00325                 const u8 *pdata;
00326                 wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u",
00327                            next_payload);
00328                 if (end - pos < (int) sizeof(*phdr)) {
00329                         wpa_printf(MSG_INFO, "IKEV2:   Too short message for "
00330                                    "payload header (left=%ld)",
00331                                    (long) (end - pos));
00332                 }
00333                 phdr = (const struct ikev2_payload_hdr *) pos;
00334                 plen = WPA_GET_BE16(phdr->payload_length);
00335                 if (plen < (int) sizeof(*phdr) || pos + plen > end) {
00336                         wpa_printf(MSG_INFO, "IKEV2:   Invalid payload header "
00337                                    "length %d", plen);
00338                         return -1;
00339                 }
00340 
00341                 wpa_printf(MSG_DEBUG, "IKEV2:   Next Payload: %u  Flags: 0x%x"
00342                            "  Payload Length: %d",
00343                            phdr->next_payload, phdr->flags, plen);
00344 
00345                 pdata = (const u8 *) (phdr + 1);
00346                 pdatalen = plen - sizeof(*phdr);
00347 
00348                 switch (next_payload) {
00349                 case IKEV2_PAYLOAD_SA:
00350                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Security "
00351                                    "Association");
00352                         payloads->sa = pdata;
00353                         payloads->sa_len = pdatalen;
00354                         break;
00355                 case IKEV2_PAYLOAD_KEY_EXCHANGE:
00356                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Key "
00357                                    "Exchange");
00358                         payloads->ke = pdata;
00359                         payloads->ke_len = pdatalen;
00360                         break;
00361                 case IKEV2_PAYLOAD_IDi:
00362                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: IDi");
00363                         payloads->idi = pdata;
00364                         payloads->idi_len = pdatalen;
00365                         break;
00366                 case IKEV2_PAYLOAD_IDr:
00367                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: IDr");
00368                         payloads->idr = pdata;
00369                         payloads->idr_len = pdatalen;
00370                         break;
00371                 case IKEV2_PAYLOAD_CERTIFICATE:
00372                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Certificate");
00373                         payloads->cert = pdata;
00374                         payloads->cert_len = pdatalen;
00375                         break;
00376                 case IKEV2_PAYLOAD_AUTHENTICATION:
00377                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: "
00378                                    "Authentication");
00379                         payloads->auth = pdata;
00380                         payloads->auth_len = pdatalen;
00381                         break;
00382                 case IKEV2_PAYLOAD_NONCE:
00383                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Nonce");
00384                         payloads->nonce = pdata;
00385                         payloads->nonce_len = pdatalen;
00386                         break;
00387                 case IKEV2_PAYLOAD_ENCRYPTED:
00388                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: Encrypted");
00389                         payloads->encrypted = pdata;
00390                         payloads->encrypted_len = pdatalen;
00391                         break;
00392                 case IKEV2_PAYLOAD_NOTIFICATION:
00393                         wpa_printf(MSG_DEBUG, "IKEV2:   Payload: "
00394                                    "Notification");
00395                         payloads->notification = pdata;
00396                         payloads->notification_len = pdatalen;
00397                         break;
00398                 default:
00399                         if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) {
00400                                 wpa_printf(MSG_INFO, "IKEV2:   Unsupported "
00401                                            "critical payload %u - reject the "
00402                                            "entire message", next_payload);
00403                                 return -1;
00404                         } else {
00405                                 wpa_printf(MSG_DEBUG, "IKEV2:   Skipped "
00406                                            "unsupported payload %u",
00407                                            next_payload);
00408                         }
00409                 }
00410 
00411                 if (next_payload == IKEV2_PAYLOAD_ENCRYPTED &&
00412                     pos + plen == end) {
00413                         /*
00414                          * Next Payload in the case of Encrypted Payload is
00415                          * actually the payload type for the first embedded
00416                          * payload.
00417                          */
00418                         payloads->encr_next_payload = phdr->next_payload;
00419                         next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD;
00420                 } else
00421                         next_payload = phdr->next_payload;
00422 
00423                 pos += plen;
00424         }
00425 
00426         if (pos != end) {
00427                 wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after "
00428                            "payloads");
00429                 return -1;
00430         }
00431 
00432         return 0;
00433 }
00434 
00435 
00436 int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg,
00437                            const u8 *ID, size_t ID_len, u8 ID_type,
00438                            struct ikev2_keys *keys, int initiator,
00439                            const u8 *shared_secret, size_t shared_secret_len,
00440                            const u8 *nonce, size_t nonce_len,
00441                            const u8 *key_pad, size_t key_pad_len,
00442                            u8 *auth_data)
00443 {
00444         size_t sign_len, buf_len;
00445         u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN];
00446         const struct ikev2_prf_alg *prf;
00447         const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr;
00448 
00449         prf = ikev2_get_prf(prf_alg);
00450         if (sign_msg == NULL || ID == NULL || SK_p == NULL ||
00451             shared_secret == NULL || nonce == NULL || prf == NULL)
00452                 return -1;
00453 
00454         /* prf(SK_pi/r,IDi/r') */
00455         buf_len = 4 + ID_len;
00456         buf = os_zalloc(buf_len);
00457         if (buf == NULL)
00458                 return -1;
00459         buf[0] = ID_type;
00460         os_memcpy(buf + 4, ID, ID_len);
00461         if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len,
00462                            1, (const u8 **) &buf, &buf_len, hash) < 0) {
00463                 os_free(buf);
00464                 return -1;
00465         }
00466         os_free(buf);
00467 
00468         /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */
00469         sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len;
00470         sign_data = os_malloc(sign_len);
00471         if (sign_data == NULL)
00472                 return -1;
00473         pos = sign_data;
00474         os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg));
00475         pos += wpabuf_len(sign_msg);
00476         os_memcpy(pos, nonce, nonce_len);
00477         pos += nonce_len;
00478         os_memcpy(pos, hash, prf->hash_len);
00479 
00480         /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */
00481         if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1,
00482                            &key_pad, &key_pad_len, hash) < 0 ||
00483             ikev2_prf_hash(prf->id, hash, prf->hash_len, 1,
00484                            (const u8 **) &sign_data, &sign_len, auth_data) < 0)
00485         {
00486                 os_free(sign_data);
00487                 return -1;
00488         }
00489         os_free(sign_data);
00490 
00491         return 0;
00492 }
00493 
00494 
00495 u8 * ikev2_decrypt_payload(int encr_id, int integ_id,
00496                            struct ikev2_keys *keys, int initiator,
00497                            const struct ikev2_hdr *hdr,
00498                            const u8 *encrypted, size_t encrypted_len,
00499                            size_t *res_len)
00500 {
00501         size_t iv_len;
00502         const u8 *pos, *end, *iv, *integ;
00503         u8 hash[IKEV2_MAX_HASH_LEN], *decrypted;
00504         size_t decrypted_len, pad_len;
00505         const struct ikev2_integ_alg *integ_alg;
00506         const struct ikev2_encr_alg *encr_alg;
00507         const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
00508         const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
00509 
00510         if (encrypted == NULL) {
00511                 wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH");
00512                 return NULL;
00513         }
00514 
00515         encr_alg = ikev2_get_encr(encr_id);
00516         if (encr_alg == NULL) {
00517                 wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
00518                 return NULL;
00519         }
00520         iv_len = encr_alg->block_size;
00521 
00522         integ_alg = ikev2_get_integ(integ_id);
00523         if (integ_alg == NULL) {
00524                 wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
00525                 return NULL;
00526         }
00527 
00528         if (encrypted_len < iv_len + 1 + integ_alg->hash_len) {
00529                 wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity "
00530                           "Checksum");
00531                 return NULL;
00532         }
00533 
00534         iv = encrypted;
00535         pos = iv + iv_len;
00536         end = encrypted + encrypted_len;
00537         integ = end - integ_alg->hash_len;
00538 
00539         if (SK_a == NULL) {
00540                 wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
00541                 return NULL;
00542         }
00543         if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
00544                              (const u8 *) hdr,
00545                              integ - (const u8 *) hdr, hash) < 0) {
00546                 wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity "
00547                            "hash");
00548                 return NULL;
00549         }
00550         if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) {
00551                 wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum "
00552                            "Data");
00553                 return NULL;
00554         }
00555 
00556         if (SK_e == NULL) {
00557                 wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
00558                 return NULL;
00559         }
00560 
00561         decrypted_len = integ - pos;
00562         decrypted = os_malloc(decrypted_len);
00563         if (decrypted == NULL)
00564                 return NULL;
00565 
00566         if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos,
00567                                decrypted, decrypted_len) < 0) {
00568                 os_free(decrypted);
00569                 return NULL;
00570         }
00571 
00572         pad_len = decrypted[decrypted_len - 1];
00573         if (decrypted_len < pad_len + 1) {
00574                 wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted "
00575                            "payload");
00576                 os_free(decrypted);
00577                 return NULL;
00578         }
00579 
00580         decrypted_len -= pad_len + 1;
00581 
00582         *res_len = decrypted_len;
00583         return decrypted;
00584 }
00585 
00586 
00587 void ikev2_update_hdr(struct wpabuf *msg)
00588 {
00589         struct ikev2_hdr *hdr;
00590 
00591         /* Update lenth field in HDR */
00592         hdr = wpabuf_mhead(msg);
00593         WPA_PUT_BE32(hdr->length, wpabuf_len(msg));
00594 }
00595 
00596 
00597 int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys,
00598                           int initiator, struct wpabuf *msg,
00599                           struct wpabuf *plain, u8 next_payload)
00600 {
00601         struct ikev2_payload_hdr *phdr;
00602         size_t plen;
00603         size_t iv_len, pad_len;
00604         u8 *icv, *iv;
00605         const struct ikev2_integ_alg *integ_alg;
00606         const struct ikev2_encr_alg *encr_alg;
00607         const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er;
00608         const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
00609 
00610         wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload");
00611 
00612         /* Encr - RFC 4306, Sect. 3.14 */
00613 
00614         encr_alg = ikev2_get_encr(encr_id);
00615         if (encr_alg == NULL) {
00616                 wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type");
00617                 return -1;
00618         }
00619         iv_len = encr_alg->block_size;
00620 
00621         integ_alg = ikev2_get_integ(integ_id);
00622         if (integ_alg == NULL) {
00623                 wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type");
00624                 return -1;
00625         }
00626 
00627         if (SK_e == NULL) {
00628                 wpa_printf(MSG_INFO, "IKEV2: No SK_e available");
00629                 return -1;
00630         }
00631 
00632         if (SK_a == NULL) {
00633                 wpa_printf(MSG_INFO, "IKEV2: No SK_a available");
00634                 return -1;
00635         }
00636 
00637         phdr = wpabuf_put(msg, sizeof(*phdr));
00638         phdr->next_payload = next_payload;
00639         phdr->flags = 0;
00640 
00641         iv = wpabuf_put(msg, iv_len);
00642         if (os_get_random(iv, iv_len)) {
00643                 wpa_printf(MSG_INFO, "IKEV2: Could not generate IV");
00644                 return -1;
00645         }
00646 
00647         pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len;
00648         if (pad_len == iv_len)
00649                 pad_len = 0;
00650         wpabuf_put(plain, pad_len);
00651         wpabuf_put_u8(plain, pad_len);
00652 
00653         if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv,
00654                                wpabuf_head(plain), wpabuf_mhead(plain),
00655                                wpabuf_len(plain)) < 0)
00656                 return -1;
00657 
00658         wpabuf_put_buf(msg, plain);
00659 
00660         /* Need to update all headers (Length fields) prior to hash func */
00661         icv = wpabuf_put(msg, integ_alg->hash_len);
00662         plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
00663         WPA_PUT_BE16(phdr->payload_length, plen);
00664 
00665         ikev2_update_hdr(msg);
00666 
00667         return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len,
00668                                 wpabuf_head(msg),
00669                                 wpabuf_len(msg) - integ_alg->hash_len, icv);
00670 
00671         return 0;
00672 }
00673 
00674 
00675 int ikev2_keys_set(struct ikev2_keys *keys)
00676 {
00677         return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei &&
00678                 keys->SK_er && keys->SK_pi && keys->SK_pr;
00679 }
00680 
00681 
00682 void ikev2_free_keys(struct ikev2_keys *keys)
00683 {
00684         os_free(keys->SK_d);
00685         os_free(keys->SK_ai);
00686         os_free(keys->SK_ar);
00687         os_free(keys->SK_ei);
00688         os_free(keys->SK_er);
00689         os_free(keys->SK_pi);
00690         os_free(keys->SK_pr);
00691         keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er =
00692                 keys->SK_pi = keys->SK_pr = NULL;
00693 }
00694 
00695 
00696 int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf,
00697                          const struct ikev2_integ_alg *integ,
00698                          const struct ikev2_encr_alg *encr,
00699                          const u8 *skeyseed, const u8 *data, size_t data_len,
00700                          struct ikev2_keys *keys)
00701 {
00702         u8 *keybuf, *pos;
00703         size_t keybuf_len;
00704 
00705         /*
00706          * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } =
00707          *      prf+(SKEYSEED, Ni | Nr | SPIi | SPIr )
00708          */
00709         ikev2_free_keys(keys);
00710         keys->SK_d_len = prf->key_len;
00711         keys->SK_integ_len = integ->key_len;
00712         keys->SK_encr_len = encr->key_len;
00713         keys->SK_prf_len = prf->key_len;
00714 #ifdef CCNS_PL
00715         /* Uses encryption key length for SK_d; should be PRF length */
00716         keys->SK_d_len = keys->SK_encr_len;
00717 #endif /* CCNS_PL */
00718 
00719         keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len +
00720                 2 * keys->SK_encr_len + 2 * keys->SK_prf_len;
00721         keybuf = os_malloc(keybuf_len);
00722         if (keybuf == NULL)
00723                 return -1;
00724 
00725         if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len,
00726                            data, data_len, keybuf, keybuf_len)) {
00727                 os_free(keybuf);
00728                 return -1;
00729         }
00730 
00731         pos = keybuf;
00732 
00733         keys->SK_d = os_malloc(keys->SK_d_len);
00734         if (keys->SK_d) {
00735                 os_memcpy(keys->SK_d, pos, keys->SK_d_len);
00736                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d",
00737                                 keys->SK_d, keys->SK_d_len);
00738         }
00739         pos += keys->SK_d_len;
00740 
00741         keys->SK_ai = os_malloc(keys->SK_integ_len);
00742         if (keys->SK_ai) {
00743                 os_memcpy(keys->SK_ai, pos, keys->SK_integ_len);
00744                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai",
00745                                 keys->SK_ai, keys->SK_integ_len);
00746         }
00747         pos += keys->SK_integ_len;
00748 
00749         keys->SK_ar = os_malloc(keys->SK_integ_len);
00750         if (keys->SK_ar) {
00751                 os_memcpy(keys->SK_ar, pos, keys->SK_integ_len);
00752                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar",
00753                                 keys->SK_ar, keys->SK_integ_len);
00754         }
00755         pos += keys->SK_integ_len;
00756 
00757         keys->SK_ei = os_malloc(keys->SK_encr_len);
00758         if (keys->SK_ei) {
00759                 os_memcpy(keys->SK_ei, pos, keys->SK_encr_len);
00760                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei",
00761                                 keys->SK_ei, keys->SK_encr_len);
00762         }
00763         pos += keys->SK_encr_len;
00764 
00765         keys->SK_er = os_malloc(keys->SK_encr_len);
00766         if (keys->SK_er) {
00767                 os_memcpy(keys->SK_er, pos, keys->SK_encr_len);
00768                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er",
00769                                 keys->SK_er, keys->SK_encr_len);
00770         }
00771         pos += keys->SK_encr_len;
00772 
00773         keys->SK_pi = os_malloc(keys->SK_prf_len);
00774         if (keys->SK_pi) {
00775                 os_memcpy(keys->SK_pi, pos, keys->SK_prf_len);
00776                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi",
00777                                 keys->SK_pi, keys->SK_prf_len);
00778         }
00779         pos += keys->SK_prf_len;
00780 
00781         keys->SK_pr = os_malloc(keys->SK_prf_len);
00782         if (keys->SK_pr) {
00783                 os_memcpy(keys->SK_pr, pos, keys->SK_prf_len);
00784                 wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr",
00785                                 keys->SK_pr, keys->SK_prf_len);
00786         }
00787 
00788         os_free(keybuf);
00789 
00790         if (!ikev2_keys_set(keys)) {
00791                 ikev2_free_keys(keys);
00792                 return -1;
00793         }
00794 
00795         return 0;
00796 }


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:25:14