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