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