| 
									
										
										
										
											2016-05-18 02:18:30 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2006-01-03 11:27:19 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-18 02:18:30 +08:00
										 |  |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											2006-01-03 11:27:19 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											1999-04-24 06:13:45 +08:00
										 |  |  | #include <openssl/objects.h>
 | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  | #include <openssl/evp.h>
 | 
					
						
							|  |  |  | #include <openssl/hmac.h>
 | 
					
						
							| 
									
										
										
										
											2007-09-27 05:56:59 +08:00
										 |  |  | #include <openssl/ocsp.h>
 | 
					
						
							| 
									
										
										
										
											2016-04-20 23:38:29 +08:00
										 |  |  | #include <openssl/conf.h>
 | 
					
						
							|  |  |  | #include <openssl/x509v3.h>
 | 
					
						
							| 
									
										
										
										
											2012-01-01 06:59:57 +08:00
										 |  |  | #include <openssl/rand.h>
 | 
					
						
							| 
									
										
										
										
											2016-03-19 02:30:20 +08:00
										 |  |  | #include <openssl/dh.h>
 | 
					
						
							|  |  |  | #include <openssl/bn.h>
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | #include "ssl_locl.h"
 | 
					
						
							| 
									
										
										
										
											2016-03-19 02:30:20 +08:00
										 |  |  | #include <openssl/ct.h>
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  | static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                               const unsigned char *sess_id, int sesslen, | 
					
						
							|  |  |  |                               SSL_SESSION **psess); | 
					
						
							| 
									
										
										
										
											2012-09-11 20:57:46 +08:00
										 |  |  | static int ssl_check_clienthello_tlsext_early(SSL *s); | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  | static int ssl_check_serverhello_tlsext(SSL *s); | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | SSL3_ENC_METHOD const TLSv1_enc_data = { | 
					
						
							|  |  |  |     tls1_enc, | 
					
						
							|  |  |  |     tls1_mac, | 
					
						
							|  |  |  |     tls1_setup_key_block, | 
					
						
							|  |  |  |     tls1_generate_master_secret, | 
					
						
							|  |  |  |     tls1_change_cipher_state, | 
					
						
							|  |  |  |     tls1_final_finish_mac, | 
					
						
							|  |  |  |     TLS1_FINISH_MAC_LENGTH, | 
					
						
							|  |  |  |     TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, | 
					
						
							|  |  |  |     TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, | 
					
						
							|  |  |  |     tls1_alert_code, | 
					
						
							|  |  |  |     tls1_export_keying_material, | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     SSL3_HM_HEADER_LENGTH, | 
					
						
							|  |  |  |     ssl3_set_handshake_header, | 
					
						
							|  |  |  |     ssl3_handshake_write | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SSL3_ENC_METHOD const TLSv1_1_enc_data = { | 
					
						
							|  |  |  |     tls1_enc, | 
					
						
							|  |  |  |     tls1_mac, | 
					
						
							|  |  |  |     tls1_setup_key_block, | 
					
						
							|  |  |  |     tls1_generate_master_secret, | 
					
						
							|  |  |  |     tls1_change_cipher_state, | 
					
						
							|  |  |  |     tls1_final_finish_mac, | 
					
						
							|  |  |  |     TLS1_FINISH_MAC_LENGTH, | 
					
						
							|  |  |  |     TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, | 
					
						
							|  |  |  |     TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, | 
					
						
							|  |  |  |     tls1_alert_code, | 
					
						
							|  |  |  |     tls1_export_keying_material, | 
					
						
							|  |  |  |     SSL_ENC_FLAG_EXPLICIT_IV, | 
					
						
							|  |  |  |     SSL3_HM_HEADER_LENGTH, | 
					
						
							|  |  |  |     ssl3_set_handshake_header, | 
					
						
							|  |  |  |     ssl3_handshake_write | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SSL3_ENC_METHOD const TLSv1_2_enc_data = { | 
					
						
							|  |  |  |     tls1_enc, | 
					
						
							|  |  |  |     tls1_mac, | 
					
						
							|  |  |  |     tls1_setup_key_block, | 
					
						
							|  |  |  |     tls1_generate_master_secret, | 
					
						
							|  |  |  |     tls1_change_cipher_state, | 
					
						
							|  |  |  |     tls1_final_finish_mac, | 
					
						
							|  |  |  |     TLS1_FINISH_MAC_LENGTH, | 
					
						
							|  |  |  |     TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE, | 
					
						
							|  |  |  |     TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE, | 
					
						
							|  |  |  |     tls1_alert_code, | 
					
						
							|  |  |  |     tls1_export_keying_material, | 
					
						
							|  |  |  |     SSL_ENC_FLAG_EXPLICIT_IV | SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF | 
					
						
							|  |  |  |         | SSL_ENC_FLAG_TLS1_2_CIPHERS, | 
					
						
							|  |  |  |     SSL3_HM_HEADER_LENGTH, | 
					
						
							|  |  |  |     ssl3_set_handshake_header, | 
					
						
							|  |  |  |     ssl3_handshake_write | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-06 07:56:11 +08:00
										 |  |  | long tls1_default_timeout(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * 2 hours, the 24 hours mentioned in the TLSv1 spec is way too long for | 
					
						
							|  |  |  |      * http, the cache would over fill | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     return (60 * 60 * 2); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | int tls1_new(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!ssl3_new(s)) | 
					
						
							|  |  |  |         return (0); | 
					
						
							|  |  |  |     s->method->ssl_clear(s); | 
					
						
							|  |  |  |     return (1); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | void tls1_free(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(s->tlsext_session_ticket); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ssl3_free(s); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | void tls1_clear(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     ssl3_clear(s); | 
					
						
							| 
									
										
										
										
											2015-12-29 16:24:17 +08:00
										 |  |  |     if (s->method->version == TLS_ANY_VERSION) | 
					
						
							|  |  |  |         s->version = TLS_MAX_VERSION; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         s->version = s->method->version; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:56:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-13 07:59:05 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2011-05-31 01:58:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     int nid;                    /* Curve NID */ | 
					
						
							|  |  |  |     int secbits;                /* Bits of security (from SP800-57) */ | 
					
						
							|  |  |  |     unsigned int flags;         /* Flags: currently just field type */ | 
					
						
							|  |  |  | } tls_curve_info; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-26 01:46:14 +08:00
										 |  |  | /* Mask for curve type */ | 
					
						
							|  |  |  | # define TLS_CURVE_TYPE          0x3
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # define TLS_CURVE_PRIME         0x0
 | 
					
						
							| 
									
										
										
										
											2016-02-26 01:46:14 +08:00
										 |  |  | # define TLS_CURVE_CHAR2         0x1
 | 
					
						
							|  |  |  | # define TLS_CURVE_CUSTOM        0x2
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-13 23:27:43 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Table of curve information. | 
					
						
							| 
									
										
										
										
											2016-01-04 02:24:32 +08:00
										 |  |  |  * Do not delete entries or reorder this array! It is used as a lookup | 
					
						
							| 
									
										
										
										
											2016-02-13 23:27:43 +08:00
										 |  |  |  * table: the index of each entry is one less than the TLS curve id. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static const tls_curve_info nid_list[] = { | 
					
						
							|  |  |  |     {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */ | 
					
						
							|  |  |  |     {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */ | 
					
						
							|  |  |  |     {NID_sect163r2, 80, TLS_CURVE_CHAR2}, /* sect163r2 (3) */ | 
					
						
							|  |  |  |     {NID_sect193r1, 80, TLS_CURVE_CHAR2}, /* sect193r1 (4) */ | 
					
						
							|  |  |  |     {NID_sect193r2, 80, TLS_CURVE_CHAR2}, /* sect193r2 (5) */ | 
					
						
							|  |  |  |     {NID_sect233k1, 112, TLS_CURVE_CHAR2}, /* sect233k1 (6) */ | 
					
						
							|  |  |  |     {NID_sect233r1, 112, TLS_CURVE_CHAR2}, /* sect233r1 (7) */ | 
					
						
							|  |  |  |     {NID_sect239k1, 112, TLS_CURVE_CHAR2}, /* sect239k1 (8) */ | 
					
						
							|  |  |  |     {NID_sect283k1, 128, TLS_CURVE_CHAR2}, /* sect283k1 (9) */ | 
					
						
							|  |  |  |     {NID_sect283r1, 128, TLS_CURVE_CHAR2}, /* sect283r1 (10) */ | 
					
						
							|  |  |  |     {NID_sect409k1, 192, TLS_CURVE_CHAR2}, /* sect409k1 (11) */ | 
					
						
							|  |  |  |     {NID_sect409r1, 192, TLS_CURVE_CHAR2}, /* sect409r1 (12) */ | 
					
						
							|  |  |  |     {NID_sect571k1, 256, TLS_CURVE_CHAR2}, /* sect571k1 (13) */ | 
					
						
							|  |  |  |     {NID_sect571r1, 256, TLS_CURVE_CHAR2}, /* sect571r1 (14) */ | 
					
						
							|  |  |  |     {NID_secp160k1, 80, TLS_CURVE_PRIME}, /* secp160k1 (15) */ | 
					
						
							|  |  |  |     {NID_secp160r1, 80, TLS_CURVE_PRIME}, /* secp160r1 (16) */ | 
					
						
							|  |  |  |     {NID_secp160r2, 80, TLS_CURVE_PRIME}, /* secp160r2 (17) */ | 
					
						
							|  |  |  |     {NID_secp192k1, 80, TLS_CURVE_PRIME}, /* secp192k1 (18) */ | 
					
						
							|  |  |  |     {NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME}, /* secp192r1 (19) */ | 
					
						
							|  |  |  |     {NID_secp224k1, 112, TLS_CURVE_PRIME}, /* secp224k1 (20) */ | 
					
						
							|  |  |  |     {NID_secp224r1, 112, TLS_CURVE_PRIME}, /* secp224r1 (21) */ | 
					
						
							|  |  |  |     {NID_secp256k1, 128, TLS_CURVE_PRIME}, /* secp256k1 (22) */ | 
					
						
							|  |  |  |     {NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME}, /* secp256r1 (23) */ | 
					
						
							|  |  |  |     {NID_secp384r1, 192, TLS_CURVE_PRIME}, /* secp384r1 (24) */ | 
					
						
							|  |  |  |     {NID_secp521r1, 256, TLS_CURVE_PRIME}, /* secp521r1 (25) */ | 
					
						
							|  |  |  |     {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */ | 
					
						
							|  |  |  |     {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */ | 
					
						
							|  |  |  |     {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME}, /* brainpool512r1 (28) */ | 
					
						
							| 
									
										
										
										
											2016-02-26 01:46:14 +08:00
										 |  |  |     /* X25519 (29) */ | 
					
						
							|  |  |  |     {NID_X25519, 128, TLS_CURVE_CUSTOM}, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const unsigned char ecformats_default[] = { | 
					
						
							|  |  |  |     TLSEXT_ECPOINTFORMAT_uncompressed, | 
					
						
							|  |  |  |     TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime, | 
					
						
							|  |  |  |     TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 05:30:36 +08:00
										 |  |  | /* The default curves */ | 
					
						
							|  |  |  | static const unsigned char eccurves_default[] = { | 
					
						
							| 
									
										
										
										
											2016-02-26 01:46:14 +08:00
										 |  |  |     0, 29,                      /* X25519 (29) */ | 
					
						
							| 
									
										
										
										
											2015-05-20 21:47:51 +08:00
										 |  |  |     0, 23,                      /* secp256r1 (23) */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     0, 25,                      /* secp521r1 (25) */ | 
					
						
							|  |  |  |     0, 24,                      /* secp384r1 (24) */ | 
					
						
							| 
									
										
										
										
											2015-05-20 21:47:51 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const unsigned char eccurves_all[] = { | 
					
						
							| 
									
										
										
										
											2016-02-26 01:46:14 +08:00
										 |  |  |     0, 29,                      /* X25519 (29) */ | 
					
						
							| 
									
										
										
										
											2015-05-20 21:47:51 +08:00
										 |  |  |     0, 23,                      /* secp256r1 (23) */ | 
					
						
							|  |  |  |     0, 25,                      /* secp521r1 (25) */ | 
					
						
							|  |  |  |     0, 24,                      /* secp384r1 (24) */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     0, 26,                      /* brainpoolP256r1 (26) */ | 
					
						
							| 
									
										
										
										
											2016-01-04 02:24:32 +08:00
										 |  |  |     0, 27,                      /* brainpoolP384r1 (27) */ | 
					
						
							|  |  |  |     0, 28,                      /* brainpool512r1 (28) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Remaining curves disabled by default but still permitted if set | 
					
						
							|  |  |  |      * via an explicit callback or parameters. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     0, 22,                      /* secp256k1 (22) */ | 
					
						
							| 
									
										
										
										
											2015-05-20 21:47:51 +08:00
										 |  |  |     0, 14,                      /* sect571r1 (14) */ | 
					
						
							|  |  |  |     0, 13,                      /* sect571k1 (13) */ | 
					
						
							|  |  |  |     0, 11,                      /* sect409k1 (11) */ | 
					
						
							|  |  |  |     0, 12,                      /* sect409r1 (12) */ | 
					
						
							|  |  |  |     0, 9,                       /* sect283k1 (9) */ | 
					
						
							|  |  |  |     0, 10,                      /* sect283r1 (10) */ | 
					
						
							|  |  |  |     0, 20,                      /* secp224k1 (20) */ | 
					
						
							|  |  |  |     0, 21,                      /* secp224r1 (21) */ | 
					
						
							|  |  |  |     0, 18,                      /* secp192k1 (18) */ | 
					
						
							|  |  |  |     0, 19,                      /* secp192r1 (19) */ | 
					
						
							|  |  |  |     0, 15,                      /* secp160k1 (15) */ | 
					
						
							|  |  |  |     0, 16,                      /* secp160r1 (16) */ | 
					
						
							|  |  |  |     0, 17,                      /* secp160r2 (17) */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     0, 8,                       /* sect239k1 (8) */ | 
					
						
							|  |  |  |     0, 6,                       /* sect233k1 (6) */ | 
					
						
							|  |  |  |     0, 7,                       /* sect233r1 (7) */ | 
					
						
							|  |  |  |     0, 4,                       /* sect193r1 (4) */ | 
					
						
							|  |  |  |     0, 5,                       /* sect193r2 (5) */ | 
					
						
							|  |  |  |     0, 1,                       /* sect163k1 (1) */ | 
					
						
							|  |  |  |     0, 2,                       /* sect163r1 (2) */ | 
					
						
							|  |  |  |     0, 3,                       /* sect163r2 (3) */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-20 21:47:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static const unsigned char suiteb_curves[] = { | 
					
						
							|  |  |  |     0, TLSEXT_curve_P_256, | 
					
						
							|  |  |  |     0, TLSEXT_curve_P_384 | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2012-08-15 23:15:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-13 07:59:05 +08:00
										 |  |  | int tls1_ec_curve_id2nid(int curve_id) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /* ECC curves from RFC 4492 and RFC 7027 */ | 
					
						
							| 
									
										
										
										
											2015-05-03 01:30:00 +08:00
										 |  |  |     if ((curve_id < 1) || ((unsigned int)curve_id > OSSL_NELEM(nid_list))) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     return nid_list[curve_id - 1].nid; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-08-13 07:59:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int tls1_ec_nid2curve_id(int nid) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-13 23:28:25 +08:00
										 |  |  |     size_t i; | 
					
						
							|  |  |  |     for (i = 0; i < OSSL_NELEM(nid_list); i++) { | 
					
						
							|  |  |  |         if (nid_list[i].nid == nid) | 
					
						
							|  |  |  |             return i + 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-02-13 23:28:25 +08:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-01 23:55:55 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Get curves list, if "sess" is set return client curves otherwise | 
					
						
							|  |  |  |  * preferred list. | 
					
						
							|  |  |  |  * Sets |num_curves| to the number of curves in the list, i.e., | 
					
						
							|  |  |  |  * the length of |pcurves| is 2 * num_curves. | 
					
						
							|  |  |  |  * Returns 1 on success and 0 if the client curves list has invalid format. | 
					
						
							|  |  |  |  * The latter indicates an internal error: we should not be accepting such | 
					
						
							|  |  |  |  * lists in the first place. | 
					
						
							|  |  |  |  * TODO(emilia): we should really be storing the curves list in explicitly | 
					
						
							|  |  |  |  * parsed form instead. (However, this would affect binary compatibility | 
					
						
							|  |  |  |  * so cannot happen in the 1.0.x series.) | 
					
						
							| 
									
										
										
										
											2012-04-04 22:41:01 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-12-01 23:55:55 +08:00
										 |  |  | static int tls1_get_curvelist(SSL *s, int sess, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                               const unsigned char **pcurves, | 
					
						
							|  |  |  |                               size_t *num_curves) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     size_t pcurveslen = 0; | 
					
						
							|  |  |  |     if (sess) { | 
					
						
							|  |  |  |         *pcurves = s->session->tlsext_ellipticcurvelist; | 
					
						
							|  |  |  |         pcurveslen = s->session->tlsext_ellipticcurvelist_length; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* For Suite B mode only include P-256, P-384 */ | 
					
						
							|  |  |  |         switch (tls1_suiteb(s)) { | 
					
						
							|  |  |  |         case SSL_CERT_FLAG_SUITEB_128_LOS: | 
					
						
							|  |  |  |             *pcurves = suiteb_curves; | 
					
						
							|  |  |  |             pcurveslen = sizeof(suiteb_curves); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: | 
					
						
							|  |  |  |             *pcurves = suiteb_curves; | 
					
						
							|  |  |  |             pcurveslen = 2; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case SSL_CERT_FLAG_SUITEB_192_LOS: | 
					
						
							|  |  |  |             *pcurves = suiteb_curves + 2; | 
					
						
							|  |  |  |             pcurveslen = 2; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             *pcurves = s->tlsext_ellipticcurvelist; | 
					
						
							|  |  |  |             pcurveslen = s->tlsext_ellipticcurvelist_length; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!*pcurves) { | 
					
						
							| 
									
										
										
										
											2015-12-05 05:30:36 +08:00
										 |  |  |             *pcurves = eccurves_default; | 
					
						
							|  |  |  |             pcurveslen = sizeof(eccurves_default); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* We do not allow odd length arrays to enter the system. */ | 
					
						
							|  |  |  |     if (pcurveslen & 1) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |         *num_curves = 0; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         *num_curves = pcurveslen / 2; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* See if curve is allowed by security callback */ | 
					
						
							|  |  |  | static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const tls_curve_info *cinfo; | 
					
						
							|  |  |  |     if (curve[0]) | 
					
						
							|  |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2015-05-03 01:30:00 +08:00
										 |  |  |     if ((curve[1] < 1) || ((size_t)curve[1] > OSSL_NELEM(nid_list))) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     cinfo = &nid_list[curve[1] - 1]; | 
					
						
							|  |  |  | # ifdef OPENSSL_NO_EC2M
 | 
					
						
							|  |  |  |     if (cinfo->flags & TLS_CURVE_CHAR2) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  |     return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)curve); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-24 21:47:40 +08:00
										 |  |  | /* Check a curve is one of our preferences */ | 
					
						
							|  |  |  | int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const unsigned char *curves; | 
					
						
							|  |  |  |     size_t num_curves, i; | 
					
						
							|  |  |  |     unsigned int suiteb_flags = tls1_suiteb(s); | 
					
						
							|  |  |  |     if (len != 3 || p[0] != NAMED_CURVE_TYPE) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /* Check curve matches Suite B preferences */ | 
					
						
							|  |  |  |     if (suiteb_flags) { | 
					
						
							|  |  |  |         unsigned long cid = s->s3->tmp.new_cipher->id; | 
					
						
							|  |  |  |         if (p[1]) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) { | 
					
						
							|  |  |  |             if (p[2] != TLSEXT_curve_P_256) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |         } else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) { | 
					
						
							|  |  |  |             if (p[2] != TLSEXT_curve_P_384) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |         } else                  /* Should never happen */ | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!tls1_get_curvelist(s, 0, &curves, &num_curves)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     for (i = 0; i < num_curves; i++, curves += 2) { | 
					
						
							|  |  |  |         if (p[1] == curves[0] && p[2] == curves[1]) | 
					
						
							|  |  |  |             return tls_curve_allowed(s, p + 1, SSL_SECOP_CURVE_CHECK); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-28 23:05:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  | /*-
 | 
					
						
							| 
									
										
										
										
											2015-12-05 05:25:11 +08:00
										 |  |  |  * For nmatch >= 0, return the NID of the |nmatch|th shared curve or NID_undef | 
					
						
							|  |  |  |  * if there is no match. | 
					
						
							|  |  |  |  * For nmatch == -1, return number of matches | 
					
						
							| 
									
										
										
										
											2014-12-04 22:00:11 +08:00
										 |  |  |  * For nmatch == -2, return the NID of the curve to use for | 
					
						
							|  |  |  |  * an EC tmp key, or NID_undef if there is no match. | 
					
						
							| 
									
										
										
										
											2012-03-28 23:05:04 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-04-05 21:38:27 +08:00
										 |  |  | int tls1_shared_curve(SSL *s, int nmatch) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const unsigned char *pref, *supp; | 
					
						
							|  |  |  |     size_t num_pref, num_supp, i, j; | 
					
						
							|  |  |  |     int k; | 
					
						
							|  |  |  |     /* Can't do anything on client side */ | 
					
						
							|  |  |  |     if (s->server == 0) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     if (nmatch == -2) { | 
					
						
							|  |  |  |         if (tls1_suiteb(s)) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * For Suite B ciphersuite determines curve: we already know | 
					
						
							|  |  |  |              * these are acceptable due to previous checks. | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             unsigned long cid = s->s3->tmp.new_cipher->id; | 
					
						
							|  |  |  |             if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) | 
					
						
							|  |  |  |                 return NID_X9_62_prime256v1; /* P-256 */ | 
					
						
							|  |  |  |             if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) | 
					
						
							|  |  |  |                 return NID_secp384r1; /* P-384 */ | 
					
						
							|  |  |  |             /* Should never happen */ | 
					
						
							|  |  |  |             return NID_undef; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* If not Suite B just return first preference shared curve */ | 
					
						
							|  |  |  |         nmatch = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Avoid truncation. tls1_get_curvelist takes an int | 
					
						
							|  |  |  |      * but s->options is a long... | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (!tls1_get_curvelist | 
					
						
							|  |  |  |         (s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0, &supp, | 
					
						
							|  |  |  |          &num_supp)) | 
					
						
							|  |  |  |         /* In practice, NID_undef == 0 but let's be precise. */ | 
					
						
							|  |  |  |         return nmatch == -1 ? 0 : NID_undef; | 
					
						
							|  |  |  |     if (!tls1_get_curvelist | 
					
						
							|  |  |  |         (s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &pref, | 
					
						
							|  |  |  |          &num_pref)) | 
					
						
							|  |  |  |         return nmatch == -1 ? 0 : NID_undef; | 
					
						
							| 
									
										
										
										
											2015-05-31 01:20:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If the client didn't send the elliptic_curves extension all of them | 
					
						
							|  |  |  |      * are allowed. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (num_supp == 0 && (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0) { | 
					
						
							|  |  |  |         supp = eccurves_all; | 
					
						
							|  |  |  |         num_supp = sizeof(eccurves_all) / 2; | 
					
						
							|  |  |  |     } else if (num_pref == 0 && | 
					
						
							|  |  |  |         (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) == 0) { | 
					
						
							|  |  |  |         pref = eccurves_all; | 
					
						
							|  |  |  |         num_pref = sizeof(eccurves_all) / 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     k = 0; | 
					
						
							|  |  |  |     for (i = 0; i < num_pref; i++, pref += 2) { | 
					
						
							|  |  |  |         const unsigned char *tsupp = supp; | 
					
						
							|  |  |  |         for (j = 0; j < num_supp; j++, tsupp += 2) { | 
					
						
							|  |  |  |             if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) { | 
					
						
							|  |  |  |                 if (!tls_curve_allowed(s, pref, SSL_SECOP_CURVE_SHARED)) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 if (nmatch == k) { | 
					
						
							|  |  |  |                     int id = (pref[0] << 8) | pref[1]; | 
					
						
							|  |  |  |                     return tls1_ec_curve_id2nid(id); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 k++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (nmatch == -1) | 
					
						
							|  |  |  |         return k; | 
					
						
							|  |  |  |     /* Out of range (nmatch > k). */ | 
					
						
							|  |  |  |     return NID_undef; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-28 23:05:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int tls1_set_curves(unsigned char **pext, size_t *pextlen, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     int *curves, size_t ncurves) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned char *clist, *p; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Bitmap of curves included to detect duplicates: only works while curve | 
					
						
							|  |  |  |      * ids < 32 | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     unsigned long dup_list = 0; | 
					
						
							|  |  |  |     clist = OPENSSL_malloc(ncurves * 2); | 
					
						
							| 
									
										
										
										
											2015-10-30 18:05:53 +08:00
										 |  |  |     if (clist == NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     for (i = 0, p = clist; i < ncurves; i++) { | 
					
						
							|  |  |  |         unsigned long idmask; | 
					
						
							|  |  |  |         int id; | 
					
						
							|  |  |  |         id = tls1_ec_nid2curve_id(curves[i]); | 
					
						
							|  |  |  |         idmask = 1L << id; | 
					
						
							|  |  |  |         if (!id || (dup_list & idmask)) { | 
					
						
							|  |  |  |             OPENSSL_free(clist); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         dup_list |= idmask; | 
					
						
							|  |  |  |         s2n(id, p); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(*pext); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     *pext = clist; | 
					
						
							|  |  |  |     *pextlen = ncurves * 2; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # define MAX_CURVELIST   28
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     size_t nidcnt; | 
					
						
							|  |  |  |     int nid_arr[MAX_CURVELIST]; | 
					
						
							|  |  |  | } nid_cb_st; | 
					
						
							| 
									
										
										
										
											2012-03-28 23:05:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int nid_cb(const char *elem, int len, void *arg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     nid_cb_st *narg = arg; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     int nid; | 
					
						
							|  |  |  |     char etmp[20]; | 
					
						
							| 
									
										
										
										
											2015-01-24 21:46:50 +08:00
										 |  |  |     if (elem == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (narg->nidcnt == MAX_CURVELIST) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (len > (int)(sizeof(etmp) - 1)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     memcpy(etmp, elem, len); | 
					
						
							|  |  |  |     etmp[len] = 0; | 
					
						
							|  |  |  |     nid = EC_curve_nist2nid(etmp); | 
					
						
							|  |  |  |     if (nid == NID_undef) | 
					
						
							|  |  |  |         nid = OBJ_sn2nid(etmp); | 
					
						
							|  |  |  |     if (nid == NID_undef) | 
					
						
							|  |  |  |         nid = OBJ_ln2nid(etmp); | 
					
						
							|  |  |  |     if (nid == NID_undef) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     for (i = 0; i < narg->nidcnt; i++) | 
					
						
							|  |  |  |         if (narg->nid_arr[i] == nid) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     narg->nid_arr[narg->nidcnt++] = nid; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-28 23:05:04 +08:00
										 |  |  | /* Set curves based on a colon separate list */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, | 
					
						
							|  |  |  |                          const char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     nid_cb_st ncb; | 
					
						
							|  |  |  |     ncb.nidcnt = 0; | 
					
						
							|  |  |  |     if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (pext == NULL) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-04 22:41:01 +08:00
										 |  |  | /* For an EC key set TLS id and required compression based on parameters */ | 
					
						
							|  |  |  | static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                           EC_KEY *ec) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-13 23:26:15 +08:00
										 |  |  |     int id; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     const EC_GROUP *grp; | 
					
						
							|  |  |  |     if (!ec) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /* Determine if it is a prime field */ | 
					
						
							|  |  |  |     grp = EC_KEY_get0_group(ec); | 
					
						
							|  |  |  |     if (!grp) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /* Determine curve ID */ | 
					
						
							|  |  |  |     id = EC_GROUP_get_curve_name(grp); | 
					
						
							|  |  |  |     id = tls1_ec_nid2curve_id(id); | 
					
						
							| 
									
										
										
										
											2016-02-13 23:26:15 +08:00
										 |  |  |     /* If no id return error: we don't support arbitrary explicit curves */ | 
					
						
							|  |  |  |     if (id == 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     curve_id[0] = 0; | 
					
						
							|  |  |  |     curve_id[1] = (unsigned char)id; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (comp_id) { | 
					
						
							|  |  |  |         if (EC_KEY_get0_public_key(ec) == NULL) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2016-02-13 23:26:15 +08:00
										 |  |  |         if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) { | 
					
						
							|  |  |  |             *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if ((nid_list[id - 1].flags & TLS_CURVE_TYPE) == TLS_CURVE_PRIME) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; | 
					
						
							| 
									
										
										
										
											2016-02-13 23:26:15 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-04 22:41:01 +08:00
										 |  |  | /* Check an EC key is compatible with extensions */ | 
					
						
							|  |  |  | static int tls1_check_ec_key(SSL *s, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                              unsigned char *curve_id, unsigned char *comp_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const unsigned char *pformats, *pcurves; | 
					
						
							|  |  |  |     size_t num_formats, num_curves, i; | 
					
						
							|  |  |  |     int j; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If point formats extension present check it, otherwise everything is | 
					
						
							|  |  |  |      * supported (see RFC4492). | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (comp_id && s->session->tlsext_ecpointformatlist) { | 
					
						
							|  |  |  |         pformats = s->session->tlsext_ecpointformatlist; | 
					
						
							|  |  |  |         num_formats = s->session->tlsext_ecpointformatlist_length; | 
					
						
							|  |  |  |         for (i = 0; i < num_formats; i++, pformats++) { | 
					
						
							|  |  |  |             if (*comp_id == *pformats) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (i == num_formats) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!curve_id) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     /* Check curve is consistent with client and server preferences */ | 
					
						
							|  |  |  |     for (j = 0; j <= 1; j++) { | 
					
						
							|  |  |  |         if (!tls1_get_curvelist(s, j, &pcurves, &num_curves)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-03-20 23:10:16 +08:00
										 |  |  |         if (j == 1 && num_curves == 0) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * If we've not received any curves then skip this check. | 
					
						
							|  |  |  |              * RFC 4492 does not require the supported elliptic curves extension | 
					
						
							|  |  |  |              * so if it is not sent we can just choose any curve. | 
					
						
							|  |  |  |              * It is invalid to send an empty list in the elliptic curves | 
					
						
							|  |  |  |              * extension, so num_curves == 0 always means no extension. | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         for (i = 0; i < num_curves; i++, pcurves += 2) { | 
					
						
							|  |  |  |             if (pcurves[0] == curve_id[0] && pcurves[1] == curve_id[1]) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (i == num_curves) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         /* For clients can only check sent curve list */ | 
					
						
							|  |  |  |         if (!s->server) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-27 02:38:10 +08:00
										 |  |  | static void tls1_get_formatlist(SSL *s, const unsigned char **pformats, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                                 size_t *num_formats) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If we have a custom point format list use it otherwise use default | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (s->tlsext_ecpointformatlist) { | 
					
						
							|  |  |  |         *pformats = s->tlsext_ecpointformatlist; | 
					
						
							|  |  |  |         *num_formats = s->tlsext_ecpointformatlist_length; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         *pformats = ecformats_default; | 
					
						
							|  |  |  |         /* For Suite B we don't support char2 fields */ | 
					
						
							|  |  |  |         if (tls1_suiteb(s)) | 
					
						
							|  |  |  |             *num_formats = sizeof(ecformats_default) - 1; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             *num_formats = sizeof(ecformats_default); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Check cert parameters compatible with extensions: currently just checks EC | 
					
						
							|  |  |  |  * certificates have compatible curves and compression. | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-08-15 23:15:05 +08:00
										 |  |  | static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     unsigned char comp_id, curve_id[2]; | 
					
						
							|  |  |  |     EVP_PKEY *pkey; | 
					
						
							|  |  |  |     int rv; | 
					
						
							| 
									
										
										
										
											2015-12-20 08:32:36 +08:00
										 |  |  |     pkey = X509_get0_pubkey(x); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!pkey) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /* If not EC nothing to do */ | 
					
						
							| 
									
										
										
										
											2016-01-19 08:21:12 +08:00
										 |  |  |     if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:21:12 +08:00
										 |  |  |     rv = tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!rv) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Can't check curve_id for client certs as we don't have a supported | 
					
						
							|  |  |  |      * curves extension. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     rv = tls1_check_ec_key(s, s->server ? curve_id : NULL, &comp_id); | 
					
						
							|  |  |  |     if (!rv) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Special case for suite B. We *MUST* sign using SHA256+P-256 or | 
					
						
							|  |  |  |      * SHA384+P-384, adjust digest if necessary. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (set_ee_md && tls1_suiteb(s)) { | 
					
						
							|  |  |  |         int check_md; | 
					
						
							|  |  |  |         size_t i; | 
					
						
							|  |  |  |         CERT *c = s->cert; | 
					
						
							|  |  |  |         if (curve_id[0]) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         /* Check to see we have necessary signing algorithm */ | 
					
						
							|  |  |  |         if (curve_id[1] == TLSEXT_curve_P_256) | 
					
						
							|  |  |  |             check_md = NID_ecdsa_with_SHA256; | 
					
						
							|  |  |  |         else if (curve_id[1] == TLSEXT_curve_P_384) | 
					
						
							|  |  |  |             check_md = NID_ecdsa_with_SHA384; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return 0;           /* Should never happen */ | 
					
						
							|  |  |  |         for (i = 0; i < c->shared_sigalgslen; i++) | 
					
						
							|  |  |  |             if (check_md == c->shared_sigalgs[i].signandhash_nid) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         if (i == c->shared_sigalgslen) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         if (set_ee_md == 2) { | 
					
						
							|  |  |  |             if (check_md == NID_ecdsa_with_SHA256) | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |                 s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha256(); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             else | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |                 s->s3->tmp.md[SSL_PKEY_ECC] = EVP_sha384(); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-11 07:09:27 +08:00
										 |  |  | # ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-12-05 05:25:11 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |  * tls1_check_ec_tmp_key - Check EC temporary key compatibility | 
					
						
							| 
									
										
										
										
											2015-12-05 05:25:11 +08:00
										 |  |  |  * @s: SSL connection | 
					
						
							|  |  |  |  * @cid: Cipher ID we're considering using | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Checks that the kECDHE cipher suite we're considering using | 
					
						
							|  |  |  |  * is compatible with the client extensions. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns 0 when the cipher can't be used or 1 when it can. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-08-15 23:15:05 +08:00
										 |  |  | int tls1_check_ec_tmp_key(SSL *s, unsigned long cid) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, no other | 
					
						
							|  |  |  |      * curves permitted. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (tls1_suiteb(s)) { | 
					
						
							| 
									
										
										
										
											2015-12-05 05:25:11 +08:00
										 |  |  |         unsigned char curve_id[2]; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /* Curve to check determined by ciphersuite */ | 
					
						
							|  |  |  |         if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) | 
					
						
							|  |  |  |             curve_id[1] = TLSEXT_curve_P_256; | 
					
						
							|  |  |  |         else if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) | 
					
						
							|  |  |  |             curve_id[1] = TLSEXT_curve_P_384; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         curve_id[0] = 0; | 
					
						
							|  |  |  |         /* Check this curve is acceptable */ | 
					
						
							|  |  |  |         if (!tls1_check_ec_key(s, curve_id, NULL)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-12-05 05:30:36 +08:00
										 |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-05 05:30:36 +08:00
										 |  |  |     /* Need a shared curve */ | 
					
						
							|  |  |  |     if (tls1_shared_curve(s, 0)) | 
					
						
							|  |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2015-12-05 05:25:11 +08:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-11 07:09:27 +08:00
										 |  |  | # endif                         /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2012-03-28 23:05:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-18 00:40:08 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-08-18 00:40:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #endif                          /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2006-01-03 11:27:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * List of supported signature algorithms and hashes. Should make this | 
					
						
							| 
									
										
										
										
											2011-05-12 00:33:28 +08:00
										 |  |  |  * customisable at some point, for now include everything we support. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifdef OPENSSL_NO_RSA
 | 
					
						
							|  |  |  | # define tlsext_sigalg_rsa(md) /* */
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifdef OPENSSL_NO_DSA
 | 
					
						
							|  |  |  | # define tlsext_sigalg_dsa(md) /* */
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifdef OPENSSL_NO_EC
 | 
					
						
							|  |  |  | # define tlsext_sigalg_ecdsa(md) /* */
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #define tlsext_sigalg(md) \
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 tlsext_sigalg_rsa(md) \ | 
					
						
							|  |  |  |                 tlsext_sigalg_dsa(md) \ | 
					
						
							|  |  |  |                 tlsext_sigalg_ecdsa(md) | 
					
						
							| 
									
										
										
										
											2011-05-12 00:33:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 05:41:15 +08:00
										 |  |  | static const unsigned char tls12_sigalgs[] = { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     tlsext_sigalg(TLSEXT_hash_sha512) | 
					
						
							|  |  |  |         tlsext_sigalg(TLSEXT_hash_sha384) | 
					
						
							|  |  |  |         tlsext_sigalg(TLSEXT_hash_sha256) | 
					
						
							|  |  |  |         tlsext_sigalg(TLSEXT_hash_sha224) | 
					
						
							|  |  |  |         tlsext_sigalg(TLSEXT_hash_sha1) | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  | #ifndef OPENSSL_NO_GOST
 | 
					
						
							|  |  |  |         TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001, | 
					
						
							|  |  |  |         TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256, | 
					
						
							|  |  |  |         TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-05-12 00:33:28 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2014-04-21 05:41:15 +08:00
										 |  |  | static const unsigned char suiteb_sigalgs[] = { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     tlsext_sigalg_ecdsa(TLSEXT_hash_sha256) | 
					
						
							|  |  |  |         tlsext_sigalg_ecdsa(TLSEXT_hash_sha384) | 
					
						
							| 
									
										
										
										
											2012-08-15 23:15:05 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-07-18 22:09:46 +08:00
										 |  |  | size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If Suite B mode use Suite B sigalgs only, ignore any other | 
					
						
							|  |  |  |      * preferences. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     switch (tls1_suiteb(s)) { | 
					
						
							|  |  |  |     case SSL_CERT_FLAG_SUITEB_128_LOS: | 
					
						
							|  |  |  |         *psigs = suiteb_sigalgs; | 
					
						
							|  |  |  |         return sizeof(suiteb_sigalgs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: | 
					
						
							|  |  |  |         *psigs = suiteb_sigalgs; | 
					
						
							|  |  |  |         return 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_CERT_FLAG_SUITEB_192_LOS: | 
					
						
							|  |  |  |         *psigs = suiteb_sigalgs + 2; | 
					
						
							|  |  |  |         return 2; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* If server use client authentication sigalgs if not NULL */ | 
					
						
							|  |  |  |     if (s->server && s->cert->client_sigalgs) { | 
					
						
							|  |  |  |         *psigs = s->cert->client_sigalgs; | 
					
						
							|  |  |  |         return s->cert->client_sigalgslen; | 
					
						
							|  |  |  |     } else if (s->cert->conf_sigalgs) { | 
					
						
							|  |  |  |         *psigs = s->cert->conf_sigalgs; | 
					
						
							|  |  |  |         return s->cert->conf_sigalgslen; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         *psigs = tls12_sigalgs; | 
					
						
							|  |  |  |         return sizeof(tls12_sigalgs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Check signature algorithm is consistent with sent supported signature | 
					
						
							| 
									
										
										
										
											2012-07-25 02:11:27 +08:00
										 |  |  |  * algorithms and if so return relevant digest. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                             const unsigned char *sig, EVP_PKEY *pkey) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const unsigned char *sent_sigs; | 
					
						
							|  |  |  |     size_t sent_sigslen, i; | 
					
						
							|  |  |  |     int sigalg = tls12_get_sigid(pkey); | 
					
						
							|  |  |  |     /* Should never happen */ | 
					
						
							|  |  |  |     if (sigalg == -1) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     /* Check key type is consistent with signature */ | 
					
						
							|  |  |  |     if (sigalg != (int)sig[1]) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2016-01-19 08:21:12 +08:00
										 |  |  |     if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         unsigned char curve_id[2], comp_id; | 
					
						
							|  |  |  |         /* Check compression and curve matches extensions */ | 
					
						
							| 
									
										
										
										
											2016-01-19 08:21:12 +08:00
										 |  |  |         if (!tls1_set_ec_id(curve_id, &comp_id, EVP_PKEY_get0_EC_KEY(pkey))) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |         if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */ | 
					
						
							|  |  |  |         if (tls1_suiteb(s)) { | 
					
						
							|  |  |  |             if (curve_id[0]) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             if (curve_id[1] == TLSEXT_curve_P_256) { | 
					
						
							|  |  |  |                 if (sig[0] != TLSEXT_hash_sha256) { | 
					
						
							|  |  |  |                     SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, | 
					
						
							|  |  |  |                            SSL_R_ILLEGAL_SUITEB_DIGEST); | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else if (curve_id[1] == TLSEXT_curve_P_384) { | 
					
						
							|  |  |  |                 if (sig[0] != TLSEXT_hash_sha384) { | 
					
						
							|  |  |  |                     SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, | 
					
						
							|  |  |  |                            SSL_R_ILLEGAL_SUITEB_DIGEST); | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (tls1_suiteb(s)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Check signature matches a type we sent */ | 
					
						
							|  |  |  |     sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); | 
					
						
							|  |  |  |     for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) { | 
					
						
							|  |  |  |         if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1]) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Allow fallback to SHA1 if not strict mode */ | 
					
						
							|  |  |  |     if (i == sent_sigslen | 
					
						
							|  |  |  |         && (sig[0] != TLSEXT_hash_sha1 | 
					
						
							|  |  |  |             || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *pmd = tls12_get_hash(sig[0]); | 
					
						
							|  |  |  |     if (*pmd == NULL) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Make sure security callback allows algorithm */ | 
					
						
							|  |  |  |     if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK, | 
					
						
							|  |  |  |                       EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), | 
					
						
							|  |  |  |                       (void *)sig)) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Store the digest used so applications can retrieve it if they wish. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |     s->s3->tmp.peer_md = *pmd; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-08-15 23:15:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-02-08 03:17:07 +08:00
										 |  |  |  * Set a mask of disabled algorithms: an algorithm is disabled if it isn't | 
					
						
							|  |  |  |  * supported, doesn't appear in supported signature algorithms, isn't supported | 
					
						
							|  |  |  |  * by the enabled protocol versions or by the security level. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This function should only be used for checking which ciphers are supported | 
					
						
							|  |  |  |  * by the client. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Call ssl_cipher_disabled() to check that it's enabled or not. | 
					
						
							| 
									
										
										
										
											2012-07-18 22:09:46 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | void ssl_set_client_disabled(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-19 06:29:57 +08:00
										 |  |  |     s->s3->tmp.mask_a = 0; | 
					
						
							|  |  |  |     s->s3->tmp.mask_k = 0; | 
					
						
							|  |  |  |     ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK); | 
					
						
							| 
									
										
										
										
											2016-02-08 03:17:07 +08:00
										 |  |  |     ssl_get_client_min_max_version(s, &s->s3->tmp.min_ver, &s->s3->tmp.max_ver); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # ifndef OPENSSL_NO_PSK
 | 
					
						
							|  |  |  |     /* with PSK there must be client callback set */ | 
					
						
							|  |  |  |     if (!s->psk_client_callback) { | 
					
						
							| 
									
										
										
										
											2015-05-19 06:29:57 +08:00
										 |  |  |         s->s3->tmp.mask_a |= SSL_aPSK; | 
					
						
							| 
									
										
										
										
											2015-06-29 00:01:07 +08:00
										 |  |  |         s->s3->tmp.mask_k |= SSL_PSK; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* OPENSSL_NO_PSK */
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_SRP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) { | 
					
						
							| 
									
										
										
										
											2015-05-19 06:29:57 +08:00
										 |  |  |         s->s3->tmp.mask_a |= SSL_aSRP; | 
					
						
							|  |  |  |         s->s3->tmp.mask_k |= SSL_kSRP; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-12 00:33:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-08 03:17:07 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ssl_cipher_disabled - check that a cipher is disabled or not | 
					
						
							|  |  |  |  * @s: SSL connection that you want to use the cipher on | 
					
						
							|  |  |  |  * @c: cipher to check | 
					
						
							|  |  |  |  * @op: Security check that you want to do | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns 1 when it's disabled, 0 when enabled. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-08 03:17:07 +08:00
										 |  |  |     if (c->algorithm_mkey & s->s3->tmp.mask_k | 
					
						
							| 
									
										
										
										
											2015-05-19 06:29:57 +08:00
										 |  |  |         || c->algorithm_auth & s->s3->tmp.mask_a) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2016-02-08 03:17:07 +08:00
										 |  |  |     if (s->s3->tmp.max_ver == 0) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     if (!SSL_IS_DTLS(s) && ((c->min_tls > s->s3->tmp.max_ver) | 
					
						
							|  |  |  |             || (c->max_tls < s->s3->tmp.min_ver))) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver) | 
					
						
							|  |  |  |             || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver))) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return !ssl_security(s, op, c->strength_bits, 0, (void *)c); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int tls_use_ticket(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (s->options & SSL_OP_NO_TICKET) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-01-03 07:14:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  | static int compare_uint(const void *p1, const void *p2) { | 
					
						
							|  |  |  |     unsigned int u1 = *((const unsigned int *)p1); | 
					
						
							|  |  |  |     unsigned int u2 = *((const unsigned int *)p2); | 
					
						
							|  |  |  |     if (u1 < u2) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     else if (u1 > u2) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
 | 
					
						
							|  |  |  |  * more than one extension of the same type in a ClientHello or ServerHello. | 
					
						
							|  |  |  |  * This function does an initial scan over the extensions block to filter those | 
					
						
							|  |  |  |  * out. It returns 1 if all extensions are unique, and 0 if the extensions | 
					
						
							|  |  |  |  * contain duplicates, could not be successfully parsed, or an internal error | 
					
						
							|  |  |  |  * occurred. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int tls1_check_duplicate_extensions(const PACKET *packet) { | 
					
						
							|  |  |  |     PACKET extensions = *packet; | 
					
						
							|  |  |  |     size_t num_extensions = 0, i = 0; | 
					
						
							|  |  |  |     unsigned int *extension_types = NULL; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* First pass: count the extensions. */ | 
					
						
							|  |  |  |     while (PACKET_remaining(&extensions) > 0) { | 
					
						
							|  |  |  |         unsigned int type; | 
					
						
							|  |  |  |         PACKET extension; | 
					
						
							|  |  |  |         if (!PACKET_get_net_2(&extensions, &type) || | 
					
						
							|  |  |  |             !PACKET_get_length_prefixed_2(&extensions, &extension)) { | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         num_extensions++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (num_extensions <= 1) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     extension_types = OPENSSL_malloc(sizeof(unsigned int) * num_extensions); | 
					
						
							|  |  |  |     if (extension_types == NULL) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Second pass: gather the extension types. */ | 
					
						
							|  |  |  |     extensions = *packet; | 
					
						
							|  |  |  |     for (i = 0; i < num_extensions; i++) { | 
					
						
							|  |  |  |         PACKET extension; | 
					
						
							|  |  |  |         if (!PACKET_get_net_2(&extensions, &extension_types[i]) || | 
					
						
							|  |  |  |             !PACKET_get_length_prefixed_2(&extensions, &extension)) { | 
					
						
							|  |  |  |             /* This should not happen. */ | 
					
						
							|  |  |  |             SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PACKET_remaining(&extensions) != 0) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Sort the extensions and make sure there are no duplicates. */ | 
					
						
							|  |  |  |     qsort(extension_types, num_extensions, sizeof(unsigned int), compare_uint); | 
					
						
							|  |  |  |     for (i = 1; i < num_extensions; i++) { | 
					
						
							|  |  |  |         if (extension_types[i - 1] == extension_types[i]) | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ret = 1; | 
					
						
							|  |  |  |  done: | 
					
						
							|  |  |  |     OPENSSL_free(extension_types); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, | 
					
						
							|  |  |  |                                           unsigned char *limit, int *al) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int extdatalen = 0; | 
					
						
							|  |  |  |     unsigned char *orig = buf; | 
					
						
							|  |  |  |     unsigned char *ret = buf; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* See if we support any ECC ciphersuites */ | 
					
						
							|  |  |  |     int using_ecc = 0; | 
					
						
							|  |  |  |     if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) { | 
					
						
							|  |  |  |         int i; | 
					
						
							|  |  |  |         unsigned long alg_k, alg_a; | 
					
						
							|  |  |  |         STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) { | 
					
						
							| 
									
										
										
										
											2015-12-23 08:47:28 +08:00
										 |  |  |             const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             alg_k = c->algorithm_mkey; | 
					
						
							|  |  |  |             alg_a = c->algorithm_auth; | 
					
						
							| 
									
										
										
										
											2016-02-12 02:19:27 +08:00
										 |  |  |             if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) | 
					
						
							|  |  |  |                  || (alg_a & SSL_aECDSA)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 using_ecc = 1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-01-03 07:14:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     ret += 2; | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (ret >= limit) | 
					
						
							|  |  |  |         return NULL;            /* this really never occurs, but ... */ | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* Add RI if renegotiating */ | 
					
						
							|  |  |  |     if (s->renegotiate) { | 
					
						
							|  |  |  |         int el; | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if ((limit - ret - 4 - el) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         s2n(TLSEXT_TYPE_renegotiate, ret); | 
					
						
							|  |  |  |         s2n(el, ret); | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-03-13 01:01:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         ret += el; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Only add RI for SSLv3 */ | 
					
						
							|  |  |  |     if (s->client_version == SSL3_VERSION) | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->tlsext_hostname != NULL) { | 
					
						
							|  |  |  |         /* Add TLS extension servername to the Client Hello message */ | 
					
						
							|  |  |  |         unsigned long size_str; | 
					
						
							|  |  |  |         long lenmax; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |         /*-
 | 
					
						
							|  |  |  |          * check for enough space. | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |          * 4 for the servername type and extension length | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |          * 2 for servernamelist length | 
					
						
							|  |  |  |          * 1 for the hostname type | 
					
						
							|  |  |  |          * 2 for hostname length | 
					
						
							|  |  |  |          * + hostname length | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ((lenmax = limit - ret - 9) < 0 | 
					
						
							|  |  |  |             || (size_str = | 
					
						
							|  |  |  |                 strlen(s->tlsext_hostname)) > (unsigned long)lenmax) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* extension type and length */ | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_server_name, ret); | 
					
						
							|  |  |  |         s2n(size_str + 5, ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* length of servername list */ | 
					
						
							|  |  |  |         s2n(size_str + 3, ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* hostname type, length and hostname */ | 
					
						
							|  |  |  |         *(ret++) = (unsigned char)TLSEXT_NAMETYPE_host_name; | 
					
						
							|  |  |  |         s2n(size_str, ret); | 
					
						
							|  |  |  |         memcpy(ret, s->tlsext_hostname, size_str); | 
					
						
							|  |  |  |         ret += size_str; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_SRP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* Add SRP username if there is one */ | 
					
						
							|  |  |  |     if (s->srp_ctx.login != NULL) { /* Add TLS extension SRP username to the
 | 
					
						
							|  |  |  |                                      * Client Hello message */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         int login_len = strlen(s->srp_ctx.login); | 
					
						
							|  |  |  |         if (login_len > 255 || login_len == 0) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-09-21 14:54:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |         /*-
 | 
					
						
							|  |  |  |          * check for enough space. | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |          * 4 for the srp type type and extension length | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |          * 1 for the srp user identity | 
					
						
							|  |  |  |          * + srp user identity length | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if ((limit - ret - 5 - login_len) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* fill in the extension */ | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_srp, ret); | 
					
						
							|  |  |  |         s2n(login_len + 1, ret); | 
					
						
							|  |  |  |         (*ret++) = (unsigned char)login_len; | 
					
						
							|  |  |  |         memcpy(ret, s->srp_ctx.login, login_len); | 
					
						
							|  |  |  |         ret += login_len; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (using_ecc) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Add TLS extension ECPointFormats to the ClientHello message | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         long lenmax; | 
					
						
							|  |  |  |         const unsigned char *pcurves, *pformats; | 
					
						
							|  |  |  |         size_t num_curves, num_formats, curves_list_len; | 
					
						
							|  |  |  |         size_t i; | 
					
						
							|  |  |  |         unsigned char *etmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tls1_get_formatlist(s, &pformats, &num_formats); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((lenmax = limit - ret - 5) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (num_formats > (size_t)lenmax) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (num_formats > 255) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-01-01 06:59:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         s2n(TLSEXT_TYPE_ec_point_formats, ret); | 
					
						
							|  |  |  |         /* The point format list has 1-byte length. */ | 
					
						
							|  |  |  |         s2n(num_formats + 1, ret); | 
					
						
							|  |  |  |         *(ret++) = (unsigned char)num_formats; | 
					
						
							|  |  |  |         memcpy(ret, pformats, num_formats); | 
					
						
							|  |  |  |         ret += num_formats; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Add TLS extension EllipticCurves to the ClientHello message | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         pcurves = s->tlsext_ellipticcurvelist; | 
					
						
							|  |  |  |         if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((lenmax = limit - ret - 6) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (num_curves > (size_t)lenmax / 2) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (num_curves > 65532 / 2) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-07-28 18:06:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         s2n(TLSEXT_TYPE_elliptic_curves, ret); | 
					
						
							|  |  |  |         etmp = ret + 4; | 
					
						
							|  |  |  |         /* Copy curve ID if supported */ | 
					
						
							|  |  |  |         for (i = 0; i < num_curves; i++, pcurves += 2) { | 
					
						
							|  |  |  |             if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) { | 
					
						
							|  |  |  |                 *etmp++ = pcurves[0]; | 
					
						
							|  |  |  |                 *etmp++ = pcurves[1]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-06-01 23:08:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         curves_list_len = etmp - ret - 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s2n(curves_list_len + 2, ret); | 
					
						
							|  |  |  |         s2n(curves_list_len, ret); | 
					
						
							|  |  |  |         ret += curves_list_len; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (tls_use_ticket(s)) { | 
					
						
							|  |  |  |         int ticklen; | 
					
						
							|  |  |  |         if (!s->new_session && s->session && s->session->tlsext_tick) | 
					
						
							|  |  |  |             ticklen = s->session->tlsext_ticklen; | 
					
						
							|  |  |  |         else if (s->session && s->tlsext_session_ticket && | 
					
						
							|  |  |  |                  s->tlsext_session_ticket->data) { | 
					
						
							|  |  |  |             ticklen = s->tlsext_session_ticket->length; | 
					
						
							|  |  |  |             s->session->tlsext_tick = OPENSSL_malloc(ticklen); | 
					
						
							| 
									
										
										
										
											2015-10-30 18:05:53 +08:00
										 |  |  |             if (s->session->tlsext_tick == NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return NULL; | 
					
						
							|  |  |  |             memcpy(s->session->tlsext_tick, | 
					
						
							|  |  |  |                    s->tlsext_session_ticket->data, ticklen); | 
					
						
							|  |  |  |             s->session->tlsext_ticklen = ticklen; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             ticklen = 0; | 
					
						
							|  |  |  |         if (ticklen == 0 && s->tlsext_session_ticket && | 
					
						
							|  |  |  |             s->tlsext_session_ticket->data == NULL) | 
					
						
							|  |  |  |             goto skip_ext; | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Check for enough room 2 for extension type, 2 for len rest for | 
					
						
							|  |  |  |          * ticket | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if ((long)(limit - ret - 4 - ticklen) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_session_ticket, ret); | 
					
						
							|  |  |  |         s2n(ticklen, ret); | 
					
						
							|  |  |  |         if (ticklen) { | 
					
						
							|  |  |  |             memcpy(ret, s->session->tlsext_tick, ticklen); | 
					
						
							|  |  |  |             ret += ticklen; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |  skip_ext: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:49:20 +08:00
										 |  |  |     if (SSL_CLIENT_USE_SIGALGS(s)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         size_t salglen; | 
					
						
							|  |  |  |         const unsigned char *salg; | 
					
						
							|  |  |  |         unsigned char *etmp; | 
					
						
							|  |  |  |         salglen = tls12_get_psigalgs(s, &salg); | 
					
						
							|  |  |  |         if ((size_t)(limit - ret) < salglen + 6) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_signature_algorithms, ret); | 
					
						
							|  |  |  |         etmp = ret; | 
					
						
							|  |  |  |         /* Skip over lengths for now */ | 
					
						
							|  |  |  |         ret += 4; | 
					
						
							|  |  |  |         salglen = tls12_copy_sigalgs(s, ret, salg, salglen); | 
					
						
							|  |  |  |         /* Fill in lengths */ | 
					
						
							|  |  |  |         s2n(salglen + 2, etmp); | 
					
						
							|  |  |  |         s2n(salglen, etmp); | 
					
						
							|  |  |  |         ret += salglen; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-22 00:54:53 +08:00
										 |  |  | #ifndef OPENSSL_NO_OCSP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) { | 
					
						
							|  |  |  |         int i; | 
					
						
							|  |  |  |         long extlen, idlen, itmp; | 
					
						
							|  |  |  |         OCSP_RESPID *id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         idlen = 0; | 
					
						
							|  |  |  |         for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { | 
					
						
							|  |  |  |             id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); | 
					
						
							|  |  |  |             itmp = i2d_OCSP_RESPID(id, NULL); | 
					
						
							|  |  |  |             if (itmp <= 0) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             idlen += itmp + 2; | 
					
						
							| 
									
										
										
										
											2009-11-11 22:51:19 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (s->tlsext_ocsp_exts) { | 
					
						
							|  |  |  |             extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL); | 
					
						
							|  |  |  |             if (extlen < 0) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             extlen = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((long)(limit - ret - 7 - extlen - idlen) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_status_request, ret); | 
					
						
							|  |  |  |         if (extlen + idlen > 0xFFF0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(extlen + idlen + 5, ret); | 
					
						
							|  |  |  |         *(ret++) = TLSEXT_STATUSTYPE_ocsp; | 
					
						
							|  |  |  |         s2n(idlen, ret); | 
					
						
							|  |  |  |         for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { | 
					
						
							|  |  |  |             /* save position of id len */ | 
					
						
							|  |  |  |             unsigned char *q = ret; | 
					
						
							|  |  |  |             id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i); | 
					
						
							|  |  |  |             /* skip over id len */ | 
					
						
							|  |  |  |             ret += 2; | 
					
						
							|  |  |  |             itmp = i2d_OCSP_RESPID(id, &ret); | 
					
						
							|  |  |  |             /* write id len */ | 
					
						
							|  |  |  |             s2n(itmp, q); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         s2n(extlen, ret); | 
					
						
							|  |  |  |         if (extlen > 0) | 
					
						
							|  |  |  |             i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-22 00:54:53 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_HEARTBEATS
 | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |     if (SSL_IS_DTLS(s)) { | 
					
						
							|  |  |  |         /* Add Heartbeat extension */ | 
					
						
							|  |  |  |         if ((limit - ret - 4 - 1) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_heartbeat, ret); | 
					
						
							|  |  |  |         s2n(1, ret); | 
					
						
							|  |  |  |         /*-
 | 
					
						
							|  |  |  |          * Set mode: | 
					
						
							|  |  |  |          * 1: peer may send requests | 
					
						
							|  |  |  |          * 2: peer not allowed to send requests | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS) | 
					
						
							|  |  |  |             *(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             *(ret++) = SSL_DTLSEXT_HB_ENABLED; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |          * The client advertises an empty extension to indicate its support | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |          * for Next Protocol Negotiation | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (limit - ret - 4 < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_next_proto_neg, ret); | 
					
						
							|  |  |  |         s2n(0, ret); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * finish_md_len is non-zero during a renegotiation, so | 
					
						
							|  |  |  |      * this avoids sending ALPN during the renegotiation | 
					
						
							|  |  |  |      * (see longer comment below) | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) { | 
					
						
							|  |  |  |         if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret); | 
					
						
							|  |  |  |         s2n(2 + s->alpn_client_proto_list_len, ret); | 
					
						
							|  |  |  |         s2n(s->alpn_client_proto_list_len, ret); | 
					
						
							|  |  |  |         memcpy(ret, s->alpn_client_proto_list, s->alpn_client_proto_list_len); | 
					
						
							|  |  |  |         ret += s->alpn_client_proto_list_len; | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |         s->s3->alpn_sent = 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_SRTP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) { | 
					
						
							|  |  |  |         int el; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-06 22:37:17 +08:00
										 |  |  |         /* Returns 0 on success!! */ | 
					
						
							|  |  |  |         if (ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ((limit - ret - 4 - el) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_use_srtp, ret); | 
					
						
							|  |  |  |         s2n(el, ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ssl_add_clienthello_use_srtp_ext(s, ret, &el, el)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ret += el; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     custom_ext_init(&s->cert->cli_ext); | 
					
						
							|  |  |  |     /* Add custom TLS Extensions to ClientHello */ | 
					
						
							|  |  |  |     if (!custom_ext_add(s, 0, &ret, limit, al)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     s2n(TLSEXT_TYPE_encrypt_then_mac, ret); | 
					
						
							|  |  |  |     s2n(0, ret); | 
					
						
							| 
									
										
										
										
											2016-03-04 00:19:23 +08:00
										 |  |  | #ifndef OPENSSL_NO_CT
 | 
					
						
							|  |  |  |     if (s->ct_validation_callback != NULL) { | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_signed_certificate_timestamp, ret); | 
					
						
							|  |  |  |         s2n(0, ret); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-23 10:45:13 +08:00
										 |  |  |     s2n(TLSEXT_TYPE_extended_master_secret, ret); | 
					
						
							|  |  |  |     s2n(0, ret); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Add padding to workaround bugs in F5 terminators. See | 
					
						
							|  |  |  |      * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
 | 
					
						
							|  |  |  |      * code works out the length of all existing extensions it MUST always | 
					
						
							|  |  |  |      * appear last. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (s->options & SSL_OP_TLSEXT_PADDING) { | 
					
						
							|  |  |  |         int hlen = ret - (unsigned char *)s->init_buf->data; | 
					
						
							| 
									
										
										
										
											2015-03-31 20:57:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (hlen > 0xff && hlen < 0x200) { | 
					
						
							|  |  |  |             hlen = 0x200 - hlen; | 
					
						
							|  |  |  |             if (hlen >= 4) | 
					
						
							|  |  |  |                 hlen -= 4; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 hlen = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             s2n(TLSEXT_TYPE_padding, ret); | 
					
						
							|  |  |  |             s2n(hlen, ret); | 
					
						
							|  |  |  |             memset(ret, 0, hlen); | 
					
						
							|  |  |  |             ret += hlen; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  done: | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if ((extdatalen = ret - orig - 2) == 0) | 
					
						
							|  |  |  |         return orig; | 
					
						
							| 
									
										
										
										
											2014-11-04 01:47:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s2n(extdatalen, orig); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-16 06:59:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, | 
					
						
							|  |  |  |                                           unsigned char *limit, int *al) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int extdatalen = 0; | 
					
						
							|  |  |  |     unsigned char *orig = buf; | 
					
						
							|  |  |  |     unsigned char *ret = buf; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int next_proto_neg_seen; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; | 
					
						
							|  |  |  |     unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; | 
					
						
							| 
									
										
										
										
											2016-02-12 02:19:27 +08:00
										 |  |  |     int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ret += 2; | 
					
						
							|  |  |  |     if (ret >= limit) | 
					
						
							|  |  |  |         return NULL;            /* this really never occurs, but ... */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->s3->send_connection_binding) { | 
					
						
							|  |  |  |         int el; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-11-16 06:59:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if ((limit - ret - 4 - el) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2011-11-16 06:59:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         s2n(TLSEXT_TYPE_renegotiate, ret); | 
					
						
							|  |  |  |         s2n(el, ret); | 
					
						
							| 
									
										
										
										
											2011-11-16 06:59:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-11-16 06:59:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         ret += el; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Only add RI for SSLv3 */ | 
					
						
							|  |  |  |     if (s->version == SSL3_VERSION) | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!s->hit && s->servername_done == 1 | 
					
						
							|  |  |  |         && s->session->tlsext_hostname != NULL) { | 
					
						
							|  |  |  |         if ((long)(limit - ret - 4) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_server_name, ret); | 
					
						
							|  |  |  |         s2n(0, ret); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (using_ecc) { | 
					
						
							|  |  |  |         const unsigned char *plist; | 
					
						
							|  |  |  |         size_t plistlen; | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Add TLS extension ECPointFormats to the ServerHello message | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         long lenmax; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tls1_get_formatlist(s, &plist, &plistlen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((lenmax = limit - ret - 5) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (plistlen > (size_t)lenmax) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (plistlen > 255) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-01-01 06:59:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         s2n(TLSEXT_TYPE_ec_point_formats, ret); | 
					
						
							|  |  |  |         s2n(plistlen + 1, ret); | 
					
						
							|  |  |  |         *(ret++) = (unsigned char)plistlen; | 
					
						
							|  |  |  |         memcpy(ret, plist, plistlen); | 
					
						
							|  |  |  |         ret += plistlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Currently the server should not respond with a SupportedCurves | 
					
						
							|  |  |  |      * extension | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s->tlsext_ticket_expected && tls_use_ticket(s)) { | 
					
						
							|  |  |  |         if ((long)(limit - ret - 4) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_session_ticket, ret); | 
					
						
							|  |  |  |         s2n(0, ret); | 
					
						
							| 
									
										
											  
											
												Fix session ticket and SNI
When session tickets are used, it's possible that SNI might swtich the
SSL_CTX on an SSL. Normally, this is not a problem, because the
initial_ctx/session_ctx are used for all session ticket/id processes.
However, when the SNI callback occurs, it's possible that the callback
may update the options in the SSL from the SSL_CTX, and this could
cause SSL_OP_NO_TICKET to be set. If this occurs, then two bad things
can happen:
1. The session ticket TLSEXT may not be written when the ticket expected
flag is set. The state machine transistions to writing the ticket, and
the client responds with an error as its not expecting a ticket.
2. When creating the session ticket, if the ticket key cb returns 0
the crypto/hmac contexts are not initialized, and the code crashes when
trying to encrypt the session ticket.
To fix 1, if the ticket TLSEXT is not written out, clear the expected
ticket flag.
To fix 2, consider a return of 0 from the ticket key cb a recoverable
error, and write a 0 length ticket and continue. The client-side code
can explicitly handle this case.
Fix these two cases, and add unit test code to validate ticket behavior.
Reviewed-by: Emilia Käsper <emilia@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1098)
											
										 
											2016-05-13 06:16:52 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         /* if we don't add the above TLSEXT, we can't add a session ticket later */ | 
					
						
							|  |  |  |         s->tlsext_ticket_expected = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->tlsext_status_expected) { | 
					
						
							|  |  |  |         if ((long)(limit - ret - 4) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_status_request, ret); | 
					
						
							|  |  |  |         s2n(0, ret); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_SRTP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (SSL_IS_DTLS(s) && s->srtp_profile) { | 
					
						
							|  |  |  |         int el; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-06 22:37:17 +08:00
										 |  |  |         /* Returns 0 on success!! */ | 
					
						
							| 
									
										
										
										
											2015-04-16 13:50:03 +08:00
										 |  |  |         if (ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0)) { | 
					
						
							| 
									
										
										
										
											2015-03-06 22:37:17 +08:00
										 |  |  |             SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if ((limit - ret - 4 - el) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_use_srtp, ret); | 
					
						
							|  |  |  |         s2n(el, ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ret += el; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (((s->s3->tmp.new_cipher->id & 0xFFFF) == 0x80 | 
					
						
							|  |  |  |          || (s->s3->tmp.new_cipher->id & 0xFFFF) == 0x81) | 
					
						
							|  |  |  |         && (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG)) { | 
					
						
							|  |  |  |         const unsigned char cryptopro_ext[36] = { | 
					
						
							|  |  |  |             0xfd, 0xe8,         /* 65000 */ | 
					
						
							|  |  |  |             0x00, 0x20,         /* 32 bytes length */ | 
					
						
							|  |  |  |             0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, | 
					
						
							|  |  |  |             0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, | 
					
						
							|  |  |  |             0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, | 
					
						
							|  |  |  |             0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         if (limit - ret < 36) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         memcpy(ret, cryptopro_ext, 36); | 
					
						
							|  |  |  |         ret += 36; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_HEARTBEATS
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* Add Heartbeat extension if we've received one */ | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |     if (SSL_IS_DTLS(s) && (s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if ((limit - ret - 4 - 1) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_heartbeat, ret); | 
					
						
							|  |  |  |         s2n(1, ret); | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |         /*-
 | 
					
						
							|  |  |  |          * Set mode: | 
					
						
							|  |  |  |          * 1: peer may send requests | 
					
						
							|  |  |  |          * 2: peer not allowed to send requests | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |         if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS) | 
					
						
							|  |  |  |             *(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |             *(ret++) = SSL_DTLSEXT_HB_ENABLED; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     next_proto_neg_seen = s->s3->next_proto_neg_seen; | 
					
						
							|  |  |  |     s->s3->next_proto_neg_seen = 0; | 
					
						
							|  |  |  |     if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) { | 
					
						
							|  |  |  |         const unsigned char *npa; | 
					
						
							|  |  |  |         unsigned int npalen; | 
					
						
							|  |  |  |         int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen, | 
					
						
							|  |  |  |                                               s-> | 
					
						
							|  |  |  |                                               ctx->next_protos_advertised_cb_arg); | 
					
						
							|  |  |  |         if (r == SSL_TLSEXT_ERR_OK) { | 
					
						
							|  |  |  |             if ((long)(limit - ret - 4 - npalen) < 0) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             s2n(TLSEXT_TYPE_next_proto_neg, ret); | 
					
						
							|  |  |  |             s2n(npalen, ret); | 
					
						
							|  |  |  |             memcpy(ret, npa, npalen); | 
					
						
							|  |  |  |             ret += npalen; | 
					
						
							|  |  |  |             s->s3->next_proto_neg_seen = 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!custom_ext_add(s, 1, &ret, limit, al)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Don't use encrypt_then_mac if AEAD or RC4 might want to disable | 
					
						
							|  |  |  |          * for other cases too. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |             || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 | 
					
						
							|  |  |  |             || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT | 
					
						
							|  |  |  |             || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             s2n(TLSEXT_TYPE_encrypt_then_mac, ret); | 
					
						
							|  |  |  |             s2n(0, ret); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |     if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) { | 
					
						
							| 
									
										
										
										
											2015-01-23 10:45:13 +08:00
										 |  |  |         s2n(TLSEXT_TYPE_extended_master_secret, ret); | 
					
						
							|  |  |  |         s2n(0, ret); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |     if (s->s3->alpn_selected != NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         const unsigned char *selected = s->s3->alpn_selected; | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |         unsigned int len = s->s3->alpn_selected_len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret); | 
					
						
							|  |  |  |         s2n(3 + len, ret); | 
					
						
							|  |  |  |         s2n(1 + len, ret); | 
					
						
							|  |  |  |         *ret++ = len; | 
					
						
							|  |  |  |         memcpy(ret, selected, len); | 
					
						
							|  |  |  |         ret += len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  done: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((extdatalen = ret - orig - 2) == 0) | 
					
						
							|  |  |  |         return orig; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s2n(extdatalen, orig); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-05-13 09:55:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |  * Save the ALPN extension in a ClientHello. | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |  * pkt: the contents of the ALPN extension, not including type and length. | 
					
						
							|  |  |  |  * al: a pointer to the  alert value to send in the event of a failure. | 
					
						
							|  |  |  |  * returns: 1 on success, 0 on error. | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     PACKET protocol_list, save_protocol_list, protocol; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     *al = SSL_AD_DECODE_ERROR; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) | 
					
						
							|  |  |  |         || PACKET_remaining(&protocol_list) < 2) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     save_protocol_list = protocol_list; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     do { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |         /* Protocol names can't be empty. */ | 
					
						
							|  |  |  |         if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) | 
					
						
							|  |  |  |             || PACKET_remaining(&protocol) == 0) { | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } while (PACKET_remaining(&protocol_list) != 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |     if (!PACKET_memdup(&save_protocol_list, | 
					
						
							|  |  |  |                        &s->s3->alpn_proposed, | 
					
						
							|  |  |  |                        &s->s3->alpn_proposed_len)) { | 
					
						
							|  |  |  |         *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Process the ALPN extension in a ClientHello. | 
					
						
							|  |  |  |  * ret: a pointer to the TLSEXT return value: SSL_TLSEXT_ERR_* | 
					
						
							|  |  |  |  * al: a pointer to the alert value to send in the event of a failure. | 
					
						
							|  |  |  |  * returns 1 on success, 0 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int tls1_alpn_handle_client_hello_late(SSL *s, int *ret, int *al) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const unsigned char *selected = NULL; | 
					
						
							|  |  |  |     unsigned char selected_len = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->ctx->alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) { | 
					
						
							|  |  |  |         int r = s->ctx->alpn_select_cb(s, &selected, &selected_len, | 
					
						
							|  |  |  |                                        s->s3->alpn_proposed, | 
					
						
							|  |  |  |                                        s->s3->alpn_proposed_len, | 
					
						
							|  |  |  |                                        s->ctx->alpn_select_cb_arg); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |         if (r == SSL_TLSEXT_ERR_OK) { | 
					
						
							|  |  |  |             OPENSSL_free(s->s3->alpn_selected); | 
					
						
							|  |  |  |             s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len); | 
					
						
							|  |  |  |             if (s->s3->alpn_selected == NULL) { | 
					
						
							|  |  |  |                 *al = SSL_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 *ret = SSL_TLSEXT_ERR_ALERT_FATAL; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             s->s3->alpn_selected_len = selected_len; | 
					
						
							| 
									
										
										
										
											2016-03-12 22:14:05 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							|  |  |  |             /* ALPN takes precedence over NPN. */ | 
					
						
							|  |  |  |             s->s3->next_proto_neg_seen = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             *al = SSL_AD_NO_APPLICATION_PROTOCOL; | 
					
						
							|  |  |  |             *ret = SSL_TLSEXT_ERR_ALERT_FATAL; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-04-16 06:07:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  | /*-
 | 
					
						
							|  |  |  |  * ssl_check_for_safari attempts to fingerprint Safari using OS X | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |  * SecureTransport using the TLS extension block in |pkt|. | 
					
						
							| 
									
										
										
										
											2013-09-05 20:09:03 +08:00
										 |  |  |  * Safari, since 10.6, sends exactly these extensions, in this order: | 
					
						
							|  |  |  |  *   SNI, | 
					
						
							|  |  |  |  *   elliptic_curves | 
					
						
							|  |  |  |  *   ec_point_formats | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8, | 
					
						
							|  |  |  |  * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them. | 
					
						
							|  |  |  |  * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from | 
					
						
							|  |  |  |  * 10.8..10.8.3 (which don't work). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-10-07 22:20:47 +08:00
										 |  |  | static void ssl_check_for_safari(SSL *s, const PACKET *pkt) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     unsigned int type; | 
					
						
							|  |  |  |     PACKET sni, tmppkt; | 
					
						
							|  |  |  |     size_t ext_len; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     static const unsigned char kSafariExtensionsBlock[] = { | 
					
						
							|  |  |  |         0x00, 0x0a,             /* elliptic_curves extension */ | 
					
						
							|  |  |  |         0x00, 0x08,             /* 8 bytes */ | 
					
						
							|  |  |  |         0x00, 0x06,             /* 6 bytes of curve ids */ | 
					
						
							|  |  |  |         0x00, 0x17,             /* P-256 */ | 
					
						
							|  |  |  |         0x00, 0x18,             /* P-384 */ | 
					
						
							|  |  |  |         0x00, 0x19,             /* P-521 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         0x00, 0x0b,             /* ec_point_formats */ | 
					
						
							|  |  |  |         0x00, 0x02,             /* 2 bytes */ | 
					
						
							|  |  |  |         0x01,                   /* 1 point format */ | 
					
						
							|  |  |  |         0x00,                   /* uncompressed */ | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |         /* The following is only present in TLS 1.2 */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         0x00, 0x0d,             /* signature_algorithms */ | 
					
						
							|  |  |  |         0x00, 0x0c,             /* 12 bytes */ | 
					
						
							|  |  |  |         0x00, 0x0a,             /* 10 bytes */ | 
					
						
							|  |  |  |         0x05, 0x01,             /* SHA-384/RSA */ | 
					
						
							|  |  |  |         0x04, 0x01,             /* SHA-256/RSA */ | 
					
						
							|  |  |  |         0x02, 0x01,             /* SHA-1/RSA */ | 
					
						
							|  |  |  |         0x04, 0x03,             /* SHA-256/ECDSA */ | 
					
						
							|  |  |  |         0x02, 0x03,             /* SHA-1/ECDSA */ | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     /* Length of the common prefix (first two extensions). */ | 
					
						
							|  |  |  |     static const size_t kSafariCommonExtensionsLength = 18; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-07 22:20:47 +08:00
										 |  |  |     tmppkt = *pkt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PACKET_forward(&tmppkt, 2) | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |         || !PACKET_get_net_2(&tmppkt, &type) | 
					
						
							|  |  |  |         || !PACKET_get_length_prefixed_2(&tmppkt, &sni)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (type != TLSEXT_TYPE_server_name) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ? | 
					
						
							|  |  |  |         sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock, | 
					
						
							|  |  |  |                                              ext_len); | 
					
						
							| 
									
										
										
										
											2013-09-05 20:09:03 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* !OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Parse ClientHello extensions and stash extension info in various parts of | 
					
						
							|  |  |  |  * the SSL object. Verify that there are no duplicate extensions. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Behaviour upon resumption is extension-specific. If the extension has no | 
					
						
							|  |  |  |  * effect during resumption, it is parsed (to verify its format) but otherwise | 
					
						
							|  |  |  |  * ignored. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Consumes the entire packet in |pkt|. Returns 1 on success and 0 on failure. | 
					
						
							|  |  |  |  * Upon failure, sets |al| to the appropriate alert. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     unsigned int type; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int renegotiate_seen = 0; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     PACKET extensions; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     *al = SSL_AD_DECODE_ERROR; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s->servername_done = 0; | 
					
						
							|  |  |  |     s->tlsext_status_type = -1; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s->s3->next_proto_neg_seen = 0; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(s->s3->alpn_selected); | 
					
						
							|  |  |  |     s->s3->alpn_selected = NULL; | 
					
						
							| 
									
										
										
										
											2016-03-12 22:14:05 +08:00
										 |  |  |     s->s3->alpn_selected_len = 0; | 
					
						
							|  |  |  |     OPENSSL_free(s->s3->alpn_proposed); | 
					
						
							|  |  |  |     s->s3->alpn_proposed = NULL; | 
					
						
							|  |  |  |     s->s3->alpn_proposed_len = 0; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_HEARTBEATS
 | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |     s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED | | 
					
						
							|  |  |  |                              SSL_DTLSEXT_HB_DONT_SEND_REQUESTS); | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |         ssl_check_for_safari(s, pkt); | 
					
						
							|  |  |  | # endif /* !OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Clear any signature algorithms extension received */ | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |     OPENSSL_free(s->s3->tmp.peer_sigalgs); | 
					
						
							|  |  |  |     s->s3->tmp.peer_sigalgs = NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_SRP
 | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(s->srp_ctx.login); | 
					
						
							|  |  |  |     s->srp_ctx.login = NULL; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     s->srtp_profile = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     if (PACKET_remaining(pkt) == 0) | 
					
						
							| 
									
										
										
										
											2015-06-12 15:05:49 +08:00
										 |  |  |         goto ri_check; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     if (!PACKET_as_length_prefixed_2(pkt, &extensions)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     if (!tls1_check_duplicate_extensions(&extensions)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * We parse all extensions to ensure the ClientHello is well-formed but, | 
					
						
							|  |  |  |      * unless an extension specifies otherwise, we ignore extensions upon | 
					
						
							|  |  |  |      * resumption. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     while (PACKET_get_net_2(&extensions, &type)) { | 
					
						
							|  |  |  |         PACKET extension; | 
					
						
							|  |  |  |         if (!PACKET_get_length_prefixed_2(&extensions, &extension)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (s->tlsext_debug_cb) | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             s->tlsext_debug_cb(s, 0, type, PACKET_data(&extension), | 
					
						
							|  |  |  |                                PACKET_remaining(&extension), | 
					
						
							|  |  |  |                                s->tlsext_debug_arg); | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (type == TLSEXT_TYPE_renegotiate) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (!ssl_parse_clienthello_renegotiate_ext(s, &extension, al)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |             renegotiate_seen = 1; | 
					
						
							|  |  |  |         } else if (s->version == SSL3_VERSION) { | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  | /*-
 | 
					
						
							|  |  |  |  * The servername extension is treated as follows: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - Only the hostname type is supported with a maximum length of 255. | 
					
						
							|  |  |  |  * - The servername is rejected if too long or if it contains zeros, | 
					
						
							|  |  |  |  *   in which case an fatal alert is generated. | 
					
						
							|  |  |  |  * - The servername field is maintained together with the session cache. | 
					
						
							|  |  |  |  * - When a session is resumed, the servername call back invoked in order | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  *   to allow the application to position itself to the right context. | 
					
						
							|  |  |  |  * - The servername is acknowledged if it is new for a session or when | 
					
						
							|  |  |  |  *   it is identical to a previously used for the same session. | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  |  *   Applications can control the behaviour.  They can at any time | 
					
						
							|  |  |  |  *   set a 'desirable' servername for a new SSL object. This can be the | 
					
						
							|  |  |  |  *   case for example with HTTPS when a Host: header field is received and | 
					
						
							|  |  |  |  *   a renegotiation is requested. In this case, a possible servername | 
					
						
							|  |  |  |  *   presented in the new client hello is only acknowledged if it matches | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  *   the value of the Host: field. | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  |  * - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  *   if they provide for changing an explicit servername context for the | 
					
						
							|  |  |  |  *   session, i.e. when the session has been established with a servername | 
					
						
							|  |  |  |  *   extension. | 
					
						
							|  |  |  |  * - On session reconnect, the servername extension may be absent. | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2006-01-03 07:14:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_server_name) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |             unsigned int servname_type; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             PACKET sni, hostname; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!PACKET_as_length_prefixed_2(&extension, &sni) | 
					
						
							|  |  |  |                 /* ServerNameList must be at least 1 byte long. */ | 
					
						
							|  |  |  |                 || PACKET_remaining(&sni) == 0) { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-04-16 06:07:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             /*
 | 
					
						
							|  |  |  |              * Although the server_name extension was intended to be | 
					
						
							|  |  |  |              * extensible to new name types, RFC 4366 defined the | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |              * syntax inextensibility and OpenSSL 1.0.x parses it as | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |              * such. | 
					
						
							|  |  |  |              * RFC 6066 corrected the mistake but adding new name types | 
					
						
							|  |  |  |              * is nevertheless no longer feasible, so act as if no other | 
					
						
							|  |  |  |              * SNI types can exist, to simplify parsing. | 
					
						
							|  |  |  |              * | 
					
						
							|  |  |  |              * Also note that the RFC permits only one SNI value per type, | 
					
						
							|  |  |  |              * i.e., we can only have a single hostname. | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             if (!PACKET_get_1(&sni, &servname_type) | 
					
						
							|  |  |  |                 || servname_type != TLSEXT_NAMETYPE_host_name | 
					
						
							|  |  |  |                 || !PACKET_as_length_prefixed_2(&sni, &hostname)) { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!s->hit) { | 
					
						
							|  |  |  |                 if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) { | 
					
						
							|  |  |  |                     *al = TLS1_AD_UNRECOGNIZED_NAME; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (PACKET_contains_zero_byte(&hostname)) { | 
					
						
							|  |  |  |                     *al = TLS1_AD_UNRECOGNIZED_NAME; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (!PACKET_strndup(&hostname, &s->session->tlsext_hostname)) { | 
					
						
							|  |  |  |                     *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 s->servername_done = 1; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                  * TODO(openssl-team): if the SNI doesn't match, we MUST | 
					
						
							|  |  |  |                  * fall back to a full handshake. | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |                 s->servername_done = s->session->tlsext_hostname | 
					
						
							|  |  |  |                     && PACKET_equal(&hostname, s->session->tlsext_hostname, | 
					
						
							|  |  |  |                                     strlen(s->session->tlsext_hostname)); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_SRP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_srp) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             PACKET srp_I; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!PACKET_as_length_prefixed_1(&extension, &srp_I)) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (PACKET_contains_zero_byte(&srp_I)) | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * TODO(openssl-team): currently, we re-authenticate the user | 
					
						
							|  |  |  |              * upon resumption. Instead, we MUST ignore the login. | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_ec_point_formats) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             PACKET ec_point_format_list; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (!PACKET_as_length_prefixed_1(&extension, | 
					
						
							|  |  |  |                                               &ec_point_format_list) | 
					
						
							|  |  |  |                 || PACKET_remaining(&ec_point_format_list) == 0) { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             if (!s->hit) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                 if (!PACKET_memdup(&ec_point_format_list, | 
					
						
							|  |  |  |                                    &s->session->tlsext_ecpointformatlist, | 
					
						
							|  |  |  |                                    &s->session->tlsext_ecpointformatlist_length)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (type == TLSEXT_TYPE_elliptic_curves) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             PACKET elliptic_curve_list; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             /* Each NamedCurve is 2 bytes and we must have at least 1. */ | 
					
						
							|  |  |  |             if (!PACKET_as_length_prefixed_2(&extension, | 
					
						
							|  |  |  |                                              &elliptic_curve_list) | 
					
						
							|  |  |  |                 || PACKET_remaining(&elliptic_curve_list) == 0 | 
					
						
							|  |  |  |                 || (PACKET_remaining(&elliptic_curve_list) % 2) != 0) { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-04-30 22:20:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             if (!s->hit) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                 if (!PACKET_memdup(&elliptic_curve_list, | 
					
						
							|  |  |  |                                    &s->session->tlsext_ellipticcurvelist, | 
					
						
							|  |  |  |                                    &s->session->tlsext_ellipticcurvelist_length)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_session_ticket) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (s->tls_session_ticket_ext_cb && | 
					
						
							|  |  |  |                 !s->tls_session_ticket_ext_cb(s, PACKET_data(&extension), | 
					
						
							|  |  |  |                                               PACKET_remaining(&extension), | 
					
						
							|  |  |  |                                               s->tls_session_ticket_ext_cb_arg)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (type == TLSEXT_TYPE_signature_algorithms) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             PACKET supported_sig_algs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!PACKET_as_length_prefixed_2(&extension, &supported_sig_algs) | 
					
						
							|  |  |  |                 || (PACKET_remaining(&supported_sig_algs) % 2) != 0 | 
					
						
							|  |  |  |                 || PACKET_remaining(&supported_sig_algs) == 0) { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if  (!s->hit) { | 
					
						
							|  |  |  |                 if (!tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs), | 
					
						
							|  |  |  |                                        PACKET_remaining(&supported_sig_algs))) { | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } else if (type == TLSEXT_TYPE_status_request) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (!PACKET_get_1(&extension, | 
					
						
							|  |  |  |                               (unsigned int *)&s->tlsext_status_type)) { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-22 00:54:53 +08:00
										 |  |  | #ifndef OPENSSL_NO_OCSP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) { | 
					
						
							| 
									
										
										
										
											2016-03-22 00:54:53 +08:00
										 |  |  |                 const unsigned char *ext_data; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                 PACKET responder_id_list, exts; | 
					
						
							|  |  |  |                 if (!PACKET_get_length_prefixed_2(&extension, &responder_id_list)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 while (PACKET_remaining(&responder_id_list) > 0) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     OCSP_RESPID *id; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                     PACKET responder_id; | 
					
						
							|  |  |  |                     const unsigned char *id_data; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                     if (!PACKET_get_length_prefixed_2(&responder_id_list, | 
					
						
							|  |  |  |                                                       &responder_id) | 
					
						
							|  |  |  |                         || PACKET_remaining(&responder_id) == 0) { | 
					
						
							|  |  |  |                         return 0; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (s->tlsext_ocsp_ids == NULL | 
					
						
							|  |  |  |                         && (s->tlsext_ocsp_ids = | 
					
						
							|  |  |  |                             sk_OCSP_RESPID_new_null()) == NULL) { | 
					
						
							|  |  |  |                         *al = SSL_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                         return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     id_data = PACKET_data(&responder_id); | 
					
						
							|  |  |  |                     id = d2i_OCSP_RESPID(NULL, &id_data, | 
					
						
							|  |  |  |                                          PACKET_remaining(&responder_id)); | 
					
						
							|  |  |  |                     if (id == NULL) | 
					
						
							|  |  |  |                         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (id_data != PACKET_end(&responder_id)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                         OCSP_RESPID_free(id); | 
					
						
							|  |  |  |                         return 0; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) { | 
					
						
							|  |  |  |                         OCSP_RESPID_free(id); | 
					
						
							|  |  |  |                         *al = SSL_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                         return 0; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2012-01-01 06:59:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 /* Read in request_extensions */ | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                 if (!PACKET_as_length_prefixed_2(&extension, &exts)) | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (PACKET_remaining(&exts) > 0) { | 
					
						
							|  |  |  |                     ext_data = PACKET_data(&exts); | 
					
						
							| 
									
										
										
										
											2015-05-01 05:33:59 +08:00
										 |  |  |                     sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, | 
					
						
							|  |  |  |                                                X509_EXTENSION_free); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     s->tlsext_ocsp_exts = | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                         d2i_X509_EXTENSIONS(NULL, &ext_data, | 
					
						
							|  |  |  |                                             PACKET_remaining(&exts)); | 
					
						
							|  |  |  |                     if (s->tlsext_ocsp_exts == NULL | 
					
						
							|  |  |  |                         || ext_data != PACKET_end(&exts)) { | 
					
						
							|  |  |  |                         return 0; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-03-22 00:54:53 +08:00
										 |  |  |             } else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                  * We don't know what to do with any other type so ignore it. | 
					
						
							|  |  |  |                  */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 s->tlsext_status_type = -1; | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_HEARTBEATS
 | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |         else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |             unsigned int hbtype; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (!PACKET_get_1(&extension, &hbtype) | 
					
						
							|  |  |  |                     || PACKET_remaining(&extension)) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 *al = SSL_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             switch (hbtype) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             case 0x01:         /* Client allows us to send HB requests */ | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |                 s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 0x02:         /* Client doesn't accept HB requests */ | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |                 s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; | 
					
						
							|  |  |  |                 s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 *al = SSL_AD_ILLEGAL_PARAMETER; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_next_proto_neg && | 
					
						
							| 
									
										
										
										
											2016-03-12 22:14:05 +08:00
										 |  |  |                  s->s3->tmp.finish_md_len == 0) { | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |             /*-
 | 
					
						
							|  |  |  |              * We shouldn't accept this extension on a | 
					
						
							|  |  |  |              * renegotiation. | 
					
						
							|  |  |  |              * | 
					
						
							|  |  |  |              * s->new_session will be set on renegotiation, but we | 
					
						
							|  |  |  |              * probably shouldn't rely that it couldn't be set on | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |              * the initial renegotiation too in certain cases (when | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |              * there's some other reason to disallow resuming an | 
					
						
							|  |  |  |              * earlier session -- the current code won't be doing | 
					
						
							|  |  |  |              * anything like that, but this might change). | 
					
						
							|  |  |  |              * | 
					
						
							|  |  |  |              * A valid sign that there's been a previous handshake | 
					
						
							|  |  |  |              * in this connection is if s->s3->tmp.finish_md_len > | 
					
						
							|  |  |  |              * 0.  (We are talking about a check that will happen | 
					
						
							|  |  |  |              * in the Hello protocol round, well before a new | 
					
						
							|  |  |  |              * Finished message could have been computed.) | 
					
						
							|  |  |  |              */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             s->s3->next_proto_neg_seen = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation && | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |                  s->s3->tmp.finish_md_len == 0) { | 
					
						
							|  |  |  |             if (!tls1_alpn_handle_client_hello(s, &extension, al)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-03-23 01:12:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /* session ticket processed earlier */ | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_SRTP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s) | 
					
						
							|  |  |  |                  && type == TLSEXT_TYPE_use_srtp) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (ssl_parse_clienthello_use_srtp_ext(s, &extension, al)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_encrypt_then_mac) | 
					
						
							|  |  |  |             s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * Note: extended master secret extension handled in | 
					
						
							|  |  |  |          * tls_check_serverhello_tlsext_early() | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * If this ClientHello extension was unhandled and this is a | 
					
						
							|  |  |  |          * nonresumed connection, check whether the extension is a custom | 
					
						
							|  |  |  |          * TLS Extension (has a custom_srv_ext_record), and if so call the | 
					
						
							|  |  |  |          * callback and record the extension number so that an appropriate | 
					
						
							|  |  |  |          * ServerHello may be later returned. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         else if (!s->hit) { | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |             if (custom_ext_parse(s, 1, type, PACKET_data(&extension), | 
					
						
							|  |  |  |                                  PACKET_remaining(&extension), al) <= 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-04-16 06:07:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     if (PACKET_remaining(pkt) != 0) { | 
					
						
							|  |  |  |         /* tls1_check_duplicate_extensions should ensure this never happens. */ | 
					
						
							|  |  |  |         *al = SSL_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-04-30 22:20:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  ri_check: | 
					
						
							| 
									
										
										
										
											2006-01-03 07:14:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* Need RI if renegotiating */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!renegotiate_seen && s->renegotiate && | 
					
						
							|  |  |  |         !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { | 
					
						
							|  |  |  |         *al = SSL_AD_HANDSHAKE_FAILURE; | 
					
						
							|  |  |  |         SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, | 
					
						
							|  |  |  |                SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 21:20:26 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * This function currently has no state to clean up, so it returns directly. | 
					
						
							|  |  |  |      * If parsing fails at any point, the function returns early. | 
					
						
							|  |  |  |      * The SSL object may be left with partial data from extensions, but it must | 
					
						
							|  |  |  |      * then no longer be used, and clearing it up will free the leftovers. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int al = -1; | 
					
						
							|  |  |  |     custom_ext_init(&s->cert->srv_ext); | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     if (ssl_scan_clienthello_tlsext(s, pkt, &al) <= 0) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         ssl3_send_alert(s, SSL3_AL_FATAL, al); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ssl_check_clienthello_tlsext_early(s) <= 0) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_CLIENTHELLO_TLSEXT); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ssl_next_proto_validate validates a Next Protocol Negotiation block. No | 
					
						
							|  |  |  |  * elements of zero length are allowed and the set of elements must exactly | 
					
						
							|  |  |  |  * fill the length of the block. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  | static char ssl_next_proto_validate(PACKET *pkt) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-12 23:51:06 +08:00
										 |  |  |     PACKET tmp_protocol; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     while (PACKET_remaining(pkt)) { | 
					
						
							| 
									
										
										
										
											2015-12-12 23:51:06 +08:00
										 |  |  |         if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol) | 
					
						
							|  |  |  |                 || PACKET_remaining(&tmp_protocol) == 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  | static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     unsigned int length, type, size; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int tlsext_servername = 0; | 
					
						
							|  |  |  |     int renegotiate_seen = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s->s3->next_proto_neg_seen = 0; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     s->tlsext_ticket_expected = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(s->s3->alpn_selected); | 
					
						
							|  |  |  |     s->s3->alpn_selected = NULL; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_HEARTBEATS
 | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |     s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED | | 
					
						
							|  |  |  |                              SSL_DTLSEXT_HB_DONT_SEND_REQUESTS); | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |     s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     if (!PACKET_get_net_2(pkt, &length)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         goto ri_check; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     if (PACKET_remaining(pkt) != length) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         *al = SSL_AD_DECODE_ERROR; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  |     if (!tls1_check_duplicate_extensions(pkt)) { | 
					
						
							|  |  |  |         *al = SSL_AD_DECODE_ERROR; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) { | 
					
						
							| 
									
										
										
										
											2016-02-01 22:26:18 +08:00
										 |  |  |         const unsigned char *data; | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |         PACKET spkt; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |         if (!PACKET_get_sub_packet(pkt, &spkt, size) | 
					
						
							|  |  |  |                 ||  !PACKET_peek_bytes(&spkt, &data, size)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             goto ri_check; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (s->tlsext_debug_cb) | 
					
						
							|  |  |  |             s->tlsext_debug_cb(s, 1, type, data, size, s->tlsext_debug_arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (type == TLSEXT_TYPE_renegotiate) { | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             if (!ssl_parse_serverhello_renegotiate_ext(s, &spkt, al)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |             renegotiate_seen = 1; | 
					
						
							|  |  |  |         } else if (s->version == SSL3_VERSION) { | 
					
						
							|  |  |  |         } else if (type == TLSEXT_TYPE_server_name) { | 
					
						
							|  |  |  |             if (s->tlsext_hostname == NULL || size > 0) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_UNRECOGNIZED_NAME; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             tlsext_servername = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_ec_point_formats) { | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             unsigned int ecpointformatlist_length; | 
					
						
							|  |  |  |             if (!PACKET_get_1(&spkt, &ecpointformatlist_length) | 
					
						
							|  |  |  |                     || ecpointformatlist_length != size - 1) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!s->hit) { | 
					
						
							|  |  |  |                 s->session->tlsext_ecpointformatlist_length = 0; | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |                 OPENSSL_free(s->session->tlsext_ecpointformatlist); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 if ((s->session->tlsext_ecpointformatlist = | 
					
						
							|  |  |  |                      OPENSSL_malloc(ecpointformatlist_length)) == NULL) { | 
					
						
							|  |  |  |                     *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 s->session->tlsext_ecpointformatlist_length = | 
					
						
							|  |  |  |                     ecpointformatlist_length; | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |                 if (!PACKET_copy_bytes(&spkt, | 
					
						
							|  |  |  |                                        s->session->tlsext_ecpointformatlist, | 
					
						
							|  |  |  |                                        ecpointformatlist_length)) { | 
					
						
							|  |  |  |                     *al = TLS1_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         else if (type == TLSEXT_TYPE_session_ticket) { | 
					
						
							|  |  |  |             if (s->tls_session_ticket_ext_cb && | 
					
						
							|  |  |  |                 !s->tls_session_ticket_ext_cb(s, data, size, | 
					
						
							|  |  |  |                                               s->tls_session_ticket_ext_cb_arg)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!tls_use_ticket(s) || (size > 0)) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_UNSUPPORTED_EXTENSION; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             s->tlsext_ticket_expected = 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (type == TLSEXT_TYPE_status_request) { | 
					
						
							|  |  |  |             /*
 | 
					
						
							|  |  |  |              * MUST be empty and only sent if we've requested a status | 
					
						
							|  |  |  |              * request message. | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             if ((s->tlsext_status_type == -1) || (size > 0)) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_UNSUPPORTED_EXTENSION; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             /* Set flag to expect CertificateStatus message */ | 
					
						
							|  |  |  |             s->tlsext_status_expected = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-03-04 00:19:23 +08:00
										 |  |  | #ifndef OPENSSL_NO_CT
 | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Only take it if we asked for it - i.e if there is no CT validation | 
					
						
							|  |  |  |          * callback set, then a custom extension MAY be processing it, so we | 
					
						
							|  |  |  |          * need to let control continue to flow to that. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         else if (type == TLSEXT_TYPE_signed_certificate_timestamp && | 
					
						
							|  |  |  |                  s->ct_validation_callback != NULL) { | 
					
						
							|  |  |  |             /* Simply copy it off for later processing */ | 
					
						
							|  |  |  |             if (s->tlsext_scts != NULL) { | 
					
						
							|  |  |  |                 OPENSSL_free(s->tlsext_scts); | 
					
						
							|  |  |  |                 s->tlsext_scts = NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             s->tlsext_scts_len = size; | 
					
						
							|  |  |  |             if (size > 0) { | 
					
						
							|  |  |  |                 s->tlsext_scts = OPENSSL_malloc(size); | 
					
						
							|  |  |  |                 if (s->tlsext_scts == NULL) { | 
					
						
							|  |  |  |                     *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 memcpy(s->tlsext_scts, data, size); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_NEXTPROTONEG
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_next_proto_neg && | 
					
						
							|  |  |  |                  s->s3->tmp.finish_md_len == 0) { | 
					
						
							|  |  |  |             unsigned char *selected; | 
					
						
							|  |  |  |             unsigned char selected_len; | 
					
						
							|  |  |  |             /* We must have requested it. */ | 
					
						
							|  |  |  |             if (s->ctx->next_proto_select_cb == NULL) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_UNSUPPORTED_EXTENSION; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             /* The data must be valid */ | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             if (!ssl_next_proto_validate(&spkt)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (s-> | 
					
						
							|  |  |  |                 ctx->next_proto_select_cb(s, &selected, &selected_len, data, | 
					
						
							|  |  |  |                                           size, | 
					
						
							|  |  |  |                                           s->ctx->next_proto_select_cb_arg) != | 
					
						
							|  |  |  |                 SSL_TLSEXT_ERR_OK) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             s->next_proto_negotiated = OPENSSL_malloc(selected_len); | 
					
						
							| 
									
										
										
										
											2015-10-30 18:05:53 +08:00
										 |  |  |             if (s->next_proto_negotiated == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             memcpy(s->next_proto_negotiated, selected, selected_len); | 
					
						
							|  |  |  |             s->next_proto_negotiated_len = selected_len; | 
					
						
							|  |  |  |             s->s3->next_proto_neg_seen = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) { | 
					
						
							|  |  |  |             unsigned len; | 
					
						
							|  |  |  |             /* We must have requested it. */ | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |             if (!s->s3->alpn_sent) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_UNSUPPORTED_EXTENSION; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-05 19:30:03 +08:00
										 |  |  |             /*-
 | 
					
						
							|  |  |  |              * The extension data consists of: | 
					
						
							|  |  |  |              *   uint16 list_length | 
					
						
							|  |  |  |              *   uint8 proto_length; | 
					
						
							|  |  |  |              *   uint8 proto[proto_length]; | 
					
						
							|  |  |  |              */ | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             if (!PACKET_get_net_2(&spkt, &len) | 
					
						
							|  |  |  |                     || PACKET_remaining(&spkt) != len | 
					
						
							|  |  |  |                     || !PACKET_get_1(&spkt, &len) | 
					
						
							|  |  |  |                     || PACKET_remaining(&spkt) != len) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |             OPENSSL_free(s->s3->alpn_selected); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             s->s3->alpn_selected = OPENSSL_malloc(len); | 
					
						
							| 
									
										
										
										
											2015-10-30 18:05:53 +08:00
										 |  |  |             if (s->s3->alpn_selected == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 *al = TLS1_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             if (!PACKET_copy_bytes(&spkt, s->s3->alpn_selected, len)) { | 
					
						
							|  |  |  |                 *al = TLS1_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             s->s3->alpn_selected_len = len; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_HEARTBEATS
 | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |         else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) { | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             unsigned int hbtype; | 
					
						
							|  |  |  |             if (!PACKET_get_1(&spkt, &hbtype)) { | 
					
						
							|  |  |  |                 *al = SSL_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             switch (hbtype) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             case 0x01:         /* Server allows us to send HB requests */ | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |                 s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 0x02:         /* Server doesn't accept HB requests */ | 
					
						
							| 
									
										
										
										
											2016-01-26 02:30:37 +08:00
										 |  |  |                 s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; | 
					
						
							|  |  |  |                 s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 *al = SSL_AD_ILLEGAL_PARAMETER; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_SRTP
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) { | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |             if (ssl_parse_serverhello_use_srtp_ext(s, &spkt, al)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 return 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_encrypt_then_mac) { | 
					
						
							|  |  |  |             /* Ignore if inappropriate ciphersuite */ | 
					
						
							|  |  |  |             if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD | 
					
						
							|  |  |  |                 && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4) | 
					
						
							|  |  |  |                 s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-23 10:45:13 +08:00
										 |  |  |         else if (type == TLSEXT_TYPE_extended_master_secret) { | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |             s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; | 
					
						
							| 
									
										
										
										
											2015-01-23 10:45:13 +08:00
										 |  |  |             if (!s->hit) | 
					
						
							|  |  |  |                 s->session->flags |= SSL_SESS_FLAG_EXTMS; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * If this extension type was not otherwise handled, but matches a | 
					
						
							|  |  |  |          * custom_cli_ext_record, then send it to the c callback | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         else if (custom_ext_parse(s, 0, type, data, size, al) <= 0) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     if (PACKET_remaining(pkt) != 0) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         *al = SSL_AD_DECODE_ERROR; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!s->hit && tlsext_servername == 1) { | 
					
						
							|  |  |  |         if (s->tlsext_hostname) { | 
					
						
							|  |  |  |             if (s->session->tlsext_hostname == NULL) { | 
					
						
							| 
									
										
										
											
												Rename some BUF_xxx to OPENSSL_xxx
Rename BUF_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
to OPENSSL_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
Add #define's for the old names.
Add CRYPTO_{memdup,strndup}, called by OPENSSL_{memdup,strndup} macros.
Reviewed-by: Tim Hudson <tjh@openssl.org>
											
										 
											2015-12-17 05:12:24 +08:00
										 |  |  |                 s->session->tlsext_hostname = OPENSSL_strdup(s->tlsext_hostname); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                 if (!s->session->tlsext_hostname) { | 
					
						
							|  |  |  |                     *al = SSL_AD_UNRECOGNIZED_NAME; | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 *al = SSL_AD_DECODE_ERROR; | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  ri_check: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Determine if we need to see RI. Strictly speaking if we want to avoid | 
					
						
							|  |  |  |      * an attack we should *always* see RI even on initial server hello | 
					
						
							|  |  |  |      * because the client doesn't see any renegotiation during an attack. | 
					
						
							|  |  |  |      * However this would mean we could not connect to any server which | 
					
						
							| 
									
										
										
										
											2016-06-14 17:41:00 +08:00
										 |  |  |      * doesn't support RI so for the immediate future tolerate RI absence | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     if (!renegotiate_seen && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) | 
					
						
							|  |  |  |         && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { | 
					
						
							|  |  |  |         *al = SSL_AD_HANDSHAKE_FAILURE; | 
					
						
							|  |  |  |         SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, | 
					
						
							|  |  |  |                SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |     if (s->hit) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Check extended master secret extension is consistent with | 
					
						
							|  |  |  |          * original session. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) != | 
					
						
							|  |  |  |             !(s->session->flags & SSL_SESS_FLAG_EXTMS)) { | 
					
						
							|  |  |  |             *al = SSL_AD_HANDSHAKE_FAILURE; | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_INCONSISTENT_EXTMS); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-04-03 19:56:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-12 07:46:37 +08:00
										 |  |  | int ssl_prepare_clienthello_tlsext(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |     s->s3->alpn_sent = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-03-12 07:46:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int ssl_prepare_serverhello_tlsext(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-03-12 07:46:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 20:57:46 +08:00
										 |  |  | static int ssl_check_clienthello_tlsext_early(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int ret = SSL_TLSEXT_ERR_NOACK; | 
					
						
							|  |  |  |     int al = SSL_AD_UNRECOGNIZED_NAME; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * The handling of the ECPointFormats extension is done elsewhere, namely | 
					
						
							|  |  |  |      * in ssl3_choose_cipher in s3_lib.c. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * The handling of the EllipticCurves extension is done elsewhere, namely | 
					
						
							|  |  |  |      * in ssl3_choose_cipher in s3_lib.c. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) | 
					
						
							|  |  |  |         ret = | 
					
						
							|  |  |  |             s->ctx->tlsext_servername_callback(s, &al, | 
					
						
							|  |  |  |                                                s->ctx->tlsext_servername_arg); | 
					
						
							|  |  |  |     else if (s->initial_ctx != NULL | 
					
						
							|  |  |  |              && s->initial_ctx->tlsext_servername_callback != 0) | 
					
						
							|  |  |  |         ret = | 
					
						
							|  |  |  |             s->initial_ctx->tlsext_servername_callback(s, &al, | 
					
						
							|  |  |  |                                                        s-> | 
					
						
							|  |  |  |                                                        initial_ctx->tlsext_servername_arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (ret) { | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_ALERT_FATAL: | 
					
						
							|  |  |  |         ssl3_send_alert(s, SSL3_AL_FATAL, al); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_ALERT_WARNING: | 
					
						
							|  |  |  |         ssl3_send_alert(s, SSL3_AL_WARNING, al); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_NOACK: | 
					
						
							|  |  |  |         s->servername_done = 0; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  | /* Initialise digests to default values */ | 
					
						
							| 
									
										
										
										
											2015-11-24 08:08:35 +08:00
										 |  |  | void ssl_set_default_md(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const EVP_MD **pmd = s->s3->tmp.md; | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_DSA
 | 
					
						
							| 
									
										
										
										
											2015-11-30 00:27:08 +08:00
										 |  |  |     pmd[SSL_PKEY_DSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX); | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_RSA
 | 
					
						
							| 
									
										
										
										
											2015-08-30 05:11:05 +08:00
										 |  |  |     if (SSL_USE_SIGALGS(s)) | 
					
						
							| 
									
										
										
										
											2015-11-30 00:27:08 +08:00
										 |  |  |         pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_SHA1_IDX); | 
					
						
							| 
									
										
										
										
											2015-08-30 05:11:05 +08:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2015-11-30 00:27:08 +08:00
										 |  |  |         pmd[SSL_PKEY_RSA_SIGN] = ssl_md(SSL_MD_MD5_SHA1_IDX); | 
					
						
							| 
									
										
										
										
											2015-08-30 05:11:05 +08:00
										 |  |  |     pmd[SSL_PKEY_RSA_ENC] = pmd[SSL_PKEY_RSA_SIGN]; | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-11-30 00:27:08 +08:00
										 |  |  |     pmd[SSL_PKEY_ECC] = ssl_md(SSL_MD_SHA1_IDX); | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  | #ifndef OPENSSL_NO_GOST
 | 
					
						
							| 
									
										
										
										
											2015-11-30 00:27:08 +08:00
										 |  |  |     pmd[SSL_PKEY_GOST01] = ssl_md(SSL_MD_GOST94_IDX); | 
					
						
							|  |  |  |     pmd[SSL_PKEY_GOST12_256] = ssl_md(SSL_MD_GOST12_256_IDX); | 
					
						
							|  |  |  |     pmd[SSL_PKEY_GOST12_512] = ssl_md(SSL_MD_GOST12_512_IDX); | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-01-03 11:27:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-18 00:52:59 +08:00
										 |  |  | int tls1_set_server_sigalgs(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int al; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Clear any shared signature algorithms */ | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(s->cert->shared_sigalgs); | 
					
						
							|  |  |  |     s->cert->shared_sigalgs = NULL; | 
					
						
							|  |  |  |     s->cert->shared_sigalgslen = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* Clear certificate digests and validity flags */ | 
					
						
							|  |  |  |     for (i = 0; i < SSL_PKEY_NUM; i++) { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |         s->s3->tmp.md[i] = NULL; | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |         s->s3->tmp.valid_flags[i] = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If sigalgs received process it. */ | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |     if (s->s3->tmp.peer_sigalgs) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (!tls1_process_sigalgs(s)) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |             al = SSL_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* Fatal error is no shared signature algorithms */ | 
					
						
							|  |  |  |         if (!s->cert->shared_sigalgs) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, | 
					
						
							|  |  |  |                    SSL_R_NO_SHARED_SIGATURE_ALGORITHMS); | 
					
						
							|  |  |  |             al = SSL_AD_ILLEGAL_PARAMETER; | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         ssl_set_default_md(s); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     ssl3_send_alert(s, SSL3_AL_FATAL, al); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-11-18 00:52:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 20:57:46 +08:00
										 |  |  | int ssl_check_clienthello_tlsext_late(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int ret = SSL_TLSEXT_ERR_OK; | 
					
						
							| 
									
										
										
										
											2015-05-06 17:16:55 +08:00
										 |  |  |     int al = SSL_AD_INTERNAL_ERROR; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If status request then ask callback what to do. Note: this must be | 
					
						
							|  |  |  |      * called after servername callbacks in case the certificate has changed, | 
					
						
							|  |  |  |      * and must be called after the cipher has been chosen because this may | 
					
						
							|  |  |  |      * influence which certificate is sent | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) { | 
					
						
							|  |  |  |         int r; | 
					
						
							|  |  |  |         CERT_PKEY *certpkey; | 
					
						
							|  |  |  |         certpkey = ssl_get_server_send_pkey(s); | 
					
						
							|  |  |  |         /* If no certificate can't return certificate status */ | 
					
						
							|  |  |  |         if (certpkey == NULL) { | 
					
						
							|  |  |  |             s->tlsext_status_expected = 0; | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Set current certificate to one we will use so SSL_get_certificate | 
					
						
							|  |  |  |          * et al can pick it up. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         s->cert->key = certpkey; | 
					
						
							|  |  |  |         r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); | 
					
						
							|  |  |  |         switch (r) { | 
					
						
							|  |  |  |             /* We don't want to send a status request response */ | 
					
						
							|  |  |  |         case SSL_TLSEXT_ERR_NOACK: | 
					
						
							|  |  |  |             s->tlsext_status_expected = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |             /* status request response should be sent */ | 
					
						
							|  |  |  |         case SSL_TLSEXT_ERR_OK: | 
					
						
							|  |  |  |             if (s->tlsext_ocsp_resp) | 
					
						
							|  |  |  |                 s->tlsext_status_expected = 1; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 s->tlsext_status_expected = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |             /* something bad happened */ | 
					
						
							|  |  |  |         case SSL_TLSEXT_ERR_ALERT_FATAL: | 
					
						
							|  |  |  |             ret = SSL_TLSEXT_ERR_ALERT_FATAL; | 
					
						
							|  |  |  |             al = SSL_AD_INTERNAL_ERROR; | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         s->tlsext_status_expected = 0; | 
					
						
							| 
									
										
										
										
											2012-09-11 20:57:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-05 21:47:55 +08:00
										 |  |  |     if (!tls1_alpn_handle_client_hello_late(s, &ret, &al)) { | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 20:57:46 +08:00
										 |  |  |  err: | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     switch (ret) { | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_ALERT_FATAL: | 
					
						
							|  |  |  |         ssl3_send_alert(s, SSL3_AL_FATAL, al); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_ALERT_WARNING: | 
					
						
							|  |  |  |         ssl3_send_alert(s, SSL3_AL_WARNING, al); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-09-11 20:57:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-12 07:46:37 +08:00
										 |  |  | int ssl_check_serverhello_tlsext(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int ret = SSL_TLSEXT_ERR_NOACK; | 
					
						
							|  |  |  |     int al = SSL_AD_UNRECOGNIZED_NAME; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * If we are client and using an elliptic curve cryptography cipher | 
					
						
							|  |  |  |      * suite, then if server returns an EC point formats lists extension it | 
					
						
							|  |  |  |      * must contain uncompressed. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; | 
					
						
							|  |  |  |     unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; | 
					
						
							|  |  |  |     if ((s->tlsext_ecpointformatlist != NULL) | 
					
						
							|  |  |  |         && (s->tlsext_ecpointformatlist_length > 0) | 
					
						
							|  |  |  |         && (s->session->tlsext_ecpointformatlist != NULL) | 
					
						
							|  |  |  |         && (s->session->tlsext_ecpointformatlist_length > 0) | 
					
						
							| 
									
										
										
										
											2016-02-12 02:19:27 +08:00
										 |  |  |         && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /* we are using an ECC cipher */ | 
					
						
							|  |  |  |         size_t i; | 
					
						
							|  |  |  |         unsigned char *list; | 
					
						
							|  |  |  |         int found_uncompressed = 0; | 
					
						
							|  |  |  |         list = s->session->tlsext_ecpointformatlist; | 
					
						
							|  |  |  |         for (i = 0; i < s->session->tlsext_ecpointformatlist_length; i++) { | 
					
						
							|  |  |  |             if (*(list++) == TLSEXT_ECPOINTFORMAT_uncompressed) { | 
					
						
							|  |  |  |                 found_uncompressed = 1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!found_uncompressed) { | 
					
						
							|  |  |  |             SSLerr(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT, | 
					
						
							|  |  |  |                    SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ret = SSL_TLSEXT_ERR_OK; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif                         /* OPENSSL_NO_EC */
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) | 
					
						
							|  |  |  |         ret = | 
					
						
							|  |  |  |             s->ctx->tlsext_servername_callback(s, &al, | 
					
						
							|  |  |  |                                                s->ctx->tlsext_servername_arg); | 
					
						
							|  |  |  |     else if (s->initial_ctx != NULL | 
					
						
							|  |  |  |              && s->initial_ctx->tlsext_servername_callback != 0) | 
					
						
							|  |  |  |         ret = | 
					
						
							|  |  |  |             s->initial_ctx->tlsext_servername_callback(s, &al, | 
					
						
							|  |  |  |                                                        s-> | 
					
						
							|  |  |  |                                                        initial_ctx->tlsext_servername_arg); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-10 18:44:30 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Ensure we get sensible values passed to tlsext_status_cb in the event | 
					
						
							|  |  |  |      * that we don't receive a status message | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-11-05 22:31:11 +08:00
										 |  |  |     OPENSSL_free(s->tlsext_ocsp_resp); | 
					
						
							|  |  |  |     s->tlsext_ocsp_resp = NULL; | 
					
						
							|  |  |  |     s->tlsext_ocsp_resplen = -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (ret) { | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_ALERT_FATAL: | 
					
						
							|  |  |  |         ssl3_send_alert(s, SSL3_AL_FATAL, al); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_ALERT_WARNING: | 
					
						
							|  |  |  |         ssl3_send_alert(s, SSL3_AL_WARNING, al); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SSL_TLSEXT_ERR_NOACK: | 
					
						
							|  |  |  |         s->servername_done = 0; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-09-21 14:54:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  | int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int al = -1; | 
					
						
							|  |  |  |     if (s->version < SSL3_VERSION) | 
					
						
							|  |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2015-08-05 00:36:02 +08:00
										 |  |  |     if (ssl_scan_serverhello_tlsext(s, pkt, &al) <= 0) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         ssl3_send_alert(s, SSL3_AL_FATAL, al); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ssl_check_serverhello_tlsext(s) <= 0) { | 
					
						
							|  |  |  |         SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT, SSL_R_SERVERHELLO_TLSEXT); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2012-04-24 20:22:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  | /*-
 | 
					
						
							|  |  |  |  * Since the server cache lookup is done early on in the processing of the | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |  * ClientHello and other operations depend on the result some extensions | 
					
						
							|  |  |  |  * need to be handled at the same time. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Two extensions are currently handled, session ticket and extended master | 
					
						
							|  |  |  |  * secret. | 
					
						
							| 
									
										
										
										
											2011-09-05 21:36:23 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |  *   session_id: ClientHello session ID. | 
					
						
							|  |  |  |  *   ext: ClientHello extensions (including length prefix) | 
					
						
							| 
									
										
										
										
											2011-09-05 21:36:23 +08:00
										 |  |  |  *   ret: (output) on return, if a ticket was decrypted, then this is set to | 
					
						
							|  |  |  |  *       point to the resulting session. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If s->tls_session_secret_cb is set then we are expecting a pre-shared key | 
					
						
							|  |  |  |  * ciphersuite, in which case we have no use for session tickets and one will | 
					
						
							|  |  |  |  * never be decrypted, nor will s->tlsext_ticket_expected be set to 1. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: | 
					
						
							|  |  |  |  *   -1: fatal error, either from parsing or decrypting the ticket. | 
					
						
							|  |  |  |  *    0: no ticket was found (or was ignored, based on settings). | 
					
						
							|  |  |  |  *    1: a zero length extension was found, indicating that the client supports | 
					
						
							|  |  |  |  *       session tickets but doesn't currently have one to offer. | 
					
						
							|  |  |  |  *    2: either s->tls_session_secret_cb was set, or a ticket was offered but | 
					
						
							|  |  |  |  *       couldn't be decrypted because of a non-fatal error. | 
					
						
							|  |  |  |  *    3: a ticket was successfully decrypted and *ret was set. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Side effects: | 
					
						
							|  |  |  |  *   Sets s->tlsext_ticket_expected to 1 if the server will have to issue | 
					
						
							|  |  |  |  *   a new session ticket to the client because the client indicated support | 
					
						
							|  |  |  |  *   (and s->tls_session_secret_cb is NULL) but the client either doesn't have | 
					
						
							|  |  |  |  *   a session ticket or we couldn't use the one it gave us, or if | 
					
						
							|  |  |  |  *   s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket. | 
					
						
							|  |  |  |  *   Otherwise, s->tlsext_ticket_expected is set to 0. | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  *   For extended master secret flag is set if the extension is present. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  | int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext, | 
					
						
							|  |  |  |                                        const PACKET *session_id, | 
					
						
							|  |  |  |                                        SSL_SESSION **ret) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     unsigned int i; | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |     PACKET local_ext = *ext; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     int retv = -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |     int have_ticket = 0; | 
					
						
							|  |  |  |     int use_ticket = tls_use_ticket(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     *ret = NULL; | 
					
						
							|  |  |  |     s->tlsext_ticket_expected = 0; | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |     s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If tickets disabled behave as if no ticket present to permit stateful | 
					
						
							|  |  |  |      * resumption. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |     if ((s->version <= SSL3_VERSION)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |     if (!PACKET_get_net_2(&local_ext, &i)) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |         retv = 0; | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |     while (PACKET_remaining(&local_ext) >= 4) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |         unsigned int type, size; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |         if (!PACKET_get_net_2(&local_ext, &type) | 
					
						
							|  |  |  |                 || !PACKET_get_net_2(&local_ext, &size)) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |             /* Shouldn't ever happen */ | 
					
						
							|  |  |  |             retv = -1; | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |         if (PACKET_remaining(&local_ext) < size) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |             retv = 0; | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |         if (type == TLSEXT_TYPE_session_ticket && use_ticket) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             int r; | 
					
						
							| 
									
										
										
										
											2016-02-01 22:26:18 +08:00
										 |  |  |             const unsigned char *etick; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |             /* Duplicate extension */ | 
					
						
							|  |  |  |             if (have_ticket != 0) { | 
					
						
							|  |  |  |                 retv = -1; | 
					
						
							|  |  |  |                 goto end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             have_ticket = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             if (size == 0) { | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                  * The client will accept a ticket but doesn't currently have | 
					
						
							|  |  |  |                  * one. | 
					
						
							|  |  |  |                  */ | 
					
						
							|  |  |  |                 s->tlsext_ticket_expected = 1; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 retv = 1; | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |             if (s->tls_session_secret_cb) { | 
					
						
							|  |  |  |                 /*
 | 
					
						
							|  |  |  |                  * Indicate that the ticket couldn't be decrypted rather than | 
					
						
							|  |  |  |                  * generating the session from ticket now, trigger | 
					
						
							|  |  |  |                  * abbreviated handshake based on external mechanism to | 
					
						
							|  |  |  |                  * calculate the master secret later. | 
					
						
							|  |  |  |                  */ | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 retv = 2; | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |             if (!PACKET_get_bytes(&local_ext, &etick, size)) { | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 /* Shouldn't ever happen */ | 
					
						
							|  |  |  |                 retv = -1; | 
					
						
							|  |  |  |                 goto end; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |             r = tls_decrypt_ticket(s, etick, size, PACKET_data(session_id), | 
					
						
							|  |  |  |                                    PACKET_remaining(session_id), ret); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             switch (r) { | 
					
						
							|  |  |  |             case 2:            /* ticket couldn't be decrypted */ | 
					
						
							|  |  |  |                 s->tlsext_ticket_expected = 1; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 retv = 2; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             case 3:            /* ticket was decrypted */ | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 retv = r; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             case 4:            /* ticket decrypted but need to renew */ | 
					
						
							|  |  |  |                 s->tlsext_ticket_expected = 1; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 retv = 3; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             default:           /* fatal error */ | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  |                 retv = -1; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2015-08-13 17:04:23 +08:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |             if (type == TLSEXT_TYPE_extended_master_secret) | 
					
						
							|  |  |  |                 s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; | 
					
						
							| 
									
										
										
										
											2015-09-30 21:33:12 +08:00
										 |  |  |             if (!PACKET_forward(&local_ext, size)) { | 
					
						
							| 
									
										
										
										
											2015-08-13 17:04:23 +08:00
										 |  |  |                 retv = -1; | 
					
						
							|  |  |  |                 goto end; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-05 03:48:15 +08:00
										 |  |  |     if (have_ticket == 0) | 
					
						
							|  |  |  |         retv = 0; | 
					
						
							| 
									
										
										
										
											2015-04-16 17:06:25 +08:00
										 |  |  | end: | 
					
						
							|  |  |  |     return retv; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-28 10:48:40 +08:00
										 |  |  | /*-
 | 
					
						
							|  |  |  |  * tls_decrypt_ticket attempts to decrypt a session ticket. | 
					
						
							| 
									
										
										
										
											2011-09-05 21:36:23 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  *   etick: points to the body of the session ticket extension. | 
					
						
							| 
									
										
										
										
											2016-03-11 04:34:48 +08:00
										 |  |  |  *   eticklen: the length of the session tickets extension. | 
					
						
							| 
									
										
										
										
											2011-09-05 21:36:23 +08:00
										 |  |  |  *   sess_id: points at the session ID. | 
					
						
							|  |  |  |  *   sesslen: the length of the session ID. | 
					
						
							|  |  |  |  *   psess: (output) on return, if a ticket was decrypted, then this is set to | 
					
						
							|  |  |  |  *       point to the resulting session. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns: | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |  *   -2: fatal error, malloc failure. | 
					
						
							| 
									
										
										
										
											2011-09-05 21:36:23 +08:00
										 |  |  |  *   -1: fatal error, either from parsing or decrypting the ticket. | 
					
						
							|  |  |  |  *    2: the ticket couldn't be decrypted. | 
					
						
							|  |  |  |  *    3: a ticket was successfully decrypted and *psess was set. | 
					
						
							|  |  |  |  *    4: same as 3, but the ticket needs to be renewed. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, | 
					
						
							|  |  |  |                               int eticklen, const unsigned char *sess_id, | 
					
						
							|  |  |  |                               int sesslen, SSL_SESSION **psess) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SSL_SESSION *sess; | 
					
						
							|  |  |  |     unsigned char *sdec; | 
					
						
							|  |  |  |     const unsigned char *p; | 
					
						
							| 
									
										
										
										
											2016-02-14 07:22:45 +08:00
										 |  |  |     int slen, mlen, renew_ticket = 0, ret = -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     unsigned char tick_hmac[EVP_MAX_MD_SIZE]; | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |     HMAC_CTX *hctx = NULL; | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |     EVP_CIPHER_CTX *ctx; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     SSL_CTX *tctx = s->initial_ctx; | 
					
						
							|  |  |  |     /* Need at least keyname + iv + some encrypted data */ | 
					
						
							|  |  |  |     if (eticklen < 48) | 
					
						
							|  |  |  |         return 2; | 
					
						
							|  |  |  |     /* Initialize session ticket encryption and HMAC contexts */ | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |     hctx = HMAC_CTX_new(); | 
					
						
							|  |  |  |     if (hctx == NULL) | 
					
						
							|  |  |  |         return -2; | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |     ctx = EVP_CIPHER_CTX_new(); | 
					
						
							| 
									
										
										
										
											2016-02-14 07:22:45 +08:00
										 |  |  |     if (ctx == NULL) { | 
					
						
							|  |  |  |         ret = -2; | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (tctx->tlsext_ticket_key_cb) { | 
					
						
							|  |  |  |         unsigned char *nctick = (unsigned char *)etick; | 
					
						
							|  |  |  |         int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |                                             ctx, hctx, 0); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (rv < 0) | 
					
						
							| 
									
										
										
										
											2016-02-14 07:22:45 +08:00
										 |  |  |             goto err; | 
					
						
							|  |  |  |         if (rv == 0) { | 
					
						
							|  |  |  |             ret = 2; | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (rv == 2) | 
					
						
							|  |  |  |             renew_ticket = 1; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* Check key name matches */ | 
					
						
							| 
									
										
										
										
											2016-02-28 02:36:00 +08:00
										 |  |  |         if (memcmp(etick, tctx->tlsext_tick_key_name, | 
					
						
							|  |  |  |                    sizeof(tctx->tlsext_tick_key_name)) != 0) { | 
					
						
							| 
									
										
										
										
											2016-02-14 07:22:45 +08:00
										 |  |  |             ret = 2; | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-02-28 02:36:00 +08:00
										 |  |  |         if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, | 
					
						
							|  |  |  |                          sizeof(tctx->tlsext_tick_hmac_key), | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  |                          EVP_sha256(), NULL) <= 0 | 
					
						
							| 
									
										
										
										
											2016-02-28 02:37:34 +08:00
										 |  |  |                 || EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  |                                       tctx->tlsext_tick_aes_key, | 
					
						
							| 
									
										
										
										
											2016-02-28 02:36:00 +08:00
										 |  |  |                                       etick + sizeof(tctx->tlsext_tick_key_name)) <= 0) { | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  |             goto err; | 
					
						
							|  |  |  |        } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Attempt to process session ticket, first conduct sanity and integrity | 
					
						
							|  |  |  |      * checks on ticket. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |     mlen = HMAC_size(hctx); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (mlen < 0) { | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  |         goto err; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     eticklen -= mlen; | 
					
						
							|  |  |  |     /* Check HMAC of encrypted ticket */ | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |     if (HMAC_Update(hctx, etick, eticklen) <= 0 | 
					
						
							|  |  |  |             || HMAC_Final(hctx, tick_hmac, NULL) <= 0) { | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |     HMAC_CTX_free(hctx); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) { | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |         EVP_CIPHER_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Attempt to decrypt session data */ | 
					
						
							|  |  |  |     /* Move p after IV to start of encrypted ticket, update length */ | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |     p = etick + 16 + EVP_CIPHER_CTX_iv_length(ctx); | 
					
						
							|  |  |  |     eticklen -= 16 + EVP_CIPHER_CTX_iv_length(ctx); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     sdec = OPENSSL_malloc(eticklen); | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  |     if (sdec == NULL | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |             || EVP_DecryptUpdate(ctx, sdec, &slen, p, eticklen) <= 0) { | 
					
						
							|  |  |  |         EVP_CIPHER_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2016-03-15 19:38:56 +08:00
										 |  |  |         OPENSSL_free(sdec); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |     if (EVP_DecryptFinal(ctx, sdec + slen, &mlen) <= 0) { | 
					
						
							|  |  |  |         EVP_CIPHER_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         OPENSSL_free(sdec); | 
					
						
							|  |  |  |         return 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     slen += mlen; | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |     EVP_CIPHER_CTX_free(ctx); | 
					
						
							|  |  |  |     ctx = NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     p = sdec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sess = d2i_SSL_SESSION(NULL, &p, slen); | 
					
						
							|  |  |  |     OPENSSL_free(sdec); | 
					
						
							|  |  |  |     if (sess) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * The session ID, if non-empty, is used by some clients to detect | 
					
						
							|  |  |  |          * that the ticket has been accepted. So we copy it to the session | 
					
						
							|  |  |  |          * structure. If it is empty set length to zero as required by | 
					
						
							|  |  |  |          * standard. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (sesslen) | 
					
						
							|  |  |  |             memcpy(sess->session_id, sess_id, sesslen); | 
					
						
							|  |  |  |         sess->session_id_length = sesslen; | 
					
						
							|  |  |  |         *psess = sess; | 
					
						
							|  |  |  |         if (renew_ticket) | 
					
						
							|  |  |  |             return 4; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return 3; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ERR_clear_error(); | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * For session parse failure, indicate that we need to send a new ticket. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     return 2; | 
					
						
							| 
									
										
										
										
											2015-11-07 00:31:21 +08:00
										 |  |  | err: | 
					
						
							| 
									
										
										
										
											2015-12-14 05:08:41 +08:00
										 |  |  |     EVP_CIPHER_CTX_free(ctx); | 
					
						
							| 
									
										
										
										
											2015-11-30 20:44:28 +08:00
										 |  |  |     HMAC_CTX_free(hctx); | 
					
						
							| 
									
										
										
										
											2016-02-14 07:22:45 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2007-08-12 07:18:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | /* Tables to translate from NIDs to TLS v1.2 ids */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     int nid; | 
					
						
							|  |  |  |     int id; | 
					
						
							|  |  |  | } tls12_lookup; | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 05:41:15 +08:00
										 |  |  | static const tls12_lookup tls12_md[] = { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     {NID_md5, TLSEXT_hash_md5}, | 
					
						
							|  |  |  |     {NID_sha1, TLSEXT_hash_sha1}, | 
					
						
							|  |  |  |     {NID_sha224, TLSEXT_hash_sha224}, | 
					
						
							|  |  |  |     {NID_sha256, TLSEXT_hash_sha256}, | 
					
						
							|  |  |  |     {NID_sha384, TLSEXT_hash_sha384}, | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |     {NID_sha512, TLSEXT_hash_sha512}, | 
					
						
							|  |  |  |     {NID_id_GostR3411_94, TLSEXT_hash_gostr3411}, | 
					
						
							|  |  |  |     {NID_id_GostR3411_2012_256, TLSEXT_hash_gostr34112012_256}, | 
					
						
							|  |  |  |     {NID_id_GostR3411_2012_512, TLSEXT_hash_gostr34112012_512}, | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 05:41:15 +08:00
										 |  |  | static const tls12_lookup tls12_sig[] = { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     {EVP_PKEY_RSA, TLSEXT_signature_rsa}, | 
					
						
							|  |  |  |     {EVP_PKEY_DSA, TLSEXT_signature_dsa}, | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |     {EVP_PKEY_EC, TLSEXT_signature_ecdsa}, | 
					
						
							|  |  |  |     {NID_id_GostR3410_2001, TLSEXT_signature_gostr34102001}, | 
					
						
							|  |  |  |     {NID_id_GostR3410_2012_256, TLSEXT_signature_gostr34102012_256}, | 
					
						
							|  |  |  |     {NID_id_GostR3410_2012_512, TLSEXT_signature_gostr34102012_512} | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 05:41:15 +08:00
										 |  |  | static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     for (i = 0; i < tlen; i++) { | 
					
						
							|  |  |  |         if (table[i].nid == nid) | 
					
						
							|  |  |  |             return table[i].id; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-06 22:28:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 05:41:15 +08:00
										 |  |  | static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     for (i = 0; i < tlen; i++) { | 
					
						
							|  |  |  |         if ((table[i].id) == id) | 
					
						
							|  |  |  |             return table[i].nid; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NID_undef; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, | 
					
						
							|  |  |  |                          const EVP_MD *md) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int sig_id, md_id; | 
					
						
							|  |  |  |     if (!md) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-05-03 01:30:00 +08:00
										 |  |  |     md_id = tls12_find_id(EVP_MD_type(md), tls12_md, OSSL_NELEM(tls12_md)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (md_id == -1) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     sig_id = tls12_get_sigid(pk); | 
					
						
							|  |  |  |     if (sig_id == -1) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     p[0] = (unsigned char)md_id; | 
					
						
							|  |  |  |     p[1] = (unsigned char)sig_id; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 23:44:01 +08:00
										 |  |  | int tls12_get_sigid(const EVP_PKEY *pk) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:21:12 +08:00
										 |  |  |     return tls12_find_id(EVP_PKEY_id(pk), tls12_sig, OSSL_NELEM(tls12_sig)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     int nid; | 
					
						
							|  |  |  |     int secbits; | 
					
						
							| 
									
										
										
										
											2015-11-30 00:54:27 +08:00
										 |  |  |     int md_idx; | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |     unsigned char tlsext_hash; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } tls12_hash_info; | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static const tls12_hash_info tls12_md_info[] = { | 
					
						
							| 
									
										
										
										
											2015-11-30 00:54:27 +08:00
										 |  |  |     {NID_md5, 64, SSL_MD_MD5_IDX, TLSEXT_hash_md5}, | 
					
						
							|  |  |  |     {NID_sha1, 80, SSL_MD_SHA1_IDX, TLSEXT_hash_sha1}, | 
					
						
							|  |  |  |     {NID_sha224, 112, SSL_MD_SHA224_IDX, TLSEXT_hash_sha224}, | 
					
						
							|  |  |  |     {NID_sha256, 128, SSL_MD_SHA256_IDX, TLSEXT_hash_sha256}, | 
					
						
							|  |  |  |     {NID_sha384, 192, SSL_MD_SHA384_IDX, TLSEXT_hash_sha384}, | 
					
						
							|  |  |  |     {NID_sha512, 256, SSL_MD_SHA512_IDX, TLSEXT_hash_sha512}, | 
					
						
							|  |  |  |     {NID_id_GostR3411_94,       128, SSL_MD_GOST94_IDX, TLSEXT_hash_gostr3411}, | 
					
						
							|  |  |  |     {NID_id_GostR3411_2012_256, 128, SSL_MD_GOST12_256_IDX, TLSEXT_hash_gostr34112012_256}, | 
					
						
							|  |  |  |     {NID_id_GostR3411_2012_512, 256, SSL_MD_GOST12_512_IDX, TLSEXT_hash_gostr34112012_512}, | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2011-05-09 23:44:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |     unsigned int i; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (hash_alg == 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i=0; i < OSSL_NELEM(tls12_md_info); i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (tls12_md_info[i].tlsext_hash == hash_alg) | 
					
						
							|  |  |  |             return tls12_md_info + i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-09 23:44:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | const EVP_MD *tls12_get_hash(unsigned char hash_alg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const tls12_hash_info *inf; | 
					
						
							|  |  |  |     if (hash_alg == TLSEXT_hash_md5 && FIPS_mode()) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     inf = tls12_get_hash_info(hash_alg); | 
					
						
							| 
									
										
										
										
											2015-11-30 00:54:27 +08:00
										 |  |  |     if (!inf) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-11-30 00:54:27 +08:00
										 |  |  |     return ssl_md(inf->md_idx); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-09 23:44:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | static int tls12_get_pkey_idx(unsigned char sig_alg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (sig_alg) { | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_RSA
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     case TLSEXT_signature_rsa: | 
					
						
							|  |  |  |         return SSL_PKEY_RSA_SIGN; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_DSA
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     case TLSEXT_signature_dsa: | 
					
						
							|  |  |  |         return SSL_PKEY_DSA_SIGN; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     case TLSEXT_signature_ecdsa: | 
					
						
							|  |  |  |         return SSL_PKEY_ECC; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  | # ifndef OPENSSL_NO_GOST
 | 
					
						
							|  |  |  |     case TLSEXT_signature_gostr34102001: | 
					
						
							|  |  |  |         return SSL_PKEY_GOST01; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case TLSEXT_signature_gostr34102012_256: | 
					
						
							|  |  |  |         return SSL_PKEY_GOST12_256; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case TLSEXT_signature_gostr34102012_512: | 
					
						
							|  |  |  |         return SSL_PKEY_GOST12_512; | 
					
						
							|  |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Convert TLS 1.2 signature algorithm extension values into NIDs */ | 
					
						
							|  |  |  | static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                                int *psignhash_nid, const unsigned char *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-11 18:44:07 +08:00
										 |  |  |     int sign_nid = NID_undef, hash_nid = NID_undef; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (!phash_nid && !psign_nid && !psignhash_nid) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (phash_nid || psignhash_nid) { | 
					
						
							| 
									
										
										
										
											2015-05-03 01:30:00 +08:00
										 |  |  |         hash_nid = tls12_find_nid(data[0], tls12_md, OSSL_NELEM(tls12_md)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (phash_nid) | 
					
						
							|  |  |  |             *phash_nid = hash_nid; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (psign_nid || psignhash_nid) { | 
					
						
							| 
									
										
										
										
											2015-05-03 01:30:00 +08:00
										 |  |  |         sign_nid = tls12_find_nid(data[1], tls12_sig, OSSL_NELEM(tls12_sig)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (psign_nid) | 
					
						
							|  |  |  |             *psign_nid = sign_nid; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (psignhash_nid) { | 
					
						
							| 
									
										
										
										
											2015-11-11 18:44:07 +08:00
										 |  |  |         if (sign_nid == NID_undef || hash_nid == NID_undef | 
					
						
							|  |  |  |                 || OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, | 
					
						
							|  |  |  |                                           sign_nid) <= 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             *psignhash_nid = NID_undef; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | /* Check to see if a signature algorithm is allowed */ | 
					
						
							|  |  |  | static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /* See if we have an entry in the hash table and it is enabled */ | 
					
						
							|  |  |  |     const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]); | 
					
						
							| 
									
										
										
										
											2015-11-30 00:54:27 +08:00
										 |  |  |     if (hinf == NULL || ssl_md(hinf->md_idx) == NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     /* See if public key algorithm allowed */ | 
					
						
							|  |  |  |     if (tls12_get_pkey_idx(ptmp[1]) == -1) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     /* Finally see if security callback allows it */ | 
					
						
							|  |  |  |     return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Get a mask of disabled public key algorithms based on supported signature | 
					
						
							|  |  |  |  * algorithms. For example if no signature algorithm supports RSA then RSA is | 
					
						
							|  |  |  |  * disabled. | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 00:14:17 +08:00
										 |  |  | void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const unsigned char *sigalgs; | 
					
						
							|  |  |  |     size_t i, sigalgslen; | 
					
						
							|  |  |  |     int have_rsa = 0, have_dsa = 0, have_ecdsa = 0; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Now go through all signature algorithms seeing if we support any for | 
					
						
							|  |  |  |      * RSA, DSA, ECDSA. Do this for all versions not just TLS 1.2. To keep | 
					
						
							|  |  |  |      * down calls to security callback only check if we have to. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     sigalgslen = tls12_get_psigalgs(s, &sigalgs); | 
					
						
							|  |  |  |     for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) { | 
					
						
							|  |  |  |         switch (sigalgs[1]) { | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_RSA
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         case TLSEXT_signature_rsa: | 
					
						
							|  |  |  |             if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs)) | 
					
						
							|  |  |  |                 have_rsa = 1; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_DSA
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         case TLSEXT_signature_dsa: | 
					
						
							|  |  |  |             if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs)) | 
					
						
							|  |  |  |                 have_dsa = 1; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         case TLSEXT_signature_ecdsa: | 
					
						
							|  |  |  |             if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs)) | 
					
						
							|  |  |  |                 have_ecdsa = 1; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!have_rsa) | 
					
						
							|  |  |  |         *pmask_a |= SSL_aRSA; | 
					
						
							|  |  |  |     if (!have_dsa) | 
					
						
							|  |  |  |         *pmask_a |= SSL_aDSS; | 
					
						
							|  |  |  |     if (!have_ecdsa) | 
					
						
							|  |  |  |         *pmask_a |= SSL_aECDSA; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | size_t tls12_copy_sigalgs(SSL *s, unsigned char *out, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                           const unsigned char *psig, size_t psiglen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned char *tmpout = out; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     for (i = 0; i < psiglen; i += 2, psig += 2) { | 
					
						
							|  |  |  |         if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig)) { | 
					
						
							|  |  |  |             *tmpout++ = psig[0]; | 
					
						
							|  |  |  |             *tmpout++ = psig[1]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return tmpout - out; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | /* Given preference and allowed sigalgs set shared sigalgs */ | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | static int tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                                 const unsigned char *pref, size_t preflen, | 
					
						
							|  |  |  |                                 const unsigned char *allow, size_t allowlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const unsigned char *ptmp, *atmp; | 
					
						
							|  |  |  |     size_t i, j, nmatch = 0; | 
					
						
							|  |  |  |     for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) { | 
					
						
							|  |  |  |         /* Skip disabled hashes or signature algorithms */ | 
					
						
							|  |  |  |         if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp)) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) { | 
					
						
							|  |  |  |             if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) { | 
					
						
							|  |  |  |                 nmatch++; | 
					
						
							|  |  |  |                 if (shsig) { | 
					
						
							|  |  |  |                     shsig->rhash = ptmp[0]; | 
					
						
							|  |  |  |                     shsig->rsign = ptmp[1]; | 
					
						
							|  |  |  |                     tls1_lookup_sigalg(&shsig->hash_nid, | 
					
						
							|  |  |  |                                        &shsig->sign_nid, | 
					
						
							|  |  |  |                                        &shsig->signandhash_nid, ptmp); | 
					
						
							|  |  |  |                     shsig++; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return nmatch; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Set shared signature algorithms for SSL structures */ | 
					
						
							|  |  |  | static int tls1_set_shared_sigalgs(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const unsigned char *pref, *allow, *conf; | 
					
						
							|  |  |  |     size_t preflen, allowlen, conflen; | 
					
						
							|  |  |  |     size_t nmatch; | 
					
						
							|  |  |  |     TLS_SIGALGS *salgs = NULL; | 
					
						
							|  |  |  |     CERT *c = s->cert; | 
					
						
							|  |  |  |     unsigned int is_suiteb = tls1_suiteb(s); | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     OPENSSL_free(c->shared_sigalgs); | 
					
						
							|  |  |  |     c->shared_sigalgs = NULL; | 
					
						
							|  |  |  |     c->shared_sigalgslen = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     /* If client use client signature algorithms if not NULL */ | 
					
						
							|  |  |  |     if (!s->server && c->client_sigalgs && !is_suiteb) { | 
					
						
							|  |  |  |         conf = c->client_sigalgs; | 
					
						
							|  |  |  |         conflen = c->client_sigalgslen; | 
					
						
							|  |  |  |     } else if (c->conf_sigalgs && !is_suiteb) { | 
					
						
							|  |  |  |         conf = c->conf_sigalgs; | 
					
						
							|  |  |  |         conflen = c->conf_sigalgslen; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         conflen = tls12_get_psigalgs(s, &conf); | 
					
						
							|  |  |  |     if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || is_suiteb) { | 
					
						
							|  |  |  |         pref = conf; | 
					
						
							|  |  |  |         preflen = conflen; | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |         allow = s->s3->tmp.peer_sigalgs; | 
					
						
							|  |  |  |         allowlen = s->s3->tmp.peer_sigalgslen; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         allow = conf; | 
					
						
							|  |  |  |         allowlen = conflen; | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |         pref = s->s3->tmp.peer_sigalgs; | 
					
						
							|  |  |  |         preflen = s->s3->tmp.peer_sigalgslen; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen); | 
					
						
							| 
									
										
										
										
											2015-03-03 21:20:57 +08:00
										 |  |  |     if (nmatch) { | 
					
						
							|  |  |  |         salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS)); | 
					
						
							| 
									
										
										
										
											2015-10-30 18:05:53 +08:00
										 |  |  |         if (salgs == NULL) | 
					
						
							| 
									
										
										
										
											2015-03-03 21:20:57 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |         nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         salgs = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     c->shared_sigalgs = salgs; | 
					
						
							|  |  |  |     c->shared_sigalgslen = nmatch; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | /* Set preferred digest for each key type */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-10 03:37:27 +08:00
										 |  |  | int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     CERT *c = s->cert; | 
					
						
							|  |  |  |     /* Extension ignored for inappropriate versions */ | 
					
						
							|  |  |  |     if (!SSL_USE_SIGALGS(s)) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     /* Should never happen */ | 
					
						
							|  |  |  |     if (!c) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |     OPENSSL_free(s->s3->tmp.peer_sigalgs); | 
					
						
							|  |  |  |     s->s3->tmp.peer_sigalgs = OPENSSL_malloc(dsize); | 
					
						
							|  |  |  |     if (s->s3->tmp.peer_sigalgs == NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |     s->s3->tmp.peer_sigalgslen = dsize; | 
					
						
							|  |  |  |     memcpy(s->s3->tmp.peer_sigalgs, data, dsize); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-10 03:37:27 +08:00
										 |  |  | int tls1_process_sigalgs(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int idx; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     const EVP_MD *md; | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |     const EVP_MD **pmd = s->s3->tmp.md; | 
					
						
							| 
									
										
										
										
											2015-07-15 06:19:11 +08:00
										 |  |  |     uint32_t *pvalid = s->s3->tmp.valid_flags; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     CERT *c = s->cert; | 
					
						
							|  |  |  |     TLS_SIGALGS *sigptr; | 
					
						
							|  |  |  |     if (!tls1_set_shared_sigalgs(s)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0, sigptr = c->shared_sigalgs; | 
					
						
							|  |  |  |          i < c->shared_sigalgslen; i++, sigptr++) { | 
					
						
							|  |  |  |         idx = tls12_get_pkey_idx(sigptr->rsign); | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |         if (idx > 0 && pmd[idx] == NULL) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             md = tls12_get_hash(sigptr->rhash); | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |             pmd[idx] = md; | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |             pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             if (idx == SSL_PKEY_RSA_SIGN) { | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |                 pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN; | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |                 pmd[SSL_PKEY_RSA_ENC] = md; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-05-06 21:00:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * In strict mode leave unset digests as NULL to indicate we can't use | 
					
						
							|  |  |  |      * the certificate for signing. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (!(s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Set any remaining keys to default values. NOTE: if alg is not | 
					
						
							|  |  |  |          * supported it stays as NULL. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #ifndef OPENSSL_NO_DSA
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |         if (pmd[SSL_PKEY_DSA_SIGN] == NULL) | 
					
						
							|  |  |  |             pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1(); | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_RSA
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |         if (pmd[SSL_PKEY_RSA_SIGN] == NULL) { | 
					
						
							|  |  |  |             pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1(); | 
					
						
							|  |  |  |             pmd[SSL_PKEY_RSA_ENC] = EVP_sha1(); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_EC
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |         if (pmd[SSL_PKEY_ECC] == NULL) | 
					
						
							|  |  |  |             pmd[SSL_PKEY_ECC] = EVP_sha1(); | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  | # ifndef OPENSSL_NO_GOST
 | 
					
						
							|  |  |  |         if (pmd[SSL_PKEY_GOST01] == NULL) | 
					
						
							|  |  |  |             pmd[SSL_PKEY_GOST01] = EVP_get_digestbynid(NID_id_GostR3411_94); | 
					
						
							|  |  |  |         if (pmd[SSL_PKEY_GOST12_256] == NULL) | 
					
						
							|  |  |  |             pmd[SSL_PKEY_GOST12_256] = EVP_get_digestbynid(NID_id_GostR3411_2012_256); | 
					
						
							|  |  |  |         if (pmd[SSL_PKEY_GOST12_512] == NULL) | 
					
						
							|  |  |  |             pmd[SSL_PKEY_GOST12_512] = EVP_get_digestbynid(NID_id_GostR3411_2012_512); | 
					
						
							|  |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-01-01 06:59:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-06 22:28:21 +08:00
										 |  |  | int SSL_get_sigalgs(SSL *s, int idx, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                     int *psign, int *phash, int *psignhash, | 
					
						
							|  |  |  |                     unsigned char *rsig, unsigned char *rhash) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |     const unsigned char *psig = s->s3->tmp.peer_sigalgs; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (psig == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (idx >= 0) { | 
					
						
							|  |  |  |         idx <<= 1; | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |         if (idx >= (int)s->s3->tmp.peer_sigalgslen) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |         psig += idx; | 
					
						
							|  |  |  |         if (rhash) | 
					
						
							|  |  |  |             *rhash = psig[0]; | 
					
						
							|  |  |  |         if (rsig) | 
					
						
							|  |  |  |             *rsig = psig[1]; | 
					
						
							|  |  |  |         tls1_lookup_sigalg(phash, psign, psignhash, psig); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |     return s->s3->tmp.peer_sigalgslen / 2; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int SSL_get_shared_sigalgs(SSL *s, int idx, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                            int *psign, int *phash, int *psignhash, | 
					
						
							|  |  |  |                            unsigned char *rsig, unsigned char *rhash) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs; | 
					
						
							|  |  |  |     if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     shsigalgs += idx; | 
					
						
							|  |  |  |     if (phash) | 
					
						
							|  |  |  |         *phash = shsigalgs->hash_nid; | 
					
						
							|  |  |  |     if (psign) | 
					
						
							|  |  |  |         *psign = shsigalgs->sign_nid; | 
					
						
							|  |  |  |     if (psignhash) | 
					
						
							|  |  |  |         *psignhash = shsigalgs->signandhash_nid; | 
					
						
							|  |  |  |     if (rsig) | 
					
						
							|  |  |  |         *rsig = shsigalgs->rsign; | 
					
						
							|  |  |  |     if (rhash) | 
					
						
							|  |  |  |         *rhash = shsigalgs->rhash; | 
					
						
							|  |  |  |     return s->cert->shared_sigalgslen; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #define MAX_SIGALGLEN   (TLSEXT_hash_num * TLSEXT_signature_num * 2)
 | 
					
						
							| 
									
										
										
										
											2012-06-22 22:03:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     size_t sigalgcnt; | 
					
						
							|  |  |  |     int sigalgs[MAX_SIGALGLEN]; | 
					
						
							|  |  |  | } sig_cb_st; | 
					
						
							| 
									
										
										
										
											2012-06-22 22:03:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-23 21:57:42 +08:00
										 |  |  | static void get_sigorhash(int *psig, int *phash, const char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (strcmp(str, "RSA") == 0) { | 
					
						
							|  |  |  |         *psig = EVP_PKEY_RSA; | 
					
						
							|  |  |  |     } else if (strcmp(str, "DSA") == 0) { | 
					
						
							|  |  |  |         *psig = EVP_PKEY_DSA; | 
					
						
							|  |  |  |     } else if (strcmp(str, "ECDSA") == 0) { | 
					
						
							|  |  |  |         *psig = EVP_PKEY_EC; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         *phash = OBJ_sn2nid(str); | 
					
						
							|  |  |  |         if (*phash == NID_undef) | 
					
						
							|  |  |  |             *phash = OBJ_ln2nid(str); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-22 22:03:31 +08:00
										 |  |  | static int sig_cb(const char *elem, int len, void *arg) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     sig_cb_st *sarg = arg; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     char etmp[20], *p; | 
					
						
							| 
									
										
										
										
											2015-07-23 21:57:42 +08:00
										 |  |  |     int sig_alg = NID_undef, hash_alg = NID_undef; | 
					
						
							| 
									
										
										
										
											2015-01-24 21:46:50 +08:00
										 |  |  |     if (elem == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (sarg->sigalgcnt == MAX_SIGALGLEN) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (len > (int)(sizeof(etmp) - 1)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     memcpy(etmp, elem, len); | 
					
						
							|  |  |  |     etmp[len] = 0; | 
					
						
							|  |  |  |     p = strchr(etmp, '+'); | 
					
						
							|  |  |  |     if (!p) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     *p = 0; | 
					
						
							|  |  |  |     p++; | 
					
						
							|  |  |  |     if (!*p) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-23 21:57:42 +08:00
										 |  |  |     get_sigorhash(&sig_alg, &hash_alg, etmp); | 
					
						
							|  |  |  |     get_sigorhash(&sig_alg, &hash_alg, p); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-23 21:57:42 +08:00
										 |  |  |     if (sig_alg == NID_undef || hash_alg == NID_undef) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < sarg->sigalgcnt; i += 2) { | 
					
						
							|  |  |  |         if (sarg->sigalgs[i] == sig_alg && sarg->sigalgs[i + 1] == hash_alg) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     sarg->sigalgs[sarg->sigalgcnt++] = hash_alg; | 
					
						
							|  |  |  |     sarg->sigalgs[sarg->sigalgcnt++] = sig_alg; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set suppored signature algorithms based on a colon separated list of the | 
					
						
							|  |  |  |  * form sig+hash e.g. RSA+SHA512:DSA+SHA512 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-07-03 20:51:14 +08:00
										 |  |  | int tls1_set_sigalgs_list(CERT *c, const char *str, int client) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     sig_cb_st sig; | 
					
						
							|  |  |  |     sig.sigalgcnt = 0; | 
					
						
							|  |  |  |     if (!CONF_parse_list(str, ':', 1, sig_cb, &sig)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (c == NULL) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, | 
					
						
							|  |  |  |                      int client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned char *sigalgs, *sptr; | 
					
						
							|  |  |  |     int rhash, rsign; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     if (salglen & 1) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     sigalgs = OPENSSL_malloc(salglen); | 
					
						
							|  |  |  |     if (sigalgs == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     for (i = 0, sptr = sigalgs; i < salglen; i += 2) { | 
					
						
							| 
									
										
										
										
											2015-05-03 01:30:00 +08:00
										 |  |  |         rhash = tls12_find_id(*psig_nids++, tls12_md, OSSL_NELEM(tls12_md)); | 
					
						
							|  |  |  |         rsign = tls12_find_id(*psig_nids++, tls12_sig, OSSL_NELEM(tls12_sig)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (rhash == -1 || rsign == -1) | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |         *sptr++ = rhash; | 
					
						
							|  |  |  |         *sptr++ = rsign; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (client) { | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |         OPENSSL_free(c->client_sigalgs); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         c->client_sigalgs = sigalgs; | 
					
						
							|  |  |  |         c->client_sigalgslen = salglen; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |         OPENSSL_free(c->conf_sigalgs); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         c->conf_sigalgs = sigalgs; | 
					
						
							|  |  |  |         c->conf_sigalgslen = salglen; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     OPENSSL_free(sigalgs); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-25 22:32:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  | static int tls1_check_sig_alg(CERT *c, X509 *x, int default_nid) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int sig_nid; | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     if (default_nid == -1) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     sig_nid = X509_get_signature_nid(x); | 
					
						
							|  |  |  |     if (default_nid) | 
					
						
							|  |  |  |         return sig_nid == default_nid ? 1 : 0; | 
					
						
							|  |  |  |     for (i = 0; i < c->shared_sigalgslen; i++) | 
					
						
							|  |  |  |         if (sig_nid == c->shared_sigalgs[i].signandhash_nid) | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-27 21:39:23 +08:00
										 |  |  | /* Check to see if a certificate issuer name matches list of CA names */ | 
					
						
							|  |  |  | static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     X509_NAME *nm; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     nm = X509_get_issuer_name(x); | 
					
						
							|  |  |  |     for (i = 0; i < sk_X509_NAME_num(names); i++) { | 
					
						
							|  |  |  |         if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i))) | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Check certificate chain is consistent with TLS extensions and is usable by | 
					
						
							|  |  |  |  * server. This servers two purposes: it allows users to check chains before | 
					
						
							|  |  |  |  * passing them to the server and it allows the server to check chains before | 
					
						
							|  |  |  |  * attempting to use them. | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-07-27 21:39:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Flags which need to be set for a certificate when stict mode not set */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #define CERT_PKEY_VALID_FLAGS \
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         (CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM) | 
					
						
							| 
									
										
										
										
											2012-07-27 21:39:23 +08:00
										 |  |  | /* Strict mode flags */ | 
					
						
							| 
									
										
										
										
											2015-05-15 17:49:56 +08:00
										 |  |  | #define CERT_PKEY_STRICT_FLAGS \
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |          (CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \ | 
					
						
							|  |  |  |          | CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE) | 
					
						
							| 
									
										
										
										
											2012-07-27 21:39:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  | int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |                      int idx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     int rv = 0; | 
					
						
							|  |  |  |     int check_flags = 0, strict_mode; | 
					
						
							|  |  |  |     CERT_PKEY *cpk = NULL; | 
					
						
							|  |  |  |     CERT *c = s->cert; | 
					
						
							| 
									
										
										
										
											2015-07-15 06:19:11 +08:00
										 |  |  |     uint32_t *pvalid; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     unsigned int suiteb_flags = tls1_suiteb(s); | 
					
						
							|  |  |  |     /* idx == -1 means checking server chains */ | 
					
						
							|  |  |  |     if (idx != -1) { | 
					
						
							|  |  |  |         /* idx == -2 means checking client certificate chains */ | 
					
						
							|  |  |  |         if (idx == -2) { | 
					
						
							|  |  |  |             cpk = c->key; | 
					
						
							|  |  |  |             idx = cpk - c->pkeys; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             cpk = c->pkeys + idx; | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |         pvalid = s->s3->tmp.valid_flags + idx; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         x = cpk->x509; | 
					
						
							|  |  |  |         pk = cpk->privatekey; | 
					
						
							|  |  |  |         chain = cpk->chain; | 
					
						
							|  |  |  |         strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT; | 
					
						
							|  |  |  |         /* If no cert or key, forget it */ | 
					
						
							|  |  |  |         if (!x || !pk) | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if (!x || !pk) | 
					
						
							| 
									
										
										
										
											2015-03-12 01:01:38 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         idx = ssl_cert_type(x, pk); | 
					
						
							|  |  |  |         if (idx == -1) | 
					
						
							| 
									
										
										
										
											2015-03-12 01:01:38 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |         pvalid = s->s3->tmp.valid_flags + idx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT) | 
					
						
							|  |  |  |             check_flags = CERT_PKEY_STRICT_FLAGS; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             check_flags = CERT_PKEY_VALID_FLAGS; | 
					
						
							|  |  |  |         strict_mode = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (suiteb_flags) { | 
					
						
							|  |  |  |         int ok; | 
					
						
							|  |  |  |         if (check_flags) | 
					
						
							|  |  |  |             check_flags |= CERT_PKEY_SUITEB; | 
					
						
							|  |  |  |         ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags); | 
					
						
							|  |  |  |         if (ok == X509_V_OK) | 
					
						
							|  |  |  |             rv |= CERT_PKEY_SUITEB; | 
					
						
							|  |  |  |         else if (!check_flags) | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Check all signature algorithms are consistent with signature | 
					
						
							|  |  |  |      * algorithms extension if TLS 1.2 or later and strict mode. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) { | 
					
						
							|  |  |  |         int default_nid; | 
					
						
							|  |  |  |         unsigned char rsign = 0; | 
					
						
							| 
									
										
										
										
											2015-05-13 00:17:37 +08:00
										 |  |  |         if (s->s3->tmp.peer_sigalgs) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             default_nid = 0; | 
					
						
							|  |  |  |         /* If no sigalgs extension use defaults from RFC5246 */ | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             switch (idx) { | 
					
						
							|  |  |  |             case SSL_PKEY_RSA_ENC: | 
					
						
							|  |  |  |             case SSL_PKEY_RSA_SIGN: | 
					
						
							|  |  |  |                 rsign = TLSEXT_signature_rsa; | 
					
						
							|  |  |  |                 default_nid = NID_sha1WithRSAEncryption; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case SSL_PKEY_DSA_SIGN: | 
					
						
							|  |  |  |                 rsign = TLSEXT_signature_dsa; | 
					
						
							|  |  |  |                 default_nid = NID_dsaWithSHA1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case SSL_PKEY_ECC: | 
					
						
							|  |  |  |                 rsign = TLSEXT_signature_ecdsa; | 
					
						
							|  |  |  |                 default_nid = NID_ecdsa_with_SHA1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |             case SSL_PKEY_GOST01: | 
					
						
							|  |  |  |                 rsign = TLSEXT_signature_gostr34102001; | 
					
						
							|  |  |  |                 default_nid = NID_id_GostR3411_94_with_GostR3410_2001; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case SSL_PKEY_GOST12_256: | 
					
						
							|  |  |  |                 rsign = TLSEXT_signature_gostr34102012_256; | 
					
						
							|  |  |  |                 default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case SSL_PKEY_GOST12_512: | 
					
						
							|  |  |  |                 rsign = TLSEXT_signature_gostr34102012_512; | 
					
						
							|  |  |  |                 default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             default: | 
					
						
							|  |  |  |                 default_nid = -1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * If peer sent no signature algorithms extension and we have set | 
					
						
							|  |  |  |          * preferred signature algorithms check we support sha1. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (default_nid > 0 && c->conf_sigalgs) { | 
					
						
							|  |  |  |             size_t j; | 
					
						
							|  |  |  |             const unsigned char *p = c->conf_sigalgs; | 
					
						
							|  |  |  |             for (j = 0; j < c->conf_sigalgslen; j += 2, p += 2) { | 
					
						
							|  |  |  |                 if (p[0] == TLSEXT_hash_sha1 && p[1] == rsign) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (j == c->conf_sigalgslen) { | 
					
						
							|  |  |  |                 if (check_flags) | 
					
						
							|  |  |  |                     goto skip_sigs; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     goto end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* Check signature algorithm of each cert in chain */ | 
					
						
							|  |  |  |         if (!tls1_check_sig_alg(c, x, default_nid)) { | 
					
						
							|  |  |  |             if (!check_flags) | 
					
						
							|  |  |  |                 goto end; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             rv |= CERT_PKEY_EE_SIGNATURE; | 
					
						
							|  |  |  |         rv |= CERT_PKEY_CA_SIGNATURE; | 
					
						
							|  |  |  |         for (i = 0; i < sk_X509_num(chain); i++) { | 
					
						
							|  |  |  |             if (!tls1_check_sig_alg(c, sk_X509_value(chain, i), default_nid)) { | 
					
						
							|  |  |  |                 if (check_flags) { | 
					
						
							|  |  |  |                     rv &= ~CERT_PKEY_CA_SIGNATURE; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } else | 
					
						
							|  |  |  |                     goto end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Else not TLS 1.2, so mark EE and CA signing algorithms OK */ | 
					
						
							|  |  |  |     else if (check_flags) | 
					
						
							|  |  |  |         rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE; | 
					
						
							|  |  |  |  skip_sigs: | 
					
						
							|  |  |  |     /* Check cert parameters are consistent */ | 
					
						
							|  |  |  |     if (tls1_check_cert_param(s, x, check_flags ? 1 : 2)) | 
					
						
							|  |  |  |         rv |= CERT_PKEY_EE_PARAM; | 
					
						
							|  |  |  |     else if (!check_flags) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     if (!s->server) | 
					
						
							|  |  |  |         rv |= CERT_PKEY_CA_PARAM; | 
					
						
							|  |  |  |     /* In strict mode check rest of chain too */ | 
					
						
							|  |  |  |     else if (strict_mode) { | 
					
						
							|  |  |  |         rv |= CERT_PKEY_CA_PARAM; | 
					
						
							|  |  |  |         for (i = 0; i < sk_X509_num(chain); i++) { | 
					
						
							|  |  |  |             X509 *ca = sk_X509_value(chain, i); | 
					
						
							|  |  |  |             if (!tls1_check_cert_param(s, ca, 0)) { | 
					
						
							|  |  |  |                 if (check_flags) { | 
					
						
							|  |  |  |                     rv &= ~CERT_PKEY_CA_PARAM; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } else | 
					
						
							|  |  |  |                     goto end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!s->server && strict_mode) { | 
					
						
							|  |  |  |         STACK_OF(X509_NAME) *ca_dn; | 
					
						
							|  |  |  |         int check_type = 0; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:21:12 +08:00
										 |  |  |         switch (EVP_PKEY_id(pk)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         case EVP_PKEY_RSA: | 
					
						
							|  |  |  |             check_type = TLS_CT_RSA_SIGN; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case EVP_PKEY_DSA: | 
					
						
							|  |  |  |             check_type = TLS_CT_DSS_SIGN; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case EVP_PKEY_EC: | 
					
						
							|  |  |  |             check_type = TLS_CT_ECDSA_SIGN; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (check_type) { | 
					
						
							|  |  |  |             const unsigned char *ctypes; | 
					
						
							|  |  |  |             int ctypelen; | 
					
						
							|  |  |  |             if (c->ctypes) { | 
					
						
							|  |  |  |                 ctypes = c->ctypes; | 
					
						
							|  |  |  |                 ctypelen = (int)c->ctype_num; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 ctypes = (unsigned char *)s->s3->tmp.ctype; | 
					
						
							|  |  |  |                 ctypelen = s->s3->tmp.ctype_num; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             for (i = 0; i < ctypelen; i++) { | 
					
						
							|  |  |  |                 if (ctypes[i] == check_type) { | 
					
						
							|  |  |  |                     rv |= CERT_PKEY_CERT_TYPE; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags) | 
					
						
							|  |  |  |                 goto end; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             rv |= CERT_PKEY_CERT_TYPE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ca_dn = s->s3->tmp.ca_names; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!sk_X509_NAME_num(ca_dn)) | 
					
						
							|  |  |  |             rv |= CERT_PKEY_ISSUER_NAME; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!(rv & CERT_PKEY_ISSUER_NAME)) { | 
					
						
							|  |  |  |             if (ssl_check_ca_name(ca_dn, x)) | 
					
						
							|  |  |  |                 rv |= CERT_PKEY_ISSUER_NAME; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!(rv & CERT_PKEY_ISSUER_NAME)) { | 
					
						
							|  |  |  |             for (i = 0; i < sk_X509_num(chain); i++) { | 
					
						
							|  |  |  |                 X509 *xtmp = sk_X509_value(chain, i); | 
					
						
							|  |  |  |                 if (ssl_check_ca_name(ca_dn, xtmp)) { | 
					
						
							|  |  |  |                     rv |= CERT_PKEY_ISSUER_NAME; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME)) | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!check_flags || (rv & check_flags) == check_flags) | 
					
						
							|  |  |  |         rv |= CERT_PKEY_VALID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  end: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (TLS1_get_version(s) >= TLS1_2_VERSION) { | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |         if (*pvalid & CERT_PKEY_EXPLICIT_SIGN) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             rv |= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN; | 
					
						
							| 
									
										
										
										
											2015-05-13 01:56:39 +08:00
										 |  |  |         else if (s->s3->tmp.md[idx] != NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             rv |= CERT_PKEY_SIGN; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * When checking a CERT_PKEY structure all flags are irrelevant if the | 
					
						
							|  |  |  |      * chain is invalid. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (!check_flags) { | 
					
						
							|  |  |  |         if (rv & CERT_PKEY_VALID) | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |             *pvalid = rv; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else { | 
					
						
							|  |  |  |             /* Preserve explicit sign flag, clear rest */ | 
					
						
							| 
									
										
										
										
											2015-05-13 05:17:34 +08:00
										 |  |  |             *pvalid &= CERT_PKEY_EXPLICIT_SIGN; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rv; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Set validity of certificates in an SSL structure */ | 
					
						
							|  |  |  | void tls1_set_cert_validity(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-03-24 23:10:15 +08:00
										 |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC); | 
					
						
							|  |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN); | 
					
						
							|  |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN); | 
					
						
							|  |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC); | 
					
						
							| 
									
										
										
										
											2015-11-17 23:32:30 +08:00
										 |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01); | 
					
						
							|  |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256); | 
					
						
							|  |  |  |     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-29 22:24:42 +08:00
										 |  |  | /* User level utiity function to check a chain is suitable */ | 
					
						
							|  |  |  | int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return tls1_check_chain(s, x, pk, chain, -1); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-06-28 20:45:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-23 00:22:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_DH
 | 
					
						
							|  |  |  | DH *ssl_get_auto_dh(SSL *s) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int dh_secbits = 80; | 
					
						
							|  |  |  |     if (s->cert->dh_tmp_auto == 2) | 
					
						
							|  |  |  |         return DH_get_1024_160(); | 
					
						
							| 
									
										
										
										
											2015-06-29 00:01:52 +08:00
										 |  |  |     if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (s->s3->tmp.new_cipher->strength_bits == 256) | 
					
						
							|  |  |  |             dh_secbits = 128; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             dh_secbits = 80; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         CERT_PKEY *cpk = ssl_get_server_send_pkey(s); | 
					
						
							|  |  |  |         dh_secbits = EVP_PKEY_security_bits(cpk->privatekey); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (dh_secbits >= 128) { | 
					
						
							|  |  |  |         DH *dhp = DH_new(); | 
					
						
							| 
									
										
										
										
											2016-04-07 00:49:48 +08:00
										 |  |  |         BIGNUM *p, *g; | 
					
						
							| 
									
										
										
										
											2015-10-30 18:05:53 +08:00
										 |  |  |         if (dhp == NULL) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2016-04-07 00:49:48 +08:00
										 |  |  |         g = BN_new(); | 
					
						
							|  |  |  |         if (g != NULL) | 
					
						
							|  |  |  |             BN_set_word(g, 2); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         if (dh_secbits >= 192) | 
					
						
							| 
									
										
										
										
											2016-04-18 19:43:54 +08:00
										 |  |  |             p = BN_get_rfc3526_prime_8192(NULL); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2016-04-18 19:43:54 +08:00
										 |  |  |             p = BN_get_rfc3526_prime_3072(NULL); | 
					
						
							| 
									
										
										
										
											2016-04-07 00:49:48 +08:00
										 |  |  |         if (p == NULL || g == NULL || !DH_set0_pqg(dhp, p, NULL, g)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             DH_free(dhp); | 
					
						
							| 
									
										
										
										
											2016-04-07 00:49:48 +08:00
										 |  |  |             BN_free(p); | 
					
						
							|  |  |  |             BN_free(g); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return dhp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (dh_secbits >= 112) | 
					
						
							|  |  |  |         return DH_get_2048_224(); | 
					
						
							|  |  |  |     return DH_get_1024_160(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-01-23 00:22:48 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-30 21:34:53 +08:00
										 |  |  |     int secbits = -1; | 
					
						
							| 
									
										
										
										
											2015-12-20 08:32:36 +08:00
										 |  |  |     EVP_PKEY *pkey = X509_get0_pubkey(x); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (pkey) { | 
					
						
							| 
									
										
										
										
											2015-12-30 21:34:53 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * If no parameters this will return -1 and fail using the default | 
					
						
							|  |  |  |          * security callback for any non-zero security level. This will | 
					
						
							|  |  |  |          * reject keys which omit parameters but this only affects DSA and | 
					
						
							|  |  |  |          * omission of parameters is never (?) done in practice. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         secbits = EVP_PKEY_security_bits(pkey); | 
					
						
							| 
									
										
										
										
											2015-12-30 21:34:53 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (s) | 
					
						
							|  |  |  |         return ssl_security(s, op, secbits, 0, x); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return ssl_ctx_security(ctx, op, secbits, 0, x); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /* Lookup signature algorithm digest */ | 
					
						
							|  |  |  |     int secbits = -1, md_nid = NID_undef, sig_nid; | 
					
						
							| 
									
										
										
										
											2016-02-11 23:25:11 +08:00
										 |  |  |     /* Don't check signature if self signed */ | 
					
						
							|  |  |  |     if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) | 
					
						
							|  |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     sig_nid = X509_get_signature_nid(x); | 
					
						
							|  |  |  |     if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL)) { | 
					
						
							|  |  |  |         const EVP_MD *md; | 
					
						
							|  |  |  |         if (md_nid && (md = EVP_get_digestbynid(md_nid))) | 
					
						
							|  |  |  |             secbits = EVP_MD_size(md) * 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (s) | 
					
						
							|  |  |  |         return ssl_security(s, op, secbits, md_nid, x); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return ssl_ctx_security(ctx, op, secbits, md_nid, x); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (vfy) | 
					
						
							|  |  |  |         vfy = SSL_SECOP_PEER; | 
					
						
							|  |  |  |     if (is_ee) { | 
					
						
							|  |  |  |         if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy)) | 
					
						
							|  |  |  |             return SSL_R_EE_KEY_TOO_SMALL; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy)) | 
					
						
							|  |  |  |             return SSL_R_CA_KEY_TOO_SMALL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy)) | 
					
						
							|  |  |  |         return SSL_R_CA_MD_TOO_WEAK; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Check security of a chain, if sk includes the end entity certificate then | 
					
						
							|  |  |  |  * x is NULL. If vfy is 1 then we are verifying a peer chain and not sending | 
					
						
							|  |  |  |  * one to the peer. Return values: 1 if ok otherwise error code to use | 
					
						
							| 
									
										
										
										
											2013-12-15 21:32:24 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int rv, start_idx, i; | 
					
						
							|  |  |  |     if (x == NULL) { | 
					
						
							|  |  |  |         x = sk_X509_value(sk, 0); | 
					
						
							|  |  |  |         start_idx = 1; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         start_idx = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rv = ssl_security_cert(s, NULL, x, vfy, 1); | 
					
						
							|  |  |  |     if (rv != 1) | 
					
						
							|  |  |  |         return rv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = start_idx; i < sk_X509_num(sk); i++) { | 
					
						
							|  |  |  |         x = sk_X509_value(sk, i); | 
					
						
							|  |  |  |         rv = ssl_security_cert(s, NULL, x, vfy, 0); | 
					
						
							|  |  |  |         if (rv != 1) | 
					
						
							|  |  |  |             return rv; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } |