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