70-test_tls13kexmodes.t 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #! /usr/bin/env perl
  2. # Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License 2.0 (the "License"). You may not use
  5. # this file except in compliance with the License. You can obtain a copy
  6. # in the file LICENSE in the source distribution or at
  7. # https://www.openssl.org/source/license.html
  8. use strict;
  9. use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/;
  10. use OpenSSL::Test::Utils;
  11. use File::Temp qw(tempfile);
  12. use TLSProxy::Proxy;
  13. use checkhandshake qw(checkhandshake @handmessages @extensions);
  14. my $test_name = "test_tls13kexmodes";
  15. setup($test_name);
  16. plan skip_all => "TLSProxy isn't usable on $^O"
  17. if $^O =~ /^(VMS)$/;
  18. plan skip_all => "$test_name needs the dynamic engine feature enabled"
  19. if disabled("engine") || disabled("dynamic-engine");
  20. plan skip_all => "$test_name needs the sock feature enabled"
  21. if disabled("sock");
  22. plan skip_all => "$test_name needs TLSv1.3 enabled"
  23. if disabled("tls1_3");
  24. plan skip_all => "$test_name needs EC enabled"
  25. if disabled("ec");
  26. $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
  27. @handmessages = (
  28. [TLSProxy::Message::MT_CLIENT_HELLO,
  29. checkhandshake::ALL_HANDSHAKES],
  30. [TLSProxy::Message::MT_SERVER_HELLO,
  31. checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
  32. [TLSProxy::Message::MT_CLIENT_HELLO,
  33. checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
  34. [TLSProxy::Message::MT_SERVER_HELLO,
  35. checkhandshake::ALL_HANDSHAKES],
  36. [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS,
  37. checkhandshake::ALL_HANDSHAKES],
  38. [TLSProxy::Message::MT_CERTIFICATE_REQUEST,
  39. checkhandshake::CLIENT_AUTH_HANDSHAKE],
  40. [TLSProxy::Message::MT_CERTIFICATE,
  41. checkhandshake::ALL_HANDSHAKES & ~(checkhandshake::RESUME_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE)],
  42. [TLSProxy::Message::MT_CERTIFICATE_VERIFY,
  43. checkhandshake::ALL_HANDSHAKES & ~(checkhandshake::RESUME_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE)],
  44. [TLSProxy::Message::MT_FINISHED,
  45. checkhandshake::ALL_HANDSHAKES],
  46. [TLSProxy::Message::MT_CERTIFICATE,
  47. checkhandshake::CLIENT_AUTH_HANDSHAKE],
  48. [TLSProxy::Message::MT_CERTIFICATE_VERIFY,
  49. checkhandshake::CLIENT_AUTH_HANDSHAKE],
  50. [TLSProxy::Message::MT_FINISHED,
  51. checkhandshake::ALL_HANDSHAKES],
  52. [0, 0]
  53. );
  54. @extensions = (
  55. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
  56. TLSProxy::Message::CLIENT,
  57. checkhandshake::SERVER_NAME_CLI_EXTENSION],
  58. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
  59. TLSProxy::Message::CLIENT,
  60. checkhandshake::STATUS_REQUEST_CLI_EXTENSION],
  61. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS,
  62. TLSProxy::Message::CLIENT,
  63. checkhandshake::DEFAULT_EXTENSIONS],
  64. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS,
  65. TLSProxy::Message::CLIENT,
  66. checkhandshake::DEFAULT_EXTENSIONS],
  67. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS,
  68. TLSProxy::Message::CLIENT,
  69. checkhandshake::DEFAULT_EXTENSIONS],
  70. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN,
  71. TLSProxy::Message::CLIENT,
  72. checkhandshake::ALPN_CLI_EXTENSION],
  73. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT,
  74. TLSProxy::Message::CLIENT,
  75. checkhandshake::SCT_CLI_EXTENSION],
  76. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
  77. TLSProxy::Message::CLIENT,
  78. checkhandshake::DEFAULT_EXTENSIONS],
  79. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
  80. TLSProxy::Message::CLIENT,
  81. checkhandshake::DEFAULT_EXTENSIONS],
  82. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
  83. TLSProxy::Message::CLIENT,
  84. checkhandshake::DEFAULT_EXTENSIONS],
  85. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
  86. TLSProxy::Message::CLIENT,
  87. checkhandshake::DEFAULT_EXTENSIONS],
  88. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
  89. TLSProxy::Message::CLIENT,
  90. checkhandshake::DEFAULT_EXTENSIONS],
  91. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES,
  92. TLSProxy::Message::CLIENT,
  93. checkhandshake::PSK_KEX_MODES_EXTENSION],
  94. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
  95. TLSProxy::Message::CLIENT,
  96. checkhandshake::PSK_CLI_EXTENSION],
  97. [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
  98. TLSProxy::Message::SERVER,
  99. checkhandshake::DEFAULT_EXTENSIONS],
  100. [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
  101. TLSProxy::Message::SERVER,
  102. checkhandshake::KEY_SHARE_HRR_EXTENSION],
  103. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
  104. TLSProxy::Message::CLIENT,
  105. checkhandshake::SERVER_NAME_CLI_EXTENSION],
  106. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
  107. TLSProxy::Message::CLIENT,
  108. checkhandshake::STATUS_REQUEST_CLI_EXTENSION],
  109. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS,
  110. TLSProxy::Message::CLIENT,
  111. checkhandshake::DEFAULT_EXTENSIONS],
  112. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS,
  113. TLSProxy::Message::CLIENT,
  114. checkhandshake::DEFAULT_EXTENSIONS],
  115. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS,
  116. TLSProxy::Message::CLIENT,
  117. checkhandshake::DEFAULT_EXTENSIONS],
  118. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN,
  119. TLSProxy::Message::CLIENT,
  120. checkhandshake::ALPN_CLI_EXTENSION],
  121. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT,
  122. TLSProxy::Message::CLIENT,
  123. checkhandshake::SCT_CLI_EXTENSION],
  124. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
  125. TLSProxy::Message::CLIENT,
  126. checkhandshake::DEFAULT_EXTENSIONS],
  127. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
  128. TLSProxy::Message::CLIENT,
  129. checkhandshake::DEFAULT_EXTENSIONS],
  130. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
  131. TLSProxy::Message::CLIENT,
  132. checkhandshake::DEFAULT_EXTENSIONS],
  133. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
  134. TLSProxy::Message::CLIENT,
  135. checkhandshake::DEFAULT_EXTENSIONS],
  136. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
  137. TLSProxy::Message::CLIENT,
  138. checkhandshake::DEFAULT_EXTENSIONS],
  139. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES,
  140. TLSProxy::Message::CLIENT,
  141. checkhandshake::PSK_KEX_MODES_EXTENSION],
  142. [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
  143. TLSProxy::Message::CLIENT,
  144. checkhandshake::PSK_CLI_EXTENSION],
  145. [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
  146. TLSProxy::Message::SERVER,
  147. checkhandshake::DEFAULT_EXTENSIONS],
  148. [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
  149. TLSProxy::Message::SERVER,
  150. checkhandshake::KEY_SHARE_SRV_EXTENSION],
  151. [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_PSK,
  152. TLSProxy::Message::SERVER,
  153. checkhandshake::PSK_SRV_EXTENSION],
  154. [TLSProxy::Message::MT_CERTIFICATE, TLSProxy::Message::EXT_STATUS_REQUEST,
  155. TLSProxy::Message::SERVER,
  156. checkhandshake::STATUS_REQUEST_SRV_EXTENSION],
  157. [0,0,0,0]
  158. );
  159. use constant {
  160. DELETE_EXTENSION => 0,
  161. EMPTY_EXTENSION => 1,
  162. NON_DHE_KEX_MODE_ONLY => 2,
  163. DHE_KEX_MODE_ONLY => 3,
  164. UNKNOWN_KEX_MODES => 4,
  165. BOTH_KEX_MODES => 5
  166. };
  167. my $proxy = TLSProxy::Proxy->new(
  168. undef,
  169. cmdstr(app(["openssl"]), display => 1),
  170. srctop_file("apps", "server.pem"),
  171. (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
  172. );
  173. #Test 1: First get a session
  174. (undef, my $session) = tempfile();
  175. $proxy->clientflags("-sess_out ".$session);
  176. $proxy->serverflags("-servername localhost");
  177. $proxy->sessionfile($session);
  178. $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
  179. plan tests => 11;
  180. ok(TLSProxy::Message->success(), "Initial connection");
  181. #Test 2: Attempt a resume with no kex modes extension. Should not resume
  182. $proxy->clear();
  183. $proxy->clientflags("-sess_in ".$session);
  184. my $testtype = DELETE_EXTENSION;
  185. $proxy->filter(\&modify_kex_modes_filter);
  186. $proxy->start();
  187. checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
  188. checkhandshake::DEFAULT_EXTENSIONS
  189. | checkhandshake::KEY_SHARE_SRV_EXTENSION
  190. | checkhandshake::PSK_CLI_EXTENSION,
  191. "Resume with no kex modes");
  192. #Test 3: Attempt a resume with empty kex modes extension. Should fail (empty
  193. # extension is invalid)
  194. $proxy->clear();
  195. $proxy->clientflags("-sess_in ".$session);
  196. $testtype = EMPTY_EXTENSION;
  197. $proxy->start();
  198. ok(TLSProxy::Message->fail(), "Resume with empty kex modes");
  199. #Test 4: Attempt a resume with non-dhe kex mode only. Should resume without a
  200. # key_share
  201. $proxy->clear();
  202. $proxy->clientflags("-allow_no_dhe_kex -sess_in ".$session);
  203. $proxy->serverflags("-allow_no_dhe_kex");
  204. $testtype = NON_DHE_KEX_MODE_ONLY;
  205. $proxy->start();
  206. checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
  207. checkhandshake::DEFAULT_EXTENSIONS
  208. | checkhandshake::PSK_KEX_MODES_EXTENSION
  209. | checkhandshake::PSK_CLI_EXTENSION
  210. | checkhandshake::PSK_SRV_EXTENSION,
  211. "Resume with non-dhe kex mode");
  212. #Test 5: Attempt a resume with dhe kex mode only. Should resume with a key_share
  213. $proxy->clear();
  214. $proxy->clientflags("-sess_in ".$session);
  215. $testtype = DHE_KEX_MODE_ONLY;
  216. $proxy->start();
  217. checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
  218. checkhandshake::DEFAULT_EXTENSIONS
  219. | checkhandshake::PSK_KEX_MODES_EXTENSION
  220. | checkhandshake::KEY_SHARE_SRV_EXTENSION
  221. | checkhandshake::PSK_CLI_EXTENSION
  222. | checkhandshake::PSK_SRV_EXTENSION,
  223. "Resume with non-dhe kex mode");
  224. #Test 6: Attempt a resume with only unrecognised kex modes. Should not resume
  225. $proxy->clear();
  226. $proxy->clientflags("-sess_in ".$session);
  227. $testtype = UNKNOWN_KEX_MODES;
  228. $proxy->start();
  229. checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
  230. checkhandshake::DEFAULT_EXTENSIONS
  231. | checkhandshake::PSK_KEX_MODES_EXTENSION
  232. | checkhandshake::KEY_SHARE_SRV_EXTENSION
  233. | checkhandshake::PSK_CLI_EXTENSION,
  234. "Resume with empty kex modes");
  235. #Test 7: Attempt a resume with both non-dhe and dhe kex mode. Should resume with
  236. # a key_share
  237. $proxy->clear();
  238. $proxy->clientflags("-sess_in ".$session);
  239. $testtype = BOTH_KEX_MODES;
  240. $proxy->start();
  241. checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
  242. checkhandshake::DEFAULT_EXTENSIONS
  243. | checkhandshake::PSK_KEX_MODES_EXTENSION
  244. | checkhandshake::KEY_SHARE_SRV_EXTENSION
  245. | checkhandshake::PSK_CLI_EXTENSION
  246. | checkhandshake::PSK_SRV_EXTENSION,
  247. "Resume with non-dhe kex mode");
  248. #Test 8: Attempt a resume with both non-dhe and dhe kex mode, but unacceptable
  249. # initial key_share. Should resume with a key_share following an HRR
  250. $proxy->clear();
  251. $proxy->clientflags("-sess_in ".$session);
  252. $proxy->serverflags("-curves P-256");
  253. $testtype = BOTH_KEX_MODES;
  254. $proxy->start();
  255. checkhandshake($proxy, checkhandshake::HRR_RESUME_HANDSHAKE,
  256. checkhandshake::DEFAULT_EXTENSIONS
  257. | checkhandshake::PSK_KEX_MODES_EXTENSION
  258. | checkhandshake::KEY_SHARE_SRV_EXTENSION
  259. | checkhandshake::KEY_SHARE_HRR_EXTENSION
  260. | checkhandshake::PSK_CLI_EXTENSION
  261. | checkhandshake::PSK_SRV_EXTENSION,
  262. "Resume with both kex modes and HRR");
  263. #Test 9: Attempt a resume with dhe kex mode only and an unacceptable initial
  264. # key_share. Should resume with a key_share following an HRR
  265. $proxy->clear();
  266. $proxy->clientflags("-sess_in ".$session);
  267. $proxy->serverflags("-curves P-256");
  268. $testtype = DHE_KEX_MODE_ONLY;
  269. $proxy->start();
  270. checkhandshake($proxy, checkhandshake::HRR_RESUME_HANDSHAKE,
  271. checkhandshake::DEFAULT_EXTENSIONS
  272. | checkhandshake::PSK_KEX_MODES_EXTENSION
  273. | checkhandshake::KEY_SHARE_SRV_EXTENSION
  274. | checkhandshake::KEY_SHARE_HRR_EXTENSION
  275. | checkhandshake::PSK_CLI_EXTENSION
  276. | checkhandshake::PSK_SRV_EXTENSION,
  277. "Resume with dhe kex mode and HRR");
  278. #Test 10: Attempt a resume with both non-dhe and dhe kex mode, unacceptable
  279. # initial key_share and no overlapping groups. Should resume without a
  280. # key_share
  281. $proxy->clear();
  282. $proxy->clientflags("-allow_no_dhe_kex -curves P-384 -sess_in ".$session);
  283. $proxy->serverflags("-allow_no_dhe_kex -curves P-256");
  284. $testtype = BOTH_KEX_MODES;
  285. $proxy->start();
  286. checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
  287. checkhandshake::DEFAULT_EXTENSIONS
  288. | checkhandshake::PSK_KEX_MODES_EXTENSION
  289. | checkhandshake::PSK_CLI_EXTENSION
  290. | checkhandshake::PSK_SRV_EXTENSION,
  291. "Resume with both kex modes, no overlapping groups");
  292. #Test 11: Attempt a resume with dhe kex mode only, unacceptable
  293. # initial key_share and no overlapping groups. Should fail
  294. $proxy->clear();
  295. $proxy->clientflags("-curves P-384 -sess_in ".$session);
  296. $proxy->serverflags("-curves P-256");
  297. $testtype = DHE_KEX_MODE_ONLY;
  298. $proxy->start();
  299. ok(TLSProxy::Message->fail(), "Resume with dhe kex mode, no overlapping groups");
  300. unlink $session;
  301. sub modify_kex_modes_filter
  302. {
  303. my $proxy = shift;
  304. # We're only interested in the initial ClientHello
  305. return if ($proxy->flight != 0);
  306. foreach my $message (@{$proxy->message_list}) {
  307. if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
  308. my $ext;
  309. if ($testtype == EMPTY_EXTENSION) {
  310. $ext = pack "C",
  311. 0x00; #List length
  312. } elsif ($testtype == NON_DHE_KEX_MODE_ONLY) {
  313. $ext = pack "C2",
  314. 0x01, #List length
  315. 0x00; #psk_ke
  316. } elsif ($testtype == DHE_KEX_MODE_ONLY) {
  317. $ext = pack "C2",
  318. 0x01, #List length
  319. 0x01; #psk_dhe_ke
  320. } elsif ($testtype == UNKNOWN_KEX_MODES) {
  321. $ext = pack "C3",
  322. 0x02, #List length
  323. 0xfe, #unknown
  324. 0xff; #unknown
  325. } elsif ($testtype == BOTH_KEX_MODES) {
  326. #We deliberately list psk_ke first...should still use psk_dhe_ke
  327. $ext = pack "C3",
  328. 0x02, #List length
  329. 0x00, #psk_ke
  330. 0x01; #psk_dhe_ke
  331. }
  332. if ($testtype == DELETE_EXTENSION) {
  333. $message->delete_extension(
  334. TLSProxy::Message::EXT_PSK_KEX_MODES);
  335. } else {
  336. $message->set_extension(
  337. TLSProxy::Message::EXT_PSK_KEX_MODES, $ext);
  338. }
  339. $message->repack();
  340. }
  341. }
  342. }