1 | #! /usr/bin/env perl
|
---|
2 | # Copyright 2020-2022 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 qw(:DEFAULT data_file srctop_file);
|
---|
14 | use OpenSSL::Test::Utils;
|
---|
15 |
|
---|
16 | #Tests for the dhparam CLI application
|
---|
17 |
|
---|
18 | setup("test_dhparam");
|
---|
19 |
|
---|
20 | plan skip_all => "DH is not supported in this build"
|
---|
21 | if disabled("dh");
|
---|
22 | plan tests => 21;
|
---|
23 |
|
---|
24 | my $fipsconf = srctop_file("test", "fips-and-base.cnf");
|
---|
25 |
|
---|
26 | sub checkdhparams {
|
---|
27 | my $file = shift; #Filename containing params
|
---|
28 | my $type = shift; #PKCS3 or X9.42?
|
---|
29 | my $gen = shift; #2, 5 or something else (0 is "something else")?
|
---|
30 | my $format = shift; #DER or PEM?
|
---|
31 | my $bits = shift; #Number of bits in p
|
---|
32 | my $keybits = shift; #Recommended private key bits
|
---|
33 | my $pemtype;
|
---|
34 | my $readtype;
|
---|
35 | my $readbits = 0;
|
---|
36 | my $genline;
|
---|
37 |
|
---|
38 | if (-T $file) {
|
---|
39 | #Text file. Check it looks like PEM
|
---|
40 | open(PEMFILE, '<', $file) or die $!;
|
---|
41 | if (my $firstline = <PEMFILE>) {
|
---|
42 | $firstline =~ s/\R$//;
|
---|
43 | if ($firstline eq "-----BEGIN DH PARAMETERS-----") {
|
---|
44 | $pemtype = "PKCS3";
|
---|
45 | } elsif ($firstline eq "-----BEGIN X9.42 DH PARAMETERS-----") {
|
---|
46 | $pemtype = "X9.42";
|
---|
47 | } else {
|
---|
48 | $pemtype = "";
|
---|
49 | }
|
---|
50 | } else {
|
---|
51 | $pemtype = "";
|
---|
52 | }
|
---|
53 | close(PEMFILE);
|
---|
54 | ok(($format eq "PEM") && defined $pemtype, "Checking format is PEM");
|
---|
55 | } else {
|
---|
56 | ok($format eq "DER", "Checking format is DER");
|
---|
57 | #No PEM type in this case, so we just set the pemtype to the expected
|
---|
58 | #type so that we never fail that part of the test
|
---|
59 | $pemtype = $type;
|
---|
60 | }
|
---|
61 | my @textdata = run(app(['openssl', 'dhparam', '-in', $file, '-noout',
|
---|
62 | '-text', '-inform', $format]), capture => 1);
|
---|
63 | chomp(@textdata);
|
---|
64 | #Trim trailing whitespace
|
---|
65 | @textdata = grep { s/\s*$//g } @textdata;
|
---|
66 | if (grep { $_ =~ 'Q:' } @textdata) {
|
---|
67 | $readtype = "X9.42";
|
---|
68 | } else {
|
---|
69 | $readtype = "PKCS3";
|
---|
70 | }
|
---|
71 | ok(($type eq $pemtype) && ($type eq $readtype),
|
---|
72 | "Checking parameter type is ".$type." ($pemtype, $readtype)");
|
---|
73 |
|
---|
74 | if (defined $textdata[0] && $textdata[0] =~ /DH Parameters: \((\d+) bit\)/) {
|
---|
75 | $readbits = $1;
|
---|
76 | }
|
---|
77 | ok($bits == $readbits, "Checking number of bits is $bits");
|
---|
78 | if ($gen == 2 || $gen == 5) {
|
---|
79 | #For generators 2 and 5 the value appears on the same line
|
---|
80 | $genline = "G: $gen (0x$gen)";
|
---|
81 | } else {
|
---|
82 | #For any other generator the value appears on the following line
|
---|
83 | $genline = "G:";
|
---|
84 | }
|
---|
85 |
|
---|
86 | ok((grep { (index($_, $genline) + length ($genline)) == length ($_)} @textdata),
|
---|
87 | "Checking generator is correct");
|
---|
88 |
|
---|
89 | if ($keybits) {
|
---|
90 | my $keybits_line = "recommended-private-length: $keybits bits";
|
---|
91 | ok((grep { (index($_, $keybits_line) + length($keybits_line))
|
---|
92 | == length($_) } @textdata),
|
---|
93 | "Checking recommended private key bits is correct");
|
---|
94 | }
|
---|
95 | }
|
---|
96 |
|
---|
97 | #Test some "known good" parameter files to check that we can read them
|
---|
98 | subtest "Read: 1024 bit PKCS3 params, generator 2, PEM file" => sub {
|
---|
99 | plan tests => 4;
|
---|
100 | checkdhparams(data_file("pkcs3-2-1024.pem"), "PKCS3", 2, "PEM", 1024);
|
---|
101 | };
|
---|
102 | subtest "Read: 1024 bit PKCS3 params, generator 5, PEM file" => sub {
|
---|
103 | plan tests => 4;
|
---|
104 | checkdhparams(data_file("pkcs3-5-1024.pem"), "PKCS3", 5, "PEM", 1024);
|
---|
105 | };
|
---|
106 | subtest "Read: 2048 bit PKCS3 params, generator 2, PEM file" => sub {
|
---|
107 | plan tests => 4;
|
---|
108 | checkdhparams(data_file("pkcs3-2-2048.pem"), "PKCS3", 2, "PEM", 2048);
|
---|
109 | };
|
---|
110 | subtest "Read: 1024 bit X9.42 params, PEM file" => sub {
|
---|
111 | plan tests => 4;
|
---|
112 | checkdhparams(data_file("x942-0-1024.pem"), "X9.42", 0, "PEM", 1024);
|
---|
113 | };
|
---|
114 | subtest "Read: 1024 bit PKCS3 params, generator 2, DER file" => sub {
|
---|
115 | plan tests => 4;
|
---|
116 | checkdhparams(data_file("pkcs3-2-1024.der"), "PKCS3", 2, "DER", 1024);
|
---|
117 | };
|
---|
118 | subtest "Read: 1024 bit PKCS3 params, generator 5, DER file" => sub {
|
---|
119 | plan tests => 4;
|
---|
120 | checkdhparams(data_file("pkcs3-5-1024.der"), "PKCS3", 5, "DER", 1024);
|
---|
121 | };
|
---|
122 | subtest "Read: 2048 bit PKCS3 params, generator 2, DER file" => sub {
|
---|
123 | plan tests => 4;
|
---|
124 | checkdhparams(data_file("pkcs3-2-2048.der"), "PKCS3", 2, "DER", 2048);
|
---|
125 | };
|
---|
126 | subtest "Read: 1024 bit X9.42 params, DER file" => sub {
|
---|
127 | checkdhparams(data_file("x942-0-1024.der"), "X9.42", 0, "DER", 1024);
|
---|
128 | };
|
---|
129 |
|
---|
130 | #Test that generating parameters of different types creates what we expect. We
|
---|
131 | #use 512 for the size for speed reasons. Don't use this in real applications!
|
---|
132 | subtest "Generate: 512 bit PKCS3 params, generator 2, PEM file" => sub {
|
---|
133 | plan tests => 6;
|
---|
134 | ok(run(app([ 'openssl', 'dhparam', '-out', 'gen-pkcs3-2-512.pem',
|
---|
135 | '512' ])));
|
---|
136 | checkdhparams("gen-pkcs3-2-512.pem", "PKCS3", 2, "PEM", 512, 125);
|
---|
137 | };
|
---|
138 | subtest "Generate: 512 bit PKCS3 params, explicit generator 2, PEM file" => sub {
|
---|
139 | plan tests => 6;
|
---|
140 | ok(run(app([ 'openssl', 'dhparam', '-out', 'gen-pkcs3-exp2-512.pem', '-2',
|
---|
141 | '512' ])));
|
---|
142 | checkdhparams("gen-pkcs3-exp2-512.pem", "PKCS3", 2, "PEM", 512, 125);
|
---|
143 | };
|
---|
144 | subtest "Generate: 512 bit PKCS3 params, generator 5, PEM file" => sub {
|
---|
145 | plan tests => 6;
|
---|
146 | ok(run(app([ 'openssl', 'dhparam', '-out', 'gen-pkcs3-5-512.pem', '-5',
|
---|
147 | '512' ])));
|
---|
148 | checkdhparams("gen-pkcs3-5-512.pem", "PKCS3", 5, "PEM", 512, 125);
|
---|
149 | };
|
---|
150 | subtest "Generate: 512 bit PKCS3 params, generator 2, explicit PEM file" => sub {
|
---|
151 | plan tests => 6;
|
---|
152 | ok(run(app([ 'openssl', 'dhparam', '-out', 'gen-pkcs3-2-512.exp.pem',
|
---|
153 | '-outform', 'PEM', '512' ])));
|
---|
154 | checkdhparams("gen-pkcs3-2-512.exp.pem", "PKCS3", 2, "PEM", 512, 125);
|
---|
155 | };
|
---|
156 | SKIP: {
|
---|
157 | skip "Skipping tests that require DSA", 4 if disabled("dsa");
|
---|
158 |
|
---|
159 | subtest "Generate: 512 bit X9.42 params, generator 0, PEM file" => sub {
|
---|
160 | plan tests => 5;
|
---|
161 | ok(run(app([ 'openssl', 'dhparam', '-out', 'gen-x942-0-512.pem',
|
---|
162 | '-dsaparam', '512' ])));
|
---|
163 | checkdhparams("gen-x942-0-512.pem", "X9.42", 0, "PEM", 512);
|
---|
164 | };
|
---|
165 | subtest "Generate: 512 bit X9.42 params, explicit generator 2, PEM file" => sub {
|
---|
166 | plan tests => 1;
|
---|
167 | #Expected to fail - you cannot select a generator with '-dsaparam'
|
---|
168 | ok(!run(app([ 'openssl', 'dhparam', '-out', 'gen-x942-exp2-512.pem', '-2',
|
---|
169 | '-dsaparam', '512' ])));
|
---|
170 | };
|
---|
171 | subtest "Generate: 512 bit X9.42 params, generator 5, PEM file" => sub {
|
---|
172 | plan tests => 1;
|
---|
173 | #Expected to fail - you cannot select a generator with '-dsaparam'
|
---|
174 | ok(!run(app([ 'openssl', 'dhparam', '-out', 'gen-x942-5-512.pem',
|
---|
175 | '-5', '-dsaparam', '512' ])));
|
---|
176 | };
|
---|
177 | subtest "Generate: 512 bit X9.42 params, generator 0, DER file" => sub {
|
---|
178 | plan tests => 5;
|
---|
179 | ok(run(app([ 'openssl', 'dhparam', '-out', 'gen-x942-0-512.der',
|
---|
180 | '-dsaparam', '-outform', 'DER', '512' ])));
|
---|
181 | checkdhparams("gen-x942-0-512.der", "X9.42", 0, "DER", 512);
|
---|
182 | };
|
---|
183 | }
|
---|
184 | SKIP: {
|
---|
185 | skip "Skipping tests that are only supported in a fips build with security ".
|
---|
186 | "checks", 4 if (disabled("fips") || disabled("fips-securitychecks"));
|
---|
187 |
|
---|
188 | $ENV{OPENSSL_CONF} = $fipsconf;
|
---|
189 |
|
---|
190 | ok(!run(app(['openssl', 'dhparam', '-check', '512'])),
|
---|
191 | "Generating 512 bit DH params should fail in FIPS mode");
|
---|
192 |
|
---|
193 | ok(run(app(['openssl', 'dhparam', '-provider', 'default', '-propquery',
|
---|
194 | '?fips!=yes', '-check', '512'])),
|
---|
195 | "Generating 512 bit DH params should succeed in FIPS mode using".
|
---|
196 | " non-FIPS property query");
|
---|
197 |
|
---|
198 | SKIP: {
|
---|
199 | skip "Skipping tests that require DSA", 2 if disabled("dsa");
|
---|
200 |
|
---|
201 | ok(!run(app(['openssl', 'dhparam', '-dsaparam', '-check', '512'])),
|
---|
202 | "Generating 512 bit DSA-style DH params should fail in FIPS mode");
|
---|
203 |
|
---|
204 | ok(run(app(['openssl', 'dhparam', '-provider', 'default', '-propquery',
|
---|
205 | '?fips!=yes', '-dsaparam', '-check', '512'])),
|
---|
206 | "Generating 512 bit DSA-style DH params should succeed in FIPS".
|
---|
207 | " mode using non-FIPS property query");
|
---|
208 | }
|
---|
209 |
|
---|
210 | delete $ENV{OPENSSL_CONF};
|
---|
211 | }
|
---|
212 |
|
---|
213 | ok(run(app(["openssl", "dhparam", "-noout", "-text"],
|
---|
214 | stdin => data_file("pkcs3-2-1024.pem"))),
|
---|
215 | "stdinbuffer input test that uses BIO_gets");
|
---|