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