|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2007 Michael Brown <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: /** ! 22: * @file ! 23: * ! 24: * Transport Layer Security Protocol ! 25: */ ! 26: ! 27: #include <stdint.h> ! 28: #include <stdlib.h> ! 29: #include <stdarg.h> ! 30: #include <string.h> ! 31: #include <errno.h> ! 32: #include <byteswap.h> ! 33: #include <ipxe/hmac.h> ! 34: #include <ipxe/md5.h> ! 35: #include <ipxe/sha1.h> ! 36: #include <ipxe/aes.h> ! 37: #include <ipxe/rsa.h> ! 38: #include <ipxe/iobuf.h> ! 39: #include <ipxe/xfer.h> ! 40: #include <ipxe/open.h> ! 41: #include <ipxe/asn1.h> ! 42: #include <ipxe/x509.h> ! 43: #include <ipxe/tls.h> ! 44: ! 45: static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, ! 46: const void *data, size_t len ); ! 47: static void tls_clear_cipher ( struct tls_session *tls, ! 48: struct tls_cipherspec *cipherspec ); ! 49: ! 50: /****************************************************************************** ! 51: * ! 52: * Utility functions ! 53: * ! 54: ****************************************************************************** ! 55: */ ! 56: ! 57: /** ! 58: * Extract 24-bit field value ! 59: * ! 60: * @v field24 24-bit field ! 61: * @ret value Field value ! 62: * ! 63: * TLS uses 24-bit integers in several places, which are awkward to ! 64: * parse in C. ! 65: */ ! 66: static unsigned long tls_uint24 ( uint8_t field24[3] ) { ! 67: return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] ); ! 68: } ! 69: ! 70: /****************************************************************************** ! 71: * ! 72: * Cleanup functions ! 73: * ! 74: ****************************************************************************** ! 75: */ ! 76: ! 77: /** ! 78: * Free TLS session ! 79: * ! 80: * @v refcnt Reference counter ! 81: */ ! 82: static void free_tls ( struct refcnt *refcnt ) { ! 83: struct tls_session *tls = ! 84: container_of ( refcnt, struct tls_session, refcnt ); ! 85: ! 86: /* Free dynamically-allocated resources */ ! 87: tls_clear_cipher ( tls, &tls->tx_cipherspec ); ! 88: tls_clear_cipher ( tls, &tls->tx_cipherspec_pending ); ! 89: tls_clear_cipher ( tls, &tls->rx_cipherspec ); ! 90: tls_clear_cipher ( tls, &tls->rx_cipherspec_pending ); ! 91: x509_free_rsa_public_key ( &tls->rsa ); ! 92: free ( tls->rx_data ); ! 93: ! 94: /* Free TLS structure itself */ ! 95: free ( tls ); ! 96: } ! 97: ! 98: /** ! 99: * Finish with TLS session ! 100: * ! 101: * @v tls TLS session ! 102: * @v rc Status code ! 103: */ ! 104: static void tls_close ( struct tls_session *tls, int rc ) { ! 105: ! 106: /* Remove process */ ! 107: process_del ( &tls->process ); ! 108: ! 109: /* Close ciphertext and plaintext streams */ ! 110: intf_shutdown ( &tls->cipherstream, rc ); ! 111: intf_shutdown ( &tls->plainstream, rc ); ! 112: } ! 113: ! 114: /****************************************************************************** ! 115: * ! 116: * Random number generation ! 117: * ! 118: ****************************************************************************** ! 119: */ ! 120: ! 121: /** ! 122: * Generate random data ! 123: * ! 124: * @v data Buffer to fill ! 125: * @v len Length of buffer ! 126: */ ! 127: static void tls_generate_random ( void *data, size_t len ) { ! 128: /* FIXME: Some real random data source would be nice... */ ! 129: memset ( data, 0x01, len ); ! 130: } ! 131: ! 132: /** ! 133: * Update HMAC with a list of ( data, len ) pairs ! 134: * ! 135: * @v digest Hash function to use ! 136: * @v digest_ctx Digest context ! 137: * @v args ( data, len ) pairs of data, terminated by NULL ! 138: */ ! 139: static void tls_hmac_update_va ( struct digest_algorithm *digest, ! 140: void *digest_ctx, va_list args ) { ! 141: void *data; ! 142: size_t len; ! 143: ! 144: while ( ( data = va_arg ( args, void * ) ) ) { ! 145: len = va_arg ( args, size_t ); ! 146: hmac_update ( digest, digest_ctx, data, len ); ! 147: } ! 148: } ! 149: ! 150: /** ! 151: * Generate secure pseudo-random data using a single hash function ! 152: * ! 153: * @v tls TLS session ! 154: * @v digest Hash function to use ! 155: * @v secret Secret ! 156: * @v secret_len Length of secret ! 157: * @v out Output buffer ! 158: * @v out_len Length of output buffer ! 159: * @v seeds ( data, len ) pairs of seed data, terminated by NULL ! 160: */ ! 161: static void tls_p_hash_va ( struct tls_session *tls, ! 162: struct digest_algorithm *digest, ! 163: void *secret, size_t secret_len, ! 164: void *out, size_t out_len, ! 165: va_list seeds ) { ! 166: uint8_t secret_copy[secret_len]; ! 167: uint8_t digest_ctx[digest->ctxsize]; ! 168: uint8_t digest_ctx_partial[digest->ctxsize]; ! 169: uint8_t a[digest->digestsize]; ! 170: uint8_t out_tmp[digest->digestsize]; ! 171: size_t frag_len = digest->digestsize; ! 172: va_list tmp; ! 173: ! 174: /* Copy the secret, in case HMAC modifies it */ ! 175: memcpy ( secret_copy, secret, secret_len ); ! 176: secret = secret_copy; ! 177: DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name ); ! 178: DBGC2_HD ( tls, secret, secret_len ); ! 179: ! 180: /* Calculate A(1) */ ! 181: hmac_init ( digest, digest_ctx, secret, &secret_len ); ! 182: va_copy ( tmp, seeds ); ! 183: tls_hmac_update_va ( digest, digest_ctx, tmp ); ! 184: va_end ( tmp ); ! 185: hmac_final ( digest, digest_ctx, secret, &secret_len, a ); ! 186: DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name ); ! 187: DBGC2_HD ( tls, &a, sizeof ( a ) ); ! 188: ! 189: /* Generate as much data as required */ ! 190: while ( out_len ) { ! 191: /* Calculate output portion */ ! 192: hmac_init ( digest, digest_ctx, secret, &secret_len ); ! 193: hmac_update ( digest, digest_ctx, a, sizeof ( a ) ); ! 194: memcpy ( digest_ctx_partial, digest_ctx, digest->ctxsize ); ! 195: va_copy ( tmp, seeds ); ! 196: tls_hmac_update_va ( digest, digest_ctx, tmp ); ! 197: va_end ( tmp ); ! 198: hmac_final ( digest, digest_ctx, ! 199: secret, &secret_len, out_tmp ); ! 200: ! 201: /* Copy output */ ! 202: if ( frag_len > out_len ) ! 203: frag_len = out_len; ! 204: memcpy ( out, out_tmp, frag_len ); ! 205: DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name ); ! 206: DBGC2_HD ( tls, out, frag_len ); ! 207: ! 208: /* Calculate A(i) */ ! 209: hmac_final ( digest, digest_ctx_partial, ! 210: secret, &secret_len, a ); ! 211: DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name ); ! 212: DBGC2_HD ( tls, &a, sizeof ( a ) ); ! 213: ! 214: out += frag_len; ! 215: out_len -= frag_len; ! 216: } ! 217: } ! 218: ! 219: /** ! 220: * Generate secure pseudo-random data ! 221: * ! 222: * @v tls TLS session ! 223: * @v secret Secret ! 224: * @v secret_len Length of secret ! 225: * @v out Output buffer ! 226: * @v out_len Length of output buffer ! 227: * @v ... ( data, len ) pairs of seed data, terminated by NULL ! 228: */ ! 229: static void tls_prf ( struct tls_session *tls, void *secret, size_t secret_len, ! 230: void *out, size_t out_len, ... ) { ! 231: va_list seeds; ! 232: va_list tmp; ! 233: size_t subsecret_len; ! 234: void *md5_secret; ! 235: void *sha1_secret; ! 236: uint8_t out_md5[out_len]; ! 237: uint8_t out_sha1[out_len]; ! 238: unsigned int i; ! 239: ! 240: va_start ( seeds, out_len ); ! 241: ! 242: /* Split secret into two, with an overlap of up to one byte */ ! 243: subsecret_len = ( ( secret_len + 1 ) / 2 ); ! 244: md5_secret = secret; ! 245: sha1_secret = ( secret + secret_len - subsecret_len ); ! 246: ! 247: /* Calculate MD5 portion */ ! 248: va_copy ( tmp, seeds ); ! 249: tls_p_hash_va ( tls, &md5_algorithm, md5_secret, subsecret_len, ! 250: out_md5, out_len, seeds ); ! 251: va_end ( tmp ); ! 252: ! 253: /* Calculate SHA1 portion */ ! 254: va_copy ( tmp, seeds ); ! 255: tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret, subsecret_len, ! 256: out_sha1, out_len, seeds ); ! 257: va_end ( tmp ); ! 258: ! 259: /* XOR the two portions together into the final output buffer */ ! 260: for ( i = 0 ; i < out_len ; i++ ) { ! 261: *( ( uint8_t * ) out + i ) = ( out_md5[i] ^ out_sha1[i] ); ! 262: } ! 263: ! 264: va_end ( seeds ); ! 265: } ! 266: ! 267: /** ! 268: * Generate secure pseudo-random data ! 269: * ! 270: * @v secret Secret ! 271: * @v secret_len Length of secret ! 272: * @v out Output buffer ! 273: * @v out_len Length of output buffer ! 274: * @v label String literal label ! 275: * @v ... ( data, len ) pairs of seed data ! 276: */ ! 277: #define tls_prf_label( tls, secret, secret_len, out, out_len, label, ... ) \ ! 278: tls_prf ( (tls), (secret), (secret_len), (out), (out_len), \ ! 279: label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL ) ! 280: ! 281: /****************************************************************************** ! 282: * ! 283: * Secret management ! 284: * ! 285: ****************************************************************************** ! 286: */ ! 287: ! 288: /** ! 289: * Generate master secret ! 290: * ! 291: * @v tls TLS session ! 292: * ! 293: * The pre-master secret and the client and server random values must ! 294: * already be known. ! 295: */ ! 296: static void tls_generate_master_secret ( struct tls_session *tls ) { ! 297: DBGC ( tls, "TLS %p pre-master-secret:\n", tls ); ! 298: DBGC_HD ( tls, &tls->pre_master_secret, ! 299: sizeof ( tls->pre_master_secret ) ); ! 300: DBGC ( tls, "TLS %p client random bytes:\n", tls ); ! 301: DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) ); ! 302: DBGC ( tls, "TLS %p server random bytes:\n", tls ); ! 303: DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) ); ! 304: ! 305: tls_prf_label ( tls, &tls->pre_master_secret, ! 306: sizeof ( tls->pre_master_secret ), ! 307: &tls->master_secret, sizeof ( tls->master_secret ), ! 308: "master secret", ! 309: &tls->client_random, sizeof ( tls->client_random ), ! 310: &tls->server_random, sizeof ( tls->server_random ) ); ! 311: ! 312: DBGC ( tls, "TLS %p generated master secret:\n", tls ); ! 313: DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) ); ! 314: } ! 315: ! 316: /** ! 317: * Generate key material ! 318: * ! 319: * @v tls TLS session ! 320: * ! 321: * The master secret must already be known. ! 322: */ ! 323: static int tls_generate_keys ( struct tls_session *tls ) { ! 324: struct tls_cipherspec *tx_cipherspec = &tls->tx_cipherspec_pending; ! 325: struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending; ! 326: size_t hash_size = tx_cipherspec->digest->digestsize; ! 327: size_t key_size = tx_cipherspec->key_len; ! 328: size_t iv_size = tx_cipherspec->cipher->blocksize; ! 329: size_t total = ( 2 * ( hash_size + key_size + iv_size ) ); ! 330: uint8_t key_block[total]; ! 331: uint8_t *key; ! 332: int rc; ! 333: ! 334: /* Generate key block */ ! 335: tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ), ! 336: key_block, sizeof ( key_block ), "key expansion", ! 337: &tls->server_random, sizeof ( tls->server_random ), ! 338: &tls->client_random, sizeof ( tls->client_random ) ); ! 339: ! 340: /* Split key block into portions */ ! 341: key = key_block; ! 342: ! 343: /* TX MAC secret */ ! 344: memcpy ( tx_cipherspec->mac_secret, key, hash_size ); ! 345: DBGC ( tls, "TLS %p TX MAC secret:\n", tls ); ! 346: DBGC_HD ( tls, key, hash_size ); ! 347: key += hash_size; ! 348: ! 349: /* RX MAC secret */ ! 350: memcpy ( rx_cipherspec->mac_secret, key, hash_size ); ! 351: DBGC ( tls, "TLS %p RX MAC secret:\n", tls ); ! 352: DBGC_HD ( tls, key, hash_size ); ! 353: key += hash_size; ! 354: ! 355: /* TX key */ ! 356: if ( ( rc = cipher_setkey ( tx_cipherspec->cipher, ! 357: tx_cipherspec->cipher_ctx, ! 358: key, key_size ) ) != 0 ) { ! 359: DBGC ( tls, "TLS %p could not set TX key: %s\n", ! 360: tls, strerror ( rc ) ); ! 361: return rc; ! 362: } ! 363: DBGC ( tls, "TLS %p TX key:\n", tls ); ! 364: DBGC_HD ( tls, key, key_size ); ! 365: key += key_size; ! 366: ! 367: /* RX key */ ! 368: if ( ( rc = cipher_setkey ( rx_cipherspec->cipher, ! 369: rx_cipherspec->cipher_ctx, ! 370: key, key_size ) ) != 0 ) { ! 371: DBGC ( tls, "TLS %p could not set TX key: %s\n", ! 372: tls, strerror ( rc ) ); ! 373: return rc; ! 374: } ! 375: DBGC ( tls, "TLS %p RX key:\n", tls ); ! 376: DBGC_HD ( tls, key, key_size ); ! 377: key += key_size; ! 378: ! 379: /* TX initialisation vector */ ! 380: cipher_setiv ( tx_cipherspec->cipher, tx_cipherspec->cipher_ctx, key ); ! 381: DBGC ( tls, "TLS %p TX IV:\n", tls ); ! 382: DBGC_HD ( tls, key, iv_size ); ! 383: key += iv_size; ! 384: ! 385: /* RX initialisation vector */ ! 386: cipher_setiv ( rx_cipherspec->cipher, rx_cipherspec->cipher_ctx, key ); ! 387: DBGC ( tls, "TLS %p RX IV:\n", tls ); ! 388: DBGC_HD ( tls, key, iv_size ); ! 389: key += iv_size; ! 390: ! 391: assert ( ( key_block + total ) == key ); ! 392: ! 393: return 0; ! 394: } ! 395: ! 396: /****************************************************************************** ! 397: * ! 398: * Cipher suite management ! 399: * ! 400: ****************************************************************************** ! 401: */ ! 402: ! 403: /** ! 404: * Clear cipher suite ! 405: * ! 406: * @v cipherspec TLS cipher specification ! 407: */ ! 408: static void tls_clear_cipher ( struct tls_session *tls __unused, ! 409: struct tls_cipherspec *cipherspec ) { ! 410: free ( cipherspec->dynamic ); ! 411: memset ( cipherspec, 0, sizeof ( cipherspec ) ); ! 412: cipherspec->pubkey = &pubkey_null; ! 413: cipherspec->cipher = &cipher_null; ! 414: cipherspec->digest = &digest_null; ! 415: } ! 416: ! 417: /** ! 418: * Set cipher suite ! 419: * ! 420: * @v tls TLS session ! 421: * @v cipherspec TLS cipher specification ! 422: * @v pubkey Public-key encryption elgorithm ! 423: * @v cipher Bulk encryption cipher algorithm ! 424: * @v digest MAC digest algorithm ! 425: * @v key_len Key length ! 426: * @ret rc Return status code ! 427: */ ! 428: static int tls_set_cipher ( struct tls_session *tls, ! 429: struct tls_cipherspec *cipherspec, ! 430: struct pubkey_algorithm *pubkey, ! 431: struct cipher_algorithm *cipher, ! 432: struct digest_algorithm *digest, ! 433: size_t key_len ) { ! 434: size_t total; ! 435: void *dynamic; ! 436: ! 437: /* Clear out old cipher contents, if any */ ! 438: tls_clear_cipher ( tls, cipherspec ); ! 439: ! 440: /* Allocate dynamic storage */ ! 441: total = ( pubkey->ctxsize + 2 * cipher->ctxsize + digest->digestsize ); ! 442: dynamic = malloc ( total ); ! 443: if ( ! dynamic ) { ! 444: DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto " ! 445: "context\n", tls, total ); ! 446: return -ENOMEM; ! 447: } ! 448: memset ( dynamic, 0, total ); ! 449: ! 450: /* Assign storage */ ! 451: cipherspec->dynamic = dynamic; ! 452: cipherspec->pubkey_ctx = dynamic; dynamic += pubkey->ctxsize; ! 453: cipherspec->cipher_ctx = dynamic; dynamic += cipher->ctxsize; ! 454: cipherspec->cipher_next_ctx = dynamic; dynamic += cipher->ctxsize; ! 455: cipherspec->mac_secret = dynamic; dynamic += digest->digestsize; ! 456: assert ( ( cipherspec->dynamic + total ) == dynamic ); ! 457: ! 458: /* Store parameters */ ! 459: cipherspec->pubkey = pubkey; ! 460: cipherspec->cipher = cipher; ! 461: cipherspec->digest = digest; ! 462: cipherspec->key_len = key_len; ! 463: ! 464: return 0; ! 465: } ! 466: ! 467: /** ! 468: * Select next cipher suite ! 469: * ! 470: * @v tls TLS session ! 471: * @v cipher_suite Cipher suite specification ! 472: * @ret rc Return status code ! 473: */ ! 474: static int tls_select_cipher ( struct tls_session *tls, ! 475: unsigned int cipher_suite ) { ! 476: struct pubkey_algorithm *pubkey = &pubkey_null; ! 477: struct cipher_algorithm *cipher = &cipher_null; ! 478: struct digest_algorithm *digest = &digest_null; ! 479: unsigned int key_len = 0; ! 480: int rc; ! 481: ! 482: switch ( cipher_suite ) { ! 483: case htons ( TLS_RSA_WITH_AES_128_CBC_SHA ): ! 484: key_len = ( 128 / 8 ); ! 485: cipher = &aes_cbc_algorithm; ! 486: digest = &sha1_algorithm; ! 487: break; ! 488: case htons ( TLS_RSA_WITH_AES_256_CBC_SHA ): ! 489: key_len = ( 256 / 8 ); ! 490: cipher = &aes_cbc_algorithm; ! 491: digest = &sha1_algorithm; ! 492: break; ! 493: default: ! 494: DBGC ( tls, "TLS %p does not support cipher %04x\n", ! 495: tls, ntohs ( cipher_suite ) ); ! 496: return -ENOTSUP; ! 497: } ! 498: ! 499: /* Set ciphers */ ! 500: if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending, pubkey, ! 501: cipher, digest, key_len ) ) != 0 ) ! 502: return rc; ! 503: if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending, pubkey, ! 504: cipher, digest, key_len ) ) != 0 ) ! 505: return rc; ! 506: ! 507: DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls, ! 508: pubkey->name, cipher->name, ( key_len * 8 ), digest->name ); ! 509: ! 510: return 0; ! 511: } ! 512: ! 513: /** ! 514: * Activate next cipher suite ! 515: * ! 516: * @v tls TLS session ! 517: * @v pending Pending cipher specification ! 518: * @v active Active cipher specification to replace ! 519: * @ret rc Return status code ! 520: */ ! 521: static int tls_change_cipher ( struct tls_session *tls, ! 522: struct tls_cipherspec *pending, ! 523: struct tls_cipherspec *active ) { ! 524: ! 525: /* Sanity check */ ! 526: if ( /* FIXME (when pubkey is not hard-coded to RSA): ! 527: * ( pending->pubkey == &pubkey_null ) || */ ! 528: ( pending->cipher == &cipher_null ) || ! 529: ( pending->digest == &digest_null ) ) { ! 530: DBGC ( tls, "TLS %p refusing to use null cipher\n", tls ); ! 531: return -ENOTSUP; ! 532: } ! 533: ! 534: tls_clear_cipher ( tls, active ); ! 535: memswap ( active, pending, sizeof ( *active ) ); ! 536: return 0; ! 537: } ! 538: ! 539: /****************************************************************************** ! 540: * ! 541: * Handshake verification ! 542: * ! 543: ****************************************************************************** ! 544: */ ! 545: ! 546: /** ! 547: * Add handshake record to verification hash ! 548: * ! 549: * @v tls TLS session ! 550: * @v data Handshake record ! 551: * @v len Length of handshake record ! 552: */ ! 553: static void tls_add_handshake ( struct tls_session *tls, ! 554: const void *data, size_t len ) { ! 555: ! 556: digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len ); ! 557: digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len ); ! 558: } ! 559: ! 560: /** ! 561: * Calculate handshake verification hash ! 562: * ! 563: * @v tls TLS session ! 564: * @v out Output buffer ! 565: * ! 566: * Calculates the MD5+SHA1 digest over all handshake messages seen so ! 567: * far. ! 568: */ ! 569: static void tls_verify_handshake ( struct tls_session *tls, void *out ) { ! 570: struct digest_algorithm *md5 = &md5_algorithm; ! 571: struct digest_algorithm *sha1 = &sha1_algorithm; ! 572: uint8_t md5_ctx[md5->ctxsize]; ! 573: uint8_t sha1_ctx[sha1->ctxsize]; ! 574: void *md5_digest = out; ! 575: void *sha1_digest = ( out + md5->digestsize ); ! 576: ! 577: memcpy ( md5_ctx, tls->handshake_md5_ctx, sizeof ( md5_ctx ) ); ! 578: memcpy ( sha1_ctx, tls->handshake_sha1_ctx, sizeof ( sha1_ctx ) ); ! 579: digest_final ( md5, md5_ctx, md5_digest ); ! 580: digest_final ( sha1, sha1_ctx, sha1_digest ); ! 581: } ! 582: ! 583: /****************************************************************************** ! 584: * ! 585: * Record handling ! 586: * ! 587: ****************************************************************************** ! 588: */ ! 589: ! 590: /** ! 591: * Transmit Handshake record ! 592: * ! 593: * @v tls TLS session ! 594: * @v data Plaintext record ! 595: * @v len Length of plaintext record ! 596: * @ret rc Return status code ! 597: */ ! 598: static int tls_send_handshake ( struct tls_session *tls, ! 599: void *data, size_t len ) { ! 600: ! 601: /* Add to handshake digest */ ! 602: tls_add_handshake ( tls, data, len ); ! 603: ! 604: /* Send record */ ! 605: return tls_send_plaintext ( tls, TLS_TYPE_HANDSHAKE, data, len ); ! 606: } ! 607: ! 608: /** ! 609: * Transmit Client Hello record ! 610: * ! 611: * @v tls TLS session ! 612: * @ret rc Return status code ! 613: */ ! 614: static int tls_send_client_hello ( struct tls_session *tls ) { ! 615: struct { ! 616: uint32_t type_length; ! 617: uint16_t version; ! 618: uint8_t random[32]; ! 619: uint8_t session_id_len; ! 620: uint16_t cipher_suite_len; ! 621: uint16_t cipher_suites[2]; ! 622: uint8_t compression_methods_len; ! 623: uint8_t compression_methods[1]; ! 624: } __attribute__ (( packed )) hello; ! 625: ! 626: memset ( &hello, 0, sizeof ( hello ) ); ! 627: hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) | ! 628: htonl ( sizeof ( hello ) - ! 629: sizeof ( hello.type_length ) ) ); ! 630: hello.version = htons ( TLS_VERSION_TLS_1_0 ); ! 631: memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) ); ! 632: hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) ); ! 633: hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ); ! 634: hello.cipher_suites[1] = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ); ! 635: hello.compression_methods_len = sizeof ( hello.compression_methods ); ! 636: ! 637: return tls_send_handshake ( tls, &hello, sizeof ( hello ) ); ! 638: } ! 639: ! 640: /** ! 641: * Transmit Client Key Exchange record ! 642: * ! 643: * @v tls TLS session ! 644: * @ret rc Return status code ! 645: */ ! 646: static int tls_send_client_key_exchange ( struct tls_session *tls ) { ! 647: /* FIXME: Hack alert */ ! 648: RSA_CTX *rsa_ctx; ! 649: RSA_pub_key_new ( &rsa_ctx, tls->rsa.modulus, tls->rsa.modulus_len, ! 650: tls->rsa.exponent, tls->rsa.exponent_len ); ! 651: struct { ! 652: uint32_t type_length; ! 653: uint16_t encrypted_pre_master_secret_len; ! 654: uint8_t encrypted_pre_master_secret[rsa_ctx->num_octets]; ! 655: } __attribute__ (( packed )) key_xchg; ! 656: ! 657: memset ( &key_xchg, 0, sizeof ( key_xchg ) ); ! 658: key_xchg.type_length = ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) | ! 659: htonl ( sizeof ( key_xchg ) - ! 660: sizeof ( key_xchg.type_length ) ) ); ! 661: key_xchg.encrypted_pre_master_secret_len ! 662: = htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) ); ! 663: ! 664: /* FIXME: Hack alert */ ! 665: DBGC ( tls, "RSA encrypting plaintext, modulus, exponent:\n" ); ! 666: DBGC_HD ( tls, &tls->pre_master_secret, ! 667: sizeof ( tls->pre_master_secret ) ); ! 668: DBGC_HD ( tls, tls->rsa.modulus, tls->rsa.modulus_len ); ! 669: DBGC_HD ( tls, tls->rsa.exponent, tls->rsa.exponent_len ); ! 670: RSA_encrypt ( rsa_ctx, ( const uint8_t * ) &tls->pre_master_secret, ! 671: sizeof ( tls->pre_master_secret ), ! 672: key_xchg.encrypted_pre_master_secret, 0 ); ! 673: DBGC ( tls, "RSA encrypt done. Ciphertext:\n" ); ! 674: DBGC_HD ( tls, &key_xchg.encrypted_pre_master_secret, ! 675: sizeof ( key_xchg.encrypted_pre_master_secret ) ); ! 676: RSA_free ( rsa_ctx ); ! 677: ! 678: ! 679: return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) ); ! 680: } ! 681: ! 682: /** ! 683: * Transmit Change Cipher record ! 684: * ! 685: * @v tls TLS session ! 686: * @ret rc Return status code ! 687: */ ! 688: static int tls_send_change_cipher ( struct tls_session *tls ) { ! 689: static const uint8_t change_cipher[1] = { 1 }; ! 690: return tls_send_plaintext ( tls, TLS_TYPE_CHANGE_CIPHER, ! 691: change_cipher, sizeof ( change_cipher ) ); ! 692: } ! 693: ! 694: /** ! 695: * Transmit Finished record ! 696: * ! 697: * @v tls TLS session ! 698: * @ret rc Return status code ! 699: */ ! 700: static int tls_send_finished ( struct tls_session *tls ) { ! 701: struct { ! 702: uint32_t type_length; ! 703: uint8_t verify_data[12]; ! 704: } __attribute__ (( packed )) finished; ! 705: uint8_t digest[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE]; ! 706: ! 707: memset ( &finished, 0, sizeof ( finished ) ); ! 708: finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) | ! 709: htonl ( sizeof ( finished ) - ! 710: sizeof ( finished.type_length ) ) ); ! 711: tls_verify_handshake ( tls, digest ); ! 712: tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ), ! 713: finished.verify_data, sizeof ( finished.verify_data ), ! 714: "client finished", digest, sizeof ( digest ) ); ! 715: ! 716: return tls_send_handshake ( tls, &finished, sizeof ( finished ) ); ! 717: } ! 718: ! 719: /** ! 720: * Receive new Change Cipher record ! 721: * ! 722: * @v tls TLS session ! 723: * @v data Plaintext record ! 724: * @v len Length of plaintext record ! 725: * @ret rc Return status code ! 726: */ ! 727: static int tls_new_change_cipher ( struct tls_session *tls, ! 728: void *data, size_t len ) { ! 729: int rc; ! 730: ! 731: if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) { ! 732: DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls ); ! 733: DBGC_HD ( tls, data, len ); ! 734: return -EINVAL; ! 735: } ! 736: ! 737: if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending, ! 738: &tls->rx_cipherspec ) ) != 0 ) { ! 739: DBGC ( tls, "TLS %p could not activate RX cipher: %s\n", ! 740: tls, strerror ( rc ) ); ! 741: return rc; ! 742: } ! 743: tls->rx_seq = ~( ( uint64_t ) 0 ); ! 744: ! 745: return 0; ! 746: } ! 747: ! 748: /** ! 749: * Receive new Alert record ! 750: * ! 751: * @v tls TLS session ! 752: * @v data Plaintext record ! 753: * @v len Length of plaintext record ! 754: * @ret rc Return status code ! 755: */ ! 756: static int tls_new_alert ( struct tls_session *tls, void *data, size_t len ) { ! 757: struct { ! 758: uint8_t level; ! 759: uint8_t description; ! 760: char next[0]; ! 761: } __attribute__ (( packed )) *alert = data; ! 762: void *end = alert->next; ! 763: ! 764: /* Sanity check */ ! 765: if ( end != ( data + len ) ) { ! 766: DBGC ( tls, "TLS %p received overlength Alert\n", tls ); ! 767: DBGC_HD ( tls, data, len ); ! 768: return -EINVAL; ! 769: } ! 770: ! 771: switch ( alert->level ) { ! 772: case TLS_ALERT_WARNING: ! 773: DBGC ( tls, "TLS %p received warning alert %d\n", ! 774: tls, alert->description ); ! 775: return 0; ! 776: case TLS_ALERT_FATAL: ! 777: DBGC ( tls, "TLS %p received fatal alert %d\n", ! 778: tls, alert->description ); ! 779: return -EPERM; ! 780: default: ! 781: DBGC ( tls, "TLS %p received unknown alert level %d" ! 782: "(alert %d)\n", tls, alert->level, alert->description ); ! 783: return -EIO; ! 784: } ! 785: } ! 786: ! 787: /** ! 788: * Receive new Server Hello handshake record ! 789: * ! 790: * @v tls TLS session ! 791: * @v data Plaintext handshake record ! 792: * @v len Length of plaintext handshake record ! 793: * @ret rc Return status code ! 794: */ ! 795: static int tls_new_server_hello ( struct tls_session *tls, ! 796: void *data, size_t len ) { ! 797: struct { ! 798: uint16_t version; ! 799: uint8_t random[32]; ! 800: uint8_t session_id_len; ! 801: char next[0]; ! 802: } __attribute__ (( packed )) *hello_a = data; ! 803: struct { ! 804: uint8_t session_id[hello_a->session_id_len]; ! 805: uint16_t cipher_suite; ! 806: uint8_t compression_method; ! 807: char next[0]; ! 808: } __attribute__ (( packed )) *hello_b = ( void * ) &hello_a->next; ! 809: void *end = hello_b->next; ! 810: int rc; ! 811: ! 812: /* Sanity check */ ! 813: if ( end != ( data + len ) ) { ! 814: DBGC ( tls, "TLS %p received overlength Server Hello\n", tls ); ! 815: DBGC_HD ( tls, data, len ); ! 816: return -EINVAL; ! 817: } ! 818: ! 819: /* Check protocol version */ ! 820: if ( ntohs ( hello_a->version ) < TLS_VERSION_TLS_1_0 ) { ! 821: DBGC ( tls, "TLS %p does not support protocol version %d.%d\n", ! 822: tls, ( ntohs ( hello_a->version ) >> 8 ), ! 823: ( ntohs ( hello_a->version ) & 0xff ) ); ! 824: return -ENOTSUP; ! 825: } ! 826: ! 827: /* Copy out server random bytes */ ! 828: memcpy ( &tls->server_random, &hello_a->random, ! 829: sizeof ( tls->server_random ) ); ! 830: ! 831: /* Select cipher suite */ ! 832: if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 ) ! 833: return rc; ! 834: ! 835: /* Generate secrets */ ! 836: tls_generate_master_secret ( tls ); ! 837: if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) ! 838: return rc; ! 839: ! 840: return 0; ! 841: } ! 842: ! 843: /** ! 844: * Receive new Certificate handshake record ! 845: * ! 846: * @v tls TLS session ! 847: * @v data Plaintext handshake record ! 848: * @v len Length of plaintext handshake record ! 849: * @ret rc Return status code ! 850: */ ! 851: static int tls_new_certificate ( struct tls_session *tls, ! 852: void *data, size_t len ) { ! 853: struct { ! 854: uint8_t length[3]; ! 855: uint8_t certificates[0]; ! 856: } __attribute__ (( packed )) *certificate = data; ! 857: struct { ! 858: uint8_t length[3]; ! 859: uint8_t certificate[0]; ! 860: } __attribute__ (( packed )) *element = ! 861: ( ( void * ) certificate->certificates ); ! 862: size_t elements_len = tls_uint24 ( certificate->length ); ! 863: void *end = ( certificate->certificates + elements_len ); ! 864: struct asn1_cursor cursor; ! 865: int rc; ! 866: ! 867: /* Sanity check */ ! 868: if ( end != ( data + len ) ) { ! 869: DBGC ( tls, "TLS %p received overlength Server Certificate\n", ! 870: tls ); ! 871: DBGC_HD ( tls, data, len ); ! 872: return -EINVAL; ! 873: } ! 874: ! 875: /* Traverse certificate chain */ ! 876: do { ! 877: cursor.data = element->certificate; ! 878: cursor.len = tls_uint24 ( element->length ); ! 879: if ( ( cursor.data + cursor.len ) > end ) { ! 880: DBGC ( tls, "TLS %p received corrupt Server " ! 881: "Certificate\n", tls ); ! 882: DBGC_HD ( tls, data, len ); ! 883: return -EINVAL; ! 884: } ! 885: ! 886: // HACK ! 887: if ( ( rc = x509_rsa_public_key ( &cursor, ! 888: &tls->rsa ) ) != 0 ) { ! 889: DBGC ( tls, "TLS %p cannot determine RSA public key: " ! 890: "%s\n", tls, strerror ( rc ) ); ! 891: return rc; ! 892: } ! 893: return 0; ! 894: ! 895: element = ( cursor.data + cursor.len ); ! 896: } while ( element != end ); ! 897: ! 898: return -EINVAL; ! 899: } ! 900: ! 901: /** ! 902: * Receive new Server Hello Done handshake record ! 903: * ! 904: * @v tls TLS session ! 905: * @v data Plaintext handshake record ! 906: * @v len Length of plaintext handshake record ! 907: * @ret rc Return status code ! 908: */ ! 909: static int tls_new_server_hello_done ( struct tls_session *tls, ! 910: void *data, size_t len ) { ! 911: struct { ! 912: char next[0]; ! 913: } __attribute__ (( packed )) *hello_done = data; ! 914: void *end = hello_done->next; ! 915: ! 916: /* Sanity check */ ! 917: if ( end != ( data + len ) ) { ! 918: DBGC ( tls, "TLS %p received overlength Server Hello Done\n", ! 919: tls ); ! 920: DBGC_HD ( tls, data, len ); ! 921: return -EINVAL; ! 922: } ! 923: ! 924: /* Check that we are ready to send the Client Key Exchange */ ! 925: if ( tls->tx_state != TLS_TX_NONE ) { ! 926: DBGC ( tls, "TLS %p received Server Hello Done while in " ! 927: "TX state %d\n", tls, tls->tx_state ); ! 928: return -EIO; ! 929: } ! 930: ! 931: /* Start sending the Client Key Exchange */ ! 932: tls->tx_state = TLS_TX_CLIENT_KEY_EXCHANGE; ! 933: ! 934: return 0; ! 935: } ! 936: ! 937: /** ! 938: * Receive new Finished handshake record ! 939: * ! 940: * @v tls TLS session ! 941: * @v data Plaintext handshake record ! 942: * @v len Length of plaintext handshake record ! 943: * @ret rc Return status code ! 944: */ ! 945: static int tls_new_finished ( struct tls_session *tls, ! 946: void *data, size_t len ) { ! 947: ! 948: /* FIXME: Handle this properly */ ! 949: tls->tx_state = TLS_TX_DATA; ! 950: ( void ) data; ! 951: ( void ) len; ! 952: return 0; ! 953: } ! 954: ! 955: /** ! 956: * Receive new Handshake record ! 957: * ! 958: * @v tls TLS session ! 959: * @v data Plaintext record ! 960: * @v len Length of plaintext record ! 961: * @ret rc Return status code ! 962: */ ! 963: static int tls_new_handshake ( struct tls_session *tls, ! 964: void *data, size_t len ) { ! 965: void *end = ( data + len ); ! 966: int rc; ! 967: ! 968: while ( data != end ) { ! 969: struct { ! 970: uint8_t type; ! 971: uint8_t length[3]; ! 972: uint8_t payload[0]; ! 973: } __attribute__ (( packed )) *handshake = data; ! 974: void *payload = &handshake->payload; ! 975: size_t payload_len = tls_uint24 ( handshake->length ); ! 976: void *next = ( payload + payload_len ); ! 977: ! 978: /* Sanity check */ ! 979: if ( next > end ) { ! 980: DBGC ( tls, "TLS %p received overlength Handshake\n", ! 981: tls ); ! 982: DBGC_HD ( tls, data, len ); ! 983: return -EINVAL; ! 984: } ! 985: ! 986: switch ( handshake->type ) { ! 987: case TLS_SERVER_HELLO: ! 988: rc = tls_new_server_hello ( tls, payload, payload_len ); ! 989: break; ! 990: case TLS_CERTIFICATE: ! 991: rc = tls_new_certificate ( tls, payload, payload_len ); ! 992: break; ! 993: case TLS_SERVER_HELLO_DONE: ! 994: rc = tls_new_server_hello_done ( tls, payload, ! 995: payload_len ); ! 996: break; ! 997: case TLS_FINISHED: ! 998: rc = tls_new_finished ( tls, payload, payload_len ); ! 999: break; ! 1000: default: ! 1001: DBGC ( tls, "TLS %p ignoring handshake type %d\n", ! 1002: tls, handshake->type ); ! 1003: rc = 0; ! 1004: break; ! 1005: } ! 1006: ! 1007: /* Add to handshake digest (except for Hello Requests, ! 1008: * which are explicitly excluded). ! 1009: */ ! 1010: if ( handshake->type != TLS_HELLO_REQUEST ) ! 1011: tls_add_handshake ( tls, data, ! 1012: sizeof ( *handshake ) + ! 1013: payload_len ); ! 1014: ! 1015: /* Abort on failure */ ! 1016: if ( rc != 0 ) ! 1017: return rc; ! 1018: ! 1019: /* Move to next handshake record */ ! 1020: data = next; ! 1021: } ! 1022: ! 1023: return 0; ! 1024: } ! 1025: ! 1026: /** ! 1027: * Receive new record ! 1028: * ! 1029: * @v tls TLS session ! 1030: * @v type Record type ! 1031: * @v data Plaintext record ! 1032: * @v len Length of plaintext record ! 1033: * @ret rc Return status code ! 1034: */ ! 1035: static int tls_new_record ( struct tls_session *tls, ! 1036: unsigned int type, void *data, size_t len ) { ! 1037: ! 1038: switch ( type ) { ! 1039: case TLS_TYPE_CHANGE_CIPHER: ! 1040: return tls_new_change_cipher ( tls, data, len ); ! 1041: case TLS_TYPE_ALERT: ! 1042: return tls_new_alert ( tls, data, len ); ! 1043: case TLS_TYPE_HANDSHAKE: ! 1044: return tls_new_handshake ( tls, data, len ); ! 1045: case TLS_TYPE_DATA: ! 1046: return xfer_deliver_raw ( &tls->plainstream, data, len ); ! 1047: default: ! 1048: /* RFC4346 says that we should just ignore unknown ! 1049: * record types. ! 1050: */ ! 1051: DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type ); ! 1052: return 0; ! 1053: } ! 1054: } ! 1055: ! 1056: /****************************************************************************** ! 1057: * ! 1058: * Record encryption/decryption ! 1059: * ! 1060: ****************************************************************************** ! 1061: */ ! 1062: ! 1063: /** ! 1064: * Calculate HMAC ! 1065: * ! 1066: * @v tls TLS session ! 1067: * @v cipherspec Cipher specification ! 1068: * @v seq Sequence number ! 1069: * @v tlshdr TLS header ! 1070: * @v data Data ! 1071: * @v len Length of data ! 1072: * @v mac HMAC to fill in ! 1073: */ ! 1074: static void tls_hmac ( struct tls_session *tls __unused, ! 1075: struct tls_cipherspec *cipherspec, ! 1076: uint64_t seq, struct tls_header *tlshdr, ! 1077: const void *data, size_t len, void *hmac ) { ! 1078: struct digest_algorithm *digest = cipherspec->digest; ! 1079: uint8_t digest_ctx[digest->ctxsize]; ! 1080: ! 1081: hmac_init ( digest, digest_ctx, cipherspec->mac_secret, ! 1082: &digest->digestsize ); ! 1083: seq = cpu_to_be64 ( seq ); ! 1084: hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) ); ! 1085: hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) ); ! 1086: hmac_update ( digest, digest_ctx, data, len ); ! 1087: hmac_final ( digest, digest_ctx, cipherspec->mac_secret, ! 1088: &digest->digestsize, hmac ); ! 1089: } ! 1090: ! 1091: /** ! 1092: * Allocate and assemble stream-ciphered record from data and MAC portions ! 1093: * ! 1094: * @v tls TLS session ! 1095: * @ret data Data ! 1096: * @ret len Length of data ! 1097: * @ret digest MAC digest ! 1098: * @ret plaintext_len Length of plaintext record ! 1099: * @ret plaintext Allocated plaintext record ! 1100: */ ! 1101: static void * __malloc tls_assemble_stream ( struct tls_session *tls, ! 1102: const void *data, size_t len, ! 1103: void *digest, size_t *plaintext_len ) { ! 1104: size_t mac_len = tls->tx_cipherspec.digest->digestsize; ! 1105: void *plaintext; ! 1106: void *content; ! 1107: void *mac; ! 1108: ! 1109: /* Calculate stream-ciphered struct length */ ! 1110: *plaintext_len = ( len + mac_len ); ! 1111: ! 1112: /* Allocate stream-ciphered struct */ ! 1113: plaintext = malloc ( *plaintext_len ); ! 1114: if ( ! plaintext ) ! 1115: return NULL; ! 1116: content = plaintext; ! 1117: mac = ( content + len ); ! 1118: ! 1119: /* Fill in stream-ciphered struct */ ! 1120: memcpy ( content, data, len ); ! 1121: memcpy ( mac, digest, mac_len ); ! 1122: ! 1123: return plaintext; ! 1124: } ! 1125: ! 1126: /** ! 1127: * Allocate and assemble block-ciphered record from data and MAC portions ! 1128: * ! 1129: * @v tls TLS session ! 1130: * @ret data Data ! 1131: * @ret len Length of data ! 1132: * @ret digest MAC digest ! 1133: * @ret plaintext_len Length of plaintext record ! 1134: * @ret plaintext Allocated plaintext record ! 1135: */ ! 1136: static void * tls_assemble_block ( struct tls_session *tls, ! 1137: const void *data, size_t len, ! 1138: void *digest, size_t *plaintext_len ) { ! 1139: size_t blocksize = tls->tx_cipherspec.cipher->blocksize; ! 1140: size_t iv_len = blocksize; ! 1141: size_t mac_len = tls->tx_cipherspec.digest->digestsize; ! 1142: size_t padding_len; ! 1143: void *plaintext; ! 1144: void *iv; ! 1145: void *content; ! 1146: void *mac; ! 1147: void *padding; ! 1148: ! 1149: /* FIXME: TLSv1.1 has an explicit IV */ ! 1150: iv_len = 0; ! 1151: ! 1152: /* Calculate block-ciphered struct length */ ! 1153: padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) ); ! 1154: *plaintext_len = ( iv_len + len + mac_len + padding_len + 1 ); ! 1155: ! 1156: /* Allocate block-ciphered struct */ ! 1157: plaintext = malloc ( *plaintext_len ); ! 1158: if ( ! plaintext ) ! 1159: return NULL; ! 1160: iv = plaintext; ! 1161: content = ( iv + iv_len ); ! 1162: mac = ( content + len ); ! 1163: padding = ( mac + mac_len ); ! 1164: ! 1165: /* Fill in block-ciphered struct */ ! 1166: memset ( iv, 0, iv_len ); ! 1167: memcpy ( content, data, len ); ! 1168: memcpy ( mac, digest, mac_len ); ! 1169: memset ( padding, padding_len, ( padding_len + 1 ) ); ! 1170: ! 1171: return plaintext; ! 1172: } ! 1173: ! 1174: /** ! 1175: * Send plaintext record ! 1176: * ! 1177: * @v tls TLS session ! 1178: * @v type Record type ! 1179: * @v data Plaintext record ! 1180: * @v len Length of plaintext record ! 1181: * @ret rc Return status code ! 1182: */ ! 1183: static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, ! 1184: const void *data, size_t len ) { ! 1185: struct tls_header plaintext_tlshdr; ! 1186: struct tls_header *tlshdr; ! 1187: struct tls_cipherspec *cipherspec = &tls->tx_cipherspec; ! 1188: void *plaintext = NULL; ! 1189: size_t plaintext_len; ! 1190: struct io_buffer *ciphertext = NULL; ! 1191: size_t ciphertext_len; ! 1192: size_t mac_len = cipherspec->digest->digestsize; ! 1193: uint8_t mac[mac_len]; ! 1194: int rc; ! 1195: ! 1196: /* Construct header */ ! 1197: plaintext_tlshdr.type = type; ! 1198: plaintext_tlshdr.version = htons ( TLS_VERSION_TLS_1_0 ); ! 1199: plaintext_tlshdr.length = htons ( len ); ! 1200: ! 1201: /* Calculate MAC */ ! 1202: tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr, ! 1203: data, len, mac ); ! 1204: ! 1205: /* Allocate and assemble plaintext struct */ ! 1206: if ( is_stream_cipher ( cipherspec->cipher ) ) { ! 1207: plaintext = tls_assemble_stream ( tls, data, len, mac, ! 1208: &plaintext_len ); ! 1209: } else { ! 1210: plaintext = tls_assemble_block ( tls, data, len, mac, ! 1211: &plaintext_len ); ! 1212: } ! 1213: if ( ! plaintext ) { ! 1214: DBGC ( tls, "TLS %p could not allocate %zd bytes for " ! 1215: "plaintext\n", tls, plaintext_len ); ! 1216: rc = -ENOMEM; ! 1217: goto done; ! 1218: } ! 1219: ! 1220: DBGC2 ( tls, "Sending plaintext data:\n" ); ! 1221: DBGC2_HD ( tls, plaintext, plaintext_len ); ! 1222: ! 1223: /* Allocate ciphertext */ ! 1224: ciphertext_len = ( sizeof ( *tlshdr ) + plaintext_len ); ! 1225: ciphertext = xfer_alloc_iob ( &tls->cipherstream, ciphertext_len ); ! 1226: if ( ! ciphertext ) { ! 1227: DBGC ( tls, "TLS %p could not allocate %zd bytes for " ! 1228: "ciphertext\n", tls, ciphertext_len ); ! 1229: rc = -ENOMEM; ! 1230: goto done; ! 1231: } ! 1232: ! 1233: /* Assemble ciphertext */ ! 1234: tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) ); ! 1235: tlshdr->type = type; ! 1236: tlshdr->version = htons ( TLS_VERSION_TLS_1_0 ); ! 1237: tlshdr->length = htons ( plaintext_len ); ! 1238: memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx, ! 1239: cipherspec->cipher->ctxsize ); ! 1240: cipher_encrypt ( cipherspec->cipher, cipherspec->cipher_next_ctx, ! 1241: plaintext, iob_put ( ciphertext, plaintext_len ), ! 1242: plaintext_len ); ! 1243: ! 1244: /* Free plaintext as soon as possible to conserve memory */ ! 1245: free ( plaintext ); ! 1246: plaintext = NULL; ! 1247: ! 1248: /* Send ciphertext */ ! 1249: if ( ( rc = xfer_deliver_iob ( &tls->cipherstream, ! 1250: iob_disown ( ciphertext ) ) ) != 0 ) { ! 1251: DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n", ! 1252: tls, strerror ( rc ) ); ! 1253: goto done; ! 1254: } ! 1255: ! 1256: /* Update TX state machine to next record */ ! 1257: tls->tx_seq += 1; ! 1258: memcpy ( tls->tx_cipherspec.cipher_ctx, ! 1259: tls->tx_cipherspec.cipher_next_ctx, ! 1260: tls->tx_cipherspec.cipher->ctxsize ); ! 1261: ! 1262: done: ! 1263: free ( plaintext ); ! 1264: free_iob ( ciphertext ); ! 1265: return rc; ! 1266: } ! 1267: ! 1268: /** ! 1269: * Split stream-ciphered record into data and MAC portions ! 1270: * ! 1271: * @v tls TLS session ! 1272: * @v plaintext Plaintext record ! 1273: * @v plaintext_len Length of record ! 1274: * @ret data Data ! 1275: * @ret len Length of data ! 1276: * @ret digest MAC digest ! 1277: * @ret rc Return status code ! 1278: */ ! 1279: static int tls_split_stream ( struct tls_session *tls, ! 1280: void *plaintext, size_t plaintext_len, ! 1281: void **data, size_t *len, void **digest ) { ! 1282: void *content; ! 1283: size_t content_len; ! 1284: void *mac; ! 1285: size_t mac_len; ! 1286: ! 1287: /* Decompose stream-ciphered data */ ! 1288: mac_len = tls->rx_cipherspec.digest->digestsize; ! 1289: if ( plaintext_len < mac_len ) { ! 1290: DBGC ( tls, "TLS %p received underlength record\n", tls ); ! 1291: DBGC_HD ( tls, plaintext, plaintext_len ); ! 1292: return -EINVAL; ! 1293: } ! 1294: content_len = ( plaintext_len - mac_len ); ! 1295: content = plaintext; ! 1296: mac = ( content + content_len ); ! 1297: ! 1298: /* Fill in return values */ ! 1299: *data = content; ! 1300: *len = content_len; ! 1301: *digest = mac; ! 1302: ! 1303: return 0; ! 1304: } ! 1305: ! 1306: /** ! 1307: * Split block-ciphered record into data and MAC portions ! 1308: * ! 1309: * @v tls TLS session ! 1310: * @v plaintext Plaintext record ! 1311: * @v plaintext_len Length of record ! 1312: * @ret data Data ! 1313: * @ret len Length of data ! 1314: * @ret digest MAC digest ! 1315: * @ret rc Return status code ! 1316: */ ! 1317: static int tls_split_block ( struct tls_session *tls, ! 1318: void *plaintext, size_t plaintext_len, ! 1319: void **data, size_t *len, ! 1320: void **digest ) { ! 1321: void *iv; ! 1322: size_t iv_len; ! 1323: void *content; ! 1324: size_t content_len; ! 1325: void *mac; ! 1326: size_t mac_len; ! 1327: void *padding; ! 1328: size_t padding_len; ! 1329: unsigned int i; ! 1330: ! 1331: /* Decompose block-ciphered data */ ! 1332: if ( plaintext_len < 1 ) { ! 1333: DBGC ( tls, "TLS %p received underlength record\n", tls ); ! 1334: DBGC_HD ( tls, plaintext, plaintext_len ); ! 1335: return -EINVAL; ! 1336: } ! 1337: iv_len = tls->rx_cipherspec.cipher->blocksize; ! 1338: ! 1339: /* FIXME: TLSv1.1 uses an explicit IV */ ! 1340: iv_len = 0; ! 1341: ! 1342: mac_len = tls->rx_cipherspec.digest->digestsize; ! 1343: padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) ); ! 1344: if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) { ! 1345: DBGC ( tls, "TLS %p received underlength record\n", tls ); ! 1346: DBGC_HD ( tls, plaintext, plaintext_len ); ! 1347: return -EINVAL; ! 1348: } ! 1349: content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 ); ! 1350: iv = plaintext; ! 1351: content = ( iv + iv_len ); ! 1352: mac = ( content + content_len ); ! 1353: padding = ( mac + mac_len ); ! 1354: ! 1355: /* Verify padding bytes */ ! 1356: for ( i = 0 ; i < padding_len ; i++ ) { ! 1357: if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) { ! 1358: DBGC ( tls, "TLS %p received bad padding\n", tls ); ! 1359: DBGC_HD ( tls, plaintext, plaintext_len ); ! 1360: return -EINVAL; ! 1361: } ! 1362: } ! 1363: ! 1364: /* Fill in return values */ ! 1365: *data = content; ! 1366: *len = content_len; ! 1367: *digest = mac; ! 1368: ! 1369: return 0; ! 1370: } ! 1371: ! 1372: /** ! 1373: * Receive new ciphertext record ! 1374: * ! 1375: * @v tls TLS session ! 1376: * @v tlshdr Record header ! 1377: * @v ciphertext Ciphertext record ! 1378: * @ret rc Return status code ! 1379: */ ! 1380: static int tls_new_ciphertext ( struct tls_session *tls, ! 1381: struct tls_header *tlshdr, void *ciphertext ) { ! 1382: struct tls_header plaintext_tlshdr; ! 1383: struct tls_cipherspec *cipherspec = &tls->rx_cipherspec; ! 1384: size_t record_len = ntohs ( tlshdr->length ); ! 1385: void *plaintext = NULL; ! 1386: void *data; ! 1387: size_t len; ! 1388: void *mac; ! 1389: size_t mac_len = cipherspec->digest->digestsize; ! 1390: uint8_t verify_mac[mac_len]; ! 1391: int rc; ! 1392: ! 1393: /* Allocate buffer for plaintext */ ! 1394: plaintext = malloc ( record_len ); ! 1395: if ( ! plaintext ) { ! 1396: DBGC ( tls, "TLS %p could not allocate %zd bytes for " ! 1397: "decryption buffer\n", tls, record_len ); ! 1398: rc = -ENOMEM; ! 1399: goto done; ! 1400: } ! 1401: ! 1402: /* Decrypt the record */ ! 1403: cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx, ! 1404: ciphertext, plaintext, record_len ); ! 1405: ! 1406: /* Split record into content and MAC */ ! 1407: if ( is_stream_cipher ( cipherspec->cipher ) ) { ! 1408: if ( ( rc = tls_split_stream ( tls, plaintext, record_len, ! 1409: &data, &len, &mac ) ) != 0 ) ! 1410: goto done; ! 1411: } else { ! 1412: if ( ( rc = tls_split_block ( tls, plaintext, record_len, ! 1413: &data, &len, &mac ) ) != 0 ) ! 1414: goto done; ! 1415: } ! 1416: ! 1417: /* Verify MAC */ ! 1418: plaintext_tlshdr.type = tlshdr->type; ! 1419: plaintext_tlshdr.version = tlshdr->version; ! 1420: plaintext_tlshdr.length = htons ( len ); ! 1421: tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr, ! 1422: data, len, verify_mac); ! 1423: if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) { ! 1424: DBGC ( tls, "TLS %p failed MAC verification\n", tls ); ! 1425: DBGC_HD ( tls, plaintext, record_len ); ! 1426: goto done; ! 1427: } ! 1428: ! 1429: DBGC2 ( tls, "Received plaintext data:\n" ); ! 1430: DBGC2_HD ( tls, data, len ); ! 1431: ! 1432: /* Process plaintext record */ ! 1433: if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 ) ! 1434: goto done; ! 1435: ! 1436: rc = 0; ! 1437: done: ! 1438: free ( plaintext ); ! 1439: return rc; ! 1440: } ! 1441: ! 1442: /****************************************************************************** ! 1443: * ! 1444: * Plaintext stream operations ! 1445: * ! 1446: ****************************************************************************** ! 1447: */ ! 1448: ! 1449: /** ! 1450: * Check flow control window ! 1451: * ! 1452: * @v tls TLS session ! 1453: * @ret len Length of window ! 1454: */ ! 1455: static size_t tls_plainstream_window ( struct tls_session *tls ) { ! 1456: ! 1457: /* Block window unless we are ready to accept data */ ! 1458: if ( tls->tx_state != TLS_TX_DATA ) ! 1459: return 0; ! 1460: ! 1461: return xfer_window ( &tls->cipherstream ); ! 1462: } ! 1463: ! 1464: /** ! 1465: * Deliver datagram as raw data ! 1466: * ! 1467: * @v tls TLS session ! 1468: * @v iobuf I/O buffer ! 1469: * @v meta Data transfer metadata ! 1470: * @ret rc Return status code ! 1471: */ ! 1472: static int tls_plainstream_deliver ( struct tls_session *tls, ! 1473: struct io_buffer *iobuf, ! 1474: struct xfer_metadata *meta __unused ) { ! 1475: int rc; ! 1476: ! 1477: /* Refuse unless we are ready to accept data */ ! 1478: if ( tls->tx_state != TLS_TX_DATA ) { ! 1479: rc = -ENOTCONN; ! 1480: goto done; ! 1481: } ! 1482: ! 1483: if ( ( rc = tls_send_plaintext ( tls, TLS_TYPE_DATA, iobuf->data, ! 1484: iob_len ( iobuf ) ) ) != 0 ) ! 1485: goto done; ! 1486: ! 1487: done: ! 1488: free_iob ( iobuf ); ! 1489: return rc; ! 1490: } ! 1491: ! 1492: /** TLS plaintext stream interface operations */ ! 1493: static struct interface_operation tls_plainstream_ops[] = { ! 1494: INTF_OP ( xfer_deliver, struct tls_session *, tls_plainstream_deliver ), ! 1495: INTF_OP ( xfer_window, struct tls_session *, tls_plainstream_window ), ! 1496: INTF_OP ( intf_close, struct tls_session *, tls_close ), ! 1497: }; ! 1498: ! 1499: /** TLS plaintext stream interface descriptor */ ! 1500: static struct interface_descriptor tls_plainstream_desc = ! 1501: INTF_DESC_PASSTHRU ( struct tls_session, plainstream, ! 1502: tls_plainstream_ops, cipherstream ); ! 1503: ! 1504: /****************************************************************************** ! 1505: * ! 1506: * Ciphertext stream operations ! 1507: * ! 1508: ****************************************************************************** ! 1509: */ ! 1510: ! 1511: /** ! 1512: * Handle received TLS header ! 1513: * ! 1514: * @v tls TLS session ! 1515: * @ret rc Returned status code ! 1516: */ ! 1517: static int tls_newdata_process_header ( struct tls_session *tls ) { ! 1518: size_t data_len = ntohs ( tls->rx_header.length ); ! 1519: ! 1520: /* Allocate data buffer now that we know the length */ ! 1521: assert ( tls->rx_data == NULL ); ! 1522: tls->rx_data = malloc ( data_len ); ! 1523: if ( ! tls->rx_data ) { ! 1524: DBGC ( tls, "TLS %p could not allocate %zd bytes " ! 1525: "for receive buffer\n", tls, data_len ); ! 1526: return -ENOMEM; ! 1527: } ! 1528: ! 1529: /* Move to data state */ ! 1530: tls->rx_state = TLS_RX_DATA; ! 1531: ! 1532: return 0; ! 1533: } ! 1534: ! 1535: /** ! 1536: * Handle received TLS data payload ! 1537: * ! 1538: * @v tls TLS session ! 1539: * @ret rc Returned status code ! 1540: */ ! 1541: static int tls_newdata_process_data ( struct tls_session *tls ) { ! 1542: int rc; ! 1543: ! 1544: /* Process record */ ! 1545: if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header, ! 1546: tls->rx_data ) ) != 0 ) ! 1547: return rc; ! 1548: ! 1549: /* Increment RX sequence number */ ! 1550: tls->rx_seq += 1; ! 1551: ! 1552: /* Free data buffer */ ! 1553: free ( tls->rx_data ); ! 1554: tls->rx_data = NULL; ! 1555: ! 1556: /* Return to header state */ ! 1557: tls->rx_state = TLS_RX_HEADER; ! 1558: ! 1559: return 0; ! 1560: } ! 1561: ! 1562: /** ! 1563: * Receive new ciphertext ! 1564: * ! 1565: * @v tls TLS session ! 1566: * @v iobuf I/O buffer ! 1567: * @v meta Data transfer metadat ! 1568: * @ret rc Return status code ! 1569: */ ! 1570: static int tls_cipherstream_deliver ( struct tls_session *tls, ! 1571: struct io_buffer *iobuf, ! 1572: struct xfer_metadata *xfer __unused ) { ! 1573: size_t frag_len; ! 1574: void *buf; ! 1575: size_t buf_len; ! 1576: int ( * process ) ( struct tls_session *tls ); ! 1577: int rc; ! 1578: ! 1579: while ( iob_len ( iobuf ) ) { ! 1580: /* Select buffer according to current state */ ! 1581: switch ( tls->rx_state ) { ! 1582: case TLS_RX_HEADER: ! 1583: buf = &tls->rx_header; ! 1584: buf_len = sizeof ( tls->rx_header ); ! 1585: process = tls_newdata_process_header; ! 1586: break; ! 1587: case TLS_RX_DATA: ! 1588: buf = tls->rx_data; ! 1589: buf_len = ntohs ( tls->rx_header.length ); ! 1590: process = tls_newdata_process_data; ! 1591: break; ! 1592: default: ! 1593: assert ( 0 ); ! 1594: rc = -EINVAL; ! 1595: goto done; ! 1596: } ! 1597: ! 1598: /* Copy data portion to buffer */ ! 1599: frag_len = ( buf_len - tls->rx_rcvd ); ! 1600: if ( frag_len > iob_len ( iobuf ) ) ! 1601: frag_len = iob_len ( iobuf ); ! 1602: memcpy ( ( buf + tls->rx_rcvd ), iobuf->data, frag_len ); ! 1603: tls->rx_rcvd += frag_len; ! 1604: iob_pull ( iobuf, frag_len ); ! 1605: ! 1606: /* Process data if buffer is now full */ ! 1607: if ( tls->rx_rcvd == buf_len ) { ! 1608: if ( ( rc = process ( tls ) ) != 0 ) { ! 1609: tls_close ( tls, rc ); ! 1610: goto done; ! 1611: } ! 1612: tls->rx_rcvd = 0; ! 1613: } ! 1614: } ! 1615: rc = 0; ! 1616: ! 1617: done: ! 1618: free_iob ( iobuf ); ! 1619: return rc; ! 1620: } ! 1621: ! 1622: /** TLS ciphertext stream interface operations */ ! 1623: static struct interface_operation tls_cipherstream_ops[] = { ! 1624: INTF_OP ( xfer_deliver, struct tls_session *, ! 1625: tls_cipherstream_deliver ), ! 1626: INTF_OP ( intf_close, struct tls_session *, tls_close ), ! 1627: }; ! 1628: ! 1629: /** TLS ciphertext stream interface descriptor */ ! 1630: static struct interface_descriptor tls_cipherstream_desc = ! 1631: INTF_DESC_PASSTHRU ( struct tls_session, cipherstream, ! 1632: tls_cipherstream_ops, plainstream ); ! 1633: ! 1634: /****************************************************************************** ! 1635: * ! 1636: * Controlling process ! 1637: * ! 1638: ****************************************************************************** ! 1639: */ ! 1640: ! 1641: /** ! 1642: * TLS TX state machine ! 1643: * ! 1644: * @v process TLS process ! 1645: */ ! 1646: static void tls_step ( struct process *process ) { ! 1647: struct tls_session *tls = ! 1648: container_of ( process, struct tls_session, process ); ! 1649: int rc; ! 1650: ! 1651: /* Wait for cipherstream to become ready */ ! 1652: if ( ! xfer_window ( &tls->cipherstream ) ) ! 1653: return; ! 1654: ! 1655: switch ( tls->tx_state ) { ! 1656: case TLS_TX_NONE: ! 1657: /* Nothing to do */ ! 1658: break; ! 1659: case TLS_TX_CLIENT_HELLO: ! 1660: /* Send Client Hello */ ! 1661: if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) { ! 1662: DBGC ( tls, "TLS %p could not send Client Hello: %s\n", ! 1663: tls, strerror ( rc ) ); ! 1664: goto err; ! 1665: } ! 1666: tls->tx_state = TLS_TX_NONE; ! 1667: break; ! 1668: case TLS_TX_CLIENT_KEY_EXCHANGE: ! 1669: /* Send Client Key Exchange */ ! 1670: if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) { ! 1671: DBGC ( tls, "TLS %p could send Client Key Exchange: " ! 1672: "%s\n", tls, strerror ( rc ) ); ! 1673: goto err; ! 1674: } ! 1675: tls->tx_state = TLS_TX_CHANGE_CIPHER; ! 1676: break; ! 1677: case TLS_TX_CHANGE_CIPHER: ! 1678: /* Send Change Cipher, and then change the cipher in use */ ! 1679: if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) { ! 1680: DBGC ( tls, "TLS %p could not send Change Cipher: " ! 1681: "%s\n", tls, strerror ( rc ) ); ! 1682: goto err; ! 1683: } ! 1684: if ( ( rc = tls_change_cipher ( tls, ! 1685: &tls->tx_cipherspec_pending, ! 1686: &tls->tx_cipherspec )) != 0 ){ ! 1687: DBGC ( tls, "TLS %p could not activate TX cipher: " ! 1688: "%s\n", tls, strerror ( rc ) ); ! 1689: goto err; ! 1690: } ! 1691: tls->tx_seq = 0; ! 1692: tls->tx_state = TLS_TX_FINISHED; ! 1693: break; ! 1694: case TLS_TX_FINISHED: ! 1695: /* Send Finished */ ! 1696: if ( ( rc = tls_send_finished ( tls ) ) != 0 ) { ! 1697: DBGC ( tls, "TLS %p could not send Finished: %s\n", ! 1698: tls, strerror ( rc ) ); ! 1699: goto err; ! 1700: } ! 1701: tls->tx_state = TLS_TX_NONE; ! 1702: break; ! 1703: case TLS_TX_DATA: ! 1704: /* Nothing to do */ ! 1705: break; ! 1706: default: ! 1707: assert ( 0 ); ! 1708: } ! 1709: ! 1710: return; ! 1711: ! 1712: err: ! 1713: tls_close ( tls, rc ); ! 1714: } ! 1715: ! 1716: /****************************************************************************** ! 1717: * ! 1718: * Instantiator ! 1719: * ! 1720: ****************************************************************************** ! 1721: */ ! 1722: ! 1723: int add_tls ( struct interface *xfer, struct interface **next ) { ! 1724: struct tls_session *tls; ! 1725: ! 1726: /* Allocate and initialise TLS structure */ ! 1727: tls = malloc ( sizeof ( *tls ) ); ! 1728: if ( ! tls ) ! 1729: return -ENOMEM; ! 1730: memset ( tls, 0, sizeof ( *tls ) ); ! 1731: ref_init ( &tls->refcnt, free_tls ); ! 1732: intf_init ( &tls->plainstream, &tls_plainstream_desc, &tls->refcnt ); ! 1733: intf_init ( &tls->cipherstream, &tls_cipherstream_desc, &tls->refcnt ); ! 1734: tls_clear_cipher ( tls, &tls->tx_cipherspec ); ! 1735: tls_clear_cipher ( tls, &tls->tx_cipherspec_pending ); ! 1736: tls_clear_cipher ( tls, &tls->rx_cipherspec ); ! 1737: tls_clear_cipher ( tls, &tls->rx_cipherspec_pending ); ! 1738: tls->client_random.gmt_unix_time = 0; ! 1739: tls_generate_random ( &tls->client_random.random, ! 1740: ( sizeof ( tls->client_random.random ) ) ); ! 1741: tls->pre_master_secret.version = htons ( TLS_VERSION_TLS_1_0 ); ! 1742: tls_generate_random ( &tls->pre_master_secret.random, ! 1743: ( sizeof ( tls->pre_master_secret.random ) ) ); ! 1744: digest_init ( &md5_algorithm, tls->handshake_md5_ctx ); ! 1745: digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx ); ! 1746: tls->tx_state = TLS_TX_CLIENT_HELLO; ! 1747: process_init ( &tls->process, tls_step, &tls->refcnt ); ! 1748: ! 1749: /* Attach to parent interface, mortalise self, and return */ ! 1750: intf_plug_plug ( &tls->plainstream, xfer ); ! 1751: *next = &tls->cipherstream; ! 1752: ref_put ( &tls->refcnt ); ! 1753: return 0; ! 1754: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.