Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/proposal_substructure.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2012-2020 Tobias Brunner
! 3: * Copyright (C) 2005-2010 Martin Willi
! 4: * Copyright (C) 2005 Jan Hutter
! 5: * HSR Hochschule fuer Technik Rapperswil
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify it
! 8: * under the terms of the GNU General Public License as published by the
! 9: * Free Software Foundation; either version 2 of the License, or (at your
! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 11: *
! 12: * This program is distributed in the hope that it will be useful, but
! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 15: * for more details.
! 16: */
! 17:
! 18: #include <stddef.h>
! 19:
! 20: #include "proposal_substructure.h"
! 21:
! 22: #include <encoding/payloads/encodings.h>
! 23: #include <encoding/payloads/transform_substructure.h>
! 24: #include <library.h>
! 25: #include <collections/linked_list.h>
! 26: #include <daemon.h>
! 27:
! 28: /**
! 29: * IKEv2 Value for a proposal payload.
! 30: */
! 31: #define PROPOSAL_TYPE_VALUE 2
! 32:
! 33: typedef struct private_proposal_substructure_t private_proposal_substructure_t;
! 34:
! 35: /**
! 36: * Private data of an proposal_substructure_t object.
! 37: */
! 38: struct private_proposal_substructure_t {
! 39:
! 40: /**
! 41: * Public proposal_substructure_t interface.
! 42: */
! 43: proposal_substructure_t public;
! 44:
! 45: /**
! 46: * Next payload type.
! 47: */
! 48: uint8_t next_payload;
! 49:
! 50: /**
! 51: * reserved byte
! 52: */
! 53: uint8_t reserved;
! 54:
! 55: /**
! 56: * Length of this payload.
! 57: */
! 58: uint16_t proposal_length;
! 59:
! 60: /**
! 61: * Proposal number.
! 62: */
! 63: uint8_t proposal_number;
! 64:
! 65: /**
! 66: * Protocol ID.
! 67: */
! 68: uint8_t protocol_id;
! 69:
! 70: /**
! 71: * SPI size of the following SPI.
! 72: */
! 73: uint8_t spi_size;
! 74:
! 75: /**
! 76: * Number of transforms.
! 77: */
! 78: uint8_t transforms_count;
! 79:
! 80: /**
! 81: * SPI is stored as chunk.
! 82: */
! 83: chunk_t spi;
! 84:
! 85: /**
! 86: * Transforms are stored in a linked_list_t.
! 87: */
! 88: linked_list_t *transforms;
! 89:
! 90: /**
! 91: * Type of this payload, PLV2_PROPOSAL_SUBSTRUCTURE or PLV1_PROPOSAL_SUBSTRUCTURE
! 92: */
! 93: payload_type_t type;
! 94: };
! 95:
! 96: /**
! 97: * Encoding rules for a IKEv1 Proposal substructure.
! 98: */
! 99: static encoding_rule_t encodings_v1[] = {
! 100: /* 1 Byte next payload type, stored in the field next_payload */
! 101: { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
! 102: /* 1 Reserved Byte */
! 103: { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) },
! 104: /* Length of the whole proposal substructure payload*/
! 105: { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
! 106: /* proposal number is a number of 8 bit */
! 107: { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
! 108: /* protocol ID is a number of 8 bit */
! 109: { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
! 110: /* SPI Size has its own type */
! 111: { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
! 112: /* Number of transforms is a number of 8 bit */
! 113: { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
! 114: /* SPI is a chunk of variable size*/
! 115: { SPI, offsetof(private_proposal_substructure_t, spi) },
! 116: /* Transforms are stored in a transform substructure list */
! 117: { PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE,
! 118: offsetof(private_proposal_substructure_t, transforms) },
! 119: };
! 120:
! 121: /**
! 122: * Encoding rules for a IKEv2 Proposal substructure.
! 123: */
! 124: static encoding_rule_t encodings_v2[] = {
! 125: /* 1 Byte next payload type, stored in the field next_payload */
! 126: { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
! 127: /* 1 Reserved Byte */
! 128: { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) },
! 129: /* Length of the whole proposal substructure payload*/
! 130: { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
! 131: /* proposal number is a number of 8 bit */
! 132: { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
! 133: /* protocol ID is a number of 8 bit */
! 134: { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
! 135: /* SPI Size has its own type */
! 136: { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
! 137: /* Number of transforms is a number of 8 bit */
! 138: { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
! 139: /* SPI is a chunk of variable size*/
! 140: { SPI, offsetof(private_proposal_substructure_t, spi) },
! 141: /* Transforms are stored in a transform substructure list */
! 142: { PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE,
! 143: offsetof(private_proposal_substructure_t, transforms) },
! 144: };
! 145:
! 146: /*
! 147: 1 2 3
! 148: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
! 149: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 150: ! 0 (last) or 2 ! RESERVED ! Proposal Length !
! 151: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 152: ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
! 153: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 154: ~ SPI (variable) ~
! 155: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 156: ! !
! 157: ~ <Transforms> ~
! 158: ! !
! 159: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 160: */
! 161:
! 162: /**
! 163: * Encryption.
! 164: */
! 165: typedef enum {
! 166: IKEV1_ENCR_DES_CBC = 1,
! 167: IKEV1_ENCR_IDEA_CBC = 2,
! 168: IKEV1_ENCR_BLOWFISH_CBC = 3,
! 169: IKEV1_ENCR_RC5_R16_B64_CBC = 4,
! 170: IKEV1_ENCR_3DES_CBC = 5,
! 171: IKEV1_ENCR_CAST_CBC = 6,
! 172: IKEV1_ENCR_AES_CBC = 7,
! 173: IKEV1_ENCR_CAMELLIA_CBC = 8,
! 174: /* FreeS/WAN proprietary */
! 175: IKEV1_ENCR_SERPENT_CBC = 65004,
! 176: IKEV1_ENCR_TWOFISH_CBC = 65005,
! 177: } ikev1_encryption_t;
! 178:
! 179: /**
! 180: * IKEv1 hash.
! 181: */
! 182: typedef enum {
! 183: IKEV1_HASH_MD5 = 1,
! 184: IKEV1_HASH_SHA1 = 2,
! 185: IKEV1_HASH_TIGER = 3,
! 186: IKEV1_HASH_SHA2_256 = 4,
! 187: IKEV1_HASH_SHA2_384 = 5,
! 188: IKEV1_HASH_SHA2_512 = 6,
! 189: } ikev1_hash_t;
! 190:
! 191: /**
! 192: * IKEv1 Transform ID IKE.
! 193: */
! 194: typedef enum {
! 195: IKEV1_TRANSID_KEY_IKE = 1,
! 196: } ikev1_ike_transid_t;
! 197:
! 198: /**
! 199: * IKEv1 Transform ID ESP encryption algorithm.
! 200: */
! 201: typedef enum {
! 202: IKEV1_ESP_ENCR_DES_IV64 = 1,
! 203: IKEV1_ESP_ENCR_DES = 2,
! 204: IKEV1_ESP_ENCR_3DES = 3,
! 205: IKEV1_ESP_ENCR_RC5 = 4,
! 206: IKEV1_ESP_ENCR_IDEA = 5,
! 207: IKEV1_ESP_ENCR_CAST = 6,
! 208: IKEV1_ESP_ENCR_BLOWFISH = 7,
! 209: IKEV1_ESP_ENCR_3IDEA = 8,
! 210: IKEV1_ESP_ENCR_DES_IV32 = 9,
! 211: IKEV1_ESP_ENCR_RC4 = 10,
! 212: IKEV1_ESP_ENCR_NULL = 11,
! 213: IKEV1_ESP_ENCR_AES_CBC = 12,
! 214: IKEV1_ESP_ENCR_AES_CTR = 13,
! 215: IKEV1_ESP_ENCR_AES_CCM_8 = 14,
! 216: IKEV1_ESP_ENCR_AES_CCM_12 = 15,
! 217: IKEV1_ESP_ENCR_AES_CCM_16 = 16,
! 218: IKEV1_ESP_ENCR_AES_GCM_8 = 18,
! 219: IKEV1_ESP_ENCR_AES_GCM_12 = 19,
! 220: IKEV1_ESP_ENCR_AES_GCM_16 = 20,
! 221: IKEV1_ESP_ENCR_SEED_CBC = 21,
! 222: IKEV1_ESP_ENCR_CAMELLIA = 22,
! 223: IKEV1_ESP_ENCR_NULL_AUTH_AES_GMAC = 23,
! 224: /* FreeS/WAN proprietary */
! 225: IKEV1_ESP_ENCR_SERPENT = 252,
! 226: IKEV1_ESP_ENCR_TWOFISH = 253,
! 227: } ikev1_esp_transid_t;
! 228:
! 229: /**
! 230: * IKEv1 Transform ID AH authentication algorithm.
! 231: */
! 232: typedef enum {
! 233: IKEV1_AH_HMAC_MD5 = 2,
! 234: IKEV1_AH_HMAC_SHA = 3,
! 235: IKEV1_AH_DES_MAC = 4,
! 236: IKEV1_AH_HMAC_SHA2_256 = 5,
! 237: IKEV1_AH_HMAC_SHA2_384 = 6,
! 238: IKEV1_AH_HMAC_SHA2_512 = 7,
! 239: IKEV1_AH_RIPEMD = 8,
! 240: IKEV1_AH_AES_XCBC_MAC = 9,
! 241: IKEV1_AH_RSA = 10,
! 242: IKEV1_AH_AES_128_GMAC = 11,
! 243: IKEV1_AH_AES_192_GMAC = 12,
! 244: IKEV1_AH_AES_256_GMAC = 13,
! 245: } ikev1_ah_transid_t;
! 246:
! 247: /**
! 248: * IKEv1 authentication algorithm.
! 249: */
! 250: typedef enum {
! 251: IKEV1_AUTH_HMAC_MD5 = 1,
! 252: IKEV1_AUTH_HMAC_SHA = 2,
! 253: IKEV1_AUTH_DES_MAC = 3,
! 254: IKEV1_AUTH_KPDK = 4,
! 255: IKEV1_AUTH_HMAC_SHA2_256 = 5,
! 256: IKEV1_AUTH_HMAC_SHA2_384 = 6,
! 257: IKEV1_AUTH_HMAC_SHA2_512 = 7,
! 258: IKEV1_AUTH_HMAC_RIPEMD = 8,
! 259: IKEV1_AUTH_AES_XCBC_MAC = 9,
! 260: IKEV1_AUTH_SIG_RSA = 10,
! 261: IKEV1_AUTH_AES_128_GMAC = 11,
! 262: IKEV1_AUTH_AES_192_GMAC = 12,
! 263: IKEV1_AUTH_AES_256_GMAC = 13,
! 264: } ikev1_auth_algo_t;
! 265:
! 266: /**
! 267: * IKEv1 ESP Encapsulation mode.
! 268: */
! 269: typedef enum {
! 270: IKEV1_ENCAP_TUNNEL = 1,
! 271: IKEV1_ENCAP_TRANSPORT = 2,
! 272: IKEV1_ENCAP_UDP_TUNNEL = 3,
! 273: IKEV1_ENCAP_UDP_TRANSPORT = 4,
! 274: IKEV1_ENCAP_UDP_TUNNEL_DRAFT_00_03 = 61443,
! 275: IKEV1_ENCAP_UDP_TRANSPORT_DRAFT_00_03 = 61444,
! 276: } ikev1_esp_encap_t;
! 277:
! 278: /**
! 279: * IKEv1 Life duration types.
! 280: */
! 281: typedef enum {
! 282: IKEV1_LIFE_TYPE_SECONDS = 1,
! 283: IKEV1_LIFE_TYPE_KILOBYTES = 2,
! 284: } ikev1_life_type_t;
! 285:
! 286: /**
! 287: * IKEv1 authentication methods
! 288: */
! 289: typedef enum {
! 290: IKEV1_AUTH_PSK = 1,
! 291: IKEV1_AUTH_DSS_SIG = 2,
! 292: IKEV1_AUTH_RSA_SIG = 3,
! 293: IKEV1_AUTH_RSA_ENC = 4,
! 294: IKEV1_AUTH_RSA_ENC_REV = 5,
! 295: IKEV1_AUTH_ECDSA_256 = 9,
! 296: IKEV1_AUTH_ECDSA_384 = 10,
! 297: IKEV1_AUTH_ECDSA_521 = 11,
! 298: /* XAuth Modes */
! 299: IKEV1_AUTH_XAUTH_INIT_PSK = 65001,
! 300: IKEV1_AUTH_XAUTH_RESP_PSK = 65002,
! 301: IKEV1_AUTH_XAUTH_INIT_DSS = 65003,
! 302: IKEV1_AUTH_XAUTH_RESP_DSS = 65004,
! 303: IKEV1_AUTH_XAUTH_INIT_RSA = 65005,
! 304: IKEV1_AUTH_XAUTH_RESP_RSA = 65006,
! 305: IKEV1_AUTH_XAUTH_INIT_RSA_ENC = 65007,
! 306: IKEV1_AUTH_XAUTH_RESP_RSA_ENC = 65008,
! 307: IKEV1_AUTH_XAUTH_INIT_RSA_ENC_REV = 65009,
! 308: IKEV1_AUTH_XAUTH_RESP_RSA_ENC_REV = 65010,
! 309: /* Hybrid Modes */
! 310: IKEV1_AUTH_HYBRID_INIT_RSA = 64221,
! 311: IKEV1_AUTH_HYBRID_RESP_RSA = 64222,
! 312: IKEV1_AUTH_HYBRID_INIT_DSS = 64223,
! 313: IKEV1_AUTH_HYBRID_RESP_DSS = 64224,
! 314: } ikev1_auth_method_t;
! 315:
! 316: /**
! 317: * IKEv1 IPComp transform IDs
! 318: */
! 319: typedef enum {
! 320: IKEV1_IPCOMP_OUI = 1,
! 321: IKEV1_IPCOMP_DEFLATE = 2,
! 322: IKEV1_IPCOMP_LZS = 3,
! 323: } ikev1_ipcomp_transform_t;
! 324:
! 325: METHOD(payload_t, verify, status_t,
! 326: private_proposal_substructure_t *this)
! 327: {
! 328: status_t status = SUCCESS;
! 329: enumerator_t *enumerator;
! 330: payload_t *current;
! 331:
! 332: if (this->next_payload != PL_NONE && this->next_payload != 2)
! 333: {
! 334: /* must be 0 or 2 */
! 335: DBG1(DBG_ENC, "inconsistent next payload");
! 336: return FAILED;
! 337: }
! 338: if (this->transforms_count != this->transforms->get_count(this->transforms))
! 339: {
! 340: /* must be the same! */
! 341: DBG1(DBG_ENC, "transform count invalid");
! 342: return FAILED;
! 343: }
! 344:
! 345: switch (this->protocol_id)
! 346: {
! 347: case PROTO_IPCOMP:
! 348: if (this->spi.len != 2 && this->spi.len != 4)
! 349: {
! 350: DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal");
! 351: return FAILED;
! 352: }
! 353: break;
! 354: case PROTO_AH:
! 355: case PROTO_ESP:
! 356: if (this->spi.len != 4)
! 357: {
! 358: DBG1(DBG_ENC, "invalid SPI length in %N proposal",
! 359: protocol_id_names, this->protocol_id);
! 360: return FAILED;
! 361: }
! 362: break;
! 363: case PROTO_IKE:
! 364: if (this->type == PLV1_PROPOSAL_SUBSTRUCTURE)
! 365: {
! 366: if (this->spi.len <= 16)
! 367: { /* according to RFC 2409, section 3.5 anything between
! 368: * 0 and 16 is fine */
! 369: break;
! 370: }
! 371: }
! 372: else if (this->spi.len == 0 || this->spi.len == 8)
! 373: {
! 374: break;
! 375: }
! 376: DBG1(DBG_ENC, "invalid SPI length in IKE proposal");
! 377: return FAILED;
! 378: default:
! 379: break;
! 380: }
! 381: enumerator = this->transforms->create_enumerator(this->transforms);
! 382: while (enumerator->enumerate(enumerator, ¤t))
! 383: {
! 384: status = current->verify(current);
! 385: if (status != SUCCESS)
! 386: {
! 387: DBG1(DBG_ENC, "TRANSFORM_SUBSTRUCTURE verification failed");
! 388: break;
! 389: }
! 390: }
! 391: enumerator->destroy(enumerator);
! 392:
! 393: /* proposal number is checked in SA payload */
! 394: return status;
! 395: }
! 396:
! 397: METHOD(payload_t, get_encoding_rules, int,
! 398: private_proposal_substructure_t *this, encoding_rule_t **rules)
! 399: {
! 400: if (this->type == PLV2_PROPOSAL_SUBSTRUCTURE)
! 401: {
! 402: *rules = encodings_v2;
! 403: return countof(encodings_v2);
! 404: }
! 405: *rules = encodings_v1;
! 406: return countof(encodings_v1);
! 407: }
! 408:
! 409: METHOD(payload_t, get_header_length, int,
! 410: private_proposal_substructure_t *this)
! 411: {
! 412: return 8 + this->spi_size;
! 413: }
! 414:
! 415: METHOD(payload_t, get_type, payload_type_t,
! 416: private_proposal_substructure_t *this)
! 417: {
! 418: return this->type;
! 419: }
! 420:
! 421: METHOD(payload_t, get_next_type, payload_type_t,
! 422: private_proposal_substructure_t *this)
! 423: {
! 424: return this->next_payload;
! 425: }
! 426:
! 427: METHOD(payload_t, set_next_type, void,
! 428: private_proposal_substructure_t *this, payload_type_t type)
! 429: {
! 430: }
! 431:
! 432: /**
! 433: * (re-)compute the length of the payload.
! 434: */
! 435: static void compute_length(private_proposal_substructure_t *this)
! 436: {
! 437: enumerator_t *enumerator;
! 438: payload_t *transform;
! 439:
! 440: this->transforms_count = 0;
! 441: this->proposal_length = get_header_length(this);
! 442: enumerator = this->transforms->create_enumerator(this->transforms);
! 443: while (enumerator->enumerate(enumerator, &transform))
! 444: {
! 445: this->proposal_length += transform->get_length(transform);
! 446: this->transforms_count++;
! 447: }
! 448: enumerator->destroy(enumerator);
! 449: }
! 450:
! 451: METHOD(payload_t, get_length, size_t,
! 452: private_proposal_substructure_t *this)
! 453: {
! 454: return this->proposal_length;
! 455: }
! 456:
! 457: /**
! 458: * Add a transform substructure to the proposal
! 459: */
! 460: static void add_transform_substructure(private_proposal_substructure_t *this,
! 461: transform_substructure_t *transform)
! 462: {
! 463: if (this->transforms->get_count(this->transforms) > 0)
! 464: {
! 465: transform_substructure_t *last;
! 466:
! 467: this->transforms->get_last(this->transforms, (void **)&last);
! 468: last->set_is_last_transform(last, FALSE);
! 469: }
! 470: transform->set_is_last_transform(transform,TRUE);
! 471: this->transforms->insert_last(this->transforms, transform);
! 472: compute_length(this);
! 473: }
! 474:
! 475: METHOD(proposal_substructure_t, set_is_last_proposal, void,
! 476: private_proposal_substructure_t *this, bool is_last)
! 477: {
! 478: this->next_payload = is_last ? 0 : PROPOSAL_TYPE_VALUE;
! 479: }
! 480:
! 481: METHOD(proposal_substructure_t, set_proposal_number, void,
! 482: private_proposal_substructure_t *this,uint8_t proposal_number)
! 483: {
! 484: this->proposal_number = proposal_number;
! 485: }
! 486:
! 487: METHOD(proposal_substructure_t, get_proposal_number, uint8_t,
! 488: private_proposal_substructure_t *this)
! 489: {
! 490: return this->proposal_number;
! 491: }
! 492:
! 493: METHOD(proposal_substructure_t, set_protocol_id, void,
! 494: private_proposal_substructure_t *this,uint8_t protocol_id)
! 495: {
! 496: this->protocol_id = protocol_id;
! 497: }
! 498:
! 499: METHOD(proposal_substructure_t, get_protocol_id, uint8_t,
! 500: private_proposal_substructure_t *this)
! 501: {
! 502: return this->protocol_id;
! 503: }
! 504:
! 505: METHOD(proposal_substructure_t, set_spi, void,
! 506: private_proposal_substructure_t *this, chunk_t spi)
! 507: {
! 508: free(this->spi.ptr);
! 509: this->spi = chunk_clone(spi);
! 510: this->spi_size = spi.len;
! 511: compute_length(this);
! 512: }
! 513:
! 514: METHOD(proposal_substructure_t, get_spi, chunk_t,
! 515: private_proposal_substructure_t *this)
! 516: {
! 517: return this->spi;
! 518: }
! 519:
! 520: METHOD(proposal_substructure_t, get_cpi, bool,
! 521: private_proposal_substructure_t *this, uint16_t *cpi)
! 522: {
! 523:
! 524: transform_substructure_t *transform;
! 525: enumerator_t *enumerator;
! 526:
! 527: if (this->protocol_id != PROTO_IPCOMP)
! 528: {
! 529: return FALSE;
! 530: }
! 531:
! 532: enumerator = this->transforms->create_enumerator(this->transforms);
! 533: while (enumerator->enumerate(enumerator, &transform))
! 534: {
! 535: if (transform->get_transform_id(transform) == IKEV1_IPCOMP_DEFLATE)
! 536: {
! 537: if (cpi)
! 538: {
! 539: *cpi = htons(untoh16(this->spi.ptr + this->spi.len - 2));
! 540: }
! 541: enumerator->destroy(enumerator);
! 542: return TRUE;
! 543: }
! 544: }
! 545: enumerator->destroy(enumerator);
! 546: return FALSE;
! 547: }
! 548:
! 549: /**
! 550: * Add a transform to a proposal for IKEv2
! 551: */
! 552: static void add_to_proposal_v2(proposal_t *proposal,
! 553: transform_substructure_t *transform)
! 554: {
! 555: transform_attribute_t *tattr;
! 556: enumerator_t *enumerator;
! 557: uint16_t key_length = 0;
! 558:
! 559: enumerator = transform->create_attribute_enumerator(transform);
! 560: while (enumerator->enumerate(enumerator, &tattr))
! 561: {
! 562: if (tattr->get_attribute_type(tattr) == TATTR_IKEV2_KEY_LENGTH)
! 563: {
! 564: key_length = tattr->get_value(tattr);
! 565: break;
! 566: }
! 567: }
! 568: enumerator->destroy(enumerator);
! 569:
! 570: proposal->add_algorithm(proposal,
! 571: transform->get_transform_type_or_number(transform),
! 572: transform->get_transform_id(transform), key_length);
! 573: }
! 574:
! 575: /**
! 576: * Map IKEv1 to IKEv2 algorithms
! 577: */
! 578: typedef struct {
! 579: uint16_t ikev1;
! 580: uint16_t ikev2;
! 581: } algo_map_t;
! 582:
! 583: /**
! 584: * Encryption algorithm mapping
! 585: */
! 586: static algo_map_t map_encr[] = {
! 587: { IKEV1_ENCR_DES_CBC, ENCR_DES },
! 588: { IKEV1_ENCR_IDEA_CBC, ENCR_IDEA },
! 589: { IKEV1_ENCR_BLOWFISH_CBC, ENCR_BLOWFISH },
! 590: { IKEV1_ENCR_3DES_CBC, ENCR_3DES },
! 591: { IKEV1_ENCR_CAST_CBC, ENCR_CAST },
! 592: { IKEV1_ENCR_AES_CBC, ENCR_AES_CBC },
! 593: { IKEV1_ENCR_CAMELLIA_CBC, ENCR_CAMELLIA_CBC },
! 594: { IKEV1_ENCR_SERPENT_CBC, ENCR_SERPENT_CBC },
! 595: { IKEV1_ENCR_TWOFISH_CBC, ENCR_TWOFISH_CBC },
! 596: };
! 597:
! 598: /**
! 599: * Integrity algorithm mapping
! 600: */
! 601: static algo_map_t map_integ[] = {
! 602: { IKEV1_HASH_MD5, AUTH_HMAC_MD5_96 },
! 603: { IKEV1_HASH_SHA1, AUTH_HMAC_SHA1_96 },
! 604: { IKEV1_HASH_SHA2_256, AUTH_HMAC_SHA2_256_128 },
! 605: { IKEV1_HASH_SHA2_384, AUTH_HMAC_SHA2_384_192 },
! 606: { IKEV1_HASH_SHA2_512, AUTH_HMAC_SHA2_512_256 },
! 607: };
! 608:
! 609: /**
! 610: * PRF algorithm mapping
! 611: */
! 612: static algo_map_t map_prf[] = {
! 613: { IKEV1_HASH_MD5, PRF_HMAC_MD5 },
! 614: { IKEV1_HASH_SHA1, PRF_HMAC_SHA1 },
! 615: { IKEV1_HASH_SHA2_256, PRF_HMAC_SHA2_256 },
! 616: { IKEV1_HASH_SHA2_384, PRF_HMAC_SHA2_384 },
! 617: { IKEV1_HASH_SHA2_512, PRF_HMAC_SHA2_512 },
! 618: };
! 619:
! 620: /**
! 621: * ESP encryption algorithm mapping
! 622: */
! 623: static algo_map_t map_esp[] = {
! 624: { IKEV1_ESP_ENCR_DES_IV64, ENCR_DES_IV64 },
! 625: { IKEV1_ESP_ENCR_DES, ENCR_DES },
! 626: { IKEV1_ESP_ENCR_3DES, ENCR_3DES },
! 627: { IKEV1_ESP_ENCR_RC5, ENCR_RC5 },
! 628: { IKEV1_ESP_ENCR_IDEA, ENCR_IDEA },
! 629: { IKEV1_ESP_ENCR_CAST, ENCR_CAST },
! 630: { IKEV1_ESP_ENCR_BLOWFISH, ENCR_BLOWFISH },
! 631: { IKEV1_ESP_ENCR_3IDEA, ENCR_3IDEA },
! 632: { IKEV1_ESP_ENCR_DES_IV32, ENCR_DES_IV32 },
! 633: { IKEV1_ESP_ENCR_NULL, ENCR_NULL },
! 634: { IKEV1_ESP_ENCR_AES_CBC, ENCR_AES_CBC },
! 635: { IKEV1_ESP_ENCR_AES_CTR, ENCR_AES_CTR },
! 636: { IKEV1_ESP_ENCR_AES_CCM_8, ENCR_AES_CCM_ICV8 },
! 637: { IKEV1_ESP_ENCR_AES_CCM_12, ENCR_AES_CCM_ICV12 },
! 638: { IKEV1_ESP_ENCR_AES_CCM_16, ENCR_AES_CCM_ICV16 },
! 639: { IKEV1_ESP_ENCR_AES_GCM_8, ENCR_AES_GCM_ICV8 },
! 640: { IKEV1_ESP_ENCR_AES_GCM_12, ENCR_AES_GCM_ICV12 },
! 641: { IKEV1_ESP_ENCR_AES_GCM_16, ENCR_AES_GCM_ICV16 },
! 642: { IKEV1_ESP_ENCR_CAMELLIA, ENCR_CAMELLIA_CBC },
! 643: { IKEV1_ESP_ENCR_NULL_AUTH_AES_GMAC, ENCR_NULL_AUTH_AES_GMAC },
! 644: { IKEV1_ESP_ENCR_SERPENT, ENCR_SERPENT_CBC },
! 645: { IKEV1_ESP_ENCR_TWOFISH, ENCR_TWOFISH_CBC },
! 646: };
! 647:
! 648: /**
! 649: * AH authentication algorithm mapping
! 650: */
! 651: static algo_map_t map_ah[] = {
! 652: { IKEV1_AH_HMAC_MD5, AUTH_HMAC_MD5_96 },
! 653: { IKEV1_AH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
! 654: { IKEV1_AH_DES_MAC, AUTH_DES_MAC },
! 655: { IKEV1_AH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
! 656: { IKEV1_AH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
! 657: { IKEV1_AH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
! 658: { IKEV1_AH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
! 659: { IKEV1_AH_AES_128_GMAC, AUTH_AES_128_GMAC },
! 660: { IKEV1_AH_AES_192_GMAC, AUTH_AES_192_GMAC },
! 661: { IKEV1_AH_AES_256_GMAC, AUTH_AES_256_GMAC },
! 662: };
! 663:
! 664: /**
! 665: * ESP/AH authentication algorithm mapping
! 666: */
! 667: static algo_map_t map_auth[] = {
! 668: { IKEV1_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 },
! 669: { IKEV1_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
! 670: { IKEV1_AUTH_DES_MAC, AUTH_DES_MAC },
! 671: { IKEV1_AUTH_KPDK, AUTH_KPDK_MD5 },
! 672: { IKEV1_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
! 673: { IKEV1_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
! 674: { IKEV1_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
! 675: { IKEV1_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
! 676: { IKEV1_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC },
! 677: { IKEV1_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC },
! 678: { IKEV1_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
! 679: };
! 680:
! 681: /**
! 682: * Map an IKEv1 to an IKEv2 identifier
! 683: */
! 684: static uint16_t ikev2_from_ikev1(algo_map_t *map, int count, uint16_t def,
! 685: uint16_t value)
! 686: {
! 687: int i;
! 688:
! 689: for (i = 0; i < count; i++)
! 690: {
! 691: if (map[i].ikev1 == value)
! 692: {
! 693: return map[i].ikev2;
! 694: }
! 695: }
! 696: return def;
! 697: }
! 698:
! 699: /**
! 700: * Map an IKEv2 to an IKEv1 identifier
! 701: */
! 702: static uint16_t ikev1_from_ikev2(algo_map_t *map, int count, uint16_t value)
! 703: {
! 704: int i;
! 705:
! 706: for (i = 0; i < count; i++)
! 707: {
! 708: if (map[i].ikev2 == value)
! 709: {
! 710: return map[i].ikev1;
! 711: }
! 712: }
! 713: return 0;
! 714: }
! 715:
! 716: /**
! 717: * Get IKEv2 algorithm from IKEv1 identifier
! 718: */
! 719: static uint16_t get_alg_from_ikev1(transform_type_t type, uint16_t value)
! 720: {
! 721: switch (type)
! 722: {
! 723: case ENCRYPTION_ALGORITHM:
! 724: return ikev2_from_ikev1(map_encr, countof(map_encr),
! 725: ENCR_UNDEFINED, value);
! 726: case INTEGRITY_ALGORITHM:
! 727: return ikev2_from_ikev1(map_integ, countof(map_integ),
! 728: AUTH_UNDEFINED, value);
! 729: case PSEUDO_RANDOM_FUNCTION:
! 730: return ikev2_from_ikev1(map_prf, countof(map_prf),
! 731: PRF_UNDEFINED, value);
! 732: default:
! 733: return 0;
! 734: }
! 735: }
! 736:
! 737: /**
! 738: * Get IKEv1 algorithm from IKEv2 identifier
! 739: */
! 740: static uint16_t get_ikev1_from_alg(transform_type_t type, uint16_t value)
! 741: {
! 742: switch (type)
! 743: {
! 744: case ENCRYPTION_ALGORITHM:
! 745: return ikev1_from_ikev2(map_encr, countof(map_encr), value);
! 746: case INTEGRITY_ALGORITHM:
! 747: return ikev1_from_ikev2(map_integ, countof(map_integ), value);
! 748: case PSEUDO_RANDOM_FUNCTION:
! 749: return ikev1_from_ikev2(map_prf, countof(map_prf), value);
! 750: default:
! 751: return 0;
! 752: }
! 753: }
! 754:
! 755: /**
! 756: * Get IKEv2 algorithm from IKEv1 ESP/AH transform ID
! 757: */
! 758: static uint16_t get_alg_from_ikev1_transid(transform_type_t type,
! 759: uint16_t value)
! 760: {
! 761: switch (type)
! 762: {
! 763: case ENCRYPTION_ALGORITHM:
! 764: return ikev2_from_ikev1(map_esp, countof(map_esp),
! 765: ENCR_UNDEFINED, value);
! 766: case INTEGRITY_ALGORITHM:
! 767: return ikev2_from_ikev1(map_ah, countof(map_ah),
! 768: AUTH_UNDEFINED, value);
! 769: default:
! 770: return 0;
! 771: }
! 772: }
! 773:
! 774: /**
! 775: * Get IKEv1 ESP/AH transform ID from IKEv2 identifier
! 776: */
! 777: static uint16_t get_ikev1_transid_from_alg(transform_type_t type,
! 778: uint16_t value)
! 779: {
! 780: switch (type)
! 781: {
! 782: case ENCRYPTION_ALGORITHM:
! 783: return ikev1_from_ikev2(map_esp, countof(map_esp), value);
! 784: case INTEGRITY_ALGORITHM:
! 785: return ikev1_from_ikev2(map_ah, countof(map_ah), value);
! 786: default:
! 787: return 0;
! 788: }
! 789: }
! 790:
! 791: /**
! 792: * Get IKEv1 authentication algorithm from IKEv2 identifier
! 793: */
! 794: static uint16_t get_alg_from_ikev1_auth(uint16_t value)
! 795: {
! 796: return ikev2_from_ikev1(map_auth, countof(map_auth), AUTH_UNDEFINED, value);
! 797: }
! 798:
! 799: /**
! 800: * Get IKEv1 authentication algorithm from IKEv2 identifier
! 801: */
! 802: static uint16_t get_ikev1_auth_from_alg(uint16_t value)
! 803: {
! 804: return ikev1_from_ikev2(map_auth, countof(map_auth), value);
! 805: }
! 806:
! 807: /**
! 808: * Get IKEv1 authentication attribute from auth_method_t
! 809: */
! 810: static uint16_t get_ikev1_auth(auth_method_t method)
! 811: {
! 812: switch (method)
! 813: {
! 814: case AUTH_RSA:
! 815: return IKEV1_AUTH_RSA_SIG;
! 816: case AUTH_DSS:
! 817: return IKEV1_AUTH_DSS_SIG;
! 818: case AUTH_XAUTH_INIT_PSK:
! 819: return IKEV1_AUTH_XAUTH_INIT_PSK;
! 820: case AUTH_XAUTH_RESP_PSK:
! 821: return IKEV1_AUTH_XAUTH_RESP_PSK;
! 822: case AUTH_XAUTH_INIT_RSA:
! 823: return IKEV1_AUTH_XAUTH_INIT_RSA;
! 824: case AUTH_XAUTH_RESP_RSA:
! 825: return IKEV1_AUTH_XAUTH_RESP_RSA;
! 826: case AUTH_HYBRID_INIT_RSA:
! 827: return IKEV1_AUTH_HYBRID_INIT_RSA;
! 828: case AUTH_HYBRID_RESP_RSA:
! 829: return IKEV1_AUTH_HYBRID_RESP_RSA;
! 830: case AUTH_ECDSA_256:
! 831: return IKEV1_AUTH_ECDSA_256;
! 832: case AUTH_ECDSA_384:
! 833: return IKEV1_AUTH_ECDSA_384;
! 834: case AUTH_ECDSA_521:
! 835: return IKEV1_AUTH_ECDSA_521;
! 836: case AUTH_PSK:
! 837: default:
! 838: return IKEV1_AUTH_PSK;
! 839: }
! 840: }
! 841:
! 842: /**
! 843: * Get IKEv1 encapsulation mode
! 844: */
! 845: static uint16_t get_ikev1_mode(ipsec_mode_t mode, encap_t udp)
! 846: {
! 847: switch (mode)
! 848: {
! 849: case MODE_TUNNEL:
! 850: switch (udp)
! 851: {
! 852: case ENCAP_UDP:
! 853: return IKEV1_ENCAP_UDP_TUNNEL;
! 854: case ENCAP_UDP_DRAFT_00_03:
! 855: return IKEV1_ENCAP_UDP_TUNNEL_DRAFT_00_03;
! 856: default:
! 857: return IKEV1_ENCAP_TUNNEL;
! 858: }
! 859: case MODE_TRANSPORT:
! 860: switch (udp)
! 861: {
! 862: case ENCAP_UDP:
! 863: return IKEV1_ENCAP_UDP_TRANSPORT;
! 864: case ENCAP_UDP_DRAFT_00_03:
! 865: return IKEV1_ENCAP_UDP_TRANSPORT_DRAFT_00_03;
! 866: default:
! 867: return IKEV1_ENCAP_TRANSPORT;
! 868: }
! 869: default:
! 870: return IKEV1_ENCAP_TUNNEL;
! 871: }
! 872: }
! 873:
! 874: /**
! 875: * Add an IKE transform to a proposal for IKEv1
! 876: */
! 877: static void add_to_proposal_v1_ike(proposal_t *proposal,
! 878: transform_substructure_t *transform)
! 879: {
! 880: transform_attribute_type_t type;
! 881: transform_attribute_t *tattr;
! 882: enumerator_t *enumerator;
! 883: uint16_t value, key_length = 0;
! 884: uint16_t encr = ENCR_UNDEFINED;
! 885:
! 886: enumerator = transform->create_attribute_enumerator(transform);
! 887: while (enumerator->enumerate(enumerator, &tattr))
! 888: {
! 889: type = tattr->get_attribute_type(tattr);
! 890: value = tattr->get_value(tattr);
! 891: switch (type)
! 892: {
! 893: case TATTR_PH1_ENCRYPTION_ALGORITHM:
! 894: encr = get_alg_from_ikev1(ENCRYPTION_ALGORITHM, value);
! 895: break;
! 896: case TATTR_PH1_KEY_LENGTH:
! 897: key_length = value;
! 898: break;
! 899: case TATTR_PH1_HASH_ALGORITHM:
! 900: proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
! 901: get_alg_from_ikev1(INTEGRITY_ALGORITHM, value), 0);
! 902: proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
! 903: get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION, value), 0);
! 904: break;
! 905: case TATTR_PH1_GROUP:
! 906: proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
! 907: value, 0);
! 908: break;
! 909: default:
! 910: break;
! 911: }
! 912: }
! 913: enumerator->destroy(enumerator);
! 914:
! 915: if (encr != ENCR_UNDEFINED)
! 916: {
! 917: if (encr == ENCR_AES_CBC && !key_length)
! 918: { /* some implementations don't send a Key Length attribute for
! 919: * AES-128, early drafts of RFC 3602 allowed that */
! 920: key_length = 128;
! 921: }
! 922: proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, key_length);
! 923: }
! 924: }
! 925:
! 926: /**
! 927: * Add an ESP/AH transform to a proposal for IKEv1
! 928: */
! 929: static void add_to_proposal_v1(proposal_t *proposal,
! 930: transform_substructure_t *transform, protocol_id_t proto)
! 931: {
! 932: transform_attribute_type_t type;
! 933: transform_attribute_t *tattr;
! 934: enumerator_t *enumerator;
! 935: uint16_t encr, value, key_length = 0;
! 936: extended_sequence_numbers_t esn = NO_EXT_SEQ_NUMBERS;
! 937:
! 938: enumerator = transform->create_attribute_enumerator(transform);
! 939: while (enumerator->enumerate(enumerator, &tattr))
! 940: {
! 941: type = tattr->get_attribute_type(tattr);
! 942: value = tattr->get_value(tattr);
! 943: switch (type)
! 944: {
! 945: case TATTR_PH2_KEY_LENGTH:
! 946: key_length = value;
! 947: break;
! 948: case TATTR_PH2_AUTH_ALGORITHM:
! 949: proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
! 950: get_alg_from_ikev1_auth(value), 0);
! 951: break;
! 952: case TATTR_PH2_GROUP:
! 953: proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
! 954: value, 0);
! 955: break;
! 956: case TATTR_PH2_EXT_SEQ_NUMBER:
! 957: esn = EXT_SEQ_NUMBERS;
! 958: break;
! 959: default:
! 960: break;
! 961: }
! 962: }
! 963: enumerator->destroy(enumerator);
! 964:
! 965: proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
! 966: if (proto == PROTO_ESP)
! 967: {
! 968: encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
! 969: transform->get_transform_id(transform));
! 970: if (encr)
! 971: {
! 972: if (encr == ENCR_AES_CBC && !key_length)
! 973: { /* some implementations don't send a Key Length attribute for
! 974: * AES-128, early drafts of RFC 3602 allowed that for IKE, some
! 975: * also seem to do it for ESP */
! 976: key_length = 128;
! 977: }
! 978: proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
! 979: key_length);
! 980: }
! 981: }
! 982: }
! 983:
! 984: METHOD(proposal_substructure_t, get_proposals, void,
! 985: private_proposal_substructure_t *this, linked_list_t *proposals)
! 986: {
! 987: transform_substructure_t *transform;
! 988: enumerator_t *enumerator;
! 989: proposal_t *proposal = NULL;
! 990: uint64_t spi = 0;
! 991:
! 992: switch (this->spi.len)
! 993: {
! 994: case 4:
! 995: spi = *((uint32_t*)this->spi.ptr);
! 996: break;
! 997: case 8:
! 998: spi = *((uint64_t*)this->spi.ptr);
! 999: break;
! 1000: default:
! 1001: break;
! 1002: }
! 1003:
! 1004: enumerator = this->transforms->create_enumerator(this->transforms);
! 1005: while (enumerator->enumerate(enumerator, &transform))
! 1006: {
! 1007: if (this->type == PLV2_PROPOSAL_SUBSTRUCTURE)
! 1008: {
! 1009: if (!proposal)
! 1010: {
! 1011: proposal = proposal_create(this->protocol_id,
! 1012: this->proposal_number);
! 1013: proposal->set_spi(proposal, spi);
! 1014: proposals->insert_last(proposals, proposal);
! 1015: }
! 1016: add_to_proposal_v2(proposal, transform);
! 1017: }
! 1018: else
! 1019: {
! 1020: /* create a new proposal for each transform in IKEv1 */
! 1021: proposal = proposal_create_v1(
! 1022: this->protocol_id, this->proposal_number,
! 1023: transform->get_transform_type_or_number(transform));
! 1024: proposal->set_spi(proposal, spi);
! 1025: proposals->insert_last(proposals, proposal);
! 1026: switch (this->protocol_id)
! 1027: {
! 1028: case PROTO_IKE:
! 1029: add_to_proposal_v1_ike(proposal, transform);
! 1030: break;
! 1031: case PROTO_ESP:
! 1032: case PROTO_AH:
! 1033: add_to_proposal_v1(proposal, transform, this->protocol_id);
! 1034: break;
! 1035: default:
! 1036: break;
! 1037: }
! 1038: }
! 1039: }
! 1040: enumerator->destroy(enumerator);
! 1041: }
! 1042:
! 1043: METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
! 1044: private_proposal_substructure_t *this)
! 1045: {
! 1046: return this->transforms->create_enumerator(this->transforms);
! 1047: }
! 1048:
! 1049: /**
! 1050: * Get an attribute from any transform, 0 if not found
! 1051: */
! 1052: static uint64_t get_attr(private_proposal_substructure_t *this,
! 1053: transform_attribute_type_t type)
! 1054: {
! 1055: enumerator_t *transforms, *attributes;
! 1056: transform_substructure_t *transform;
! 1057: transform_attribute_t *attr;
! 1058:
! 1059: transforms = this->transforms->create_enumerator(this->transforms);
! 1060: while (transforms->enumerate(transforms, &transform))
! 1061: {
! 1062: attributes = transform->create_attribute_enumerator(transform);
! 1063: while (attributes->enumerate(attributes, &attr))
! 1064: {
! 1065: if (attr->get_attribute_type(attr) == type)
! 1066: {
! 1067: attributes->destroy(attributes);
! 1068: transforms->destroy(transforms);
! 1069: return attr->get_value(attr);
! 1070: }
! 1071: }
! 1072: attributes->destroy(attributes);
! 1073: }
! 1074: transforms->destroy(transforms);
! 1075: return 0;
! 1076: }
! 1077:
! 1078: /**
! 1079: * Look up a lifetime duration of a given kind in all transforms
! 1080: */
! 1081: static uint64_t get_life_duration(private_proposal_substructure_t *this,
! 1082: uint8_t number, transform_attribute_type_t type_attr,
! 1083: ikev1_life_type_t type, transform_attribute_type_t dur_attr)
! 1084: {
! 1085: enumerator_t *transforms, *attributes;
! 1086: transform_substructure_t *transform;
! 1087: transform_attribute_t *attr;
! 1088:
! 1089: transforms = this->transforms->create_enumerator(this->transforms);
! 1090: while (transforms->enumerate(transforms, &transform))
! 1091: {
! 1092: if (transform->get_transform_type_or_number(transform) != number)
! 1093: {
! 1094: continue;
! 1095: }
! 1096: attributes = transform->create_attribute_enumerator(transform);
! 1097: while (attributes->enumerate(attributes, &attr))
! 1098: {
! 1099: if (attr->get_attribute_type(attr) == type_attr &&
! 1100: attr->get_value(attr) == type)
! 1101: { /* got type attribute, look for duration following next */
! 1102: while (attributes->enumerate(attributes, &attr))
! 1103: {
! 1104: if (attr->get_attribute_type(attr) == dur_attr)
! 1105: {
! 1106: attributes->destroy(attributes);
! 1107: transforms->destroy(transforms);
! 1108: return attr->get_value(attr);
! 1109: }
! 1110: }
! 1111: }
! 1112: }
! 1113: attributes->destroy(attributes);
! 1114: }
! 1115: transforms->destroy(transforms);
! 1116: return 0;
! 1117: }
! 1118:
! 1119: METHOD(proposal_substructure_t, get_lifetime, uint32_t,
! 1120: private_proposal_substructure_t *this, uint8_t transform)
! 1121: {
! 1122: uint32_t duration;
! 1123:
! 1124: switch (this->protocol_id)
! 1125: {
! 1126: case PROTO_IKE:
! 1127: return get_life_duration(this, transform, TATTR_PH1_LIFE_TYPE,
! 1128: IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
! 1129: case PROTO_ESP:
! 1130: case PROTO_AH:
! 1131: duration = get_life_duration(this, transform,
! 1132: TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS,
! 1133: TATTR_PH2_SA_LIFE_DURATION);
! 1134: if (!duration)
! 1135: { /* default to 8 hours, RFC 2407 */
! 1136: return 28800;
! 1137: }
! 1138: return duration;
! 1139: default:
! 1140: return 0;
! 1141: }
! 1142: }
! 1143:
! 1144: METHOD(proposal_substructure_t, get_lifebytes, uint64_t,
! 1145: private_proposal_substructure_t *this, uint8_t transform)
! 1146: {
! 1147: switch (this->protocol_id)
! 1148: {
! 1149: case PROTO_ESP:
! 1150: case PROTO_AH:
! 1151: return 1000 * get_life_duration(this, transform,
! 1152: TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES,
! 1153: TATTR_PH2_SA_LIFE_DURATION);
! 1154: case PROTO_IKE:
! 1155: default:
! 1156: return 0;
! 1157: }
! 1158: }
! 1159:
! 1160: METHOD(proposal_substructure_t, get_auth_method, auth_method_t,
! 1161: private_proposal_substructure_t *this)
! 1162: {
! 1163: switch (get_attr(this, TATTR_PH1_AUTH_METHOD))
! 1164: {
! 1165: case IKEV1_AUTH_PSK:
! 1166: return AUTH_PSK;
! 1167: case IKEV1_AUTH_RSA_SIG:
! 1168: return AUTH_RSA;
! 1169: case IKEV1_AUTH_DSS_SIG:
! 1170: return AUTH_DSS;
! 1171: case IKEV1_AUTH_XAUTH_INIT_PSK:
! 1172: return AUTH_XAUTH_INIT_PSK;
! 1173: case IKEV1_AUTH_XAUTH_RESP_PSK:
! 1174: return AUTH_XAUTH_RESP_PSK;
! 1175: case IKEV1_AUTH_XAUTH_INIT_RSA:
! 1176: return AUTH_XAUTH_INIT_RSA;
! 1177: case IKEV1_AUTH_XAUTH_RESP_RSA:
! 1178: return AUTH_XAUTH_RESP_RSA;
! 1179: case IKEV1_AUTH_HYBRID_INIT_RSA:
! 1180: return AUTH_HYBRID_INIT_RSA;
! 1181: case IKEV1_AUTH_HYBRID_RESP_RSA:
! 1182: return AUTH_HYBRID_RESP_RSA;
! 1183: case IKEV1_AUTH_ECDSA_256:
! 1184: return AUTH_ECDSA_256;
! 1185: case IKEV1_AUTH_ECDSA_384:
! 1186: return AUTH_ECDSA_384;
! 1187: case IKEV1_AUTH_ECDSA_521:
! 1188: return AUTH_ECDSA_521;
! 1189: default:
! 1190: return AUTH_NONE;
! 1191: }
! 1192: }
! 1193:
! 1194: METHOD(proposal_substructure_t, get_encap_mode, ipsec_mode_t,
! 1195: private_proposal_substructure_t *this, bool *udp)
! 1196: {
! 1197: *udp = FALSE;
! 1198: switch (get_attr(this, TATTR_PH2_ENCAP_MODE))
! 1199: {
! 1200: case IKEV1_ENCAP_TRANSPORT:
! 1201: return MODE_TRANSPORT;
! 1202: case IKEV1_ENCAP_TUNNEL:
! 1203: return MODE_TUNNEL;
! 1204: case IKEV1_ENCAP_UDP_TRANSPORT:
! 1205: case IKEV1_ENCAP_UDP_TRANSPORT_DRAFT_00_03:
! 1206: *udp = TRUE;
! 1207: return MODE_TRANSPORT;
! 1208: case IKEV1_ENCAP_UDP_TUNNEL:
! 1209: case IKEV1_ENCAP_UDP_TUNNEL_DRAFT_00_03:
! 1210: *udp = TRUE;
! 1211: return MODE_TUNNEL;
! 1212: default:
! 1213: /* default to TUNNEL, RFC 2407 says implementation specific */
! 1214: return MODE_TUNNEL;
! 1215: }
! 1216: }
! 1217:
! 1218: METHOD2(payload_t, proposal_substructure_t, destroy, void,
! 1219: private_proposal_substructure_t *this)
! 1220: {
! 1221: this->transforms->destroy_offset(this->transforms,
! 1222: offsetof(payload_t, destroy));
! 1223: chunk_free(&this->spi);
! 1224: free(this);
! 1225: }
! 1226:
! 1227: /*
! 1228: * Described in header.
! 1229: */
! 1230: proposal_substructure_t *proposal_substructure_create(payload_type_t type)
! 1231: {
! 1232: private_proposal_substructure_t *this;
! 1233:
! 1234: INIT(this,
! 1235: .public = {
! 1236: .payload_interface = {
! 1237: .verify = _verify,
! 1238: .get_encoding_rules = _get_encoding_rules,
! 1239: .get_header_length = _get_header_length,
! 1240: .get_length = _get_length,
! 1241: .get_next_type = _get_next_type,
! 1242: .set_next_type = _set_next_type,
! 1243: .get_type = _get_type,
! 1244: .destroy = _destroy,
! 1245: },
! 1246: .set_proposal_number = _set_proposal_number,
! 1247: .get_proposal_number = _get_proposal_number,
! 1248: .set_protocol_id = _set_protocol_id,
! 1249: .get_protocol_id = _get_protocol_id,
! 1250: .set_is_last_proposal = _set_is_last_proposal,
! 1251: .get_proposals = _get_proposals,
! 1252: .create_substructure_enumerator = _create_substructure_enumerator,
! 1253: .set_spi = _set_spi,
! 1254: .get_spi = _get_spi,
! 1255: .get_cpi = _get_cpi,
! 1256: .get_lifetime = _get_lifetime,
! 1257: .get_lifebytes = _get_lifebytes,
! 1258: .get_auth_method = _get_auth_method,
! 1259: .get_encap_mode = _get_encap_mode,
! 1260: .destroy = _destroy,
! 1261: },
! 1262: .next_payload = PL_NONE,
! 1263: .transforms = linked_list_create(),
! 1264: .type = type,
! 1265: );
! 1266: compute_length(this);
! 1267:
! 1268: return &this->public;
! 1269: }
! 1270:
! 1271: /**
! 1272: * Add an IKEv1 IKE proposal to the substructure
! 1273: */
! 1274: static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
! 1275: proposal_t *proposal, uint32_t lifetime,
! 1276: auth_method_t method, int number)
! 1277: {
! 1278: transform_substructure_t *transform;
! 1279: uint16_t alg, key_size;
! 1280: enumerator_t *enumerator;
! 1281:
! 1282: transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
! 1283: number, IKEV1_TRANSID_KEY_IKE);
! 1284:
! 1285: enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
! 1286: while (enumerator->enumerate(enumerator, &alg, &key_size))
! 1287: {
! 1288: alg = get_ikev1_from_alg(ENCRYPTION_ALGORITHM, alg);
! 1289: if (alg)
! 1290: {
! 1291: transform->add_transform_attribute(transform,
! 1292: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1293: TATTR_PH1_ENCRYPTION_ALGORITHM, alg));
! 1294: if (key_size)
! 1295: {
! 1296: transform->add_transform_attribute(transform,
! 1297: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1298: TATTR_PH1_KEY_LENGTH, key_size));
! 1299: }
! 1300: break;
! 1301: }
! 1302: }
! 1303: enumerator->destroy(enumerator);
! 1304:
! 1305: /* encode the integrity algorithm as hash and assume use the same PRF */
! 1306: enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
! 1307: while (enumerator->enumerate(enumerator, &alg, &key_size))
! 1308: {
! 1309: alg = get_ikev1_from_alg(INTEGRITY_ALGORITHM, alg);
! 1310: if (alg)
! 1311: {
! 1312: transform->add_transform_attribute(transform,
! 1313: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1314: TATTR_PH1_HASH_ALGORITHM, alg));
! 1315: break;
! 1316: }
! 1317: }
! 1318: enumerator->destroy(enumerator);
! 1319:
! 1320: enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
! 1321: if (enumerator->enumerate(enumerator, &alg, &key_size))
! 1322: {
! 1323: transform->add_transform_attribute(transform,
! 1324: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1325: TATTR_PH1_GROUP, alg));
! 1326: }
! 1327: enumerator->destroy(enumerator);
! 1328:
! 1329: transform->add_transform_attribute(transform,
! 1330: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1331: TATTR_PH1_AUTH_METHOD, get_ikev1_auth(method)));
! 1332: transform->add_transform_attribute(transform,
! 1333: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1334: TATTR_PH1_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
! 1335: transform->add_transform_attribute(transform,
! 1336: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1337: TATTR_PH1_LIFE_DURATION, lifetime));
! 1338:
! 1339: add_transform_substructure(this, transform);
! 1340: }
! 1341:
! 1342: /**
! 1343: * Add an IKEv1 ESP/AH proposal to the substructure
! 1344: */
! 1345: static void set_from_proposal_v1(private_proposal_substructure_t *this,
! 1346: proposal_t *proposal, uint32_t lifetime, uint64_t lifebytes,
! 1347: ipsec_mode_t mode, encap_t udp, int number)
! 1348: {
! 1349: transform_substructure_t *transform = NULL;
! 1350: uint16_t alg, transid, key_size;
! 1351: enumerator_t *enumerator;
! 1352:
! 1353: enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
! 1354: if (enumerator->enumerate(enumerator, &alg, &key_size))
! 1355: {
! 1356: transid = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg);
! 1357: if (transid)
! 1358: {
! 1359: transform = transform_substructure_create_type(
! 1360: PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
! 1361: if (key_size)
! 1362: {
! 1363: transform->add_transform_attribute(transform,
! 1364: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1365: TATTR_PH2_KEY_LENGTH, key_size));
! 1366: }
! 1367: }
! 1368: }
! 1369: enumerator->destroy(enumerator);
! 1370:
! 1371: enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
! 1372: if (enumerator->enumerate(enumerator, &alg, &key_size))
! 1373: {
! 1374: transid = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg);
! 1375: alg = get_ikev1_auth_from_alg(alg);
! 1376: if (alg)
! 1377: {
! 1378: if (!transform && transid)
! 1379: {
! 1380: transform = transform_substructure_create_type(
! 1381: PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
! 1382: }
! 1383: if (transform)
! 1384: {
! 1385: transform->add_transform_attribute(transform,
! 1386: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1387: TATTR_PH2_AUTH_ALGORITHM, alg));
! 1388: }
! 1389: }
! 1390: }
! 1391: enumerator->destroy(enumerator);
! 1392:
! 1393: if (!transform)
! 1394: {
! 1395: return;
! 1396: }
! 1397:
! 1398: enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
! 1399: if (enumerator->enumerate(enumerator, &alg, &key_size))
! 1400: {
! 1401: transform->add_transform_attribute(transform,
! 1402: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1403: TATTR_PH2_GROUP, alg));
! 1404: }
! 1405: enumerator->destroy(enumerator);
! 1406:
! 1407: transform->add_transform_attribute(transform,
! 1408: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1409: TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
! 1410: if (lifetime)
! 1411: {
! 1412: transform->add_transform_attribute(transform,
! 1413: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1414: TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
! 1415: transform->add_transform_attribute(transform,
! 1416: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1417: TATTR_PH2_SA_LIFE_DURATION, lifetime));
! 1418: }
! 1419: if (lifebytes)
! 1420: {
! 1421: transform->add_transform_attribute(transform,
! 1422: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1423: TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
! 1424: transform->add_transform_attribute(transform,
! 1425: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1426: TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
! 1427: }
! 1428:
! 1429: enumerator = proposal->create_enumerator(proposal,
! 1430: EXTENDED_SEQUENCE_NUMBERS);
! 1431: while (enumerator->enumerate(enumerator, &alg, NULL))
! 1432: {
! 1433: if (alg == EXT_SEQ_NUMBERS)
! 1434: {
! 1435: transform->add_transform_attribute(transform,
! 1436: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1437: TATTR_PH2_EXT_SEQ_NUMBER, alg));
! 1438: }
! 1439: }
! 1440: enumerator->destroy(enumerator);
! 1441: add_transform_substructure(this, transform);
! 1442: }
! 1443:
! 1444: /**
! 1445: * Add an IKEv2 proposal to the substructure
! 1446: */
! 1447: static void set_from_proposal_v2(private_proposal_substructure_t *this,
! 1448: proposal_t *proposal)
! 1449: {
! 1450: transform_substructure_t *transform;
! 1451: uint16_t alg, key_size;
! 1452: enumerator_t *enumerator;
! 1453:
! 1454: /* encryption algorithm is only available in ESP */
! 1455: enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
! 1456: while (enumerator->enumerate(enumerator, &alg, &key_size))
! 1457: {
! 1458: transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
! 1459: ENCRYPTION_ALGORITHM, alg);
! 1460: if (key_size)
! 1461: {
! 1462: transform->add_transform_attribute(transform,
! 1463: transform_attribute_create_value(PLV2_TRANSFORM_ATTRIBUTE,
! 1464: TATTR_IKEV2_KEY_LENGTH, key_size));
! 1465: }
! 1466: add_transform_substructure(this, transform);
! 1467: }
! 1468: enumerator->destroy(enumerator);
! 1469:
! 1470: /* integrity algorithms */
! 1471: enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
! 1472: while (enumerator->enumerate(enumerator, &alg, &key_size))
! 1473: {
! 1474: transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
! 1475: INTEGRITY_ALGORITHM, alg);
! 1476: add_transform_substructure(this, transform);
! 1477: }
! 1478: enumerator->destroy(enumerator);
! 1479:
! 1480: /* prf algorithms */
! 1481: enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
! 1482: while (enumerator->enumerate(enumerator, &alg, &key_size))
! 1483: {
! 1484: transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
! 1485: PSEUDO_RANDOM_FUNCTION, alg);
! 1486: add_transform_substructure(this, transform);
! 1487: }
! 1488: enumerator->destroy(enumerator);
! 1489:
! 1490: /* dh groups */
! 1491: enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
! 1492: while (enumerator->enumerate(enumerator, &alg, NULL))
! 1493: {
! 1494: transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
! 1495: DIFFIE_HELLMAN_GROUP, alg);
! 1496: add_transform_substructure(this, transform);
! 1497: }
! 1498: enumerator->destroy(enumerator);
! 1499:
! 1500: /* extended sequence numbers */
! 1501: enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
! 1502: while (enumerator->enumerate(enumerator, &alg, NULL))
! 1503: {
! 1504: transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
! 1505: EXTENDED_SEQUENCE_NUMBERS, alg);
! 1506: add_transform_substructure(this, transform);
! 1507: }
! 1508: enumerator->destroy(enumerator);
! 1509: }
! 1510:
! 1511: /**
! 1512: * Set SPI and other data from proposal, compute length
! 1513: */
! 1514: static void set_data(private_proposal_substructure_t *this, proposal_t *proposal)
! 1515: {
! 1516: uint64_t spi64;
! 1517: uint32_t spi32;
! 1518:
! 1519: /* add SPI, if necessary */
! 1520: switch (proposal->get_protocol(proposal))
! 1521: {
! 1522: case PROTO_AH:
! 1523: case PROTO_ESP:
! 1524: spi32 = proposal->get_spi(proposal);
! 1525: this->spi = chunk_clone(chunk_from_thing(spi32));
! 1526: this->spi_size = this->spi.len;
! 1527: break;
! 1528: case PROTO_IKE:
! 1529: spi64 = proposal->get_spi(proposal);
! 1530: if (spi64)
! 1531: { /* IKE only uses SPIS when rekeying, but on initial setup */
! 1532: this->spi = chunk_clone(chunk_from_thing(spi64));
! 1533: this->spi_size = this->spi.len;
! 1534: }
! 1535: break;
! 1536: default:
! 1537: break;
! 1538: }
! 1539: /* default to 1 if no number is set (mainly for IKEv1, for IKEv2 the numbers
! 1540: * are explicitly set when proposals are added to the SA payload) */
! 1541: this->proposal_number = proposal->get_number(proposal) ?: 1;
! 1542: this->protocol_id = proposal->get_protocol(proposal);
! 1543: compute_length(this);
! 1544: }
! 1545:
! 1546: /*
! 1547: * Described in header.
! 1548: */
! 1549: proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
! 1550: proposal_t *proposal)
! 1551: {
! 1552: private_proposal_substructure_t *this;
! 1553:
! 1554: this = (private_proposal_substructure_t*)
! 1555: proposal_substructure_create(PLV2_PROPOSAL_SUBSTRUCTURE);
! 1556: set_from_proposal_v2(this, proposal);
! 1557: set_data(this, proposal);
! 1558:
! 1559: return &this->public;
! 1560: }
! 1561:
! 1562: /**
! 1563: * Creates an IKEv1 proposal_substructure_t from a proposal_t.
! 1564: */
! 1565: static proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
! 1566: proposal_t *proposal, uint32_t lifetime, uint64_t lifebytes,
! 1567: auth_method_t auth, ipsec_mode_t mode, encap_t udp, uint8_t number)
! 1568: {
! 1569: private_proposal_substructure_t *this;
! 1570:
! 1571: this = (private_proposal_substructure_t*)
! 1572: proposal_substructure_create(PLV1_PROPOSAL_SUBSTRUCTURE);
! 1573: switch (proposal->get_protocol(proposal))
! 1574: {
! 1575: case PROTO_IKE:
! 1576: set_from_proposal_v1_ike(this, proposal, lifetime, auth, number);
! 1577: break;
! 1578: case PROTO_ESP:
! 1579: case PROTO_AH:
! 1580: set_from_proposal_v1(this, proposal, lifetime,
! 1581: lifebytes, mode, udp, number);
! 1582: break;
! 1583: default:
! 1584: break;
! 1585: }
! 1586: set_data(this, proposal);
! 1587:
! 1588: return &this->public;
! 1589: }
! 1590:
! 1591: /**
! 1592: * See header.
! 1593: */
! 1594: proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
! 1595: linked_list_t *proposals, uint32_t lifetime, uint64_t lifebytes,
! 1596: auth_method_t auth, ipsec_mode_t mode, encap_t udp)
! 1597: {
! 1598: private_proposal_substructure_t *this = NULL;
! 1599: enumerator_t *enumerator;
! 1600: proposal_t *proposal;
! 1601: int number = 1;
! 1602:
! 1603: enumerator = proposals->create_enumerator(proposals);
! 1604: while (enumerator->enumerate(enumerator, &proposal))
! 1605: {
! 1606: if (!this)
! 1607: { /* as responder the transform number is set and we only have a
! 1608: * single proposal, start with 1 otherwise */
! 1609: this = (private_proposal_substructure_t*)
! 1610: proposal_substructure_create_from_proposal_v1(
! 1611: proposal, lifetime, lifebytes, auth, mode, udp,
! 1612: proposal->get_transform_number(proposal) ?: number);
! 1613: }
! 1614: else
! 1615: {
! 1616: switch (proposal->get_protocol(proposal))
! 1617: {
! 1618: case PROTO_IKE:
! 1619: set_from_proposal_v1_ike(this, proposal, lifetime,
! 1620: auth, ++number);
! 1621: break;
! 1622: case PROTO_ESP:
! 1623: case PROTO_AH:
! 1624: set_from_proposal_v1(this, proposal, lifetime,
! 1625: lifebytes, mode, udp, ++number);
! 1626: break;
! 1627: default:
! 1628: break;
! 1629: }
! 1630: }
! 1631: }
! 1632: enumerator->destroy(enumerator);
! 1633:
! 1634: return &this->public;
! 1635: }
! 1636:
! 1637: /**
! 1638: * See header.
! 1639: */
! 1640: proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
! 1641: uint32_t lifetime, uint64_t lifebytes, uint16_t cpi,
! 1642: ipsec_mode_t mode, encap_t udp, uint8_t proposal_number)
! 1643: {
! 1644: private_proposal_substructure_t *this;
! 1645: transform_substructure_t *transform;
! 1646:
! 1647:
! 1648: this = (private_proposal_substructure_t*)
! 1649: proposal_substructure_create(PLV1_PROPOSAL_SUBSTRUCTURE);
! 1650:
! 1651: /* we currently support DEFLATE only */
! 1652: transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
! 1653: 1, IKEV1_IPCOMP_DEFLATE);
! 1654:
! 1655: transform->add_transform_attribute(transform,
! 1656: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1657: TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
! 1658: if (lifetime)
! 1659: {
! 1660: transform->add_transform_attribute(transform,
! 1661: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1662: TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
! 1663: transform->add_transform_attribute(transform,
! 1664: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1665: TATTR_PH2_SA_LIFE_DURATION, lifetime));
! 1666: }
! 1667: if (lifebytes)
! 1668: {
! 1669: transform->add_transform_attribute(transform,
! 1670: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1671: TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
! 1672: transform->add_transform_attribute(transform,
! 1673: transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
! 1674: TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
! 1675: }
! 1676:
! 1677: add_transform_substructure(this, transform);
! 1678:
! 1679: this->spi = chunk_clone(chunk_from_thing(cpi));
! 1680: this->spi_size = this->spi.len;
! 1681: this->protocol_id = PROTO_IPCOMP;
! 1682: this->proposal_number = proposal_number;
! 1683:
! 1684: compute_length(this);
! 1685:
! 1686: return &this->public;
! 1687: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>