eap_ikev2_common.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * EAP-IKEv2 common routines
  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. #include "includes.h"
  9. #include "common.h"
  10. #include "eap_defs.h"
  11. #include "eap_common.h"
  12. #include "ikev2_common.h"
  13. #include "eap_ikev2_common.h"
  14. int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
  15. const u8 *i_nonce, size_t i_nonce_len,
  16. const u8 *r_nonce, size_t r_nonce_len,
  17. u8 *keymat)
  18. {
  19. u8 *nonces;
  20. size_t nlen;
  21. /* KEYMAT = prf+(SK_d, Ni | Nr) */
  22. if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
  23. return -1;
  24. nlen = i_nonce_len + r_nonce_len;
  25. nonces = os_malloc(nlen);
  26. if (nonces == NULL)
  27. return -1;
  28. os_memcpy(nonces, i_nonce, i_nonce_len);
  29. os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
  30. if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
  31. keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
  32. os_free(nonces);
  33. return -1;
  34. }
  35. os_free(nonces);
  36. wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
  37. keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
  38. return 0;
  39. }
  40. struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code)
  41. {
  42. struct wpabuf *msg;
  43. msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
  44. if (msg == NULL) {
  45. wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
  46. "for fragment ack");
  47. return NULL;
  48. }
  49. wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
  50. return msg;
  51. }
  52. int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
  53. int initiator, const struct wpabuf *msg,
  54. const u8 *pos, const u8 *end)
  55. {
  56. const struct ikev2_integ_alg *integ;
  57. size_t icv_len;
  58. u8 icv[IKEV2_MAX_HASH_LEN];
  59. const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
  60. integ = ikev2_get_integ(integ_alg);
  61. if (integ == NULL) {
  62. wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
  63. "transform / cannot validate ICV");
  64. return -1;
  65. }
  66. icv_len = integ->hash_len;
  67. if (end - pos < (int) icv_len) {
  68. wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
  69. "message for Integrity Checksum Data");
  70. return -1;
  71. }
  72. if (SK_a == NULL) {
  73. wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
  74. return -1;
  75. }
  76. if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
  77. wpabuf_head(msg),
  78. wpabuf_len(msg) - icv_len, icv) < 0) {
  79. wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
  80. return -1;
  81. }
  82. if (os_memcmp_const(icv, end - icv_len, icv_len) != 0) {
  83. wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
  84. wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
  85. icv, icv_len);
  86. wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
  87. end - icv_len, icv_len);
  88. return -1;
  89. }
  90. wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
  91. "the received message");
  92. return icv_len;
  93. }