1#! /usr/bin/env perl 2# Copyright 2020-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 10use strict; 11use warnings; 12 13use OpenSSL::Test qw(:DEFAULT data_file srctop_file); 14use OpenSSL::Test::Utils; 15 16#Tests for the dhparam CLI application 17 18setup("test_dhparam"); 19 20plan skip_all => "DH is not supported in this build" 21 if disabled("dh"); 22plan tests => 21; 23 24my $fipsconf = srctop_file("test", "fips-and-base.cnf"); 25 26sub 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 98subtest "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}; 102subtest "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}; 106subtest "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}; 110subtest "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}; 114subtest "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}; 118subtest "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}; 122subtest "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}; 126subtest "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! 132subtest "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}; 138subtest "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}; 144subtest "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}; 150subtest "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}; 156SKIP: { 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} 184SKIP: { 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 213ok(run(app(["openssl", "dhparam", "-noout", "-text"], 214 stdin => data_file("pkcs3-2-1024.pem"))), 215 "stdinbuffer input test that uses BIO_gets"); 216