1*e0c4386eSCy Schubert#! /usr/bin/env perl 2*e0c4386eSCy Schubert# Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. 3*e0c4386eSCy Schubert# 4*e0c4386eSCy Schubert# Licensed under the Apache License 2.0 (the "License"). You may not use 5*e0c4386eSCy Schubert# this file except in compliance with the License. You can obtain a copy 6*e0c4386eSCy Schubert# in the file LICENSE in the source distribution or at 7*e0c4386eSCy Schubert# https://www.openssl.org/source/license.html 8*e0c4386eSCy Schubert 9*e0c4386eSCy Schubert 10*e0c4386eSCy Schubertuse strict; 11*e0c4386eSCy Schubertuse warnings; 12*e0c4386eSCy Schubert 13*e0c4386eSCy Schubertuse File::Spec; 14*e0c4386eSCy Schubertuse File::Basename; 15*e0c4386eSCy Schubertuse OpenSSL::Test qw/:DEFAULT with srctop_file bldtop_dir/; 16*e0c4386eSCy Schubertuse OpenSSL::Test::Utils; 17*e0c4386eSCy Schubert 18*e0c4386eSCy Schubertsetup("test_dgst"); 19*e0c4386eSCy Schubert 20*e0c4386eSCy Schubertplan tests => 13; 21*e0c4386eSCy Schubert 22*e0c4386eSCy Schubertsub tsignverify { 23*e0c4386eSCy Schubert my $testtext = shift; 24*e0c4386eSCy Schubert my $privkey = shift; 25*e0c4386eSCy Schubert my $pubkey = shift; 26*e0c4386eSCy Schubert 27*e0c4386eSCy Schubert my $data_to_sign = srctop_file('test', 'data.bin'); 28*e0c4386eSCy Schubert my $other_data = srctop_file('test', 'data2.bin'); 29*e0c4386eSCy Schubert 30*e0c4386eSCy Schubert my $sigfile = basename($privkey, '.pem') . '.sig'; 31*e0c4386eSCy Schubert plan tests => 4; 32*e0c4386eSCy Schubert 33*e0c4386eSCy Schubert ok(run(app(['openssl', 'dgst', '-sign', $privkey, 34*e0c4386eSCy Schubert '-out', $sigfile, 35*e0c4386eSCy Schubert $data_to_sign])), 36*e0c4386eSCy Schubert $testtext.": Generating signature"); 37*e0c4386eSCy Schubert 38*e0c4386eSCy Schubert ok(run(app(['openssl', 'dgst', '-prverify', $privkey, 39*e0c4386eSCy Schubert '-signature', $sigfile, 40*e0c4386eSCy Schubert $data_to_sign])), 41*e0c4386eSCy Schubert $testtext.": Verify signature with private key"); 42*e0c4386eSCy Schubert 43*e0c4386eSCy Schubert ok(run(app(['openssl', 'dgst', '-verify', $pubkey, 44*e0c4386eSCy Schubert '-signature', $sigfile, 45*e0c4386eSCy Schubert $data_to_sign])), 46*e0c4386eSCy Schubert $testtext.": Verify signature with public key"); 47*e0c4386eSCy Schubert 48*e0c4386eSCy Schubert ok(!run(app(['openssl', 'dgst', '-verify', $pubkey, 49*e0c4386eSCy Schubert '-signature', $sigfile, 50*e0c4386eSCy Schubert $other_data])), 51*e0c4386eSCy Schubert $testtext.": Expect failure verifying mismatching data"); 52*e0c4386eSCy Schubert} 53*e0c4386eSCy Schubert 54*e0c4386eSCy Schubertsub tsignverify_sha512 { 55*e0c4386eSCy Schubert my $testtext = shift; 56*e0c4386eSCy Schubert my $privkey = shift; 57*e0c4386eSCy Schubert my $pubkey = shift; 58*e0c4386eSCy Schubert 59*e0c4386eSCy Schubert my $data_to_sign = srctop_file('test', 'data.bin'); 60*e0c4386eSCy Schubert my $other_data = srctop_file('test', 'data2.bin'); 61*e0c4386eSCy Schubert 62*e0c4386eSCy Schubert my $sigfile = basename($privkey, '.pem') . '.sig'; 63*e0c4386eSCy Schubert plan tests => 5; 64*e0c4386eSCy Schubert 65*e0c4386eSCy Schubert ok(run(app(['openssl', 'sha512', '-sign', $privkey, 66*e0c4386eSCy Schubert '-out', $sigfile, 67*e0c4386eSCy Schubert $data_to_sign])), 68*e0c4386eSCy Schubert $testtext.": Generating signature using sha512 command"); 69*e0c4386eSCy Schubert 70*e0c4386eSCy Schubert ok(run(app(['openssl', 'sha512', '-verify', $pubkey, 71*e0c4386eSCy Schubert '-signature', $sigfile, 72*e0c4386eSCy Schubert $data_to_sign])), 73*e0c4386eSCy Schubert $testtext.": Verify signature with public key using sha512 command"); 74*e0c4386eSCy Schubert 75*e0c4386eSCy Schubert ok(run(app(['openssl', 'dgst', '-sha512', '-prverify', $privkey, 76*e0c4386eSCy Schubert '-signature', $sigfile, 77*e0c4386eSCy Schubert $data_to_sign])), 78*e0c4386eSCy Schubert $testtext.": Verify signature with private key"); 79*e0c4386eSCy Schubert 80*e0c4386eSCy Schubert ok(run(app(['openssl', 'dgst', '-sha512', '-verify', $pubkey, 81*e0c4386eSCy Schubert '-signature', $sigfile, 82*e0c4386eSCy Schubert $data_to_sign])), 83*e0c4386eSCy Schubert $testtext.": Verify signature with public key"); 84*e0c4386eSCy Schubert 85*e0c4386eSCy Schubert ok(!run(app(['openssl', 'dgst', '-sha512', '-verify', $pubkey, 86*e0c4386eSCy Schubert '-signature', $sigfile, 87*e0c4386eSCy Schubert $other_data])), 88*e0c4386eSCy Schubert $testtext.": Expect failure verifying mismatching data"); 89*e0c4386eSCy Schubert} 90*e0c4386eSCy Schubert 91*e0c4386eSCy SchubertSKIP: { 92*e0c4386eSCy Schubert skip "RSA is not supported by this OpenSSL build", 1 93*e0c4386eSCy Schubert if disabled("rsa"); 94*e0c4386eSCy Schubert 95*e0c4386eSCy Schubert subtest "RSA signature generation and verification with `dgst` CLI" => sub { 96*e0c4386eSCy Schubert tsignverify("RSA", 97*e0c4386eSCy Schubert srctop_file("test","testrsa.pem"), 98*e0c4386eSCy Schubert srctop_file("test","testrsapub.pem")); 99*e0c4386eSCy Schubert }; 100*e0c4386eSCy Schubert 101*e0c4386eSCy Schubert subtest "RSA signature generation and verification with `sha512` CLI" => sub { 102*e0c4386eSCy Schubert tsignverify_sha512("RSA", 103*e0c4386eSCy Schubert srctop_file("test","testrsa2048.pem"), 104*e0c4386eSCy Schubert srctop_file("test","testrsa2048pub.pem")); 105*e0c4386eSCy Schubert }; 106*e0c4386eSCy Schubert} 107*e0c4386eSCy Schubert 108*e0c4386eSCy SchubertSKIP: { 109*e0c4386eSCy Schubert skip "DSA is not supported by this OpenSSL build", 1 110*e0c4386eSCy Schubert if disabled("dsa"); 111*e0c4386eSCy Schubert 112*e0c4386eSCy Schubert subtest "DSA signature generation and verification with `dgst` CLI" => sub { 113*e0c4386eSCy Schubert tsignverify("DSA", 114*e0c4386eSCy Schubert srctop_file("test","testdsa.pem"), 115*e0c4386eSCy Schubert srctop_file("test","testdsapub.pem")); 116*e0c4386eSCy Schubert }; 117*e0c4386eSCy Schubert} 118*e0c4386eSCy Schubert 119*e0c4386eSCy SchubertSKIP: { 120*e0c4386eSCy Schubert skip "ECDSA is not supported by this OpenSSL build", 1 121*e0c4386eSCy Schubert if disabled("ec"); 122*e0c4386eSCy Schubert 123*e0c4386eSCy Schubert subtest "ECDSA signature generation and verification with `dgst` CLI" => sub { 124*e0c4386eSCy Schubert tsignverify("ECDSA", 125*e0c4386eSCy Schubert srctop_file("test","testec-p256.pem"), 126*e0c4386eSCy Schubert srctop_file("test","testecpub-p256.pem")); 127*e0c4386eSCy Schubert }; 128*e0c4386eSCy Schubert} 129*e0c4386eSCy Schubert 130*e0c4386eSCy SchubertSKIP: { 131*e0c4386eSCy Schubert skip "EdDSA is not supported by this OpenSSL build", 2 132*e0c4386eSCy Schubert if disabled("ec"); 133*e0c4386eSCy Schubert 134*e0c4386eSCy Schubert skip "EdDSA is not supported with `dgst` CLI", 2; 135*e0c4386eSCy Schubert 136*e0c4386eSCy Schubert subtest "Ed25519 signature generation and verification with `dgst` CLI" => sub { 137*e0c4386eSCy Schubert tsignverify("Ed25519", 138*e0c4386eSCy Schubert srctop_file("test","tested25519.pem"), 139*e0c4386eSCy Schubert srctop_file("test","tested25519pub.pem")); 140*e0c4386eSCy Schubert }; 141*e0c4386eSCy Schubert 142*e0c4386eSCy Schubert subtest "Ed448 signature generation and verification with `dgst` CLI" => sub { 143*e0c4386eSCy Schubert tsignverify("Ed448", 144*e0c4386eSCy Schubert srctop_file("test","tested448.pem"), 145*e0c4386eSCy Schubert srctop_file("test","tested448pub.pem")); 146*e0c4386eSCy Schubert }; 147*e0c4386eSCy Schubert} 148*e0c4386eSCy Schubert 149*e0c4386eSCy SchubertSKIP: { 150*e0c4386eSCy Schubert skip "dgst with engine is not supported by this OpenSSL build", 1 151*e0c4386eSCy Schubert if disabled("engine") || disabled("dynamic-engine"); 152*e0c4386eSCy Schubert 153*e0c4386eSCy Schubert subtest "SHA1 generation by engine with `dgst` CLI" => sub { 154*e0c4386eSCy Schubert plan tests => 1; 155*e0c4386eSCy Schubert 156*e0c4386eSCy Schubert my $testdata = srctop_file('test', 'data.bin'); 157*e0c4386eSCy Schubert # intentionally using -engine twice, please do not remove the duplicate line 158*e0c4386eSCy Schubert my @macdata = run(app(['openssl', 'dgst', '-sha1', 159*e0c4386eSCy Schubert '-engine', "ossltest", 160*e0c4386eSCy Schubert '-engine', "ossltest", 161*e0c4386eSCy Schubert $testdata]), capture => 1); 162*e0c4386eSCy Schubert chomp(@macdata); 163*e0c4386eSCy Schubert my $expected = qr/SHA1\(\Q$testdata\E\)= 000102030405060708090a0b0c0d0e0f10111213/; 164*e0c4386eSCy Schubert ok($macdata[0] =~ $expected, "SHA1: Check HASH value is as expected ($macdata[0]) vs ($expected)"); 165*e0c4386eSCy Schubert } 166*e0c4386eSCy Schubert} 167*e0c4386eSCy Schubert 168*e0c4386eSCy Schubertsubtest "HMAC generation with `dgst` CLI" => sub { 169*e0c4386eSCy Schubert plan tests => 2; 170*e0c4386eSCy Schubert 171*e0c4386eSCy Schubert my $testdata = srctop_file('test', 'data.bin'); 172*e0c4386eSCy Schubert #HMAC the data twice to check consistency 173*e0c4386eSCy Schubert my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-hmac', '123456', 174*e0c4386eSCy Schubert $testdata, $testdata]), capture => 1); 175*e0c4386eSCy Schubert chomp(@hmacdata); 176*e0c4386eSCy Schubert my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/; 177*e0c4386eSCy Schubert ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)"); 178*e0c4386eSCy Schubert ok($hmacdata[1] =~ $expected, 179*e0c4386eSCy Schubert "HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)"); 180*e0c4386eSCy Schubert}; 181*e0c4386eSCy Schubert 182*e0c4386eSCy Schubertsubtest "HMAC generation with `dgst` CLI, default digest" => sub { 183*e0c4386eSCy Schubert plan tests => 2; 184*e0c4386eSCy Schubert 185*e0c4386eSCy Schubert my $testdata = srctop_file('test', 'data.bin'); 186*e0c4386eSCy Schubert #HMAC the data twice to check consistency 187*e0c4386eSCy Schubert my @hmacdata = run(app(['openssl', 'dgst', '-hmac', '123456', 188*e0c4386eSCy Schubert $testdata, $testdata]), capture => 1); 189*e0c4386eSCy Schubert chomp(@hmacdata); 190*e0c4386eSCy Schubert my $expected = qr/HMAC-SHA256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/; 191*e0c4386eSCy Schubert ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)"); 192*e0c4386eSCy Schubert ok($hmacdata[1] =~ $expected, 193*e0c4386eSCy Schubert "HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)"); 194*e0c4386eSCy Schubert}; 195*e0c4386eSCy Schubert 196*e0c4386eSCy Schubertsubtest "HMAC generation with `dgst` CLI, key via option" => sub { 197*e0c4386eSCy Schubert plan tests => 2; 198*e0c4386eSCy Schubert 199*e0c4386eSCy Schubert my $testdata = srctop_file('test', 'data.bin'); 200*e0c4386eSCy Schubert #HMAC the data twice to check consistency 201*e0c4386eSCy Schubert my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-hmac', 202*e0c4386eSCy Schubert '-macopt', 'hexkey:FFFF', 203*e0c4386eSCy Schubert $testdata, $testdata]), capture => 1); 204*e0c4386eSCy Schubert chomp(@hmacdata); 205*e0c4386eSCy Schubert my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= b6727b7bb251dfa65846e0a8223bdd57d244aa6d7e312cb906d8e21f2dee3a57/; 206*e0c4386eSCy Schubert ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)"); 207*e0c4386eSCy Schubert ok($hmacdata[1] =~ $expected, 208*e0c4386eSCy Schubert "HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)"); 209*e0c4386eSCy Schubert}; 210*e0c4386eSCy Schubert 211*e0c4386eSCy Schubertsubtest "Custom length XOF digest generation with `dgst` CLI" => sub { 212*e0c4386eSCy Schubert plan tests => 2; 213*e0c4386eSCy Schubert 214*e0c4386eSCy Schubert my $testdata = srctop_file('test', 'data.bin'); 215*e0c4386eSCy Schubert #Digest the data twice to check consistency 216*e0c4386eSCy Schubert my @xofdata = run(app(['openssl', 'dgst', '-shake128', '-xoflen', '64', 217*e0c4386eSCy Schubert $testdata, $testdata]), capture => 1); 218*e0c4386eSCy Schubert chomp(@xofdata); 219*e0c4386eSCy Schubert my $expected = qr/SHAKE-128\(\Q$testdata\E\)= bb565dac72640109e1c926ef441d3fa64ffd0b3e2bf8cd73d5182dfba19b6a8a2eab96d2df854b647b3795ef090582abe41ba4e0717dc4df40bc4e17d88e4677/; 220*e0c4386eSCy Schubert ok($xofdata[0] =~ $expected, "XOF: Check digest value is as expected ($xofdata[0]) vs ($expected)"); 221*e0c4386eSCy Schubert ok($xofdata[1] =~ $expected, 222*e0c4386eSCy Schubert "XOF: Check second digest value is consistent with the first ($xofdata[1]) vs ($expected)"); 223*e0c4386eSCy Schubert}; 224*e0c4386eSCy Schubert 225*e0c4386eSCy Schubertsubtest "SHAKE digest generation with no xoflen set `dgst` CLI" => sub { 226*e0c4386eSCy Schubert plan tests => 1; 227*e0c4386eSCy Schubert 228*e0c4386eSCy Schubert my $testdata = srctop_file('test', 'data.bin'); 229*e0c4386eSCy Schubert my @xofdata = run(app(['openssl', 'dgst', '-shake128', $testdata], stderr => "outerr.txt"), capture => 1); 230*e0c4386eSCy Schubert chomp(@xofdata); 231*e0c4386eSCy Schubert my $expected = qr/SHAKE-128\(\Q$testdata\E\)= bb565dac72640109e1c926ef441d3fa6/; 232*e0c4386eSCy Schubert ok($xofdata[0] =~ $expected, "Check short digest is output"); 233*e0c4386eSCy Schubert}; 234*e0c4386eSCy Schubert 235*e0c4386eSCy SchubertSKIP: { 236*e0c4386eSCy Schubert skip "ECDSA is not supported by this OpenSSL build", 1 237*e0c4386eSCy Schubert if disabled("ec"); 238*e0c4386eSCy Schubert 239*e0c4386eSCy Schubert subtest "signing with xoflen is not supported `dgst` CLI" => sub { 240*e0c4386eSCy Schubert plan tests => 1; 241*e0c4386eSCy Schubert my $data_to_sign = srctop_file('test', 'data.bin'); 242*e0c4386eSCy Schubert 243*e0c4386eSCy Schubert ok(!run(app(['openssl', 'dgst', '-shake256', '-xoflen', '64', 244*e0c4386eSCy Schubert '-sign', srctop_file("test","testec-p256.pem"), 245*e0c4386eSCy Schubert '-out', 'test.sig', 246*e0c4386eSCy Schubert srctop_file('test', 'data.bin')])), 247*e0c4386eSCy Schubert "Generating signature with xoflen should fail"); 248*e0c4386eSCy Schubert } 249*e0c4386eSCy Schubert} 250