ikev2_common.c

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

Generated on Sat Nov 21 23:16:51 2009 for hostapd by  doxygen 1.6.1