#! /usr/bin/env perl
# -*- mode: perl; -*-
-# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt";
use OpenSSL::Glob;
use OpenSSL::Template;
+use OpenSSL::config;
-# see INSTALL for instructions.
+# see INSTALL.md for instructions.
my $orig_death_handler = $SIG{__DIE__};
$SIG{__DIE__} = \&death_handler;
# 386 generate 80386 code in assembly modules
# no-sse2 disables IA-32 SSE2 code in assembly modules, the above
# mentioned '386' option implies this one
-# no-<cipher> build without specified algorithm (rsa, idea, rc5, ...)
+# no-<cipher> build without specified algorithm (dsa, idea, rc5, ...)
# -<xxx> +<xxx> All options which are unknown to the 'Configure' script are
# /<xxx> passed through to the compiler. Unix-style options beginning
# with a '-' or '+' are recognized, as well as Windows-style
# The numbering used changes from 3.0 and on because we updated
# (solidified) our version numbering scheme at that point.
- # From 3.0 and on, we internalise the given version number in dedcimal
+ # From 3.0 and on, we internalise the given version number in decimal
# as MAJOR * 10000 + MINOR * 100 + 0
"3.0.0" => 30000,
"3.0" => 30000,
"0.9.8" => 908,
};
+# For OpenSSL::config::get_platform
+my %guess_opts = ();
+
+my $dryrun = 0;
+
our %table = ();
our %config = ();
our %withargs = ();
# Unified build supports separate build dir
my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
my $blddir = catdir(absolutedir(".")); # catdir ensures local syntax
+
+# File::Spec::Unix doesn't detect case insensitivity, so we make sure to
+# check if the source and build directory are really the same, and make
+# them so. This avoids all kinds of confusion later on.
+# We must check @File::Spec::ISA rather than using File::Spec->isa() to
+# know if File::Spec ended up loading File::Spec::Unix.
+$srcdir = $blddir
+ if (grep(/::Unix$/, @File::Spec::ISA)
+ && samedir($srcdir, $blddir));
+
my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
-$config{sourcedir} = abs2rel($srcdir);
-$config{builddir} = abs2rel($blddir);
+$config{sourcedir} = abs2rel($srcdir, $blddir);
+$config{builddir} = abs2rel($blddir, $blddir);
+# echo -n 'holy hand grenade of antioch' | openssl sha256
+$config{FIPSKEY} =
+ 'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813';
# Collect reconfiguration information if needed
my @argvcopy=@ARGV;
# 'unshift' adds at the front of the list (i.e. in reverse input order).
foreach ( reverse sort( 'aes', 'aria', 'bf', 'camellia', 'cast', 'des', 'dh',
'dsa', 'ec', 'hmac', 'idea', 'md2', 'md5', 'mdc2',
- 'rc2', 'rc4', 'rc5', 'ripemd', 'rsa', 'seed', 'sha',
+ 'rc2', 'rc4', 'rc5', 'ripemd', 'seed', 'sha',
'sm2', 'sm3', 'sm4') ) {
unshift @argvcopy, "no-$_" if ! -d catdir($srcdir, 'crypto', $_);
}
my %version = ();
collect_information(
- collect_from_file(catfile($srcdir,'VERSION')),
+ collect_from_file(catfile($srcdir,'VERSION.dat')),
qr/\s*(\w+)\s*=\s*(.*?)\s*$/ =>
sub {
# Only define it if there is a value at all
- $version{uc $1} = $2 if $2 ne '';
+ if ($2 ne '') {
+ my $k = $1;
+ my $v = $2;
+ # Some values are quoted. Trim the quotes
+ $v = $1 if $v =~ /^"(.*)"$/;
+ $version{uc $k} = $v;
+ }
},
"OTHERWISE" =>
- sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION" },
+ sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION.dat" },
);
$config{major} = $version{MAJOR} // 'unknown';
$config{version} = "$config{major}.$config{minor}.$config{patch}";
$config{full_version} = "$config{version}$config{prerelease}$config{build_metadata}";
-die "erroneous version information in VERSION: ",
+die "erroneous version information in VERSION.dat: ",
"$config{version}, $config{shlib_version}\n"
unless (defined $version{MAJOR}
&& defined $version{MINOR}
# For developers: keep it sorted alphabetically
my @disablables = (
+ "acvp_tests",
"afalgeng",
"aria",
"asan",
"bf",
"blake2",
"buildtest-c++",
+ "bulk",
+ "cached-fetch",
"camellia",
"capieng",
"cast",
"external-tests",
"filenames",
"fips",
+ "fips-securitychecks",
"fuzz-libfuzzer",
"fuzz-afl",
"gost",
# Note: => pair form used for aesthetics, not to truly make a hash table
my @disable_cascades = (
# "what" => [ "cascade", ... ]
+ "bulk" => [ "shared", "dso",
+ "aria", "async", "autoload-config",
+ "blake2", "bf", "camellia", "cast", "chacha",
+ "cmac", "cms", "cmp", "comp", "ct",
+ "des", "dgram", "dh", "dsa",
+ "ec", "engine",
+ "filenames",
+ "idea", "ktls",
+ "md4", "multiblock", "nextprotoneg",
+ "ocsp", "ocb", "poly1305", "psk",
+ "rc2", "rc4", "rmd160",
+ "seed", "siphash", "siv",
+ "sm3", "sm4", "srp",
+ "srtp", "ssl3-method",
+ "ts", "ui-console", "whirlpool",
+ "fips-securitychecks" ],
sub { $config{processor} eq "386" }
=> [ "sse2" ],
"ssl" => [ "ssl3" ],
"ssl3-method" => [ "ssl3" ],
"zlib" => [ "zlib-dynamic" ],
"des" => [ "mdc2" ],
- "ec" => [ "ecdsa", "ecdh", "sm2" ],
- sub { $disabled{"ec"} && $disabled{"dh"} }
- => [ "tls1_3" ],
+ "ec" => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ],
"dgram" => [ "dtls", "sctp" ],
"sock" => [ "dgram" ],
"dtls" => [ @dtls ],
# or modules.
"pic" => [ "shared", "module" ],
- "module" => [ "fips" ],
+ "module" => [ "fips", "dso" ],
- "engine" => [ grep /eng$/, @disablables ],
+ "engine" => [ "dynamic-engine", grep(/eng$/, @disablables) ],
"hw" => [ "padlockeng" ],
# no-autoalginit is only useful when building non-shared
sub { !$disabled{"msan"} } => [ "asm" ],
- sub { $disabled{cmac}; } => [ "siv" ],
- "legacy" => [ "md2" ],
+ "cmac" => [ "siv" ],
+ "legacy" => [ "md2" ],
"cmp" => [ "crmf" ],
- # Padlock engine uses low-level AES APIs which are deprecated
- sub { $disabled{"deprecated-3.0"} }
- => [ "padlockeng" ]
+ "deprecated-3.0" => [ "engine", "srp" ]
);
# Avoid protocol support holes. Also disable all versions below N, if version
# To remove something from %disabled, use "enable-foo".
# For symmetry, "disable-foo" is a synonym for "no-foo".
-&usage if ($#ARGV < 0);
-
# For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with
# platform specific list separators. Users from those platforms should
# recognise those separators from how you set up the PATH to find executables.
# No longer an automatic choice
$auto_threads = 0 if ($1 eq "threads");
}
+ elsif (/^-d$/) # From older 'config'
+ {
+ $config{build_type} = "debug";
+ }
+ elsif (/^-v$/) # From older 'config'
+ {
+ $guess_opts{verbose} = 1;
+ }
+ elsif (/^-w$/) # From older 'config'
+ {
+ $guess_opts{nowait} = 1;
+ }
+ elsif (/^-t$/) # From older 'config'
+ {
+ $dryrun = 1;
+ }
elsif (/^--strict-warnings$/)
{
# Pretend that our strict flags is a C flag, and replace it
push @seed_sources, $x;
}
}
+ elsif (/^--fips-key=(.*)$/)
+ {
+ $user{FIPSKEY}=lc($1);
+ die "Non-hex character in FIPS key\n"
+ if $user{FIPSKEY} =~ /[^a-f0-9]/;
+ die "FIPS key must have even number of characters\n"
+ if length $1 & 1;
+ die "FIPS key too long (64 bytes max)\n"
+ if length $1 > 64;
+ }
elsif (/^--cross-compile-prefix=(.*)$/)
{
$user{CROSS_COMPILE}=$1;
"***** any of asan, msan or ubsan\n";
}
+# If no target was given, try guessing.
+unless ($target) {
+ my %system_config = OpenSSL::config::get_platform(%guess_opts, %user);
+
+ # The $system_config{disable} is used to populate %disabled with
+ # entries that aren't already there.
+ foreach ( @{$system_config{disable} // []} ) {
+ $disabled{$_} = 'system' unless defined $disabled{$_};
+ }
+ delete $system_config{disable};
+
+ # Override config entries with stuff from the guesser.
+ # It's assumed that this really is nothing new.
+ %config = ( %config, %system_config );
+ $target = $system_config{target};
+}
+
sub disable {
my $disable_type = shift;
print "Using os-specific seed configuration\n";
push @seed_sources, 'os';
}
+if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) {
+ delete $disabled{'egd'};
+}
if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
warn <<_____ if scalar(@seed_sources) == 1;
application.
Please read the 'Note on random number generation' section in the
-INSTALL instructions and the RAND_DRBG(7) manual page for more details.
+INSTALL.md instructions and the RAND_DRBG(7) manual page for more
+details.
============================== WARNING ===============================
_____
}
}
-&usage if !$table{$target} || $table{$target}->{template};
+if ($target) {
+ # It's possible that we have different config targets for specific
+ # toolchains, so we try to detect them, and go for the plain config
+ # target if not.
+ my $found;
+ foreach ( ( "$target-$user{CC}", "$target", undef ) ) {
+ $found=$_ if $table{$_} && !$table{$_}->{template};
+ last if $found;
+ }
+ $target = $found;
+} else {
+ # If we don't have a config target now, we try the C compiler as we
+ # fallback
+ my $cc = $user{CC} // 'cc';
+ $target = $cc if $table{$cc} && !$table{$cc}->{template};
+}
+
+&usage unless $target;
+
+exit 0 if $dryrun; # From older 'config'
$config{target} = $target;
my %target = resolve_config($target);
}
my $no_shared_warn=0;
-if ($target{shared_target} eq "")
+if (($target{shared_target} // '') eq "")
{
$no_shared_warn = 1
if (!$disabled{shared} || !$disabled{"dynamic-engine"});
$config{build_infos} = [ ];
+ # We want to detect configdata.pm in the source tree, so we
+ # don't use it if the build tree is different.
+ my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
+
+ # Any source file that we recognise is placed in this hash table, with
+ # the list of its intended destinations as value. When everything has
+ # been collected, there's a routine that checks that these source files
+ # exist, or if they are generated, that the generator exists.
+ my %check_exist = ();
+ my %check_generate = ();
+
my %ordinals = ();
while (@build_dirs) {
my @curd = @{shift @build_dirs};
my $variable_name_re = qr/(?P<VARIABLE>[[:alpha:]][[:alnum:]_]*)/;
# Value modifier syntaxes
my $variable_subst_re = qr/\/(?P<RE>(?:\\\/|.)*?)\/(?P<SUBST>.*?)/;
- # Put it all together
- my $variable_re = qr/\$
- (?|
- # Simple case, just the name
- ${variable_name_re}
- |
- # Expressive case, with braces and possible
- # modifier expressions
- \{
- ${variable_name_re}
- (?:
- # Pile on modifier expressions,
- # separated by |
- ${variable_subst_re}
- )
- \}
- )/x;
+ # Variable reference
+ my $variable_simple_re = qr/(?<!\\)\$${variable_name_re}/;
+ my $variable_w_mod_re =
+ qr/(?<!\\)\$\{${variable_name_re}(?P<MOD>(?:\\\/|.)*?)\}/;
+ # Tie it all together
+ my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/;
+
my $expand_variables = sub {
my $value = '';
my $value_rest = shift;
print STDERR
"DEBUG[\$expand_variables] Parsed '$value_rest' ...\n"
}
- while ($value_rest =~ /(?<!\\)${variable_re}/) {
- $value_rest = $';
- $value .= $`;
+ while ($value_rest =~ /${variable_re}/) {
+ # We must save important regexp values, because the next
+ # regexp clears them
+ my $mod = $+{MOD};
my $variable_value = $variables{$+{VARIABLE}};
+ $value_rest = $';
+ $value .= $`;
+
# Process modifier expressions, if present
- if (defined $+{RE}) {
- # We must save important %+ values, because the s///
- # below clears them
- my $re = $+{RE};
- my $subst = $+{SUBST};
-
- $variable_value =~ s/\Q$re\E/$subst/g;
-
- if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
- print STDERR
- "DEBUG[\$expand_variables] ... and substituted ",
- "'$re' with '$subst'\n";
+ if (defined $mod) {
+ if ($mod =~ /^${variable_subst_re}$/) {
+ my $re = $+{RE};
+ my $subst = $+{SUBST};
+
+ $variable_value =~ s/\Q$re\E/$subst/g;
+
+ if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
+ print STDERR
+ "DEBUG[\$expand_variables] ... and substituted ",
+ "'$re' with '$subst'\n";
+ }
}
}
my $ac = 1;
my $ak = $a;
my $av = 1;
- if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|) {
+ if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|x) {
$ac = ! $1;
- $ak = $1;
- $av = $2;
+ $ak = $2;
+ $av = $3;
}
foreach my $g (@goals) {
if ($ac) {
}
};
- # We want to detect configdata.pm in the source tree, so we
- # don't use it if the build tree is different.
- my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
-
-
if ($buildinfo_debug) {
print STDERR "DEBUG: Reading ",catfile($sourced, $f),"\n";
}
}
# We recognise C++, C and asm files
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
+ push @{$check_exist{$s}}, $ddest;
my $o = $_;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
+ push @{$check_exist{$s}}, $ddest;
my $o = $_;
$o =~ s/\.rc$/.res/; # Resource configuration
- my $o = cleanfile($buildd, $o, $blddir);
+ $o = cleanfile($buildd, $o, $blddir);
$unified_info{sources}->{$ddest}->{$o} = -1;
$unified_info{sources}->{$o}->{$s} = -1;
} else {
+ push @{$check_exist{$s}}, $ddest;
$unified_info{sources}->{$ddest}->{$s} = 1;
}
}
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
# We recognise C++, C and asm files
+ push @{$check_exist{$s}}, $ddest;
my $o = $_;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
+ push @{$check_exist{$s}}, $ddest;
my $o = $_;
$o =~ s/\.rc$/.res/; # Resource configuration
- my $o = cleanfile($buildd, $o, $blddir);
+ $o = cleanfile($buildd, $o, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = -1;
$unified_info{sources}->{$o}->{$s} = -1;
} elsif ($s =~ /\.ld$/) {
# We also recognise linker scripts (or corresponding)
# We know they are generated files
+ push @{$check_exist{$s}}, $ddest;
my $ld = cleanfile($buildd, $_, $blddir);
$unified_info{shared_sources}->{$ddest}->{$ld} = 1;
} else {
if ($generate{$gen}) {
$generator[0] = cleanfile($buildd, $gen, $blddir);
}
+ $check_generate{$ddest}->{$generator[0]}++;
$unified_info{generate}->{$ddest} = [ @generator ];
}
DEPEND and SHARED_SOURCE.
EOF
+ # Check that each generated file is only generated once
+ my $ambiguous_generation = 0;
+ foreach (sort keys %check_generate) {
+ my @generators = sort keys %{$check_generate{$_}};
+ my $generators_txt = join(', ', @generators);
+ if (scalar @generators > 1) {
+ warn "$_ is GENERATEd by more than one generator ($generators_txt)\n";
+ $ambiguous_generation++;
+ }
+ if ($check_generate{$_}->{$generators[0]} > 1) {
+ warn "INFO: $_ has more than one GENERATE declaration (same generator)\n"
+ }
+ }
+ die "There are ambiguous source file generations\n"
+ if $ambiguous_generation > 0;
+
+ # All given source files should exist, or if generated, their
+ # generator should exist. This loop ensures this is true.
+ my $missing = 0;
+ foreach my $orig (sort keys %check_exist) {
+ foreach my $dest (@{$check_exist{$orig}}) {
+ if ($orig ne $src_configdata) {
+ if ($orig =~ /\.a$/) {
+ # Static library names may be used as sources, so we
+ # need to detect those and give them special treatment.
+ unless (grep { $_ eq $orig }
+ keys %{$unified_info{libraries}}) {
+ warn "$orig is given as source for $dest, but no such library is built\n";
+ $missing++;
+ }
+ } else {
+ # A source may be generated, and its generator may be
+ # generated as well. We therefore loop to dig out the
+ # first generator.
+ my $gen = $orig;
+
+ while (my @next = keys %{$check_generate{$gen}}) {
+ $gen = $next[0];
+ }
+
+ if (! -f $gen) {
+ if ($gen ne $orig) {
+ $missing++;
+ warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n";
+ } else {
+ $missing++;
+ warn "$orig is given as source for $dest, but is missing\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ die "There are files missing\n" if $missing > 0;
# Go through the sources of all libraries and check that the same basename
# doesn't appear more than once. Some static library archivers depend on
The library could not be configured for supporting multi-threaded
applications as the compiler options required on this system are not known.
-See file INSTALL for details if you need multi-threading.
+See file INSTALL.md for details if you need multi-threading.
EOF
print <<"EOF" if ($no_shared_warn);
*** perl configdata.pm --dump ***
*** ***
*** (If you are new to OpenSSL, you might want to consult the ***
-*** 'Troubleshooting' section in the INSTALL file first) ***
+*** 'Troubleshooting' section in the INSTALL.md file first) ***
*** ***
**********************************************************************
EOF
my @message = ( <<"_____", @_ );
Failure! $build_file wasn't produced.
-Please read INSTALL and associated NOTES files. You may also have to look over
-your available compiler tool chain or change your configuration.
+Please read INSTALL.md and associated NOTES-* files. You may also have to
+look over your available compiler tool chain or change your configuration.
_____
}
print STDERR $i . " ";
}
- print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
exit(1);
}
"loutflag",
"ex_libs",
"bn_ops",
+ "enable",
+ "disable",
"poly1035_asm_src",
"thread_scheme",
"perlasm_scheme",
return realpath($dir);
}
+# Check if all paths are one and the same, using stat. They must both exist
+# We need this for the cases when File::Spec doesn't detect case insensitivity
+# (File::Spec::Unix assumes case sensitivity)
+sub samedir {
+ die "samedir expects two arguments\n" unless scalar @_ == 2;
+
+ my @stat0 = stat($_[0]); # First argument
+ my @stat1 = stat($_[1]); # Second argument
+
+ die "Couldn't stat $_[0]" unless @stat0;
+ die "Couldn't stat $_[1]" unless @stat1;
+
+ # Compare device number
+ return 0 unless ($stat0[0] == $stat1[0]);
+ # Compare "inode". The perl manual recommends comparing as
+ # string rather than as number.
+ return 0 unless ($stat0[1] eq $stat1[1]);
+
+ return 1; # All the same
+}
+
sub quotify {
my %processors = (
perl => sub { my $x = shift;