checkhandshake.pm 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #! /usr/bin/env perl
  2. # Copyright 2015-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. package checkhandshake;
  9. use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/;
  10. use OpenSSL::Test::Utils;
  11. use TLSProxy::Proxy;
  12. use Exporter;
  13. our @ISA = 'Exporter';
  14. our @EXPORT = qw(@handmessages @extensions checkhandshake);
  15. use constant {
  16. DEFAULT_HANDSHAKE => 1,
  17. OCSP_HANDSHAKE => 2,
  18. RESUME_HANDSHAKE => 4,
  19. CLIENT_AUTH_HANDSHAKE => 8,
  20. RENEG_HANDSHAKE => 16,
  21. NPN_HANDSHAKE => 32,
  22. EC_HANDSHAKE => 64,
  23. HRR_HANDSHAKE => 128,
  24. HRR_RESUME_HANDSHAKE => 256,
  25. CERT_COMP_SRV_HANDSHAKE => 512,
  26. CERT_COMP_CLI_HANDSHAKE => 1024,
  27. CERT_COMP_BOTH_HANDSHAKE => 2048,
  28. ALL_HANDSHAKES => 4095
  29. };
  30. use constant {
  31. #DEFAULT also includes SESSION_TICKET_SRV_EXTENSION and SERVER_NAME_CLI
  32. DEFAULT_EXTENSIONS => 0x00000007,
  33. SESSION_TICKET_SRV_EXTENSION => 0x00000002,
  34. SERVER_NAME_CLI_EXTENSION => 0x00000004,
  35. SERVER_NAME_SRV_EXTENSION => 0x00000008,
  36. STATUS_REQUEST_CLI_EXTENSION => 0x00000010,
  37. STATUS_REQUEST_SRV_EXTENSION => 0x00000020,
  38. ALPN_CLI_EXTENSION => 0x00000040,
  39. ALPN_SRV_EXTENSION => 0x00000080,
  40. SCT_CLI_EXTENSION => 0x00000100,
  41. SCT_SRV_EXTENSION => 0x00000200,
  42. RENEGOTIATE_CLI_EXTENSION => 0x00000400,
  43. NPN_CLI_EXTENSION => 0x00000800,
  44. NPN_SRV_EXTENSION => 0x00001000,
  45. SRP_CLI_EXTENSION => 0x00002000,
  46. #Client side for ec point formats is a default extension
  47. EC_POINT_FORMAT_SRV_EXTENSION => 0x00004000,
  48. PSK_CLI_EXTENSION => 0x00008000,
  49. PSK_SRV_EXTENSION => 0x00010000,
  50. KEY_SHARE_SRV_EXTENSION => 0x00020000,
  51. PSK_KEX_MODES_EXTENSION => 0x00040000,
  52. KEY_SHARE_HRR_EXTENSION => 0x00080000,
  53. SUPPORTED_GROUPS_SRV_EXTENSION => 0x00100000,
  54. POST_HANDSHAKE_AUTH_CLI_EXTENSION => 0x00200000,
  55. CERT_COMP_CLI_EXTENSION => 0x00400000,
  56. CERT_COMP_SRV_EXTENSION => 0x00800000
  57. };
  58. our @handmessages = ();
  59. our @extensions = ();
  60. sub checkhandshake($$$$)
  61. {
  62. my ($proxy, $handtype, $exttype, $testname) = @_;
  63. subtest $testname => sub {
  64. my $loop = 0;
  65. my $numtests;
  66. my $extcount;
  67. my $clienthelloseen = 0;
  68. my $lastmt = 0;
  69. my $numsh = 0;
  70. if (TLSProxy::Proxy::is_tls13()) {
  71. #How many ServerHellos are we expecting?
  72. for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) {
  73. next if (($handmessages[$loop][1] & $handtype) == 0);
  74. $numsh++ if ($lastmt != TLSProxy::Message::MT_SERVER_HELLO
  75. && $handmessages[$loop][0] == TLSProxy::Message::MT_SERVER_HELLO);
  76. $lastmt = $handmessages[$loop][0];
  77. }
  78. }
  79. #First count the number of tests
  80. my $nextmess = 0;
  81. my $message = undef;
  82. my $chnum = 0;
  83. my $shnum = 0;
  84. if (!TLSProxy::Proxy::is_tls13()) {
  85. # In non-TLSv1.3 we always treat reneg CH and SH like the first CH
  86. # and SH
  87. $chnum = 1;
  88. $shnum = 1;
  89. }
  90. #If we're only expecting one ServerHello out of two then we skip the
  91. #first ServerHello in the list completely
  92. $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13());
  93. $loop = 0;
  94. for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) {
  95. next if (($handmessages[$loop][1] & $handtype) == 0);
  96. if (scalar @{$proxy->message_list} > $nextmess) {
  97. $message = ${$proxy->message_list}[$nextmess];
  98. $nextmess++;
  99. } else {
  100. $message = undef;
  101. }
  102. $numtests++;
  103. next if (!defined $message);
  104. if (TLSProxy::Proxy::is_tls13()) {
  105. $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO;
  106. $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO;
  107. }
  108. next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
  109. && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO
  110. && $message->mt() !=
  111. TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS
  112. && $message->mt() != TLSProxy::Message::MT_CERTIFICATE
  113. && $message->mt() != TLSProxy::Message::MT_CERTIFICATE_REQUEST);
  114. next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE
  115. && !TLSProxy::Proxy::is_tls13();
  116. my $extchnum = 1;
  117. my $extshnum = 1;
  118. for (my $extloop = 0;
  119. $extensions[$extloop][3] != 0;
  120. $extloop++) {
  121. $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO
  122. && TLSProxy::Proxy::is_tls13();
  123. $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO
  124. && $extchnum == 2;
  125. next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO
  126. && $extchnum != $chnum;
  127. next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO
  128. && $extshnum != $shnum;
  129. next if ($message->mt() != $extensions[$extloop][0]);
  130. next if ($message->server() != $extensions[$extloop][2]);
  131. $numtests++;
  132. }
  133. $numtests++;
  134. }
  135. plan tests => $numtests;
  136. $nextmess = 0;
  137. $message = undef;
  138. if (TLSProxy::Proxy::is_tls13()) {
  139. $chnum = 0;
  140. $shnum = 0;
  141. } else {
  142. # In non-TLSv1.3 we always treat reneg CH and SH like the first CH
  143. # and SH
  144. $chnum = 1;
  145. $shnum = 1;
  146. }
  147. #If we're only expecting one ServerHello out of two then we skip the
  148. #first ServerHello in the list completely
  149. $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13());
  150. for ($loop = 0; $handmessages[$loop][1] != 0; $loop++) {
  151. next if (($handmessages[$loop][1] & $handtype) == 0);
  152. if (scalar @{$proxy->message_list} > $nextmess) {
  153. $message = ${$proxy->message_list}[$nextmess];
  154. $nextmess++;
  155. } else {
  156. $message = undef;
  157. }
  158. if (!defined $message) {
  159. fail("Message type check. Got nothing, expected "
  160. .$handmessages[$loop][0]);
  161. next;
  162. } else {
  163. ok($message->mt == $handmessages[$loop][0],
  164. "Message type check. Got ".$message->mt
  165. .", expected ".$handmessages[$loop][0]);
  166. }
  167. if (TLSProxy::Proxy::is_tls13()) {
  168. $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO;
  169. $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO;
  170. }
  171. next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
  172. && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO
  173. && $message->mt() !=
  174. TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS
  175. && $message->mt() != TLSProxy::Message::MT_CERTIFICATE
  176. && $message->mt() != TLSProxy::Message::MT_CERTIFICATE_REQUEST);
  177. next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE
  178. && !TLSProxy::Proxy::is_tls13();
  179. if ($message->mt() == TLSProxy::Message::MT_CLIENT_HELLO) {
  180. #Add renegotiate extension we will expect if renegotiating
  181. $exttype |= RENEGOTIATE_CLI_EXTENSION
  182. if ($clienthelloseen && !TLSProxy::Proxy::is_tls13());
  183. $clienthelloseen = 1;
  184. }
  185. #Now check that we saw the extensions we expected
  186. my $msgexts = $message->extension_data();
  187. my $extchnum = 1;
  188. my $extshnum = 1;
  189. for (my $extloop = 0, $extcount = 0; $extensions[$extloop][3] != 0;
  190. $extloop++) {
  191. #In TLSv1.3 we can have two ClientHellos if there has been a
  192. #HelloRetryRequest, and they may have different extensions. Skip
  193. #if these are extensions for a different ClientHello
  194. $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO
  195. && TLSProxy::Proxy::is_tls13();
  196. $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO
  197. && $extchnum == 2;
  198. next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO
  199. && $extchnum != $chnum;
  200. next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO
  201. && $extshnum != $shnum;
  202. next if ($message->mt() != $extensions[$extloop][0]);
  203. next if ($message->server() != $extensions[$extloop][2]);
  204. ok (($extensions[$extloop][3] & $exttype) == 0
  205. || defined ($msgexts->{$extensions[$extloop][1]}),
  206. "Extension presence check (Message: ".$message->mt()
  207. ." Extension: ".($extensions[$extloop][3] & $exttype).", "
  208. .$extloop.")");
  209. $extcount++ if (($extensions[$extloop][3] & $exttype) != 0);
  210. }
  211. ok($extcount == keys %$msgexts, "Extensions count mismatch ("
  212. .$extcount.", ".(keys %$msgexts)
  213. .")");
  214. }
  215. }
  216. }
  217. 1;