Skip to content

Commit 8e583e2

Browse files
codarrenvelvindronbukka
codarrenvelvindron
authored andcommitted
Added tls 1.3 support for PHP
1 parent f8850cc commit 8e583e2

File tree

6 files changed

+147
-5
lines changed

6 files changed

+147
-5
lines changed

ext/openssl/openssl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,9 @@ PHP_MINIT_FUNCTION(openssl)
15531553
php_stream_xport_register("tlsv1.0", php_openssl_ssl_socket_factory);
15541554
php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory);
15551555
php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory);
1556+
#if OPENSSL_VERSION_NUMBER >= 0x10101000
1557+
php_stream_xport_register("tlsv1.3", php_openssl_ssl_socket_factory);
1558+
#endif
15561559

15571560
/* override the default tcp socket provider */
15581561
php_stream_xport_register("tcp", php_openssl_ssl_socket_factory);
@@ -1626,6 +1629,9 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
16261629
php_stream_xport_unregister("tlsv1.0");
16271630
php_stream_xport_unregister("tlsv1.1");
16281631
php_stream_xport_unregister("tlsv1.2");
1632+
#if OPENSSL_VERSION_NUMBER >= 0x10101000
1633+
php_stream_xport_unregister("tlsv1.3");
1634+
#endif
16291635

16301636
/* reinstate the default tcp handler */
16311637
php_stream_xport_register("tcp", php_stream_generic_socket_factory);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
Capture SSL session meta array in stream context for TLSv1.3
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("openssl")) die("skip openssl not loaded");
6+
if (!function_exists("proc_open")) die("skip no proc_open");
7+
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
8+
?>
9+
--FILE--
10+
<?php
11+
$serverCode = <<<'CODE'
12+
$serverUri = "ssl://127.0.0.1:64321";
13+
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
14+
$serverCtx = stream_context_create(['ssl' => [
15+
'local_cert' => __DIR__ . '/bug54992.pem',
16+
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_SERVER,
17+
]]);
18+
19+
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
20+
phpt_notify();
21+
22+
@stream_socket_accept($server, 1);
23+
@stream_socket_accept($server, 1);
24+
@stream_socket_accept($server, 1);
25+
@stream_socket_accept($server, 1);
26+
CODE;
27+
28+
$clientCode = <<<'CODE'
29+
$serverUri = "ssl://127.0.0.1:64321";
30+
$clientFlags = STREAM_CLIENT_CONNECT;
31+
$clientCtx = stream_context_create(['ssl' => [
32+
'verify_peer' => true,
33+
'cafile' => __DIR__ . '/bug54992-ca.pem',
34+
'peer_name' => 'bug54992.local',
35+
'capture_session_meta' => true,
36+
]]);
37+
38+
phpt_wait();
39+
40+
stream_context_set_option($clientCtx, 'ssl', 'crypto_method', STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT);
41+
@stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx);
42+
$meta = stream_context_get_options($clientCtx)['ssl']['session_meta'];
43+
var_dump($meta['protocol']);
44+
CODE;
45+
46+
include 'ServerClientTestCase.inc';
47+
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
48+
?>
49+
--EXPECT--
50+
string(7) "TLSv1.3"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
tlsv1.3 stream wrapper
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("openssl")) die("skip openssl not loaded");
6+
if (!function_exists("proc_open")) die("skip no proc_open");
7+
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
8+
?>
9+
--FILE--
10+
<?php
11+
$serverCode = <<<'CODE'
12+
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
13+
$ctx = stream_context_create(['ssl' => [
14+
'local_cert' => __DIR__ . '/streams_crypto_method.pem',
15+
]]);
16+
17+
$server = stream_socket_server('tlsv1.3://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
18+
phpt_notify();
19+
20+
for ($i=0; $i < 3; $i++) {
21+
@stream_socket_accept($server, 3);
22+
}
23+
CODE;
24+
25+
$clientCode = <<<'CODE'
26+
$flags = STREAM_CLIENT_CONNECT;
27+
$ctx = stream_context_create(['ssl' => [
28+
'verify_peer' => false,
29+
'verify_peer_name' => false,
30+
]]);
31+
32+
phpt_wait();
33+
34+
$client = stream_socket_client("tlsv1.3://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
35+
var_dump($client);
36+
37+
$client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
38+
var_dump($client);
39+
40+
$client = @stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
41+
var_dump($client);
42+
CODE;
43+
44+
include 'ServerClientTestCase.inc';
45+
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
46+
?>
47+
--EXPECTF--
48+
resource(%d) of type (stream)
49+
bool(false)
50+
bool(false)

ext/openssl/xp_ssl.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,22 @@
5858
#define STREAM_CRYPTO_METHOD_TLSv1_0 (1<<3)
5959
#define STREAM_CRYPTO_METHOD_TLSv1_1 (1<<4)
6060
#define STREAM_CRYPTO_METHOD_TLSv1_2 (1<<5)
61+
#define STREAM_CRYPTO_METHOD_TLSv1_3 (1<<6)
6162

6263
#ifndef OPENSSL_NO_SSL3
6364
#define HAVE_SSL3 1
6465
#define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_SSLv3
6566
#else
6667
#define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_0
6768
#endif
68-
#define PHP_OPENSSL_MAX_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_2
69+
#define PHP_OPENSSL_MAX_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_3
6970

7071

7172
#define HAVE_TLS11 1
7273
#define HAVE_TLS12 1
74+
#if OPENSSL_VERSION_NUMBER >= 0x10101000
75+
#define HAVE_TLS13 1
76+
#endif
7377

7478
#ifndef OPENSSL_NO_ECDH
7579
#define HAVE_ECDH 1
@@ -992,6 +996,11 @@ static int php_openssl_get_crypto_method_ctx_flags(int method_flags) /* {{{ */
992996
ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
993997
}
994998
#endif
999+
#ifdef HAVE_TLS13
1000+
if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_3)) {
1001+
ssl_ctx_options |= SSL_OP_NO_TLSv1_3;
1002+
}
1003+
#endif
9951004

9961005
return ssl_ctx_options;
9971006
}
@@ -1006,7 +1015,7 @@ static inline int php_openssl_get_min_proto_version_flag(int flags) /* {{{ */
10061015
return ver;
10071016
}
10081017
}
1009-
return STREAM_CRYPTO_METHOD_TLSv1_2;
1018+
return STREAM_CRYPTO_METHOD_TLSv1_3;
10101019
}
10111020
/* }}} */
10121021

@@ -1018,7 +1027,7 @@ static inline int php_openssl_get_max_proto_version_flag(int flags) /* {{{ */
10181027
return ver;
10191028
}
10201029
}
1021-
return STREAM_CRYPTO_METHOD_TLSv1_2;
1030+
return STREAM_CRYPTO_METHOD_TLSv1_3;
10221031
}
10231032
/* }}} */
10241033

@@ -1034,9 +1043,13 @@ static inline int php_openssl_map_proto_version(int flag) /* {{{ */
10341043
return TLS1_VERSION;
10351044
case STREAM_CRYPTO_METHOD_TLSv1_1:
10361045
return TLS1_1_VERSION;
1037-
/* case STREAM_CRYPTO_METHOD_TLSv1_2: */
1046+
case STREAM_CRYPTO_METHOD_TLSv1_2:
1047+
return TLS1_2_VERSION;
1048+
/* case STREAM_CRYPTO_METHOD_TLSv1_3: */
1049+
#ifdef HAVE_TLS13
10381050
default:
1039-
return TLS1_2_VERSION;
1051+
return TLS1_3_VERSION;
1052+
#endif
10401053

10411054
}
10421055
}
@@ -1782,6 +1795,11 @@ static zend_array *php_openssl_capture_session_meta(SSL *ssl_handle) /* {{{ */
17821795
char version_str[PHP_SSL_MAX_VERSION_LEN];
17831796

17841797
switch (proto) {
1798+
#ifdef HAVE_TLS13
1799+
case TLS1_3_VERSION:
1800+
proto_str = "TLSv1.3";
1801+
break;
1802+
#endif
17851803
#ifdef HAVE_TLS12
17861804
case TLS1_2_VERSION:
17871805
proto_str = "TLSv1.2";
@@ -2386,6 +2404,9 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
23862404
array_init(&tmp);
23872405

23882406
switch (SSL_version(sslsock->ssl_handle)) {
2407+
#ifdef HAVE_TLS13
2408+
case TLS1_3_VERSION: proto_str = "TLSv1.3"; break;
2409+
#endif
23892410
#ifdef HAVE_TLS12
23902411
case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
23912412
#endif
@@ -2725,6 +2746,16 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen,
27252746
"TLSv1.2 support is not compiled into the OpenSSL library against which PHP is linked");
27262747
php_stream_close(stream);
27272748
return NULL;
2749+
#endif
2750+
} else if (strncmp(proto, "tlsv1.3", protolen) == 0) {
2751+
#ifdef HAVE_TLS13
2752+
sslsock->enable_on_connect = 1;
2753+
sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT;
2754+
#else
2755+
php_error_docref(NULL, E_WARNING,
2756+
"TLSv1.3 support is not compiled into the OpenSSL library against which PHP is linked");
2757+
php_stream_close(stream);
2758+
return NULL;
27282759
#endif
27292760
}
27302761

ext/standard/file.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ PHP_MINIT_FUNCTION(file)
217217
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT, CONST_CS|CONST_PERSISTENT);
218218
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT, CONST_CS|CONST_PERSISTENT);
219219
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, CONST_CS|CONST_PERSISTENT);
220+
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT, CONST_CS|CONST_PERSISTENT);
220221
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_ANY_SERVER", STREAM_CRYPTO_METHOD_ANY_SERVER, CONST_CS|CONST_PERSISTENT);
221222
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER", STREAM_CRYPTO_METHOD_SSLv2_SERVER, CONST_CS|CONST_PERSISTENT);
222223
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT);
@@ -225,11 +226,13 @@ PHP_MINIT_FUNCTION(file)
225226
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_SERVER", STREAM_CRYPTO_METHOD_TLSv1_0_SERVER, CONST_CS|CONST_PERSISTENT);
226227
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT);
227228
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT);
229+
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_3_SERVER", STREAM_CRYPTO_METHOD_TLSv1_3_SERVER, CONST_CS|CONST_PERSISTENT);
228230

229231
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_SSLv3", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT);
230232
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_0", STREAM_CRYPTO_METHOD_TLSv1_0_SERVER, CONST_CS|CONST_PERSISTENT);
231233
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_1", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT);
232234
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_2", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT);
235+
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_3", STREAM_CRYPTO_METHOD_TLSv1_3_SERVER, CONST_CS|CONST_PERSISTENT);
233236

234237
REGISTER_LONG_CONSTANT("STREAM_SHUT_RD", STREAM_SHUT_RD, CONST_CS|CONST_PERSISTENT);
235238
REGISTER_LONG_CONSTANT("STREAM_SHUT_WR", STREAM_SHUT_WR, CONST_CS|CONST_PERSISTENT);

main/streams/php_stream_transport.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ typedef enum {
171171
STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT = (1 << 3 | 1),
172172
STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT = (1 << 4 | 1),
173173
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT = (1 << 5 | 1),
174+
STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT = (1 << 6 | 1),
174175
/* TLS equates to TLS_ANY as of PHP 7.2 */
175176
STREAM_CRYPTO_METHOD_TLS_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | 1),
176177
STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | 1),
@@ -182,6 +183,7 @@ typedef enum {
182183
STREAM_CRYPTO_METHOD_TLSv1_0_SERVER = (1 << 3),
183184
STREAM_CRYPTO_METHOD_TLSv1_1_SERVER = (1 << 4),
184185
STREAM_CRYPTO_METHOD_TLSv1_2_SERVER = (1 << 5),
186+
STREAM_CRYPTO_METHOD_TLSv1_3_SERVER = (1 << 6),
185187
/* TLS equates to TLS_ANY as of PHP 7.2 */
186188
STREAM_CRYPTO_METHOD_TLS_SERVER = ((1 << 3) | (1 << 4) | (1 << 5)),
187189
STREAM_CRYPTO_METHOD_TLS_ANY_SERVER = ((1 << 3) | (1 << 4) | (1 << 5)),

0 commit comments

Comments
 (0)