Skip to content

Commit 741ff7a

Browse files
author
codarrenvelvindron
committed
Added tls 1.3 support for PHP
1 parent 4dd7177 commit 741ff7a

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
@@ -1559,6 +1559,9 @@ PHP_MINIT_FUNCTION(openssl)
15591559
php_stream_xport_register("tlsv1.0", php_openssl_ssl_socket_factory);
15601560
php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory);
15611561
php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory);
1562+
#if OPENSSL_VERSION_NUMBER >= 0x10101000
1563+
php_stream_xport_register("tlsv1.3", php_openssl_ssl_socket_factory);
1564+
#endif
15621565

15631566
/* override the default tcp socket provider */
15641567
php_stream_xport_register("tcp", php_openssl_ssl_socket_factory);
@@ -1632,6 +1635,9 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
16321635
php_stream_xport_unregister("tlsv1.0");
16331636
php_stream_xport_unregister("tlsv1.1");
16341637
php_stream_xport_unregister("tlsv1.2");
1638+
#if OPENSSL_VERSION_NUMBER >= 0x10101000
1639+
php_stream_xport_unregister("tlsv1.3");
1640+
#endif
16351641

16361642
/* reinstate the default tcp handler */
16371643
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
@@ -998,6 +1002,11 @@ static int php_openssl_get_crypto_method_ctx_flags(int method_flags) /* {{{ */
9981002
ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
9991003
}
10001004
#endif
1005+
#ifdef HAVE_TLS13
1006+
if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_3)) {
1007+
ssl_ctx_options |= SSL_OP_NO_TLSv1_3;
1008+
}
1009+
#endif
10011010

10021011
return ssl_ctx_options;
10031012
}
@@ -1012,7 +1021,7 @@ static inline int php_openssl_get_min_proto_version_flag(int flags) /* {{{ */
10121021
return ver;
10131022
}
10141023
}
1015-
return STREAM_CRYPTO_METHOD_TLSv1_2;
1024+
return STREAM_CRYPTO_METHOD_TLSv1_3;
10161025
}
10171026
/* }}} */
10181027

@@ -1024,7 +1033,7 @@ static inline int php_openssl_get_max_proto_version_flag(int flags) /* {{{ */
10241033
return ver;
10251034
}
10261035
}
1027-
return STREAM_CRYPTO_METHOD_TLSv1_2;
1036+
return STREAM_CRYPTO_METHOD_TLSv1_3;
10281037
}
10291038
/* }}} */
10301039

@@ -1040,9 +1049,13 @@ static inline int php_openssl_map_proto_version(int flag) /* {{{ */
10401049
return TLS1_VERSION;
10411050
case STREAM_CRYPTO_METHOD_TLSv1_1:
10421051
return TLS1_1_VERSION;
1043-
/* case STREAM_CRYPTO_METHOD_TLSv1_2: */
1052+
case STREAM_CRYPTO_METHOD_TLSv1_2:
1053+
return TLS1_2_VERSION;
1054+
/* case STREAM_CRYPTO_METHOD_TLSv1_3: */
1055+
#ifdef HAVE_TLS13
10441056
default:
1045-
return TLS1_2_VERSION;
1057+
return TLS1_3_VERSION;
1058+
#endif
10461059

10471060
}
10481061
}
@@ -1788,6 +1801,11 @@ static zend_array *php_openssl_capture_session_meta(SSL *ssl_handle) /* {{{ */
17881801
char version_str[PHP_SSL_MAX_VERSION_LEN];
17891802

17901803
switch (proto) {
1804+
#ifdef HAVE_TLS13
1805+
case TLS1_3_VERSION:
1806+
proto_str = "TLSv1.3";
1807+
break;
1808+
#endif
17911809
#ifdef HAVE_TLS12
17921810
case TLS1_2_VERSION:
17931811
proto_str = "TLSv1.2";
@@ -2392,6 +2410,9 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
23922410
array_init(&tmp);
23932411

23942412
switch (SSL_version(sslsock->ssl_handle)) {
2413+
#ifdef HAVE_TLS13
2414+
case TLS1_3_VERSION: proto_str = "TLSv1.3"; break;
2415+
#endif
23952416
#ifdef HAVE_TLS12
23962417
case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
23972418
#endif
@@ -2739,6 +2760,16 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen,
27392760
"TLSv1.2 support is not compiled into the OpenSSL library against which PHP is linked");
27402761
php_stream_close(stream);
27412762
return NULL;
2763+
#endif
2764+
} else if (strncmp(proto, "tlsv1.3", protolen) == 0) {
2765+
#ifdef HAVE_TLS13
2766+
sslsock->enable_on_connect = 1;
2767+
sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT;
2768+
#else
2769+
php_error_docref(NULL, E_WARNING,
2770+
"TLSv1.3 support is not compiled into the OpenSSL library against which PHP is linked");
2771+
php_stream_close(stream);
2772+
return NULL;
27422773
#endif
27432774
}
27442775

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)