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