diff --git a/CHANGES b/CHANGES index aa00369e..29be4fc7 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,24 @@ Changes between 1.1.1 and 1.1.2 [xx XXX xxxx] + *) Ported the HMAC, CMAC and SipHash EVP_PKEY_METHODs to EVP_MAC. + [Richard Levitte] + + *) Added EVP_MAC, an EVP layer MAC API, to simplify adding MAC + implementations. This includes a generic EVP_PKEY to EVP_MAC bridge, + to facilitate the continued use of MACs through raw private keys in + functionality such as EVP_DigestSign* and EVP_DigestVerify*. + [Richard Levitte] + + *) Deprecate ECDH_KDF_X9_62() and mark its replacement as internal. Users + should use the EVP interface instead (EVP_PKEY_CTX_set_ecdh_kdf_type). + [Antoine Salon] + + *) Added EVP_PKEY_ECDH_KDF_X9_63 and ecdh_KDF_X9_63() as replacements for + the EVP_PKEY_ECDH_KDF_X9_62 KDF type and ECDH_KDF_X9_62(). The old names + are retained for backwards compatibility. + [Antoine Salon] + *) AES-XTS mode now enforces that its two keys are different to mitigate the attacked described in "Efficient Instantiations of Tweakable Blockciphers and Refinements to Modes OCB and PMAC" by Phillip Rogaway. diff --git a/Configurations/15-android.conf b/Configurations/15-android.conf index d3b428b6..10342ed5 100644 --- a/Configurations/15-android.conf +++ b/Configurations/15-android.conf @@ -24,7 +24,12 @@ my $ndk = $ENV{ANDROID_NDK}; die "\$ANDROID_NDK is not defined" if (!$ndk); - die "\$ANDROID_NDK=$ndk is invalid" if (!-d "$ndk/platforms"); + if (!-d "$ndk/platforms" && !-f "$ndk/AndroidVersion.txt") { + # $ndk/platforms is traditional "all-inclusive" NDK, while + # $ndk/AndroidVersion.txt is so-called standalone toolchain + # tailored for specific target down to API level. + die "\$ANDROID_NDK=$ndk is invalid"; + } $ndk = canonpath($ndk); my $ndkver = undef; @@ -40,10 +45,18 @@ close $fh; } - my $sysroot; + my ($sysroot, $api, $arch); - if (!($sysroot = $ENV{CROSS_SYSROOT})) { - my $api = "*"; + $config{target} =~ m|[^-]+-([^-]+)$|; # split on dash + $arch = $1; + + if ($sysroot = $ENV{CROSS_SYSROOT}) { + $sysroot =~ m|/android-([0-9]+)/arch-(\w+)/?$|; + ($api, $arch) = ($1, $2); + } elsif (-f "$ndk/AndroidVersion.txt") { + $sysroot = "$ndk/sysroot"; + } else { + $api = "*"; # see if user passed -D__ANDROID_API__=N foreach (@{$useradd{CPPDEFINES}}, @{$user{CPPFLAGS}}) { @@ -59,19 +72,17 @@ } glob("$ndk/platforms/android-$api"); die "no $ndk/platforms/android-$api" if ($#platforms < 0); - $config{target} =~ m|[^-]+-([^-]+)$|; # split on dash - $sysroot = "@platforms[$#platforms]/arch-$1"; + $sysroot = "@platforms[$#platforms]/arch-$arch"; + $sysroot =~ m|/android-([0-9]+)/arch-$arch|; + $api = $1; } die "no sysroot=$sysroot" if (!-d $sysroot); - $sysroot =~ m|/android-([0-9]+)/arch-(\w+)/?$|; - my ($api, $arch) = ($1, $2); - my $triarch = $triplet{$arch}; my $cflags; my $cppflags; - # see if there is NDK clang on $PATH + # see if there is NDK clang on $PATH, "universal" or "standalone" if (which("clang") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) { my $host=$1; # harmonize with gcc default @@ -83,6 +94,23 @@ . "/$tritools-4.9/prebuilt/$host"; $user{CC} = "clang" if ($user{CC} !~ m|clang|); $user{CROSS_COMPILE} = undef; + if (which("llvm-ar") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) { + $user{AR} = "llvm-ar"; + $user{ARFLAGS} = [ "rs" ]; + $user{RANLIB} = ":"; + } + } elsif (-f "$ndk/AndroidVersion.txt") { #"standalone toolchain" + my $cc = $user{CC} // "clang"; + # One can probably argue that both clang and gcc should be + # probed, but support for "standalone toolchain" was added + # *after* announcement that gcc is being phased out, so + # favouring clang is considered adequate. Those who insist + # have option to enforce test for gcc with CC=gcc. + if (which("$triarch-$cc") !~ m|^$ndk|) { + die "no NDK $triarch-$cc on \$PATH"; + } + $user{CC} = $cc; + $user{CROSS_COMPILE} = "$triarch-"; } elsif ($user{CC} eq "clang") { die "no NDK clang on \$PATH"; } else { diff --git a/Configurations/15-ios.conf b/Configurations/15-ios.conf index aff90962..1bb9f48d 100644 --- a/Configurations/15-ios.conf +++ b/Configurations/15-ios.conf @@ -6,31 +6,31 @@ # work... # my %targets = ( + "ios-common" => { + template => 1, + inherit_from => [ "darwin-common" ], + sys_id => "iOS", + disable => [ "engine", "async" ], + }, "ios-xcrun" => { - inherit_from => [ "darwin-common", asm("armv4_asm") ], + inherit_from => [ "ios-common", asm("armv4_asm") ], # It should be possible to go below iOS 6 and even add -arch armv6, # thus targeting iPhone pre-3GS, but it's assumed to be irrelevant # at this point. CC => "xcrun -sdk iphoneos cc", cflags => add("-arch armv7 -mios-version-min=6.0.0 -fno-common"), - sys_id => "iOS", perlasm_scheme => "ios32", - disable => [ "engine" ], }, "ios64-xcrun" => { - inherit_from => [ "darwin-common", asm("aarch64_asm") ], + inherit_from => [ "ios-common", asm("aarch64_asm") ], CC => "xcrun -sdk iphoneos cc", cflags => add("-arch arm64 -mios-version-min=7.0.0 -fno-common"), - sys_id => "iOS", bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", perlasm_scheme => "ios64", - disable => [ "engine" ], }, "iossimulator-xcrun" => { - inherit_from => [ "darwin-common" ], + inherit_from => [ "ios-common" ], CC => "xcrun -sdk iphonesimulator cc", - sys_id => "iOS", - disable => [ "engine" ], }, # It takes three prior-set environment variables to make it work: # @@ -46,10 +46,8 @@ my %targets = ( # CROSS_SDK=iPhoneOS.sdk # "iphoneos-cross" => { - inherit_from => [ "darwin-common" ], + inherit_from => [ "ios-common" ], cflags => add("-isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK) -fno-common"), - sys_id => "iOS", - disable => [ "engine" ], }, "ios-cross" => { inherit_from => [ "ios-xcrun" ], diff --git a/Configurations/common.tmpl b/Configurations/common.tmpl index c1c96a2b..4a086559 100644 --- a/Configurations/common.tmpl +++ b/Configurations/common.tmpl @@ -210,47 +210,6 @@ # Start with populating the cache with all the overrides %cache = map { $_ => 1 } @{$unified_info{overrides}}; - # For convenience collect information regarding directories where - # files are generated, those generated files and the end product - # they end up in where applicable. Then, add build rules for those - # directories - if (exists &generatedir) { - my %loopinfo = ( "dso" => [ @{$unified_info{engines}} ], - "lib" => [ @{$unified_info{libraries}} ], - "bin" => [ @{$unified_info{programs}} ], - "script" => [ @{$unified_info{scripts}} ] ); - foreach my $type (keys %loopinfo) { - foreach my $product (@{$loopinfo{$type}}) { - my %dirs = (); - my $pd = dirname($product); - - # We already have a "test" target, and the current directory - # is just silly to make a target for - $dirs{$pd} = 1 unless $pd eq "test" || $pd eq "."; - - foreach (@{$unified_info{sources}->{$product}}) { - my $d = dirname($_); - - # We don't want to create targets for source directories - # when building out of source - next if ($config{sourcedir} ne $config{builddir} - && $d =~ m|^\Q$config{sourcedir}\E|); - # We already have a "test" target, and the current directory - # is just silly to make a target for - next if $d eq "test" || $d eq "."; - - $dirs{$d} = 1; - push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ - if $d ne $pd; - } - foreach (keys %dirs) { - push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, - $product; - } - } - } - } - # Build mandatory generated headers foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); } diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index 3f76c592..f81ebb01 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -499,11 +499,11 @@ install_dev: @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) @$(ECHO) "*** Installing development files" @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/include/openssl - @ : {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$target{defines}}; "" -} + @ : {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} @$(ECHO) "install $(SRCDIR)/ms/applink.c -> $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c" @cp $(SRCDIR)/ms/applink.c $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c @chmod 644 $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c - @ : {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$target{defines}}; "" -} + @ : {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} @set -e; for i in $(SRCDIR)/include/openssl/*.h \ $(BLDDIR)/include/openssl/*.h; do \ fn=`basename $$i`; \ @@ -574,10 +574,10 @@ install_dev: uninstall_dev: @$(ECHO) "*** Uninstalling development files" - @ : {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$target{defines}}; "" -} + @ : {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} @$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c" @$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c - @ : {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$target{defines}}; "" -} + @ : {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} @set -e; for i in $(SRCDIR)/include/openssl/*.h \ $(BLDDIR)/include/openssl/*.h; do \ fn=`basename $$i`; \ @@ -1134,9 +1134,7 @@ EOF } return $recipe; } - # On Unix, we build shlibs from static libs, so we're ignoring the - # object file array. We *know* this routine is only called when we've - # configure 'shared'. + # We *know* this routine is only called when we've configure 'shared'. sub obj2shlib { my %args = @_; my $lib = $args{lib}; @@ -1163,26 +1161,20 @@ EOF die "More than one exported symbol map" if scalar @defs > 1; my $objs = join(" ", @objs); my $deps = join(" ", @objs, @defs, @deps); - my $target = shlib_simple($lib); - my $target_full = shlib($lib); + my $simple = shlib_simple($lib); + my $full = shlib($lib); + my $target = "$simple $full"; my $shared_soname = ""; - $shared_soname .= ' '.$target{shared_sonameflag}.basename($target_full) + $shared_soname .= ' '.$target{shared_sonameflag}.basename($full) if defined $target{shared_sonameflag}; my $shared_imp = ""; - $shared_imp .= ' '.$target{shared_impflag}.basename($target) + $shared_imp .= ' '.$target{shared_impflag}.basename($simple) if defined $target{shared_impflag}; my $shared_def = join("", map { ' '.$target{shared_defflag}.$_ } @defs); my $recipe = <<"EOF"; -# When building on a Windows POSIX layer (Cygwin or Mingw), we know for a fact -# that two files get produced, {shlibname}.dll and {libname}.dll.a. -# With all other Unix platforms, we often build a shared library with the -# SO version built into the file name and a symlink without the SO version -# It's not necessary to have both as targets. The choice falls on the -# simplest, {libname}\$(SHLIB_EXT_IMPORT) for Windows POSIX layers and -# {libname}\$(SHLIB_EXT_SIMPLE) for the Unix platforms. $target: $deps \$(CC) \$(LIB_CFLAGS) $linkflags\$(LIB_LDFLAGS)$shared_soname$shared_imp \\ - -o $target_full$shared_def $objs \\ + -o $full$shared_def $objs \\ $linklibs \$(LIB_EX_LIBS) EOF if (windowsdll()) { @@ -1196,14 +1188,14 @@ EOF EOF } elsif (sharedaix()) { $recipe .= <<"EOF"; - rm -f $target && \\ - \$(AR) r $target $target_full + rm -f $simple && \\ + \$(AR) r $simple $full EOF } else { $recipe .= <<"EOF"; - if [ '$target' != '$target_full' ]; then \\ - rm -f $target; \\ - ln -s $target_full $target; \\ + if [ '$simple' != '$full' ]; then \\ + rm -f $simple; \\ + ln -s $full $simple; \\ fi EOF } @@ -1311,6 +1303,10 @@ EOF lib => $libext, bin => $exeext ); + # We already have a 'test' target, and the top directory is just plain + # silly + return if $dir eq "test" || $dir eq "."; + foreach my $type (("dso", "lib", "bin", "script")) { next unless defined($unified_info{dirinfo}->{$dir}->{products}->{$type}); # For lib object files, we could update the library. However, it @@ -1331,7 +1327,7 @@ EOF my $deps = join(" ", @deps); my $actions = join("\n", "", @actions); return <<"EOF"; -$args{dir} $args{dir}/: $deps$actions +$dir $dir/: $deps$actions EOF } "" # Important! This becomes part of the template result. diff --git a/Configurations/windows-makefile.tmpl b/Configurations/windows-makefile.tmpl index 6ab298e4..6344d186 100644 --- a/Configurations/windows-makefile.tmpl +++ b/Configurations/windows-makefile.tmpl @@ -41,6 +41,8 @@ sub lib { (my $lib = shift) =~ s/\.a$//; + $lib .= '_static' + if (defined $unified_info{sharednames}->{$lib}); return $lib . $libext; } @@ -75,7 +77,7 @@ MINOR={- $config{minor} -} SHLIB_VERSION_NUMBER={- $config{shlib_version_number} -} -LIBS={- join(" ", map { lib($_) } @{$unified_info{libraries}}) -} +LIBS={- join(" ", map { ( shlib_import($_), lib($_) ) } @{$unified_info{libraries}}) -} SHLIBS={- join(" ", map { shlib($_) } @{$unified_info{libraries}}) -} SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; shlib($_) } @{$unified_info{libraries}}) -} ENGINES={- join(" ", map { dso($_) } @{$unified_info{engines}}) -} @@ -96,7 +98,7 @@ GENERATED={- # common0.tmpl provides @generated $x } @generated) -} -INSTALL_LIBS={- join(" ", map { quotify1(lib($_)) } @{$unified_info{install}->{libraries}}) -} +INSTALL_LIBS={- join(" ", map { quotify1(shlib_import($_) or lib($_)) } @{$unified_info{install}->{libraries}}) -} INSTALL_SHLIBS={- join(" ", map { quotify_l(shlib($_)) } @{$unified_info{install}->{libraries}}) -} INSTALL_SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; quotify_l(shlib($_)) } @{$unified_info{install}->{libraries}}) -} INSTALL_ENGINES={- join(" ", map { quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -} @@ -414,10 +416,10 @@ install_dev: @if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 ) @$(ECHO) "*** Installing development files" @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(INSTALLTOP)\include\openssl" - @{- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$config{defines}}; "" -} + @{- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} @"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\ms\applink.c" \ "$(INSTALLTOP)\include\openssl" - @{- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$config{defines}}; "" -} + @{- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } (@{$target{defines}}, @{$config{defines}}); "" -} @"$(PERL)" "$(SRCDIR)\util\copy.pl" "-exclude_re=/__DECC_" \ "$(SRCDIR)\include\openssl\*.h" \ "$(INSTALLTOP)\include\openssl" @@ -490,11 +492,6 @@ reconfigure reconf: if ($disabled{shared}) { return map { lib($_) } @_; } - foreach (@_) { - (my $l = $_) =~ s/\.a$//; - die "Linking with static variants of shared libraries is not supported in this configuration\n" - if $l ne $_ && shlib($l); - } return map { shlib_import($_) or lib($_) } @_; } @@ -618,25 +615,22 @@ $obj$objext: $deps \$(CC) /EP /D__ASSEMBLER__ $cflags $srcs > \$@.asm && \$(AS) $asflags \$(ASOUTFLAG)\$\@ \$@.asm EOF } - return <<"EOF" if (!$disabled{makedepend}); -$obj$depext: $deps - \$(CC) $cflags /Zs /showIncludes $srcs 2>&1 > $obj$depext -$obj$objext: $obj$depext - \$(CC) $cflags -c \$(COUTFLAG)\$\@ $srcs -EOF - return <<"EOF" if ($disabled{makedepend}); + my $recipe = <<"EOF"; $obj$objext: $deps \$(CC) $cflags -c \$(COUTFLAG)\$\@ $srcs EOF + $recipe .= <<"EOF" unless $disabled{makedepend}; + \$(CC) $cflags /Zs /showIncludes $srcs 2>&1 > $obj$depext +EOF + return $recipe; } - # On Unix, we build shlibs from static libs, so we're ignoring the - # object file array. We *know* this routine is only called when we've - # configure 'shared'. + # We *know* this routine is only called when we've configure 'shared'. + # Also, note that even though the import library built here looks like + # a static library, it really isn't. sub obj2shlib { my %args = @_; my $lib = $args{lib}; - my $shlib = $args{shlib}; my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } grep { $_ =~ m/\.(?:o|res)$/ } @{$args{objs}}; @@ -648,25 +642,30 @@ EOF my $linklibs = join("", map { "$_\n" } @deps); my $objs = join("\n", @objs); my $deps = join(" ", @objs, @defs, @deps); - my $target = shlib_import($lib); + my $import = shlib_import($lib); + my $dll = shlib($lib); my $shared_def = join("", map { " /def:$_" } @defs); return <<"EOF" -$target: $deps - IF EXIST $shlib$shlibext.manifest DEL /F /Q $shlib$shlibext.manifest +# The import library may look like a static library, but it is not. +# We MUST make the import library depend on the DLL, in case someone +# mistakenly removes the latter. +$import: $dll +$dll: $deps + IF EXIST $full.manifest DEL /F /Q $full.manifest IF EXIST \$@ DEL /F /Q \$@ \$(LD) \$(LDFLAGS) \$(LIB_LDFLAGS) \\ - /implib:\$@ \$(LDOUTFLAG)$shlib$shlibext$shared_def @<< || (DEL /Q \$(\@B).* $shlib.* && EXIT 1) + /implib:$import \$(LDOUTFLAG)$dll$shared_def @<< || (DEL /Q \$(\@B).* $import && EXIT 1) $objs $linklibs\$(LIB_EX_LIBS) << - IF EXIST $shlib$shlibext.manifest \\ - \$(MT) \$(MTFLAGS) \$(MTINFLAG)$shlib$shlibext.manifest \$(MTOUTFLAG)$shlib$shlibext - IF EXIST apps\\$shlib$shlibext DEL /Q /F apps\\$shlib$shlibext - IF EXIST test\\$shlib$shlibext DEL /Q /F test\\$shlib$shlibext - IF EXIST fuzz\\$shlib$shlibext DEL /Q /F fuzz\\$shlib$shlibext - COPY $shlib$shlibext apps - COPY $shlib$shlibext test - COPY $shlib$shlibext fuzz + IF EXIST $dll.manifest \\ + \$(MT) \$(MTFLAGS) \$(MTINFLAG)$dll.manifest \$(MTOUTFLAG)$dll + IF EXIST apps\\$dll DEL /Q /F apps\\$dll + IF EXIST test\\$dll DEL /Q /F test\\$dll + IF EXIST fuzz\\$dll DEL /Q /F fuzz\\$dll + COPY $dll apps + COPY $dll test + COPY $dll fuzz EOF } sub obj2dso { @@ -698,20 +697,13 @@ EOF } sub obj2lib { my %args = @_; - my $lib = $args{lib}; - - # Because static libs and import libs are both named the same in native - # Windows, we can't have both. We skip the static lib in that case, - # as the shared libs are what we use anyway. - return "" unless $disabled{"shared"} || $lib =~ /\.a$/; - - $lib =~ s/\.a$//; + my $lib = lib($args{lib}); my @objs = map { (my $x = $_) =~ s|\.o$|$objext|; $x } @{$args{objs}}; my $objs = join("\n", @objs); my $deps = join(" ", @objs); return <<"EOF"; -$lib$libext: $deps - \$(AR) \$(ARFLAGS) \$(AROUTFLAG)$lib$libext @<< +$lib: $deps + \$(AR) \$(ARFLAGS) \$(AROUTFLAG)$lib @<< $objs << EOF @@ -758,6 +750,10 @@ EOF lib => $libext, bin => $exeext ); + # We already have a 'test' target, and the top directory is just plain + # silly + return if $dir eq "test" || $dir eq "."; + foreach my $type (("dso", "lib", "bin", "script")) { next unless defined($unified_info{dirinfo}->{$dir}->{products}->{$type}); # For lib object files, we could update the library. However, @@ -775,7 +771,7 @@ EOF my $deps = join(" ", @deps); my $actions = join("\n", "", @actions); return <<"EOF"; -$args{dir} $args{dir}\\ : $deps$actions +$dir $dir\\ : $deps$actions EOF } "" # Important! This becomes part of the template result. diff --git a/Configure b/Configure index 2e81640e..bf0c2d5f 100755 --- a/Configure +++ b/Configure @@ -1013,13 +1013,18 @@ if (scalar(@seed_sources) == 0) { 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; -You have selected the --with-rand-seed=none option, which effectively disables -automatic reseeding of the OpenSSL random generator. All operations depending -on the random generator such as creating keys will not work unless the random -generator is seeded manually by the application. -Please read the 'Note on random number generation' section in the INSTALL -instructions and the RAND_DRBG(7) manual page for more details. +============================== WARNING =============================== +You have selected the --with-rand-seed=none option, which effectively +disables automatic reseeding of the OpenSSL random generator. +All operations depending on the random generator such as creating keys +will not work unless the random generator is seeded manually by the +application. + +Please read the 'Note on random number generation' section in the +INSTALL instructions and the RAND_DRBG(7) manual page for more details. +============================== WARNING =============================== + _____ } push @{$config{openssl_other_defines}}, @@ -2325,6 +2330,42 @@ EOF delete $unified_info{includes}->{$dest}; } } + + # For convenience collect information regarding directories where + # files are generated, those generated files and the end product + # they end up in where applicable. Then, add build rules for those + # directories + my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ], + "dso" => [ @{$unified_info{engines}} ], + "bin" => [ @{$unified_info{programs}} ], + "script" => [ @{$unified_info{scripts}} ] ); + foreach my $type (keys %loopinfo) { + foreach my $product (@{$loopinfo{$type}}) { + my %dirs = (); + my $pd = dirname($product); + + foreach (@{$unified_info{sources}->{$product}}, + @{$unified_info{shared_sources}->{$product} // []}) { + my $d = dirname($_); + + # We don't want to create targets for source directories + # when building out of source + next if ($config{sourcedir} ne $config{builddir} + && $d =~ m|^\Q$config{sourcedir}\E|); + # We already have a "test" target, and the current directory + # is just silly to make a target for + next if $d eq "test" || $d eq "."; + + $dirs{$d} = 1; + push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ + if $d ne $pd; + } + foreach (keys %dirs) { + push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, + $product; + } + } + } } # For the schemes that need it, we provide the old *_obj configs @@ -2799,10 +2840,16 @@ print <<"EOF"; ********************************************************************** *** *** -*** If you want to report a building issue, please include the *** -*** output from this command: *** +*** OpenSSL has been successfully configured *** *** *** -*** perl configdata.pm --dump *** +*** If you encounter a problem while building, please open an *** +*** issue on GitHub *** +*** and include the output from the following command: *** +*** *** +*** perl configdata.pm --dump *** +*** *** +*** (If you are new to OpenSSL, you might want to consult the *** +*** 'Troubleshooting' section in the INSTALL file first) *** *** *** ********************************************************************** EOF diff --git a/NEWS b/NEWS index 3179b1dd..56aab217 100644 --- a/NEWS +++ b/NEWS @@ -7,7 +7,8 @@ Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.2 [under development] - o + o Added EVP_MAC, an EVP layer MAC API, and a generic EVP_PKEY to EVP_MAC + bridge. Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018] diff --git a/NOTES.ANDROID b/NOTES.ANDROID index d13f47d6..bbbd8e4d 100644 --- a/NOTES.ANDROID +++ b/NOTES.ANDROID @@ -24,16 +24,18 @@ in order to invoke $(CROSS_COMPILE)gcc and company. (Configure will fail and give you a hint if you get it wrong.) Apart from PATH adjustment you need to set ANDROID_NDK environment to point at NDK directory - as /some/where/android-ndk-. NDK customarily supports multiple + as /some/where/android-ndk-. Both variables are significant at both + configuration and compilation times. NDK customarily supports multiple Android API levels, e.g. android-14, android-21, etc. By default latest one available is chosen. If you need to target older platform, pass additional -D__ANDROID_API__=N to Configure. N is numeric value of the target platform version. For example, to compile for ICS on ARM with NDK 10d: - ANDROID_NDK=/some/where/android-ndk-10d + export ANDROID_NDK=/some/where/android-ndk-10d PATH=$ANDROID_NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin:$PATH ./Configure android-arm -D__ANDROID_API__=14 + make Caveat lector! Earlier OpenSSL versions relied on additional CROSS_SYSROOT variable set to $ANDROID_NDK/platforms/android-/arch- to @@ -43,12 +45,18 @@ conflict, and mixing the two is therefore not supported. Migration to CROSS_SYSROOT-less setup is recommended. - One can engage clang by adjusting PATH to cover NDK's clang. Just keep - in mind that if you miss it, Configure will try to use gcc... Also, - PATH would need even further adjustment to cover unprefixed, yet + One can engage clang by adjusting PATH to cover same NDK's clang. Just + keep in mind that if you miss it, Configure will try to use gcc... + Also, PATH would need even further adjustment to cover unprefixed, yet target-specific, ar and ranlib. It's possible that you don't need to bother, if binutils-multiarch is installed on your Linux system. + Another option is to create so called "standalone toolchain" tailored + for single specific platform including Android API level, and assign its + location to ANDROID_NDK. In such case you have to pass matching target + name to Configure and shouldn't use -D__ANDROID_API__=N. PATH adjusment + becomes simpler, $ANDROID_NDK/bin:$PATH suffices. + Running tests (on Linux) ------------------------ diff --git a/apps/ca.c b/apps/ca.c index 847809a5..69207c06 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -976,7 +976,7 @@ end_of_options: BIO_printf(bio_err, "Write out database with %d new entries\n", sk_X509_num(cert_sk)); - if (!rand_ser + if (serialfile != NULL && !save_serial(serialfile, "new", serial, NULL)) goto end; @@ -1044,7 +1044,8 @@ end_of_options: if (sk_X509_num(cert_sk)) { /* Rename the database and the serial file */ - if (!rotate_serial(serialfile, "new", "old")) + if (serialfile != NULL + && !rotate_serial(serialfile, "new", "old")) goto end; if (!rotate_index(dbfile, "new", "old")) @@ -1177,10 +1178,9 @@ end_of_options: } /* we have a CRL number that need updating */ - if (crlnumberfile != NULL) - if (!rand_ser - && !save_serial(crlnumberfile, "new", crlnumber, NULL)) - goto end; + if (crlnumberfile != NULL + && !save_serial(crlnumberfile, "new", crlnumber, NULL)) + goto end; BN_free(crlnumber); crlnumber = NULL; @@ -1195,9 +1195,10 @@ end_of_options: PEM_write_bio_X509_CRL(Sout, crl); - if (crlnumberfile != NULL) /* Rename the crlnumber file */ - if (!rotate_serial(crlnumberfile, "new", "old")) - goto end; + /* Rename the crlnumber file */ + if (crlnumberfile != NULL + && !rotate_serial(crlnumberfile, "new", "old")) + goto end; } /*****************************************************************/ diff --git a/apps/rehash.c b/apps/rehash.c index de7217cb..bb41d312 100644 --- a/apps/rehash.c +++ b/apps/rehash.c @@ -1,6 +1,6 @@ /* * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2013-2014 Timo Teräs + * Copyright (c) 2013-2014 Timo Teräs * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/apps/s_server.c b/apps/s_server.c index 6f2a2ae8..ac7dca60 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -193,9 +193,8 @@ static int psk_find_session_cb(SSL *ssl, const unsigned char *identity, if (strlen(psk_identity) != identity_len || memcmp(psk_identity, identity, identity_len) != 0) { - BIO_printf(bio_s_out, - "PSK warning: client identity not what we expected" - " (got '%s' expected '%s')\n", identity, psk_identity); + *sess = NULL; + return 1; } if (psksess != NULL) { diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h index b07c2cb0..62449fe6 100644 --- a/crypto/async/arch/async_posix.h +++ b/crypto/async/arch/async_posix.h @@ -17,7 +17,8 @@ # include -# if _POSIX_VERSION >= 200112L +# if _POSIX_VERSION >= 200112L \ + && (_POSIX_VERSION < 200809L || defined(__GLIBC__)) # include diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 2c92d7ea..c026ffcb 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -1077,7 +1077,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, * is not only slower but also makes each bit vulnerable to * EM (and likely other) side-channel attacks like One&Done * (for details see "One&Done: A Single-Decryption EM-Based - * Attack on OpenSSL’s Constant-Time Blinded RSA" by M. Alam, + * Attack on OpenSSL's Constant-Time Blinded RSA" by M. Alam, * H. Khan, M. Dey, N. Sinha, R. Callan, A. Zajic, and * M. Prvulovic, in USENIX Security'18) */ diff --git a/crypto/cmac/build.info b/crypto/cmac/build.info index c8a4949a..c460598e 100644 --- a/crypto/cmac/build.info +++ b/crypto/cmac/build.info @@ -1,2 +1,2 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_pmeth.c +SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_meth.c diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c index a58454a0..71265846 100644 --- a/crypto/cmac/cm_ameth.c +++ b/crypto/cmac/cm_ameth.c @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,7 +10,6 @@ #include #include "internal/cryptlib.h" #include -#include #include "internal/asn1_int.h" /* @@ -25,8 +24,8 @@ static int cmac_size(const EVP_PKEY *pkey) static void cmac_key_free(EVP_PKEY *pkey) { - CMAC_CTX *cmctx = EVP_PKEY_get0(pkey); - CMAC_CTX_free(cmctx); + EVP_MAC_CTX *cmctx = EVP_PKEY_get0(pkey); + EVP_MAC_CTX_free(cmctx); } const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = { diff --git a/crypto/cmac/cm_meth.c b/crypto/cmac/cm_meth.c new file mode 100644 index 00000000..70899360 --- /dev/null +++ b/crypto/cmac/cm_meth.c @@ -0,0 +1,164 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include "internal/evp_int.h" + +/* local CMAC pkey structure */ + +/* typedef EVP_MAC_IMPL */ +struct evp_mac_impl_st { + /* tmpcipher and tmpengine are set to NULL after a CMAC_Init call */ + const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */ + const ENGINE *tmpengine; /* cached CMAC cipher engine */ + CMAC_CTX *ctx; +}; + +static EVP_MAC_IMPL *cmac_new(void) +{ + EVP_MAC_IMPL *cctx; + + if ((cctx = OPENSSL_zalloc(sizeof(*cctx))) == NULL + || (cctx->ctx = CMAC_CTX_new()) == NULL) { + OPENSSL_free(cctx); + cctx = NULL; + } + + return cctx; +} + +static void cmac_free(EVP_MAC_IMPL *cctx) +{ + if (cctx != NULL) { + CMAC_CTX_free(cctx->ctx); + OPENSSL_free(cctx); + } +} + +static int cmac_copy(EVP_MAC_IMPL *cdst, EVP_MAC_IMPL *csrc) +{ + if (!CMAC_CTX_copy(cdst->ctx, csrc->ctx)) + return 0; + + cdst->tmpengine = csrc->tmpengine; + cdst->tmpcipher = csrc->tmpcipher; + return 1; +} + +static size_t cmac_size(EVP_MAC_IMPL *cctx) +{ + return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(cctx->ctx)); +} + +static int cmac_init(EVP_MAC_IMPL *cctx) +{ + int rv = CMAC_Init(cctx->ctx, NULL, 0, cctx->tmpcipher, + (ENGINE *)cctx->tmpengine); + cctx->tmpcipher = NULL; + cctx->tmpengine = NULL; + + return rv; +} + +static int cmac_update(EVP_MAC_IMPL *cctx, const unsigned char *data, + size_t datalen) +{ + return CMAC_Update(cctx->ctx, data, datalen); +} + +static int cmac_final(EVP_MAC_IMPL *cctx, unsigned char *out) +{ + size_t hlen; + + return CMAC_Final(cctx->ctx, out, &hlen); +} + +static int cmac_ctrl(EVP_MAC_IMPL *cctx, int cmd, va_list args) +{ + switch (cmd) { + case EVP_MAC_CTRL_SET_KEY: + { + const unsigned char *key = va_arg(args, const unsigned char *); + size_t keylen = va_arg(args, size_t); + int rv = CMAC_Init(cctx->ctx, key, keylen, cctx->tmpcipher, + (ENGINE *)cctx->tmpengine); + + cctx->tmpcipher = NULL; + cctx->tmpengine = NULL; + + return rv; + } + break; + case EVP_MAC_CTRL_SET_CIPHER: + cctx->tmpcipher = va_arg(args, const EVP_CIPHER *); + break; + case EVP_MAC_CTRL_SET_ENGINE: + cctx->tmpengine = va_arg(args, const ENGINE *); + break; + default: + return -2; + } + return 1; +} + +static int cmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...) +{ + int rv; + va_list args; + + va_start(args, cmd); + rv = cmac_ctrl(hctx, cmd, args); + va_end(args); + + return rv; +} + +static int cmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen) +{ + return cmac_ctrl_int(hctx, cmd, buf, buflen); +} + +static int cmac_ctrl_str(EVP_MAC_IMPL *cctx, const char *type, + const char *value) +{ + if (!value) + return 0; + if (strcmp(type, "cipher") == 0) { + const EVP_CIPHER *c = EVP_get_cipherbyname(value); + + if (c == NULL) + return 0; + return cmac_ctrl_int(cctx, EVP_MAC_CTRL_SET_CIPHER, c); + } + if (strcmp(type, "key") == 0) + return EVP_str2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "hexkey") == 0) + return EVP_hex2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY, + value); + return -2; +} + +const EVP_MAC cmac_meth = { + EVP_MAC_CMAC, + cmac_new, + cmac_copy, + cmac_free, + cmac_size, + cmac_init, + cmac_update, + cmac_final, + cmac_ctrl, + cmac_ctrl_str +}; diff --git a/crypto/cmac/cm_pmeth.c b/crypto/cmac/cm_pmeth.c deleted file mode 100644 index 10748f14..00000000 --- a/crypto/cmac/cm_pmeth.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include -#include -#include "internal/evp_int.h" - -/* The context structure and "key" is simply a CMAC_CTX */ - -static int pkey_cmac_init(EVP_PKEY_CTX *ctx) -{ - ctx->data = CMAC_CTX_new(); - if (ctx->data == NULL) - return 0; - ctx->keygen_info_count = 0; - return 1; -} - -static int pkey_cmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) -{ - if (!pkey_cmac_init(dst)) - return 0; - if (!CMAC_CTX_copy(dst->data, src->data)) - return 0; - return 1; -} - -static void pkey_cmac_cleanup(EVP_PKEY_CTX *ctx) -{ - CMAC_CTX_free(ctx->data); -} - -static int pkey_cmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) -{ - CMAC_CTX *cmkey = CMAC_CTX_new(); - CMAC_CTX *cmctx = ctx->data; - if (cmkey == NULL) - return 0; - if (!CMAC_CTX_copy(cmkey, cmctx)) { - CMAC_CTX_free(cmkey); - return 0; - } - EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmkey); - - return 1; -} - -static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - if (!CMAC_Update(EVP_MD_CTX_pkey_ctx(ctx)->data, data, count)) - return 0; - return 1; -} - -static int cmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) -{ - EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); - EVP_MD_CTX_set_update_fn(mctx, int_update); - return 1; -} - -static int cmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, - EVP_MD_CTX *mctx) -{ - return CMAC_Final(ctx->data, sig, siglen); -} - -static int pkey_cmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) -{ - CMAC_CTX *cmctx = ctx->data; - switch (type) { - - case EVP_PKEY_CTRL_SET_MAC_KEY: - if (!p2 || p1 < 0) - return 0; - if (!CMAC_Init(cmctx, p2, p1, NULL, NULL)) - return 0; - break; - - case EVP_PKEY_CTRL_CIPHER: - if (!CMAC_Init(cmctx, NULL, 0, p2, ctx->engine)) - return 0; - break; - - case EVP_PKEY_CTRL_MD: - if (ctx->pkey && !CMAC_CTX_copy(ctx->data, - (CMAC_CTX *)ctx->pkey->pkey.ptr)) - return 0; - if (!CMAC_Init(cmctx, NULL, 0, NULL, NULL)) - return 0; - break; - - default: - return -2; - - } - return 1; -} - -static int pkey_cmac_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) -{ - if (!value) { - return 0; - } - if (strcmp(type, "cipher") == 0) { - const EVP_CIPHER *c; - c = EVP_get_cipherbyname(value); - if (!c) - return 0; - return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_CIPHER, -1, (void *)c); - } - if (strcmp(type, "key") == 0) - return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); - if (strcmp(type, "hexkey") == 0) - return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); - return -2; -} - -const EVP_PKEY_METHOD cmac_pkey_meth = { - EVP_PKEY_CMAC, - EVP_PKEY_FLAG_SIGCTX_CUSTOM, - pkey_cmac_init, - pkey_cmac_copy, - pkey_cmac_cleanup, - - 0, 0, - - 0, - pkey_cmac_keygen, - - 0, 0, - - 0, 0, - - 0, 0, - - cmac_signctx_init, - cmac_signctx, - - 0, 0, - - 0, 0, - - 0, 0, - - 0, 0, - - pkey_cmac_ctrl, - pkey_cmac_ctrl_str -}; diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 46f4f01e..383d853b 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -327,6 +327,12 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, if (mctx == NULL) goto err; + /* make sure L > N, otherwise we'll get trapped in an infinite loop */ + if (L <= N) { + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); + goto err; + } + if (evpmd == NULL) { if (N == 160) evpmd = EVP_sha1(); diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index ac1f65a5..2dd2d748 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -9,6 +9,7 @@ #include #include "internal/cryptlib.h" +#include "internal/bn_int.h" #include #include #include "dsa_locl.h" @@ -23,6 +24,8 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa); static int dsa_init(DSA *dsa); static int dsa_finish(DSA *dsa); +static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, + BN_CTX *ctx); static DSA_METHOD openssl_dsa_meth = { "OpenSSL DSA method", @@ -178,9 +181,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, { BN_CTX *ctx = NULL; BIGNUM *k, *kinv = NULL, *r = *rp; - BIGNUM *l, *m; + BIGNUM *l; int ret = 0; - int q_bits; + int q_bits, q_words; if (!dsa->p || !dsa->q || !dsa->g) { DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS); @@ -189,8 +192,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, k = BN_new(); l = BN_new(); - m = BN_new(); - if (k == NULL || l == NULL || m == NULL) + if (k == NULL || l == NULL) goto err; if (ctx_in == NULL) { @@ -201,9 +203,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, /* Preallocate space */ q_bits = BN_num_bits(dsa->q); - if (!BN_set_bit(k, q_bits) - || !BN_set_bit(l, q_bits) - || !BN_set_bit(m, q_bits)) + q_words = bn_get_top(dsa->q); + if (!bn_wexpand(k, q_words + 2) + || !bn_wexpand(l, q_words + 2)) goto err; /* Get random k */ @@ -238,14 +240,17 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, * small timing information leakage. We then choose the sum that is * one bit longer than the modulus. * - * TODO: revisit the BN_copy aiming for a memory access agnostic - * conditional copy. + * There are some concerns about the efficacy of doing this. More + * specificly refer to the discussion starting with: + * https://github.com/openssl/openssl/pull/7486#discussion_r228323705 + * The fix is to rework BN so these gymnastics aren't required. */ if (!BN_add(l, k, dsa->q) - || !BN_add(m, l, dsa->q) - || !BN_copy(k, BN_num_bits(l) > q_bits ? l : m)) + || !BN_add(k, l, dsa->q)) goto err; + BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2); + if ((dsa)->meth->bn_mod_exp != NULL) { if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx, dsa->method_mont_p)) @@ -258,8 +263,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, if (!BN_mod(r, r, dsa->q, ctx)) goto err; - /* Compute part of 's = inv(k) (m + xr) mod q' */ - if ((kinv = BN_mod_inverse(NULL, k, dsa->q, ctx)) == NULL) + /* Compute part of 's = inv(k) (m + xr) mod q' */ + if ((kinv = dsa_mod_inverse_fermat(k, dsa->q, ctx)) == NULL) goto err; BN_clear_free(*kinvp); @@ -273,7 +278,6 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BN_CTX_free(ctx); BN_clear_free(k); BN_clear_free(l); - BN_clear_free(m); return ret; } @@ -393,3 +397,31 @@ static int dsa_finish(DSA *dsa) BN_MONT_CTX_free(dsa->method_mont_p); return 1; } + +/* + * Compute the inverse of k modulo q. + * Since q is prime, Fermat's Little Theorem applies, which reduces this to + * mod-exp operation. Both the exponent and modulus are public information + * so a mod-exp that doesn't leak the base is sufficient. A newly allocated + * BIGNUM is returned which the caller must free. + */ +static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, + BN_CTX *ctx) +{ + BIGNUM *res = NULL; + BIGNUM *r, *e; + + if ((r = BN_new()) == NULL) + return NULL; + + BN_CTX_start(ctx); + if ((e = BN_CTX_get(ctx)) != NULL + && BN_set_word(r, 2) + && BN_sub(e, q, r) + && BN_mod_exp_mont(r, k, e, q, ctx, NULL)) + res = r; + else + BN_free(r); + BN_CTX_end(ctx); + return res; +} diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 21302685..a3164b5b 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -699,7 +699,7 @@ static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) return 0; - if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0) + if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) return 0; kdf_md = EVP_get_digestbynid(kdfmd_nid); @@ -864,7 +864,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) ecdh_nid = NID_dh_cofactor_kdf; if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { - kdf_type = EVP_PKEY_ECDH_KDF_X9_62; + kdf_type = EVP_PKEY_ECDH_KDF_X9_63; if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) goto err; } else diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index 7e1b3650..0e0a5e13 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -206,8 +206,8 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, */ cardinality_bits = BN_num_bits(cardinality); group_top = bn_get_top(cardinality); - if ((bn_wexpand(k, group_top + 1) == NULL) - || (bn_wexpand(lambda, group_top + 1) == NULL)) { + if ((bn_wexpand(k, group_top + 2) == NULL) + || (bn_wexpand(lambda, group_top + 2) == NULL)) { ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); goto err; } @@ -244,7 +244,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, * k := scalar + 2*cardinality */ kbit = BN_is_bit_set(lambda, cardinality_bits); - BN_consttime_swap(kbit, k, lambda, group_top + 1); + BN_consttime_swap(kbit, k, lambda, group_top + 2); group_top = bn_get_top(group->field); if ((bn_wexpand(s->X, group_top) == NULL) diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index 5bee031b..f4ad0749 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -209,7 +209,7 @@ static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) goto err; /* Do KDF stuff */ - if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen, + if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) goto err; rv = 1; @@ -281,7 +281,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_EC_KDF_TYPE: if (p1 == -2) return dctx->kdf_type; - if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62) + if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63) return -2; dctx->kdf_type = p1; return 1; diff --git a/crypto/ec/ecdh_kdf.c b/crypto/ec/ecdh_kdf.c index d47486eb..c21e7880 100644 --- a/crypto/ec/ecdh_kdf.c +++ b/crypto/ec/ecdh_kdf.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,12 +10,13 @@ #include #include #include +#include "ec_lcl.h" -/* Key derivation function from X9.62/SECG */ +/* Key derivation function from X9.63/SECG */ /* Way more than we will ever need */ #define ECDH_KDF_MAX (1 << 30) -int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, +int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md) @@ -66,3 +67,17 @@ int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, EVP_MD_CTX_free(mctx); return rv; } + +/*- + * The old name for ecdh_KDF_X9_63 + * Retained for ABI compatibility + */ +#if OPENSSL_API_COMPAT < 0x10200000L +int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md) +{ + return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md); +} +#endif diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 489ccc09..151bc831 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -740,6 +740,11 @@ EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate +EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl +EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str +EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy +EVP_F_EVP_MAC_CTX_NEW:213:EVP_MAC_CTX_new +EVP_F_EVP_MAC_INIT:212:EVP_MAC_init EVP_F_EVP_MD_CTX_COPY_EX:110:EVP_MD_CTX_copy_ex EVP_F_EVP_MD_SIZE:162:EVP_MD_size EVP_F_EVP_OPENINIT:102:EVP_OpenInit @@ -802,6 +807,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen +EVP_F_PKEY_MAC_INIT:214:pkey_mac_init EVP_F_PKEY_SET_TYPE:158:pkey_set_type EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth EVP_F_RC5_CTRL:125:rc5_ctrl diff --git a/crypto/evp/build.info b/crypto/evp/build.info index cc33ac3c..84193b09 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -12,7 +12,8 @@ SOURCE[../../libcrypto]=\ evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ - e_chacha20_poly1305.c cmeth_lib.c + e_chacha20_poly1305.c cmeth_lib.c \ + mac_lib.c c_allm.c pkey_mac.c INCLUDE[e_aes.o]=.. ../modes INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes diff --git a/crypto/evp/c_allm.c b/crypto/evp/c_allm.c new file mode 100644 index 00000000..2bcd9dc9 --- /dev/null +++ b/crypto/evp/c_allm.c @@ -0,0 +1,22 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/evp_int.h" + +void openssl_add_all_macs_int(void) +{ +#ifndef OPENSSL_NO_CMAC + EVP_add_mac(&cmac_meth); +#endif + EVP_add_mac(&hmac_meth); +#ifndef OPENSSL_NO_SIPHASH + EVP_add_mac(&siphash_meth); +#endif +} diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index ec6efb6e..32760db0 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -54,6 +54,11 @@ static const ERR_STRING_DATA EVP_str_functs[] = { {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0), "EVP_EncryptFinal_ex"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_NEW, 0), "EVP_MAC_CTX_new"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_INIT, 0), "EVP_MAC_init"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_CTX_COPY_EX, 0), "EVP_MD_CTX_copy_ex"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_SIZE, 0), "EVP_MD_size"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_OPENINIT, 0), "EVP_OpenInit"}, @@ -145,6 +150,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = { "PKCS5_v2_PBKDF2_keyivgen"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0), "PKCS5_v2_scrypt_keyivgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"}, diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 1b3c9840..01c89399 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -526,3 +526,30 @@ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags) { return (ctx->flags & flags); } + +int EVP_str2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen), + void *ctx, int cmd, const char *value) +{ + size_t len; + + len = strlen(value); + if (len > INT_MAX) + return -1; + return cb(ctx, cmd, (void *)value, len); +} + +int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen), + void *ctx, int cmd, const char *hex) +{ + unsigned char *bin; + long binlen; + int rv = -1; + + bin = OPENSSL_hexstr2buf(hex, &binlen); + if (bin == NULL) + return 0; + if (binlen <= INT_MAX) + rv = cb(ctx, cmd, bin, binlen); + OPENSSL_free(bin); + return rv; +} diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index f1589d68..eaee472b 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -41,6 +41,11 @@ struct evp_cipher_ctx_st { unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ } /* EVP_CIPHER_CTX */ ; +struct evp_mac_ctx_st { + const EVP_MAC *meth; /* Method structure */ + void *data; /* Individual method data */ +} /* EVP_MAC_CTX */; + int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c new file mode 100644 index 00000000..2786a012 --- /dev/null +++ b/crypto/evp/mac_lib.c @@ -0,0 +1,185 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/nelem.h" +#include "internal/evp_int.h" +#include "evp_locl.h" + +EVP_MAC_CTX *EVP_MAC_CTX_new_id(int id) +{ + const EVP_MAC *mac = EVP_get_macbynid(id); + + if (mac == NULL) + return NULL; + return EVP_MAC_CTX_new(mac); +} + +EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac) +{ + EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX)); + + if (ctx == NULL || (ctx->data = mac->new()) == NULL) { + EVPerr(EVP_F_EVP_MAC_CTX_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ctx); + ctx = NULL; + } else { + ctx->meth = mac; + } + return ctx; +} + +void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx) +{ + if (ctx != NULL && ctx->data != NULL) { + ctx->meth->free(ctx->data); + ctx->data = NULL; + } + OPENSSL_free(ctx); +} + +int EVP_MAC_CTX_copy(EVP_MAC_CTX *dst, EVP_MAC_CTX *src) +{ + EVP_MAC_IMPL *macdata; + + if (src->data != NULL && !dst->meth->copy(dst->data, src->data)) + return 0; + + macdata = dst->data; + *dst = *src; + dst->data = macdata; + + return 1; +} + +const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx) +{ + return ctx->meth; +} + +size_t EVP_MAC_size(EVP_MAC_CTX *ctx) +{ + if (ctx->data != NULL) + return ctx->meth->size(ctx->data); + /* If the MAC hasn't been initialized yet, we return zero */ + return 0; +} + +int EVP_MAC_init(EVP_MAC_CTX *ctx) +{ + return ctx->meth->init(ctx->data); +} + +int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen) +{ + return ctx->meth->update(ctx->data, data, datalen); +} + +int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen) +{ + int l = ctx->meth->size(ctx->data); + + if (l < 0) + return 0; + if (poutlen != NULL) + *poutlen = l; + if (out == NULL) + return 1; + return ctx->meth->final(ctx->data, out); +} + +int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...) +{ + int ok = -1; + va_list args; + + va_start(args, cmd); + ok = EVP_MAC_vctrl(ctx, cmd, args); + va_end(args); + + if (ok == -2) + EVPerr(EVP_F_EVP_MAC_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + + return ok; +} + +int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args) +{ + int ok = 1; + + if (ctx == NULL || ctx->meth == NULL) + return -2; + + switch (cmd) { +#if 0 + case ...: + /* code */ + ok = 1; + break; +#endif + default: + if (ctx->meth->ctrl != NULL) + ok = ctx->meth->ctrl(ctx->data, cmd, args); + else + ok = -2; + break; + } + + return ok; +} + +int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value) +{ + int ok = 1; + + if (ctx == NULL || ctx->meth == NULL || ctx->meth->ctrl_str == NULL) { + EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + + ok = ctx->meth->ctrl_str(ctx->data, type, value); + + if (ok == -2) + EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); + return ok; +} + +int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value) +{ + size_t len; + + len = strlen(value); + if (len > INT_MAX) + return -1; + return EVP_MAC_ctrl(ctx, cmd, value, len); +} + +int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *hex) +{ + unsigned char *bin; + long binlen; + int rv = -1; + + bin = OPENSSL_hexstr2buf(hex, &binlen); + if (bin == NULL) + return 0; + if (binlen <= INT_MAX) + rv = EVP_MAC_ctrl(ctx, cmd, bin, (size_t)binlen); + OPENSSL_free(bin); + return rv; +} + +int EVP_MAC_nid(const EVP_MAC *mac) +{ + return mac->type; +} diff --git a/crypto/evp/names.c b/crypto/evp/names.c index 077c2a6c..6cdab225 100644 --- a/crypto/evp/names.c +++ b/crypto/evp/names.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -55,6 +55,22 @@ int EVP_add_digest(const EVP_MD *md) return r; } +int EVP_add_mac(const EVP_MAC *m) +{ + int r; + + if (m == NULL) + return 0; + + r = OBJ_NAME_add(OBJ_nid2sn(m->type), OBJ_NAME_TYPE_MAC_METH, + (const char *)m); + if (r == 0) + return 0; + r = OBJ_NAME_add(OBJ_nid2ln(m->type), OBJ_NAME_TYPE_MAC_METH, + (const char *)m); + return r; +} + const EVP_CIPHER *EVP_get_cipherbyname(const char *name) { const EVP_CIPHER *cp; @@ -77,8 +93,20 @@ const EVP_MD *EVP_get_digestbyname(const char *name) return cp; } +const EVP_MAC *EVP_get_macbyname(const char *name) +{ + const EVP_MAC *mp; + + if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL)) + return NULL; + + mp = (const EVP_MAC *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MAC_METH); + return mp; +} + void evp_cleanup_int(void) { + OBJ_NAME_cleanup(OBJ_NAME_TYPE_MAC_METH); OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH); OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH); /* @@ -178,3 +206,48 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md, dc.arg = arg; OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); } + +struct doall_mac { + void *arg; + void (*fn) (const EVP_MAC *ciph, + const char *from, const char *to, void *arg); +}; + +static void do_all_mac_fn(const OBJ_NAME *nm, void *arg) +{ + struct doall_mac *dc = arg; + + if (nm->alias) + dc->fn(NULL, nm->name, nm->data, dc->arg); + else + dc->fn((const EVP_MAC *)nm->data, nm->name, NULL, dc->arg); +} + +void EVP_MAC_do_all(void (*fn) + (const EVP_MAC *ciph, const char *from, const char *to, + void *x), void *arg) +{ + struct doall_mac dc; + + /* Ignore errors */ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL); + + dc.fn = fn; + dc.arg = arg; + OBJ_NAME_do_all(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc); +} + +void EVP_MAC_do_all_sorted(void (*fn) + (const EVP_MAC *ciph, const char *from, + const char *to, void *x), void *arg) +{ + struct doall_mac dc; + + /* Ignore errors */ + OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL); + + dc.fn = fn; + dc.arg = arg; + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc); +} + diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 9429be97..154ef788 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -319,7 +319,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, { #ifndef OPENSSL_NO_CMAC EVP_PKEY *ret = EVP_PKEY_new(); - CMAC_CTX *cmctx = CMAC_CTX_new(); + EVP_MAC_CTX *cmctx = EVP_MAC_CTX_new_id(EVP_MAC_CMAC); if (ret == NULL || cmctx == NULL @@ -328,7 +328,9 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, goto err; } - if (!CMAC_Init(cmctx, priv, len, cipher, e)) { + if (EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_ENGINE, e) <= 0 + || EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_CIPHER, cipher) <= 0 + || EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_KEY, priv, len) <= 0) { EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED); goto err; } @@ -338,7 +340,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, err: EVP_PKEY_free(ret); - CMAC_CTX_free(cmctx); + EVP_MAC_CTX_free(cmctx); return NULL; #else EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, diff --git a/crypto/evp/pkey_mac.c b/crypto/evp/pkey_mac.c new file mode 100644 index 00000000..d8c0e897 --- /dev/null +++ b/crypto/evp/pkey_mac.c @@ -0,0 +1,427 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/evp_int.h" + +/* MAC PKEY context structure */ + +typedef struct { + EVP_MAC_CTX *ctx; + + /* + * We know of two MAC types: + * + * 1. those who take a secret in raw form, i.e. raw data as a + * ASN1_OCTET_STRING embedded in a EVP_PKEY. So far, that's + * all of them but CMAC. + * 2. those who take a secret with associated cipher in very generic + * form, i.e. a complete EVP_MAC_CTX embedded in a PKEY. So far, + * only CMAC does this. + * + * (one might wonder why the second form isn't used for all) + */ +#define MAC_TYPE_RAW 1 /* HMAC like MAC type (all but CMAC so far) */ +#define MAC_TYPE_MAC 2 /* CMAC like MAC type (only CMAC known so far) */ + int type; + + /* The following is only used for MAC_TYPE_RAW implementations */ + struct { + const EVP_MD *md; /* temp storage of MD */ + ASN1_OCTET_STRING ktmp; /* temp storage for key */ + } raw_data; +} MAC_PKEY_CTX; + +static int pkey_mac_init(EVP_PKEY_CTX *ctx) +{ + MAC_PKEY_CTX *hctx; + int nid = ctx->pmeth->pkey_id; + + if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { + EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* We're being smart and using the same base NIDs for PKEY and for MAC */ + hctx->ctx = EVP_MAC_CTX_new_id(nid); + if (hctx->ctx == NULL) { + OPENSSL_free(hctx); + return 0; + } + + if (nid == EVP_PKEY_CMAC) { + hctx->type = MAC_TYPE_MAC; + } else { + hctx->type = MAC_TYPE_RAW; + hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING; + } + + EVP_PKEY_CTX_set_data(ctx, hctx); + ctx->keygen_info_count = 0; + + return 1; +} + +static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx); + +static int pkey_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +{ + MAC_PKEY_CTX *sctx, *dctx; + + if (!pkey_mac_init(dst)) + return 0; + + sctx = EVP_PKEY_CTX_get_data(src); + dctx = EVP_PKEY_CTX_get_data(dst); + + if (!EVP_MAC_CTX_copy(dctx->ctx, sctx->ctx)) + goto err; + + switch (dctx->type) { + case MAC_TYPE_RAW: + dctx->raw_data.md = sctx->raw_data.md; + if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL && + !ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp)) + goto err; + break; + case MAC_TYPE_MAC: + /* Nothing more to do */ + break; + default: + /* This should be dead code */ + return 0; + } + return 1; + err: + pkey_mac_cleanup (dst); + return 0; +} + +static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + if (hctx != NULL) { + switch (hctx->type) { + case MAC_TYPE_RAW: + OPENSSL_clear_free(hctx->raw_data.ktmp.data, + hctx->raw_data.ktmp.length); + break; + } + EVP_MAC_CTX_free(hctx->ctx); + OPENSSL_free(hctx); + EVP_PKEY_CTX_set_data(ctx, NULL); + } +} + +static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + int nid = ctx->pmeth->pkey_id; + + switch (hctx->type) { + case MAC_TYPE_RAW: + { + ASN1_OCTET_STRING *hkey = NULL; + + if (!hctx->raw_data.ktmp.data) + return 0; + hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp); + if (!hkey) + return 0; + EVP_PKEY_assign(pkey, nid, hkey); + } + break; + case MAC_TYPE_MAC: + { + EVP_MAC_CTX *cmkey = EVP_MAC_CTX_new_id(nid); + + if (cmkey == NULL) + return 0; + if (!EVP_MAC_CTX_copy(cmkey, hctx->ctx)) { + EVP_MAC_CTX_free(cmkey); + return 0; + } + EVP_PKEY_assign(pkey, nid, cmkey); + } + break; + default: + /* This should be dead code */ + return 0; + } + + return 1; +} + +static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx)); + + if (!EVP_MAC_update(hctx->ctx, data, count)) + return 0; + return 1; +} + +static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + ASN1_OCTET_STRING *key = NULL; + int rv = 1; + /* + * For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that + * gets the key passed as an ASN.1 OCTET STRING, we set the key here, + * as this may be only time it's set during a DigestSign. + * + * MACs that pass around the key in form of EVP_MAC_CTX are setting + * the key through other mechanisms. (this is only CMAC for now) + */ + int set_key = + hctx->type == MAC_TYPE_RAW + && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0; + + if (set_key) { + if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx)) + != EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx))) + return 0; + key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx)); + if (key == NULL) + return 0; + } + + /* Some MACs don't support this control... that's fine */ + EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS, + EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT)); + + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); + EVP_MD_CTX_set_update_fn(mctx, int_update); + + if (set_key) + rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data, + key->length); + return rv > 0; +} + +static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, EVP_MD_CTX *mctx) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + return EVP_MAC_final(hctx->ctx, sig, siglen); +} + +static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + switch (type) { + + case EVP_PKEY_CTRL_CIPHER: + switch (hctx->type) { + case MAC_TYPE_RAW: + return -2; /* The raw types don't support ciphers */ + case MAC_TYPE_MAC: + { + int rv; + + if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE, + ctx->engine)) < 0 + || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER, + p2)) < 0 + || !(rv = EVP_MAC_init(hctx->ctx))) + return rv; + } + break; + default: + /* This should be dead code */ + return 0; + } + break; + + case EVP_PKEY_CTRL_MD: + switch (hctx->type) { + case MAC_TYPE_RAW: + hctx->raw_data.md = p2; + break; + case MAC_TYPE_MAC: + if (ctx->pkey != NULL + && !EVP_MAC_CTX_copy(hctx->ctx, + (EVP_MAC_CTX *)ctx->pkey->pkey.ptr)) + return 0; + if (!EVP_MAC_init(hctx->ctx)) + return 0; + break; + default: + /* This should be dead code */ + return 0; + } + break; + + case EVP_PKEY_CTRL_SET_DIGEST_SIZE: + return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1); + + case EVP_PKEY_CTRL_SET_MAC_KEY: + switch (hctx->type) { + case MAC_TYPE_RAW: + if ((!p2 && p1 > 0) || (p1 < -1)) + return 0; + if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1)) + return 0; + break; + case MAC_TYPE_MAC: + if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1)) + return 0; + break; + default: + /* This should be dead code */ + return 0; + } + break; + + case EVP_PKEY_CTRL_DIGESTINIT: + switch (hctx->type) { + case MAC_TYPE_RAW: + /* Ensure that we have attached the implementation */ + if (!EVP_MAC_init(hctx->ctx)) + return 0; + { + int rv; + ASN1_OCTET_STRING *key = + (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr; + + if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE, + ctx->engine)) < 0 + || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD, + hctx->raw_data.md)) < 0 + || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, + key->data, key->length)) < 0) + return rv; + } + break; + case MAC_TYPE_MAC: + return -2; /* The mac types don't support ciphers */ + default: + /* This should be dead code */ + return 0; + } + break; + + default: + return -2; + + } + return 1; +} + +static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) +{ + MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); + + return EVP_MAC_ctrl_str(hctx->ctx, type, value); +} + +const EVP_PKEY_METHOD cmac_pkey_meth = { + EVP_PKEY_CMAC, + EVP_PKEY_FLAG_SIGCTX_CUSTOM, + pkey_mac_init, + pkey_mac_copy, + pkey_mac_cleanup, + + 0, 0, + + 0, + pkey_mac_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_mac_signctx_init, + pkey_mac_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_mac_ctrl, + pkey_mac_ctrl_str +}; + +const EVP_PKEY_METHOD hmac_pkey_meth = { + EVP_PKEY_HMAC, + 0, + pkey_mac_init, + pkey_mac_copy, + pkey_mac_cleanup, + + 0, 0, + + 0, + pkey_mac_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_mac_signctx_init, + pkey_mac_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_mac_ctrl, + pkey_mac_ctrl_str +}; + +const EVP_PKEY_METHOD siphash_pkey_meth = { + EVP_PKEY_SIPHASH, + EVP_PKEY_FLAG_SIGCTX_CUSTOM, + pkey_mac_init, + pkey_mac_copy, + pkey_mac_cleanup, + + 0, 0, + + 0, + pkey_mac_keygen, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_mac_signctx_init, + pkey_mac_signctx, + + 0, 0, + + 0, 0, + + 0, 0, + + 0, 0, + + pkey_mac_ctrl, + pkey_mac_ctrl_str +}; diff --git a/crypto/hmac/build.info b/crypto/hmac/build.info index 09f67c2a..f63524d3 100644 --- a/crypto/hmac/build.info +++ b/crypto/hmac/build.info @@ -1,3 +1,3 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ - hmac.c hm_ameth.c hm_pmeth.c + hmac.c hm_ameth.c hm_meth.c diff --git a/crypto/hmac/hm_meth.c b/crypto/hmac/hm_meth.c new file mode 100644 index 00000000..fb488306 --- /dev/null +++ b/crypto/hmac/hm_meth.c @@ -0,0 +1,173 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include "internal/evp_int.h" + +/* local HMAC context structure */ + +/* typedef EVP_MAC_IMPL */ +struct evp_mac_impl_st { + /* tmpmd and tmpengine are set to NULL after a CMAC_Init call */ + const EVP_MD *tmpmd; /* HMAC digest */ + const ENGINE *tmpengine; /* HMAC digest engine */ + HMAC_CTX *ctx; /* HMAC context */ +}; + +static EVP_MAC_IMPL *hmac_new(void) +{ + EVP_MAC_IMPL *hctx; + + if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL + || (hctx->ctx = HMAC_CTX_new()) == NULL) { + OPENSSL_free(hctx); + return NULL; + } + + return hctx; +} + +static void hmac_free(EVP_MAC_IMPL *hctx) +{ + if (hctx != NULL) { + HMAC_CTX_free(hctx->ctx); + OPENSSL_free(hctx); + } +} + +static int hmac_copy(EVP_MAC_IMPL *hdst, EVP_MAC_IMPL *hsrc) +{ + if (!HMAC_CTX_copy(hdst->ctx, hsrc->ctx)) + return 0; + + hdst->tmpengine = hsrc->tmpengine; + hdst->tmpmd = hsrc->tmpmd; + return 1; +} + +static size_t hmac_size(EVP_MAC_IMPL *hctx) +{ + return HMAC_size(hctx->ctx); +} + +static int hmac_init(EVP_MAC_IMPL *hctx) +{ + int rv = 1; + + /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */ + if (hctx->tmpmd != NULL) + rv = HMAC_Init_ex(hctx->ctx, NULL, 0, hctx->tmpmd, + (ENGINE * )hctx->tmpengine); + hctx->tmpengine = NULL; + hctx->tmpmd = NULL; + return rv; +} + +static int hmac_update(EVP_MAC_IMPL *hctx, const unsigned char *data, + size_t datalen) +{ + return HMAC_Update(hctx->ctx, data, datalen); +} + +static int hmac_final(EVP_MAC_IMPL *hctx, unsigned char *out) +{ + unsigned int hlen; + + return HMAC_Final(hctx->ctx, out, &hlen); +} + +static int hmac_ctrl(EVP_MAC_IMPL *hctx, int cmd, va_list args) +{ + switch (cmd) { + case EVP_MAC_CTRL_SET_FLAGS: + { + unsigned long flags = va_arg(args, unsigned long); + + HMAC_CTX_set_flags(hctx->ctx, flags); + } + break; + case EVP_MAC_CTRL_SET_KEY: + { + const unsigned char *key = va_arg(args, const unsigned char *); + size_t keylen = va_arg(args, size_t); + int rv = HMAC_Init_ex(hctx->ctx, key, keylen, hctx->tmpmd, + (ENGINE *)hctx->tmpengine); + + hctx->tmpengine = NULL; + hctx->tmpmd = NULL; + return rv; + } + break; + case EVP_MAC_CTRL_SET_MD: + hctx->tmpmd = va_arg(args, const EVP_MD *); + break; + case EVP_MAC_CTRL_SET_ENGINE: + hctx->tmpengine = va_arg(args, const ENGINE *); + break; + default: + return -2; + + } + return 1; +} + +static int hmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...) +{ + int rv; + va_list args; + + va_start(args, cmd); + rv = hmac_ctrl(hctx, cmd, args); + va_end(args); + + return rv; +} + +static int hmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen) +{ + return hmac_ctrl_int(hctx, cmd, buf, buflen); +} + +static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type, + const char *value) +{ + if (!value) + return 0; + if (strcmp(type, "digest") == 0) { + const EVP_MD *d = EVP_get_digestbyname(value); + + if (d == NULL) + return 0; + return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d); + } + if (strcmp(type, "key") == 0) + return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "hexkey") == 0) + return EVP_hex2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY, + value); + return -2; +} + +const EVP_MAC hmac_meth = { + EVP_MAC_HMAC, + hmac_new, + hmac_copy, + hmac_free, + hmac_size, + hmac_init, + hmac_update, + hmac_final, + hmac_ctrl, + hmac_ctrl_str +}; diff --git a/crypto/hmac/hm_pmeth.c b/crypto/hmac/hm_pmeth.c deleted file mode 100644 index 55dd27d6..00000000 --- a/crypto/hmac/hm_pmeth.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include -#include -#include -#include "internal/evp_int.h" - -/* HMAC pkey context structure */ - -typedef struct { - const EVP_MD *md; /* MD for HMAC use */ - ASN1_OCTET_STRING ktmp; /* Temp storage for key */ - HMAC_CTX *ctx; -} HMAC_PKEY_CTX; - -static int pkey_hmac_init(EVP_PKEY_CTX *ctx) -{ - HMAC_PKEY_CTX *hctx; - - if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { - CRYPTOerr(CRYPTO_F_PKEY_HMAC_INIT, ERR_R_MALLOC_FAILURE); - return 0; - } - hctx->ktmp.type = V_ASN1_OCTET_STRING; - hctx->ctx = HMAC_CTX_new(); - if (hctx->ctx == NULL) { - OPENSSL_free(hctx); - return 0; - } - - ctx->data = hctx; - ctx->keygen_info_count = 0; - - return 1; -} - -static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx); - -static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) -{ - HMAC_PKEY_CTX *sctx, *dctx; - - /* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */ - if (!pkey_hmac_init(dst)) - return 0; - sctx = EVP_PKEY_CTX_get_data(src); - dctx = EVP_PKEY_CTX_get_data(dst); - dctx->md = sctx->md; - if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx)) - goto err; - if (sctx->ktmp.data) { - if (!ASN1_OCTET_STRING_set(&dctx->ktmp, - sctx->ktmp.data, sctx->ktmp.length)) - goto err; - } - return 1; -err: - /* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */ - pkey_hmac_cleanup (dst); - return 0; -} - -static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx) -{ - HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); - - if (hctx != NULL) { - HMAC_CTX_free(hctx->ctx); - OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length); - OPENSSL_free(hctx); - EVP_PKEY_CTX_set_data(ctx, NULL); - } -} - -static int pkey_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) -{ - ASN1_OCTET_STRING *hkey = NULL; - HMAC_PKEY_CTX *hctx = ctx->data; - if (!hctx->ktmp.data) - return 0; - hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp); - if (!hkey) - return 0; - EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey); - - return 1; -} - -static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - HMAC_PKEY_CTX *hctx = EVP_MD_CTX_pkey_ctx(ctx)->data; - if (!HMAC_Update(hctx->ctx, data, count)) - return 0; - return 1; -} - -static int hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) -{ - HMAC_PKEY_CTX *hctx = ctx->data; - HMAC_CTX_set_flags(hctx->ctx, - EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT)); - EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); - EVP_MD_CTX_set_update_fn(mctx, int_update); - return 1; -} - -static int hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, - EVP_MD_CTX *mctx) -{ - unsigned int hlen; - HMAC_PKEY_CTX *hctx = ctx->data; - int l = EVP_MD_CTX_size(mctx); - - if (l < 0) - return 0; - *siglen = l; - if (!sig) - return 1; - - if (!HMAC_Final(hctx->ctx, sig, &hlen)) - return 0; - *siglen = (size_t)hlen; - return 1; -} - -static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) -{ - HMAC_PKEY_CTX *hctx = ctx->data; - ASN1_OCTET_STRING *key; - switch (type) { - - case EVP_PKEY_CTRL_SET_MAC_KEY: - if ((!p2 && p1 > 0) || (p1 < -1)) - return 0; - if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1)) - return 0; - break; - - case EVP_PKEY_CTRL_MD: - hctx->md = p2; - break; - - case EVP_PKEY_CTRL_DIGESTINIT: - key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr; - if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, - ctx->engine)) - return 0; - break; - - default: - return -2; - - } - return 1; -} - -static int pkey_hmac_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) -{ - if (!value) { - return 0; - } - if (strcmp(type, "key") == 0) - return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); - if (strcmp(type, "hexkey") == 0) - return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); - return -2; -} - -const EVP_PKEY_METHOD hmac_pkey_meth = { - EVP_PKEY_HMAC, - 0, - pkey_hmac_init, - pkey_hmac_copy, - pkey_hmac_cleanup, - - 0, 0, - - 0, - pkey_hmac_keygen, - - 0, 0, - - 0, 0, - - 0, 0, - - hmac_signctx_init, - hmac_signctx, - - 0, 0, - - 0, 0, - - 0, 0, - - 0, 0, - - pkey_hmac_ctrl, - pkey_hmac_ctrl_str -}; diff --git a/crypto/include/internal/ec_int.h b/crypto/include/internal/ec_int.h index bb4b5129..182c39cc 100644 --- a/crypto/include/internal/ec_int.h +++ b/crypto/include/internal/ec_int.h @@ -41,5 +41,13 @@ __owur int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, const BIGNUM *x, BN_CTX *ctx); +/*- + * ECDH Key Derivation Function as defined in ANSI X9.63 + */ +int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md); + # endif /* OPENSSL_NO_EC */ #endif diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h index d86aed36..060538e7 100644 --- a/crypto/include/internal/evp_int.h +++ b/crypto/include/internal/evp_int.h @@ -112,6 +112,35 @@ extern const EVP_PKEY_METHOD hkdf_pkey_meth; extern const EVP_PKEY_METHOD poly1305_pkey_meth; extern const EVP_PKEY_METHOD siphash_pkey_meth; +/* struct evp_mac_impl_st is defined by the implementation */ +typedef struct evp_mac_impl_st EVP_MAC_IMPL; +struct evp_mac_st { + int type; + EVP_MAC_IMPL *(*new) (void); + int (*copy) (EVP_MAC_IMPL *macdst, EVP_MAC_IMPL *macsrc); + void (*free) (EVP_MAC_IMPL *macctx); + size_t (*size) (EVP_MAC_IMPL *macctx); + int (*init) (EVP_MAC_IMPL *macctx); + int (*update) (EVP_MAC_IMPL *macctx, const unsigned char *data, + size_t datalen); + int (*final) (EVP_MAC_IMPL *macctx, unsigned char *out); + int (*ctrl) (EVP_MAC_IMPL *macctx, int cmd, va_list args); + int (*ctrl_str) (EVP_MAC_IMPL *macctx, const char *type, const char *value); +}; + +extern const EVP_MAC cmac_meth; +extern const EVP_MAC hmac_meth; +extern const EVP_MAC siphash_meth; + +/* + * This function is internal for now, but can be made external when needed. + * The documentation would read: + * + * EVP_add_mac() adds the MAC implementation C to the internal + * object database. + */ +int EVP_add_mac(const EVP_MAC *mac); + struct evp_md_st { int type; int pkey_type; @@ -423,6 +452,7 @@ struct evp_pkey_st { void openssl_add_all_ciphers_int(void); void openssl_add_all_digests_int(void); +void openssl_add_all_macs_int(void); void evp_cleanup_int(void); void evp_app_cleanup_int(void); diff --git a/crypto/init.c b/crypto/init.c index 209d1a48..fc6aade1 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -235,6 +235,23 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) return 1; } +static CRYPTO_ONCE add_all_macs = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_macs) +{ + /* + * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time + * pulling in all the macs during static linking + */ +#ifndef OPENSSL_NO_AUTOALGINIT +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_macs: " + "openssl_add_all_macs_int()\n"); +# endif + openssl_add_all_macs_int(); +#endif + return 1; +} + DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs) { /* Do nothing */ @@ -619,6 +636,14 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests)) return 0; + if ((opts & OPENSSL_INIT_NO_ADD_ALL_MACS) + && !RUN_ONCE(&add_all_macs, ossl_init_no_add_algs)) + return 0; + + if ((opts & OPENSSL_INIT_ADD_ALL_MACS) + && !RUN_ONCE(&add_all_macs, ossl_init_add_all_macs)) + return 0; + if ((opts & OPENSSL_INIT_ATFORK) && !openssl_init_fork_handlers()) return 0; diff --git a/crypto/kdf/hkdf.c b/crypto/kdf/hkdf.c index ec6090ad..ae46fad6 100644 --- a/crypto/kdf/hkdf.c +++ b/crypto/kdf/hkdf.c @@ -175,6 +175,18 @@ static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, return -2; } +static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx) +{ + HKDF_PKEY_CTX *kctx = ctx->data; + + OPENSSL_clear_free(kctx->key, kctx->key_len); + OPENSSL_clear_free(kctx->salt, kctx->salt_len); + OPENSSL_cleanse(kctx->info, kctx->info_len); + memset(kctx, 0, sizeof(*kctx)); + + return 1; +} + static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { @@ -236,7 +248,7 @@ const EVP_PKEY_METHOD hkdf_pkey_meth = { 0, 0, - 0, + pkey_hkdf_derive_init, pkey_hkdf_derive, pkey_hkdf_ctrl, pkey_hkdf_ctrl_str diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index 36b20c93..c4ecf0c9 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -374,6 +374,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg, max_entropylen += drbg->max_noncelen; } + drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter); + if (drbg->reseed_next_counter) { + drbg->reseed_next_counter++; + if(!drbg->reseed_next_counter) + drbg->reseed_next_counter = 1; + } + if (drbg->get_entropy != NULL) entropylen = drbg->get_entropy(drbg, &entropy, min_entropy, min_entropylen, max_entropylen, 0); @@ -401,27 +408,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg, drbg->state = DRBG_READY; drbg->reseed_gen_counter = 1; drbg->reseed_time = time(NULL); - if (drbg->reseed_prop_counter > 0) { - if (drbg->parent == NULL) - drbg->reseed_prop_counter++; - else - drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter; - } + tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter); end: if (entropy != NULL && drbg->cleanup_entropy != NULL) drbg->cleanup_entropy(drbg, entropy, entropylen); if (nonce != NULL && drbg->cleanup_nonce != NULL) drbg->cleanup_nonce(drbg, nonce, noncelen); - if (drbg->pool != NULL) { - if (drbg->state == DRBG_READY) { - RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, - RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED); - drbg->state = DRBG_ERROR; - } - rand_pool_free(drbg->pool); - drbg->pool = NULL; - } if (drbg->state == DRBG_READY) return 1; return 0; @@ -498,6 +491,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg, } drbg->state = DRBG_ERROR; + + drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter); + if (drbg->reseed_next_counter) { + drbg->reseed_next_counter++; + if(!drbg->reseed_next_counter) + drbg->reseed_next_counter = 1; + } + if (drbg->get_entropy != NULL) entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength, drbg->min_entropylen, @@ -515,12 +516,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg, drbg->state = DRBG_READY; drbg->reseed_gen_counter = 1; drbg->reseed_time = time(NULL); - if (drbg->reseed_prop_counter > 0) { - if (drbg->parent == NULL) - drbg->reseed_prop_counter++; - else - drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter; - } + tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter); end: if (entropy != NULL && drbg->cleanup_entropy != NULL) @@ -625,14 +621,8 @@ int rand_drbg_restart(RAND_DRBG *drbg, } } - /* check whether a given entropy pool was cleared properly during reseed */ - if (drbg->pool != NULL) { - drbg->state = DRBG_ERROR; - RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR); - rand_pool_free(drbg->pool); - drbg->pool = NULL; - return 0; - } + rand_pool_free(drbg->pool); + drbg->pool = NULL; return drbg->state == DRBG_READY; } @@ -691,8 +681,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, || now - drbg->reseed_time >= drbg->reseed_time_interval) reseed_required = 1; } - if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) { - if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter) + if (drbg->parent != NULL) { + unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter); + if (reseed_counter > 0 + && tsan_load(&drbg->parent->reseed_prop_counter) + != reseed_counter) reseed_required = 1; } @@ -764,7 +757,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg, RAND_DRBG_get_nonce_fn get_nonce, RAND_DRBG_cleanup_nonce_fn cleanup_nonce) { - if (drbg->state != DRBG_UNINITIALISED) + if (drbg->state != DRBG_UNINITIALISED + || drbg->parent != NULL) return 0; drbg->get_entropy = get_entropy; drbg->cleanup_entropy = cleanup_entropy; @@ -942,7 +936,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type) goto err; /* enable seed propagation */ - drbg->reseed_prop_counter = 1; + tsan_store(&drbg->reseed_prop_counter, 1); /* * Ignore instantiation error to support just-in-time instantiation. @@ -1031,11 +1025,53 @@ static int drbg_bytes(unsigned char *out, int count) return ret; } +/* + * Calculates the minimum length of a full entropy buffer + * which is necessary to seed (i.e. instantiate) the DRBG + * successfully. + * + * NOTE: There is a copy of this function in drbgtest.c. + * If you change anything here, you need to update + * the copy accordingly. + */ +static size_t rand_drbg_seedlen(RAND_DRBG *drbg) +{ + /* + * If no os entropy source is available then RAND_seed(buffer, bufsize) + * is expected to succeed if and only if the buffer length satisfies + * the following requirements, which follow from the calculations + * in RAND_DRBG_instantiate(). + */ + size_t min_entropy = drbg->strength; + size_t min_entropylen = drbg->min_entropylen; + + /* + * Extra entropy for the random nonce in the absence of a + * get_nonce callback, see comment in RAND_DRBG_instantiate(). + */ + if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) { + min_entropy += drbg->strength / 2; + min_entropylen += drbg->min_noncelen; + } + + /* + * Convert entropy requirement from bits to bytes + * (dividing by 8 without rounding upwards, because + * all entropy requirements are divisible by 8). + */ + min_entropy >>= 3; + + /* Return a value that satisfies both requirements */ + return min_entropy > min_entropylen ? min_entropy : min_entropylen; +} + /* Implements the default OpenSSL RAND_add() method */ static int drbg_add(const void *buf, int num, double randomness) { int ret = 0; RAND_DRBG *drbg = RAND_DRBG_get0_master(); + size_t buflen; + size_t seedlen; if (drbg == NULL) return 0; @@ -1043,7 +1079,37 @@ static int drbg_add(const void *buf, int num, double randomness) if (num < 0 || randomness < 0.0) return 0; - if (randomness > (double)RAND_DRBG_STRENGTH) { + rand_drbg_lock(drbg); + seedlen = rand_drbg_seedlen(drbg); + + buflen = (size_t)num; + + if (buflen < seedlen || randomness < (double) seedlen) { +#if defined(OPENSSL_RAND_SEED_NONE) + /* + * If no os entropy source is available, a reseeding will fail + * inevitably. So we use a trick to mix the buffer contents into + * the DRBG state without forcing a reseeding: we generate a + * dummy random byte, using the buffer content as additional data. + * Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF. + */ + unsigned char dummy[1]; + + ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen); + rand_drbg_unlock(drbg); + return ret; +#else + /* + * If an os entropy source is avaible then we declare the buffer content + * as additional data by setting randomness to zero and trigger a regular + * reseeding. + */ + randomness = 0.0; +#endif + } + + + if (randomness > (double)seedlen) { /* * The purpose of this check is to bound |randomness| by a * relatively small value in order to prevent an integer @@ -1052,13 +1118,10 @@ static int drbg_add(const void *buf, int num, double randomness) * not bits, so this value corresponds to eight times the * security strength. */ - randomness = (double)RAND_DRBG_STRENGTH; + randomness = (double)seedlen; } - rand_drbg_lock(drbg); - ret = rand_drbg_restart(drbg, buf, - (size_t)(unsigned int)num, - (size_t)(8*randomness)); + ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness)); rand_drbg_unlock(drbg); return ret; diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 13f8cc82..8abca4c2 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -16,6 +16,9 @@ # include # include # include +# include "internal/tsan_assist.h" + +# include "internal/numbers.h" /* How many times to read the TSC as a randomness source. */ # define TSC_READ_COUNT 4 @@ -256,7 +259,8 @@ struct rand_drbg_st { * is added by RAND_add() or RAND_seed() will have an immediate effect on * the output of RAND_bytes() resp. RAND_priv_bytes(). */ - unsigned int reseed_prop_counter; + TSAN_QUALIFIER unsigned int reseed_prop_counter; + unsigned int reseed_next_counter; size_t seedlen; DRBG_STATUS state; diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index f40c513c..555fea36 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -151,6 +151,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, pool->entropy_requested = entropy; } else { pool = rand_pool_new(entropy, min_len, max_len); + if (pool == NULL) + return 0; } if (drbg->parent) { @@ -172,6 +174,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, prediction_resistance, NULL, 0) != 0) bytes = bytes_needed; + drbg->reseed_next_counter + = tsan_load(&drbg->parent->reseed_prop_counter); rand_drbg_unlock(drbg->parent); rand_pool_add_end(pool, bytes, 8 * bytes); @@ -200,7 +204,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, } err: - rand_pool_free(pool); + if (drbg->pool == NULL) + rand_pool_free(pool); return ret; } @@ -213,8 +218,6 @@ void rand_drbg_cleanup_entropy(RAND_DRBG *drbg, { if (drbg->pool == NULL) OPENSSL_secure_clear_free(out, outlen); - else - drbg->pool = NULL; } @@ -539,6 +542,8 @@ unsigned char *rand_pool_detach(RAND_POOL *pool) { unsigned char *ret = pool->buffer; pool->buffer = NULL; + pool->len = 0; + pool->entropy = 0; return ret; } diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index 89720eb5..1b737d1b 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -16,6 +16,7 @@ #include #include +#include #include #ifdef OPENSSL_SYS_VMS @@ -48,7 +49,7 @@ # define S_ISREG(m) ((m) & S_IFREG) # endif -#define RAND_FILE_SIZE 1024 +#define RAND_BUF_SIZE 1024 #define RFILE ".rnd" #ifdef OPENSSL_SYS_VMS @@ -74,7 +75,16 @@ static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) = */ int RAND_load_file(const char *file, long bytes) { - unsigned char buf[RAND_FILE_SIZE]; + /* + * The load buffer size exceeds the chunk size by the comfortable amount + * of 'RAND_DRBG_STRENGTH' bytes (not bits!). This is done on purpose + * to avoid calling RAND_add() with a small final chunk. Instead, such + * a small final chunk will be added together with the previous chunk + * (unless it's the only one). + */ +#define RAND_LOAD_BUF_SIZE (RAND_BUF_SIZE + RAND_DRBG_STRENGTH) + unsigned char buf[RAND_LOAD_BUF_SIZE]; + #ifndef OPENSSL_NO_POSIX_IO struct stat sb; #endif @@ -98,8 +108,12 @@ int RAND_load_file(const char *file, long bytes) return -1; } - if (!S_ISREG(sb.st_mode) && bytes < 0) - bytes = 256; + if (bytes < 0) { + if (S_ISREG(sb.st_mode)) + bytes = sb.st_size; + else + bytes = RAND_DRBG_STRENGTH; + } #endif /* * On VMS, setbuf() will only take 32-bit pointers, and a compilation @@ -124,9 +138,9 @@ int RAND_load_file(const char *file, long bytes) for ( ; ; ) { if (bytes > 0) - n = (bytes < RAND_FILE_SIZE) ? (int)bytes : RAND_FILE_SIZE; + n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE; else - n = RAND_FILE_SIZE; + n = RAND_LOAD_BUF_SIZE; i = fread(buf, 1, n, in); #ifdef EINTR if (ferror(in) && errno == EINTR){ @@ -148,12 +162,18 @@ int RAND_load_file(const char *file, long bytes) OPENSSL_cleanse(buf, sizeof(buf)); fclose(in); + if (!RAND_status()) { + RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_RESEED_ERROR); + ERR_add_error_data(2, "Filename=", file); + return -1; + } + return ret; } int RAND_write_file(const char *file) { - unsigned char buf[RAND_FILE_SIZE]; + unsigned char buf[RAND_BUF_SIZE]; int ret = -1; FILE *out = NULL; #ifndef OPENSSL_NO_POSIX_IO @@ -222,9 +242,9 @@ int RAND_write_file(const char *file) chmod(file, 0600); #endif - ret = fwrite(buf, 1, RAND_FILE_SIZE, out); + ret = fwrite(buf, 1, RAND_BUF_SIZE, out); fclose(out); - OPENSSL_cleanse(buf, RAND_FILE_SIZE); + OPENSSL_cleanse(buf, RAND_BUF_SIZE); return ret; } diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 49c34b7c..3b997432 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -163,6 +163,133 @@ void *RSA_get_ex_data(const RSA *r, int idx) return CRYPTO_get_ex_data(&r->ex_data, idx); } +/* + * Define a scaling constant for our fixed point arithmetic. + * This value must be a power of two because the base two logarithm code + * makes this assumption. The exponent must also be a multiple of three so + * that the scale factor has an exact cube root. Finally, the scale factor + * should not be so large that a multiplication of two scaled numbers + * overflows a 64 bit unsigned integer. + */ +static const unsigned int scale = 1 << 18; +static const unsigned int cbrt_scale = 1 << (2 * 18 / 3); + +/* Define some constants, none exceed 32 bits */ +static const unsigned int log_2 = 0x02c5c8; /* scale * log(2) */ +static const unsigned int log_e = 0x05c551; /* scale * log2(M_E) */ +static const unsigned int c1_923 = 0x07b126; /* scale * 1.923 */ +static const unsigned int c4_690 = 0x12c28f; /* scale * 4.690 */ + +/* + * Multiply two scale integers together and rescale the result. + */ +static ossl_inline uint64_t mul2(uint64_t a, uint64_t b) +{ + return a * b / scale; +} + +/* + * Calculate the cube root of a 64 bit scaled integer. + * Although the cube root of a 64 bit number does fit into a 32 bit unsigned + * integer, this is not guaranteed after scaling, so this function has a + * 64 bit return. This uses the shifting nth root algorithm with some + * algebraic simplifications. + */ +static uint64_t icbrt64(uint64_t x) +{ + uint64_t r = 0; + uint64_t b; + int s; + + for (s = 63; s >= 0; s -= 3) { + r <<= 1; + b = 3 * r * (r + 1) + 1; + if ((x >> s) >= b) { + x -= b << s; + r++; + } + } + return r * cbrt_scale; +} + +/* + * Calculate the natural logarithm of a 64 bit scaled integer. + * This is done by calculating a base two logarithm and scaling. + * The maximum logarithm (base 2) is 64 and this reduces base e, so + * a 32 bit result should not overflow. The argument passed must be + * greater than unity so we don't need to handle negative results. + */ +static uint32_t ilog_e(uint64_t v) +{ + uint32_t i, r = 0; + + /* + * Scale down the value into the range 1 .. 2. + * + * If fractional numbers need to be processed, another loop needs + * to go here that checks v < scale and if so multiplies it by 2 and + * reduces r by scale. This also means making r signed. + */ + while (v >= 2 * scale) { + v >>= 1; + r += scale; + } + for (i = scale / 2; i != 0; i /= 2) { + v = mul2(v, v); + if (v >= 2 * scale) { + v >>= 1; + r += i; + } + } + r = (r * (uint64_t)scale) / log_e; + return r; +} + +/* + * NIST SP 800-56B rev 2 Appendix D: Maximum Security Strength Estimates for IFC + * Modulus Lengths. + * + * E = \frac{1.923 \sqrt[3]{nBits \cdot log_e(2)} + * \cdot(log_e(nBits \cdot log_e(2))^{2/3} - 4.69}{log_e(2)} + * The two cube roots are merged together here. + */ +static uint16_t rsa_compute_security_bits(int n) +{ + uint64_t x; + uint32_t lx; + uint16_t y; + + /* Look for common values as listed in SP 800-56B rev 2 Appendix D */ + switch (n) { + case 2048: + return 112; + case 3072: + return 128; + case 4096: + return 152; + case 6144: + return 176; + case 8192: + return 200; + } + /* + * The first incorrect result (i.e. not accurate or off by one low) occurs + * for n = 699668. The true value here is 1200. Instead of using this n + * as the check threshold, the smallest n such that the correct result is + * 1200 is used instead. + */ + if (n >= 687737) + return 1200; + if (n < 8) + return 0; + + x = n * (uint64_t)log_2; + lx = ilog_e(x); + y = (uint16_t)((mul2(c1_923, icbrt64(mul2(mul2(x, lx), lx))) - c4_690) + / log_2); + return (y + 4) & ~7; +} + int RSA_security_bits(const RSA *rsa) { int bits = BN_num_bits(rsa->n); @@ -174,7 +301,7 @@ int RSA_security_bits(const RSA *rsa) if (ex_primes <= 0 || (ex_primes + 2) > rsa_multip_cap(bits)) return 0; } - return BN_security_bits(bits, -1); + return rsa_compute_security_bits(bits); } int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) diff --git a/crypto/s390x_arch.h b/crypto/s390x_arch.h index 4a775a92..3bed6552 100644 --- a/crypto/s390x_arch.h +++ b/crypto/s390x_arch.h @@ -49,6 +49,9 @@ struct OPENSSL_s390xcap_st { extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; +/* Max number of 64-bit words currently returned by STFLE */ +# define S390X_STFLE_MAX 3 + /* convert facility bit number or function code to bit mask */ # define S390X_CAPBIT(i) (1ULL << (63 - (i) % 64)) @@ -68,9 +71,15 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; # define S390X_KMA 0xb0 /* Facility Bit Numbers */ -# define S390X_VX 129 -# define S390X_VXD 134 -# define S390X_VXE 135 +# define S390X_MSA 17 /* message-security-assist */ +# define S390X_STCKF 25 /* store-clock-fast */ +# define S390X_MSA5 57 /* message-security-assist-ext. 5 */ +# define S390X_MSA3 76 /* message-security-assist-ext. 3 */ +# define S390X_MSA4 77 /* message-security-assist-ext. 4 */ +# define S390X_VX 129 /* vector */ +# define S390X_VXD 134 /* vector packed decimal */ +# define S390X_VXE 135 /* vector enhancements 1 */ +# define S390X_MSA8 146 /* message-security-assist-ext. 8 */ /* Function Codes */ @@ -78,6 +87,9 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; # define S390X_QUERY 0 /* kimd/klmd */ +# define S390X_SHA_1 1 +# define S390X_SHA_256 2 +# define S390X_SHA_512 3 # define S390X_SHA3_224 32 # define S390X_SHA3_256 33 # define S390X_SHA3_384 34 @@ -91,7 +103,12 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; # define S390X_AES_192 19 # define S390X_AES_256 20 +/* km */ +# define S390X_XTS_AES_128 50 +# define S390X_XTS_AES_256 52 + /* prno */ +# define S390X_SHA_512_DRNG 3 # define S390X_TRNG 114 /* Register 0 Flags */ diff --git a/crypto/s390xcap.c b/crypto/s390xcap.c index e7c7f0a3..881613a4 100644 --- a/crypto/s390xcap.c +++ b/crypto/s390xcap.c @@ -13,15 +13,51 @@ #include #include #include "internal/cryptlib.h" +#include "internal/ctype.h" #include "s390x_arch.h" +#define LEN 128 +#define STR_(S) #S +#define STR(S) STR_(S) + +#define TOK_FUNC(NAME) \ + (sscanf(tok_begin, \ + " " STR(NAME) " : %" STR(LEN) "[^:] : " \ + "%" STR(LEN) "s %" STR(LEN) "s ", \ + tok[0], tok[1], tok[2]) == 2) { \ + \ + off = (tok[0][0] == '~') ? 1 : 0; \ + if (sscanf(tok[0] + off, "%llx", &cap->NAME[0]) != 1) \ + goto ret; \ + if (off) \ + cap->NAME[0] = ~cap->NAME[0]; \ + \ + off = (tok[1][0] == '~') ? 1 : 0; \ + if (sscanf(tok[1] + off, "%llx", &cap->NAME[1]) != 1) \ + goto ret; \ + if (off) \ + cap->NAME[1] = ~cap->NAME[1]; \ + } + +#define TOK_CPU(NAME) \ + (sscanf(tok_begin, \ + " %" STR(LEN) "s %" STR(LEN) "s ", \ + tok[0], tok[1]) == 1 \ + && !strcmp(tok[0], #NAME)) { \ + memcpy(cap, &NAME, sizeof(*cap)); \ + } + static sigjmp_buf ill_jmp; static void ill_handler(int sig) { siglongjmp(ill_jmp, sig); } +static const char *env; +static int parse_env(struct OPENSSL_s390xcap_st *cap); + void OPENSSL_s390x_facilities(void); +void OPENSSL_s390x_functions(void); void OPENSSL_vx_probe(void); struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; @@ -30,6 +66,7 @@ void OPENSSL_cpuid_setup(void) { sigset_t oset; struct sigaction ill_act, oact; + struct OPENSSL_s390xcap_st cap; if (OPENSSL_s390xcap_P.stfle[0]) return; @@ -37,6 +74,12 @@ void OPENSSL_cpuid_setup(void) /* set a bit that will not be tested later */ OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0); + env = getenv("OPENSSL_s390xcap"); + if (env != NULL) { + if (!parse_env(&cap)) + env = NULL; + } + memset(&ill_act, 0, sizeof(ill_act)); ill_act.sa_handler = ill_handler; sigfillset(&ill_act.sa_mask); @@ -51,6 +94,12 @@ void OPENSSL_cpuid_setup(void) if (sigsetjmp(ill_jmp, 1) == 0) OPENSSL_s390x_facilities(); + if (env != NULL) { + OPENSSL_s390xcap_P.stfle[0] &= cap.stfle[0]; + OPENSSL_s390xcap_P.stfle[1] &= cap.stfle[1]; + OPENSSL_s390xcap_P.stfle[2] &= cap.stfle[2]; + } + /* protection against disabled vector facility */ if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX)) && (sigsetjmp(ill_jmp, 1) == 0)) { @@ -64,4 +113,470 @@ void OPENSSL_cpuid_setup(void) sigaction(SIGFPE, &oact, NULL); sigaction(SIGILL, &oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); + + OPENSSL_s390x_functions(); + + if (env != NULL) { + OPENSSL_s390xcap_P.kimd[0] &= cap.kimd[0]; + OPENSSL_s390xcap_P.kimd[1] &= cap.kimd[1]; + OPENSSL_s390xcap_P.klmd[0] &= cap.klmd[0]; + OPENSSL_s390xcap_P.klmd[1] &= cap.klmd[1]; + OPENSSL_s390xcap_P.km[0] &= cap.km[0]; + OPENSSL_s390xcap_P.km[1] &= cap.km[1]; + OPENSSL_s390xcap_P.kmc[0] &= cap.kmc[0]; + OPENSSL_s390xcap_P.kmc[1] &= cap.kmc[1]; + OPENSSL_s390xcap_P.kmac[0] &= cap.kmac[0]; + OPENSSL_s390xcap_P.kmac[1] &= cap.kmac[1]; + OPENSSL_s390xcap_P.kmctr[0] &= cap.kmctr[0]; + OPENSSL_s390xcap_P.kmctr[1] &= cap.kmctr[1]; + OPENSSL_s390xcap_P.kmo[0] &= cap.kmo[0]; + OPENSSL_s390xcap_P.kmo[1] &= cap.kmo[1]; + OPENSSL_s390xcap_P.kmf[0] &= cap.kmf[0]; + OPENSSL_s390xcap_P.kmf[1] &= cap.kmf[1]; + OPENSSL_s390xcap_P.prno[0] &= cap.prno[0]; + OPENSSL_s390xcap_P.prno[1] &= cap.prno[1]; + OPENSSL_s390xcap_P.kma[0] &= cap.kma[0]; + OPENSSL_s390xcap_P.kma[1] &= cap.kma[1]; + } +} + +static int parse_env(struct OPENSSL_s390xcap_st *cap) +{ + /*- + * CPU model data + * (only the STFLE- and QUERY-bits relevant to libcrypto are set) + */ + + /*- + * z900 (2000) - z/Architecture POP SA22-7832-00 + * Facility detection would fail on real hw (no STFLE). + */ + static const struct OPENSSL_s390xcap_st z900 = { + .stfle = {0ULL, 0ULL, 0ULL, 0ULL}, + .kimd = {0ULL, 0ULL}, + .klmd = {0ULL, 0ULL}, + .km = {0ULL, 0ULL}, + .kmc = {0ULL, 0ULL}, + .kmac = {0ULL, 0ULL}, + .kmctr = {0ULL, 0ULL}, + .kmo = {0ULL, 0ULL}, + .kmf = {0ULL, 0ULL}, + .prno = {0ULL, 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * z990 (2003) - z/Architecture POP SA22-7832-02 + * Implements MSA. Facility detection would fail on real hw (no STFLE). + */ + static const struct OPENSSL_s390xcap_st z990 = { + .stfle = {S390X_CAPBIT(S390X_MSA), + 0ULL, 0ULL, 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1), + 0ULL}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY), + 0ULL}, + .kmctr = {0ULL, 0ULL}, + .kmo = {0ULL, 0ULL}, + .kmf = {0ULL, 0ULL}, + .prno = {0ULL, 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * z9 (2005) - z/Architecture POP SA22-7832-04 + * Implements MSA and MSA1. + */ + static const struct OPENSSL_s390xcap_st z9 = { + .stfle = {S390X_CAPBIT(S390X_MSA) + | S390X_CAPBIT(S390X_STCKF), + 0ULL, 0ULL, 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256), + 0ULL}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY), + 0ULL}, + .kmctr = {0ULL, 0ULL}, + .kmo = {0ULL, 0ULL}, + .kmf = {0ULL, 0ULL}, + .prno = {0ULL, 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * z10 (2008) - z/Architecture POP SA22-7832-06 + * Implements MSA and MSA1-2. + */ + static const struct OPENSSL_s390xcap_st z10 = { + .stfle = {S390X_CAPBIT(S390X_MSA) + | S390X_CAPBIT(S390X_STCKF), + 0ULL, 0ULL, 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + 0ULL}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY), + 0ULL}, + .kmctr = {0ULL, 0ULL}, + .kmo = {0ULL, 0ULL}, + .kmf = {0ULL, 0ULL}, + .prno = {0ULL, 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * z196 (2010) - z/Architecture POP SA22-7832-08 + * Implements MSA and MSA1-4. + */ + static const struct OPENSSL_s390xcap_st z196 = { + .stfle = {S390X_CAPBIT(S390X_MSA) + | S390X_CAPBIT(S390X_STCKF), + S390X_CAPBIT(S390X_MSA3) + | S390X_CAPBIT(S390X_MSA4), + 0ULL, 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + S390X_CAPBIT(S390X_GHASH)}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256) + | S390X_CAPBIT(S390X_XTS_AES_128) + | S390X_CAPBIT(S390X_XTS_AES_256), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmctr = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmo = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmf = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .prno = {0ULL, 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * zEC12 (2012) - z/Architecture POP SA22-7832-09 + * Implements MSA and MSA1-4. + */ + static const struct OPENSSL_s390xcap_st zEC12 = { + .stfle = {S390X_CAPBIT(S390X_MSA) + | S390X_CAPBIT(S390X_STCKF), + S390X_CAPBIT(S390X_MSA3) + | S390X_CAPBIT(S390X_MSA4), + 0ULL, 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + S390X_CAPBIT(S390X_GHASH)}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256) + | S390X_CAPBIT(S390X_XTS_AES_128) + | S390X_CAPBIT(S390X_XTS_AES_256), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmctr = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmo = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmf = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .prno = {0ULL, 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * z13 (2015) - z/Architecture POP SA22-7832-10 + * Implements MSA and MSA1-5. + */ + static const struct OPENSSL_s390xcap_st z13 = { + .stfle = {S390X_CAPBIT(S390X_MSA) + | S390X_CAPBIT(S390X_STCKF) + | S390X_CAPBIT(S390X_MSA5), + S390X_CAPBIT(S390X_MSA3) + | S390X_CAPBIT(S390X_MSA4), + S390X_CAPBIT(S390X_VX), + 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + S390X_CAPBIT(S390X_GHASH)}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256) + | S390X_CAPBIT(S390X_XTS_AES_128) + | S390X_CAPBIT(S390X_XTS_AES_256), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmctr = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmo = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmf = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .prno = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_512_DRNG), + 0ULL}, + .kma = {0ULL, 0ULL}, + }; + + /*- + * z14 (2017) - z/Architecture POP SA22-7832-11 + * Implements MSA and MSA1-8. + */ + static const struct OPENSSL_s390xcap_st z14 = { + .stfle = {S390X_CAPBIT(S390X_MSA) + | S390X_CAPBIT(S390X_STCKF) + | S390X_CAPBIT(S390X_MSA5), + S390X_CAPBIT(S390X_MSA3) + | S390X_CAPBIT(S390X_MSA4), + S390X_CAPBIT(S390X_VX) + | S390X_CAPBIT(S390X_VXD) + | S390X_CAPBIT(S390X_VXE) + | S390X_CAPBIT(S390X_MSA8), + 0ULL}, + .kimd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512) + | S390X_CAPBIT(S390X_SHA3_224) + | S390X_CAPBIT(S390X_SHA3_256) + | S390X_CAPBIT(S390X_SHA3_384) + | S390X_CAPBIT(S390X_SHA3_512) + | S390X_CAPBIT(S390X_SHAKE_128) + | S390X_CAPBIT(S390X_SHAKE_256), + S390X_CAPBIT(S390X_GHASH)}, + .klmd = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_1) + | S390X_CAPBIT(S390X_SHA_256) + | S390X_CAPBIT(S390X_SHA_512) + | S390X_CAPBIT(S390X_SHA3_224) + | S390X_CAPBIT(S390X_SHA3_256) + | S390X_CAPBIT(S390X_SHA3_384) + | S390X_CAPBIT(S390X_SHA3_512) + | S390X_CAPBIT(S390X_SHAKE_128) + | S390X_CAPBIT(S390X_SHAKE_256), + 0ULL}, + .km = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256) + | S390X_CAPBIT(S390X_XTS_AES_128) + | S390X_CAPBIT(S390X_XTS_AES_256), + 0ULL}, + .kmc = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmac = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmctr = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmo = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .kmf = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + .prno = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_SHA_512_DRNG), + S390X_CAPBIT(S390X_TRNG)}, + .kma = {S390X_CAPBIT(S390X_QUERY) + | S390X_CAPBIT(S390X_AES_128) + | S390X_CAPBIT(S390X_AES_192) + | S390X_CAPBIT(S390X_AES_256), + 0ULL}, + }; + + char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1]; + int rc, off, i, n; + + buff = malloc(strlen(env) + 1); + if (buff == NULL) + return 0; + + rc = 0; + memset(cap, ~0, sizeof(*cap)); + strcpy(buff, env); + + tok_begin = buff + strspn(buff, ";"); + strtok(tok_begin, ";"); + tok_end = strtok(NULL, ";"); + + while (tok_begin != NULL) { + /* stfle token */ + if ((n = sscanf(tok_begin, + " stfle : %" STR(LEN) "[^:] : " + "%" STR(LEN) "[^:] : %" STR(LEN) "s ", + tok[0], tok[1], tok[2]))) { + for (i = 0; i < n; i++) { + off = (tok[i][0] == '~') ? 1 : 0; + if (sscanf(tok[i] + off, "%llx", &cap->stfle[i]) != 1) + goto ret; + if (off) + cap->stfle[i] = ~cap->stfle[i]; + } + } + + /* query function tokens */ + else if TOK_FUNC(kimd) + else if TOK_FUNC(klmd) + else if TOK_FUNC(km) + else if TOK_FUNC(kmc) + else if TOK_FUNC(kmac) + else if TOK_FUNC(kmctr) + else if TOK_FUNC(kmo) + else if TOK_FUNC(kmf) + else if TOK_FUNC(prno) + else if TOK_FUNC(kma) + + /* CPU model tokens */ + else if TOK_CPU(z900) + else if TOK_CPU(z990) + else if TOK_CPU(z9) + else if TOK_CPU(z10) + else if TOK_CPU(z196) + else if TOK_CPU(zEC12) + else if TOK_CPU(z13) + else if TOK_CPU(z14) + + /* whitespace(ignored) or invalid tokens */ + else { + while (*tok_begin != '\0') { + if (!ossl_isspace(*tok_begin)) + goto ret; + tok_begin++; + } + } + + tok_begin = tok_end; + tok_end = strtok(NULL, ";"); + } + + rc = 1; +ret: + free(buff); + return rc; } diff --git a/crypto/s390xcpuid.pl b/crypto/s390xcpuid.pl index ec700a47..5e18aef9 100755 --- a/crypto/s390xcpuid.pl +++ b/crypto/s390xcpuid.pl @@ -38,7 +38,26 @@ OPENSSL_s390x_facilities: stg %r0,S390X_STFLE+8(%r4) # wipe capability vectors stg %r0,S390X_STFLE+16(%r4) stg %r0,S390X_STFLE+24(%r4) - stg %r0,S390X_KIMD(%r4) + + .long 0xb2b04000 # stfle 0(%r4) + brc 8,.Ldone + lghi %r0,1 + .long 0xb2b04000 # stfle 0(%r4) + brc 8,.Ldone + lghi %r0,2 + .long 0xb2b04000 # stfle 0(%r4) +.Ldone: + br $ra +.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities + +.globl OPENSSL_s390x_functions +.type OPENSSL_s390x_functions,\@function +.align 16 +OPENSSL_s390x_functions: + lghi %r0,0 + larl %r4,OPENSSL_s390xcap_P + + stg %r0,S390X_KIMD(%r4) # wipe capability vectors stg %r0,S390X_KIMD+8(%r4) stg %r0,S390X_KLMD(%r4) stg %r0,S390X_KLMD+8(%r4) @@ -59,14 +78,6 @@ OPENSSL_s390x_facilities: stg %r0,S390X_KMA(%r4) stg %r0,S390X_KMA+8(%r4) - .long 0xb2b04000 # stfle 0(%r4) - brc 8,.Ldone - lghi %r0,1 - .long 0xb2b04000 # stfle 0(%r4) - brc 8,.Ldone - lghi %r0,2 - .long 0xb2b04000 # stfle 0(%r4) -.Ldone: lmg %r2,%r3,S390X_STFLE(%r4) tmhl %r2,0x4000 # check for message-security-assist jz .Lret @@ -123,7 +134,7 @@ OPENSSL_s390x_facilities: .Lret: br $ra -.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities +.size OPENSSL_s390x_functions,.-OPENSSL_s390x_functions .globl OPENSSL_rdtsc .type OPENSSL_rdtsc,\@function diff --git a/crypto/sha/asm/keccak1600-armv8.pl b/crypto/sha/asm/keccak1600-armv8.pl index 704ab4a7..e4e94bca 100755 --- a/crypto/sha/asm/keccak1600-armv8.pl +++ b/crypto/sha/asm/keccak1600-armv8.pl @@ -533,30 +533,28 @@ my @A = map([ "v".$_.".16b", "v".($_+1).".16b", "v".($_+2).".16b", (0, 5, 10, 15, 20)); my @C = map("v$_.16b", (25..31)); +my @D = @C[4,5,6,2,3]; $code.=<<___; .type KeccakF1600_ce,%function .align 5 KeccakF1600_ce: - mov x9,#12 + mov x9,#24 adr x10,iotas b .Loop_ce .align 4 .Loop_ce: -___ -for($i=0; $i<2; $i++) { -$code.=<<___; ////////////////////////////////////////////////// Theta - eor3 $C[0],$A[0][0],$A[1][0],$A[2][0] - eor3 $C[1],$A[0][1],$A[1][1],$A[2][1] - eor3 $C[2],$A[0][2],$A[1][2],$A[2][2] - eor3 $C[3],$A[0][3],$A[1][3],$A[2][3] - eor3 $C[4],$A[0][4],$A[1][4],$A[2][4] - eor3 $C[0],$C[0], $A[3][0],$A[4][0] - eor3 $C[1],$C[1], $A[3][1],$A[4][1] - eor3 $C[2],$C[2], $A[3][2],$A[4][2] - eor3 $C[3],$C[3], $A[3][3],$A[4][3] - eor3 $C[4],$C[4], $A[3][4],$A[4][4] + eor3 $C[0],$A[4][0],$A[3][0],$A[2][0] + eor3 $C[1],$A[4][1],$A[3][1],$A[2][1] + eor3 $C[2],$A[4][2],$A[3][2],$A[2][2] + eor3 $C[3],$A[4][3],$A[3][3],$A[2][3] + eor3 $C[4],$A[4][4],$A[3][4],$A[2][4] + eor3 $C[0],$C[0], $A[1][0],$A[0][0] + eor3 $C[1],$C[1], $A[1][1],$A[0][1] + eor3 $C[2],$C[2], $A[1][2],$A[0][2] + eor3 $C[3],$C[3], $A[1][3],$A[0][3] + eor3 $C[4],$C[4], $A[1][4],$A[0][4] rax1 $C[5],$C[0],$C[2] // D[1] rax1 $C[6],$C[1],$C[3] // D[2] @@ -565,81 +563,75 @@ $code.=<<___; rax1 $C[4],$C[4],$C[1] // D[0] ////////////////////////////////////////////////// Theta+Rho+Pi - xar $C[0], $A[1][1],$C[5],#64-$rhotates[1][1] // C[0]=A[0][1] - xar $A[1][1],$A[1][4],$C[3],#64-$rhotates[1][4] - xar $A[1][4],$A[4][2],$C[6],#64-$rhotates[4][2] - xar $A[4][2],$A[2][4],$C[3],#64-$rhotates[2][4] - xar $A[2][4],$A[4][0],$C[4],#64-$rhotates[4][0] + xar $C[0], $A[0][1],$D[1],#64-$rhotates[0][1] // C[0]=A[2][0] - xar $A[4][0],$A[0][2],$C[6],#64-$rhotates[0][2] + xar $A[0][1],$A[1][1],$D[1],#64-$rhotates[1][1] + xar $A[1][1],$A[1][4],$D[4],#64-$rhotates[1][4] + xar $A[1][4],$A[4][2],$D[2],#64-$rhotates[4][2] + xar $A[4][2],$A[2][4],$D[4],#64-$rhotates[2][4] + xar $A[2][4],$A[4][0],$D[0],#64-$rhotates[4][0] - xar $A[0][2],$A[2][2],$C[6],#64-$rhotates[2][2] - xar $A[2][2],$A[2][3],$C[2],#64-$rhotates[2][3] - xar $A[2][3],$A[3][4],$C[3],#64-$rhotates[3][4] - xar $A[3][4],$A[4][3],$C[2],#64-$rhotates[4][3] - xar $A[4][3],$A[3][0],$C[4],#64-$rhotates[3][0] + xar $C[1], $A[0][2],$D[2],#64-$rhotates[0][2] // C[1]=A[4][0] - xar $A[3][0],$A[0][4],$C[3],#64-$rhotates[0][4] + xar $A[0][2],$A[2][2],$D[2],#64-$rhotates[2][2] + xar $A[2][2],$A[2][3],$D[3],#64-$rhotates[2][3] + xar $A[2][3],$A[3][4],$D[4],#64-$rhotates[3][4] + xar $A[3][4],$A[4][3],$D[3],#64-$rhotates[4][3] + xar $A[4][3],$A[3][0],$D[0],#64-$rhotates[3][0] - eor $A[0][0],$A[0][0],$C[4] - ldr x11,[x10],#8 + xar $A[3][0],$A[0][4],$D[4],#64-$rhotates[0][4] - xar $C[1], $A[3][3],$C[2],#64-$rhotates[3][3] // C[1]=A[0][3] - xar $A[3][3],$A[3][2],$C[6],#64-$rhotates[3][2] - xar $A[3][2],$A[2][1],$C[5],#64-$rhotates[2][1] - xar $A[2][1],$A[1][2],$C[6],#64-$rhotates[1][2] - xar $A[1][2],$A[2][0],$C[4],#64-$rhotates[2][0] + xar $D[4], $A[4][4],$D[4],#64-$rhotates[4][4] // D[4]=A[0][4] + xar $A[4][4],$A[4][1],$D[1],#64-$rhotates[4][1] + xar $A[1][3],$A[1][3],$D[3],#64-$rhotates[1][3] // A[1][3]=A[4][1] + xar $A[0][4],$A[3][1],$D[1],#64-$rhotates[3][1] // A[0][4]=A[1][3] + xar $A[3][1],$A[1][0],$D[0],#64-$rhotates[1][0] - xar $A[2][0],$A[0][1],$C[5],#64-$rhotates[0][1] // * + xar $A[1][0],$A[0][3],$D[3],#64-$rhotates[0][3] - xar $A[0][4],$A[4][4],$C[3],#64-$rhotates[4][4] - xar $A[4][4],$A[4][1],$C[5],#64-$rhotates[4][1] - xar $A[4][1],$A[1][3],$C[2],#64-$rhotates[1][3] - xar $A[1][3],$A[3][1],$C[5],#64-$rhotates[3][1] - xar $A[3][1],$A[1][0],$C[4],#64-$rhotates[1][0] + eor $A[0][0],$A[0][0],$D[0] - xar $C[2], $A[0][3],$C[2],#64-$rhotates[0][3] // C[2]=A[1][0] + xar $D[3], $A[3][3],$D[3],#64-$rhotates[3][3] // D[3]=A[0][3] + xar $A[0][3],$A[3][2],$D[2],#64-$rhotates[3][2] // A[0][3]=A[3][3] + xar $D[1], $A[2][1],$D[1],#64-$rhotates[2][1] // D[1]=A[3][2] + xar $D[2], $A[1][2],$D[2],#64-$rhotates[1][2] // D[2]=A[2][1] + xar $D[0], $A[2][0],$D[0],#64-$rhotates[2][0] // D[0]=A[1][2] ////////////////////////////////////////////////// Chi+Iota - dup $C[6],x11 // borrow C[6] - bcax $C[3], $A[0][0],$A[0][2],$C[0] // * - bcax $A[0][1],$C[0], $C[1], $A[0][2] // * - bcax $A[0][2],$A[0][2],$A[0][4],$C[1] - bcax $A[0][3],$C[1], $A[0][0],$A[0][4] - bcax $A[0][4],$A[0][4],$C[0], $A[0][0] - - bcax $A[1][0],$C[2], $A[1][2],$A[1][1] // * - bcax $C[0], $A[1][1],$A[1][3],$A[1][2] // * - bcax $A[1][2],$A[1][2],$A[1][4],$A[1][3] - bcax $A[1][3],$A[1][3],$C[2], $A[1][4] - bcax $A[1][4],$A[1][4],$A[1][1],$C[2] - - eor $A[0][0],$C[3],$C[6] // Iota - - bcax $C[1], $A[2][0],$A[2][2],$A[2][1] // * - bcax $C[2], $A[2][1],$A[2][3],$A[2][2] // * - bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3] - bcax $A[2][3],$A[2][3],$A[2][0],$A[2][4] - bcax $A[2][4],$A[2][4],$A[2][1],$A[2][0] - - bcax $C[3], $A[3][0],$A[3][2],$A[3][1] // * - bcax $C[4], $A[3][1],$A[3][3],$A[3][2] // * - bcax $A[3][2],$A[3][2],$A[3][4],$A[3][3] - bcax $A[3][3],$A[3][3],$A[3][0],$A[3][4] - bcax $A[3][4],$A[3][4],$A[3][1],$A[3][0] - - bcax $C[5], $A[4][0],$A[4][2],$A[4][1] // * - bcax $C[6], $A[4][1],$A[4][3],$A[4][2] // * + bcax $A[4][0],$C[1], $A[4][2],$A[1][3] // A[1][3]=A[4][1] + bcax $A[4][1],$A[1][3],$A[4][3],$A[4][2] // A[1][3]=A[4][1] bcax $A[4][2],$A[4][2],$A[4][4],$A[4][3] - bcax $A[4][3],$A[4][3],$A[4][0],$A[4][4] - bcax $A[4][4],$A[4][4],$A[4][1],$A[4][0] -___ - ( $A[1][1], $C[0]) = ( $C[0], $A[1][1]); - ($A[2][0],$A[2][1], $C[1],$C[2]) = ($C[1],$C[2], $A[2][0],$A[2][1]); - ($A[3][0],$A[3][1], $C[3],$C[4]) = ($C[3],$C[4], $A[3][0],$A[3][1]); - ($A[4][0],$A[4][1], $C[5],$C[6]) = ($C[5],$C[6], $A[4][0],$A[4][1]); -} -$code.=<<___; + bcax $A[4][3],$A[4][3],$C[1], $A[4][4] + bcax $A[4][4],$A[4][4],$A[1][3],$C[1] // A[1][3]=A[4][1] + + ld1r {$C[1]},[x10],#8 + + bcax $A[3][2],$D[1], $A[3][4],$A[0][3] // A[0][3]=A[3][3] + bcax $A[3][3],$A[0][3],$A[3][0],$A[3][4] // A[0][3]=A[3][3] + bcax $A[3][4],$A[3][4],$A[3][1],$A[3][0] + bcax $A[3][0],$A[3][0],$D[1], $A[3][1] + bcax $A[3][1],$A[3][1],$A[0][3],$D[1] // A[0][3]=A[3][3] + + bcax $A[2][0],$C[0], $A[2][2],$D[2] + bcax $A[2][1],$D[2], $A[2][3],$A[2][2] + bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3] + bcax $A[2][3],$A[2][3],$C[0], $A[2][4] + bcax $A[2][4],$A[2][4],$D[2], $C[0] + + bcax $A[1][2],$D[0], $A[1][4],$A[0][4] // A[0][4]=A[1][3] + bcax $A[1][3],$A[0][4],$A[1][0],$A[1][4] // A[0][4]=A[1][3] + bcax $A[1][4],$A[1][4],$A[1][1],$A[1][0] + bcax $A[1][0],$A[1][0],$D[0], $A[1][1] + bcax $A[1][1],$A[1][1],$A[0][4],$D[0] // A[0][4]=A[1][3] + + bcax $A[0][3],$D[3], $A[0][0],$D[4] + bcax $A[0][4],$D[4], $A[0][1],$A[0][0] + bcax $A[0][0],$A[0][0],$A[0][2],$A[0][1] + bcax $A[0][1],$A[0][1],$D[3], $A[0][2] + bcax $A[0][2],$A[0][2],$D[4], $D[3] + + eor $A[0][0],$A[0][0],$C[1] + subs x9,x9,#1 bne .Loop_ce @@ -857,7 +849,7 @@ foreach(split("\n",$code)) { s/\`([^\`]*)\`/eval($1)/ge; - m/\bdup\b/ and s/\.16b/.2d/g or + m/\bld1r\b/ and s/\.16b/.2d/g or s/\b(eor3|rax1|xar|bcax)\s+(v.*)/unsha3($1,$2)/ge; print $_,"\n"; diff --git a/crypto/siphash/build.info b/crypto/siphash/build.info index 4166344a..b56563f0 100644 --- a/crypto/siphash/build.info +++ b/crypto/siphash/build.info @@ -1,5 +1,5 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ siphash.c \ - siphash_pmeth.c \ + siphash_meth.c \ siphash_ameth.c diff --git a/crypto/siphash/siphash_meth.c b/crypto/siphash/siphash_meth.c new file mode 100644 index 00000000..7a5457de --- /dev/null +++ b/crypto/siphash/siphash_meth.c @@ -0,0 +1,139 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/siphash.h" +#include "siphash_local.h" +#include "internal/evp_int.h" + +/* local SIPHASH structure is actually a SIPHASH */ + +struct evp_mac_impl_st { + SIPHASH ctx; +}; + +static EVP_MAC_IMPL *siphash_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_MAC_IMPL)); +} + +static void siphash_free(EVP_MAC_IMPL *sctx) +{ + OPENSSL_free(sctx); +} + +static int siphash_copy(EVP_MAC_IMPL *sdst, EVP_MAC_IMPL *ssrc) +{ + *sdst = *ssrc; + return 1; +} + +static size_t siphash_size(EVP_MAC_IMPL *sctx) +{ + return SipHash_hash_size(&sctx->ctx); +} + +static int siphash_init(EVP_MAC_IMPL *sctx) +{ + /* Not much to do here, actual initialization happens through controls */ + return 1; +} + +static int siphash_update(EVP_MAC_IMPL *sctx, const unsigned char *data, + size_t datalen) +{ + SipHash_Update(&sctx->ctx, data, datalen); + return 1; +} + +static int siphash_final(EVP_MAC_IMPL *sctx, unsigned char *out) +{ + size_t hlen = siphash_size(sctx); + + return SipHash_Final(&sctx->ctx, out, hlen); +} + +static int siphash_ctrl(EVP_MAC_IMPL *sctx, int cmd, va_list args) +{ + switch (cmd) { + case EVP_MAC_CTRL_SET_SIZE: + { + size_t size = va_arg(args, size_t); + + return SipHash_set_hash_size(&sctx->ctx, size); + } + break; + case EVP_MAC_CTRL_SET_KEY: + { + const unsigned char *key = va_arg(args, const unsigned char *); + size_t keylen = va_arg(args, size_t); + + if (key == NULL || keylen != SIPHASH_KEY_SIZE) + return 0; + + return SipHash_Init(&sctx->ctx, key, 0, 0); + } + break; + default: + return -2; + } + return 1; +} + +static int siphash_ctrl_int(EVP_MAC_IMPL *sctx, int cmd, ...) +{ + int rv; + va_list args; + + va_start(args, cmd); + rv = siphash_ctrl(sctx, cmd, args); + va_end(args); + + return rv; +} + +static int siphash_ctrl_str_cb(void *ctx, int cmd, void *buf, size_t buflen) +{ + return siphash_ctrl_int(ctx, cmd, buf, buflen); +} + +static int siphash_ctrl_str(EVP_MAC_IMPL *ctx, + const char *type, const char *value) +{ + if (value == NULL) + return 0; + if (strcmp(type, "digestsize") == 0) { + size_t hash_size = atoi(value); + + return siphash_ctrl_int(ctx, EVP_MAC_CTRL_SET_SIZE, hash_size); + } + if (strcmp(type, "key") == 0) + return EVP_str2ctrl(siphash_ctrl_str_cb, ctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "hexkey") == 0) + return EVP_hex2ctrl(siphash_ctrl_str_cb, ctx, EVP_MAC_CTRL_SET_KEY, + value); + return -2; +} + +const EVP_MAC siphash_meth = { + EVP_MAC_SIPHASH, + siphash_new, + siphash_copy, + siphash_free, + siphash_size, + siphash_init, + siphash_update, + siphash_final, + siphash_ctrl, + siphash_ctrl_str +}; diff --git a/crypto/siphash/siphash_pmeth.c b/crypto/siphash/siphash_pmeth.c deleted file mode 100644 index 66e552fe..00000000 --- a/crypto/siphash/siphash_pmeth.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include -#include -#include "internal/siphash.h" -#include "siphash_local.h" -#include "internal/evp_int.h" - -/* SIPHASH pkey context structure */ - -typedef struct siphash_pkey_ctx_st { - ASN1_OCTET_STRING ktmp; /* Temp storage for key */ - SIPHASH ctx; -} SIPHASH_PKEY_CTX; - -static int pkey_siphash_init(EVP_PKEY_CTX *ctx) -{ - SIPHASH_PKEY_CTX *pctx; - - if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) { - CRYPTOerr(CRYPTO_F_PKEY_SIPHASH_INIT, ERR_R_MALLOC_FAILURE); - return 0; - } - pctx->ktmp.type = V_ASN1_OCTET_STRING; - - EVP_PKEY_CTX_set_data(ctx, pctx); - EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0); - return 1; -} - -static void pkey_siphash_cleanup(EVP_PKEY_CTX *ctx) -{ - SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); - - if (pctx != NULL) { - OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length); - OPENSSL_clear_free(pctx, sizeof(*pctx)); - EVP_PKEY_CTX_set_data(ctx, NULL); - } -} - -static int pkey_siphash_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) -{ - SIPHASH_PKEY_CTX *sctx, *dctx; - - /* allocate memory for dst->data and a new SIPHASH_CTX in dst->data->ctx */ - if (!pkey_siphash_init(dst)) - return 0; - sctx = EVP_PKEY_CTX_get_data(src); - dctx = EVP_PKEY_CTX_get_data(dst); - if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL && - !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) { - /* cleanup and free the SIPHASH_PKEY_CTX in dst->data */ - pkey_siphash_cleanup(dst); - return 0; - } - memcpy(&dctx->ctx, &sctx->ctx, sizeof(SIPHASH)); - return 1; -} - -static int pkey_siphash_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) -{ - ASN1_OCTET_STRING *key; - SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); - - if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL) - return 0; - key = ASN1_OCTET_STRING_dup(&pctx->ktmp); - if (key == NULL) - return 0; - return EVP_PKEY_assign_SIPHASH(pkey, key); -} - -static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx)); - - SipHash_Update(&pctx->ctx, data, count); - return 1; -} - -static int siphash_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) -{ - SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); - const unsigned char* key; - size_t len; - - key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len); - if (key == NULL || len != SIPHASH_KEY_SIZE) - return 0; - EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); - EVP_MD_CTX_set_update_fn(mctx, int_update); - return SipHash_Init(&pctx->ctx, key, 0, 0); -} -static int siphash_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, - EVP_MD_CTX *mctx) -{ - SIPHASH_PKEY_CTX *pctx = ctx->data; - - *siglen = SipHash_hash_size(&pctx->ctx); - if (sig != NULL) - return SipHash_Final(&pctx->ctx, sig, *siglen); - return 1; -} - -static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) -{ - SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx); - const unsigned char *key; - size_t len; - - switch (type) { - - case EVP_PKEY_CTRL_MD: - /* ignore */ - break; - - case EVP_PKEY_CTRL_SET_DIGEST_SIZE: - return SipHash_set_hash_size(&pctx->ctx, p1); - - case EVP_PKEY_CTRL_SET_MAC_KEY: - case EVP_PKEY_CTRL_DIGESTINIT: - if (type == EVP_PKEY_CTRL_SET_MAC_KEY) { - /* user explicitly setting the key */ - key = p2; - len = p1; - } else { - /* user indirectly setting the key via EVP_DigestSignInit */ - key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len); - } - if (key == NULL || len != SIPHASH_KEY_SIZE || - !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len)) - return 0; - /* use default rounds (2,4) */ - return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp), - 0, 0); - - default: - return -2; - - } - return 1; -} - -static int pkey_siphash_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) -{ - if (value == NULL) - return 0; - if (strcmp(type, "digestsize") == 0) { - size_t hash_size = atoi(value); - - return pkey_siphash_ctrl(ctx, EVP_PKEY_CTRL_SET_DIGEST_SIZE, hash_size, - NULL); - } - if (strcmp(type, "key") == 0) - return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); - if (strcmp(type, "hexkey") == 0) - return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value); - return -2; -} - -const EVP_PKEY_METHOD siphash_pkey_meth = { - EVP_PKEY_SIPHASH, - EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */ - pkey_siphash_init, - pkey_siphash_copy, - pkey_siphash_cleanup, - - 0, 0, - - 0, - pkey_siphash_keygen, - - 0, 0, - - 0, 0, - - 0, 0, - - siphash_signctx_init, - siphash_signctx, - - 0, 0, - - 0, 0, - - 0, 0, - - 0, 0, - - pkey_siphash_ctrl, - pkey_siphash_ctrl_str -}; diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c index 9c69a450..4389fc73 100644 --- a/crypto/sm2/sm2_crypt.c +++ b/crypto/sm2/sm2_crypt.c @@ -11,6 +11,7 @@ #include "internal/sm2.h" #include "internal/sm2err.h" +#include "internal/ec_int.h" /* ecdh_KDF_X9_63() */ #include #include #include @@ -203,7 +204,7 @@ int sm2_encrypt(const EC_KEY *key, } /* X9.63 with no salt happens to match the KDF used in SM2 */ - if (!ECDH_KDF_X9_62(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, + if (!ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, digest)) { SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB); goto done; @@ -344,7 +345,7 @@ int sm2_decrypt(const EC_KEY *key, if (BN_bn2binpad(x2, x2y2, field_size) < 0 || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0 - || !ECDH_KDF_X9_62(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, + || !ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, digest)) { SM2err(SM2_F_SM2_DECRYPT, ERR_R_INTERNAL_ERROR); goto done; diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 3a60d412..61e81922 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -517,15 +517,14 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) /* check_purpose() makes the callback as needed */ if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca)) return 0; - /* Check pathlen if not self issued */ - if ((i > 1) && !(x->ex_flags & EXFLAG_SI) - && (x->ex_pathlen != -1) - && (plen > (x->ex_pathlen + proxy_path_length + 1))) { + /* Check pathlen */ + if ((i > 1) && (x->ex_pathlen != -1) + && (plen > (x->ex_pathlen + proxy_path_length))) { if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED)) return 0; } - /* Increment path length if not self issued */ - if (!(x->ex_flags & EXFLAG_SI)) + /* Increment path length if not a self issued intermediate CA */ + if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0) plen++; /* * If this certificate is a proxy certificate, the next certificate diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509v3/v3_ncons.c index 9a2cd5af..8465818f 100644 --- a/crypto/x509v3/v3_ncons.c +++ b/crypto/x509v3/v3_ncons.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "internal/x509_int.h" #include "ext_dat.h" @@ -435,6 +436,27 @@ int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc) return X509_V_OK; } +/* + * Return nonzero if the GeneralSubtree has valid 'minimum' field + * (must be absent or 0) and valid 'maximum' field (must be absent). + */ +static int nc_minmax_valid(GENERAL_SUBTREE *sub) { + BIGNUM *bn = NULL; + int ok = 1; + + if (sub->maximum) + ok = 0; + + if (sub->minimum) { + bn = ASN1_INTEGER_to_BN(sub->minimum, NULL); + if (bn == NULL || !BN_is_zero(bn)) + ok = 0; + BN_free(bn); + } + + return ok; +} + static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) { GENERAL_SUBTREE *sub; @@ -449,7 +471,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); if (gen->type != sub->base->type) continue; - if (sub->minimum || sub->maximum) + if (!nc_minmax_valid(sub)) return X509_V_ERR_SUBTREE_MINMAX; /* If we already have a match don't bother trying any more */ if (match == 2) @@ -472,7 +494,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); if (gen->type != sub->base->type) continue; - if (sub->minimum || sub->maximum) + if (!nc_minmax_valid(sub)) return X509_V_ERR_SUBTREE_MINMAX; r = nc_match_single(gen, sub->base); diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod new file mode 100644 index 00000000..a3201811 --- /dev/null +++ b/doc/man3/EVP_MAC.pod @@ -0,0 +1,342 @@ +=pod + +=head1 NAME + +EVP_MAC, EVP_MAC_CTX, EVP_MAC_CTX_new, EVP_MAC_CTX_new_id, EVP_MAC_CTX_free, +EVP_MAC_CTX_copy, EVP_MAC_CTX_mac, EVP_MAC_size, EVP_MAC_init, EVP_MAC_update, +EVP_MAC_final, EVP_MAC_ctrl, EVP_MAC_vctrl, EVP_MAC_ctrl_str, +EVP_MAC_str2ctrl, EVP_MAC_hex2ctrl, EVP_MAC_nid, EVP_MAC_name, +EVP_get_macbyname, EVP_get_macbynid, EVP_get_macbyobj - EVP MAC routines + +=head1 SYNOPSIS + + #include + + typedef struct evp_mac_st EVP_MAC; + typedef struct evp_mac_ctx_st EVP_MAC_CTX; + + EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac); + EVP_MAC_CTX *EVP_MAC_CTX_new_id(int nid); + void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx); + int EVP_MAC_CTX_copy(EVP_MAC_CTX *dest, EVP_MAC_CTX *src); + const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx); + size_t EVP_MAC_size(EVP_MAC_CTX *ctx); + int EVP_MAC_init(EVP_MAC_CTX *ctx); + int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen); + int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen); + int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...); + int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args); + int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value); + int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value); + int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value); + int EVP_MAC_nid(const EVP_MAC *mac); + const char *EVP_MAC_name(const EVP_MAC *mac); + const EVP_MAC *EVP_get_macbyname(const char *name); + const EVP_MAC *EVP_get_macbynid(int nid); + const EVP_MAC *EVP_get_macbyobj(const ASN1_OBJECT *o); + +=head1 DESCRIPTION + +These types and functions help the application to calculate MACs of +different types and with different underlying algorithms if there are +any. + +MACs are a bit complex insofar that some of them use other algorithms +for actual computation. HMAC uses a digest, and CMAC uses a cipher. +Therefore, there are sometimes two contexts to keep track of, one for +the MAC algorithm itself and one for the underlying computation +algorithm if there is one. + +To make things less ambiguous, this manual talks about a "context" or +"MAC context", which is to denote the MAC level context, and about a +"underlying context", or "computation context", which is to denote the +context for the underlying computation algorithm if there is one. + +=head2 Types + +B is a type that holds the implementation of a MAC. + +B is a context type that holds internal MAC information +as well as a reference to a computation context, for those MACs that +rely on an underlying computation algorithm. + +=head2 Context manipulation functions + +EVP_MAC_CTX_new() creates a new context for the MAC type C. +EVP_MAC_CTX_new_id() creates a new context for the numerical MAC +identity . +The created context can then be used with most other functions +described here. + +EVP_MAC_CTX_free() frees the contents of the context, including an +underlying context if there is one, as well as the context itself. +B is a valid parameter, for which this function is a no-op. + +EVP_MAC_CTX_copy() makes a deep copy of the C context to the +C context. +The C context I have been created before calling this +function. + +EVP_MAC_CTX_mac() returns the B associated with the context +C. + +=head2 Computing functions + +EVP_MAC_init() sets up the underlying context with information given +through diverse controls. +This should be called before calling EVP_MAC_update() and +EVP_MAC_final(). + +EVP_MAC_reset() resets the computation for the given context. +This may not be supported by the MAC implementation. + +EVP_MAC_update() adds C bytes from C to the MAC input. + +EVP_MAC_final() does the final computation and stores the result in +the memory pointed at by C, and sets its size in the B +the C points at. +If C is B, then no computation is made. +To figure out what the output length will be and allocate space for it +dynamically, simply call with C being B and C +pointing at a valid location, then allocate space and make a second +call with C pointing at the allocated space. + +EVP_MAC_ctrl() is used to manipulate or get information on aspects of +the MAC which may vary depending on the MAC algorithm or its +implementation. +This includes the MAC key, and for MACs that use other algorithms to +do their computation, this is also the way to tell it which one to +use. +This functions takes variable arguments, the exact expected arguments +depend on C. +EVP_MAC_ctrl() can be called both before and after EVP_MAC_init(), but +the effect will depend on what control is being use. +See below for a description of standard controls. + +EVP_MAC_vctrl() is the variant of EVP_MAC_ctrl() that takes a +C argument instead of variadic arguments. + +EVP_MAC_ctrl_str() is an alternative to EVP_MAC_ctrl() to control the +MAC implementation as E C, C E pairs. +The MAC implementation documentation should specify what control type +strings are accepted. + +EVP_MAC_str2ctrl() and EVP_MAC_hex2ctrl() are helper functions to +control the MAC implementation with raw strings or with strings +containing hexadecimal numbers. +The latter are decoded into bitstrings that are sent on to +EVP_MAC_ctrl(). + +=head2 Information functions + +EVP_MAC_size() returns the MAC output size for the given context. + +EVP_MAC_nid() returns the numeric identity of the given MAC implementation. + +EVP_MAC_name() returns the name of the given MAC implementation. + +=head2 Object database functions + +EVP_get_macbyname() fetches a MAC implementation from the object +database by name. + +EVP_get_macbynid() fetches a MAC implementation from the object +database by numeric identity. + +EVP_get_macbyobj() fetches a MAC implementation from the object +database by ASN.1 OBJECT (i.e. an encoded OID). + +=head1 CONTROLS + +The standard controls are: + +=over 4 + +=item B + +This control expects two arguments: C, C + +These will set the MAC key from the given string of the given length. +The string may be any bitstring, and can contain NUL bytes. + +For MACs that use an underlying computation algorithm, the algorithm +I be set first, see B, +B and B below. + +=item B + +This control expects one arguments: C + +These will set the MAC flags to the given numbers. +Some MACs do not support this option. + +=item B + +=item B + +=item B + +For MAC implementations that use an underlying computation algorithm, +these controls set what the algorithm should be, and the engine that +implements the algorithm if needed. + +B takes one argument: C + +B takes one argument: C + +B takes one argument: C + +=item B + +For MAC implementations that support it, set the output size that +EVP_MAC_final() should produce. +The allowed sizes vary between MAC implementations. + +=back + +All these control should be used before the calls to any of +EVP_MAC_init(), EVP_MAC_update() and EVP_MAC_final() for a full +computation. +Anything else may give undefined results. + +=head1 NOTES + +EVP_get_macbynid(), EVP_get_macbyobj() and EVP_MAC_name() are +implemented as a macro. + +=head1 RETURN VALUES + +EVP_MAC_CTX_new() and EVP_MAC_CTX_new_id() return a pointer to a newly +created EVP_MAC_CTX, or NULL if allocation failed. + +EVP_MAC_CTX_free() returns nothing at all. + +EVP_MAC_CTX_copy(), EVP_MAC_reset(), EVP_MAC_init(), EVP_MAC_update(), +and EVP_MAC_final() return 1 on success, 0 on error. + +EVP_MAC_ctrl(), EVP_MAC_ctrl_str(), EVP_MAC_str2ctrl() and +EVP_MAC_hex2ctrl() return 1 on success and 0 or a negative value on +error. +In particular, the value -2 indicates that the given control type +isn't supported by the MAC implementation. + +EVP_MAC_size() returns the expected output size, or 0 if it isn't +set. +If it isn't set, a call to EVP_MAC_init() should get it set. + +EVP_MAC_nid() returns the numeric identity for the given C. + +EVP_MAC_name() returns the name for the given C, if it has been +added to the object database. + +EVP_add_mac() returns 1 if the given C was successfully added to +the object database, otherwise 0. + +EVP_get_macbyname(), EVP_get_macbynid() and EVP_get_macbyobj() return +the request MAC implementation, if it exists in the object database, +otherwise B. + +=head1 EXAMPLE + + #include + #include + #include + #include + #include + + #include + #include + + int ctrl_ign_unsupported(EVP_MAC_CTX *ctx, int cmd, ...) + { + va_list args; + int rv; + + va_start(args, cmd); + rv = EVP_MAC_vctrl(ctx, cmd, args); + va_end(args); + + if (rv == -2) + rv = 1; /* Ignore unsupported, pretend it worked fine */ + + return rv; + } + + int main() { + const EVP_MAC *mac = + EVP_get_macbyname(getenv("MY_MAC")); + const EVP_CIPHER *cipher = + EVP_get_cipherbyname(getenv("MY_MAC_CIPHER")); + const EVP_MD *digest = + EVP_get_digestbyname(getenv("MY_MAC_DIGEST")); + const char *key = getenv("MY_KEY"); + EVP_MAC_CTX *ctx = NULL; + + unsigned char buf[4096]; + ssize_t read_l; + size_t final_l; + + size_t i; + + if (mac == NULL + || key == NULL + || (ctx = EVP_MAC_CTX_new(mac)) == NULL + || (cipher != NULL + && !ctrl_ign_unsupported(ctx, EVP_MAC_CTRL_SET_CIPHER, cipher)) + || (digest != NULL + && !ctrl_ign_unsupported(ctx, EVP_MAC_CTRL_SET_MD, digest)) + || EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_KEY, key, strlen(key)) <= 0) + goto err; + + if (!EVP_MAC_init(ctx)) + goto err; + + while ( (read_l = read(STDIN_FILENO, buf, sizeof(buf))) < 0) { + if (!EVP_MAC_update(ctx, buf, read_l)) + goto err; + } + + if (!EVP_MAC_final(ctx, buf, &final_l)) + goto err; + + printf("Result: "); + for (i = 0; i < final_l; i++) + printf("%02X", buf[i]); + printf("\n"); + + EVP_MAC_CTX_free(ctx); + exit(0); + + err: + EVP_MAC_CTX_free(ctx); + fprintf(stderr, "Something went wrong\n"); + ERR_print_errors_fp(stderr); + exit (1); + } + +A run of this program, called with correct environment variables, can +look like this: + + $ MY_MAC=cmac MY_KEY=secret0123456789 MY_MAC_CIPHER=aes-128-cbc \ + LD_LIBRARY_PATH=. ./foo < foo.c + Result: ECCAAFF041B22A2299EB90A1B53B6D45 + +(in this example, that program was stored in F and compiled to +F<./foo>) + +=head1 SEE ALSO + +L, +L, +L + +=head1 COPYRIGHT + +Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the OpenSSL license (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index e1a107c0..75fba58f 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -4,20 +4,55 @@ EVP_PKEY_CTX_ctrl, EVP_PKEY_CTX_ctrl_str, +EVP_PKEY_CTX_ctrl_uint64, +EVP_PKEY_CTX_md, EVP_PKEY_CTX_set_signature_md, EVP_PKEY_CTX_get_signature_md, EVP_PKEY_CTX_set_mac_key, EVP_PKEY_CTX_set_rsa_padding, +EVP_PKEY_CTX_get_rsa_padding, EVP_PKEY_CTX_set_rsa_pss_saltlen, +EVP_PKEY_CTX_get_rsa_pss_saltlen, EVP_PKEY_CTX_set_rsa_keygen_bits, EVP_PKEY_CTX_set_rsa_keygen_pubexp, +EVP_PKEY_CTX_set_rsa_keygen_primes, +EVP_PKEY_CTX_set_rsa_mgf1_md, +EVP_PKEY_CTX_get_rsa_mgf1_md, +EVP_PKEY_CTX_set_rsa_oaep_md, +EVP_PKEY_CTX_get_rsa_oaep_md, +EVP_PKEY_CTX_set0_rsa_oaep_label, +EVP_PKEY_CTX_get0_rsa_oaep_label, EVP_PKEY_CTX_set_dsa_paramgen_bits, EVP_PKEY_CTX_set_dh_paramgen_prime_len, +EVP_PKEY_CTX_set_dh_paramgen_subprime_len, EVP_PKEY_CTX_set_dh_paramgen_generator, +EVP_PKEY_CTX_set_dh_paramgen_type, +EVP_PKEY_CTX_set_dh_rfc5114, +EVP_PKEY_CTX_set_dhx_rfc5114, EVP_PKEY_CTX_set_dh_pad, EVP_PKEY_CTX_set_dh_nid, +EVP_PKEY_CTX_set_dh_kdf_type, +EVP_PKEY_CTX_get_dh_kdf_type, +EVP_PKEY_CTX_set0_dh_kdf_oid, +EVP_PKEY_CTX_get0_dh_kdf_oid, +EVP_PKEY_CTX_set_dh_kdf_md, +EVP_PKEY_CTX_get_dh_kdf_md, +EVP_PKEY_CTX_set_dh_kdf_outlen, +EVP_PKEY_CTX_get_dh_kdf_outlen, +EVP_PKEY_CTX_set0_dh_kdf_ukm, +EVP_PKEY_CTX_get0_dh_kdf_ukm, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_CTX_set_ec_param_enc, +EVP_PKEY_CTX_set_ecdh_cofactor_mode, +EVP_PKEY_CTX_get_ecdh_cofactor_mode, +EVP_PKEY_CTX_set_ecdh_kdf_type, +EVP_PKEY_CTX_get_ecdh_kdf_type, +EVP_PKEY_CTX_set_ecdh_kdf_md, +EVP_PKEY_CTX_get_ecdh_kdf_md, +EVP_PKEY_CTX_set_ecdh_kdf_outlen, +EVP_PKEY_CTX_get_ecdh_kdf_outlen, +EVP_PKEY_CTX_set0_ecdh_kdf_ukm, +EVP_PKEY_CTX_get0_ecdh_kdf_ukm, EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len - algorithm specific control operations @@ -27,9 +62,13 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2); + int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, uint64_t value); int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value); + int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md); + int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd); @@ -38,22 +77,58 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len #include int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad); + int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad); int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int len); + int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *len); int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int mbits); int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp); + int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes); + int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); + int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md); + int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); + int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md); + int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char *label, int len); + int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label); #include + int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits); #include + int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int len); + int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int len); int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen); + int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int type); int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad); int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid); + int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114); + int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int rfc5114); + int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf); + int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx); + int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid); + int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid); + int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); + int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md); + int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int len); + int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len); + int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len); + int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm); #include + int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid); int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc); + int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode); + int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx); + int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf); + int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx); + int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); + int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **md); + int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int len); + int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *len); + int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len); + int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm); int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, void *id, size_t id_len); int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id); @@ -73,6 +148,9 @@ and B is MAC key. This is used by Poly1305, SipHash, HMAC and CMAC. Applications will not normally call EVP_PKEY_CTX_ctrl() directly but will instead call one of the algorithm specific macros below. +The function EVP_PKEY_CTX_ctrl_uint64() is a wrapper that directly passes a +uint64 value as B to EVP_PKEY_CTX_ctrl(). + The function EVP_PKEY_CTX_ctrl_str() allows an application to send an algorithm specific control operation to a context B in string form. This is intended to be used for options specified on the command line or in text @@ -80,6 +158,9 @@ files. The commands supported are documented in the openssl utility command line pages for the option B<-pkeyopt> which is supported by the B, B and B commands. +The function EVP_PKEY_CTX_md() sends a message digest control operation +to the context B. The message digest is specified by its name B. + All the remaining "functions" are implemented as macros. The EVP_PKEY_CTX_set_signature_md() macro sets the message digest type used @@ -99,12 +180,14 @@ L or similar functions instead of this macro. The EVP_PKEY_CTX_set_mac_key() macro can be used with any of the algorithms supported by the L function. -The macro EVP_PKEY_CTX_set_rsa_padding() sets the RSA padding mode for B. -The B parameter can take the value RSA_PKCS1_PADDING for PKCS#1 padding, -RSA_SSLV23_PADDING for SSLv23 padding, RSA_NO_PADDING for no padding, -RSA_PKCS1_OAEP_PADDING for OAEP padding (encrypt and decrypt only), -RSA_X931_PADDING for X9.31 padding (signature operations only) and -RSA_PKCS1_PSS_PADDING (sign and verify only). +=head2 RSA parameters + +The EVP_PKEY_CTX_set_rsa_padding() macro sets the RSA padding mode for B. +The B parameter can take the value B for PKCS#1 +padding, B for SSLv23 padding, B for +no padding, B for OAEP padding (encrypt and +decrypt only), B for X9.31 padding (signature operations +only) and B (sign and verify only). Two RSA padding modes behave differently if EVP_PKEY_CTX_set_signature_md() is used. If this macro is called for PKCS#1 padding the plaintext buffer is @@ -116,41 +199,154 @@ padding for RSA the algorithm identifier byte is added or checked and removed if this control is called. If it is not called then the first byte of the plaintext buffer is expected to be the algorithm identifier byte. +The EVP_PKEY_CTX_get_rsa_padding() macro gets the RSA padding mode for B. + The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro sets the RSA PSS salt length to -B as its name implies it is only supported for PSS padding. Three special -values are supported: RSA_PSS_SALTLEN_DIGEST sets the salt length to the -digest length, RSA_PSS_SALTLEN_MAX sets the salt length to the maximum -permissible value. When verifying RSA_PSS_SALTLEN_AUTO causes the salt length +B. As its name implies it is only supported for PSS padding. Three special +values are supported: B sets the salt length to the +digest length, B sets the salt length to the maximum +permissible value. When verifying B causes the salt length to be automatically determined based on the B block structure. If this macro is not called maximum salt length is used when signing and auto detection when verifying is used by default. +The EVP_PKEY_CTX_get_rsa_pss_saltlen() macro gets the RSA PSS salt length +for B. The padding mode must have been set to B. + The EVP_PKEY_CTX_set_rsa_keygen_bits() macro sets the RSA key length for RSA key generation to B. If not specified 1024 bits is used. The EVP_PKEY_CTX_set_rsa_keygen_pubexp() macro sets the public exponent value -for RSA key generation to B currently it should be an odd integer. The +for RSA key generation to B. Currently it should be an odd integer. The B pointer is used internally by this function so it should not be -modified or free after the call. If this macro is not called then 65537 is used. +modified or freed after the call. If not specified 65537 is used. -The macro EVP_PKEY_CTX_set_dsa_paramgen_bits() sets the number of bits used +The EVP_PKEY_CTX_set_rsa_keygen_primes() macro sets the number of primes for +RSA key generation to B. If not specified 2 is used. + +The EVP_PKEY_CTX_set_rsa_mgf1_md() macro sets the MGF1 digest for RSA padding +schemes to B. If not explicitly set the signing digest is used. The +padding mode must have been set to B +or B. + +The EVP_PKEY_CTX_get_rsa_mgf1_md() macro gets the MGF1 digest for B. +If not explicitly set the signing digest is used. The padding mode must have +been set to B or B. + +The EVP_PKEY_CTX_set_rsa_oaep_md() macro sets the message digest type used +in RSA OAEP to B. The padding mode must have been set to +B. + +The EVP_PKEY_CTX_get_rsa_oaep_md() macro gets the message digest type used +in RSA OAEP to B. The padding mode must have been set to +B. + +The EVP_PKEY_CTX_set0_rsa_oaep_label() macro sets the RSA OAEP label to +B