Return to proposal.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / crypto / proposal |
1.1 misho 1: /* 2: * Copyright (C) 2008-2020 Tobias Brunner 3: * Copyright (C) 2006-2010 Martin Willi 4: * Copyright (C) 2013-2015 Andreas Steffen 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 <string.h> 19: 20: #include "proposal.h" 21: 22: #include <collections/array.h> 23: #include <utils/identification.h> 24: 25: #include <crypto/transform.h> 26: #include <crypto/prfs/prf.h> 27: #include <crypto/crypters/crypter.h> 28: #include <crypto/signers/signer.h> 29: 30: ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP, 31: "PROTO_NONE", 32: "IKE", 33: "AH", 34: "ESP", 35: "IPCOMP", 36: ); 37: 38: typedef struct private_proposal_t private_proposal_t; 39: 40: /** 41: * Private data of an proposal_t object 42: */ 43: struct private_proposal_t { 44: 45: /** 46: * Public part 47: */ 48: proposal_t public; 49: 50: /** 51: * protocol (ESP or AH) 52: */ 53: protocol_id_t protocol; 54: 55: /** 56: * Priority ordered list of transforms, as entry_t 57: */ 58: array_t *transforms; 59: 60: /** 61: * Types of transforms contained, as transform_type_t 62: */ 63: array_t *types; 64: 65: /** 66: * senders SPI 67: */ 68: uint64_t spi; 69: 70: /** 71: * Proposal number 72: */ 73: uint8_t number; 74: 75: /** 76: * Transform number (IKEv1 only) 77: */ 78: uint8_t transform_number; 79: }; 80: 81: /** 82: * This is a hack to not change the previous order when printing proposals 83: */ 84: static transform_type_t type_for_sort(const void *type) 85: { 86: const transform_type_t *t = type; 87: 88: switch (*t) 89: { 90: case PSEUDO_RANDOM_FUNCTION: 91: return INTEGRITY_ALGORITHM; 92: case INTEGRITY_ALGORITHM: 93: return PSEUDO_RANDOM_FUNCTION; 94: default: 95: return *t; 96: } 97: } 98: 99: /** 100: * Sort transform types 101: */ 102: static int type_sort(const void *a, const void *b, void *user) 103: { 104: transform_type_t ta = type_for_sort(a), tb = type_for_sort(b); 105: return ta - tb; 106: } 107: 108: /** 109: * Find a transform type 110: */ 111: static int type_find(const void *a, const void *b) 112: { 113: return type_sort(a, b, NULL); 114: } 115: 116: /** 117: * Check if the given transform type is already in the set 118: */ 119: static bool contains_type(array_t *types, transform_type_t type) 120: { 121: return array_bsearch(types, &type, type_find, NULL) != -1; 122: } 123: 124: /** 125: * Add the given transform type to the set 126: */ 127: static void add_type(array_t *types, transform_type_t type) 128: { 129: if (!contains_type(types, type)) 130: { 131: array_insert(types, ARRAY_TAIL, &type); 132: array_sort(types, type_sort, NULL); 133: } 134: } 135: 136: /** 137: * Merge two sets of transform types into a new array 138: */ 139: static array_t *merge_types(private_proposal_t *this, private_proposal_t *other) 140: { 141: array_t *types; 142: transform_type_t type; 143: int i, count; 144: 145: count = max(array_count(this->types), array_count(other->types)); 146: types = array_create(sizeof(transform_type_t), count); 147: 148: for (i = 0; i < count; i++) 149: { 150: if (array_get(this->types, i, &type)) 151: { 152: add_type(types, type); 153: } 154: if (array_get(other->types, i, &type)) 155: { 156: add_type(types, type); 157: } 158: } 159: return types; 160: } 161: 162: /** 163: * Remove the given transform type from the set 164: */ 165: static void remove_type(private_proposal_t *this, transform_type_t type) 166: { 167: int i; 168: 169: i = array_bsearch(this->types, &type, type_find, NULL); 170: if (i >= 0) 171: { 172: array_remove(this->types, i, NULL); 173: } 174: } 175: 176: /** 177: * Struct used to store different kinds of algorithms. 178: */ 179: typedef struct { 180: /** Type of the transform */ 181: transform_type_t type; 182: /** algorithm identifier */ 183: uint16_t alg; 184: /** key size in bits, or zero if not needed */ 185: uint16_t key_size; 186: } entry_t; 187: 188: METHOD(proposal_t, add_algorithm, void, 189: private_proposal_t *this, transform_type_t type, 190: uint16_t alg, uint16_t key_size) 191: { 192: entry_t entry = { 193: .type = type, 194: .alg = alg, 195: .key_size = key_size, 196: }; 197: 198: array_insert(this->transforms, ARRAY_TAIL, &entry); 199: add_type(this->types, type); 200: } 201: 202: CALLBACK(alg_filter, bool, 203: uintptr_t type, enumerator_t *orig, va_list args) 204: { 205: entry_t *entry; 206: uint16_t *alg, *key_size; 207: 208: VA_ARGS_VGET(args, alg, key_size); 209: 210: while (orig->enumerate(orig, &entry)) 211: { 212: if (entry->type != type) 213: { 214: continue; 215: } 216: if (alg) 217: { 218: *alg = entry->alg; 219: } 220: if (key_size) 221: { 222: *key_size = entry->key_size; 223: } 224: return TRUE; 225: } 226: return FALSE; 227: } 228: 229: METHOD(proposal_t, create_enumerator, enumerator_t*, 230: private_proposal_t *this, transform_type_t type) 231: { 232: return enumerator_create_filter( 233: array_create_enumerator(this->transforms), 234: alg_filter, (void*)(uintptr_t)type, NULL); 235: } 236: 237: METHOD(proposal_t, get_algorithm, bool, 238: private_proposal_t *this, transform_type_t type, 239: uint16_t *alg, uint16_t *key_size) 240: { 241: enumerator_t *enumerator; 242: bool found = FALSE; 243: 244: enumerator = create_enumerator(this, type); 245: if (enumerator->enumerate(enumerator, alg, key_size)) 246: { 247: found = TRUE; 248: } 249: enumerator->destroy(enumerator); 250: 251: return found; 252: } 253: 254: METHOD(proposal_t, has_dh_group, bool, 255: private_proposal_t *this, diffie_hellman_group_t group) 256: { 257: bool found = FALSE, any = FALSE; 258: enumerator_t *enumerator; 259: uint16_t current; 260: 261: enumerator = create_enumerator(this, DIFFIE_HELLMAN_GROUP); 262: while (enumerator->enumerate(enumerator, ¤t, NULL)) 263: { 264: any = TRUE; 265: if (current == group) 266: { 267: found = TRUE; 268: break; 269: } 270: } 271: enumerator->destroy(enumerator); 272: 273: if (!any && group == MODP_NONE) 274: { 275: found = TRUE; 276: } 277: return found; 278: } 279: 280: METHOD(proposal_t, promote_dh_group, bool, 281: private_proposal_t *this, diffie_hellman_group_t group) 282: { 283: enumerator_t *enumerator; 284: entry_t *entry; 285: bool found = FALSE; 286: 287: enumerator = array_create_enumerator(this->transforms); 288: while (enumerator->enumerate(enumerator, &entry)) 289: { 290: if (entry->type == DIFFIE_HELLMAN_GROUP && 291: entry->alg == group) 292: { 293: array_remove_at(this->transforms, enumerator); 294: found = TRUE; 295: } 296: } 297: enumerator->destroy(enumerator); 298: 299: if (found) 300: { 301: entry_t entry = { 302: .type = DIFFIE_HELLMAN_GROUP, 303: .alg = group, 304: }; 305: array_insert(this->transforms, ARRAY_HEAD, &entry); 306: } 307: return found; 308: } 309: 310: /** 311: * Select a matching proposal from this and other. 312: */ 313: static bool select_algo(private_proposal_t *this, proposal_t *other, 314: transform_type_t type, proposal_selection_flag_t flags, 315: bool log, uint16_t *alg, uint16_t *ks) 316: { 317: enumerator_t *e1, *e2; 318: uint16_t alg1, alg2, ks1, ks2; 319: bool found = FALSE, optional = FALSE; 320: 321: if (type == DIFFIE_HELLMAN_GROUP) 322: { 323: optional = this->protocol == PROTO_ESP || this->protocol == PROTO_AH; 324: } 325: 326: e1 = create_enumerator(this, type); 327: e2 = other->create_enumerator(other, type); 328: if (!e1->enumerate(e1, &alg1, NULL)) 329: { 330: if (!e2->enumerate(e2, &alg2, NULL)) 331: { 332: found = TRUE; 333: } 334: else if (optional) 335: { 336: do 337: { /* if NONE is proposed, we accept the proposal */ 338: found = !alg2; 339: } 340: while (!found && e2->enumerate(e2, &alg2, NULL)); 341: } 342: } 343: else if (!e2->enumerate(e2, NULL, NULL)) 344: { 345: if (optional) 346: { 347: do 348: { /* if NONE is proposed, we accept the proposal */ 349: found = !alg1; 350: } 351: while (!found && e1->enumerate(e1, &alg1, NULL)); 352: } 353: } 354: 355: e1->destroy(e1); 356: e1 = create_enumerator(this, type); 357: /* compare algs, order of algs in "first" is preferred */ 358: while (!found && e1->enumerate(e1, &alg1, &ks1)) 359: { 360: e2->destroy(e2); 361: e2 = other->create_enumerator(other, type); 362: while (e2->enumerate(e2, &alg2, &ks2)) 363: { 364: if (alg1 == alg2 && ks1 == ks2) 365: { 366: if ((flags & PROPOSAL_SKIP_PRIVATE) && alg1 >= 1024) 367: { 368: if (log) 369: { 370: DBG1(DBG_CFG, "an algorithm from private space would " 371: "match, but peer implementation is unknown, " 372: "skipped"); 373: } 374: continue; 375: } 376: *alg = alg1; 377: *ks = ks1; 378: found = TRUE; 379: break; 380: } 381: } 382: } 383: e1->destroy(e1); 384: e2->destroy(e2); 385: return found; 386: } 387: 388: /** 389: * Select algorithms from the given proposals, if selected is given, the result 390: * is stored there and errors are logged. 391: */ 392: static bool select_algos(private_proposal_t *this, proposal_t *other, 393: proposal_t *selected, proposal_selection_flag_t flags) 394: { 395: transform_type_t type; 396: array_t *types; 397: bool skip_integrity = FALSE; 398: int i; 399: 400: types = merge_types(this, (private_proposal_t*)other); 401: for (i = 0; i < array_count(types); i++) 402: { 403: uint16_t alg = 0, ks = 0; 404: 405: array_get(types, i, &type); 406: if (type == INTEGRITY_ALGORITHM && skip_integrity) 407: { 408: continue; 409: } 410: if (type == DIFFIE_HELLMAN_GROUP && (flags & PROPOSAL_SKIP_DH)) 411: { 412: continue; 413: } 414: if (select_algo(this, other, type, flags, selected != NULL, &alg, &ks)) 415: { 416: if (alg == 0 && type != EXTENDED_SEQUENCE_NUMBERS) 417: { /* 0 is "valid" for extended sequence numbers, for other 418: * transforms it either means NONE or is reserved */ 419: continue; 420: } 421: if (selected) 422: { 423: selected->add_algorithm(selected, type, alg, ks); 424: } 425: if (type == ENCRYPTION_ALGORITHM && 426: encryption_algorithm_is_aead(alg)) 427: { 428: /* no integrity algorithm required, we have an AEAD */ 429: skip_integrity = TRUE; 430: } 431: } 432: else 433: { 434: if (selected) 435: { 436: DBG2(DBG_CFG, " no acceptable %N found", transform_type_names, 437: type); 438: } 439: array_destroy(types); 440: return FALSE; 441: } 442: } 443: array_destroy(types); 444: return TRUE; 445: } 446: 447: METHOD(proposal_t, select_proposal, proposal_t*, 448: private_proposal_t *this, proposal_t *other, 449: proposal_selection_flag_t flags) 450: { 451: proposal_t *selected; 452: 453: DBG2(DBG_CFG, "selecting proposal:"); 454: 455: if (this->protocol != other->get_protocol(other)) 456: { 457: DBG2(DBG_CFG, " protocol mismatch, skipping"); 458: return NULL; 459: } 460: 461: if (flags & PROPOSAL_PREFER_SUPPLIED) 462: { 463: selected = proposal_create_v1(this->protocol, this->number, 464: this->transform_number); 465: selected->set_spi(selected, this->spi); 466: } 467: else 468: { 469: selected = proposal_create_v1(this->protocol, other->get_number(other), 470: other->get_transform_number(other)); 471: selected->set_spi(selected, other->get_spi(other)); 472: } 473: 474: if (!select_algos(this, other, selected, flags)) 475: { 476: selected->destroy(selected); 477: return NULL; 478: } 479: DBG2(DBG_CFG, " proposal matches"); 480: return selected; 481: } 482: 483: METHOD(proposal_t, matches, bool, 484: private_proposal_t *this, proposal_t *other, 485: proposal_selection_flag_t flags) 486: { 487: if (this->protocol != other->get_protocol(other)) 488: { 489: return FALSE; 490: } 491: return select_algos(this, other, NULL, flags); 492: } 493: 494: METHOD(proposal_t, get_protocol, protocol_id_t, 495: private_proposal_t *this) 496: { 497: return this->protocol; 498: } 499: 500: METHOD(proposal_t, set_spi, void, 501: private_proposal_t *this, uint64_t spi) 502: { 503: this->spi = spi; 504: } 505: 506: METHOD(proposal_t, get_spi, uint64_t, 507: private_proposal_t *this) 508: { 509: return this->spi; 510: } 511: 512: /** 513: * Check if two proposals have the same algorithms for a given transform type 514: */ 515: static bool algo_list_equals(private_proposal_t *this, proposal_t *other, 516: transform_type_t type) 517: { 518: enumerator_t *e1, *e2; 519: uint16_t alg1, alg2, ks1, ks2; 520: bool equals = TRUE; 521: 522: e1 = create_enumerator(this, type); 523: e2 = other->create_enumerator(other, type); 524: while (e1->enumerate(e1, &alg1, &ks1)) 525: { 526: if (!e2->enumerate(e2, &alg2, &ks2)) 527: { 528: /* this has more algs */ 529: equals = FALSE; 530: break; 531: } 532: if (alg1 != alg2 || ks1 != ks2) 533: { 534: equals = FALSE; 535: break; 536: } 537: } 538: if (e2->enumerate(e2, &alg2, &ks2)) 539: { 540: /* other has more algs */ 541: equals = FALSE; 542: } 543: e1->destroy(e1); 544: e2->destroy(e2); 545: 546: return equals; 547: } 548: 549: METHOD(proposal_t, get_number, uint8_t, 550: private_proposal_t *this) 551: { 552: return this->number; 553: } 554: 555: METHOD(proposal_t, get_transform_number, uint8_t, 556: private_proposal_t *this) 557: { 558: return this->transform_number; 559: } 560: 561: METHOD(proposal_t, equals, bool, 562: private_proposal_t *this, proposal_t *other) 563: { 564: transform_type_t type; 565: array_t *types; 566: int i; 567: 568: if (&this->public == other) 569: { 570: return TRUE; 571: } 572: 573: types = merge_types(this, (private_proposal_t*)other); 574: for (i = 0; i < array_count(types); i++) 575: { 576: array_get(types, i, &type); 577: if (!algo_list_equals(this, other, type)) 578: { 579: array_destroy(types); 580: return FALSE; 581: } 582: } 583: array_destroy(types); 584: return TRUE; 585: } 586: 587: METHOD(proposal_t, clone_, proposal_t*, 588: private_proposal_t *this, proposal_selection_flag_t flags) 589: { 590: private_proposal_t *clone; 591: enumerator_t *enumerator; 592: entry_t *entry; 593: 594: clone = (private_proposal_t*)proposal_create(this->protocol, 0); 595: 596: enumerator = array_create_enumerator(this->transforms); 597: while (enumerator->enumerate(enumerator, &entry)) 598: { 599: if (entry->alg >= 1024 && (flags & PROPOSAL_SKIP_PRIVATE)) 600: { 601: continue; 602: } 603: if (entry->type == DIFFIE_HELLMAN_GROUP && (flags & PROPOSAL_SKIP_DH)) 604: { 605: continue; 606: } 607: array_insert(clone->transforms, ARRAY_TAIL, entry); 608: add_type(clone->types, entry->type); 609: } 610: enumerator->destroy(enumerator); 611: 612: clone->spi = this->spi; 613: clone->number = this->number; 614: clone->transform_number = this->transform_number; 615: 616: return &clone->public; 617: } 618: 619: /** 620: * Map integrity algorithms to the PRF functions using the same algorithm. 621: */ 622: static const struct { 623: integrity_algorithm_t integ; 624: pseudo_random_function_t prf; 625: } integ_prf_map[] = { 626: {AUTH_HMAC_SHA1_96, PRF_HMAC_SHA1 }, 627: {AUTH_HMAC_SHA1_160, PRF_HMAC_SHA1 }, 628: {AUTH_HMAC_SHA2_256_128, PRF_HMAC_SHA2_256 }, 629: {AUTH_HMAC_SHA2_384_192, PRF_HMAC_SHA2_384 }, 630: {AUTH_HMAC_SHA2_512_256, PRF_HMAC_SHA2_512 }, 631: {AUTH_HMAC_MD5_96, PRF_HMAC_MD5 }, 632: {AUTH_HMAC_MD5_128, PRF_HMAC_MD5 }, 633: {AUTH_AES_XCBC_96, PRF_AES128_XCBC }, 634: {AUTH_CAMELLIA_XCBC_96, PRF_CAMELLIA128_XCBC }, 635: {AUTH_AES_CMAC_96, PRF_AES128_CMAC }, 636: }; 637: 638: /** 639: * Remove all entries of the given transform type 640: */ 641: static void remove_transform(private_proposal_t *this, transform_type_t type) 642: { 643: enumerator_t *e; 644: entry_t *entry; 645: 646: e = array_create_enumerator(this->transforms); 647: while (e->enumerate(e, &entry)) 648: { 649: if (entry->type == type) 650: { 651: array_remove_at(this->transforms, e); 652: } 653: } 654: e->destroy(e); 655: remove_type(this, type); 656: } 657: 658: /** 659: * Checks the proposal read from a string. 660: */ 661: static bool check_proposal(private_proposal_t *this) 662: { 663: enumerator_t *e; 664: entry_t *entry; 665: uint16_t alg, ks; 666: bool all_aead = TRUE, any_aead = FALSE, any_enc = FALSE; 667: int i; 668: 669: if (this->protocol == PROTO_IKE) 670: { 671: if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL)) 672: { /* No explicit PRF found. We assume the same algorithm as used 673: * for integrity checking. */ 674: e = create_enumerator(this, INTEGRITY_ALGORITHM); 675: while (e->enumerate(e, &alg, &ks)) 676: { 677: for (i = 0; i < countof(integ_prf_map); i++) 678: { 679: if (alg == integ_prf_map[i].integ) 680: { 681: add_algorithm(this, PSEUDO_RANDOM_FUNCTION, 682: integ_prf_map[i].prf, 0); 683: break; 684: } 685: } 686: } 687: e->destroy(e); 688: } 689: if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL)) 690: { 691: DBG1(DBG_CFG, "a PRF algorithm is mandatory in IKE proposals"); 692: return FALSE; 693: } 694: /* remove MODP_NONE from IKE proposal */ 695: e = array_create_enumerator(this->transforms); 696: while (e->enumerate(e, &entry)) 697: { 698: if (entry->type == DIFFIE_HELLMAN_GROUP && !entry->alg) 699: { 700: array_remove_at(this->transforms, e); 701: } 702: } 703: e->destroy(e); 704: if (!get_algorithm(this, DIFFIE_HELLMAN_GROUP, NULL, NULL)) 705: { 706: DBG1(DBG_CFG, "a DH group is mandatory in IKE proposals"); 707: return FALSE; 708: } 709: } 710: else 711: { /* remove PRFs from ESP/AH proposals */ 712: remove_transform(this, PSEUDO_RANDOM_FUNCTION); 713: } 714: 715: if (this->protocol == PROTO_IKE || this->protocol == PROTO_ESP) 716: { 717: e = create_enumerator(this, ENCRYPTION_ALGORITHM); 718: while (e->enumerate(e, &alg, &ks)) 719: { 720: any_enc = TRUE; 721: if (encryption_algorithm_is_aead(alg)) 722: { 723: any_aead = TRUE; 724: continue; 725: } 726: all_aead = FALSE; 727: } 728: e->destroy(e); 729: 730: if (!any_enc) 731: { 732: DBG1(DBG_CFG, "an encryption algorithm is mandatory in %N proposals", 733: protocol_id_names, this->protocol); 734: return FALSE; 735: } 736: else if (any_aead && !all_aead) 737: { 738: DBG1(DBG_CFG, "classic and combined-mode (AEAD) encryption " 739: "algorithms can't be contained in the same %N proposal", 740: protocol_id_names, this->protocol); 741: return FALSE; 742: } 743: else if (all_aead) 744: { /* if all encryption algorithms in the proposal are AEADs, 745: * we MUST NOT propose any integrity algorithms */ 746: remove_transform(this, INTEGRITY_ALGORITHM); 747: } 748: else if (this->protocol == PROTO_IKE && 749: !get_algorithm(this, INTEGRITY_ALGORITHM, NULL, NULL)) 750: { 751: DBG1(DBG_CFG, "an integrity algorithm is mandatory in %N proposals " 752: "with classic (non-AEAD) encryption algorithms", 753: protocol_id_names, this->protocol); 754: return FALSE; 755: } 756: } 757: else 758: { /* AES-GMAC is parsed as encryption algorithm, so we map that to the 759: * proper integrity algorithm */ 760: e = array_create_enumerator(this->transforms); 761: while (e->enumerate(e, &entry)) 762: { 763: if (entry->type == ENCRYPTION_ALGORITHM) 764: { 765: if (entry->alg == ENCR_NULL_AUTH_AES_GMAC) 766: { 767: entry->type = INTEGRITY_ALGORITHM; 768: ks = entry->key_size; 769: entry->key_size = 0; 770: switch (ks) 771: { 772: case 128: 773: entry->alg = AUTH_AES_128_GMAC; 774: continue; 775: case 192: 776: entry->alg = AUTH_AES_192_GMAC; 777: continue; 778: case 256: 779: entry->alg = AUTH_AES_256_GMAC; 780: continue; 781: default: 782: break; 783: } 784: } 785: /* remove all other encryption algorithms */ 786: array_remove_at(this->transforms, e); 787: } 788: } 789: e->destroy(e); 790: remove_type(this, ENCRYPTION_ALGORITHM); 791: 792: if (!get_algorithm(this, INTEGRITY_ALGORITHM, NULL, NULL)) 793: { 794: DBG1(DBG_CFG, "an integrity algorithm is mandatory in AH " 795: "proposals"); 796: return FALSE; 797: } 798: } 799: 800: if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP) 801: { 802: if (!get_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NULL, NULL)) 803: { /* ESN not specified, assume not supported */ 804: add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); 805: } 806: } 807: 808: array_compress(this->transforms); 809: array_compress(this->types); 810: return TRUE; 811: } 812: 813: /** 814: * add a algorithm identified by a string to the proposal. 815: */ 816: static bool add_string_algo(private_proposal_t *this, const char *alg) 817: { 818: const proposal_token_t *token; 819: 820: token = lib->proposal->get_token(lib->proposal, alg); 821: if (token == NULL) 822: { 823: DBG1(DBG_CFG, "algorithm '%s' not recognized", alg); 824: return FALSE; 825: } 826: 827: add_algorithm(this, token->type, token->algorithm, token->keysize); 828: 829: return TRUE; 830: } 831: 832: /** 833: * Print all algorithms of the given type 834: */ 835: static int print_alg(private_proposal_t *this, printf_hook_data_t *data, 836: transform_type_t type, bool *first) 837: { 838: enumerator_t *enumerator; 839: size_t written = 0; 840: entry_t *entry; 841: enum_name_t *names; 842: 843: names = transform_get_enum_names(type); 844: 845: enumerator = array_create_enumerator(this->transforms); 846: while (enumerator->enumerate(enumerator, &entry)) 847: { 848: char *prefix = "/"; 849: 850: if (type != entry->type) 851: { 852: continue; 853: } 854: if (*first) 855: { 856: prefix = ""; 857: *first = FALSE; 858: } 859: if (names) 860: { 861: written += print_in_hook(data, "%s%N", prefix, names, entry->alg); 862: } 863: else 864: { 865: written += print_in_hook(data, "%sUNKNOWN_%u_%u", prefix, 866: entry->type, entry->alg); 867: } 868: if (entry->key_size) 869: { 870: written += print_in_hook(data, "_%u", entry->key_size); 871: } 872: } 873: enumerator->destroy(enumerator); 874: return written; 875: } 876: 877: /** 878: * Described in header. 879: */ 880: int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, 881: const void *const *args) 882: { 883: private_proposal_t *this = *((private_proposal_t**)(args[0])); 884: linked_list_t *list = *((linked_list_t**)(args[0])); 885: enumerator_t *enumerator; 886: transform_type_t *type; 887: size_t written = 0; 888: bool first = TRUE; 889: 890: if (this == NULL) 891: { 892: return print_in_hook(data, "(null)"); 893: } 894: 895: if (spec->hash) 896: { 897: enumerator = list->create_enumerator(list); 898: while (enumerator->enumerate(enumerator, &this)) 899: { /* call recursively */ 900: if (first) 901: { 902: written += print_in_hook(data, "%P", this); 903: first = FALSE; 904: } 905: else 906: { 907: written += print_in_hook(data, ", %P", this); 908: } 909: } 910: enumerator->destroy(enumerator); 911: return written; 912: } 913: 914: written = print_in_hook(data, "%N:", protocol_id_names, this->protocol); 915: enumerator = array_create_enumerator(this->types); 916: while (enumerator->enumerate(enumerator, &type)) 917: { 918: written += print_alg(this, data, *type, &first); 919: } 920: enumerator->destroy(enumerator); 921: return written; 922: } 923: 924: METHOD(proposal_t, destroy, void, 925: private_proposal_t *this) 926: { 927: array_destroy(this->transforms); 928: array_destroy(this->types); 929: free(this); 930: } 931: 932: /* 933: * Described in header 934: */ 935: proposal_t *proposal_create_v1(protocol_id_t protocol, uint8_t number, 936: uint8_t transform) 937: { 938: private_proposal_t *this; 939: 940: INIT(this, 941: .public = { 942: .add_algorithm = _add_algorithm, 943: .create_enumerator = _create_enumerator, 944: .get_algorithm = _get_algorithm, 945: .has_dh_group = _has_dh_group, 946: .promote_dh_group = _promote_dh_group, 947: .select = _select_proposal, 948: .matches = _matches, 949: .get_protocol = _get_protocol, 950: .set_spi = _set_spi, 951: .get_spi = _get_spi, 952: .get_number = _get_number, 953: .get_transform_number = _get_transform_number, 954: .equals = _equals, 955: .clone = _clone_, 956: .destroy = _destroy, 957: }, 958: .protocol = protocol, 959: .number = number, 960: .transform_number = transform, 961: .transforms = array_create(sizeof(entry_t), 0), 962: .types = array_create(sizeof(transform_type_t), 0), 963: ); 964: 965: return &this->public; 966: } 967: 968: /* 969: * Described in header 970: */ 971: proposal_t *proposal_create(protocol_id_t protocol, uint8_t number) 972: { 973: return proposal_create_v1(protocol, number, 0); 974: } 975: 976: /** 977: * Add supported IKE algorithms to proposal 978: */ 979: static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) 980: { 981: enumerator_t *enumerator; 982: encryption_algorithm_t encryption; 983: integrity_algorithm_t integrity; 984: pseudo_random_function_t prf; 985: diffie_hellman_group_t group; 986: const char *plugin_name; 987: 988: if (aead) 989: { 990: /* Round 1 adds algorithms with at least 128 bit security strength */ 991: enumerator = lib->crypto->create_aead_enumerator(lib->crypto); 992: while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) 993: { 994: switch (encryption) 995: { 996: case ENCR_AES_GCM_ICV16: 997: case ENCR_AES_CCM_ICV16: 998: case ENCR_CAMELLIA_CCM_ICV16: 999: /* we assume that we support all AES/Camellia sizes */ 1000: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); 1001: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); 1002: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); 1003: break; 1004: case ENCR_CHACHA20_POLY1305: 1005: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0); 1006: break; 1007: default: 1008: break; 1009: } 1010: } 1011: enumerator->destroy(enumerator); 1012: 1013: /* Round 2 adds algorithms with less than 128 bit security strength */ 1014: enumerator = lib->crypto->create_aead_enumerator(lib->crypto); 1015: while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) 1016: { 1017: switch (encryption) 1018: { 1019: case ENCR_AES_GCM_ICV12: 1020: case ENCR_AES_GCM_ICV8: 1021: case ENCR_AES_CCM_ICV12: 1022: case ENCR_AES_CCM_ICV8: 1023: case ENCR_CAMELLIA_CCM_ICV12: 1024: case ENCR_CAMELLIA_CCM_ICV8: 1025: /* we assume that we support all AES/Camellia sizes */ 1026: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); 1027: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); 1028: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); 1029: break; 1030: default: 1031: break; 1032: } 1033: } 1034: enumerator->destroy(enumerator); 1035: 1036: if (!array_count(this->transforms)) 1037: { 1038: return FALSE; 1039: } 1040: } 1041: else 1042: { 1043: /* Round 1 adds algorithms with at least 128 bit security strength */ 1044: enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); 1045: while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) 1046: { 1047: switch (encryption) 1048: { 1049: case ENCR_AES_CBC: 1050: case ENCR_AES_CTR: 1051: case ENCR_CAMELLIA_CBC: 1052: case ENCR_CAMELLIA_CTR: 1053: /* we assume that we support all AES/Camellia sizes */ 1054: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); 1055: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); 1056: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); 1057: break; 1058: default: 1059: break; 1060: } 1061: } 1062: enumerator->destroy(enumerator); 1063: 1064: /* Round 2 adds algorithms with less than 128 bit security strength */ 1065: enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); 1066: while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) 1067: { 1068: switch (encryption) 1069: { 1070: case ENCR_3DES: 1071: add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0); 1072: break; 1073: case ENCR_DES: 1074: /* no, thanks */ 1075: break; 1076: default: 1077: break; 1078: } 1079: } 1080: enumerator->destroy(enumerator); 1081: 1082: if (!array_count(this->transforms)) 1083: { 1084: return FALSE; 1085: } 1086: 1087: /* Round 1 adds algorithms with at least 128 bit security strength */ 1088: enumerator = lib->crypto->create_signer_enumerator(lib->crypto); 1089: while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) 1090: { 1091: switch (integrity) 1092: { 1093: case AUTH_HMAC_SHA2_256_128: 1094: case AUTH_HMAC_SHA2_384_192: 1095: case AUTH_HMAC_SHA2_512_256: 1096: add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0); 1097: break; 1098: default: 1099: break; 1100: } 1101: } 1102: enumerator->destroy(enumerator); 1103: 1104: /* Round 2 adds algorithms with less than 128 bit security strength */ 1105: enumerator = lib->crypto->create_signer_enumerator(lib->crypto); 1106: while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) 1107: { 1108: switch (integrity) 1109: { 1110: case AUTH_AES_XCBC_96: 1111: case AUTH_AES_CMAC_96: 1112: case AUTH_HMAC_SHA1_96: 1113: add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0); 1114: break; 1115: case AUTH_HMAC_MD5_96: 1116: /* no, thanks */ 1117: default: 1118: break; 1119: } 1120: } 1121: enumerator->destroy(enumerator); 1122: } 1123: 1124: /* Round 1 adds algorithms with at least 128 bit security strength */ 1125: enumerator = lib->crypto->create_prf_enumerator(lib->crypto); 1126: while (enumerator->enumerate(enumerator, &prf, &plugin_name)) 1127: { 1128: switch (prf) 1129: { 1130: case PRF_HMAC_SHA2_256: 1131: case PRF_HMAC_SHA2_384: 1132: case PRF_HMAC_SHA2_512: 1133: case PRF_AES128_XCBC: 1134: case PRF_AES128_CMAC: 1135: add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); 1136: break; 1137: default: 1138: break; 1139: } 1140: } 1141: enumerator->destroy(enumerator); 1142: 1143: /* Round 2 adds algorithms with less than 128 bit security strength */ 1144: enumerator = lib->crypto->create_prf_enumerator(lib->crypto); 1145: while (enumerator->enumerate(enumerator, &prf, &plugin_name)) 1146: { 1147: switch (prf) 1148: { 1149: case PRF_HMAC_SHA1: 1150: add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); 1151: break; 1152: case PRF_HMAC_MD5: 1153: /* no, thanks */ 1154: break; 1155: default: 1156: break; 1157: } 1158: } 1159: enumerator->destroy(enumerator); 1160: 1161: /* Round 1 adds ECC and NTRU algorithms with at least 128 bit security strength */ 1162: enumerator = lib->crypto->create_dh_enumerator(lib->crypto); 1163: while (enumerator->enumerate(enumerator, &group, &plugin_name)) 1164: { 1165: switch (group) 1166: { 1167: case ECP_256_BIT: 1168: case ECP_384_BIT: 1169: case ECP_521_BIT: 1170: case ECP_256_BP: 1171: case ECP_384_BP: 1172: case ECP_512_BP: 1173: case CURVE_25519: 1174: case CURVE_448: 1175: case NTRU_128_BIT: 1176: case NTRU_192_BIT: 1177: case NTRU_256_BIT: 1178: case NH_128_BIT: 1179: add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); 1180: break; 1181: default: 1182: break; 1183: } 1184: } 1185: enumerator->destroy(enumerator); 1186: 1187: /* Round 2 adds other algorithms with at least 128 bit security strength */ 1188: enumerator = lib->crypto->create_dh_enumerator(lib->crypto); 1189: while (enumerator->enumerate(enumerator, &group, &plugin_name)) 1190: { 1191: switch (group) 1192: { 1193: case MODP_3072_BIT: 1194: case MODP_4096_BIT: 1195: case MODP_6144_BIT: 1196: case MODP_8192_BIT: 1197: add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); 1198: break; 1199: default: 1200: break; 1201: } 1202: } 1203: enumerator->destroy(enumerator); 1204: 1205: /* Round 3 adds algorithms with less than 128 bit security strength */ 1206: enumerator = lib->crypto->create_dh_enumerator(lib->crypto); 1207: while (enumerator->enumerate(enumerator, &group, &plugin_name)) 1208: { 1209: switch (group) 1210: { 1211: case MODP_NULL: 1212: /* only for testing purposes */ 1213: break; 1214: case MODP_768_BIT: 1215: case MODP_1024_BIT: 1216: case MODP_1536_BIT: 1217: /* weak */ 1218: break; 1219: case MODP_1024_160: 1220: case MODP_2048_224: 1221: case MODP_2048_256: 1222: /* RFC 5114 primes are of questionable source */ 1223: break; 1224: case ECP_224_BIT: 1225: case ECP_224_BP: 1226: case ECP_192_BIT: 1227: case NTRU_112_BIT: 1228: /* rarely used */ 1229: break; 1230: case MODP_2048_BIT: 1231: add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); 1232: break; 1233: default: 1234: break; 1235: } 1236: } 1237: enumerator->destroy(enumerator); 1238: 1239: return TRUE; 1240: } 1241: 1242: /* 1243: * Described in header 1244: */ 1245: proposal_t *proposal_create_default(protocol_id_t protocol) 1246: { 1247: private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0); 1248: 1249: switch (protocol) 1250: { 1251: case PROTO_IKE: 1252: if (!proposal_add_supported_ike(this, FALSE)) 1253: { 1254: destroy(this); 1255: return NULL; 1256: } 1257: break; 1258: case PROTO_ESP: 1259: add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); 1260: add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); 1261: add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); 1262: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); 1263: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); 1264: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); 1265: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); 1266: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); 1267: add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); 1268: break; 1269: case PROTO_AH: 1270: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); 1271: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); 1272: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); 1273: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); 1274: add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); 1275: add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); 1276: break; 1277: default: 1278: break; 1279: } 1280: return &this->public; 1281: } 1282: 1283: /* 1284: * Described in header 1285: */ 1286: proposal_t *proposal_create_default_aead(protocol_id_t protocol) 1287: { 1288: private_proposal_t *this; 1289: 1290: switch (protocol) 1291: { 1292: case PROTO_IKE: 1293: this = (private_proposal_t*)proposal_create(protocol, 0); 1294: if (!proposal_add_supported_ike(this, TRUE)) 1295: { 1296: destroy(this); 1297: return NULL; 1298: } 1299: return &this->public; 1300: case PROTO_ESP: 1301: /* we currently don't include any AEAD proposal for ESP, as we 1302: * don't know if our kernel backend actually supports it. */ 1303: return NULL; 1304: case PROTO_AH: 1305: default: 1306: return NULL; 1307: } 1308: } 1309: 1310: /* 1311: * Described in header 1312: */ 1313: proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs) 1314: { 1315: private_proposal_t *this; 1316: enumerator_t *enumerator; 1317: bool failed = TRUE; 1318: char *alg; 1319: 1320: this = (private_proposal_t*)proposal_create(protocol, 0); 1321: 1322: /* get all tokens, separated by '-' */ 1323: enumerator = enumerator_create_token(algs, "-", " "); 1324: while (enumerator->enumerate(enumerator, &alg)) 1325: { 1326: if (!add_string_algo(this, alg)) 1327: { 1328: failed = TRUE; 1329: break; 1330: } 1331: failed = FALSE; 1332: } 1333: enumerator->destroy(enumerator); 1334: 1335: if (failed || !check_proposal(this)) 1336: { 1337: destroy(this); 1338: return NULL; 1339: } 1340: 1341: return &this->public; 1342: } 1343: 1344: /* 1345: * Described in header 1346: */ 1347: proposal_t *proposal_select(linked_list_t *configured, linked_list_t *supplied, 1348: proposal_selection_flag_t flags) 1349: { 1350: enumerator_t *prefer_enum, *match_enum; 1351: proposal_t *proposal, *match, *selected = NULL; 1352: 1353: if (flags & PROPOSAL_PREFER_SUPPLIED) 1354: { 1355: prefer_enum = supplied->create_enumerator(supplied); 1356: match_enum = configured->create_enumerator(configured); 1357: } 1358: else 1359: { 1360: prefer_enum = configured->create_enumerator(configured); 1361: match_enum = supplied->create_enumerator(supplied); 1362: } 1363: 1364: while (prefer_enum->enumerate(prefer_enum, &proposal)) 1365: { 1366: if (flags & PROPOSAL_PREFER_SUPPLIED) 1367: { 1368: configured->reset_enumerator(configured, match_enum); 1369: } 1370: else 1371: { 1372: supplied->reset_enumerator(supplied, match_enum); 1373: } 1374: while (match_enum->enumerate(match_enum, &match)) 1375: { 1376: selected = proposal->select(proposal, match, flags); 1377: if (selected) 1378: { 1379: DBG2(DBG_CFG, "received proposals: %#P", supplied); 1380: DBG2(DBG_CFG, "configured proposals: %#P", configured); 1381: DBG1(DBG_CFG, "selected proposal: %P", selected); 1382: break; 1383: } 1384: } 1385: if (selected) 1386: { 1387: break; 1388: } 1389: } 1390: prefer_enum->destroy(prefer_enum); 1391: match_enum->destroy(match_enum); 1392: if (!selected) 1393: { 1394: DBG1(DBG_CFG, "received proposals: %#P", supplied); 1395: DBG1(DBG_CFG, "configured proposals: %#P", configured); 1396: } 1397: return selected; 1398: }