1e1051a39Sopenharmony_ci#! /usr/bin/env perl 2e1051a39Sopenharmony_ci# Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci# 4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci# this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ciuse strict; 11e1051a39Sopenharmony_ciuse warnings; 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ciuse OpenSSL::Test; 14e1051a39Sopenharmony_ciuse OpenSSL::Test::Utils; 15e1051a39Sopenharmony_ciuse Storable qw(dclone); 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_cisetup("test_mac"); 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_cimy @mac_tests = ( 20e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -digest SHA1 -macopt hexkey:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F}], 21e1051a39Sopenharmony_ci type => 'HMAC', 22e1051a39Sopenharmony_ci input => unpack("H*", "Sample message for keylen=blocklen"), 23e1051a39Sopenharmony_ci expected => '5FD596EE78D5553C8FF4E72D266DFD192366DA29', 24e1051a39Sopenharmony_ci desc => 'HMAC SHA1' }, 25e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt digest:SHA1 -macopt hexkey:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F}], 26e1051a39Sopenharmony_ci type => 'HMAC', 27e1051a39Sopenharmony_ci input => unpack("H*", "Sample message for keylen=blocklen"), 28e1051a39Sopenharmony_ci expected => '5FD596EE78D5553C8FF4E72D266DFD192366DA29', 29e1051a39Sopenharmony_ci desc => 'HMAC SHA1 via -macopt' }, 30e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -cipher AES-256-GCM -macopt hexkey:4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5 -macopt hexiv:7AE8E2CA4EC500012E58495C}], 31e1051a39Sopenharmony_ci type => 'GMAC', 32e1051a39Sopenharmony_ci input => '68F2E77696CE7AE8E2CA4EC588E541002E58495C08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D0007', 33e1051a39Sopenharmony_ci expected => '00BDA1B7E87608BCBF470F12157F4C07', 34e1051a39Sopenharmony_ci desc => 'GMAC' }, 35e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt cipher:AES-256-GCM -macopt hexkey:4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5 -macopt hexiv:7AE8E2CA4EC500012E58495C}], 36e1051a39Sopenharmony_ci type => 'GMAC', 37e1051a39Sopenharmony_ci input => '68F2E77696CE7AE8E2CA4EC588E541002E58495C08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D0007', 38e1051a39Sopenharmony_ci expected => '00BDA1B7E87608BCBF470F12157F4C07', 39e1051a39Sopenharmony_ci desc => 'GMAC via -macopt' }, 40e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt hexkey:404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F -macopt xof:0}], 41e1051a39Sopenharmony_ci type => 'KMAC128', 42e1051a39Sopenharmony_ci input => '00010203', 43e1051a39Sopenharmony_ci expected => 'E5780B0D3EA6F7D3A429C5706AA43A00FADBD7D49628839E3187243F456EE14E', 44e1051a39Sopenharmony_ci desc => 'KMAC128' }, 45e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt hexkey:404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F -macopt }, 'custom:My Tagged Application'], 46e1051a39Sopenharmony_ci type => 'KMAC256', 47e1051a39Sopenharmony_ci input => '00010203', 48e1051a39Sopenharmony_ci expected => '20C570C31346F703C9AC36C61C03CB64C3970D0CFC787E9B79599D273A68D2F7F69D4CC3DE9D104A351689F27CF6F5951F0103F33F4F24871024D9C27773A8DD', 49e1051a39Sopenharmony_ci desc => 'KMAC256' }, 50e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt hexkey:404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F -macopt xof:1 -macopt}, 'custom:My Tagged Application'], 51e1051a39Sopenharmony_ci type => 'KMAC256', 52e1051a39Sopenharmony_ci input => '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7', 53e1051a39Sopenharmony_ci expected => 'D5BE731C954ED7732846BB59DBE3A8E30F83E77A4BFF4459F2F1C2B4ECEBB8CE67BA01C62E8AB8578D2D499BD1BB276768781190020A306A97DE281DCC30305D', 54e1051a39Sopenharmony_ci desc => 'KMAC256 with xof len of 64' }, 55e1051a39Sopenharmony_ci); 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_cimy @siphash_tests = ( 58e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt hexkey:000102030405060708090A0B0C0D0E0F}], 59e1051a39Sopenharmony_ci type => 'SipHash', 60e1051a39Sopenharmony_ci input => '00', 61e1051a39Sopenharmony_ci expected => 'da87c1d86b99af44347659119b22fc45', 62e1051a39Sopenharmony_ci desc => 'SipHash No input' } 63e1051a39Sopenharmony_ci); 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_cimy @cmac_tests = ( 66e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -cipher AES-256-CBC -macopt hexkey:0B122AC8F34ED1FE082A3625D157561454167AC145A10BBF77C6A70596D574F1}], 67e1051a39Sopenharmony_ci type => 'CMAC', 68e1051a39Sopenharmony_ci input => '498B53FDEC87EDCBF07097DCCDE93A084BAD7501A224E388DF349CE18959FE8485F8AD1537F0D896EA73BEDC7214713F', 69e1051a39Sopenharmony_ci expected => 'F62C46329B41085625669BAF51DEA66A', 70e1051a39Sopenharmony_ci desc => 'CMAC AES-256-CBC' }, 71e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt cipher:AES-256-CBC -macopt hexkey:0B122AC8F34ED1FE082A3625D157561454167AC145A10BBF77C6A70596D574F1}], 72e1051a39Sopenharmony_ci type => 'CMAC', 73e1051a39Sopenharmony_ci input => '498B53FDEC87EDCBF07097DCCDE93A084BAD7501A224E388DF349CE18959FE8485F8AD1537F0D896EA73BEDC7214713F', 74e1051a39Sopenharmony_ci expected => 'F62C46329B41085625669BAF51DEA66A', 75e1051a39Sopenharmony_ci desc => 'CMAC AES-256-CBC' }, 76e1051a39Sopenharmony_ci); 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_cimy @poly1305_tests = ( 79e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -macopt hexkey:02000000000000000000000000000000ffffffffffffffffffffffffffffffff}], 80e1051a39Sopenharmony_ci type => 'Poly1305', 81e1051a39Sopenharmony_ci input => '02000000000000000000000000000000', 82e1051a39Sopenharmony_ci expected => '03000000000000000000000000000000', 83e1051a39Sopenharmony_ci desc => 'Poly1305 (wrap 2^128)' }, 84e1051a39Sopenharmony_ci); 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_cipush @mac_tests, @siphash_tests unless disabled("siphash"); 87e1051a39Sopenharmony_cipush @mac_tests, @cmac_tests unless disabled("cmac"); 88e1051a39Sopenharmony_cipush @mac_tests, @poly1305_tests unless disabled("poly1305"); 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_cimy @mac_fail_tests = ( 91e1051a39Sopenharmony_ci { cmd => [qw{openssl mac}], 92e1051a39Sopenharmony_ci type => 'KMAC128', 93e1051a39Sopenharmony_ci input => '00', 94e1051a39Sopenharmony_ci err => 'EVP_MAC_Init', 95e1051a39Sopenharmony_ci desc => 'KMAC128 Fail no key' }, 96e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -propquery unknown -macopt hexkey:404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F}], 97e1051a39Sopenharmony_ci type => 'KMAC128', 98e1051a39Sopenharmony_ci input => '00', 99e1051a39Sopenharmony_ci err => 'Invalid MAC name KMAC128', 100e1051a39Sopenharmony_ci desc => 'KMAC128 Fail unknown property' }, 101e1051a39Sopenharmony_ci { cmd => [qw{openssl mac -cipher AES-128-CBC -macopt hexkey:00}], 102e1051a39Sopenharmony_ci type => 'HMAC', 103e1051a39Sopenharmony_ci input => '00', 104e1051a39Sopenharmony_ci err => 'MAC parameter error', 105e1051a39Sopenharmony_ci desc => 'HMAC given a cipher' }, 106e1051a39Sopenharmony_ci); 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_cimy @siphash_fail_tests = ( 109e1051a39Sopenharmony_ci { cmd => [qw{openssl mac}], 110e1051a39Sopenharmony_ci type => 'SipHash', 111e1051a39Sopenharmony_ci input => '00', 112e1051a39Sopenharmony_ci err => '', 113e1051a39Sopenharmony_ci desc => 'SipHash Fail no key' }, 114e1051a39Sopenharmony_ci); 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_cipush @mac_fail_tests, @siphash_fail_tests unless disabled("siphash"); 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ciplan tests => (scalar @mac_tests * 2) + scalar @mac_fail_tests; 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_cimy $test_count = 0; 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ciforeach (@mac_tests) { 123e1051a39Sopenharmony_ci $test_count++; 124e1051a39Sopenharmony_ci ok(compareline($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{err}), $_->{desc}); 125e1051a39Sopenharmony_ci} 126e1051a39Sopenharmony_ciforeach (@mac_tests) { 127e1051a39Sopenharmony_ci $test_count++; 128e1051a39Sopenharmony_ci ok(comparefile($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}), $_->{desc}); 129e1051a39Sopenharmony_ci} 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ciforeach (@mac_fail_tests) { 132e1051a39Sopenharmony_ci $test_count++; 133e1051a39Sopenharmony_ci ok(compareline($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{err}), $_->{desc}); 134e1051a39Sopenharmony_ci} 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci# Create a temp input file and save the input data into it, and 137e1051a39Sopenharmony_ci# then compare the stdout output matches the expected value. 138e1051a39Sopenharmony_cisub compareline { 139e1051a39Sopenharmony_ci my $tmpfile = "input-$test_count.bin"; 140e1051a39Sopenharmony_ci my ($cmdarray_orig, $type, $input, $expect, $err) = @_; 141e1051a39Sopenharmony_ci my $cmdarray = dclone $cmdarray_orig; 142e1051a39Sopenharmony_ci if (defined($expect)) { 143e1051a39Sopenharmony_ci $expect = uc $expect; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci # Open a temporary input file and write $input to it 146e1051a39Sopenharmony_ci open(my $in, '>', $tmpfile) or die "Could not open file"; 147e1051a39Sopenharmony_ci binmode($in); 148e1051a39Sopenharmony_ci my $bin = pack("H*", $input); 149e1051a39Sopenharmony_ci print $in $bin; 150e1051a39Sopenharmony_ci close $in; 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci # The last cmd parameter is the temporary input file we just created. 153e1051a39Sopenharmony_ci my @other = ('-in', $tmpfile, $type); 154e1051a39Sopenharmony_ci push @$cmdarray, @other; 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci my @lines = run(app($cmdarray), capture => 1); 157e1051a39Sopenharmony_ci # Not unlinking $tmpfile 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci if (defined($expect)) { 160e1051a39Sopenharmony_ci if ($lines[0] =~ m|^\Q${expect}\E\R$|) { 161e1051a39Sopenharmony_ci return 1; 162e1051a39Sopenharmony_ci } else { 163e1051a39Sopenharmony_ci print "Got: $lines[0]"; 164e1051a39Sopenharmony_ci print "Exp: $expect\n"; 165e1051a39Sopenharmony_ci return 0; 166e1051a39Sopenharmony_ci } 167e1051a39Sopenharmony_ci } 168e1051a39Sopenharmony_ci if (defined($err)) { 169e1051a39Sopenharmony_ci if (defined($lines[0])) { 170e1051a39Sopenharmony_ci $lines[0] =~ s/\s+$//; 171e1051a39Sopenharmony_ci if ($lines[0] eq $err) { 172e1051a39Sopenharmony_ci return 1; 173e1051a39Sopenharmony_ci } else { 174e1051a39Sopenharmony_ci print "Got: $lines[0]"; 175e1051a39Sopenharmony_ci print "Exp: $err\n"; 176e1051a39Sopenharmony_ci return 0; 177e1051a39Sopenharmony_ci } 178e1051a39Sopenharmony_ci } else { 179e1051a39Sopenharmony_ci # expected an error 180e1051a39Sopenharmony_ci return 1; 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci } 183e1051a39Sopenharmony_ci return 0; 184e1051a39Sopenharmony_ci} 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci# Create a temp input file and save the input data into it, and 187e1051a39Sopenharmony_ci# use the '-bin -out <file>' commandline options to save results out to a file. 188e1051a39Sopenharmony_ci# Read this file back in and check its output matches the expected value. 189e1051a39Sopenharmony_cisub comparefile { 190e1051a39Sopenharmony_ci my $tmpfile = "input-$test_count.bin"; 191e1051a39Sopenharmony_ci my $outfile = "output-$test_count.bin"; 192e1051a39Sopenharmony_ci my ($cmdarray, $type, $input, $expect) = @_; 193e1051a39Sopenharmony_ci $expect = uc $expect; 194e1051a39Sopenharmony_ci 195e1051a39Sopenharmony_ci # Open a temporary input file and write $input to it 196e1051a39Sopenharmony_ci open(my $in, '>', $tmpfile) or die "Could not open file"; 197e1051a39Sopenharmony_ci binmode($in); 198e1051a39Sopenharmony_ci my $bin = pack("H*", $input); 199e1051a39Sopenharmony_ci print $in $bin; 200e1051a39Sopenharmony_ci close $in; 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci my @other = ("-binary", "-in", $tmpfile, "-out", $outfile, $type); 203e1051a39Sopenharmony_ci push @$cmdarray, @other; 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci run(app($cmdarray)); 206e1051a39Sopenharmony_ci # Not unlinking $tmpfile 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_ci open(my $out, '<', $outfile) or die "Could not open file"; 209e1051a39Sopenharmony_ci binmode($out); 210e1051a39Sopenharmony_ci my $buffer; 211e1051a39Sopenharmony_ci my $BUFSIZE = 1024; 212e1051a39Sopenharmony_ci read($out, $buffer, $BUFSIZE) or die "unable to read"; 213e1051a39Sopenharmony_ci my $line = uc unpack("H*", $buffer); 214e1051a39Sopenharmony_ci close($out); 215e1051a39Sopenharmony_ci # Not unlinking $outfile 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if ($line eq $expect) { 218e1051a39Sopenharmony_ci return 1; 219e1051a39Sopenharmony_ci } else { 220e1051a39Sopenharmony_ci print "Got: $line\n"; 221e1051a39Sopenharmony_ci print "Exp: $expect\n"; 222e1051a39Sopenharmony_ci return 0; 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci} 225