Return to tls_peer.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtls |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2010 Martin Willi ! 3: * Copyright (C) 2010 revosec AG ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify it ! 6: * under the terms of the GNU General Public License as published by the ! 7: * Free Software Foundation; either version 2 of the License, or (at your ! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, but ! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 13: * for more details. ! 14: */ ! 15: ! 16: #include "tls_peer.h" ! 17: ! 18: #include <utils/debug.h> ! 19: #include <credentials/certificates/x509.h> ! 20: ! 21: #include <time.h> ! 22: ! 23: typedef struct private_tls_peer_t private_tls_peer_t; ! 24: ! 25: typedef enum { ! 26: STATE_INIT, ! 27: STATE_HELLO_SENT, ! 28: STATE_HELLO_RECEIVED, ! 29: STATE_HELLO_DONE, ! 30: STATE_CERT_SENT, ! 31: STATE_CERT_RECEIVED, ! 32: STATE_KEY_EXCHANGE_RECEIVED, ! 33: STATE_CERTREQ_RECEIVED, ! 34: STATE_KEY_EXCHANGE_SENT, ! 35: STATE_VERIFY_SENT, ! 36: STATE_CIPHERSPEC_CHANGED_OUT, ! 37: STATE_FINISHED_SENT, ! 38: STATE_CIPHERSPEC_CHANGED_IN, ! 39: STATE_FINISHED_RECEIVED, ! 40: } peer_state_t; ! 41: ! 42: /** ! 43: * Private data of an tls_peer_t object. ! 44: */ ! 45: struct private_tls_peer_t { ! 46: ! 47: /** ! 48: * Public tls_peer_t interface. ! 49: */ ! 50: tls_peer_t public; ! 51: ! 52: /** ! 53: * TLS stack ! 54: */ ! 55: tls_t *tls; ! 56: ! 57: /** ! 58: * TLS crypto context ! 59: */ ! 60: tls_crypto_t *crypto; ! 61: ! 62: /** ! 63: * TLS alert handler ! 64: */ ! 65: tls_alert_t *alert; ! 66: ! 67: /** ! 68: * Peer identity, NULL for no client authentication ! 69: */ ! 70: identification_t *peer; ! 71: ! 72: /** ! 73: * Server identity ! 74: */ ! 75: identification_t *server; ! 76: ! 77: /** ! 78: * State we are in ! 79: */ ! 80: peer_state_t state; ! 81: ! 82: /** ! 83: * TLS version we offered in hello ! 84: */ ! 85: tls_version_t hello_version; ! 86: ! 87: /** ! 88: * Hello random data selected by client ! 89: */ ! 90: char client_random[32]; ! 91: ! 92: /** ! 93: * Hello random data selected by server ! 94: */ ! 95: char server_random[32]; ! 96: ! 97: /** ! 98: * Auth helper for peer authentication ! 99: */ ! 100: auth_cfg_t *peer_auth; ! 101: ! 102: /** ! 103: * Auth helper for server authentication ! 104: */ ! 105: auth_cfg_t *server_auth; ! 106: ! 107: /** ! 108: * Peer private key ! 109: */ ! 110: private_key_t *private; ! 111: ! 112: /** ! 113: * DHE exchange ! 114: */ ! 115: diffie_hellman_t *dh; ! 116: ! 117: /** ! 118: * Resuming a session? ! 119: */ ! 120: bool resume; ! 121: ! 122: /** ! 123: * TLS session identifier ! 124: */ ! 125: chunk_t session; ! 126: ! 127: /** ! 128: * List of server-supported hashsig algorithms ! 129: */ ! 130: chunk_t hashsig; ! 131: ! 132: /** ! 133: * List of server-supported client certificate types ! 134: */ ! 135: chunk_t cert_types; ! 136: }; ! 137: ! 138: /** ! 139: * Process a server hello message ! 140: */ ! 141: static status_t process_server_hello(private_tls_peer_t *this, ! 142: bio_reader_t *reader) ! 143: { ! 144: uint8_t compression; ! 145: uint16_t version, cipher; ! 146: chunk_t random, session, ext = chunk_empty; ! 147: tls_cipher_suite_t suite = 0; ! 148: ! 149: this->crypto->append_handshake(this->crypto, ! 150: TLS_SERVER_HELLO, reader->peek(reader)); ! 151: ! 152: if (!reader->read_uint16(reader, &version) || ! 153: !reader->read_data(reader, sizeof(this->server_random), &random) || ! 154: !reader->read_data8(reader, &session) || ! 155: !reader->read_uint16(reader, &cipher) || ! 156: !reader->read_uint8(reader, &compression) || ! 157: (reader->remaining(reader) && !reader->read_data16(reader, &ext))) ! 158: { ! 159: DBG1(DBG_TLS, "received invalid ServerHello"); ! 160: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 161: return NEED_MORE; ! 162: } ! 163: ! 164: memcpy(this->server_random, random.ptr, sizeof(this->server_random)); ! 165: ! 166: if (!this->tls->set_version(this->tls, version)) ! 167: { ! 168: DBG1(DBG_TLS, "negotiated version %N not supported", ! 169: tls_version_names, version); ! 170: this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION); ! 171: return NEED_MORE; ! 172: } ! 173: ! 174: if (chunk_equals(this->session, session)) ! 175: { ! 176: suite = this->crypto->resume_session(this->crypto, session, this->server, ! 177: chunk_from_thing(this->client_random), ! 178: chunk_from_thing(this->server_random)); ! 179: if (suite) ! 180: { ! 181: DBG1(DBG_TLS, "resumed %N using suite %N", ! 182: tls_version_names, version, tls_cipher_suite_names, suite); ! 183: this->resume = TRUE; ! 184: } ! 185: } ! 186: if (!suite) ! 187: { ! 188: suite = cipher; ! 189: if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1, KEY_ANY)) ! 190: { ! 191: DBG1(DBG_TLS, "received TLS cipher suite %N unacceptable", ! 192: tls_cipher_suite_names, suite); ! 193: this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); ! 194: return NEED_MORE; ! 195: } ! 196: DBG1(DBG_TLS, "negotiated %N using suite %N", ! 197: tls_version_names, version, tls_cipher_suite_names, suite); ! 198: free(this->session.ptr); ! 199: this->session = chunk_clone(session); ! 200: } ! 201: this->state = STATE_HELLO_RECEIVED; ! 202: return NEED_MORE; ! 203: } ! 204: ! 205: /** ! 206: * Check if a server certificate is acceptable for the given server identity ! 207: */ ! 208: static bool check_certificate(private_tls_peer_t *this, certificate_t *cert) ! 209: { ! 210: identification_t *id; ! 211: ! 212: if (cert->has_subject(cert, this->server)) ! 213: { ! 214: return TRUE; ! 215: } ! 216: id = cert->get_subject(cert); ! 217: if (id->matches(id, this->server)) ! 218: { ! 219: return TRUE; ! 220: } ! 221: if (cert->get_type(cert) == CERT_X509) ! 222: { ! 223: x509_t *x509 = (x509_t*)cert; ! 224: enumerator_t *enumerator; ! 225: ! 226: enumerator = x509->create_subjectAltName_enumerator(x509); ! 227: while (enumerator->enumerate(enumerator, &id)) ! 228: { ! 229: if (id->matches(id, this->server)) ! 230: { ! 231: enumerator->destroy(enumerator); ! 232: return TRUE; ! 233: } ! 234: } ! 235: enumerator->destroy(enumerator); ! 236: } ! 237: DBG1(DBG_TLS, "server certificate does not match to '%Y'", this->server); ! 238: return FALSE; ! 239: } ! 240: ! 241: /** ! 242: * Process a Certificate message ! 243: */ ! 244: static status_t process_certificate(private_tls_peer_t *this, ! 245: bio_reader_t *reader) ! 246: { ! 247: certificate_t *cert; ! 248: bio_reader_t *certs; ! 249: chunk_t data; ! 250: bool first = TRUE; ! 251: ! 252: this->crypto->append_handshake(this->crypto, ! 253: TLS_CERTIFICATE, reader->peek(reader)); ! 254: ! 255: if (!reader->read_data24(reader, &data)) ! 256: { ! 257: DBG1(DBG_TLS, "certificate message header invalid"); ! 258: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 259: return NEED_MORE; ! 260: } ! 261: certs = bio_reader_create(data); ! 262: while (certs->remaining(certs)) ! 263: { ! 264: if (!certs->read_data24(certs, &data)) ! 265: { ! 266: DBG1(DBG_TLS, "certificate message invalid"); ! 267: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 268: certs->destroy(certs); ! 269: return NEED_MORE; ! 270: } ! 271: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, ! 272: BUILD_BLOB_ASN1_DER, data, BUILD_END); ! 273: if (cert) ! 274: { ! 275: if (first) ! 276: { ! 277: if (!check_certificate(this, cert)) ! 278: { ! 279: cert->destroy(cert); ! 280: certs->destroy(certs); ! 281: this->alert->add(this->alert, TLS_FATAL, TLS_ACCESS_DENIED); ! 282: return NEED_MORE; ! 283: } ! 284: this->server_auth->add(this->server_auth, ! 285: AUTH_HELPER_SUBJECT_CERT, cert); ! 286: DBG1(DBG_TLS, "received TLS server certificate '%Y'", ! 287: cert->get_subject(cert)); ! 288: first = FALSE; ! 289: } ! 290: else ! 291: { ! 292: DBG1(DBG_TLS, "received TLS intermediate certificate '%Y'", ! 293: cert->get_subject(cert)); ! 294: this->server_auth->add(this->server_auth, ! 295: AUTH_HELPER_IM_CERT, cert); ! 296: } ! 297: } ! 298: else ! 299: { ! 300: DBG1(DBG_TLS, "parsing TLS certificate failed, skipped"); ! 301: this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE); ! 302: } ! 303: } ! 304: certs->destroy(certs); ! 305: this->state = STATE_CERT_RECEIVED; ! 306: return NEED_MORE; ! 307: } ! 308: ! 309: /** ! 310: * Find a trusted public key to encrypt/verify key exchange data ! 311: */ ! 312: static public_key_t *find_public_key(private_tls_peer_t *this) ! 313: { ! 314: public_key_t *public = NULL, *current; ! 315: certificate_t *cert, *found; ! 316: enumerator_t *enumerator; ! 317: auth_cfg_t *auth; ! 318: ! 319: cert = this->server_auth->get(this->server_auth, AUTH_HELPER_SUBJECT_CERT); ! 320: if (cert) ! 321: { ! 322: enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, ! 323: KEY_ANY, cert->get_subject(cert), ! 324: this->server_auth, TRUE); ! 325: while (enumerator->enumerate(enumerator, ¤t, &auth)) ! 326: { ! 327: found = auth->get(auth, AUTH_RULE_SUBJECT_CERT); ! 328: if (found && cert->equals(cert, found)) ! 329: { ! 330: public = current->get_ref(current); ! 331: this->server_auth->merge(this->server_auth, auth, FALSE); ! 332: break; ! 333: } ! 334: } ! 335: enumerator->destroy(enumerator); ! 336: } ! 337: return public; ! 338: } ! 339: ! 340: /** ! 341: * Process a Key Exchange message using MODP Diffie Hellman ! 342: */ ! 343: static status_t process_modp_key_exchange(private_tls_peer_t *this, ! 344: bio_reader_t *reader) ! 345: { ! 346: chunk_t prime, generator, pub, chunk; ! 347: public_key_t *public; ! 348: ! 349: chunk = reader->peek(reader); ! 350: if (!reader->read_data16(reader, &prime) || ! 351: !reader->read_data16(reader, &generator) || ! 352: !reader->read_data16(reader, &pub)) ! 353: { ! 354: DBG1(DBG_TLS, "received invalid Server Key Exchange"); ! 355: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 356: return NEED_MORE; ! 357: } ! 358: /* reject (export) DH groups using primes smaller than 1024 bit */ ! 359: if (prime.len < 1024 / 8) ! 360: { ! 361: DBG1(DBG_TLS, "short DH prime received (%zu bytes)", prime.len); ! 362: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 363: return NEED_MORE; ! 364: } ! 365: public = find_public_key(this); ! 366: if (!public) ! 367: { ! 368: DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server); ! 369: this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); ! 370: return NEED_MORE; ! 371: } ! 372: ! 373: chunk.len = 2 + prime.len + 2 + generator.len + 2 + pub.len; ! 374: chunk = chunk_cat("ccc", chunk_from_thing(this->client_random), ! 375: chunk_from_thing(this->server_random), chunk); ! 376: if (!this->crypto->verify(this->crypto, public, reader, chunk)) ! 377: { ! 378: public->destroy(public); ! 379: free(chunk.ptr); ! 380: DBG1(DBG_TLS, "verifying DH parameters failed"); ! 381: this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE); ! 382: return NEED_MORE; ! 383: } ! 384: public->destroy(public); ! 385: free(chunk.ptr); ! 386: ! 387: this->dh = lib->crypto->create_dh(lib->crypto, MODP_CUSTOM, ! 388: generator, prime); ! 389: if (!this->dh) ! 390: { ! 391: DBG1(DBG_TLS, "custom DH parameters not supported"); ! 392: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 393: return NEED_MORE; ! 394: } ! 395: if (!this->dh->set_other_public_value(this->dh, pub)) ! 396: { ! 397: DBG1(DBG_TLS, "applying DH public value failed"); ! 398: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 399: return NEED_MORE; ! 400: } ! 401: ! 402: this->state = STATE_KEY_EXCHANGE_RECEIVED; ! 403: return NEED_MORE; ! 404: } ! 405: ! 406: /** ! 407: * Get the EC group for a TLS named curve ! 408: */ ! 409: static diffie_hellman_group_t curve_to_ec_group(private_tls_peer_t *this, ! 410: tls_named_curve_t curve) ! 411: { ! 412: diffie_hellman_group_t group; ! 413: tls_named_curve_t current; ! 414: enumerator_t *enumerator; ! 415: ! 416: enumerator = this->crypto->create_ec_enumerator(this->crypto); ! 417: while (enumerator->enumerate(enumerator, &group, ¤t)) ! 418: { ! 419: if (current == curve) ! 420: { ! 421: enumerator->destroy(enumerator); ! 422: return group; ! 423: } ! 424: } ! 425: enumerator->destroy(enumerator); ! 426: return 0; ! 427: } ! 428: ! 429: /** ! 430: * Process a Key Exchange message using EC Diffie Hellman ! 431: */ ! 432: static status_t process_ec_key_exchange(private_tls_peer_t *this, ! 433: bio_reader_t *reader) ! 434: { ! 435: diffie_hellman_group_t group; ! 436: public_key_t *public; ! 437: uint8_t type; ! 438: uint16_t curve; ! 439: chunk_t pub, chunk; ! 440: ! 441: chunk = reader->peek(reader); ! 442: if (!reader->read_uint8(reader, &type)) ! 443: { ! 444: DBG1(DBG_TLS, "received invalid Server Key Exchange"); ! 445: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 446: return NEED_MORE; ! 447: } ! 448: if (type != TLS_ECC_NAMED_CURVE) ! 449: { ! 450: DBG1(DBG_TLS, "ECDH curve type %N not supported", ! 451: tls_ecc_curve_type_names, type); ! 452: this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); ! 453: return NEED_MORE; ! 454: } ! 455: if (!reader->read_uint16(reader, &curve) || ! 456: !reader->read_data8(reader, &pub) || pub.len == 0) ! 457: { ! 458: DBG1(DBG_TLS, "received invalid Server Key Exchange"); ! 459: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 460: return NEED_MORE; ! 461: } ! 462: ! 463: group = curve_to_ec_group(this, curve); ! 464: if (!group) ! 465: { ! 466: DBG1(DBG_TLS, "ECDH curve %N not supported", ! 467: tls_named_curve_names, curve); ! 468: this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); ! 469: return NEED_MORE; ! 470: } ! 471: ! 472: public = find_public_key(this); ! 473: if (!public) ! 474: { ! 475: DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server); ! 476: this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); ! 477: return NEED_MORE; ! 478: } ! 479: ! 480: chunk.len = 4 + pub.len; ! 481: chunk = chunk_cat("ccc", chunk_from_thing(this->client_random), ! 482: chunk_from_thing(this->server_random), chunk); ! 483: if (!this->crypto->verify(this->crypto, public, reader, chunk)) ! 484: { ! 485: public->destroy(public); ! 486: free(chunk.ptr); ! 487: DBG1(DBG_TLS, "verifying DH parameters failed"); ! 488: this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE); ! 489: return NEED_MORE; ! 490: } ! 491: public->destroy(public); ! 492: free(chunk.ptr); ! 493: ! 494: this->dh = lib->crypto->create_dh(lib->crypto, group); ! 495: if (!this->dh) ! 496: { ! 497: DBG1(DBG_TLS, "DH group %N not supported", ! 498: diffie_hellman_group_names, group); ! 499: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 500: return NEED_MORE; ! 501: } ! 502: ! 503: if (pub.ptr[0] != TLS_ANSI_UNCOMPRESSED) ! 504: { ! 505: DBG1(DBG_TLS, "DH point format '%N' not supported", ! 506: tls_ansi_point_format_names, pub.ptr[0]); ! 507: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 508: return NEED_MORE; ! 509: } ! 510: if (!this->dh->set_other_public_value(this->dh, chunk_skip(pub, 1))) ! 511: { ! 512: DBG1(DBG_TLS, "applying DH public value failed"); ! 513: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 514: return NEED_MORE; ! 515: } ! 516: ! 517: this->state = STATE_KEY_EXCHANGE_RECEIVED; ! 518: return NEED_MORE; ! 519: } ! 520: ! 521: /** ! 522: * Process a Server Key Exchange ! 523: */ ! 524: static status_t process_key_exchange(private_tls_peer_t *this, ! 525: bio_reader_t *reader) ! 526: { ! 527: diffie_hellman_group_t group; ! 528: ! 529: this->crypto->append_handshake(this->crypto, ! 530: TLS_SERVER_KEY_EXCHANGE, reader->peek(reader)); ! 531: ! 532: group = this->crypto->get_dh_group(this->crypto); ! 533: if (group == MODP_NONE) ! 534: { ! 535: DBG1(DBG_TLS, "received Server Key Exchange, but not required " ! 536: "for current suite"); ! 537: this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); ! 538: return NEED_MORE; ! 539: } ! 540: if (diffie_hellman_group_is_ec(group)) ! 541: { ! 542: return process_ec_key_exchange(this, reader); ! 543: } ! 544: return process_modp_key_exchange(this, reader); ! 545: } ! 546: ! 547: /** ! 548: * Process a Certificate Request message ! 549: */ ! 550: static status_t process_certreq(private_tls_peer_t *this, bio_reader_t *reader) ! 551: { ! 552: chunk_t types, hashsig, data; ! 553: bio_reader_t *authorities; ! 554: identification_t *id; ! 555: certificate_t *cert; ! 556: ! 557: if (!this->peer) ! 558: { ! 559: DBG1(DBG_TLS, "server requested a certificate, but client " ! 560: "authentication disabled"); ! 561: } ! 562: this->crypto->append_handshake(this->crypto, ! 563: TLS_CERTIFICATE_REQUEST, reader->peek(reader)); ! 564: ! 565: if (!reader->read_data8(reader, &types)) ! 566: { ! 567: DBG1(DBG_TLS, "certreq message header invalid"); ! 568: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 569: return NEED_MORE; ! 570: } ! 571: this->cert_types = chunk_clone(types); ! 572: if (this->tls->get_version(this->tls) >= TLS_1_2) ! 573: { ! 574: if (!reader->read_data16(reader, &hashsig)) ! 575: { ! 576: DBG1(DBG_TLS, "certreq message invalid"); ! 577: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 578: return NEED_MORE; ! 579: } ! 580: this->hashsig = chunk_clone(hashsig); ! 581: } ! 582: if (!reader->read_data16(reader, &data)) ! 583: { ! 584: DBG1(DBG_TLS, "certreq message invalid"); ! 585: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 586: return NEED_MORE; ! 587: } ! 588: authorities = bio_reader_create(data); ! 589: while (authorities->remaining(authorities)) ! 590: { ! 591: if (!authorities->read_data16(authorities, &data)) ! 592: { ! 593: DBG1(DBG_TLS, "certreq message invalid"); ! 594: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 595: authorities->destroy(authorities); ! 596: return NEED_MORE; ! 597: } ! 598: if (this->peer) ! 599: { ! 600: id = identification_create_from_encoding(ID_DER_ASN1_DN, data); ! 601: cert = lib->credmgr->get_cert(lib->credmgr, ! 602: CERT_X509, KEY_ANY, id, TRUE); ! 603: if (cert) ! 604: { ! 605: DBG1(DBG_TLS, "received TLS cert request for '%Y", id); ! 606: this->peer_auth->add(this->peer_auth, AUTH_RULE_CA_CERT, cert); ! 607: } ! 608: else ! 609: { ! 610: DBG1(DBG_TLS, "received TLS cert request for unknown CA '%Y'", id); ! 611: } ! 612: id->destroy(id); ! 613: } ! 614: } ! 615: authorities->destroy(authorities); ! 616: this->state = STATE_CERTREQ_RECEIVED; ! 617: return NEED_MORE; ! 618: } ! 619: ! 620: /** ! 621: * Process Hello Done message ! 622: */ ! 623: static status_t process_hello_done(private_tls_peer_t *this, ! 624: bio_reader_t *reader) ! 625: { ! 626: this->crypto->append_handshake(this->crypto, ! 627: TLS_SERVER_HELLO_DONE, reader->peek(reader)); ! 628: this->state = STATE_HELLO_DONE; ! 629: return NEED_MORE; ! 630: } ! 631: ! 632: /** ! 633: * Process finished message ! 634: */ ! 635: static status_t process_finished(private_tls_peer_t *this, bio_reader_t *reader) ! 636: { ! 637: chunk_t received; ! 638: char buf[12]; ! 639: ! 640: if (!reader->read_data(reader, sizeof(buf), &received)) ! 641: { ! 642: DBG1(DBG_TLS, "received server finished too short"); ! 643: this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); ! 644: return NEED_MORE; ! 645: } ! 646: if (!this->crypto->calculate_finished(this->crypto, "server finished", buf)) ! 647: { ! 648: DBG1(DBG_TLS, "calculating server finished failed"); ! 649: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 650: return NEED_MORE; ! 651: } ! 652: if (!chunk_equals_const(received, chunk_from_thing(buf))) ! 653: { ! 654: DBG1(DBG_TLS, "received server finished invalid"); ! 655: this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR); ! 656: return NEED_MORE; ! 657: } ! 658: this->state = STATE_FINISHED_RECEIVED; ! 659: this->crypto->append_handshake(this->crypto, TLS_FINISHED, received); ! 660: ! 661: return NEED_MORE; ! 662: } ! 663: ! 664: METHOD(tls_handshake_t, process, status_t, ! 665: private_tls_peer_t *this, tls_handshake_type_t type, bio_reader_t *reader) ! 666: { ! 667: tls_handshake_type_t expected; ! 668: ! 669: switch (this->state) ! 670: { ! 671: case STATE_HELLO_SENT: ! 672: if (type == TLS_SERVER_HELLO) ! 673: { ! 674: return process_server_hello(this, reader); ! 675: } ! 676: expected = TLS_SERVER_HELLO; ! 677: break; ! 678: case STATE_HELLO_RECEIVED: ! 679: if (type == TLS_CERTIFICATE) ! 680: { ! 681: return process_certificate(this, reader); ! 682: } ! 683: expected = TLS_CERTIFICATE; ! 684: break; ! 685: case STATE_CERT_RECEIVED: ! 686: if (type == TLS_SERVER_KEY_EXCHANGE) ! 687: { ! 688: return process_key_exchange(this, reader); ! 689: } ! 690: /* fall through since TLS_SERVER_KEY_EXCHANGE is optional */ ! 691: case STATE_KEY_EXCHANGE_RECEIVED: ! 692: if (type == TLS_CERTIFICATE_REQUEST) ! 693: { ! 694: return process_certreq(this, reader); ! 695: } ! 696: /* no cert request, server does not want to authenticate us */ ! 697: DESTROY_IF(this->peer); ! 698: this->peer = NULL; ! 699: /* fall through since TLS_CERTIFICATE_REQUEST is optional */ ! 700: case STATE_CERTREQ_RECEIVED: ! 701: if (type == TLS_SERVER_HELLO_DONE) ! 702: { ! 703: return process_hello_done(this, reader); ! 704: } ! 705: expected = TLS_SERVER_HELLO_DONE; ! 706: break; ! 707: case STATE_CIPHERSPEC_CHANGED_IN: ! 708: if (type == TLS_FINISHED) ! 709: { ! 710: return process_finished(this, reader); ! 711: } ! 712: expected = TLS_FINISHED; ! 713: break; ! 714: default: ! 715: DBG1(DBG_TLS, "TLS %N not expected in current state", ! 716: tls_handshake_type_names, type); ! 717: this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE); ! 718: return NEED_MORE; ! 719: } ! 720: DBG1(DBG_TLS, "TLS %N expected, but received %N", ! 721: tls_handshake_type_names, expected, tls_handshake_type_names, type); ! 722: this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE); ! 723: return NEED_MORE; ! 724: } ! 725: ! 726: /** ! 727: * Send a client hello ! 728: */ ! 729: static status_t send_client_hello(private_tls_peer_t *this, ! 730: tls_handshake_type_t *type, bio_writer_t *writer) ! 731: { ! 732: tls_cipher_suite_t *suites; ! 733: bio_writer_t *extensions, *curves = NULL; ! 734: tls_version_t version; ! 735: tls_named_curve_t curve; ! 736: enumerator_t *enumerator; ! 737: int count, i; ! 738: rng_t *rng; ! 739: ! 740: htoun32(&this->client_random, time(NULL)); ! 741: rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); ! 742: if (!rng || ! 743: !rng->get_bytes(rng, sizeof(this->client_random) - 4, ! 744: this->client_random + 4)) ! 745: { ! 746: DBG1(DBG_TLS, "failed to generate client random"); ! 747: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 748: DESTROY_IF(rng); ! 749: return NEED_MORE; ! 750: } ! 751: rng->destroy(rng); ! 752: ! 753: /* TLS version */ ! 754: version = this->tls->get_version(this->tls); ! 755: this->hello_version = version; ! 756: writer->write_uint16(writer, version); ! 757: writer->write_data(writer, chunk_from_thing(this->client_random)); ! 758: ! 759: /* session identifier */ ! 760: this->session = this->crypto->get_session(this->crypto, this->server); ! 761: writer->write_data8(writer, this->session); ! 762: ! 763: /* add TLS cipher suites */ ! 764: count = this->crypto->get_cipher_suites(this->crypto, &suites); ! 765: writer->write_uint16(writer, count * 2); ! 766: for (i = 0; i < count; i++) ! 767: { ! 768: writer->write_uint16(writer, suites[i]); ! 769: } ! 770: ! 771: /* NULL compression only */ ! 772: writer->write_uint8(writer, 1); ! 773: writer->write_uint8(writer, 0); ! 774: ! 775: extensions = bio_writer_create(32); ! 776: ! 777: extensions->write_uint16(extensions, TLS_EXT_SIGNATURE_ALGORITHMS); ! 778: this->crypto->get_signature_algorithms(this->crypto, extensions); ! 779: ! 780: /* add supported Elliptic Curves, if any */ ! 781: enumerator = this->crypto->create_ec_enumerator(this->crypto); ! 782: while (enumerator->enumerate(enumerator, NULL, &curve)) ! 783: { ! 784: if (!curves) ! 785: { ! 786: extensions->write_uint16(extensions, TLS_EXT_ELLIPTIC_CURVES); ! 787: curves = bio_writer_create(16); ! 788: } ! 789: curves->write_uint16(curves, curve); ! 790: } ! 791: enumerator->destroy(enumerator); ! 792: if (curves) ! 793: { ! 794: curves->wrap16(curves); ! 795: extensions->write_data16(extensions, curves->get_buf(curves)); ! 796: curves->destroy(curves); ! 797: ! 798: /* if we support curves, add point format extension */ ! 799: extensions->write_uint16(extensions, TLS_EXT_EC_POINT_FORMATS); ! 800: extensions->write_uint16(extensions, 2); ! 801: extensions->write_uint8(extensions, 1); ! 802: extensions->write_uint8(extensions, TLS_EC_POINT_UNCOMPRESSED); ! 803: } ! 804: if (this->server->get_type(this->server) == ID_FQDN) ! 805: { ! 806: bio_writer_t *names; ! 807: ! 808: DBG2(DBG_TLS, "sending Server Name Indication for '%Y'", this->server); ! 809: ! 810: names = bio_writer_create(8); ! 811: names->write_uint8(names, TLS_NAME_TYPE_HOST_NAME); ! 812: names->write_data16(names, this->server->get_encoding(this->server)); ! 813: names->wrap16(names); ! 814: extensions->write_uint16(extensions, TLS_EXT_SERVER_NAME); ! 815: extensions->write_data16(extensions, names->get_buf(names)); ! 816: names->destroy(names); ! 817: } ! 818: ! 819: writer->write_data16(writer, extensions->get_buf(extensions)); ! 820: extensions->destroy(extensions); ! 821: ! 822: *type = TLS_CLIENT_HELLO; ! 823: this->state = STATE_HELLO_SENT; ! 824: this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); ! 825: return NEED_MORE; ! 826: } ! 827: ! 828: /** ! 829: * Find a private key suitable to sign Certificate Verify ! 830: */ ! 831: static private_key_t *find_private_key(private_tls_peer_t *this) ! 832: { ! 833: private_key_t *key = NULL; ! 834: bio_reader_t *reader; ! 835: key_type_t type; ! 836: uint8_t cert; ! 837: ! 838: if (!this->peer) ! 839: { ! 840: return NULL; ! 841: } ! 842: reader = bio_reader_create(this->cert_types); ! 843: while (reader->remaining(reader) && reader->read_uint8(reader, &cert)) ! 844: { ! 845: switch (cert) ! 846: { ! 847: case TLS_RSA_SIGN: ! 848: type = KEY_RSA; ! 849: break; ! 850: case TLS_ECDSA_SIGN: ! 851: type = KEY_ECDSA; ! 852: break; ! 853: default: ! 854: continue; ! 855: } ! 856: key = lib->credmgr->get_private(lib->credmgr, type, ! 857: this->peer, this->peer_auth); ! 858: if (key) ! 859: { ! 860: break; ! 861: } ! 862: } ! 863: reader->destroy(reader); ! 864: return key; ! 865: } ! 866: ! 867: /** ! 868: * Send Certificate ! 869: */ ! 870: static status_t send_certificate(private_tls_peer_t *this, ! 871: tls_handshake_type_t *type, bio_writer_t *writer) ! 872: { ! 873: enumerator_t *enumerator; ! 874: certificate_t *cert; ! 875: auth_rule_t rule; ! 876: bio_writer_t *certs; ! 877: chunk_t data; ! 878: ! 879: this->private = find_private_key(this); ! 880: if (!this->private) ! 881: { ! 882: DBG1(DBG_TLS, "no TLS peer certificate found for '%Y', " ! 883: "skipping client authentication", this->peer); ! 884: this->peer->destroy(this->peer); ! 885: this->peer = NULL; ! 886: } ! 887: ! 888: /* generate certificate payload */ ! 889: certs = bio_writer_create(256); ! 890: if (this->peer) ! 891: { ! 892: cert = this->peer_auth->get(this->peer_auth, AUTH_RULE_SUBJECT_CERT); ! 893: if (cert) ! 894: { ! 895: if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) ! 896: { ! 897: DBG1(DBG_TLS, "sending TLS peer certificate '%Y'", ! 898: cert->get_subject(cert)); ! 899: certs->write_data24(certs, data); ! 900: free(data.ptr); ! 901: } ! 902: } ! 903: enumerator = this->peer_auth->create_enumerator(this->peer_auth); ! 904: while (enumerator->enumerate(enumerator, &rule, &cert)) ! 905: { ! 906: if (rule == AUTH_RULE_IM_CERT) ! 907: { ! 908: if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) ! 909: { ! 910: DBG1(DBG_TLS, "sending TLS intermediate certificate '%Y'", ! 911: cert->get_subject(cert)); ! 912: certs->write_data24(certs, data); ! 913: free(data.ptr); ! 914: } ! 915: } ! 916: } ! 917: enumerator->destroy(enumerator); ! 918: } ! 919: ! 920: writer->write_data24(writer, certs->get_buf(certs)); ! 921: certs->destroy(certs); ! 922: ! 923: *type = TLS_CERTIFICATE; ! 924: this->state = STATE_CERT_SENT; ! 925: this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); ! 926: return NEED_MORE; ! 927: } ! 928: ! 929: /** ! 930: * Send client key exchange, using premaster encryption ! 931: */ ! 932: static status_t send_key_exchange_encrypt(private_tls_peer_t *this, ! 933: tls_handshake_type_t *type, bio_writer_t *writer) ! 934: { ! 935: public_key_t *public; ! 936: rng_t *rng; ! 937: char premaster[48]; ! 938: chunk_t encrypted; ! 939: ! 940: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); ! 941: if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2)) ! 942: { ! 943: DBG1(DBG_TLS, "failed to generate TLS premaster secret"); ! 944: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 945: DESTROY_IF(rng); ! 946: return NEED_MORE; ! 947: } ! 948: rng->destroy(rng); ! 949: htoun16(premaster, this->hello_version); ! 950: ! 951: if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster), ! 952: this->session, this->server, ! 953: chunk_from_thing(this->client_random), ! 954: chunk_from_thing(this->server_random))) ! 955: { ! 956: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 957: return NEED_MORE; ! 958: } ! 959: ! 960: public = find_public_key(this); ! 961: if (!public) ! 962: { ! 963: DBG1(DBG_TLS, "no TLS public key found for server '%Y'", this->server); ! 964: this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); ! 965: return NEED_MORE; ! 966: } ! 967: if (!public->encrypt(public, ENCRYPT_RSA_PKCS1, ! 968: chunk_from_thing(premaster), &encrypted)) ! 969: { ! 970: public->destroy(public); ! 971: DBG1(DBG_TLS, "encrypting TLS premaster secret failed"); ! 972: this->alert->add(this->alert, TLS_FATAL, TLS_BAD_CERTIFICATE); ! 973: return NEED_MORE; ! 974: } ! 975: public->destroy(public); ! 976: ! 977: writer->write_data16(writer, encrypted); ! 978: free(encrypted.ptr); ! 979: ! 980: *type = TLS_CLIENT_KEY_EXCHANGE; ! 981: this->state = STATE_KEY_EXCHANGE_SENT; ! 982: this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); ! 983: return NEED_MORE; ! 984: } ! 985: ! 986: /** ! 987: * Send client key exchange, using DHE exchange ! 988: */ ! 989: static status_t send_key_exchange_dhe(private_tls_peer_t *this, ! 990: tls_handshake_type_t *type, bio_writer_t *writer) ! 991: { ! 992: chunk_t premaster, pub; ! 993: ! 994: if (!this->dh->get_shared_secret(this->dh, &premaster)) ! 995: { ! 996: DBG1(DBG_TLS, "calculating premaster from DH failed"); ! 997: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 998: return NEED_MORE; ! 999: } ! 1000: if (!this->crypto->derive_secrets(this->crypto, premaster, ! 1001: this->session, this->server, ! 1002: chunk_from_thing(this->client_random), ! 1003: chunk_from_thing(this->server_random))) ! 1004: { ! 1005: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 1006: chunk_clear(&premaster); ! 1007: return NEED_MORE; ! 1008: } ! 1009: chunk_clear(&premaster); ! 1010: ! 1011: if (!this->dh->get_my_public_value(this->dh, &pub)) ! 1012: { ! 1013: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 1014: return NEED_MORE; ! 1015: } ! 1016: if (this->dh->get_dh_group(this->dh) == MODP_CUSTOM) ! 1017: { ! 1018: writer->write_data16(writer, pub); ! 1019: } ! 1020: else ! 1021: { /* ECP uses 8bit length header only, but a point format */ ! 1022: writer->write_uint8(writer, pub.len + 1); ! 1023: writer->write_uint8(writer, TLS_ANSI_UNCOMPRESSED); ! 1024: writer->write_data(writer, pub); ! 1025: } ! 1026: free(pub.ptr); ! 1027: ! 1028: *type = TLS_CLIENT_KEY_EXCHANGE; ! 1029: this->state = STATE_KEY_EXCHANGE_SENT; ! 1030: this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); ! 1031: return NEED_MORE; ! 1032: } ! 1033: ! 1034: /** ! 1035: * Send client key exchange, depending on suite ! 1036: */ ! 1037: static status_t send_key_exchange(private_tls_peer_t *this, ! 1038: tls_handshake_type_t *type, bio_writer_t *writer) ! 1039: { ! 1040: if (this->dh) ! 1041: { ! 1042: return send_key_exchange_dhe(this, type, writer); ! 1043: } ! 1044: return send_key_exchange_encrypt(this, type, writer); ! 1045: } ! 1046: ! 1047: /** ! 1048: * Send certificate verify ! 1049: */ ! 1050: static status_t send_certificate_verify(private_tls_peer_t *this, ! 1051: tls_handshake_type_t *type, bio_writer_t *writer) ! 1052: { ! 1053: if (!this->private || ! 1054: !this->crypto->sign_handshake(this->crypto, this->private, ! 1055: writer, this->hashsig)) ! 1056: { ! 1057: DBG1(DBG_TLS, "creating TLS Certificate Verify signature failed"); ! 1058: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 1059: return NEED_MORE; ! 1060: } ! 1061: ! 1062: *type = TLS_CERTIFICATE_VERIFY; ! 1063: this->state = STATE_VERIFY_SENT; ! 1064: this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); ! 1065: return NEED_MORE; ! 1066: } ! 1067: ! 1068: /** ! 1069: * Send Finished ! 1070: */ ! 1071: static status_t send_finished(private_tls_peer_t *this, ! 1072: tls_handshake_type_t *type, bio_writer_t *writer) ! 1073: { ! 1074: char buf[12]; ! 1075: ! 1076: if (!this->crypto->calculate_finished(this->crypto, "client finished", buf)) ! 1077: { ! 1078: DBG1(DBG_TLS, "calculating client finished data failed"); ! 1079: this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); ! 1080: return NEED_MORE; ! 1081: } ! 1082: ! 1083: writer->write_data(writer, chunk_from_thing(buf)); ! 1084: ! 1085: *type = TLS_FINISHED; ! 1086: this->state = STATE_FINISHED_SENT; ! 1087: this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); ! 1088: return NEED_MORE; ! 1089: } ! 1090: ! 1091: METHOD(tls_handshake_t, build, status_t, ! 1092: private_tls_peer_t *this, tls_handshake_type_t *type, bio_writer_t *writer) ! 1093: { ! 1094: switch (this->state) ! 1095: { ! 1096: case STATE_INIT: ! 1097: return send_client_hello(this, type, writer); ! 1098: case STATE_HELLO_DONE: ! 1099: if (this->peer) ! 1100: { ! 1101: return send_certificate(this, type, writer); ! 1102: } ! 1103: /* otherwise fall through to next state */ ! 1104: case STATE_CERT_SENT: ! 1105: return send_key_exchange(this, type, writer); ! 1106: case STATE_KEY_EXCHANGE_SENT: ! 1107: if (this->peer) ! 1108: { ! 1109: return send_certificate_verify(this, type, writer); ! 1110: } ! 1111: else ! 1112: { ! 1113: return INVALID_STATE; ! 1114: } ! 1115: case STATE_CIPHERSPEC_CHANGED_OUT: ! 1116: return send_finished(this, type, writer); ! 1117: default: ! 1118: return INVALID_STATE; ! 1119: } ! 1120: } ! 1121: ! 1122: METHOD(tls_handshake_t, cipherspec_changed, bool, ! 1123: private_tls_peer_t *this, bool inbound) ! 1124: { ! 1125: if (inbound) ! 1126: { ! 1127: if (this->resume) ! 1128: { ! 1129: return this->state == STATE_HELLO_RECEIVED; ! 1130: } ! 1131: return this->state == STATE_FINISHED_SENT; ! 1132: } ! 1133: else ! 1134: { ! 1135: if (this->resume) ! 1136: { ! 1137: return this->state == STATE_FINISHED_RECEIVED; ! 1138: } ! 1139: if (this->peer) ! 1140: { ! 1141: return this->state == STATE_VERIFY_SENT; ! 1142: } ! 1143: return this->state == STATE_KEY_EXCHANGE_SENT; ! 1144: } ! 1145: } ! 1146: ! 1147: METHOD(tls_handshake_t, change_cipherspec, void, ! 1148: private_tls_peer_t *this, bool inbound) ! 1149: { ! 1150: this->crypto->change_cipher(this->crypto, inbound); ! 1151: if (inbound) ! 1152: { ! 1153: this->state = STATE_CIPHERSPEC_CHANGED_IN; ! 1154: } ! 1155: else ! 1156: { ! 1157: this->state = STATE_CIPHERSPEC_CHANGED_OUT; ! 1158: } ! 1159: } ! 1160: ! 1161: METHOD(tls_handshake_t, finished, bool, ! 1162: private_tls_peer_t *this) ! 1163: { ! 1164: if (this->resume) ! 1165: { ! 1166: return this->state == STATE_FINISHED_SENT; ! 1167: } ! 1168: return this->state == STATE_FINISHED_RECEIVED; ! 1169: } ! 1170: ! 1171: METHOD(tls_handshake_t, get_peer_id, identification_t*, ! 1172: private_tls_peer_t *this) ! 1173: { ! 1174: return this->peer; ! 1175: } ! 1176: ! 1177: METHOD(tls_handshake_t, get_server_id, identification_t*, ! 1178: private_tls_peer_t *this) ! 1179: { ! 1180: return this->server; ! 1181: } ! 1182: ! 1183: METHOD(tls_handshake_t, get_auth, auth_cfg_t*, ! 1184: private_tls_peer_t *this) ! 1185: { ! 1186: return this->server_auth; ! 1187: } ! 1188: ! 1189: METHOD(tls_handshake_t, destroy, void, ! 1190: private_tls_peer_t *this) ! 1191: { ! 1192: DESTROY_IF(this->private); ! 1193: DESTROY_IF(this->dh); ! 1194: DESTROY_IF(this->peer); ! 1195: this->server->destroy(this->server); ! 1196: this->peer_auth->destroy(this->peer_auth); ! 1197: this->server_auth->destroy(this->server_auth); ! 1198: free(this->hashsig.ptr); ! 1199: free(this->cert_types.ptr); ! 1200: free(this->session.ptr); ! 1201: free(this); ! 1202: } ! 1203: ! 1204: /** ! 1205: * See header ! 1206: */ ! 1207: tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert, ! 1208: identification_t *peer, identification_t *server) ! 1209: { ! 1210: private_tls_peer_t *this; ! 1211: ! 1212: INIT(this, ! 1213: .public = { ! 1214: .handshake = { ! 1215: .process = _process, ! 1216: .build = _build, ! 1217: .cipherspec_changed = _cipherspec_changed, ! 1218: .change_cipherspec = _change_cipherspec, ! 1219: .finished = _finished, ! 1220: .get_peer_id = _get_peer_id, ! 1221: .get_server_id = _get_server_id, ! 1222: .get_auth = _get_auth, ! 1223: .destroy = _destroy, ! 1224: }, ! 1225: }, ! 1226: .state = STATE_INIT, ! 1227: .tls = tls, ! 1228: .crypto = crypto, ! 1229: .alert = alert, ! 1230: .peer = peer ? peer->clone(peer) : NULL, ! 1231: .server = server->clone(server), ! 1232: .peer_auth = auth_cfg_create(), ! 1233: .server_auth = auth_cfg_create(), ! 1234: ); ! 1235: ! 1236: return &this->public; ! 1237: }