1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IKEv2 common routines for initiator and responder 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "sha1.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "md5.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "crypto.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ikev2_common.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct ikev2_integ_alg ikev2_integ_algs[] = { 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { AUTH_HMAC_SHA1_96, 20, 12 }, 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { AUTH_HMAC_MD5_96, 16, 12 } 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0])) 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct ikev2_prf_alg ikev2_prf_algs[] = { 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { PRF_HMAC_SHA1, 20, 20 }, 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { PRF_HMAC_MD5, 16, 16 } 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0])) 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct ikev2_encr_alg ikev2_encr_algs[] = { 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */ 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { ENCR_3DES, 24, 8 } 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0])) 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtconst struct ikev2_integ_alg * ikev2_get_integ(int id) 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t i; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < NUM_INTEG_ALGS; i++) { 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_integ_algs[i].id == id) 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return &ikev2_integ_algs[i]; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data, 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t data_len, u8 *hash) 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 tmphash[IKEV2_MAX_HASH_LEN]; 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (alg) { 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AUTH_HMAC_SHA1_96: 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_len != 20) 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1(key, key_len, data, data_len, tmphash); 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hash, tmphash, 12); 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AUTH_HMAC_MD5_96: 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_len != 16) 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_md5(key, key_len, data, data_len, tmphash); 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hash, tmphash, 12); 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtconst struct ikev2_prf_alg * ikev2_get_prf(int id) 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t i; 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < NUM_PRF_ALGS; i++) { 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_prf_algs[i].id == id) 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return &ikev2_prf_algs[i]; 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_prf_hash(int alg, const u8 *key, size_t key_len, 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t num_elem, const u8 *addr[], const size_t *len, 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *hash) 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (alg) { 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PRF_HMAC_SHA1: 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1_vector(key, key_len, num_elem, addr, len, hash); 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PRF_HMAC_MD5: 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_md5_vector(key, key_len, num_elem, addr, len, hash); 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_prf_plus(int alg, const u8 *key, size_t key_len, 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *data, size_t data_len, 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *out, size_t out_len) 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 hash[IKEV2_MAX_HASH_LEN]; 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t hash_len; 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 iter, *pos, *end; 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr[3]; 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len[3]; 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_prf_alg *prf; 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int res; 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prf = ikev2_get_prf(alg); 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prf == NULL) 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hash_len = prf->hash_len; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[0] = hash; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[0] = hash_len; 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[1] = data; 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[1] = data_len; 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr[2] = &iter; 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len[2] = 1; 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = out; 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = out + out_len; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iter = 1; 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (pos < end) { 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t clen; 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (iter == 1) 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1], 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &len[1], hash); 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = ikev2_prf_hash(alg, key, key_len, 3, addr, len, 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hash); 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt clen = hash_len; 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((int) clen > end - pos) 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt clen = end - pos; 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, hash, clen); 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += clen; 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iter++; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtconst struct ikev2_encr_alg * ikev2_get_encr(int id) 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t i; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < NUM_ENCR_ALGS; i++) { 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_encr_algs[i].id == id) 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return &ikev2_encr_algs[i]; 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* from des.c */ 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct des3_key_s { 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 ek[3][32]; 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u32 dk[3][32]; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des3_key_setup(const u8 *key, struct des3_key_s *dkey); 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *plain, u8 *crypt, size_t len) 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct crypto_cipher *cipher; 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int encr_alg; 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (alg == ENCR_3DES) { 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct des3_key_s des3key; 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t i, blocks; 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos; 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* ECB mode is used incorrectly for 3DES!? */ 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_len != 24) { 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt des3_key_setup(key, &des3key); 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt blocks = len / 8; 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = crypt; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < blocks; i++) { 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt des3_encrypt(pos, &des3key, pos); 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 8; 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (alg) { 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case ENCR_3DES: 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_3DES; 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case ENCR_AES_CBC: 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_AES; 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cipher = crypto_cipher_init(encr_alg, iv, key, key_len); 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cipher == NULL) { 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) { 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Encryption failed"); 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt crypto_cipher_deinit(cipher); 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt crypto_cipher_deinit(cipher); 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *crypt, u8 *plain, size_t len) 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct crypto_cipher *cipher; 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int encr_alg; 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (alg == ENCR_3DES) { 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct des3_key_s des3key; 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t i, blocks; 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* ECB mode is used incorrectly for 3DES!? */ 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_len != 24) { 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt des3_key_setup(key, &des3key); 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len % 8) { 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted " 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "length"); 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt blocks = len / 8; 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < blocks; i++) { 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt des3_decrypt(crypt, &des3key, plain); 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plain += 8; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt crypt += 8; 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (alg) { 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case ENCR_3DES: 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_3DES; 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case ENCR_AES_CBC: 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr_alg = CRYPTO_CIPHER_ALG_AES; 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cipher = crypto_cipher_init(encr_alg, iv, key, key_len); 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cipher == NULL) { 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) { 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Decryption failed"); 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt crypto_cipher_deinit(cipher); 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt crypto_cipher_deinit(cipher); 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_parse_payloads(struct ikev2_payloads *payloads, 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 next_payload, const u8 *pos, const u8 *end) 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_payload_hdr *phdr; 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(payloads, 0, sizeof(*payloads)); 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) { 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int plen, pdatalen; 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pdata; 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u", 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_payload); 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (end - pos < (int) sizeof(*phdr)) { 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short message for " 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "payload header (left=%ld)", 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (long) (end - pos)); 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = (const struct ikev2_payload_hdr *) pos; 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = WPA_GET_BE16(phdr->payload_length); 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (plen < (int) sizeof(*phdr) || pos + plen > end) { 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid payload header " 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "length %d", plen); 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x" 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " Payload Length: %d", 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload, phdr->flags, plen); 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pdata = (const u8 *) (phdr + 1); 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pdatalen = plen - sizeof(*phdr); 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (next_payload) { 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_SA: 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security " 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Association"); 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->sa = pdata; 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->sa_len = pdatalen; 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_KEY_EXCHANGE: 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key " 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Exchange"); 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->ke = pdata; 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->ke_len = pdatalen; 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_IDi: 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi"); 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->idi = pdata; 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->idi_len = pdatalen; 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_IDr: 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr"); 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->idr = pdata; 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->idr_len = pdatalen; 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_CERTIFICATE: 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate"); 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->cert = pdata; 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->cert_len = pdatalen; 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_AUTHENTICATION: 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: " 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Authentication"); 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->auth = pdata; 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->auth_len = pdatalen; 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_NONCE: 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce"); 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->nonce = pdata; 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->nonce_len = pdatalen; 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_ENCRYPTED: 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted"); 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->encrypted = pdata; 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->encrypted_len = pdatalen; 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case IKEV2_PAYLOAD_NOTIFICATION: 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Payload: " 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Notification"); 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->notification = pdata; 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->notification_len = pdatalen; 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) { 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported " 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "critical payload %u - reject the " 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "entire message", next_payload); 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Skipped " 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "unsupported payload %u", 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_payload); 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (next_payload == IKEV2_PAYLOAD_ENCRYPTED && 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos + plen == end) { 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Next Payload in the case of Encrypted Payload is 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * actually the payload type for the first embedded 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * payload. 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt payloads->encr_next_payload = phdr->next_payload; 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD; 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_payload = phdr->next_payload; 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += plen; 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos != end) { 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after " 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "payloads"); 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *ID, size_t ID_len, u8 ID_type, 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_keys *keys, int initiator, 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *shared_secret, size_t shared_secret_len, 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *nonce, size_t nonce_len, 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *key_pad, size_t key_pad_len, 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *auth_data) 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t sign_len, buf_len; 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN]; 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_prf_alg *prf; 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr; 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prf = ikev2_get_prf(prf_alg); 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sign_msg == NULL || ID == NULL || SK_p == NULL || 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret == NULL || nonce == NULL || prf == NULL) 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* prf(SK_pi/r,IDi/r') */ 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len = 4 + ID_len; 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_zalloc(buf_len); 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[0] = ID_type; 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf + 4, ID, ID_len); 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len, 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1, (const u8 **) &buf, &buf_len, hash) < 0) { 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */ 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len; 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sign_data = os_malloc(sign_len); 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sign_data == NULL) 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = sign_data; 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg)); 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += wpabuf_len(sign_msg); 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, nonce, nonce_len); 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += nonce_len; 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, hash, prf->hash_len); 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */ 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1, 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &key_pad, &key_pad_len, hash) < 0 || 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_prf_hash(prf->id, hash, prf->hash_len, 1, 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (const u8 **) &sign_data, &sign_len, auth_data) < 0) 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt { 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sign_data); 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sign_data); 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtu8 * ikev2_decrypt_payload(int encr_id, int integ_id, 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_keys *keys, int initiator, 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_hdr *hdr, 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *encrypted, size_t encrypted_len, 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t *res_len) 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t iv_len; 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos, *end, *iv, *integ; 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 hash[IKEV2_MAX_HASH_LEN], *decrypted; 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t decrypted_len, pad_len; 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_integ_alg *integ_alg; 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_encr_alg *encr_alg; 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (encrypted == NULL) { 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH"); 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr_alg = ikev2_get_encr(encr_id); 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (encr_alg == NULL) { 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iv_len = encr_alg->block_size; 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt integ_alg = ikev2_get_integ(integ_id); 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (integ_alg == NULL) { 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (encrypted_len < iv_len + 1 + integ_alg->hash_len) { 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity " 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Checksum"); 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iv = encrypted; 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = iv + iv_len; 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = encrypted + encrypted_len; 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt integ = end - integ_alg->hash_len; 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (SK_a == NULL) { 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (const u8 *) hdr, 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt integ - (const u8 *) hdr, hash) < 0) { 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity " 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "hash"); 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) { 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum " 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Data"); 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (SK_e == NULL) { 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted_len = integ - pos; 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted = os_malloc(decrypted_len); 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (decrypted == NULL) 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos, 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted, decrypted_len) < 0) { 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pad_len = decrypted[decrypted_len - 1]; 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (decrypted_len < pad_len + 1) { 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted " 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "payload"); 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted_len -= pad_len + 1; 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *res_len = decrypted_len; 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return decrypted; 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ikev2_update_hdr(struct wpabuf *msg) 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_hdr *hdr; 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Update lenth field in HDR */ 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = wpabuf_mhead(msg); 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE32(hdr->length, wpabuf_len(msg)); 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int initiator, struct wpabuf *msg, 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *plain, u8 next_payload) 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_payload_hdr *phdr; 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t plen; 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t iv_len, pad_len; 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *icv, *iv; 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_integ_alg *integ_alg; 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_encr_alg *encr_alg; 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload"); 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Encr - RFC 4306, Sect. 3.14 */ 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt encr_alg = ikev2_get_encr(encr_id); 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (encr_alg == NULL) { 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iv_len = encr_alg->block_size; 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt integ_alg = ikev2_get_integ(integ_id); 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (integ_alg == NULL) { 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (SK_e == NULL) { 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (SK_a == NULL) { 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->next_payload = next_payload; 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phdr->flags = 0; 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iv = wpabuf_put(msg, iv_len); 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(iv, iv_len)) { 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not generate IV"); 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len; 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pad_len == iv_len) 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pad_len = 0; 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put(plain, pad_len); 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(plain, pad_len); 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_head(plain), wpabuf_mhead(plain), 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_len(plain)) < 0) 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_buf(msg, plain); 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Need to update all headers (Length fields) prior to hash func */ 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt icv = wpabuf_put(msg, integ_alg->hash_len); 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_update_hdr(msg); 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_head(msg), 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_len(msg) - integ_alg->hash_len, icv); 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_keys_set(struct ikev2_keys *keys) 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei && 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_er && keys->SK_pi && keys->SK_pr; 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ikev2_free_keys(struct ikev2_keys *keys) 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_d); 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_ai); 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_ar); 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_ei); 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_er); 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_pi); 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keys->SK_pr); 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er = 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_pi = keys->SK_pr = NULL; 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_integ_alg *integ, 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct ikev2_encr_alg *encr, 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *skeyseed, const u8 *data, size_t data_len, 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ikev2_keys *keys) 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *keybuf, *pos; 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t keybuf_len; 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr ) 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_free_keys(keys); 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_d_len = prf->key_len; 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_integ_len = integ->key_len; 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_encr_len = encr->key_len; 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_prf_len = prf->key_len; 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CCNS_PL 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Uses encryption key length for SK_d; should be PRF length */ 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_d_len = keys->SK_encr_len; 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CCNS_PL */ 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len + 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 2 * keys->SK_encr_len + 2 * keys->SK_prf_len; 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keybuf = os_malloc(keybuf_len); 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keybuf == NULL) 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len, 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data, data_len, keybuf, keybuf_len)) { 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keybuf); 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = keybuf; 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_d = os_malloc(keys->SK_d_len); 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_d) { 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_d, pos, keys->SK_d_len); 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d", 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_d, keys->SK_d_len); 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += keys->SK_d_len; 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_ai = os_malloc(keys->SK_integ_len); 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_ai) { 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_ai, pos, keys->SK_integ_len); 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai", 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_ai, keys->SK_integ_len); 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += keys->SK_integ_len; 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_ar = os_malloc(keys->SK_integ_len); 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_ar) { 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_ar, pos, keys->SK_integ_len); 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar", 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_ar, keys->SK_integ_len); 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += keys->SK_integ_len; 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_ei = os_malloc(keys->SK_encr_len); 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_ei) { 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_ei, pos, keys->SK_encr_len); 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei", 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_ei, keys->SK_encr_len); 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += keys->SK_encr_len; 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_er = os_malloc(keys->SK_encr_len); 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_er) { 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_er, pos, keys->SK_encr_len); 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er", 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_er, keys->SK_encr_len); 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += keys->SK_encr_len; 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_pi = os_malloc(keys->SK_prf_len); 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_pi) { 775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_pi, pos, keys->SK_prf_len); 776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi", 777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_pi, keys->SK_prf_len); 778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += keys->SK_prf_len; 780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_pr = os_malloc(keys->SK_prf_len); 782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (keys->SK_pr) { 783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(keys->SK_pr, pos, keys->SK_prf_len); 784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr", 785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt keys->SK_pr, keys->SK_prf_len); 786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(keybuf); 789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!ikev2_keys_set(keys)) { 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ikev2_free_keys(keys); 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 797