tls.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 /**
00022  * @file
00023  *
00024  * Transport Layer Security Protocol
00025  */
00026 
00027 #include <stdint.h>
00028 #include <stdlib.h>
00029 #include <stdarg.h>
00030 #include <string.h>
00031 #include <errno.h>
00032 #include <byteswap.h>
00033 #include <gpxe/hmac.h>
00034 #include <gpxe/md5.h>
00035 #include <gpxe/sha1.h>
00036 #include <gpxe/aes.h>
00037 #include <gpxe/rsa.h>
00038 #include <gpxe/xfer.h>
00039 #include <gpxe/open.h>
00040 #include <gpxe/filter.h>
00041 #include <gpxe/asn1.h>
00042 #include <gpxe/x509.h>
00043 #include <gpxe/tls.h>
00044 
00045 static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
00046                                 const void *data, size_t len );
00047 static void tls_clear_cipher ( struct tls_session *tls,
00048                                struct tls_cipherspec *cipherspec );
00049 
00050 /******************************************************************************
00051  *
00052  * Utility functions
00053  *
00054  ******************************************************************************
00055  */
00056 
00057 /**
00058  * Extract 24-bit field value
00059  *
00060  * @v field24           24-bit field
00061  * @ret value           Field value
00062  *
00063  * TLS uses 24-bit integers in several places, which are awkward to
00064  * parse in C.
00065  */
00066 static unsigned long tls_uint24 ( uint8_t field24[3] ) {
00067         return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] );
00068 }
00069 
00070 /******************************************************************************
00071  *
00072  * Cleanup functions
00073  *
00074  ******************************************************************************
00075  */
00076 
00077 /**
00078  * Free TLS session
00079  *
00080  * @v refcnt            Reference counter
00081  */
00082 static void free_tls ( struct refcnt *refcnt ) {
00083         struct tls_session *tls =
00084                 container_of ( refcnt, struct tls_session, refcnt );
00085 
00086         /* Free dynamically-allocated resources */
00087         tls_clear_cipher ( tls, &tls->tx_cipherspec );
00088         tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
00089         tls_clear_cipher ( tls, &tls->rx_cipherspec );
00090         tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
00091         x509_free_rsa_public_key ( &tls->rsa );
00092         free ( tls->rx_data );
00093 
00094         /* Free TLS structure itself */
00095         free ( tls );   
00096 }
00097 
00098 /**
00099  * Finish with TLS session
00100  *
00101  * @v tls               TLS session
00102  * @v rc                Status code
00103  */
00104 static void tls_close ( struct tls_session *tls, int rc ) {
00105 
00106         /* Remove process */
00107         process_del ( &tls->process );
00108         
00109         /* Close ciphertext and plaintext streams */
00110         xfer_nullify ( &tls->cipherstream.xfer );
00111         xfer_close ( &tls->cipherstream.xfer, rc );
00112         xfer_nullify ( &tls->plainstream.xfer );
00113         xfer_close ( &tls->plainstream.xfer, rc );
00114 }
00115 
00116 /******************************************************************************
00117  *
00118  * Random number generation
00119  *
00120  ******************************************************************************
00121  */
00122 
00123 /**
00124  * Generate random data
00125  *
00126  * @v data              Buffer to fill
00127  * @v len               Length of buffer
00128  */
00129 static void tls_generate_random ( void *data, size_t len ) {
00130         /* FIXME: Some real random data source would be nice... */
00131         memset ( data, 0x01, len );
00132 }
00133 
00134 /**
00135  * Update HMAC with a list of ( data, len ) pairs
00136  *
00137  * @v digest            Hash function to use
00138  * @v digest_ctx        Digest context
00139  * @v args              ( data, len ) pairs of data, terminated by NULL
00140  */
00141 static void tls_hmac_update_va ( struct digest_algorithm *digest,
00142                                  void *digest_ctx, va_list args ) {
00143         void *data;
00144         size_t len;
00145 
00146         while ( ( data = va_arg ( args, void * ) ) ) {
00147                 len = va_arg ( args, size_t );
00148                 hmac_update ( digest, digest_ctx, data, len );
00149         }
00150 }
00151 
00152 /**
00153  * Generate secure pseudo-random data using a single hash function
00154  *
00155  * @v tls               TLS session
00156  * @v digest            Hash function to use
00157  * @v secret            Secret
00158  * @v secret_len        Length of secret
00159  * @v out               Output buffer
00160  * @v out_len           Length of output buffer
00161  * @v seeds             ( data, len ) pairs of seed data, terminated by NULL
00162  */
00163 static void tls_p_hash_va ( struct tls_session *tls,
00164                             struct digest_algorithm *digest,
00165                             void *secret, size_t secret_len,
00166                             void *out, size_t out_len,
00167                             va_list seeds ) {
00168         uint8_t secret_copy[secret_len];
00169         uint8_t digest_ctx[digest->ctxsize];
00170         uint8_t digest_ctx_partial[digest->ctxsize];
00171         uint8_t a[digest->digestsize];
00172         uint8_t out_tmp[digest->digestsize];
00173         size_t frag_len = digest->digestsize;
00174         va_list tmp;
00175 
00176         /* Copy the secret, in case HMAC modifies it */
00177         memcpy ( secret_copy, secret, secret_len );
00178         secret = secret_copy;
00179         DBGC2 ( tls, "TLS %p %s secret:\n", tls, digest->name );
00180         DBGC2_HD ( tls, secret, secret_len );
00181 
00182         /* Calculate A(1) */
00183         hmac_init ( digest, digest_ctx, secret, &secret_len );
00184         va_copy ( tmp, seeds );
00185         tls_hmac_update_va ( digest, digest_ctx, tmp );
00186         va_end ( tmp );
00187         hmac_final ( digest, digest_ctx, secret, &secret_len, a );
00188         DBGC2 ( tls, "TLS %p %s A(1):\n", tls, digest->name );
00189         DBGC2_HD ( tls, &a, sizeof ( a ) );
00190 
00191         /* Generate as much data as required */
00192         while ( out_len ) {
00193                 /* Calculate output portion */
00194                 hmac_init ( digest, digest_ctx, secret, &secret_len );
00195                 hmac_update ( digest, digest_ctx, a, sizeof ( a ) );
00196                 memcpy ( digest_ctx_partial, digest_ctx, digest->ctxsize );
00197                 va_copy ( tmp, seeds );
00198                 tls_hmac_update_va ( digest, digest_ctx, tmp );
00199                 va_end ( tmp );
00200                 hmac_final ( digest, digest_ctx,
00201                              secret, &secret_len, out_tmp );
00202 
00203                 /* Copy output */
00204                 if ( frag_len > out_len )
00205                         frag_len = out_len;
00206                 memcpy ( out, out_tmp, frag_len );
00207                 DBGC2 ( tls, "TLS %p %s output:\n", tls, digest->name );
00208                 DBGC2_HD ( tls, out, frag_len );
00209 
00210                 /* Calculate A(i) */
00211                 hmac_final ( digest, digest_ctx_partial,
00212                              secret, &secret_len, a );
00213                 DBGC2 ( tls, "TLS %p %s A(n):\n", tls, digest->name );
00214                 DBGC2_HD ( tls, &a, sizeof ( a ) );
00215 
00216                 out += frag_len;
00217                 out_len -= frag_len;
00218         }
00219 }
00220 
00221 /**
00222  * Generate secure pseudo-random data
00223  *
00224  * @v tls               TLS session
00225  * @v secret            Secret
00226  * @v secret_len        Length of secret
00227  * @v out               Output buffer
00228  * @v out_len           Length of output buffer
00229  * @v ...               ( data, len ) pairs of seed data, terminated by NULL
00230  */
00231 static void tls_prf ( struct tls_session *tls, void *secret, size_t secret_len,
00232                       void *out, size_t out_len, ... ) {
00233         va_list seeds;
00234         va_list tmp;
00235         size_t subsecret_len;
00236         void *md5_secret;
00237         void *sha1_secret;
00238         uint8_t out_md5[out_len];
00239         uint8_t out_sha1[out_len];
00240         unsigned int i;
00241 
00242         va_start ( seeds, out_len );
00243 
00244         /* Split secret into two, with an overlap of up to one byte */
00245         subsecret_len = ( ( secret_len + 1 ) / 2 );
00246         md5_secret = secret;
00247         sha1_secret = ( secret + secret_len - subsecret_len );
00248 
00249         /* Calculate MD5 portion */
00250         va_copy ( tmp, seeds );
00251         tls_p_hash_va ( tls, &md5_algorithm, md5_secret, subsecret_len,
00252                         out_md5, out_len, seeds );
00253         va_end ( tmp );
00254 
00255         /* Calculate SHA1 portion */
00256         va_copy ( tmp, seeds );
00257         tls_p_hash_va ( tls, &sha1_algorithm, sha1_secret, subsecret_len,
00258                         out_sha1, out_len, seeds );
00259         va_end ( tmp );
00260 
00261         /* XOR the two portions together into the final output buffer */
00262         for ( i = 0 ; i < out_len ; i++ ) {
00263                 *( ( uint8_t * ) out + i ) = ( out_md5[i] ^ out_sha1[i] );
00264         }
00265 
00266         va_end ( seeds );
00267 }
00268 
00269 /**
00270  * Generate secure pseudo-random data
00271  *
00272  * @v secret            Secret
00273  * @v secret_len        Length of secret
00274  * @v out               Output buffer
00275  * @v out_len           Length of output buffer
00276  * @v label             String literal label
00277  * @v ...               ( data, len ) pairs of seed data
00278  */
00279 #define tls_prf_label( tls, secret, secret_len, out, out_len, label, ... ) \
00280         tls_prf ( (tls), (secret), (secret_len), (out), (out_len),         \
00281                   label, ( sizeof ( label ) - 1 ), __VA_ARGS__, NULL )
00282 
00283 /******************************************************************************
00284  *
00285  * Secret management
00286  *
00287  ******************************************************************************
00288  */
00289 
00290 /**
00291  * Generate master secret
00292  *
00293  * @v tls               TLS session
00294  *
00295  * The pre-master secret and the client and server random values must
00296  * already be known.
00297  */
00298 static void tls_generate_master_secret ( struct tls_session *tls ) {
00299         DBGC ( tls, "TLS %p pre-master-secret:\n", tls );
00300         DBGC_HD ( tls, &tls->pre_master_secret,
00301                   sizeof ( tls->pre_master_secret ) );
00302         DBGC ( tls, "TLS %p client random bytes:\n", tls );
00303         DBGC_HD ( tls, &tls->client_random, sizeof ( tls->client_random ) );
00304         DBGC ( tls, "TLS %p server random bytes:\n", tls );
00305         DBGC_HD ( tls, &tls->server_random, sizeof ( tls->server_random ) );
00306 
00307         tls_prf_label ( tls, &tls->pre_master_secret,
00308                         sizeof ( tls->pre_master_secret ),
00309                         &tls->master_secret, sizeof ( tls->master_secret ),
00310                         "master secret",
00311                         &tls->client_random, sizeof ( tls->client_random ),
00312                         &tls->server_random, sizeof ( tls->server_random ) );
00313 
00314         DBGC ( tls, "TLS %p generated master secret:\n", tls );
00315         DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
00316 }
00317 
00318 /**
00319  * Generate key material
00320  *
00321  * @v tls               TLS session
00322  *
00323  * The master secret must already be known.
00324  */
00325 static int tls_generate_keys ( struct tls_session *tls ) {
00326         struct tls_cipherspec *tx_cipherspec = &tls->tx_cipherspec_pending;
00327         struct tls_cipherspec *rx_cipherspec = &tls->rx_cipherspec_pending;
00328         size_t hash_size = tx_cipherspec->digest->digestsize;
00329         size_t key_size = tx_cipherspec->key_len;
00330         size_t iv_size = tx_cipherspec->cipher->blocksize;
00331         size_t total = ( 2 * ( hash_size + key_size + iv_size ) );
00332         uint8_t key_block[total];
00333         uint8_t *key;
00334         int rc;
00335 
00336         /* Generate key block */
00337         tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
00338                         key_block, sizeof ( key_block ), "key expansion",
00339                         &tls->server_random, sizeof ( tls->server_random ),
00340                         &tls->client_random, sizeof ( tls->client_random ) );
00341 
00342         /* Split key block into portions */
00343         key = key_block;
00344 
00345         /* TX MAC secret */
00346         memcpy ( tx_cipherspec->mac_secret, key, hash_size );
00347         DBGC ( tls, "TLS %p TX MAC secret:\n", tls );
00348         DBGC_HD ( tls, key, hash_size );
00349         key += hash_size;
00350 
00351         /* RX MAC secret */
00352         memcpy ( rx_cipherspec->mac_secret, key, hash_size );
00353         DBGC ( tls, "TLS %p RX MAC secret:\n", tls );
00354         DBGC_HD ( tls, key, hash_size );
00355         key += hash_size;
00356 
00357         /* TX key */
00358         if ( ( rc = cipher_setkey ( tx_cipherspec->cipher,
00359                                     tx_cipherspec->cipher_ctx,
00360                                     key, key_size ) ) != 0 ) {
00361                 DBGC ( tls, "TLS %p could not set TX key: %s\n",
00362                        tls, strerror ( rc ) );
00363                 return rc;
00364         }
00365         DBGC ( tls, "TLS %p TX key:\n", tls );
00366         DBGC_HD ( tls, key, key_size );
00367         key += key_size;
00368 
00369         /* RX key */
00370         if ( ( rc = cipher_setkey ( rx_cipherspec->cipher,
00371                                     rx_cipherspec->cipher_ctx,
00372                                     key, key_size ) ) != 0 ) {
00373                 DBGC ( tls, "TLS %p could not set TX key: %s\n",
00374                        tls, strerror ( rc ) );
00375                 return rc;
00376         }
00377         DBGC ( tls, "TLS %p RX key:\n", tls );
00378         DBGC_HD ( tls, key, key_size );
00379         key += key_size;
00380 
00381         /* TX initialisation vector */
00382         cipher_setiv ( tx_cipherspec->cipher, tx_cipherspec->cipher_ctx, key );
00383         DBGC ( tls, "TLS %p TX IV:\n", tls );
00384         DBGC_HD ( tls, key, iv_size );
00385         key += iv_size;
00386 
00387         /* RX initialisation vector */
00388         cipher_setiv ( rx_cipherspec->cipher, rx_cipherspec->cipher_ctx, key );
00389         DBGC ( tls, "TLS %p RX IV:\n", tls );
00390         DBGC_HD ( tls, key, iv_size );
00391         key += iv_size;
00392 
00393         assert ( ( key_block + total ) == key );
00394 
00395         return 0;
00396 }
00397 
00398 /******************************************************************************
00399  *
00400  * Cipher suite management
00401  *
00402  ******************************************************************************
00403  */
00404 
00405 /**
00406  * Clear cipher suite
00407  *
00408  * @v cipherspec        TLS cipher specification
00409  */
00410 static void tls_clear_cipher ( struct tls_session *tls __unused,
00411                                struct tls_cipherspec *cipherspec ) {
00412         free ( cipherspec->dynamic );
00413         memset ( cipherspec, 0, sizeof ( cipherspec ) );
00414         cipherspec->pubkey = &pubkey_null;
00415         cipherspec->cipher = &cipher_null;
00416         cipherspec->digest = &digest_null;
00417 }
00418 
00419 /**
00420  * Set cipher suite
00421  *
00422  * @v tls               TLS session
00423  * @v cipherspec        TLS cipher specification
00424  * @v pubkey            Public-key encryption elgorithm
00425  * @v cipher            Bulk encryption cipher algorithm
00426  * @v digest            MAC digest algorithm
00427  * @v key_len           Key length
00428  * @ret rc              Return status code
00429  */
00430 static int tls_set_cipher ( struct tls_session *tls,
00431                             struct tls_cipherspec *cipherspec,
00432                             struct pubkey_algorithm *pubkey,
00433                             struct cipher_algorithm *cipher,
00434                             struct digest_algorithm *digest,
00435                             size_t key_len ) {
00436         size_t total;
00437         void *dynamic;
00438 
00439         /* Clear out old cipher contents, if any */
00440         tls_clear_cipher ( tls, cipherspec );
00441         
00442         /* Allocate dynamic storage */
00443         total = ( pubkey->ctxsize + 2 * cipher->ctxsize + digest->digestsize );
00444         dynamic = malloc ( total );
00445         if ( ! dynamic ) {
00446                 DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
00447                        "context\n", tls, total );
00448                 return -ENOMEM;
00449         }
00450         memset ( dynamic, 0, total );
00451 
00452         /* Assign storage */
00453         cipherspec->dynamic = dynamic;
00454         cipherspec->pubkey_ctx = dynamic;       dynamic += pubkey->ctxsize;
00455         cipherspec->cipher_ctx = dynamic;       dynamic += cipher->ctxsize;
00456         cipherspec->cipher_next_ctx = dynamic;  dynamic += cipher->ctxsize;
00457         cipherspec->mac_secret = dynamic;       dynamic += digest->digestsize;
00458         assert ( ( cipherspec->dynamic + total ) == dynamic );
00459 
00460         /* Store parameters */
00461         cipherspec->pubkey = pubkey;
00462         cipherspec->cipher = cipher;
00463         cipherspec->digest = digest;
00464         cipherspec->key_len = key_len;
00465 
00466         return 0;
00467 }
00468 
00469 /**
00470  * Select next cipher suite
00471  *
00472  * @v tls               TLS session
00473  * @v cipher_suite      Cipher suite specification
00474  * @ret rc              Return status code
00475  */
00476 static int tls_select_cipher ( struct tls_session *tls,
00477                                unsigned int cipher_suite ) {
00478         struct pubkey_algorithm *pubkey = &pubkey_null;
00479         struct cipher_algorithm *cipher = &cipher_null;
00480         struct digest_algorithm *digest = &digest_null;
00481         unsigned int key_len = 0;
00482         int rc;
00483 
00484         switch ( cipher_suite ) {
00485         case htons ( TLS_RSA_WITH_AES_128_CBC_SHA ):
00486                 key_len = ( 128 / 8 );
00487                 cipher = &aes_cbc_algorithm;
00488                 digest = &sha1_algorithm;
00489                 break;
00490         case htons ( TLS_RSA_WITH_AES_256_CBC_SHA ):
00491                 key_len = ( 256 / 8 );
00492                 cipher = &aes_cbc_algorithm;
00493                 digest = &sha1_algorithm;
00494                 break;
00495         default:
00496                 DBGC ( tls, "TLS %p does not support cipher %04x\n",
00497                        tls, ntohs ( cipher_suite ) );
00498                 return -ENOTSUP;
00499         }
00500 
00501         /* Set ciphers */
00502         if ( ( rc = tls_set_cipher ( tls, &tls->tx_cipherspec_pending, pubkey,
00503                                      cipher, digest, key_len ) ) != 0 )
00504                 return rc;
00505         if ( ( rc = tls_set_cipher ( tls, &tls->rx_cipherspec_pending, pubkey,
00506                                      cipher, digest, key_len ) ) != 0 )
00507                 return rc;
00508 
00509         DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls,
00510                pubkey->name, cipher->name, ( key_len * 8 ), digest->name );
00511 
00512         return 0;
00513 }
00514 
00515 /**
00516  * Activate next cipher suite
00517  *
00518  * @v tls               TLS session
00519  * @v pending           Pending cipher specification
00520  * @v active            Active cipher specification to replace
00521  * @ret rc              Return status code
00522  */
00523 static int tls_change_cipher ( struct tls_session *tls,
00524                                struct tls_cipherspec *pending,
00525                                struct tls_cipherspec *active ) {
00526 
00527         /* Sanity check */
00528         if ( /* FIXME (when pubkey is not hard-coded to RSA):
00529               * ( pending->pubkey == &pubkey_null ) || */
00530              ( pending->cipher == &cipher_null ) ||
00531              ( pending->digest == &digest_null ) ) {
00532                 DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
00533                 return -ENOTSUP;
00534         }
00535 
00536         tls_clear_cipher ( tls, active );
00537         memswap ( active, pending, sizeof ( *active ) );
00538         return 0;
00539 }
00540 
00541 /******************************************************************************
00542  *
00543  * Handshake verification
00544  *
00545  ******************************************************************************
00546  */
00547 
00548 /**
00549  * Add handshake record to verification hash
00550  *
00551  * @v tls               TLS session
00552  * @v data              Handshake record
00553  * @v len               Length of handshake record
00554  */
00555 static void tls_add_handshake ( struct tls_session *tls,
00556                                 const void *data, size_t len ) {
00557 
00558         digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len );
00559         digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len );
00560 }
00561 
00562 /**
00563  * Calculate handshake verification hash
00564  *
00565  * @v tls               TLS session
00566  * @v out               Output buffer
00567  *
00568  * Calculates the MD5+SHA1 digest over all handshake messages seen so
00569  * far.
00570  */
00571 static void tls_verify_handshake ( struct tls_session *tls, void *out ) {
00572         struct digest_algorithm *md5 = &md5_algorithm;
00573         struct digest_algorithm *sha1 = &sha1_algorithm;
00574         uint8_t md5_ctx[md5->ctxsize];
00575         uint8_t sha1_ctx[sha1->ctxsize];
00576         void *md5_digest = out;
00577         void *sha1_digest = ( out + md5->digestsize );
00578 
00579         memcpy ( md5_ctx, tls->handshake_md5_ctx, sizeof ( md5_ctx ) );
00580         memcpy ( sha1_ctx, tls->handshake_sha1_ctx, sizeof ( sha1_ctx ) );
00581         digest_final ( md5, md5_ctx, md5_digest );
00582         digest_final ( sha1, sha1_ctx, sha1_digest );
00583 }
00584 
00585 /******************************************************************************
00586  *
00587  * Record handling
00588  *
00589  ******************************************************************************
00590  */
00591 
00592 /**
00593  * Transmit Handshake record
00594  *
00595  * @v tls               TLS session
00596  * @v data              Plaintext record
00597  * @v len               Length of plaintext record
00598  * @ret rc              Return status code
00599  */
00600 static int tls_send_handshake ( struct tls_session *tls,
00601                                 void *data, size_t len ) {
00602 
00603         /* Add to handshake digest */
00604         tls_add_handshake ( tls, data, len );
00605 
00606         /* Send record */
00607         return tls_send_plaintext ( tls, TLS_TYPE_HANDSHAKE, data, len );
00608 }
00609 
00610 /**
00611  * Transmit Client Hello record
00612  *
00613  * @v tls               TLS session
00614  * @ret rc              Return status code
00615  */
00616 static int tls_send_client_hello ( struct tls_session *tls ) {
00617         struct {
00618                 uint32_t type_length;
00619                 uint16_t version;
00620                 uint8_t random[32];
00621                 uint8_t session_id_len;
00622                 uint16_t cipher_suite_len;
00623                 uint16_t cipher_suites[2];
00624                 uint8_t compression_methods_len;
00625                 uint8_t compression_methods[1];
00626         } __attribute__ (( packed )) hello;
00627 
00628         memset ( &hello, 0, sizeof ( hello ) );
00629         hello.type_length = ( cpu_to_le32 ( TLS_CLIENT_HELLO ) |
00630                               htonl ( sizeof ( hello ) -
00631                                       sizeof ( hello.type_length ) ) );
00632         hello.version = htons ( TLS_VERSION_TLS_1_0 );
00633         memcpy ( &hello.random, &tls->client_random, sizeof ( hello.random ) );
00634         hello.cipher_suite_len = htons ( sizeof ( hello.cipher_suites ) );
00635         hello.cipher_suites[0] = htons ( TLS_RSA_WITH_AES_128_CBC_SHA );
00636         hello.cipher_suites[1] = htons ( TLS_RSA_WITH_AES_256_CBC_SHA );
00637         hello.compression_methods_len = sizeof ( hello.compression_methods );
00638 
00639         return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
00640 }
00641 
00642 /**
00643  * Transmit Client Key Exchange record
00644  *
00645  * @v tls               TLS session
00646  * @ret rc              Return status code
00647  */
00648 static int tls_send_client_key_exchange ( struct tls_session *tls ) {
00649         /* FIXME: Hack alert */
00650         RSA_CTX *rsa_ctx;
00651         RSA_pub_key_new ( &rsa_ctx, tls->rsa.modulus, tls->rsa.modulus_len,
00652                           tls->rsa.exponent, tls->rsa.exponent_len );
00653         struct {
00654                 uint32_t type_length;
00655                 uint16_t encrypted_pre_master_secret_len;
00656                 uint8_t encrypted_pre_master_secret[rsa_ctx->num_octets];
00657         } __attribute__ (( packed )) key_xchg;
00658 
00659         memset ( &key_xchg, 0, sizeof ( key_xchg ) );
00660         key_xchg.type_length = ( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
00661                                  htonl ( sizeof ( key_xchg ) -
00662                                          sizeof ( key_xchg.type_length ) ) );
00663         key_xchg.encrypted_pre_master_secret_len
00664                 = htons ( sizeof ( key_xchg.encrypted_pre_master_secret ) );
00665 
00666         /* FIXME: Hack alert */
00667         DBGC ( tls, "RSA encrypting plaintext, modulus, exponent:\n" );
00668         DBGC_HD ( tls, &tls->pre_master_secret,
00669                   sizeof ( tls->pre_master_secret ) );
00670         DBGC_HD ( tls, tls->rsa.modulus, tls->rsa.modulus_len );
00671         DBGC_HD ( tls, tls->rsa.exponent, tls->rsa.exponent_len );
00672         RSA_encrypt ( rsa_ctx, ( const uint8_t * ) &tls->pre_master_secret,
00673                       sizeof ( tls->pre_master_secret ),
00674                       key_xchg.encrypted_pre_master_secret, 0 );
00675         DBGC ( tls, "RSA encrypt done.  Ciphertext:\n" );
00676         DBGC_HD ( tls, &key_xchg.encrypted_pre_master_secret,
00677                   sizeof ( key_xchg.encrypted_pre_master_secret ) );
00678         RSA_free ( rsa_ctx );
00679 
00680 
00681         return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) );
00682 }
00683 
00684 /**
00685  * Transmit Change Cipher record
00686  *
00687  * @v tls               TLS session
00688  * @ret rc              Return status code
00689  */
00690 static int tls_send_change_cipher ( struct tls_session *tls ) {
00691         static const uint8_t change_cipher[1] = { 1 };
00692         return tls_send_plaintext ( tls, TLS_TYPE_CHANGE_CIPHER,
00693                                     change_cipher, sizeof ( change_cipher ) );
00694 }
00695 
00696 /**
00697  * Transmit Finished record
00698  *
00699  * @v tls               TLS session
00700  * @ret rc              Return status code
00701  */
00702 static int tls_send_finished ( struct tls_session *tls ) {
00703         struct {
00704                 uint32_t type_length;
00705                 uint8_t verify_data[12];
00706         } __attribute__ (( packed )) finished;
00707         uint8_t digest[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
00708 
00709         memset ( &finished, 0, sizeof ( finished ) );
00710         finished.type_length = ( cpu_to_le32 ( TLS_FINISHED ) |
00711                                  htonl ( sizeof ( finished ) -
00712                                          sizeof ( finished.type_length ) ) );
00713         tls_verify_handshake ( tls, digest );
00714         tls_prf_label ( tls, &tls->master_secret, sizeof ( tls->master_secret ),
00715                         finished.verify_data, sizeof ( finished.verify_data ),
00716                         "client finished", digest, sizeof ( digest ) );
00717 
00718         return tls_send_handshake ( tls, &finished, sizeof ( finished ) );
00719 }
00720 
00721 /**
00722  * Receive new Change Cipher record
00723  *
00724  * @v tls               TLS session
00725  * @v data              Plaintext record
00726  * @v len               Length of plaintext record
00727  * @ret rc              Return status code
00728  */
00729 static int tls_new_change_cipher ( struct tls_session *tls,
00730                                    void *data, size_t len ) {
00731         int rc;
00732 
00733         if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) {
00734                 DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
00735                 DBGC_HD ( tls, data, len );
00736                 return -EINVAL;
00737         }
00738 
00739         if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending,
00740                                         &tls->rx_cipherspec ) ) != 0 ) {
00741                 DBGC ( tls, "TLS %p could not activate RX cipher: %s\n",
00742                        tls, strerror ( rc ) );
00743                 return rc;
00744         }
00745         tls->rx_seq = ~( ( uint64_t ) 0 );
00746 
00747         return 0;
00748 }
00749 
00750 /**
00751  * Receive new Alert record
00752  *
00753  * @v tls               TLS session
00754  * @v data              Plaintext record
00755  * @v len               Length of plaintext record
00756  * @ret rc              Return status code
00757  */
00758 static int tls_new_alert ( struct tls_session *tls, void *data, size_t len ) {
00759         struct {
00760                 uint8_t level;
00761                 uint8_t description;
00762                 char next[0];
00763         } __attribute__ (( packed )) *alert = data;
00764         void *end = alert->next;
00765 
00766         /* Sanity check */
00767         if ( end != ( data + len ) ) {
00768                 DBGC ( tls, "TLS %p received overlength Alert\n", tls );
00769                 DBGC_HD ( tls, data, len );
00770                 return -EINVAL;
00771         }
00772 
00773         switch ( alert->level ) {
00774         case TLS_ALERT_WARNING:
00775                 DBGC ( tls, "TLS %p received warning alert %d\n",
00776                        tls, alert->description );
00777                 return 0;
00778         case TLS_ALERT_FATAL:
00779                 DBGC ( tls, "TLS %p received fatal alert %d\n",
00780                        tls, alert->description );
00781                 return -EPERM;
00782         default:
00783                 DBGC ( tls, "TLS %p received unknown alert level %d"
00784                        "(alert %d)\n", tls, alert->level, alert->description );
00785                 return -EIO;
00786         }
00787 }
00788 
00789 /**
00790  * Receive new Server Hello handshake record
00791  *
00792  * @v tls               TLS session
00793  * @v data              Plaintext handshake record
00794  * @v len               Length of plaintext handshake record
00795  * @ret rc              Return status code
00796  */
00797 static int tls_new_server_hello ( struct tls_session *tls,
00798                                   void *data, size_t len ) {
00799         struct {
00800                 uint16_t version;
00801                 uint8_t random[32];
00802                 uint8_t session_id_len;
00803                 char next[0];
00804         } __attribute__ (( packed )) *hello_a = data;
00805         struct {
00806                 uint8_t session_id[hello_a->session_id_len];
00807                 uint16_t cipher_suite;
00808                 uint8_t compression_method;
00809                 char next[0];
00810         } __attribute__ (( packed )) *hello_b = ( void * ) &hello_a->next;
00811         void *end = hello_b->next;
00812         int rc;
00813 
00814         /* Sanity check */
00815         if ( end != ( data + len ) ) {
00816                 DBGC ( tls, "TLS %p received overlength Server Hello\n", tls );
00817                 DBGC_HD ( tls, data, len );
00818                 return -EINVAL;
00819         }
00820 
00821         /* Check protocol version */
00822         if ( ntohs ( hello_a->version ) < TLS_VERSION_TLS_1_0 ) {
00823                 DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
00824                        tls, ( ntohs ( hello_a->version ) >> 8 ),
00825                        ( ntohs ( hello_a->version ) & 0xff ) );
00826                 return -ENOTSUP;
00827         }
00828 
00829         /* Copy out server random bytes */
00830         memcpy ( &tls->server_random, &hello_a->random,
00831                  sizeof ( tls->server_random ) );
00832 
00833         /* Select cipher suite */
00834         if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
00835                 return rc;
00836 
00837         /* Generate secrets */
00838         tls_generate_master_secret ( tls );
00839         if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
00840                 return rc;
00841 
00842         return 0;
00843 }
00844 
00845 /**
00846  * Receive new Certificate handshake record
00847  *
00848  * @v tls               TLS session
00849  * @v data              Plaintext handshake record
00850  * @v len               Length of plaintext handshake record
00851  * @ret rc              Return status code
00852  */
00853 static int tls_new_certificate ( struct tls_session *tls,
00854                                  void *data, size_t len ) {
00855         struct {
00856                 uint8_t length[3];
00857                 uint8_t certificates[0];
00858         } __attribute__ (( packed )) *certificate = data;
00859         struct {
00860                 uint8_t length[3];
00861                 uint8_t certificate[0];
00862         } __attribute__ (( packed )) *element =
00863                   ( ( void * ) certificate->certificates );
00864         size_t elements_len = tls_uint24 ( certificate->length );
00865         void *end = ( certificate->certificates + elements_len );
00866         struct asn1_cursor cursor;
00867         int rc;
00868 
00869         /* Sanity check */
00870         if ( end != ( data + len ) ) {
00871                 DBGC ( tls, "TLS %p received overlength Server Certificate\n",
00872                        tls );
00873                 DBGC_HD ( tls, data, len );
00874                 return -EINVAL;
00875         }
00876 
00877         /* Traverse certificate chain */
00878         do {
00879                 cursor.data = element->certificate;
00880                 cursor.len = tls_uint24 ( element->length );
00881                 if ( ( cursor.data + cursor.len ) > end ) {
00882                         DBGC ( tls, "TLS %p received corrupt Server "
00883                                "Certificate\n", tls );
00884                         DBGC_HD ( tls, data, len );
00885                         return -EINVAL;
00886                 }
00887 
00888                 // HACK
00889                 if ( ( rc = x509_rsa_public_key ( &cursor,
00890                                                   &tls->rsa ) ) != 0 ) {
00891                         DBGC ( tls, "TLS %p cannot determine RSA public key: "
00892                                "%s\n", tls, strerror ( rc ) );
00893                         return rc;
00894                 }
00895                 return 0;
00896 
00897                 element = ( cursor.data + cursor.len );
00898         } while ( element != end );
00899 
00900         return -EINVAL;
00901 }
00902 
00903 /**
00904  * Receive new Server Hello Done handshake record
00905  *
00906  * @v tls               TLS session
00907  * @v data              Plaintext handshake record
00908  * @v len               Length of plaintext handshake record
00909  * @ret rc              Return status code
00910  */
00911 static int tls_new_server_hello_done ( struct tls_session *tls,
00912                                        void *data, size_t len ) {
00913         struct {
00914                 char next[0];
00915         } __attribute__ (( packed )) *hello_done = data;
00916         void *end = hello_done->next;
00917 
00918         /* Sanity check */
00919         if ( end != ( data + len ) ) {
00920                 DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
00921                        tls );
00922                 DBGC_HD ( tls, data, len );
00923                 return -EINVAL;
00924         }
00925 
00926         /* Check that we are ready to send the Client Key Exchange */
00927         if ( tls->tx_state != TLS_TX_NONE ) {
00928                 DBGC ( tls, "TLS %p received Server Hello Done while in "
00929                        "TX state %d\n", tls, tls->tx_state );
00930                 return -EIO;
00931         }
00932 
00933         /* Start sending the Client Key Exchange */
00934         tls->tx_state = TLS_TX_CLIENT_KEY_EXCHANGE;
00935 
00936         return 0;
00937 }
00938 
00939 /**
00940  * Receive new Finished handshake record
00941  *
00942  * @v tls               TLS session
00943  * @v data              Plaintext handshake record
00944  * @v len               Length of plaintext handshake record
00945  * @ret rc              Return status code
00946  */
00947 static int tls_new_finished ( struct tls_session *tls,
00948                               void *data, size_t len ) {
00949 
00950         /* FIXME: Handle this properly */
00951         tls->tx_state = TLS_TX_DATA;
00952         ( void ) data;
00953         ( void ) len;
00954         return 0;
00955 }
00956 
00957 /**
00958  * Receive new Handshake record
00959  *
00960  * @v tls               TLS session
00961  * @v data              Plaintext record
00962  * @v len               Length of plaintext record
00963  * @ret rc              Return status code
00964  */
00965 static int tls_new_handshake ( struct tls_session *tls,
00966                                void *data, size_t len ) {
00967         struct {
00968                 uint8_t type;
00969                 uint8_t length[3];
00970                 uint8_t payload[0];
00971         } __attribute__ (( packed )) *handshake = data;
00972         void *payload = &handshake->payload;
00973         size_t payload_len = tls_uint24 ( handshake->length );
00974         void *end = ( payload + payload_len );
00975         int rc;
00976 
00977         /* Sanity check */
00978         if ( end != ( data + len ) ) {
00979                 DBGC ( tls, "TLS %p received overlength Handshake\n", tls );
00980                 DBGC_HD ( tls, data, len );
00981                 return -EINVAL;
00982         }
00983 
00984         switch ( handshake->type ) {
00985         case TLS_SERVER_HELLO:
00986                 rc = tls_new_server_hello ( tls, payload, payload_len );
00987                 break;
00988         case TLS_CERTIFICATE:
00989                 rc = tls_new_certificate ( tls, payload, payload_len );
00990                 break;
00991         case TLS_SERVER_HELLO_DONE:
00992                 rc = tls_new_server_hello_done ( tls, payload, payload_len );
00993                 break;
00994         case TLS_FINISHED:
00995                 rc = tls_new_finished ( tls, payload, payload_len );
00996                 break;
00997         default:
00998                 DBGC ( tls, "TLS %p ignoring handshake type %d\n",
00999                        tls, handshake->type );
01000                 rc = 0;
01001                 break;
01002         }
01003 
01004         /* Add to handshake digest (except for Hello Requests, which
01005          * are explicitly excluded).
01006          */
01007         if ( handshake->type != TLS_HELLO_REQUEST )
01008                 tls_add_handshake ( tls, data, len );
01009 
01010         return rc;
01011 }
01012 
01013 /**
01014  * Receive new record
01015  *
01016  * @v tls               TLS session
01017  * @v type              Record type
01018  * @v data              Plaintext record
01019  * @v len               Length of plaintext record
01020  * @ret rc              Return status code
01021  */
01022 static int tls_new_record ( struct tls_session *tls,
01023                             unsigned int type, void *data, size_t len ) {
01024 
01025         switch ( type ) {
01026         case TLS_TYPE_CHANGE_CIPHER:
01027                 return tls_new_change_cipher ( tls, data, len );
01028         case TLS_TYPE_ALERT:
01029                 return tls_new_alert ( tls, data, len );
01030         case TLS_TYPE_HANDSHAKE:
01031                 return tls_new_handshake ( tls, data, len );
01032         case TLS_TYPE_DATA:
01033                 return xfer_deliver_raw ( &tls->plainstream.xfer, data, len );
01034         default:
01035                 /* RFC4346 says that we should just ignore unknown
01036                  * record types.
01037                  */
01038                 DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
01039                 return 0;
01040         }
01041 }
01042 
01043 /******************************************************************************
01044  *
01045  * Record encryption/decryption
01046  *
01047  ******************************************************************************
01048  */
01049 
01050 /**
01051  * Calculate HMAC
01052  *
01053  * @v tls               TLS session
01054  * @v cipherspec        Cipher specification
01055  * @v seq               Sequence number
01056  * @v tlshdr            TLS header
01057  * @v data              Data
01058  * @v len               Length of data
01059  * @v mac               HMAC to fill in
01060  */
01061 static void tls_hmac ( struct tls_session *tls __unused,
01062                        struct tls_cipherspec *cipherspec,
01063                        uint64_t seq, struct tls_header *tlshdr,
01064                        const void *data, size_t len, void *hmac ) {
01065         struct digest_algorithm *digest = cipherspec->digest;
01066         uint8_t digest_ctx[digest->ctxsize];
01067 
01068         hmac_init ( digest, digest_ctx, cipherspec->mac_secret,
01069                     &digest->digestsize );
01070         seq = cpu_to_be64 ( seq );
01071         hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) );
01072         hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) );
01073         hmac_update ( digest, digest_ctx, data, len );
01074         hmac_final ( digest, digest_ctx, cipherspec->mac_secret,
01075                      &digest->digestsize, hmac );
01076 }
01077 
01078 /**
01079  * Allocate and assemble stream-ciphered record from data and MAC portions
01080  *
01081  * @v tls               TLS session
01082  * @ret data            Data
01083  * @ret len             Length of data
01084  * @ret digest          MAC digest
01085  * @ret plaintext_len   Length of plaintext record
01086  * @ret plaintext       Allocated plaintext record
01087  */
01088 static void * __malloc tls_assemble_stream ( struct tls_session *tls,
01089                                     const void *data, size_t len,
01090                                     void *digest, size_t *plaintext_len ) {
01091         size_t mac_len = tls->tx_cipherspec.digest->digestsize;
01092         void *plaintext;
01093         void *content;
01094         void *mac;
01095 
01096         /* Calculate stream-ciphered struct length */
01097         *plaintext_len = ( len + mac_len );
01098 
01099         /* Allocate stream-ciphered struct */
01100         plaintext = malloc ( *plaintext_len );
01101         if ( ! plaintext )
01102                 return NULL;
01103         content = plaintext;
01104         mac = ( content + len );
01105 
01106         /* Fill in stream-ciphered struct */
01107         memcpy ( content, data, len );
01108         memcpy ( mac, digest, mac_len );
01109 
01110         return plaintext;
01111 }
01112 
01113 /**
01114  * Allocate and assemble block-ciphered record from data and MAC portions
01115  *
01116  * @v tls               TLS session
01117  * @ret data            Data
01118  * @ret len             Length of data
01119  * @ret digest          MAC digest
01120  * @ret plaintext_len   Length of plaintext record
01121  * @ret plaintext       Allocated plaintext record
01122  */
01123 static void * tls_assemble_block ( struct tls_session *tls,
01124                                    const void *data, size_t len,
01125                                    void *digest, size_t *plaintext_len ) {
01126         size_t blocksize = tls->tx_cipherspec.cipher->blocksize;
01127         size_t iv_len = blocksize;
01128         size_t mac_len = tls->tx_cipherspec.digest->digestsize;
01129         size_t padding_len;
01130         void *plaintext;
01131         void *iv;
01132         void *content;
01133         void *mac;
01134         void *padding;
01135 
01136         /* FIXME: TLSv1.1 has an explicit IV */
01137         iv_len = 0;
01138 
01139         /* Calculate block-ciphered struct length */
01140         padding_len = ( ( blocksize - 1 ) & -( iv_len + len + mac_len + 1 ) );
01141         *plaintext_len = ( iv_len + len + mac_len + padding_len + 1 );
01142 
01143         /* Allocate block-ciphered struct */
01144         plaintext = malloc ( *plaintext_len );
01145         if ( ! plaintext )
01146                 return NULL;
01147         iv = plaintext;
01148         content = ( iv + iv_len );
01149         mac = ( content + len );
01150         padding = ( mac + mac_len );
01151 
01152         /* Fill in block-ciphered struct */
01153         memset ( iv, 0, iv_len );
01154         memcpy ( content, data, len );
01155         memcpy ( mac, digest, mac_len );
01156         memset ( padding, padding_len, ( padding_len + 1 ) );
01157 
01158         return plaintext;
01159 }
01160 
01161 /**
01162  * Send plaintext record
01163  *
01164  * @v tls               TLS session
01165  * @v type              Record type
01166  * @v data              Plaintext record
01167  * @v len               Length of plaintext record
01168  * @ret rc              Return status code
01169  */
01170 static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
01171                                 const void *data, size_t len ) {
01172         struct tls_header plaintext_tlshdr;
01173         struct tls_header *tlshdr;
01174         struct tls_cipherspec *cipherspec = &tls->tx_cipherspec;
01175         void *plaintext = NULL;
01176         size_t plaintext_len;
01177         struct io_buffer *ciphertext = NULL;
01178         size_t ciphertext_len;
01179         size_t mac_len = cipherspec->digest->digestsize;
01180         uint8_t mac[mac_len];
01181         int rc;
01182 
01183         /* Construct header */
01184         plaintext_tlshdr.type = type;
01185         plaintext_tlshdr.version = htons ( TLS_VERSION_TLS_1_0 );
01186         plaintext_tlshdr.length = htons ( len );
01187 
01188         /* Calculate MAC */
01189         tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr,
01190                    data, len, mac );
01191 
01192         /* Allocate and assemble plaintext struct */
01193         if ( is_stream_cipher ( cipherspec->cipher ) ) {
01194                 plaintext = tls_assemble_stream ( tls, data, len, mac,
01195                                                   &plaintext_len );
01196         } else {
01197                 plaintext = tls_assemble_block ( tls, data, len, mac,
01198                                                  &plaintext_len );
01199         }
01200         if ( ! plaintext ) {
01201                 DBGC ( tls, "TLS %p could not allocate %zd bytes for "
01202                        "plaintext\n", tls, plaintext_len );
01203                 rc = -ENOMEM;
01204                 goto done;
01205         }
01206 
01207         DBGC2 ( tls, "Sending plaintext data:\n" );
01208         DBGC2_HD ( tls, plaintext, plaintext_len );
01209 
01210         /* Allocate ciphertext */
01211         ciphertext_len = ( sizeof ( *tlshdr ) + plaintext_len );
01212         ciphertext = xfer_alloc_iob ( &tls->cipherstream.xfer,
01213                                       ciphertext_len );
01214         if ( ! ciphertext ) {
01215                 DBGC ( tls, "TLS %p could not allocate %zd bytes for "
01216                        "ciphertext\n", tls, ciphertext_len );
01217                 rc = -ENOMEM;
01218                 goto done;
01219         }
01220 
01221         /* Assemble ciphertext */
01222         tlshdr = iob_put ( ciphertext, sizeof ( *tlshdr ) );
01223         tlshdr->type = type;
01224         tlshdr->version = htons ( TLS_VERSION_TLS_1_0 );
01225         tlshdr->length = htons ( plaintext_len );
01226         memcpy ( cipherspec->cipher_next_ctx, cipherspec->cipher_ctx,
01227                  cipherspec->cipher->ctxsize );
01228         cipher_encrypt ( cipherspec->cipher, cipherspec->cipher_next_ctx,
01229                          plaintext, iob_put ( ciphertext, plaintext_len ),
01230                          plaintext_len );
01231 
01232         /* Free plaintext as soon as possible to conserve memory */
01233         free ( plaintext );
01234         plaintext = NULL;
01235 
01236         /* Send ciphertext */
01237         rc = xfer_deliver_iob ( &tls->cipherstream.xfer, ciphertext );
01238         ciphertext = NULL;
01239         if ( rc != 0 ) {
01240                 DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
01241                        tls, strerror ( rc ) );
01242                 goto done;
01243         }
01244 
01245         /* Update TX state machine to next record */
01246         tls->tx_seq += 1;
01247         memcpy ( tls->tx_cipherspec.cipher_ctx,
01248                  tls->tx_cipherspec.cipher_next_ctx,
01249                  tls->tx_cipherspec.cipher->ctxsize );
01250 
01251  done:
01252         free ( plaintext );
01253         free_iob ( ciphertext );
01254         return rc;
01255 }
01256 
01257 /**
01258  * Split stream-ciphered record into data and MAC portions
01259  *
01260  * @v tls               TLS session
01261  * @v plaintext         Plaintext record
01262  * @v plaintext_len     Length of record
01263  * @ret data            Data
01264  * @ret len             Length of data
01265  * @ret digest          MAC digest
01266  * @ret rc              Return status code
01267  */
01268 static int tls_split_stream ( struct tls_session *tls,
01269                               void *plaintext, size_t plaintext_len,
01270                               void **data, size_t *len, void **digest ) {
01271         void *content;
01272         size_t content_len;
01273         void *mac;
01274         size_t mac_len;
01275 
01276         /* Decompose stream-ciphered data */
01277         mac_len = tls->rx_cipherspec.digest->digestsize;
01278         if ( plaintext_len < mac_len ) {
01279                 DBGC ( tls, "TLS %p received underlength record\n", tls );
01280                 DBGC_HD ( tls, plaintext, plaintext_len );
01281                 return -EINVAL;
01282         }
01283         content_len = ( plaintext_len - mac_len );
01284         content = plaintext;
01285         mac = ( content + content_len );
01286 
01287         /* Fill in return values */
01288         *data = content;
01289         *len = content_len;
01290         *digest = mac;
01291 
01292         return 0;
01293 }
01294 
01295 /**
01296  * Split block-ciphered record into data and MAC portions
01297  *
01298  * @v tls               TLS session
01299  * @v plaintext         Plaintext record
01300  * @v plaintext_len     Length of record
01301  * @ret data            Data
01302  * @ret len             Length of data
01303  * @ret digest          MAC digest
01304  * @ret rc              Return status code
01305  */
01306 static int tls_split_block ( struct tls_session *tls,
01307                              void *plaintext, size_t plaintext_len,
01308                              void **data, size_t *len,
01309                              void **digest ) {
01310         void *iv;
01311         size_t iv_len;
01312         void *content;
01313         size_t content_len;
01314         void *mac;
01315         size_t mac_len;
01316         void *padding;
01317         size_t padding_len;
01318         unsigned int i;
01319 
01320         /* Decompose block-ciphered data */
01321         if ( plaintext_len < 1 ) {
01322                 DBGC ( tls, "TLS %p received underlength record\n", tls );
01323                 DBGC_HD ( tls, plaintext, plaintext_len );
01324                 return -EINVAL;
01325         }
01326         iv_len = tls->rx_cipherspec.cipher->blocksize;
01327 
01328         /* FIXME: TLSv1.1 uses an explicit IV */
01329         iv_len = 0;
01330 
01331         mac_len = tls->rx_cipherspec.digest->digestsize;
01332         padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
01333         if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
01334                 DBGC ( tls, "TLS %p received underlength record\n", tls );
01335                 DBGC_HD ( tls, plaintext, plaintext_len );
01336                 return -EINVAL;
01337         }
01338         content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 );
01339         iv = plaintext;
01340         content = ( iv + iv_len );
01341         mac = ( content + content_len );
01342         padding = ( mac + mac_len );
01343 
01344         /* Verify padding bytes */
01345         for ( i = 0 ; i < padding_len ; i++ ) {
01346                 if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) {
01347                         DBGC ( tls, "TLS %p received bad padding\n", tls );
01348                         DBGC_HD ( tls, plaintext, plaintext_len );
01349                         return -EINVAL;
01350                 }
01351         }
01352 
01353         /* Fill in return values */
01354         *data = content;
01355         *len = content_len;
01356         *digest = mac;
01357 
01358         return 0;
01359 }
01360 
01361 /**
01362  * Receive new ciphertext record
01363  *
01364  * @v tls               TLS session
01365  * @v tlshdr            Record header
01366  * @v ciphertext        Ciphertext record
01367  * @ret rc              Return status code
01368  */
01369 static int tls_new_ciphertext ( struct tls_session *tls,
01370                                 struct tls_header *tlshdr, void *ciphertext ) {
01371         struct tls_header plaintext_tlshdr;
01372         struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
01373         size_t record_len = ntohs ( tlshdr->length );
01374         void *plaintext = NULL;
01375         void *data;
01376         size_t len;
01377         void *mac;
01378         size_t mac_len = cipherspec->digest->digestsize;
01379         uint8_t verify_mac[mac_len];
01380         int rc;
01381 
01382         /* Allocate buffer for plaintext */
01383         plaintext = malloc ( record_len );
01384         if ( ! plaintext ) {
01385                 DBGC ( tls, "TLS %p could not allocate %zd bytes for "
01386                        "decryption buffer\n", tls, record_len );
01387                 rc = -ENOMEM;
01388                 goto done;
01389         }
01390 
01391         /* Decrypt the record */
01392         cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx,
01393                          ciphertext, plaintext, record_len );
01394 
01395         /* Split record into content and MAC */
01396         if ( is_stream_cipher ( cipherspec->cipher ) ) {
01397                 if ( ( rc = tls_split_stream ( tls, plaintext, record_len,
01398                                                &data, &len, &mac ) ) != 0 )
01399                         goto done;
01400         } else {
01401                 if ( ( rc = tls_split_block ( tls, plaintext, record_len,
01402                                               &data, &len, &mac ) ) != 0 )
01403                         goto done;
01404         }
01405 
01406         /* Verify MAC */
01407         plaintext_tlshdr.type = tlshdr->type;
01408         plaintext_tlshdr.version = tlshdr->version;
01409         plaintext_tlshdr.length = htons ( len );
01410         tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr,
01411                    data, len, verify_mac);
01412         if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) {
01413                 DBGC ( tls, "TLS %p failed MAC verification\n", tls );
01414                 DBGC_HD ( tls, plaintext, record_len );
01415                 goto done;
01416         }
01417 
01418         DBGC2 ( tls, "Received plaintext data:\n" );
01419         DBGC2_HD ( tls, data, len );
01420 
01421         /* Process plaintext record */
01422         if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 )
01423                 goto done;
01424 
01425         rc = 0;
01426  done:
01427         free ( plaintext );
01428         return rc;
01429 }
01430 
01431 /******************************************************************************
01432  *
01433  * Plaintext stream operations
01434  *
01435  ******************************************************************************
01436  */
01437 
01438 /**
01439  * Close interface
01440  *
01441  * @v xfer              Plainstream data transfer interface
01442  * @v rc                Reason for close
01443  */
01444 static void tls_plainstream_close ( struct xfer_interface *xfer, int rc ) {
01445         struct tls_session *tls =
01446                 container_of ( xfer, struct tls_session, plainstream.xfer );
01447 
01448         tls_close ( tls, rc );
01449 }
01450 
01451 /**
01452  * Check flow control window
01453  *
01454  * @v xfer              Plainstream data transfer interface
01455  * @ret len             Length of window
01456  */
01457 static size_t tls_plainstream_window ( struct xfer_interface *xfer ) {
01458         struct tls_session *tls =
01459                 container_of ( xfer, struct tls_session, plainstream.xfer );
01460 
01461         /* Block window unless we are ready to accept data */
01462         if ( tls->tx_state != TLS_TX_DATA )
01463                 return 0;
01464 
01465         return filter_window ( xfer );
01466 }
01467 
01468 /**
01469  * Deliver datagram as raw data
01470  *
01471  * @v xfer              Plainstream data transfer interface
01472  * @v data              Data buffer
01473  * @v len               Length of data buffer
01474  * @ret rc              Return status code
01475  */
01476 static int tls_plainstream_deliver_raw ( struct xfer_interface *xfer,
01477                                          const void *data, size_t len ) {
01478         struct tls_session *tls =
01479                 container_of ( xfer, struct tls_session, plainstream.xfer );
01480         
01481         /* Refuse unless we are ready to accept data */
01482         if ( tls->tx_state != TLS_TX_DATA )
01483                 return -ENOTCONN;
01484 
01485         return tls_send_plaintext ( tls, TLS_TYPE_DATA, data, len );
01486 }
01487 
01488 /** TLS plaintext stream operations */
01489 static struct xfer_interface_operations tls_plainstream_operations = {
01490         .close          = tls_plainstream_close,
01491         .vredirect      = ignore_xfer_vredirect,
01492         .window         = tls_plainstream_window,
01493         .alloc_iob      = default_xfer_alloc_iob,
01494         .deliver_iob    = xfer_deliver_as_raw,
01495         .deliver_raw    = tls_plainstream_deliver_raw,
01496 };
01497 
01498 /******************************************************************************
01499  *
01500  * Ciphertext stream operations
01501  *
01502  ******************************************************************************
01503  */
01504 
01505 /**
01506  * Close interface
01507  *
01508  * @v xfer              Plainstream data transfer interface
01509  * @v rc                Reason for close
01510  */
01511 static void tls_cipherstream_close ( struct xfer_interface *xfer, int rc ) {
01512         struct tls_session *tls =
01513                 container_of ( xfer, struct tls_session, cipherstream.xfer );
01514 
01515         tls_close ( tls, rc );
01516 }
01517 
01518 /**
01519  * Handle received TLS header
01520  *
01521  * @v tls               TLS session
01522  * @ret rc              Returned status code
01523  */
01524 static int tls_newdata_process_header ( struct tls_session *tls ) {
01525         size_t data_len = ntohs ( tls->rx_header.length );
01526 
01527         /* Allocate data buffer now that we know the length */
01528         assert ( tls->rx_data == NULL );
01529         tls->rx_data = malloc ( data_len );
01530         if ( ! tls->rx_data ) {
01531                 DBGC ( tls, "TLS %p could not allocate %zd bytes "
01532                        "for receive buffer\n", tls, data_len );
01533                 return -ENOMEM;
01534         }
01535 
01536         /* Move to data state */
01537         tls->rx_state = TLS_RX_DATA;
01538 
01539         return 0;
01540 }
01541 
01542 /**
01543  * Handle received TLS data payload
01544  *
01545  * @v tls               TLS session
01546  * @ret rc              Returned status code
01547  */
01548 static int tls_newdata_process_data ( struct tls_session *tls ) {
01549         int rc;
01550 
01551         /* Process record */
01552         if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
01553                                          tls->rx_data ) ) != 0 )
01554                 return rc;
01555 
01556         /* Increment RX sequence number */
01557         tls->rx_seq += 1;
01558 
01559         /* Free data buffer */
01560         free ( tls->rx_data );
01561         tls->rx_data = NULL;
01562 
01563         /* Return to header state */
01564         tls->rx_state = TLS_RX_HEADER;
01565 
01566         return 0;
01567 }
01568 
01569 /**
01570  * Receive new ciphertext
01571  *
01572  * @v app               Stream application
01573  * @v data              Data received
01574  * @v len               Length of received data
01575  * @ret rc              Return status code
01576  */
01577 static int tls_cipherstream_deliver_raw ( struct xfer_interface *xfer,
01578                                           const void *data, size_t len ) {
01579         struct tls_session *tls = 
01580                 container_of ( xfer, struct tls_session, cipherstream.xfer );
01581         size_t frag_len;
01582         void *buf;
01583         size_t buf_len;
01584         int ( * process ) ( struct tls_session *tls );
01585         int rc;
01586 
01587         while ( len ) {
01588                 /* Select buffer according to current state */
01589                 switch ( tls->rx_state ) {
01590                 case TLS_RX_HEADER:
01591                         buf = &tls->rx_header;
01592                         buf_len = sizeof ( tls->rx_header );
01593                         process = tls_newdata_process_header;
01594                         break;
01595                 case TLS_RX_DATA:
01596                         buf = tls->rx_data;
01597                         buf_len = ntohs ( tls->rx_header.length );
01598                         process = tls_newdata_process_data;
01599                         break;
01600                 default:
01601                         assert ( 0 );
01602                         return -EINVAL;
01603                 }
01604 
01605                 /* Copy data portion to buffer */
01606                 frag_len = ( buf_len - tls->rx_rcvd );
01607                 if ( frag_len > len )
01608                         frag_len = len;
01609                 memcpy ( ( buf + tls->rx_rcvd ), data, frag_len );
01610                 tls->rx_rcvd += frag_len;
01611                 data += frag_len;
01612                 len -= frag_len;
01613 
01614                 /* Process data if buffer is now full */
01615                 if ( tls->rx_rcvd == buf_len ) {
01616                         if ( ( rc = process ( tls ) ) != 0 ) {
01617                                 tls_close ( tls, rc );
01618                                 return rc;
01619                         }
01620                         tls->rx_rcvd = 0;
01621                 }
01622         }
01623 
01624         return 0;
01625 }
01626 
01627 /** TLS ciphertext stream operations */
01628 static struct xfer_interface_operations tls_cipherstream_operations = {
01629         .close          = tls_cipherstream_close,
01630         .vredirect      = xfer_vreopen,
01631         .window         = filter_window,
01632         .alloc_iob      = default_xfer_alloc_iob,
01633         .deliver_iob    = xfer_deliver_as_raw,
01634         .deliver_raw    = tls_cipherstream_deliver_raw,
01635 };
01636 
01637 /******************************************************************************
01638  *
01639  * Controlling process
01640  *
01641  ******************************************************************************
01642  */
01643 
01644 /**
01645  * TLS TX state machine
01646  *
01647  * @v process           TLS process
01648  */
01649 static void tls_step ( struct process *process ) {
01650         struct tls_session *tls =
01651                 container_of ( process, struct tls_session, process );
01652         int rc;
01653 
01654         /* Wait for cipherstream to become ready */
01655         if ( ! xfer_window ( &tls->cipherstream.xfer ) )
01656                 return;
01657 
01658         switch ( tls->tx_state ) {
01659         case TLS_TX_NONE:
01660                 /* Nothing to do */
01661                 break;
01662         case TLS_TX_CLIENT_HELLO:
01663                 /* Send Client Hello */
01664                 if ( ( rc = tls_send_client_hello ( tls ) ) != 0 ) {
01665                         DBGC ( tls, "TLS %p could not send Client Hello: %s\n",
01666                                tls, strerror ( rc ) );
01667                         goto err;
01668                 }
01669                 tls->tx_state = TLS_TX_NONE;
01670                 break;
01671         case TLS_TX_CLIENT_KEY_EXCHANGE:
01672                 /* Send Client Key Exchange */
01673                 if ( ( rc = tls_send_client_key_exchange ( tls ) ) != 0 ) {
01674                         DBGC ( tls, "TLS %p could send Client Key Exchange: "
01675                                "%s\n", tls, strerror ( rc ) );
01676                         goto err;
01677                 }
01678                 tls->tx_state = TLS_TX_CHANGE_CIPHER;
01679                 break;
01680         case TLS_TX_CHANGE_CIPHER:
01681                 /* Send Change Cipher, and then change the cipher in use */
01682                 if ( ( rc = tls_send_change_cipher ( tls ) ) != 0 ) {
01683                         DBGC ( tls, "TLS %p could not send Change Cipher: "
01684                                "%s\n", tls, strerror ( rc ) );
01685                         goto err;
01686                 }
01687                 if ( ( rc = tls_change_cipher ( tls,
01688                                                 &tls->tx_cipherspec_pending,
01689                                                 &tls->tx_cipherspec )) != 0 ){
01690                         DBGC ( tls, "TLS %p could not activate TX cipher: "
01691                                "%s\n", tls, strerror ( rc ) );
01692                         goto err;
01693                 }
01694                 tls->tx_seq = 0;
01695                 tls->tx_state = TLS_TX_FINISHED;
01696                 break;
01697         case TLS_TX_FINISHED:
01698                 /* Send Finished */
01699                 if ( ( rc = tls_send_finished ( tls ) ) != 0 ) {
01700                         DBGC ( tls, "TLS %p could not send Finished: %s\n",
01701                                tls, strerror ( rc ) );
01702                         goto err;
01703                 }
01704                 tls->tx_state = TLS_TX_NONE;
01705                 break;
01706         case TLS_TX_DATA:
01707                 /* Nothing to do */
01708                 break;
01709         default:
01710                 assert ( 0 );
01711         }
01712 
01713         return;
01714 
01715  err:
01716         tls_close ( tls, rc );
01717 }
01718 
01719 /******************************************************************************
01720  *
01721  * Instantiator
01722  *
01723  ******************************************************************************
01724  */
01725 
01726 int add_tls ( struct xfer_interface *xfer, struct xfer_interface **next ) {
01727         struct tls_session *tls;
01728 
01729         /* Allocate and initialise TLS structure */
01730         tls = malloc ( sizeof ( *tls ) );
01731         if ( ! tls )
01732                 return -ENOMEM;
01733         memset ( tls, 0, sizeof ( *tls ) );
01734         tls->refcnt.free = free_tls;
01735         filter_init ( &tls->plainstream, &tls_plainstream_operations,
01736                       &tls->cipherstream, &tls_cipherstream_operations,
01737                       &tls->refcnt );
01738         tls_clear_cipher ( tls, &tls->tx_cipherspec );
01739         tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
01740         tls_clear_cipher ( tls, &tls->rx_cipherspec );
01741         tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
01742         tls->client_random.gmt_unix_time = 0;
01743         tls_generate_random ( &tls->client_random.random,
01744                               ( sizeof ( tls->client_random.random ) ) );
01745         tls->pre_master_secret.version = htons ( TLS_VERSION_TLS_1_0 );
01746         tls_generate_random ( &tls->pre_master_secret.random,
01747                               ( sizeof ( tls->pre_master_secret.random ) ) );
01748         digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
01749         digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
01750         tls->tx_state = TLS_TX_CLIENT_HELLO;
01751         process_init ( &tls->process, tls_step, &tls->refcnt );
01752 
01753         /* Attach to parent interface, mortalise self, and return */
01754         xfer_plug_plug ( &tls->plainstream.xfer, xfer );
01755         *next = &tls->cipherstream.xfer;
01756         ref_put ( &tls->refcnt );
01757         return 0;
01758 }
01759 

Generated on Tue Apr 6 20:01:11 2010 for gPXE by  doxygen 1.5.7.1