70-test_sslsigalgs.t 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. #! /usr/bin/env perl
  2. # Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the OpenSSL license (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 bldtop_dir/;
  10. use OpenSSL::Test::Utils;
  11. use TLSProxy::Proxy;
  12. my $test_name = "test_sslsigalgs";
  13. setup($test_name);
  14. plan skip_all => "TLSProxy isn't usable on $^O"
  15. if $^O =~ /^(VMS)$/;
  16. plan skip_all => "$test_name needs the dynamic engine feature enabled"
  17. if disabled("engine") || disabled("dynamic-engine");
  18. plan skip_all => "$test_name needs the sock feature enabled"
  19. if disabled("sock");
  20. plan skip_all => "$test_name needs TLS1.2 or TLS1.3 enabled"
  21. if disabled("tls1_2") && disabled("tls1_3");
  22. $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
  23. my $proxy = TLSProxy::Proxy->new(
  24. undef,
  25. cmdstr(app(["openssl"]), display => 1),
  26. srctop_file("apps", "server.pem"),
  27. (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
  28. );
  29. use constant {
  30. NO_SIG_ALGS_EXT => 0,
  31. EMPTY_SIG_ALGS_EXT => 1,
  32. NO_KNOWN_SIG_ALGS => 2,
  33. NO_PSS_SIG_ALGS => 3,
  34. PSS_ONLY_SIG_ALGS => 4,
  35. PURE_SIGALGS => 5,
  36. COMPAT_SIGALGS => 6,
  37. SIGALGS_CERT_ALL => 7,
  38. SIGALGS_CERT_PKCS => 8,
  39. SIGALGS_CERT_INVALID => 9
  40. };
  41. #Note: Throughout this test we override the default ciphersuites where TLSv1.2
  42. # is expected to ensure that a ServerKeyExchange message is sent that uses
  43. # the sigalgs
  44. #Test 1: Default sig algs should succeed
  45. $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
  46. plan tests => 24;
  47. ok(TLSProxy::Message->success, "Default sigalgs");
  48. my $testtype;
  49. SKIP: {
  50. skip "TLSv1.3 disabled", 6 if disabled("tls1_3");
  51. $proxy->filter(\&sigalgs_filter);
  52. #Test 2: Sending no sig algs extension in TLSv1.3 should fail
  53. $proxy->clear();
  54. $testtype = NO_SIG_ALGS_EXT;
  55. $proxy->start();
  56. ok(TLSProxy::Message->fail, "No TLSv1.3 sigalgs");
  57. #Test 3: Sending an empty sig algs extension in TLSv1.3 should fail
  58. $proxy->clear();
  59. $testtype = EMPTY_SIG_ALGS_EXT;
  60. $proxy->start();
  61. ok(TLSProxy::Message->fail, "Empty TLSv1.3 sigalgs");
  62. #Test 4: Sending a list with no recognised sig algs in TLSv1.3 should fail
  63. $proxy->clear();
  64. $testtype = NO_KNOWN_SIG_ALGS;
  65. $proxy->start();
  66. ok(TLSProxy::Message->fail, "No known TLSv1.3 sigalgs");
  67. #Test 5: Sending a sig algs list without pss for an RSA cert in TLSv1.3
  68. # should fail
  69. $proxy->clear();
  70. $testtype = NO_PSS_SIG_ALGS;
  71. $proxy->start();
  72. ok(TLSProxy::Message->fail, "No PSS TLSv1.3 sigalgs");
  73. #Test 6: Sending only TLSv1.3 PSS sig algs in TLSv1.3 should succeed
  74. #TODO(TLS1.3): Do we need to verify the cert to make sure its a PSS only
  75. #cert in this case?
  76. $proxy->clear();
  77. $testtype = PSS_ONLY_SIG_ALGS;
  78. $proxy->start();
  79. ok(TLSProxy::Message->success, "PSS only sigalgs in TLSv1.3");
  80. #Test 7: Modify the CertificateVerify sigalg from rsa_pss_rsae_sha256 to
  81. # rsa_pss_pss_sha256. This should fail because the public key OID
  82. # in the certificate is rsaEncryption and not rsassaPss
  83. $proxy->filter(\&modify_cert_verify_sigalg);
  84. $proxy->clear();
  85. $proxy->start();
  86. ok(TLSProxy::Message->fail,
  87. "Mismatch between CertVerify sigalg and public key OID");
  88. }
  89. SKIP: {
  90. skip "EC or TLSv1.3 disabled", 1
  91. if disabled("tls1_3") || disabled("ec");
  92. #Test 8: Sending a valid sig algs list but not including a sig type that
  93. # matches the certificate should fail in TLSv1.3.
  94. $proxy->clear();
  95. $proxy->clientflags("-sigalgs ECDSA+SHA256");
  96. $proxy->filter(undef);
  97. $proxy->start();
  98. ok(TLSProxy::Message->fail, "No matching TLSv1.3 sigalgs");
  99. }
  100. SKIP: {
  101. skip "EC, TLSv1.3 or TLSv1.2 disabled", 1
  102. if disabled("tls1_2") || disabled("tls1_3") || disabled("ec");
  103. #Test 9: Sending a full list of TLSv1.3 sig algs but negotiating TLSv1.2
  104. # should succeed
  105. $proxy->clear();
  106. $proxy->serverflags("-no_tls1_3");
  107. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  108. $proxy->filter(undef);
  109. $proxy->start();
  110. ok(TLSProxy::Message->success, "TLSv1.3 client TLSv1.2 server");
  111. }
  112. SKIP: {
  113. skip "EC or TLSv1.2 disabled", 10 if disabled("tls1_2") || disabled("ec");
  114. $proxy->filter(\&sigalgs_filter);
  115. #Test 10: Sending no sig algs extension in TLSv1.2 should succeed at
  116. # security level 1
  117. $proxy->clear();
  118. $testtype = NO_SIG_ALGS_EXT;
  119. $proxy->clientflags("-no_tls1_3 -cipher DEFAULT\@SECLEVEL=1");
  120. $proxy->ciphers("ECDHE-RSA-AES128-SHA\@SECLEVEL=1");
  121. $proxy->start();
  122. ok(TLSProxy::Message->success, "No TLSv1.2 sigalgs seclevel 1");
  123. #Test 11: Sending no sig algs extension in TLSv1.2 should fail at security
  124. # level 2 since it will try to use SHA1. Testing client at level 1,
  125. # server level 2.
  126. $proxy->clear();
  127. $testtype = NO_SIG_ALGS_EXT;
  128. $proxy->clientflags("-tls1_2 -cipher DEFAULT\@SECLEVEL=1");
  129. $proxy->ciphers("DEFAULT\@SECLEVEL=2");
  130. $proxy->start();
  131. ok(TLSProxy::Message->fail, "No TLSv1.2 sigalgs server seclevel 2");
  132. #Test 12: Sending no sig algs extension in TLSv1.2 should fail at security
  133. # level 2 since it will try to use SHA1. Testing client at level 2,
  134. # server level 1.
  135. $proxy->clear();
  136. $testtype = NO_SIG_ALGS_EXT;
  137. $proxy->clientflags("-tls1_2 -cipher DEFAULT\@SECLEVEL=2");
  138. $proxy->ciphers("DEFAULT\@SECLEVEL=1");
  139. $proxy->start();
  140. ok(TLSProxy::Message->fail, "No TLSv1.2 sigalgs client seclevel 2");
  141. #Test 13: Sending an empty sig algs extension in TLSv1.2 should fail
  142. $proxy->clear();
  143. $testtype = EMPTY_SIG_ALGS_EXT;
  144. $proxy->clientflags("-no_tls1_3");
  145. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  146. $proxy->start();
  147. ok(TLSProxy::Message->fail, "Empty TLSv1.2 sigalgs");
  148. #Test 14: Sending a list with no recognised sig algs in TLSv1.2 should fail
  149. $proxy->clear();
  150. $testtype = NO_KNOWN_SIG_ALGS;
  151. $proxy->clientflags("-no_tls1_3");
  152. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  153. $proxy->start();
  154. ok(TLSProxy::Message->fail, "No known TLSv1.3 sigalgs");
  155. #Test 15: Sending a sig algs list without pss for an RSA cert in TLSv1.2
  156. # should succeed
  157. $proxy->clear();
  158. $testtype = NO_PSS_SIG_ALGS;
  159. $proxy->clientflags("-no_tls1_3");
  160. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  161. $proxy->start();
  162. ok(TLSProxy::Message->success, "No PSS TLSv1.2 sigalgs");
  163. #Test 16: Sending only TLSv1.3 PSS sig algs in TLSv1.2 should succeed
  164. $proxy->clear();
  165. $testtype = PSS_ONLY_SIG_ALGS;
  166. $proxy->serverflags("-no_tls1_3");
  167. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  168. $proxy->start();
  169. ok(TLSProxy::Message->success, "PSS only sigalgs in TLSv1.2");
  170. #Test 17: Responding with a sig alg we did not send in TLSv1.2 should fail
  171. # We send rsa_pkcs1_sha256 and respond with rsa_pss_rsae_sha256
  172. # TODO(TLS1.3): Add a similar test to the TLSv1.3 section above
  173. # when we have an API capable of configuring the TLSv1.3 sig algs
  174. $proxy->clear();
  175. $testtype = PSS_ONLY_SIG_ALGS;
  176. $proxy->clientflags("-no_tls1_3 -sigalgs RSA+SHA256");
  177. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  178. $proxy->start();
  179. ok(TLSProxy::Message->fail, "Sigalg we did not send in TLSv1.2");
  180. #Test 18: Sending a valid sig algs list but not including a sig type that
  181. # matches the certificate should fail in TLSv1.2
  182. $proxy->clear();
  183. $proxy->clientflags("-no_tls1_3 -sigalgs ECDSA+SHA256");
  184. $proxy->ciphers("ECDHE-RSA-AES128-SHA");
  185. $proxy->filter(undef);
  186. $proxy->start();
  187. ok(TLSProxy::Message->fail, "No matching TLSv1.2 sigalgs");
  188. $proxy->filter(\&sigalgs_filter);
  189. #Test 19: No sig algs extension, ECDSA cert, TLSv1.2 should succeed
  190. $proxy->clear();
  191. $testtype = NO_SIG_ALGS_EXT;
  192. $proxy->clientflags("-no_tls1_3");
  193. $proxy->serverflags("-cert " . srctop_file("test", "certs",
  194. "server-ecdsa-cert.pem") .
  195. " -key " . srctop_file("test", "certs",
  196. "server-ecdsa-key.pem")),
  197. $proxy->ciphers("ECDHE-ECDSA-AES128-SHA");
  198. $proxy->start();
  199. ok(TLSProxy::Message->success, "No TLSv1.2 sigalgs, ECDSA");
  200. }
  201. my ($dsa_status, $sha1_status, $sha224_status);
  202. SKIP: {
  203. skip "TLSv1.3 disabled", 2 if disabled("tls1_3") || disabled("dsa");
  204. #Test 20: signature_algorithms with 1.3-only ClientHello
  205. $testtype = PURE_SIGALGS;
  206. $dsa_status = $sha1_status = $sha224_status = 0;
  207. $proxy->clear();
  208. $proxy->clientflags("-tls1_3");
  209. $proxy->filter(\&modify_sigalgs_filter);
  210. $proxy->start();
  211. ok($dsa_status && $sha1_status && $sha224_status,
  212. "DSA/SHA2 sigalg sent for 1.3-only ClientHello");
  213. #Test 21: signature_algorithms with backwards compatible ClientHello
  214. SKIP: {
  215. skip "TLSv1.2 disabled", 1 if disabled("tls1_2");
  216. $testtype = COMPAT_SIGALGS;
  217. $dsa_status = $sha1_status = $sha224_status = 0;
  218. $proxy->clear();
  219. $proxy->filter(\&modify_sigalgs_filter);
  220. $proxy->start();
  221. ok($dsa_status && $sha1_status && $sha224_status,
  222. "DSA sigalg not sent for compat ClientHello");
  223. }
  224. }
  225. SKIP: {
  226. skip "TLSv1.3 disabled", 3 if disabled("tls1_3");
  227. #Test 22: Insert signature_algorithms_cert that match normal sigalgs
  228. $testtype = SIGALGS_CERT_ALL;
  229. $proxy->clear();
  230. $proxy->filter(\&modify_sigalgs_cert_filter);
  231. $proxy->start();
  232. ok(TLSProxy::Message->success, "sigalgs_cert in TLSv1.3");
  233. #Test 23: Insert signature_algorithms_cert that forces PKCS#1 cert
  234. $testtype = SIGALGS_CERT_PKCS;
  235. $proxy->clear();
  236. $proxy->filter(\&modify_sigalgs_cert_filter);
  237. $proxy->start();
  238. ok(TLSProxy::Message->success, "sigalgs_cert in TLSv1.3 with PKCS#1 cert");
  239. #Test 24: Insert signature_algorithms_cert that fails
  240. $testtype = SIGALGS_CERT_INVALID;
  241. $proxy->clear();
  242. $proxy->filter(\&modify_sigalgs_cert_filter);
  243. $proxy->start();
  244. ok(TLSProxy::Message->fail, "No matching certificate for sigalgs_cert");
  245. }
  246. sub sigalgs_filter
  247. {
  248. my $proxy = shift;
  249. # We're only interested in the initial ClientHello
  250. if ($proxy->flight != 0) {
  251. return;
  252. }
  253. foreach my $message (@{$proxy->message_list}) {
  254. if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
  255. if ($testtype == NO_SIG_ALGS_EXT) {
  256. $message->delete_extension(TLSProxy::Message::EXT_SIG_ALGS);
  257. } else {
  258. my $sigalg;
  259. if ($testtype == EMPTY_SIG_ALGS_EXT) {
  260. $sigalg = pack "C2", 0x00, 0x00;
  261. } elsif ($testtype == NO_KNOWN_SIG_ALGS) {
  262. $sigalg = pack "C4", 0x00, 0x02, 0xff, 0xff;
  263. } elsif ($testtype == NO_PSS_SIG_ALGS) {
  264. #No PSS sig algs - just send rsa_pkcs1_sha256
  265. $sigalg = pack "C4", 0x00, 0x02, 0x04, 0x01;
  266. } else {
  267. #PSS sig algs only - just send rsa_pss_rsae_sha256
  268. $sigalg = pack "C4", 0x00, 0x02, 0x08, 0x04;
  269. }
  270. $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS, $sigalg);
  271. }
  272. $message->repack();
  273. }
  274. }
  275. }
  276. sub modify_sigalgs_filter
  277. {
  278. my $proxy = shift;
  279. # We're only interested in the initial ClientHello
  280. return if ($proxy->flight != 0);
  281. foreach my $message (@{$proxy->message_list}) {
  282. my $ext;
  283. my @algs;
  284. if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
  285. if ($testtype == PURE_SIGALGS) {
  286. my $ok = 1;
  287. $ext = $message->extension_data->{TLSProxy::Message::EXT_SIG_ALGS};
  288. @algs = unpack('S>*', $ext);
  289. # unpack will unpack the length as well
  290. shift @algs;
  291. foreach (@algs) {
  292. if ($_ == TLSProxy::Message::SIG_ALG_DSA_SHA256
  293. || $_ == TLSProxy::Message::SIG_ALG_DSA_SHA384
  294. || $_ == TLSProxy::Message::SIG_ALG_DSA_SHA512
  295. || $_ == TLSProxy::Message::OSSL_SIG_ALG_DSA_SHA224
  296. || $_ == TLSProxy::Message::SIG_ALG_RSA_PKCS1_SHA1
  297. || $_ == TLSProxy::Message::SIG_ALG_DSA_SHA1
  298. || $_ == TLSProxy::Message::SIG_ALG_ECDSA_SHA1) {
  299. $ok = 0;
  300. }
  301. }
  302. $sha1_status = $dsa_status = $sha224_status = 1 if ($ok);
  303. } elsif ($testtype == COMPAT_SIGALGS) {
  304. $ext = $message->extension_data->{TLSProxy::Message::EXT_SIG_ALGS};
  305. @algs = unpack('S>*', $ext);
  306. # unpack will unpack the length as well
  307. shift @algs;
  308. foreach (@algs) {
  309. if ($_ == TLSProxy::Message::SIG_ALG_DSA_SHA256
  310. || $_ == TLSProxy::Message::SIG_ALG_DSA_SHA384
  311. || $_ == TLSProxy::Message::SIG_ALG_DSA_SHA512) {
  312. $dsa_status = 1;
  313. }
  314. if ($_ == TLSProxy::Message::SIG_ALG_RSA_PKCS1_SHA1
  315. || $_ == TLSProxy::Message::SIG_ALG_DSA_SHA1
  316. || $_ == TLSProxy::Message::SIG_ALG_ECDSA_SHA1) {
  317. $sha1_status = 1;
  318. }
  319. if ($_ == TLSProxy::Message::OSSL_SIG_ALG_RSA_PKCS1_SHA224
  320. || $_ == TLSProxy::Message::OSSL_SIG_ALG_DSA_SHA224
  321. || $_ == TLSProxy::Message::OSSL_SIG_ALG_ECDSA_SHA224) {
  322. $sha224_status = 1;
  323. }
  324. }
  325. }
  326. }
  327. }
  328. }
  329. sub modify_sigalgs_cert_filter
  330. {
  331. my $proxy = shift;
  332. # We're only interested in the initial ClientHello
  333. if ($proxy->flight != 0) {
  334. return;
  335. }
  336. foreach my $message (@{$proxy->message_list}) {
  337. if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
  338. my $sigs;
  339. # two byte length at front of sigs, then two-byte sigschemes
  340. if ($testtype == SIGALGS_CERT_ALL) {
  341. $sigs = pack "C26", 0x00, 0x18,
  342. # rsa_pkcs_sha{256,512} rsa_pss_rsae_sha{256,512}
  343. 0x04, 0x01, 0x06, 0x01, 0x08, 0x04, 0x08, 0x06,
  344. # ed25518 ed448 rsa_pss_pss_sha{256,512}
  345. 0x08, 0x07, 0x08, 0x08, 0x08, 0x09, 0x08, 0x0b,
  346. # ecdsa_secp{256,512} rsa+sha1 ecdsa+sha1
  347. 0x04, 0x03, 0x06, 0x03, 0x02, 0x01, 0x02, 0x03;
  348. } elsif ($testtype == SIGALGS_CERT_PKCS) {
  349. $sigs = pack "C10", 0x00, 0x08,
  350. # rsa_pkcs_sha{256,384,512,1}
  351. 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01;
  352. } elsif ($testtype == SIGALGS_CERT_INVALID) {
  353. $sigs = pack "C4", 0x00, 0x02,
  354. # unregistered codepoint
  355. 0xb2, 0x6f;
  356. }
  357. $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS_CERT, $sigs);
  358. $message->repack();
  359. }
  360. }
  361. }
  362. sub modify_cert_verify_sigalg
  363. {
  364. my $proxy = shift;
  365. # We're only interested in the CertificateVerify
  366. if ($proxy->flight != 1) {
  367. return;
  368. }
  369. foreach my $message (@{$proxy->message_list}) {
  370. if ($message->mt == TLSProxy::Message::MT_CERTIFICATE_VERIFY) {
  371. $message->sigalg(TLSProxy::Message::SIG_ALG_RSA_PSS_PSS_SHA256);
  372. $message->repack();
  373. }
  374. }
  375. }