70-test_sslrecords.t 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. #! /usr/bin/env perl
  2. # Copyright 2016-2018 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 feature 'state';
  10. use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
  11. use OpenSSL::Test::Utils;
  12. use TLSProxy::Proxy;
  13. my $test_name = "test_sslrecords";
  14. setup($test_name);
  15. plan skip_all => "TLSProxy isn't usable on $^O"
  16. if $^O =~ /^(VMS)$/;
  17. plan skip_all => "$test_name needs the dynamic engine feature enabled"
  18. if disabled("engine") || disabled("dynamic-engine");
  19. plan skip_all => "$test_name needs the sock feature enabled"
  20. if disabled("sock");
  21. plan skip_all => "$test_name needs TLSv1.2 enabled"
  22. if disabled("tls1_2");
  23. $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
  24. my $proxy = TLSProxy::Proxy->new(
  25. \&add_empty_recs_filter,
  26. cmdstr(app(["openssl"]), display => 1),
  27. srctop_file("apps", "server.pem"),
  28. (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
  29. );
  30. my $boundary_test_type;
  31. my $fatal_alert = 0; # set by filters at expected fatal alerts
  32. #Test 1: Injecting out of context empty records should fail
  33. my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
  34. my $inject_recs_num = 1;
  35. $proxy->serverflags("-tls1_2");
  36. $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
  37. plan tests => 20;
  38. ok($fatal_alert, "Out of context empty records test");
  39. #Test 2: Injecting in context empty records should succeed
  40. $proxy->clear();
  41. $content_type = TLSProxy::Record::RT_HANDSHAKE;
  42. $proxy->serverflags("-tls1_2");
  43. $proxy->start();
  44. ok(TLSProxy::Message->success(), "In context empty records test");
  45. #Test 3: Injecting too many in context empty records should fail
  46. $fatal_alert = 0;
  47. $proxy->clear();
  48. #We allow 32 consecutive in context empty records
  49. $inject_recs_num = 33;
  50. $proxy->serverflags("-tls1_2");
  51. $proxy->start();
  52. ok($fatal_alert, "Too many in context empty records test");
  53. #Test 4: Injecting a fragmented fatal alert should fail. We expect the server to
  54. # send back an alert of its own because it cannot handle fragmented
  55. # alerts
  56. $fatal_alert = 0;
  57. $proxy->clear();
  58. $proxy->filter(\&add_frag_alert_filter);
  59. $proxy->serverflags("-tls1_2");
  60. $proxy->start();
  61. ok($fatal_alert, "Fragmented alert records test");
  62. #Run some SSLv2 ClientHello tests
  63. use constant {
  64. TLSV1_2_IN_SSLV2 => 0,
  65. SSLV2_IN_SSLV2 => 1,
  66. FRAGMENTED_IN_TLSV1_2 => 2,
  67. FRAGMENTED_IN_SSLV2 => 3,
  68. ALERT_BEFORE_SSLV2 => 4
  69. };
  70. #Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
  71. my $sslv2testtype = TLSV1_2_IN_SSLV2;
  72. $proxy->clear();
  73. $proxy->filter(\&add_sslv2_filter);
  74. $proxy->serverflags("-tls1_2");
  75. $proxy->start();
  76. ok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
  77. #Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
  78. # support this so it should fail. We actually treat it as an unknown
  79. # protocol so we don't even send an alert in this case.
  80. $sslv2testtype = SSLV2_IN_SSLV2;
  81. $proxy->clear();
  82. $proxy->serverflags("-tls1_2");
  83. $proxy->start();
  84. ok(TLSProxy::Message->fail(), "SSLv2 in SSLv2 ClientHello test");
  85. #Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
  86. # at all, but it gives us confidence that Test 8 fails for the right
  87. # reasons
  88. $sslv2testtype = FRAGMENTED_IN_TLSV1_2;
  89. $proxy->clear();
  90. $proxy->serverflags("-tls1_2");
  91. $proxy->start();
  92. ok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
  93. #Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
  94. # record; and another TLS1.2 record. This isn't allowed so should fail
  95. $sslv2testtype = FRAGMENTED_IN_SSLV2;
  96. $proxy->clear();
  97. $proxy->serverflags("-tls1_2");
  98. $proxy->start();
  99. ok(TLSProxy::Message->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
  100. #Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
  101. # fail because an SSLv2 ClientHello must be the first record.
  102. $sslv2testtype = ALERT_BEFORE_SSLV2;
  103. $proxy->clear();
  104. $proxy->serverflags("-tls1_2");
  105. $proxy->start();
  106. ok(TLSProxy::Message->fail(), "Alert before SSLv2 ClientHello test");
  107. #Unrecognised record type tests
  108. #Test 10: Sending an unrecognised record type in TLS1.2 should fail
  109. $fatal_alert = 0;
  110. $proxy->clear();
  111. $proxy->serverflags("-tls1_2");
  112. $proxy->filter(\&add_unknown_record_type);
  113. $proxy->start();
  114. ok($fatal_alert, "Unrecognised record type in TLS1.2");
  115. SKIP: {
  116. skip "TLSv1.1 disabled", 1 if disabled("tls1_1");
  117. #Test 11: Sending an unrecognised record type in TLS1.1 should fail
  118. $fatal_alert = 0;
  119. $proxy->clear();
  120. $proxy->clientflags("-tls1_1");
  121. $proxy->start();
  122. ok($fatal_alert, "Unrecognised record type in TLS1.1");
  123. }
  124. #Test 12: Sending a different record version in TLS1.2 should fail
  125. $fatal_alert = 0;
  126. $proxy->clear();
  127. $proxy->clientflags("-tls1_2");
  128. $proxy->filter(\&change_version);
  129. $proxy->start();
  130. ok($fatal_alert, "Changed record version in TLS1.2");
  131. #TLS1.3 specific tests
  132. SKIP: {
  133. skip "TLSv1.3 disabled", 8 if disabled("tls1_3");
  134. #Test 13: Sending a different record version in TLS1.3 should fail
  135. $proxy->clear();
  136. $proxy->filter(\&change_version);
  137. $proxy->start();
  138. ok(TLSProxy::Message->fail(), "Changed record version in TLS1.3");
  139. #Test 14: Sending an unrecognised record type in TLS1.3 should fail
  140. $fatal_alert = 0;
  141. $proxy->clear();
  142. $proxy->filter(\&add_unknown_record_type);
  143. $proxy->start();
  144. ok($fatal_alert, "Unrecognised record type in TLS1.3");
  145. #Test 15: Sending an outer record type other than app data once encrypted
  146. #should fail
  147. $fatal_alert = 0;
  148. $proxy->clear();
  149. $proxy->filter(\&change_outer_record_type);
  150. $proxy->start();
  151. ok($fatal_alert, "Wrong outer record type in TLS1.3");
  152. use constant {
  153. DATA_AFTER_SERVER_HELLO => 0,
  154. DATA_AFTER_FINISHED => 1,
  155. DATA_AFTER_KEY_UPDATE => 2,
  156. DATA_BETWEEN_KEY_UPDATE => 3,
  157. NO_DATA_BETWEEN_KEY_UPDATE => 4,
  158. };
  159. #Test 16: Sending a ServerHello which doesn't end on a record boundary
  160. # should fail
  161. $fatal_alert = 0;
  162. $proxy->clear();
  163. $boundary_test_type = DATA_AFTER_SERVER_HELLO;
  164. $proxy->filter(\&not_on_record_boundary);
  165. $proxy->start();
  166. ok($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
  167. #Test 17: Sending a Finished which doesn't end on a record boundary
  168. # should fail
  169. $fatal_alert = 0;
  170. $proxy->clear();
  171. $boundary_test_type = DATA_AFTER_FINISHED;
  172. $proxy->start();
  173. ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
  174. #Test 18: Sending a KeyUpdate which doesn't end on a record boundary
  175. # should fail
  176. $fatal_alert = 0;
  177. $proxy->clear();
  178. $boundary_test_type = DATA_AFTER_KEY_UPDATE;
  179. $proxy->start();
  180. ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
  181. #Test 19: Sending application data in the middle of a fragmented KeyUpdate
  182. # should fail. Strictly speaking this is not a record boundary test
  183. # but we use the same filter.
  184. $fatal_alert = 0;
  185. $proxy->clear();
  186. $boundary_test_type = DATA_BETWEEN_KEY_UPDATE;
  187. $proxy->start();
  188. ok($fatal_alert, "Data between KeyUpdate");
  189. #Test 20: Fragmented KeyUpdate. This should succeed. Strictly speaking this
  190. # is not a record boundary test but we use the same filter.
  191. $proxy->clear();
  192. $boundary_test_type = NO_DATA_BETWEEN_KEY_UPDATE;
  193. $proxy->start();
  194. ok(TLSProxy::Message->success(), "No data between KeyUpdate");
  195. }
  196. sub add_empty_recs_filter
  197. {
  198. my $proxy = shift;
  199. my $records = $proxy->record_list;
  200. # We're only interested in the initial ClientHello
  201. if ($proxy->flight != 0) {
  202. $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
  203. return;
  204. }
  205. for (my $i = 0; $i < $inject_recs_num; $i++) {
  206. my $record = TLSProxy::Record->new(
  207. 0,
  208. $content_type,
  209. TLSProxy::Record::VERS_TLS_1_2,
  210. 0,
  211. 0,
  212. 0,
  213. 0,
  214. "",
  215. ""
  216. );
  217. push @{$records}, $record;
  218. }
  219. }
  220. sub add_frag_alert_filter
  221. {
  222. my $proxy = shift;
  223. my $records = $proxy->record_list;
  224. my $byte;
  225. # We're only interested in the initial ClientHello
  226. if ($proxy->flight != 0) {
  227. $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
  228. return;
  229. }
  230. # Add a zero length fragment first
  231. #my $record = TLSProxy::Record->new(
  232. # 0,
  233. # TLSProxy::Record::RT_ALERT,
  234. # TLSProxy::Record::VERS_TLS_1_2,
  235. # 0,
  236. # 0,
  237. # 0,
  238. # "",
  239. # ""
  240. #);
  241. #push @{$proxy->record_list}, $record;
  242. # Now add the alert level (Fatal) as a separate record
  243. $byte = pack('C', TLSProxy::Message::AL_LEVEL_FATAL);
  244. my $record = TLSProxy::Record->new(
  245. 0,
  246. TLSProxy::Record::RT_ALERT,
  247. TLSProxy::Record::VERS_TLS_1_2,
  248. 1,
  249. 0,
  250. 1,
  251. 1,
  252. $byte,
  253. $byte
  254. );
  255. push @{$records}, $record;
  256. # And finally the description (Unexpected message) in a third record
  257. $byte = pack('C', TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE);
  258. $record = TLSProxy::Record->new(
  259. 0,
  260. TLSProxy::Record::RT_ALERT,
  261. TLSProxy::Record::VERS_TLS_1_2,
  262. 1,
  263. 0,
  264. 1,
  265. 1,
  266. $byte,
  267. $byte
  268. );
  269. push @{$records}, $record;
  270. }
  271. sub add_sslv2_filter
  272. {
  273. my $proxy = shift;
  274. my $clienthello;
  275. my $record;
  276. # We're only interested in the initial ClientHello
  277. if ($proxy->flight != 0) {
  278. return;
  279. }
  280. # Ditch the real ClientHello - we're going to replace it with our own
  281. shift @{$proxy->record_list};
  282. if ($sslv2testtype == ALERT_BEFORE_SSLV2) {
  283. my $alert = pack('CC', TLSProxy::Message::AL_LEVEL_FATAL,
  284. TLSProxy::Message::AL_DESC_NO_RENEGOTIATION);
  285. my $alertlen = length $alert;
  286. $record = TLSProxy::Record->new(
  287. 0,
  288. TLSProxy::Record::RT_ALERT,
  289. TLSProxy::Record::VERS_TLS_1_2,
  290. $alertlen,
  291. 0,
  292. $alertlen,
  293. $alertlen,
  294. $alert,
  295. $alert
  296. );
  297. push @{$proxy->record_list}, $record;
  298. }
  299. if ($sslv2testtype == ALERT_BEFORE_SSLV2
  300. || $sslv2testtype == TLSV1_2_IN_SSLV2
  301. || $sslv2testtype == SSLV2_IN_SSLV2) {
  302. # This is an SSLv2 format ClientHello
  303. $clienthello =
  304. pack "C44",
  305. 0x01, # ClientHello
  306. 0x03, 0x03, #TLSv1.2
  307. 0x00, 0x03, # Ciphersuites len
  308. 0x00, 0x00, # Session id len
  309. 0x00, 0x20, # Challenge len
  310. 0x00, 0x00, 0x2f, #AES128-SHA
  311. 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
  312. 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
  313. 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
  314. if ($sslv2testtype == SSLV2_IN_SSLV2) {
  315. # Set the version to "real" SSLv2
  316. vec($clienthello, 1, 8) = 0x00;
  317. vec($clienthello, 2, 8) = 0x02;
  318. }
  319. my $chlen = length $clienthello;
  320. $record = TLSProxy::Record->new(
  321. 0,
  322. TLSProxy::Record::RT_HANDSHAKE,
  323. TLSProxy::Record::VERS_TLS_1_2,
  324. $chlen,
  325. 1, #SSLv2
  326. $chlen,
  327. $chlen,
  328. $clienthello,
  329. $clienthello
  330. );
  331. push @{$proxy->record_list}, $record;
  332. } else {
  333. # For this test we're using a real TLS ClientHello
  334. $clienthello =
  335. pack "C49",
  336. 0x01, # ClientHello
  337. 0x00, 0x00, 0x2D, # Message length
  338. 0x03, 0x03, # TLSv1.2
  339. 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
  340. 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
  341. 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
  342. 0x00, # Session id len
  343. 0x00, 0x04, # Ciphersuites len
  344. 0x00, 0x2f, # AES128-SHA
  345. 0x00, 0xff, # Empty reneg info SCSV
  346. 0x01, # Compression methods len
  347. 0x00, # Null compression
  348. 0x00, 0x00; # Extensions len
  349. # Split this into 3: A TLS record; a SSLv2 record and a TLS record.
  350. # We deliberately split the second record prior to the Challenge/Random
  351. # and set the first byte of the random to 1. This makes the second SSLv2
  352. # record look like an SSLv2 ClientHello
  353. my $frag1 = substr $clienthello, 0, 6;
  354. my $frag2 = substr $clienthello, 6, 32;
  355. my $frag3 = substr $clienthello, 38;
  356. my $fraglen = length $frag1;
  357. $record = TLSProxy::Record->new(
  358. 0,
  359. TLSProxy::Record::RT_HANDSHAKE,
  360. TLSProxy::Record::VERS_TLS_1_2,
  361. $fraglen,
  362. 0,
  363. $fraglen,
  364. $fraglen,
  365. $frag1,
  366. $frag1
  367. );
  368. push @{$proxy->record_list}, $record;
  369. $fraglen = length $frag2;
  370. my $recvers;
  371. if ($sslv2testtype == FRAGMENTED_IN_SSLV2) {
  372. $recvers = 1;
  373. } else {
  374. $recvers = 0;
  375. }
  376. $record = TLSProxy::Record->new(
  377. 0,
  378. TLSProxy::Record::RT_HANDSHAKE,
  379. TLSProxy::Record::VERS_TLS_1_2,
  380. $fraglen,
  381. $recvers,
  382. $fraglen,
  383. $fraglen,
  384. $frag2,
  385. $frag2
  386. );
  387. push @{$proxy->record_list}, $record;
  388. $fraglen = length $frag3;
  389. $record = TLSProxy::Record->new(
  390. 0,
  391. TLSProxy::Record::RT_HANDSHAKE,
  392. TLSProxy::Record::VERS_TLS_1_2,
  393. $fraglen,
  394. 0,
  395. $fraglen,
  396. $fraglen,
  397. $frag3,
  398. $frag3
  399. );
  400. push @{$proxy->record_list}, $record;
  401. }
  402. }
  403. sub add_unknown_record_type
  404. {
  405. my $proxy = shift;
  406. my $records = $proxy->record_list;
  407. state $added_record;
  408. # We'll change a record after the initial version neg has taken place
  409. if ($proxy->flight == 0) {
  410. $added_record = 0;
  411. return;
  412. } elsif ($proxy->flight != 1 || $added_record) {
  413. $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
  414. return;
  415. }
  416. my $record = TLSProxy::Record->new(
  417. 1,
  418. TLSProxy::Record::RT_UNKNOWN,
  419. @{$records}[-1]->version(),
  420. 1,
  421. 0,
  422. 1,
  423. 1,
  424. "X",
  425. "X"
  426. );
  427. #Find ServerHello record and insert after that
  428. my $i;
  429. for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
  430. next;
  431. }
  432. $i++;
  433. splice @{$proxy->record_list}, $i, 0, $record;
  434. $added_record = 1;
  435. }
  436. sub change_version
  437. {
  438. my $proxy = shift;
  439. my $records = $proxy->record_list;
  440. # We'll change a version after the initial version neg has taken place
  441. if ($proxy->flight != 1) {
  442. $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 70;
  443. return;
  444. }
  445. if ($#{$records} > 1) {
  446. # ... typically in ServerHelloDone
  447. @{$records}[-1]->version(TLSProxy::Record::VERS_TLS_1_1);
  448. }
  449. }
  450. sub change_outer_record_type
  451. {
  452. my $proxy = shift;
  453. my $records = $proxy->record_list;
  454. # We'll change a record after the initial version neg has taken place
  455. if ($proxy->flight != 1) {
  456. $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
  457. return;
  458. }
  459. # Find CCS record and change record after that
  460. my $i = 0;
  461. foreach my $record (@{$records}) {
  462. last if $record->content_type == TLSProxy::Record::RT_CCS;
  463. $i++;
  464. }
  465. if (defined(${$records}[++$i])) {
  466. ${$records}[$i]->outer_content_type(TLSProxy::Record::RT_HANDSHAKE);
  467. }
  468. }
  469. sub not_on_record_boundary
  470. {
  471. my $proxy = shift;
  472. my $records = $proxy->record_list;
  473. my $data;
  474. #Find server's first flight
  475. if ($proxy->flight != 1) {
  476. $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
  477. return;
  478. }
  479. if ($boundary_test_type == DATA_AFTER_SERVER_HELLO) {
  480. #Merge the ServerHello and EncryptedExtensions records into one
  481. my $i = 0;
  482. foreach my $record (@{$records}) {
  483. if ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) {
  484. $record->{sent} = 1; # pretend it's sent already
  485. last;
  486. }
  487. $i++;
  488. }
  489. if (defined(${$records}[$i+1])) {
  490. $data = ${$records}[$i]->data();
  491. $data .= ${$records}[$i+1]->decrypt_data();
  492. ${$records}[$i+1]->data($data);
  493. ${$records}[$i+1]->len(length $data);
  494. #Delete the old ServerHello record
  495. splice @{$records}, $i, 1;
  496. }
  497. } elsif ($boundary_test_type == DATA_AFTER_FINISHED) {
  498. return if @{$proxy->{message_list}}[-1]->{mt}
  499. != TLSProxy::Message::MT_FINISHED;
  500. my $last_record = @{$records}[-1];
  501. $data = $last_record->decrypt_data;
  502. #Add a KeyUpdate message onto the end of the Finished record
  503. my $keyupdate = pack "C5",
  504. 0x18, # KeyUpdate
  505. 0x00, 0x00, 0x01, # Message length
  506. 0x00; # Update not requested
  507. $data .= $keyupdate;
  508. #Add content type and tag
  509. $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
  510. #Update the record
  511. $last_record->data($data);
  512. $last_record->len(length $data);
  513. } elsif ($boundary_test_type == DATA_AFTER_KEY_UPDATE) {
  514. return if @{$proxy->{message_list}}[-1]->{mt}
  515. != TLSProxy::Message::MT_FINISHED;
  516. #KeyUpdates must end on a record boundary
  517. my $record = TLSProxy::Record->new(
  518. 1,
  519. TLSProxy::Record::RT_APPLICATION_DATA,
  520. TLSProxy::Record::VERS_TLS_1_2,
  521. 0,
  522. 0,
  523. 0,
  524. 0,
  525. "",
  526. ""
  527. );
  528. #Add two KeyUpdate messages into a single record
  529. my $keyupdate = pack "C5",
  530. 0x18, # KeyUpdate
  531. 0x00, 0x00, 0x01, # Message length
  532. 0x00; # Update not requested
  533. $data = $keyupdate.$keyupdate;
  534. #Add content type and tag
  535. $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
  536. $record->data($data);
  537. $record->len(length $data);
  538. push @{$records}, $record;
  539. } else {
  540. return if @{$proxy->{message_list}}[-1]->{mt}
  541. != TLSProxy::Message::MT_FINISHED;
  542. my $record = TLSProxy::Record->new(
  543. 1,
  544. TLSProxy::Record::RT_APPLICATION_DATA,
  545. TLSProxy::Record::VERS_TLS_1_2,
  546. 0,
  547. 0,
  548. 0,
  549. 0,
  550. "",
  551. ""
  552. );
  553. #Add a partial KeyUpdate message into the record
  554. $data = pack "C1",
  555. 0x18; # KeyUpdate message type. Omit the rest of the message header
  556. #Add content type and tag
  557. $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
  558. $record->data($data);
  559. $record->len(length $data);
  560. push @{$records}, $record;
  561. if ($boundary_test_type == DATA_BETWEEN_KEY_UPDATE) {
  562. #Now add an app data record
  563. $record = TLSProxy::Record->new(
  564. 1,
  565. TLSProxy::Record::RT_APPLICATION_DATA,
  566. TLSProxy::Record::VERS_TLS_1_2,
  567. 0,
  568. 0,
  569. 0,
  570. 0,
  571. "",
  572. ""
  573. );
  574. #Add an empty app data record (just content type and tag)
  575. $data = pack("C", TLSProxy::Record::RT_APPLICATION_DATA).("\0"x16);
  576. $record->data($data);
  577. $record->len(length $data);
  578. push @{$records}, $record;
  579. }
  580. #Now add the rest of the KeyUpdate message
  581. $record = TLSProxy::Record->new(
  582. 1,
  583. TLSProxy::Record::RT_APPLICATION_DATA,
  584. TLSProxy::Record::VERS_TLS_1_2,
  585. 0,
  586. 0,
  587. 0,
  588. 0,
  589. "",
  590. ""
  591. );
  592. #Add the last 4 bytes of the KeyUpdate record
  593. $data = pack "C4",
  594. 0x00, 0x00, 0x01, # Message length
  595. 0x00; # Update not requested
  596. #Add content type and tag
  597. $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
  598. $record->data($data);
  599. $record->len(length $data);
  600. push @{$records}, $record;
  601. }
  602. }