gpxe import
[grub-extras.git] / gpxe / src / net / tls.c
bloba5b126ed8b631eea96b949fbd098458e8928b76c
1 /*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER );
21 /**
22 * @file
24 * Transport Layer Security Protocol
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>
45 static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
46 const void *data, size_t len );
47 static void tls_clear_cipher ( struct tls_session *tls,
48 struct tls_cipherspec *cipherspec );
50 /******************************************************************************
52 * Utility functions
54 ******************************************************************************
57 /**
58 * Extract 24-bit field value
60 * @v field24 24-bit field
61 * @ret value Field value
63 * TLS uses 24-bit integers in several places, which are awkward to
64 * parse in C.
66 static unsigned long tls_uint24 ( uint8_t field24[3] ) {
67 return ( ( field24[0] << 16 ) + ( field24[1] << 8 ) + field24[2] );
70 /******************************************************************************
72 * Cleanup functions
74 ******************************************************************************
77 /**
78 * Free TLS session
80 * @v refcnt Reference counter
82 static void free_tls ( struct refcnt *refcnt ) {
83 struct tls_session *tls =
84 container_of ( refcnt, struct tls_session, refcnt );
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 );
94 /* Free TLS structure itself */
95 free ( tls );
98 /**
99 * Finish with TLS session
101 * @v tls TLS session
102 * @v rc Status code
104 static void tls_close ( struct tls_session *tls, int rc ) {
106 /* Remove process */
107 process_del ( &tls->process );
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 );
116 /******************************************************************************
118 * Random number generation
120 ******************************************************************************
124 * Generate random data
126 * @v data Buffer to fill
127 * @v len Length of buffer
129 static void tls_generate_random ( void *data, size_t len ) {
130 /* FIXME: Some real random data source would be nice... */
131 memset ( data, 0x01, len );
135 * Update HMAC with a list of ( data, len ) pairs
137 * @v digest Hash function to use
138 * @v digest_ctx Digest context
139 * @v args ( data, len ) pairs of data, terminated by NULL
141 static void tls_hmac_update_va ( struct digest_algorithm *digest,
142 void *digest_ctx, va_list args ) {
143 void *data;
144 size_t len;
146 while ( ( data = va_arg ( args, void * ) ) ) {
147 len = va_arg ( args, size_t );
148 hmac_update ( digest, digest_ctx, data, len );
153 * Generate secure pseudo-random data using a single hash function
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
163 static 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;
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 );
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 ) );
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 );
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 );
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 ) );
216 out += frag_len;
217 out_len -= frag_len;
222 * Generate secure pseudo-random data
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
231 static 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;
242 va_start ( seeds, out_len );
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 );
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 );
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 );
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] );
266 va_end ( seeds );
270 * Generate secure pseudo-random data
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
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 )
283 /******************************************************************************
285 * Secret management
287 ******************************************************************************
291 * Generate master secret
293 * @v tls TLS session
295 * The pre-master secret and the client and server random values must
296 * already be known.
298 static 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 ) );
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 ) );
314 DBGC ( tls, "TLS %p generated master secret:\n", tls );
315 DBGC_HD ( tls, &tls->master_secret, sizeof ( tls->master_secret ) );
319 * Generate key material
321 * @v tls TLS session
323 * The master secret must already be known.
325 static 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;
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 ) );
342 /* Split key block into portions */
343 key = key_block;
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;
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;
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;
365 DBGC ( tls, "TLS %p TX key:\n", tls );
366 DBGC_HD ( tls, key, key_size );
367 key += key_size;
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;
377 DBGC ( tls, "TLS %p RX key:\n", tls );
378 DBGC_HD ( tls, key, key_size );
379 key += key_size;
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;
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;
393 assert ( ( key_block + total ) == key );
395 return 0;
398 /******************************************************************************
400 * Cipher suite management
402 ******************************************************************************
406 * Clear cipher suite
408 * @v cipherspec TLS cipher specification
410 static 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;
420 * Set cipher suite
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
430 static 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;
439 /* Clear out old cipher contents, if any */
440 tls_clear_cipher ( tls, cipherspec );
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;
450 memset ( dynamic, 0, total );
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 );
460 /* Store parameters */
461 cipherspec->pubkey = pubkey;
462 cipherspec->cipher = cipher;
463 cipherspec->digest = digest;
464 cipherspec->key_len = key_len;
466 return 0;
470 * Select next cipher suite
472 * @v tls TLS session
473 * @v cipher_suite Cipher suite specification
474 * @ret rc Return status code
476 static 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;
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;
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;
509 DBGC ( tls, "TLS %p selected %s-%s-%d-%s\n", tls,
510 pubkey->name, cipher->name, ( key_len * 8 ), digest->name );
512 return 0;
516 * Activate next cipher suite
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
523 static int tls_change_cipher ( struct tls_session *tls,
524 struct tls_cipherspec *pending,
525 struct tls_cipherspec *active ) {
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;
536 tls_clear_cipher ( tls, active );
537 memswap ( active, pending, sizeof ( *active ) );
538 return 0;
541 /******************************************************************************
543 * Handshake verification
545 ******************************************************************************
549 * Add handshake record to verification hash
551 * @v tls TLS session
552 * @v data Handshake record
553 * @v len Length of handshake record
555 static void tls_add_handshake ( struct tls_session *tls,
556 const void *data, size_t len ) {
558 digest_update ( &md5_algorithm, tls->handshake_md5_ctx, data, len );
559 digest_update ( &sha1_algorithm, tls->handshake_sha1_ctx, data, len );
563 * Calculate handshake verification hash
565 * @v tls TLS session
566 * @v out Output buffer
568 * Calculates the MD5+SHA1 digest over all handshake messages seen so
569 * far.
571 static 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 );
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 );
585 /******************************************************************************
587 * Record handling
589 ******************************************************************************
593 * Transmit Handshake record
595 * @v tls TLS session
596 * @v data Plaintext record
597 * @v len Length of plaintext record
598 * @ret rc Return status code
600 static int tls_send_handshake ( struct tls_session *tls,
601 void *data, size_t len ) {
603 /* Add to handshake digest */
604 tls_add_handshake ( tls, data, len );
606 /* Send record */
607 return tls_send_plaintext ( tls, TLS_TYPE_HANDSHAKE, data, len );
611 * Transmit Client Hello record
613 * @v tls TLS session
614 * @ret rc Return status code
616 static 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;
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 );
639 return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
643 * Transmit Client Key Exchange record
645 * @v tls TLS session
646 * @ret rc Return status code
648 static 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;
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 ) );
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 );
681 return tls_send_handshake ( tls, &key_xchg, sizeof ( key_xchg ) );
685 * Transmit Change Cipher record
687 * @v tls TLS session
688 * @ret rc Return status code
690 static 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 ) );
697 * Transmit Finished record
699 * @v tls TLS session
700 * @ret rc Return status code
702 static 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];
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 ) );
718 return tls_send_handshake ( tls, &finished, sizeof ( finished ) );
722 * Receive new Change Cipher record
724 * @v tls TLS session
725 * @v data Plaintext record
726 * @v len Length of plaintext record
727 * @ret rc Return status code
729 static int tls_new_change_cipher ( struct tls_session *tls,
730 void *data, size_t len ) {
731 int rc;
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;
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;
745 tls->rx_seq = ~( ( uint64_t ) 0 );
747 return 0;
751 * Receive new Alert record
753 * @v tls TLS session
754 * @v data Plaintext record
755 * @v len Length of plaintext record
756 * @ret rc Return status code
758 static 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;
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;
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;
790 * Receive new Server Hello handshake record
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
797 static 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;
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;
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;
829 /* Copy out server random bytes */
830 memcpy ( &tls->server_random, &hello_a->random,
831 sizeof ( tls->server_random ) );
833 /* Select cipher suite */
834 if ( ( rc = tls_select_cipher ( tls, hello_b->cipher_suite ) ) != 0 )
835 return rc;
837 /* Generate secrets */
838 tls_generate_master_secret ( tls );
839 if ( ( rc = tls_generate_keys ( tls ) ) != 0 )
840 return rc;
842 return 0;
846 * Receive new Certificate handshake record
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
853 static 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;
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;
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;
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;
895 return 0;
897 element = ( cursor.data + cursor.len );
898 } while ( element != end );
900 return -EINVAL;
904 * Receive new Server Hello Done handshake record
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
911 static 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;
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;
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;
933 /* Start sending the Client Key Exchange */
934 tls->tx_state = TLS_TX_CLIENT_KEY_EXCHANGE;
936 return 0;
940 * Receive new Finished handshake record
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
947 static int tls_new_finished ( struct tls_session *tls,
948 void *data, size_t len ) {
950 /* FIXME: Handle this properly */
951 tls->tx_state = TLS_TX_DATA;
952 ( void ) data;
953 ( void ) len;
954 return 0;
958 * Receive new Handshake record
960 * @v tls TLS session
961 * @v data Plaintext record
962 * @v len Length of plaintext record
963 * @ret rc Return status code
965 static 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;
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;
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;
1004 /* Add to handshake digest (except for Hello Requests, which
1005 * are explicitly excluded).
1007 if ( handshake->type != TLS_HELLO_REQUEST )
1008 tls_add_handshake ( tls, data, len );
1010 return rc;
1014 * Receive new record
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
1022 static int tls_new_record ( struct tls_session *tls,
1023 unsigned int type, void *data, size_t len ) {
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.
1038 DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
1039 return 0;
1043 /******************************************************************************
1045 * Record encryption/decryption
1047 ******************************************************************************
1051 * Calculate HMAC
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
1061 static 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];
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 );
1079 * Allocate and assemble stream-ciphered record from data and MAC portions
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
1088 static 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;
1096 /* Calculate stream-ciphered struct length */
1097 *plaintext_len = ( len + mac_len );
1099 /* Allocate stream-ciphered struct */
1100 plaintext = malloc ( *plaintext_len );
1101 if ( ! plaintext )
1102 return NULL;
1103 content = plaintext;
1104 mac = ( content + len );
1106 /* Fill in stream-ciphered struct */
1107 memcpy ( content, data, len );
1108 memcpy ( mac, digest, mac_len );
1110 return plaintext;
1114 * Allocate and assemble block-ciphered record from data and MAC portions
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
1123 static 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;
1136 /* FIXME: TLSv1.1 has an explicit IV */
1137 iv_len = 0;
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 );
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 );
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 ) );
1158 return plaintext;
1162 * Send plaintext record
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
1170 static 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;
1183 /* Construct header */
1184 plaintext_tlshdr.type = type;
1185 plaintext_tlshdr.version = htons ( TLS_VERSION_TLS_1_0 );
1186 plaintext_tlshdr.length = htons ( len );
1188 /* Calculate MAC */
1189 tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr,
1190 data, len, mac );
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 );
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;
1207 DBGC2 ( tls, "Sending plaintext data:\n" );
1208 DBGC2_HD ( tls, plaintext, plaintext_len );
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;
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 );
1232 /* Free plaintext as soon as possible to conserve memory */
1233 free ( plaintext );
1234 plaintext = NULL;
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;
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 );
1251 done:
1252 free ( plaintext );
1253 free_iob ( ciphertext );
1254 return rc;
1258 * Split stream-ciphered record into data and MAC portions
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
1268 static 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;
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;
1283 content_len = ( plaintext_len - mac_len );
1284 content = plaintext;
1285 mac = ( content + content_len );
1287 /* Fill in return values */
1288 *data = content;
1289 *len = content_len;
1290 *digest = mac;
1292 return 0;
1296 * Split block-ciphered record into data and MAC portions
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
1306 static 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;
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;
1326 iv_len = tls->rx_cipherspec.cipher->blocksize;
1328 /* FIXME: TLSv1.1 uses an explicit IV */
1329 iv_len = 0;
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;
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 );
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;
1353 /* Fill in return values */
1354 *data = content;
1355 *len = content_len;
1356 *digest = mac;
1358 return 0;
1362 * Receive new ciphertext record
1364 * @v tls TLS session
1365 * @v tlshdr Record header
1366 * @v ciphertext Ciphertext record
1367 * @ret rc Return status code
1369 static 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;
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;
1391 /* Decrypt the record */
1392 cipher_decrypt ( cipherspec->cipher, cipherspec->cipher_ctx,
1393 ciphertext, plaintext, record_len );
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;
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;
1418 DBGC2 ( tls, "Received plaintext data:\n" );
1419 DBGC2_HD ( tls, data, len );
1421 /* Process plaintext record */
1422 if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 )
1423 goto done;
1425 rc = 0;
1426 done:
1427 free ( plaintext );
1428 return rc;
1431 /******************************************************************************
1433 * Plaintext stream operations
1435 ******************************************************************************
1439 * Close interface
1441 * @v xfer Plainstream data transfer interface
1442 * @v rc Reason for close
1444 static void tls_plainstream_close ( struct xfer_interface *xfer, int rc ) {
1445 struct tls_session *tls =
1446 container_of ( xfer, struct tls_session, plainstream.xfer );
1448 tls_close ( tls, rc );
1452 * Check flow control window
1454 * @v xfer Plainstream data transfer interface
1455 * @ret len Length of window
1457 static size_t tls_plainstream_window ( struct xfer_interface *xfer ) {
1458 struct tls_session *tls =
1459 container_of ( xfer, struct tls_session, plainstream.xfer );
1461 /* Block window unless we are ready to accept data */
1462 if ( tls->tx_state != TLS_TX_DATA )
1463 return 0;
1465 return filter_window ( xfer );
1469 * Deliver datagram as raw data
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
1476 static 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 );
1481 /* Refuse unless we are ready to accept data */
1482 if ( tls->tx_state != TLS_TX_DATA )
1483 return -ENOTCONN;
1485 return tls_send_plaintext ( tls, TLS_TYPE_DATA, data, len );
1488 /** TLS plaintext stream operations */
1489 static 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,
1498 /******************************************************************************
1500 * Ciphertext stream operations
1502 ******************************************************************************
1506 * Close interface
1508 * @v xfer Plainstream data transfer interface
1509 * @v rc Reason for close
1511 static void tls_cipherstream_close ( struct xfer_interface *xfer, int rc ) {
1512 struct tls_session *tls =
1513 container_of ( xfer, struct tls_session, cipherstream.xfer );
1515 tls_close ( tls, rc );
1519 * Handle received TLS header
1521 * @v tls TLS session
1522 * @ret rc Returned status code
1524 static int tls_newdata_process_header ( struct tls_session *tls ) {
1525 size_t data_len = ntohs ( tls->rx_header.length );
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;
1536 /* Move to data state */
1537 tls->rx_state = TLS_RX_DATA;
1539 return 0;
1543 * Handle received TLS data payload
1545 * @v tls TLS session
1546 * @ret rc Returned status code
1548 static int tls_newdata_process_data ( struct tls_session *tls ) {
1549 int rc;
1551 /* Process record */
1552 if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
1553 tls->rx_data ) ) != 0 )
1554 return rc;
1556 /* Increment RX sequence number */
1557 tls->rx_seq += 1;
1559 /* Free data buffer */
1560 free ( tls->rx_data );
1561 tls->rx_data = NULL;
1563 /* Return to header state */
1564 tls->rx_state = TLS_RX_HEADER;
1566 return 0;
1570 * Receive new ciphertext
1572 * @v app Stream application
1573 * @v data Data received
1574 * @v len Length of received data
1575 * @ret rc Return status code
1577 static 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;
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;
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;
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;
1620 tls->rx_rcvd = 0;
1624 return 0;
1627 /** TLS ciphertext stream operations */
1628 static 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,
1637 /******************************************************************************
1639 * Controlling process
1641 ******************************************************************************
1645 * TLS TX state machine
1647 * @v process TLS process
1649 static void tls_step ( struct process *process ) {
1650 struct tls_session *tls =
1651 container_of ( process, struct tls_session, process );
1652 int rc;
1654 /* Wait for cipherstream to become ready */
1655 if ( ! xfer_window ( &tls->cipherstream.xfer ) )
1656 return;
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;
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;
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;
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;
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;
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 );
1713 return;
1715 err:
1716 tls_close ( tls, rc );
1719 /******************************************************************************
1721 * Instantiator
1723 ******************************************************************************
1726 int add_tls ( struct xfer_interface *xfer, struct xfer_interface **next ) {
1727 struct tls_session *tls;
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 );
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;