source: bootcd/isolinux/syslinux-6.03/gpxe/src/net/tls.c @ 26ffad7

Last change on this file since 26ffad7 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

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