diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index 65062030..21d83455 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -651,7 +651,7 @@ my %targets = ( dso_scheme => "dlfcn", shared_target => "linux-shared", shared_cflag => "-fPIC", - shared_ldflag => "-Wl,-znodelete", + shared_ldflag => sub { $disabled{pinshared} ? () : "-Wl,-znodelete" }, shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)", enable => [ "afalgeng" ], }, diff --git a/Configure b/Configure index da090030..7a2be83e 100755 --- a/Configure +++ b/Configure @@ -374,6 +374,7 @@ my @disablables = ( "msan", "multiblock", "nextprotoneg", + "pinshared", "ocb", "ocsp", "pic", diff --git a/INSTALL b/INSTALL index 049ff21f..2fd2235d 100644 --- a/INSTALL +++ b/INSTALL @@ -416,6 +416,24 @@ no-pic Don't build with support for Position Independent Code. + no-pinshared By default OpenSSL will attempt to stay in memory until the + process exits. This is so that libcrypto and libssl can be + properly cleaned up automatically via an "atexit()" handler. + The handler is registered by libcrypto and cleans up both + libraries. On some platforms the atexit() handler will run on + unload of libcrypto (if it has been dynamically loaded) + rather than at process exit. This option can be used to stop + OpenSSL from attempting to stay in memory until the process + exits. This could lead to crashes if either libcrypto or + libssl have already been unloaded at the point + that the atexit handler is invoked, e.g. on a platform which + calls atexit() on unload of the library, and libssl is + unloaded before libcrypto then a crash is likely to happen. + Applications can suppress running of the atexit() handler at + run time by using the OPENSSL_INIT_NO_ATEXIT option to + OPENSSL_init_crypto(). See the man page for it for further + details. + no-posix-io Don't use POSIX IO capabilities. diff --git a/apps/verify.c b/apps/verify.c index 3768feda..2f66912c 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -286,16 +286,19 @@ static int cb(int ok, X509_STORE_CTX *ctx) cert_error, X509_STORE_CTX_get_error_depth(ctx), X509_verify_cert_error_string(cert_error)); + + /* + * Pretend that some errors are ok, so they don't stop further + * processing of the certificate chain. Setting ok = 1 does this. + * After X509_verify_cert() is done, we verify that there were + * no actual errors, even if the returned value was positive. + */ switch (cert_error) { case X509_V_ERR_NO_EXPLICIT_POLICY: policies_print(ctx); /* fall thru */ case X509_V_ERR_CERT_HAS_EXPIRED: - - /* - * since we are just checking the certificates, it is ok if they - * are self signed. But we should still warn the user. - */ + /* Continue even if the leaf is a self signed cert */ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: /* Continue after extension errors too */ case X509_V_ERR_INVALID_CA: diff --git a/crypto/armcap.c b/crypto/armcap.c index e97bdd14..70d2719b 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -62,14 +62,12 @@ uint32_t OPENSSL_rdtsc(void) # if defined(__GNUC__) && __GNUC__>=2 void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); # endif -/* - * Use a weak reference to getauxval() so we can use it if it is available but - * don't break the build if it is not. - */ -# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) -extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); -# else -static unsigned long (*getauxval) (unsigned long) = NULL; + +# if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 16) +# include +# define OSSL_IMPLEMENT_GETAUXVAL +# endif # endif /* @@ -134,6 +132,33 @@ void OPENSSL_cpuid_setup(void) */ # endif + OPENSSL_armcap_P = 0; + +# ifdef OSSL_IMPLEMENT_GETAUXVAL + if (getauxval(HWCAP) & HWCAP_NEON) { + unsigned long hwcap = getauxval(HWCAP_CE); + + OPENSSL_armcap_P |= ARMV7_NEON; + + if (hwcap & HWCAP_CE_AES) + OPENSSL_armcap_P |= ARMV8_AES; + + if (hwcap & HWCAP_CE_PMULL) + OPENSSL_armcap_P |= ARMV8_PMULL; + + if (hwcap & HWCAP_CE_SHA1) + OPENSSL_armcap_P |= ARMV8_SHA1; + + if (hwcap & HWCAP_CE_SHA256) + OPENSSL_armcap_P |= ARMV8_SHA256; + +# ifdef __aarch64__ + if (hwcap & HWCAP_CE_SHA512) + OPENSSL_armcap_P |= ARMV8_SHA512; +# endif + } +# endif + sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); sigdelset(&all_masked, SIGTRAP); @@ -141,8 +166,6 @@ void OPENSSL_cpuid_setup(void) sigdelset(&all_masked, SIGBUS); sigdelset(&all_masked, SIGSEGV); - OPENSSL_armcap_P = 0; - memset(&ill_act, 0, sizeof(ill_act)); ill_act.sa_handler = ill_handler; ill_act.sa_mask = all_masked; @@ -150,30 +173,9 @@ void OPENSSL_cpuid_setup(void) sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); sigaction(SIGILL, &ill_act, &ill_oact); - if (getauxval != NULL) { - if (getauxval(HWCAP) & HWCAP_NEON) { - unsigned long hwcap = getauxval(HWCAP_CE); - - OPENSSL_armcap_P |= ARMV7_NEON; - - if (hwcap & HWCAP_CE_AES) - OPENSSL_armcap_P |= ARMV8_AES; - - if (hwcap & HWCAP_CE_PMULL) - OPENSSL_armcap_P |= ARMV8_PMULL; - - if (hwcap & HWCAP_CE_SHA1) - OPENSSL_armcap_P |= ARMV8_SHA1; - - if (hwcap & HWCAP_CE_SHA256) - OPENSSL_armcap_P |= ARMV8_SHA256; - -# ifdef __aarch64__ - if (hwcap & HWCAP_CE_SHA512) - OPENSSL_armcap_P |= ARMV8_SHA512; -# endif - } - } else if (sigsetjmp(ill_jmp, 1) == 0) { + /* If we used getauxval, we already have all the values */ +# ifndef OSSL_IMPLEMENT_GETAUXVAL + if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_neon_probe(); OPENSSL_armcap_P |= ARMV7_NEON; if (sigsetjmp(ill_jmp, 1) == 0) { @@ -191,13 +193,16 @@ void OPENSSL_cpuid_setup(void) _armv8_sha256_probe(); OPENSSL_armcap_P |= ARMV8_SHA256; } -# if defined(__aarch64__) && !defined(__APPLE__) +# if defined(__aarch64__) && !defined(__APPLE__) if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha512_probe(); OPENSSL_armcap_P |= ARMV8_SHA512; } -# endif +# endif } +# endif + + /* Things that getauxval didn't tell us */ if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_tick(); OPENSSL_armcap_P |= ARMV7_TICK; diff --git a/crypto/asn1/charmap.h b/crypto/asn1/charmap.h index 17bf9a40..0374b643 100644 --- a/crypto/asn1/charmap.h +++ b/crypto/asn1/charmap.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/asn1/charmap.pl * - * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/asn1/charmap.pl b/crypto/asn1/charmap.pl index 20f05fcf..d29a21b3 100644 --- a/crypto/asn1/charmap.pl +++ b/crypto/asn1/charmap.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/bio/b_dump.c b/crypto/bio/b_dump.c index f4d2de36..e4ad3615 100644 --- a/crypto/bio/b_dump.c +++ b/crypto/bio/b_dump.c @@ -20,14 +20,15 @@ #define SPACE(buf, pos, n) (sizeof(buf) - (pos) > (n)) int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), - void *u, const char *s, int len) + void *u, const void *s, int len) { return BIO_dump_indent_cb(cb, u, s, len, 0); } int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), - void *u, const char *s, int len, int indent) + void *u, const void *v, int len, int indent) { + const unsigned char *s = v; int ret = 0; char buf[288 + 1]; int i, j, rows, n; @@ -51,7 +52,7 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), if (((i * dump_width) + j) >= len) { strcpy(buf + n, " "); } else { - ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; + ch = *(s + i * dump_width + j) & 0xff; BIO_snprintf(buf + n, 4, "%02x%c", ch, j == 7 ? '-' : ' '); } @@ -66,7 +67,7 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), if (((i * dump_width) + j) >= len) break; if (SPACE(buf, n, 1)) { - ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; + ch = *(s + i * dump_width + j) & 0xff; #ifndef CHARSET_EBCDIC buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.'; #else @@ -96,12 +97,12 @@ static int write_fp(const void *data, size_t len, void *fp) return UP_fwrite(data, len, 1, fp); } -int BIO_dump_fp(FILE *fp, const char *s, int len) +int BIO_dump_fp(FILE *fp, const void *s, int len) { return BIO_dump_cb(write_fp, fp, s, len); } -int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent) +int BIO_dump_indent_fp(FILE *fp, const void *s, int len, int indent) { return BIO_dump_indent_cb(write_fp, fp, s, len, indent); } @@ -112,19 +113,20 @@ static int write_bio(const void *data, size_t len, void *bp) return BIO_write((BIO *)bp, (const char *)data, len); } -int BIO_dump(BIO *bp, const char *s, int len) +int BIO_dump(BIO *bp, const void *s, int len) { return BIO_dump_cb(write_bio, bp, s, len); } -int BIO_dump_indent(BIO *bp, const char *s, int len, int indent) +int BIO_dump_indent(BIO *bp, const void *s, int len, int indent) { return BIO_dump_indent_cb(write_bio, bp, s, len, indent); } -int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, +int BIO_hex_string(BIO *out, int indent, int width, const void *data, int datalen) { + const unsigned char *d = data; int i, j = 0; if (datalen < 1) @@ -134,7 +136,7 @@ int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, if (i && !j) BIO_printf(out, "%*s", indent, ""); - BIO_printf(out, "%02X:", data[i]); + BIO_printf(out, "%02X:", d[i]); j = (j + 1) % width; if (!j) @@ -143,6 +145,6 @@ int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, if (i && !j) BIO_printf(out, "%*s", indent, ""); - BIO_printf(out, "%02X", data[datalen - 1]); + BIO_printf(out, "%02X", d[datalen - 1]); return 1; } diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 83b0e5af..9ea120be 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -648,34 +648,41 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, goto err; } -#ifdef RSAZ_ENABLED - if (!a->neg) { - /* - * If the size of the operands allow it, perform the optimized - * RSAZ exponentiation. For further information see - * crypto/bn/rsaz_exp.c and accompanying assembly modules. - */ - if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) - && rsaz_avx2_eligible()) { - if (NULL == bn_wexpand(rr, 16)) - goto err; - RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, - mont->n0[0]); - rr->top = 16; - rr->neg = 0; - bn_correct_top(rr); - ret = 1; - goto err; - } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) { - if (NULL == bn_wexpand(rr, 8)) - goto err; - RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d); - rr->top = 8; - rr->neg = 0; - bn_correct_top(rr); - ret = 1; + if (a->neg || BN_ucmp(a, m) >= 0) { + BIGNUM *reduced = BN_CTX_get(ctx); + if (reduced == NULL + || !BN_nnmod(reduced, a, m, ctx)) { goto err; } + a = reduced; + } + +#ifdef RSAZ_ENABLED + /* + * If the size of the operands allow it, perform the optimized + * RSAZ exponentiation. For further information see + * crypto/bn/rsaz_exp.c and accompanying assembly modules. + */ + if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) + && rsaz_avx2_eligible()) { + if (NULL == bn_wexpand(rr, 16)) + goto err; + RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, + mont->n0[0]); + rr->top = 16; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) { + if (NULL == bn_wexpand(rr, 8)) + goto err; + RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d); + rr->top = 8; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; } #endif @@ -747,12 +754,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, goto err; /* prepare a^1 in Montgomery domain */ - if (a->neg || BN_ucmp(a, m) >= 0) { - if (!BN_nnmod(&am, a, m, ctx)) - goto err; - if (!bn_to_mont_fixed_top(&am, &am, mont, ctx)) - goto err; - } else if (!bn_to_mont_fixed_top(&am, a, mont, ctx)) + if (!bn_to_mont_fixed_top(&am, a, mont, ctx)) goto err; #if defined(SPARC_T4_MONT) diff --git a/crypto/bn/bn_prime.h b/crypto/bn/bn_prime.h index 22a3ef17..e99433cd 100644 --- a/crypto/bn/bn_prime.h +++ b/crypto/bn/bn_prime.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/bn/bn_prime.pl * - * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/bn/bn_prime.pl b/crypto/bn/bn_prime.pl index fb548101..76df3fc5 100644 --- a/crypto/bn/bn_prime.pl +++ b/crypto/bn/bn_prime.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/chacha/asm/chacha-s390x.pl b/crypto/chacha/asm/chacha-s390x.pl index 1b13a41c..005c810e 100755 --- a/crypto/chacha/asm/chacha-s390x.pl +++ b/crypto/chacha/asm/chacha-s390x.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -20,41 +20,46 @@ # # 3 times faster than compiler-generated code. -$flavour = shift; +# +# August 2018 +# +# Add vx code path. +# +# Copyright IBM Corp. 2018 +# Author: Patrick Steuer +use strict; +use FindBin qw($Bin); +use lib "$Bin/../.."; +use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL INCLUDE); + +my $flavour = shift; + +my ($z,$SIZE_T); if ($flavour =~ /3[12]/) { + $z=0; # S/390 ABI $SIZE_T=4; - $g=""; } else { + $z=1; # zSeries ABI $SIZE_T=8; - $g="g"; } +my $output; while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; - -sub AUTOLOAD() # thunk [simplified] x86-style perlasm -{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; - $code .= "\t$opcode\t".join(',',@_)."\n"; -} my $sp="%r15"; - my $stdframe=16*$SIZE_T+4*8; -my $frame=$stdframe+4*20; - -my ($out,$inp,$len,$key,$counter)=map("%r$_",(2..6)); my @x=map("%r$_",(0..7,"x","x","x","x",(10..13))); my @t=map("%r$_",(8,9)); +my @v=map("%v$_",(16..31)); sub ROUND { my ($a0,$b0,$c0,$d0)=@_; my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); -my ($xc,$xc_)=map("\"$_\"",@t); -my @x=map("\"$_\"",@x); +my ($xc,$xc_)=map("$_",@t); # Consider order in which variables are addressed by their # index: @@ -78,249 +83,542 @@ my @x=map("\"$_\"",@x); # 'c' stores and loads in the middle, but none in the beginning # or end. - ( - "&alr (@x[$a0],@x[$b0])", # Q1 - "&alr (@x[$a1],@x[$b1])", # Q2 - "&xr (@x[$d0],@x[$a0])", - "&xr (@x[$d1],@x[$a1])", - "&rll (@x[$d0],@x[$d0],16)", - "&rll (@x[$d1],@x[$d1],16)", + alr (@x[$a0],@x[$b0]); # Q1 + alr (@x[$a1],@x[$b1]); # Q2 + xr (@x[$d0],@x[$a0]); + xr (@x[$d1],@x[$a1]); + rll (@x[$d0],@x[$d0],16); + rll (@x[$d1],@x[$d1],16); - "&alr ($xc,@x[$d0])", - "&alr ($xc_,@x[$d1])", - "&xr (@x[$b0],$xc)", - "&xr (@x[$b1],$xc_)", - "&rll (@x[$b0],@x[$b0],12)", - "&rll (@x[$b1],@x[$b1],12)", + alr ($xc,@x[$d0]); + alr ($xc_,@x[$d1]); + xr (@x[$b0],$xc); + xr (@x[$b1],$xc_); + rll (@x[$b0],@x[$b0],12); + rll (@x[$b1],@x[$b1],12); - "&alr (@x[$a0],@x[$b0])", - "&alr (@x[$a1],@x[$b1])", - "&xr (@x[$d0],@x[$a0])", - "&xr (@x[$d1],@x[$a1])", - "&rll (@x[$d0],@x[$d0],8)", - "&rll (@x[$d1],@x[$d1],8)", + alr (@x[$a0],@x[$b0]); + alr (@x[$a1],@x[$b1]); + xr (@x[$d0],@x[$a0]); + xr (@x[$d1],@x[$a1]); + rll (@x[$d0],@x[$d0],8); + rll (@x[$d1],@x[$d1],8); - "&alr ($xc,@x[$d0])", - "&alr ($xc_,@x[$d1])", - "&xr (@x[$b0],$xc)", - "&xr (@x[$b1],$xc_)", - "&rll (@x[$b0],@x[$b0],7)", - "&rll (@x[$b1],@x[$b1],7)", + alr ($xc,@x[$d0]); + alr ($xc_,@x[$d1]); + xr (@x[$b0],$xc); + xr (@x[$b1],$xc_); + rll (@x[$b0],@x[$b0],7); + rll (@x[$b1],@x[$b1],7); - "&stm ($xc,$xc_,'$stdframe+4*8+4*$c0($sp)')", # reload pair of 'c's - "&lm ($xc,$xc_,'$stdframe+4*8+4*$c2($sp)')", + stm ($xc,$xc_,"$stdframe+4*8+4*$c0($sp)"); # reload pair of 'c's + lm ($xc,$xc_,"$stdframe+4*8+4*$c2($sp)"); - "&alr (@x[$a2],@x[$b2])", # Q3 - "&alr (@x[$a3],@x[$b3])", # Q4 - "&xr (@x[$d2],@x[$a2])", - "&xr (@x[$d3],@x[$a3])", - "&rll (@x[$d2],@x[$d2],16)", - "&rll (@x[$d3],@x[$d3],16)", + alr (@x[$a2],@x[$b2]); # Q3 + alr (@x[$a3],@x[$b3]); # Q4 + xr (@x[$d2],@x[$a2]); + xr (@x[$d3],@x[$a3]); + rll (@x[$d2],@x[$d2],16); + rll (@x[$d3],@x[$d3],16); - "&alr ($xc,@x[$d2])", - "&alr ($xc_,@x[$d3])", - "&xr (@x[$b2],$xc)", - "&xr (@x[$b3],$xc_)", - "&rll (@x[$b2],@x[$b2],12)", - "&rll (@x[$b3],@x[$b3],12)", + alr ($xc,@x[$d2]); + alr ($xc_,@x[$d3]); + xr (@x[$b2],$xc); + xr (@x[$b3],$xc_); + rll (@x[$b2],@x[$b2],12); + rll (@x[$b3],@x[$b3],12); - "&alr (@x[$a2],@x[$b2])", - "&alr (@x[$a3],@x[$b3])", - "&xr (@x[$d2],@x[$a2])", - "&xr (@x[$d3],@x[$a3])", - "&rll (@x[$d2],@x[$d2],8)", - "&rll (@x[$d3],@x[$d3],8)", + alr (@x[$a2],@x[$b2]); + alr (@x[$a3],@x[$b3]); + xr (@x[$d2],@x[$a2]); + xr (@x[$d3],@x[$a3]); + rll (@x[$d2],@x[$d2],8); + rll (@x[$d3],@x[$d3],8); - "&alr ($xc,@x[$d2])", - "&alr ($xc_,@x[$d3])", - "&xr (@x[$b2],$xc)", - "&xr (@x[$b3],$xc_)", - "&rll (@x[$b2],@x[$b2],7)", - "&rll (@x[$b3],@x[$b3],7)" - ); + alr ($xc,@x[$d2]); + alr ($xc_,@x[$d3]); + xr (@x[$b2],$xc); + xr (@x[$b3],$xc_); + rll (@x[$b2],@x[$b2],7); + rll (@x[$b3],@x[$b3],7); } -$code.=<<___; -.text +sub VX_ROUND { +my ($a0,$b0,$c0,$d0)=@_; +my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); +my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); +my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); -.globl ChaCha20_ctr32 -.type ChaCha20_ctr32,\@function -.align 32 -ChaCha20_ctr32: - lt${g}r $len,$len # $len==0? - bzr %r14 - a${g}hi $len,-64 - l${g}hi %r1,-$frame - stm${g} %r6,%r15,`6*$SIZE_T`($sp) - sl${g}r $out,$inp # difference - la $len,0($inp,$len) # end of input minus 64 - larl %r7,.Lsigma - lgr %r0,$sp - la $sp,0(%r1,$sp) - st${g} %r0,0($sp) + vaf (@v[$a0],@v[$a0],@v[$b0]); + vaf (@v[$a1],@v[$a1],@v[$b1]); + vaf (@v[$a2],@v[$a2],@v[$b2]); + vaf (@v[$a3],@v[$a3],@v[$b3]); + vx (@v[$d0],@v[$d0],@v[$a0]); + vx (@v[$d1],@v[$d1],@v[$a1]); + vx (@v[$d2],@v[$d2],@v[$a2]); + vx (@v[$d3],@v[$d3],@v[$a3]); + verllf (@v[$d0],@v[$d0],16); + verllf (@v[$d1],@v[$d1],16); + verllf (@v[$d2],@v[$d2],16); + verllf (@v[$d3],@v[$d3],16); - lmg %r8,%r11,0($key) # load key - lmg %r12,%r13,0($counter) # load counter - lmg %r6,%r7,0(%r7) # load sigma constant + vaf (@v[$c0],@v[$c0],@v[$d0]); + vaf (@v[$c1],@v[$c1],@v[$d1]); + vaf (@v[$c2],@v[$c2],@v[$d2]); + vaf (@v[$c3],@v[$c3],@v[$d3]); + vx (@v[$b0],@v[$b0],@v[$c0]); + vx (@v[$b1],@v[$b1],@v[$c1]); + vx (@v[$b2],@v[$b2],@v[$c2]); + vx (@v[$b3],@v[$b3],@v[$c3]); + verllf (@v[$b0],@v[$b0],12); + verllf (@v[$b1],@v[$b1],12); + verllf (@v[$b2],@v[$b2],12); + verllf (@v[$b3],@v[$b3],12); - la %r14,0($inp) - st${g} $out,$frame+3*$SIZE_T($sp) - st${g} $len,$frame+4*$SIZE_T($sp) - stmg %r6,%r13,$stdframe($sp) # copy key schedule to stack - srlg @x[12],%r12,32 # 32-bit counter value - j .Loop_outer + vaf (@v[$a0],@v[$a0],@v[$b0]); + vaf (@v[$a1],@v[$a1],@v[$b1]); + vaf (@v[$a2],@v[$a2],@v[$b2]); + vaf (@v[$a3],@v[$a3],@v[$b3]); + vx (@v[$d0],@v[$d0],@v[$a0]); + vx (@v[$d1],@v[$d1],@v[$a1]); + vx (@v[$d2],@v[$d2],@v[$a2]); + vx (@v[$d3],@v[$d3],@v[$a3]); + verllf (@v[$d0],@v[$d0],8); + verllf (@v[$d1],@v[$d1],8); + verllf (@v[$d2],@v[$d2],8); + verllf (@v[$d3],@v[$d3],8); -.align 16 -.Loop_outer: - lm @x[0],@x[7],$stdframe+4*0($sp) # load x[0]-x[7] - lm @t[0],@t[1],$stdframe+4*10($sp) # load x[10]-x[11] - lm @x[13],@x[15],$stdframe+4*13($sp) # load x[13]-x[15] - stm @t[0],@t[1],$stdframe+4*8+4*10($sp) # offload x[10]-x[11] - lm @t[0],@t[1],$stdframe+4*8($sp) # load x[8]-x[9] - st @x[12],$stdframe+4*12($sp) # save counter - st${g} %r14,$frame+2*$SIZE_T($sp) # save input pointer - lhi %r14,10 - j .Loop - -.align 4 -.Loop: -___ - foreach (&ROUND(0, 4, 8,12)) { eval; } - foreach (&ROUND(0, 5,10,15)) { eval; } -$code.=<<___; - brct %r14,.Loop - - l${g} %r14,$frame+2*$SIZE_T($sp) # pull input pointer - stm @t[0],@t[1],$stdframe+4*8+4*8($sp) # offload x[8]-x[9] - lm${g} @t[0],@t[1],$frame+3*$SIZE_T($sp) - - al @x[0],$stdframe+4*0($sp) # accumulate key schedule - al @x[1],$stdframe+4*1($sp) - al @x[2],$stdframe+4*2($sp) - al @x[3],$stdframe+4*3($sp) - al @x[4],$stdframe+4*4($sp) - al @x[5],$stdframe+4*5($sp) - al @x[6],$stdframe+4*6($sp) - al @x[7],$stdframe+4*7($sp) - lrvr @x[0],@x[0] - lrvr @x[1],@x[1] - lrvr @x[2],@x[2] - lrvr @x[3],@x[3] - lrvr @x[4],@x[4] - lrvr @x[5],@x[5] - lrvr @x[6],@x[6] - lrvr @x[7],@x[7] - al @x[12],$stdframe+4*12($sp) - al @x[13],$stdframe+4*13($sp) - al @x[14],$stdframe+4*14($sp) - al @x[15],$stdframe+4*15($sp) - lrvr @x[12],@x[12] - lrvr @x[13],@x[13] - lrvr @x[14],@x[14] - lrvr @x[15],@x[15] - - la @t[0],0(@t[0],%r14) # reconstruct output pointer - cl${g}r %r14,@t[1] - jh .Ltail - - x @x[0],4*0(%r14) # xor with input - x @x[1],4*1(%r14) - st @x[0],4*0(@t[0]) # store output - x @x[2],4*2(%r14) - st @x[1],4*1(@t[0]) - x @x[3],4*3(%r14) - st @x[2],4*2(@t[0]) - x @x[4],4*4(%r14) - st @x[3],4*3(@t[0]) - lm @x[0],@x[3],$stdframe+4*8+4*8($sp) # load x[8]-x[11] - x @x[5],4*5(%r14) - st @x[4],4*4(@t[0]) - x @x[6],4*6(%r14) - al @x[0],$stdframe+4*8($sp) - st @x[5],4*5(@t[0]) - x @x[7],4*7(%r14) - al @x[1],$stdframe+4*9($sp) - st @x[6],4*6(@t[0]) - x @x[12],4*12(%r14) - al @x[2],$stdframe+4*10($sp) - st @x[7],4*7(@t[0]) - x @x[13],4*13(%r14) - al @x[3],$stdframe+4*11($sp) - st @x[12],4*12(@t[0]) - x @x[14],4*14(%r14) - st @x[13],4*13(@t[0]) - x @x[15],4*15(%r14) - st @x[14],4*14(@t[0]) - lrvr @x[0],@x[0] - st @x[15],4*15(@t[0]) - lrvr @x[1],@x[1] - lrvr @x[2],@x[2] - lrvr @x[3],@x[3] - lhi @x[12],1 - x @x[0],4*8(%r14) - al @x[12],$stdframe+4*12($sp) # increment counter - x @x[1],4*9(%r14) - st @x[0],4*8(@t[0]) - x @x[2],4*10(%r14) - st @x[1],4*9(@t[0]) - x @x[3],4*11(%r14) - st @x[2],4*10(@t[0]) - st @x[3],4*11(@t[0]) - - cl${g}r %r14,@t[1] # done yet? - la %r14,64(%r14) - jl .Loop_outer - -.Ldone: - xgr %r0,%r0 - xgr %r1,%r1 - xgr %r2,%r2 - xgr %r3,%r3 - stmg %r0,%r3,$stdframe+4*4($sp) # wipe key copy - stmg %r0,%r3,$stdframe+4*12($sp) - - lm${g} %r6,%r15,`$frame+6*$SIZE_T`($sp) - br %r14 - -.align 16 -.Ltail: - la @t[1],64($t[1]) - stm @x[0],@x[7],$stdframe+4*0($sp) - sl${g}r @t[1],%r14 - lm @x[0],@x[3],$stdframe+4*8+4*8($sp) - l${g}hi @x[6],0 - stm @x[12],@x[15],$stdframe+4*12($sp) - al @x[0],$stdframe+4*8($sp) - al @x[1],$stdframe+4*9($sp) - al @x[2],$stdframe+4*10($sp) - al @x[3],$stdframe+4*11($sp) - lrvr @x[0],@x[0] - lrvr @x[1],@x[1] - lrvr @x[2],@x[2] - lrvr @x[3],@x[3] - stm @x[0],@x[3],$stdframe+4*8($sp) - -.Loop_tail: - llgc @x[4],0(@x[6],%r14) - llgc @x[5],$stdframe(@x[6],$sp) - xr @x[5],@x[4] - stc @x[5],0(@x[6],@t[0]) - la @x[6],1(@x[6]) - brct @t[1],.Loop_tail - - j .Ldone -.size ChaCha20_ctr32,.-ChaCha20_ctr32 - -.align 32 -.Lsigma: -.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 # endian-neutral -.asciz "ChaCha20 for s390x, CRYPTOGAMS by " -.align 4 -___ - -foreach (split("\n",$code)) { - s/\`([^\`]*)\`/eval $1/ge; - - print $_,"\n"; + vaf (@v[$c0],@v[$c0],@v[$d0]); + vaf (@v[$c1],@v[$c1],@v[$d1]); + vaf (@v[$c2],@v[$c2],@v[$d2]); + vaf (@v[$c3],@v[$c3],@v[$d3]); + vx (@v[$b0],@v[$b0],@v[$c0]); + vx (@v[$b1],@v[$b1],@v[$c1]); + vx (@v[$b2],@v[$b2],@v[$c2]); + vx (@v[$b3],@v[$b3],@v[$c3]); + verllf (@v[$b0],@v[$b0],7); + verllf (@v[$b1],@v[$b1],7); + verllf (@v[$b2],@v[$b2],7); + verllf (@v[$b3],@v[$b3],7); } -close STDOUT; + +PERLASM_BEGIN($output); + +INCLUDE ("s390x_arch.h"); +TEXT (); + +################ +# void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len, +# const unsigned int key[8], const unsigned int counter[4]) +{ +my ($out,$inp,$len,$key,$counter)=map("%r$_",(2..6)); + +# VX CODE PATH +{ +my $off=$z*8*16+8; # offset(initial state) +my $frame=$stdframe+4*16+$off; + +GLOBL ("ChaCha20_ctr32"); +TYPE ("ChaCha20_ctr32","\@function"); +ALIGN (32); +LABEL ("ChaCha20_ctr32"); + larl ("%r1","OPENSSL_s390xcap_P"); + + lghi ("%r0",64); +&{$z? \&cgr:\&cr} ($len,"%r0"); + jle ("_s390x_chacha_novx"); + + lg ("%r0","S390X_STFLE+16(%r1)"); + tmhh ("%r0",0x4000); # check for vector facility + jz ("_s390x_chacha_novx"); + +if (!$z) { + llgfr ($len,$len); + std ("%f4","16*$SIZE_T+2*8($sp)"); + std ("%f6","16*$SIZE_T+3*8($sp)"); +} +&{$z? \&stmg:\&stm} ("%r6","%r7","6*$SIZE_T($sp)"); + + lghi ("%r1",-$frame); + lgr ("%r0",$sp); + la ($sp,"0(%r1,$sp)"); # allocate stack frame + + larl ("%r7",".Lsigma"); +&{$z? \&stg:\&st} ("%r0","0($sp)"); # backchain + + vstm ("%v8","%v15","8($sp)") if ($z); + + vlm ("%v1","%v2","0($key)"); # load key + vl ("%v0","0(%r7)"); # load sigma constant + vl ("%v3","0($counter)"); # load iv (counter||nonce) + l ("%r0","0($counter)"); # load counter + vstm ("%v0","%v3","$off($sp)"); # copy initial state to stack + + srlg ("%r1",$len,8); + ltgr ("%r1","%r1"); + jz (".Lvx_4x_done"); + +ALIGN (16); # process 4 64-byte blocks +LABEL (".Lvx_4x"); + vlrepf ("%v$_",($_*4)."+$off($sp)") for (0..15); # load initial + # state + vl ("%v31","16(%r7)"); + vaf ("%v12","%v12","%v31"); # increment counter + + vlr (@v[$_],"%v$_") for (0..15); # copy initial state + + lhi ("%r6",10); + j (".Loop_vx_4x"); + +ALIGN (16); +LABEL (".Loop_vx_4x"); + VX_ROUND( 0, 4, 8,12); # column round + VX_ROUND( 0, 5,10,15); # diagonal round + brct ("%r6",".Loop_vx_4x"); + + vaf (@v[$_],@v[$_],"%v$_") for (0..15); # state += initial + # state (mod 32) + vlm ("%v6","%v7","32(%r7)"); # load vperm operands + +for (0..3) { # blocks 1,2 + vmrhf ("%v0",@v[$_*4+0],@v[$_*4+1]); # ks = serialize(state) + vmrhf ("%v1",@v[$_*4+2],@v[$_*4+3]); + vperm ("%v".($_+ 8),"%v0","%v1","%v6"); + vperm ("%v".($_+12),"%v0","%v1","%v7"); +} + vlm ("%v0","%v7","0($inp)"); # load in + vx ("%v$_","%v$_","%v".($_+8)) for (0..7); # out = in ^ ks + vstm ("%v0","%v7","0($out)"); # store out + + vlm ("%v6","%v7","32(%r7)"); # restore vperm operands + +for (0..3) { # blocks 2,3 + vmrlf ("%v0",@v[$_*4+0],@v[$_*4+1]); # ks = serialize(state) + vmrlf ("%v1",@v[$_*4+2],@v[$_*4+3]); + vperm ("%v".($_+ 8),"%v0","%v1","%v6"); + vperm ("%v".($_+12),"%v0","%v1","%v7"); +} + vlm ("%v0","%v7","128($inp)"); # load in + vx ("%v$_","%v$_","%v".($_+8)) for (0..7); # out = in ^ ks + vstm ("%v0","%v7","128($out)"); # store out + + ahi ("%r0",4); + st ("%r0","48+$off($sp)"); # update initial state + + la ($inp,"256($inp)"); + la ($out,"256($out)"); + brctg ("%r1",".Lvx_4x"); + +ALIGN (16); +LABEL (".Lvx_4x_done"); + lghi ("%r1",0xff); + ngr ($len,"%r1"); + jnz (".Lvx_rem"); + +ALIGN (16); +LABEL (".Lvx_done"); + vzero ("%v$_") for (16..31); # wipe ks and key copy + vstm ("%v16","%v17","16+$off($sp)"); + vlm ("%v8","%v15","8($sp)") if ($z); + + la ($sp,"$frame($sp)"); +&{$z? \&lmg:\&lm} ("%r6","%r7","6*$SIZE_T($sp)"); + +if (!$z) { + ld ("%f4","16*$SIZE_T+2*8($sp)"); + ld ("%f6","16*$SIZE_T+3*8($sp)"); + vzero ("%v$_") for (8..15); +} + br ("%r14"); +ALIGN (16); +LABEL (".Lvx_rem"); + lhi ("%r0",64); + + sr ($len,"%r0"); + brc (2,".Lvx_rem_g64"); # cc==2? + + lghi ("%r1",-$stdframe); + + la ($counter,"48+$off($sp)"); # load updated iv + ar ($len,"%r0"); # restore len + + lgr ("%r7",$counter); +&{$z? \&stg:\&st} ("%r14","14*$SIZE_T+$frame($sp)"); + la ($sp,"0(%r1,$sp)"); + + bras ("%r14","_s390x_chacha_novx"); + + la ($sp,"$stdframe($sp)"); +&{$z? \&lg:\&l} ("%r14","14*$SIZE_T+$frame($sp)"); + lgr ($counter,"%r7"); + j (".Lvx_done"); + +ALIGN (16); +LABEL (".Lvx_rem_g64"); + vlrepf ("%v$_",($_*4)."+$off($sp)") for (0..15); # load initial + # state + vl ("%v31","16(%r7)"); + vaf ("%v12","%v12","%v31"); # increment counter + + vlr (@v[$_],"%v$_") for (0..15); # state = initial state + + lhi ("%r6",10); + j (".Loop_vx_rem"); + +ALIGN (16); +LABEL (".Loop_vx_rem"); + VX_ROUND( 0, 4, 8,12); # column round + VX_ROUND( 0, 5,10,15); # diagonal round + brct ("%r6",".Loop_vx_rem"); + + vaf (@v[$_],@v[$_],"%v$_") for (0..15); # state += initial + # state (mod 32) + vlm ("%v6","%v7","32(%r7)"); # load vperm operands + +for (0..3) { # blocks 1,2 + vmrhf ("%v0",@v[$_*4+0],@v[$_*4+1]); # ks = serialize(state) + vmrhf ("%v1",@v[$_*4+2],@v[$_*4+3]); + vperm ("%v".($_+8),"%v0","%v1","%v6"); + vperm ("%v".($_+12),"%v0","%v1","%v7"); +} + vlm ("%v0","%v3","0($inp)"); # load in + vx ("%v$_","%v$_","%v".($_+8)) for (0..3); # out = in ^ ks + vstm ("%v0","%v3","0($out)"); # store out + + la ($inp,"64($inp)"); + la ($out,"64($out)"); + + sr ($len,"%r0"); + brc (4,".Lvx_tail"); # cc==4? + + vlm ("%v0","%v3","0($inp)"); # load in + vx ("%v$_","%v$_","%v".($_+12)) for (0..3); # out = in ^ ks + vstm ("%v0","%v3","0($out)"); # store out + jz (".Lvx_done"); + +for (0..3) { # blocks 3,4 + vmrlf ("%v0",@v[$_*4+0],@v[$_*4+1]); # ks = serialize(state) + vmrlf ("%v1",@v[$_*4+2],@v[$_*4+3]); + vperm ("%v".($_+12),"%v0","%v1","%v6"); + vperm ("%v".($_+8),"%v0","%v1","%v7"); +} + la ($inp,"64($inp)"); + la ($out,"64($out)"); + + sr ($len,"%r0"); + brc (4,".Lvx_tail"); # cc==4? + + vlm ("%v0","%v3","0($inp)"); # load in + vx ("%v$_","%v$_","%v".($_+12)) for (0..3); # out = in ^ ks + vstm ("%v0","%v3","0($out)"); # store out + jz (".Lvx_done"); + + la ($inp,"64($inp)"); + la ($out,"64($out)"); + + sr ($len,"%r0"); + vlr ("%v".($_+4),"%v$_") for (8..11); + j (".Lvx_tail"); + +ALIGN (16); +LABEL (".Lvx_tail"); + ar ($len,"%r0"); # restore $len + ahi ($len,-1); + + lhi ("%r0",16); +for (0..2) { + vll ("%v0",$len,($_*16)."($inp)"); + vx ("%v0","%v0","%v".($_+12)); + vstl ("%v0",$len,($_*16)."($out)"); + sr ($len,"%r0"); + brc (4,".Lvx_done"); # cc==4? +} + vll ("%v0",$len,"3*16($inp)"); + vx ("%v0","%v0","%v15"); + vstl ("%v0",$len,"3*16($out)"); + j (".Lvx_done"); +SIZE ("ChaCha20_ctr32",".-ChaCha20_ctr32"); +} + +# NOVX CODE PATH +{ +my $frame=$stdframe+4*20; + +TYPE ("_s390x_chacha_novx","\@function"); +ALIGN (32); +LABEL ("_s390x_chacha_novx"); +&{$z? \<gr:\<r} ($len,$len); # $len==0? + bzr ("%r14"); +&{$z? \&aghi:\&ahi} ($len,-64); +&{$z? \&lghi:\&lhi} ("%r1",-$frame); +&{$z? \&stmg:\&stm} ("%r6","%r15","6*$SIZE_T($sp)"); +&{$z? \&slgr:\&slr} ($out,$inp); # difference + la ($len,"0($inp,$len)"); # end of input minus 64 + larl ("%r7",".Lsigma"); + lgr ("%r0",$sp); + la ($sp,"0(%r1,$sp)"); +&{$z? \&stg:\&st} ("%r0","0($sp)"); + + lmg ("%r8","%r11","0($key)"); # load key + lmg ("%r12","%r13","0($counter)"); # load counter + lmg ("%r6","%r7","0(%r7)"); # load sigma constant + + la ("%r14","0($inp)"); +&{$z? \&stg:\&st} ($out,"$frame+3*$SIZE_T($sp)"); +&{$z? \&stg:\&st} ($len,"$frame+4*$SIZE_T($sp)"); + stmg ("%r6","%r13","$stdframe($sp)");# copy key schedule to stack + srlg (@x[12],"%r12",32); # 32-bit counter value + j (".Loop_outer"); + +ALIGN (16); +LABEL (".Loop_outer"); + lm (@x[0],@x[7],"$stdframe+4*0($sp)"); # load x[0]-x[7] + lm (@t[0],@t[1],"$stdframe+4*10($sp)"); # load x[10]-x[11] + lm (@x[13],@x[15],"$stdframe+4*13($sp)"); # load x[13]-x[15] + stm (@t[0],@t[1],"$stdframe+4*8+4*10($sp)");# offload x[10]-x[11] + lm (@t[0],@t[1],"$stdframe+4*8($sp)"); # load x[8]-x[9] + st (@x[12],"$stdframe+4*12($sp)"); # save counter +&{$z? \&stg:\&st} ("%r14","$frame+2*$SIZE_T($sp)");# save input pointer + lhi ("%r14",10); + j (".Loop"); + +ALIGN (4); +LABEL (".Loop"); + ROUND (0, 4, 8,12); + ROUND (0, 5,10,15); + brct ("%r14",".Loop"); + +&{$z? \&lg:\&l} ("%r14","$frame+2*$SIZE_T($sp)");# pull input pointer + stm (@t[0],@t[1],"$stdframe+4*8+4*8($sp)"); # offload x[8]-x[9] +&{$z? \&lmg:\&lm} (@t[0],@t[1],"$frame+3*$SIZE_T($sp)"); + + al (@x[0],"$stdframe+4*0($sp)"); # accumulate key schedule + al (@x[1],"$stdframe+4*1($sp)"); + al (@x[2],"$stdframe+4*2($sp)"); + al (@x[3],"$stdframe+4*3($sp)"); + al (@x[4],"$stdframe+4*4($sp)"); + al (@x[5],"$stdframe+4*5($sp)"); + al (@x[6],"$stdframe+4*6($sp)"); + al (@x[7],"$stdframe+4*7($sp)"); + lrvr (@x[0],@x[0]); + lrvr (@x[1],@x[1]); + lrvr (@x[2],@x[2]); + lrvr (@x[3],@x[3]); + lrvr (@x[4],@x[4]); + lrvr (@x[5],@x[5]); + lrvr (@x[6],@x[6]); + lrvr (@x[7],@x[7]); + al (@x[12],"$stdframe+4*12($sp)"); + al (@x[13],"$stdframe+4*13($sp)"); + al (@x[14],"$stdframe+4*14($sp)"); + al (@x[15],"$stdframe+4*15($sp)"); + lrvr (@x[12],@x[12]); + lrvr (@x[13],@x[13]); + lrvr (@x[14],@x[14]); + lrvr (@x[15],@x[15]); + + la (@t[0],"0(@t[0],%r14)"); # reconstruct output pointer +&{$z? \&clgr:\&clr} ("%r14",@t[1]); + jh (".Ltail"); + + x (@x[0],"4*0(%r14)"); # xor with input + x (@x[1],"4*1(%r14)"); + st (@x[0],"4*0(@t[0])"); # store output + x (@x[2],"4*2(%r14)"); + st (@x[1],"4*1(@t[0])"); + x (@x[3],"4*3(%r14)"); + st (@x[2],"4*2(@t[0])"); + x (@x[4],"4*4(%r14)"); + st (@x[3],"4*3(@t[0])"); + lm (@x[0],@x[3],"$stdframe+4*8+4*8($sp)"); # load x[8]-x[11] + x (@x[5],"4*5(%r14)"); + st (@x[4],"4*4(@t[0])"); + x (@x[6],"4*6(%r14)"); + al (@x[0],"$stdframe+4*8($sp)"); + st (@x[5],"4*5(@t[0])"); + x (@x[7],"4*7(%r14)"); + al (@x[1],"$stdframe+4*9($sp)"); + st (@x[6],"4*6(@t[0])"); + x (@x[12],"4*12(%r14)"); + al (@x[2],"$stdframe+4*10($sp)"); + st (@x[7],"4*7(@t[0])"); + x (@x[13],"4*13(%r14)"); + al (@x[3],"$stdframe+4*11($sp)"); + st (@x[12],"4*12(@t[0])"); + x (@x[14],"4*14(%r14)"); + st (@x[13],"4*13(@t[0])"); + x (@x[15],"4*15(%r14)"); + st (@x[14],"4*14(@t[0])"); + lrvr (@x[0],@x[0]); + st (@x[15],"4*15(@t[0])"); + lrvr (@x[1],@x[1]); + lrvr (@x[2],@x[2]); + lrvr (@x[3],@x[3]); + lhi (@x[12],1); + x (@x[0],"4*8(%r14)"); + al (@x[12],"$stdframe+4*12($sp)"); # increment counter + x (@x[1],"4*9(%r14)"); + st (@x[0],"4*8(@t[0])"); + x (@x[2],"4*10(%r14)"); + st (@x[1],"4*9(@t[0])"); + x (@x[3],"4*11(%r14)"); + st (@x[2],"4*10(@t[0])"); + st (@x[3],"4*11(@t[0])"); + +&{$z? \&clgr:\&clr} ("%r14",@t[1]); # done yet? + la ("%r14","64(%r14)"); + jl (".Loop_outer"); + +LABEL (".Ldone"); + xgr ("%r0","%r0"); + xgr ("%r1","%r1"); + xgr ("%r2","%r2"); + xgr ("%r3","%r3"); + stmg ("%r0","%r3","$stdframe+4*4($sp)"); # wipe key copy + stmg ("%r0","%r3","$stdframe+4*12($sp)"); + +&{$z? \&lmg:\&lm} ("%r6","%r15","$frame+6*$SIZE_T($sp)"); + br ("%r14"); + +ALIGN (16); +LABEL (".Ltail"); + la (@t[1],"64($t[1])"); + stm (@x[0],@x[7],"$stdframe+4*0($sp)"); +&{$z? \&slgr:\&slr} (@t[1],"%r14"); + lm (@x[0],@x[3],"$stdframe+4*8+4*8($sp)"); +&{$z? \&lghi:\&lhi} (@x[6],0); + stm (@x[12],@x[15],"$stdframe+4*12($sp)"); + al (@x[0],"$stdframe+4*8($sp)"); + al (@x[1],"$stdframe+4*9($sp)"); + al (@x[2],"$stdframe+4*10($sp)"); + al (@x[3],"$stdframe+4*11($sp)"); + lrvr (@x[0],@x[0]); + lrvr (@x[1],@x[1]); + lrvr (@x[2],@x[2]); + lrvr (@x[3],@x[3]); + stm (@x[0],@x[3],"$stdframe+4*8($sp)"); + +LABEL (".Loop_tail"); + llgc (@x[4],"0(@x[6],%r14)"); + llgc (@x[5],"$stdframe(@x[6],$sp)"); + xr (@x[5],@x[4]); + stc (@x[5],"0(@x[6],@t[0])"); + la (@x[6],"1(@x[6])"); + brct (@t[1],".Loop_tail"); + + j (".Ldone"); +SIZE ("_s390x_chacha_novx",".-_s390x_chacha_novx"); +} +} +################ + +ALIGN (64); +LABEL (".Lsigma"); +LONG (0x61707865,0x3320646e,0x79622d32,0x6b206574); # endian-neutral sigma +LONG (0x00000000,0x00000001,0x00000002,0x00000003); # vaf counter increment +LONG (0x03020100,0x07060504,0x13121110,0x17161514); # vperm serialization +LONG (0x0b0a0908,0x0f0e0d0c,0x1b1a1918,0x1f1e1d1c); # vperm serialization +ASCIZ ("\"ChaCha20 for s390x, CRYPTOGAMS by \""); +ALIGN (4); + +PERLASM_END(); diff --git a/crypto/chacha/build.info b/crypto/chacha/build.info index 02f8e518..e1d61164 100644 --- a/crypto/chacha/build.info +++ b/crypto/chacha/build.info @@ -9,6 +9,7 @@ GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl $(PERLASM_SCHEME) INCLUDE[chacha-armv4.o]=.. GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl $(PERLASM_SCHEME) INCLUDE[chacha-armv8.o]=.. +INCLUDE[chacha-s390x.o]=.. BEGINRAW[Makefile(unix)] ##### CHACHA assembler implementations diff --git a/crypto/conf/conf_def.h b/crypto/conf/conf_def.h index 275df0c2..9b2a3c1b 100644 --- a/crypto/conf/conf_def.h +++ b/crypto/conf/conf_def.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/conf/keysets.pl * - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c index 860ac676..606563a4 100644 --- a/crypto/conf/conf_lib.c +++ b/crypto/conf/conf_lib.c @@ -358,11 +358,36 @@ OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void) if (ret != NULL) memset(ret, 0, sizeof(*ret)); + ret->flags = DEFAULT_CONF_MFLAGS; + return ret; } #ifndef OPENSSL_NO_STDIO +int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, + const char *filename) +{ + char *newfilename = NULL; + + if (filename != NULL) { + newfilename = strdup(filename); + if (newfilename == NULL) + return 0; + } + + free(settings->filename); + settings->filename = newfilename; + + return 1; +} + +void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, + unsigned long flags) +{ + settings->flags = flags; +} + int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, const char *appname) { @@ -383,6 +408,7 @@ int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings) { + free(settings->filename); free(settings->appname); free(settings); } diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c index 4ce3951d..3ad09a79 100644 --- a/crypto/conf/conf_mod.c +++ b/crypto/conf/conf_mod.c @@ -142,6 +142,9 @@ int CONF_modules_load_file(const char *filename, const char *appname, OPENSSL_free(file); NCONF_free(conf); + if (flags & CONF_MFLAGS_IGNORE_RETURN_CODES) + return 1; + return ret; } diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c index c0876cbb..38621db3 100644 --- a/crypto/conf/conf_sap.c +++ b/crypto/conf/conf_sap.c @@ -39,10 +39,24 @@ void OPENSSL_config(const char *appname) } #endif -void openssl_config_int(const char *appname) +int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings) { + int ret; + const char *filename; + const char *appname; + unsigned long flags; + if (openssl_configured) - return; + return 1; + + filename = settings ? settings->filename : NULL; + appname = settings ? settings->appname : NULL; + flags = settings ? settings->flags : DEFAULT_CONF_MFLAGS; + +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: openssl_config_int(%s, %s, %lu)\n", + filename, appname, flags); +#endif OPENSSL_load_builtin_modules(); #ifndef OPENSSL_NO_ENGINE @@ -51,11 +65,10 @@ void openssl_config_int(const char *appname) #endif ERR_clear_error(); #ifndef OPENSSL_SYS_UEFI - CONF_modules_load_file(NULL, appname, - CONF_MFLAGS_DEFAULT_SECTION | - CONF_MFLAGS_IGNORE_MISSING_FILE); + ret = CONF_modules_load_file(filename, appname, flags); #endif openssl_configured = 1; + return ret; } void openssl_no_config_int(void) diff --git a/crypto/conf/keysets.pl b/crypto/conf/keysets.pl index cb3c3787..68addbfe 100644 --- a/crypto/conf/keysets.pl +++ b/crypto/conf/keysets.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/des/asm/des_enc.m4 b/crypto/des/asm/des_enc.m4 index 92b9678d..9a17fac6 100644 --- a/crypto/des/asm/des_enc.m4 +++ b/crypto/des/asm/des_enc.m4 @@ -29,8 +29,6 @@ .ident "des_enc.m4 2.1" .file "des_enc-sparc.S" -#include - #if defined(__SUNPRO_C) && defined(__sparcv9) # define ABI64 /* They've said -xarch=v9 at command line */ #elif defined(__GNUC__) && defined(__arch64__) diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index f426be01..f1b193bb 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -111,7 +111,7 @@ int DSO_up_ref(DSO *dso) if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0) return 0; - REF_PRINT_COUNT("DSO", r); + REF_PRINT_COUNT("DSO", dso); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c index 2db7d192..82affd6e 100644 --- a/crypto/ec/ecp_nistz256.c +++ b/crypto/ec/ecp_nistz256.c @@ -1432,7 +1432,7 @@ void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre) return; CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); - REF_PRINT_COUNT("EC_nistz256", x); + REF_PRINT_COUNT("EC_nistz256", pre); if (i > 0) return; REF_ASSERT_ISNT(i < 0); diff --git a/crypto/err/err.c b/crypto/err/err.c index c80aa6be..44e7115f 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -741,6 +741,18 @@ int err_shelve_state(void **state) { int saveerrno = get_last_sys_error(); + /* + * Note, at present our only caller is OPENSSL_init_crypto(), indirectly + * via ossl_init_load_crypto_nodelete(), by which point the requested + * "base" initialization has already been performed, so the below call is a + * NOOP, that re-enters OPENSSL_init_crypto() only to quickly return. + * + * If are no other valid callers of this function, the call below can be + * removed, avoiding the re-entry into OPENSSL_init_crypto(). If there are + * potential uses that are not from inside OPENSSL_init_crypto(), then this + * call is needed, but some care is required to make sure that the re-entry + * remains a NOOP. + */ if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL)) return 0; diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index a882f217..8dc52352 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -927,6 +927,11 @@ static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len); # endif /* OPENSSL_NO_OCB */ +# ifndef OPENSSL_NO_SIV +# define aes_t4_siv_init_key aes_siv_init_key +# define aes_t4_siv_cipher aes_siv_cipher +# endif /* OPENSSL_NO_SIV */ + # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ static const EVP_CIPHER aes_t4_##keylen##_##mode = { \ nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ @@ -2427,6 +2432,18 @@ static int s390x_aes_ocb_cleanup(EVP_CIPHER_CTX *); static int s390x_aes_ocb_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr); # endif +# ifndef OPENSSL_NO_SIV +# define S390X_AES_SIV_CTX EVP_AES_SIV_CTX +# define S390X_aes_128_siv_CAPABLE 0 +# define S390X_aes_192_siv_CAPABLE 0 +# define S390X_aes_256_siv_CAPABLE 0 + +# define s390x_aes_siv_init_key aes_siv_init_key +# define s390x_aes_siv_cipher aes_siv_cipher +# define s390x_aes_siv_cleanup aes_siv_cleanup +# define s390x_aes_siv_ctrl aes_siv_ctrl +# endif + # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode, \ MODE,flags) \ static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \ @@ -2468,7 +2485,7 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \ nid##_##keylen##_##mode, \ blocksize, \ - (EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8, \ ivlen, \ flags | EVP_CIPH_##MODE##_MODE, \ s390x_aes_##mode##_init_key, \ @@ -2482,7 +2499,7 @@ static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \ }; \ static const EVP_CIPHER aes_##keylen##_##mode = { \ nid##_##keylen##_##mode,blocksize, \ - (EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \ + (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8, \ ivlen, \ flags | EVP_CIPH_##MODE##_MODE, \ aes_##mode##_init_key, \ diff --git a/crypto/init.c b/crypto/init.c index 1736f2db..22d28a98 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -100,10 +100,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) return 0; if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) goto err; -#ifndef OPENSSL_SYS_UEFI - if (atexit(OPENSSL_cleanup) != 0) - goto err; -#endif OPENSSL_cpuid_setup(); destructor_key.value = key; @@ -121,13 +117,53 @@ err: return 0; } +static CRYPTO_ONCE register_atexit = CRYPTO_ONCE_STATIC_INIT; +#if !defined(OPENSSL_SYS_UEFI) && defined(_WIN32) +static int win32atexit(void) +{ + OPENSSL_cleanup(); + return 0; +} +#endif + +DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n"); +#endif +#ifndef OPENSSL_SYS_UEFI +# ifdef _WIN32 + /* We use _onexit() in preference because it gets called on DLL unload */ + if (_onexit(win32atexit) == NULL) + return 0; +# else + if (atexit(OPENSSL_cleanup) != 0) + return 0; +# endif +#endif + + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit, + ossl_init_register_atexit) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_no_register_atexit ok!\n"); +#endif + /* Do nothing in this case */ + return 1; +} + static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) { #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n"); #endif -#if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) +#if !defined(OPENSSL_NO_DSO) \ + && !defined(OPENSSL_USE_NODELETE) \ + && !defined(OPENSSL_NO_PINSHARED) # ifdef DSO_WIN32 { HMODULE handle = NULL; @@ -177,12 +213,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT; static int load_crypto_strings_inited = 0; -DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_crypto_strings) -{ - /* Do nothing in this case */ - return 1; -} - DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) { int ret = 1; @@ -201,6 +231,13 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) return ret; } +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings, + ossl_init_load_crypto_strings) +{ + /* Do nothing in this case */ + return 1; +} + static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) { @@ -218,6 +255,13 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) return 1; } +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers, + ossl_init_add_all_ciphers) +{ + /* Do nothing */ + return 1; +} + static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) { @@ -235,6 +279,13 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) return 1; } +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests, + ossl_init_add_all_digests) +{ + /* Do nothing */ + return 1; +} + static CRYPTO_ONCE add_all_macs = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_macs) { @@ -252,7 +303,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_macs) return 1; } -DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs) +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_macs, ossl_init_add_all_macs) { /* Do nothing */ return 1; @@ -260,19 +311,14 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs) static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT; static int config_inited = 0; -static const char *appname; +static const OPENSSL_INIT_SETTINGS *conf_settings = NULL; DEFINE_RUN_ONCE_STATIC(ossl_init_config) { -#ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, - "OPENSSL_INIT: ossl_init_config: openssl_config(%s)\n", - appname == NULL ? "NULL" : appname); -#endif - openssl_config_int(appname); + int ret = openssl_config_int(conf_settings); config_inited = 1; - return 1; + return ret; } -DEFINE_RUN_ONCE_STATIC(ossl_init_no_config) +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config) { #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, @@ -603,17 +649,44 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; } + /* + * When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the + * *only* option specified. With that option we return immediately after + * doing the requested limited initialization. Note that + * err_shelve_state() called by us via ossl_init_load_crypto_nodelete() + * re-enters OPENSSL_init_crypto() with OPENSSL_INIT_BASE_ONLY, but with + * base already initialized this is a harmless NOOP. + * + * If we remain the only caller of err_shelve_state() the recursion should + * perhaps be removed, but if in doubt, it can be left in place. + */ if (!RUN_ONCE(&base, ossl_init_base)) return 0; - if (!(opts & OPENSSL_INIT_BASE_ONLY) - && !RUN_ONCE(&load_crypto_nodelete, - ossl_init_load_crypto_nodelete)) + if (opts & OPENSSL_INIT_BASE_ONLY) + return 1; + + /* + * Now we don't always set up exit handlers, the INIT_BASE_ONLY calls + * should not have the side-effect of setting up exit handlers, and + * therefore, this code block is below the INIT_BASE_ONLY-conditioned early + * return above. + */ + if ((opts & OPENSSL_INIT_NO_ATEXIT) != 0) { + if (!RUN_ONCE_ALT(®ister_atexit, ossl_init_no_register_atexit, + ossl_init_register_atexit)) + return 0; + } else if (!RUN_ONCE(®ister_atexit, ossl_init_register_atexit)) { + return 0; + } + + if (!RUN_ONCE(&load_crypto_nodelete, ossl_init_load_crypto_nodelete)) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) - && !RUN_ONCE(&load_crypto_strings, - ossl_init_no_load_crypto_strings)) + && !RUN_ONCE_ALT(&load_crypto_strings, + ossl_init_no_load_crypto_strings, + ossl_init_load_crypto_strings)) return 0; if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) @@ -621,7 +694,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) - && !RUN_ONCE(&add_all_ciphers, ossl_init_no_add_algs)) + && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers, + ossl_init_add_all_ciphers)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS) @@ -629,7 +703,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) - && !RUN_ONCE(&add_all_digests, ossl_init_no_add_algs)) + && !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests, + ossl_init_add_all_digests)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS) @@ -637,7 +712,8 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_MACS) - && !RUN_ONCE(&add_all_macs, ossl_init_no_add_algs)) + && !RUN_ONCE_ALT(&add_all_macs, ossl_init_no_add_all_macs, + ossl_init_add_all_macs)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_MACS) @@ -649,14 +725,15 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) - && !RUN_ONCE(&config, ossl_init_no_config)) + && !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config)) return 0; if (opts & OPENSSL_INIT_LOAD_CONFIG) { int ret; CRYPTO_THREAD_write_lock(init_lock); - appname = (settings == NULL) ? NULL : settings->appname; + conf_settings = settings; ret = RUN_ONCE(&config, ossl_init_config); + conf_settings = NULL; CRYPTO_THREAD_unlock(init_lock); if (!ret) return 0; @@ -720,7 +797,9 @@ int OPENSSL_atexit(void (*handler)(void)) { OPENSSL_INIT_STOP *newhand; -#if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) +#if !defined(OPENSSL_NO_DSO) \ + && !defined(OPENSSL_USE_NODELETE)\ + && !defined(OPENSSL_NO_PINSHARED) { union { void *sym; diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 09c53e08..550e794f 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/obj_dat.pl * - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at diff --git a/crypto/objects/obj_dat.pl b/crypto/objects/obj_dat.pl index 6885b9b3..24f09b49 100644 --- a/crypto/objects/obj_dat.pl +++ b/crypto/objects/obj_dat.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h index dc0a0d65..1c2a0636 100644 --- a/crypto/objects/obj_xref.h +++ b/crypto/objects/obj_xref.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by objxref.pl * - * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/objects/objects.pl b/crypto/objects/objects.pl index e387313b..62d6b44b 100644 --- a/crypto/objects/objects.pl +++ b/crypto/objects/objects.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/objects/objxref.pl b/crypto/objects/objxref.pl index b1b7eb97..e6b69a83 100644 --- a/crypto/objects/objxref.pl +++ b/crypto/objects/objxref.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/perlasm/s390x.pm b/crypto/perlasm/s390x.pm new file mode 100644 index 00000000..5f3a49dd --- /dev/null +++ b/crypto/perlasm/s390x.pm @@ -0,0 +1,3060 @@ +#!/usr/bin/env perl +# 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 + +# Copyright IBM Corp. 2018 +# Author: Patrick Steuer + +package perlasm::s390x; + +use strict; +use warnings; +use Carp qw(confess); +use Exporter qw(import); + +our @EXPORT=qw(PERLASM_BEGIN PERLASM_END); +our @EXPORT_OK=qw(AUTOLOAD LABEL INCLUDE stfle); +our %EXPORT_TAGS=( + MSA => [qw(kmac km kmc kimd klmd)], + MSA4 => [qw(kmf kmo pcc kmctr)], + MSA5 => [qw(ppno prno)], + MSA8 => [qw(kma)], + VX => [qw(vgef vgeg vgbm vzero vone vgm vgmb vgmh vgmf vgmg + vl vlr vlrep vlrepb vlreph vlrepf vlrepg vleb vleh vlef vleg vleib + vleih vleif vleig vlgv vlgvb vlgvh vlgvf vlgvg vllez vllezb vllezh + vllezf vllezg vlm vlbb vlvg vlvgb vlvgh vlvgf vlvgg vlvgp + vll vmrh vmrhb vmrhh vmrhf vmrhg vmrl vmrlb vmrlh vmrlf vmrlg vpk + vpkh vpkf vpkg vpks vpksh vpksf vpksg vpkshs vpksfs vpksgs vpkls + vpklsh vpklsf vpklsg vpklshs vpklsfs vpklsgs vperm vpdi vrep vrepb + vreph vrepf vrepg vrepi vrepib vrepih vrepif vrepig vscef vsceg + vsel vseg vsegb vsegh vsegf vst vsteb vsteh vstef vsteg vstm vstl + vuph vuphb vuphh vuphf vuplh vuplhb vuplhh vuplhf vupl vuplb vuplhw + vuplf vupll vupllb vupllh vupllf va vab vah vaf vag vaq vacc vaccb + vacch vaccf vaccg vaccq vac vacq vaccc vacccq vn vnc vavg vavgb + vavgh vavgf vavgg vavgl vavglb vavglh vavglf vavglg vcksm vec_ vecb + vech vecf vecg vecl veclb veclh veclf veclg vceq vceqb vceqh vceqf + vceqg vceqbs vceqhs vceqfs vceqgs vch vchb vchh vchf vchg vchbs + vchhs vchfs vchgs vchl vchlb vchlh vchlf vchlg vchlbs vchlhs vchlfs + vchlgs vclz vclzb vclzh vclzf vclzg vctz vctzb vctzh vctzf vctzg + vx vgfm vgfmb vgfmh vgfmf vgfmg vgfma vgfmab vgfmah vgfmaf vgfmag + vlc vlcb vlch vlcf vlcg vlp vlpb vlph vlpf vlpg vmx vmxb vmxh vmxf + vmxg vmxl vmxlb vmxlh vmxlf vmxlg vmn vmnb vmnh vmnf vmng vmnl + vmnlb vmnlh vmnlf vmnlg vmal vmalb vmalhw vmalf vmah vmahb vmahh + vmahf vmalh vmalhb vmalhh vmalhf vmae vmaeb vmaeh vmaef vmale + vmaleb vmaleh vmalef vmao vmaob vmaoh vmaof vmalo vmalob vmaloh + vmalof vmh vmhb vmhh vmhf vmlh vmlhb vmlhh vmlhf vml vmlb vmlhw + vmlf vme vmeb vmeh vmef vmle vmleb vmleh vmlef vmo vmob vmoh vmof + vmlo vmlob vmloh vmlof vno vnot vo vpopct verllv verllvb verllvh + verllvf verllvg verll verllb verllh verllf verllg verim verimb + verimh verimf verimg veslv veslvb veslvh veslvf veslvg vesl veslb + veslh veslf veslg vesrav vesravb vesravh vesravf vesravg vesra + vesrab vesrah vesraf vesrag vesrlv vesrlvb vesrlvh vesrlvf vesrlvg + vesrl vesrlb vesrlh vesrlf vesrlg vsl vslb vsldb vsra vsrab vsrl + vsrlb vs vsb vsh vsf vsg vsq vscbi vscbib vscbih vscbif vscbig + vscbiq vsbi vsbiq vsbcbi vsbcbiq vsumg vsumgh vsumgf vsumq vsumqf + vsumqg vsum vsumb vsumh vtm vfae vfaeb vfaeh vfaef vfaebs vfaehs + vfaefs vfaezb vfaezh vfaezf vfaezbs vfaezhs vfaezfs vfee vfeeb + vfeeh vfeef vfeebs vfeehs vfeefs vfeezb vfeezh vfeezf vfeezbs + vfeezhs vfeezfs vfene vfeneb vfeneh vfenef vfenebs vfenehs vfenefs + vfenezb vfenezh vfenezf vfenezbs vfenezhs vfenezfs vistr vistrb + vistrh vistrf vistrbs vistrhs vistrfs vstrc vstrcb vstrch vstrcf + vstrcbs vstrchs vstrcfs vstrczb vstrczh vstrczf vstrczbs vstrczhs + vstrczfs vfa vfadb wfadb wfc wfcdb wfk wfkdb vfce vfcedb wfcedb + vfcedbs wfcedbs vfch vfchdb wfchdb vfchdbs wfchdbs vfche vfchedb + wfchedb vfchedbs wfchedbs vcdg vcdgb wcdgb vcdlg vcdlgb wcdlgb vcgd + vcgdb wcgdb vclgd vclgdb wclgdb vfd vfddb wfddb vfi vfidb wfidb + vlde vldeb wldeb vled vledb wledb vfm vfmdb wfmdb vfma vfmadb + wfmadb vfms vfmsdb wfmsdb vfpso vfpsodb wfpsodb vflcdb wflcdb + vflndb wflndb vflpdb wflpdb vfsq vfsqdb wfsqdb vfs vfsdb wfsdb + vftci vftcidb wftcidb)], + VXE => [qw(vbperm vllezlf vmsl vmslg vnx vnn voc vpopctb vpopcth + vpopctf vpopctg vfasb wfasb wfaxb wfcsb wfcxb wfksb wfkxb vfcesb + vfcesbs wfcesb wfcesbs wfcexb wfcexbs vfchsb vfchsbs wfchsb wfchsbs + wfchxb wfchxbs vfchesb vfchesbs wfchesb wfchesbs wfchexb wfchexbs + vfdsb wfdsb wfdxb vfisb wfisb wfixb vfll vflls wflls wflld vflr + vflrd wflrd wflrx vfmax vfmaxsb vfmaxdb wfmaxsb wfmaxdb wfmaxxb + vfmin vfminsb vfmindb wfminsb wfmindb wfminxb vfmsb wfmsb wfmxb + vfnma vfnms vfmasb wfmasb wfmaxb vfmssb wfmssb wfmsxb vfnmasb + vfnmadb wfnmasb wfnmadb wfnmaxb vfnmssb vfnmsdb wfnmssb wfnmsdb + wfnmsxb vfpsosb wfpsosb vflcsb wflcsb vflnsb wflnsb vflpsb wflpsb + vfpsoxb wfpsoxb vflcxb wflcxb vflnxb wflnxb vflpxb wflpxb vfsqsb + wfsqsb wfsqxb vfssb wfssb wfsxb vftcisb wftcisb wftcixb)], + VXD => [qw(vlrlr vlrl vstrlr vstrl vap vcp vcvb vcvbg vcvd vcvdg vdp + vlip vmp vmsp vpkz vpsop vrp vsdp vsrp vsp vtp vupkz)], +); +Exporter::export_ok_tags(qw(MSA MSA4 MSA5 MSA8 VX VXE VXD)); + +our $AUTOLOAD; + +my $GR='(?:%r)?([0-9]|1[0-5])'; +my $VR='(?:%v)?([0-9]|1[0-9]|2[0-9]|3[0-1])'; + +my ($file,$out); + +sub PERLASM_BEGIN +{ + ($file,$out)=(shift,""); +} +sub PERLASM_END +{ + if (defined($file)) { + open(my $fd,'>',$file)||die("can't open $file: $!"); + print({$fd}$out); + close($fd); + } else { + print($out); + } +} + +sub AUTOLOAD { + confess(err("PARSE")) if (grep(!defined($_),@_)); + my $token; + for ($AUTOLOAD) { + $token=".$1" if (/^.*::([A-Z_]+)$/); # uppercase: directive + $token="\t$1" if (/^.*::([a-z]+)$/); # lowercase: mnemonic + confess(err("PARSE")) if (!defined($token)); + } + $token.="\t" if ($#_>=0); + $out.=$token.join(',',@_)."\n"; +} + +sub LABEL { # label directive + confess(err("ARGNUM")) if ($#_!=0); + my ($label)=@_; + $out.="$label:\n"; +} + +sub INCLUDE { + confess(err("ARGNUM")) if ($#_!=0); + my ($file)=@_; + $out.="#include \"$file\"\n"; +} + +# +# Mnemonics +# + +sub stfle { + confess(err("ARGNUM")) if ($#_!=0); + S(0xb2b0,@_); +} + +# MSA + +sub kmac { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb91e,@_); +} + +sub km { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb92e,@_); +} + +sub kmc { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb92f,@_); +} + +sub kimd { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb93e,@_); +} + +sub klmd { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb93f,@_); +} + +# MSA4 + +sub kmf { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb92a,@_); +} + +sub kmo { + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb92b,@_); +} + +sub pcc { + confess(err("ARGNUM")) if ($#_!=-1); + RRE(0xb92c,@_); +} + +sub kmctr { + confess(err("ARGNUM")) if ($#_!=2); + RRFb(0xb92d,@_); +} + +# MSA5 + +sub prno { + ppno(@_); +} + +sub ppno { # deprecated, use prno + confess(err("ARGNUM")) if ($#_!=1); + RRE(0xb93c,@_); +} + +# MSA8 + +sub kma { + confess(err("ARGNUM")) if ($#_!=2); + RRFb(0xb929,@_); +} + +# VX - Support Instructions + +sub vgef { + confess(err("ARGNUM")) if ($#_!=2); + VRV(0xe713,@_); +} +sub vgeg { + confess(err("ARGNUM")) if ($#_!=2); + VRV(0xe712,@_); +} + +sub vgbm { + confess(err("ARGNUM")) if ($#_!=1); + VRIa(0xe744,@_); +} +sub vzero { + vgbm(@_,0); +} +sub vone { + vgbm(@_,0xffff); +} + +sub vgm { + confess(err("ARGNUM")) if ($#_!=3); + VRIb(0xe746,@_); +} +sub vgmb { + vgm(@_,0); +} +sub vgmh { + vgm(@_,1); +} +sub vgmf { + vgm(@_,2); +} +sub vgmg { + vgm(@_,3); +} + +sub vl { + confess(err("ARGNUM")) if ($#_!=1); + VRX(0xe706,@_); +} + +sub vlr { + confess(err("ARGNUM")) if ($#_!=1); + VRRa(0xe756,@_); +} + +sub vlrep { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe705,@_); +} +sub vlrepb { + vlrep(@_,0); +} +sub vlreph { + vlrep(@_,1); +} +sub vlrepf { + vlrep(@_,2); +} +sub vlrepg { + vlrep(@_,3); +} + +sub vleb { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe700,@_); +} +sub vleh { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe701,@_); +} +sub vlef { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe703,@_); +} +sub vleg { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe702,@_); +} + +sub vleib { + confess(err("ARGNUM")) if ($#_!=2); + VRIa(0xe740,@_); +} +sub vleih { + confess(err("ARGNUM")) if ($#_!=2); + VRIa(0xe741,@_); +} +sub vleif { + confess(err("ARGNUM")) if ($#_!=2); + VRIa(0xe743,@_); +} +sub vleig { + confess(err("ARGNUM")) if ($#_!=2); + VRIa(0xe742,@_); +} + +sub vlgv { + confess(err("ARGNUM")) if ($#_!=3); + VRSc(0xe721,@_); +} +sub vlgvb { + vlgv(@_,0); +} +sub vlgvh { + vlgv(@_,1); +} +sub vlgvf { + vlgv(@_,2); +} +sub vlgvg { + vlgv(@_,3); +} + +sub vllez { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe704,@_); +} +sub vllezb { + vllez(@_,0); +} +sub vllezh { + vllez(@_,1); +} +sub vllezf { + vllez(@_,2); +} +sub vllezg { + vllez(@_,3); +} + +sub vlm { + confess(err("ARGNUM")) if ($#_!=2); + VRSa(0xe736,@_); +} + +sub vlbb { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe707,@_); +} + +sub vlvg { + confess(err("ARGNUM")) if ($#_!=3); + VRSb(0xe722,@_); +} +sub vlvgb { + vlvg(@_,0); +} +sub vlvgh { + vlvg(@_,1); +} +sub vlvgf { + vlvg(@_,2); +} +sub vlvgg { + vlvg(@_,3); +} + +sub vlvgp { + confess(err("ARGNUM")) if ($#_!=2); + VRRf(0xe762,@_); +} + +sub vll { + confess(err("ARGNUM")) if ($#_!=2); + VRSb(0xe737,@_); +} + +sub vmrh { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe761,@_); +} +sub vmrhb { + vmrh(@_,0); +} +sub vmrhh { + vmrh(@_,1); +} +sub vmrhf { + vmrh(@_,2); +} +sub vmrhg { + vmrh(@_,3); +} + +sub vmrl { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe760,@_); +} +sub vmrlb { + vmrl(@_,0); +} +sub vmrlh { + vmrl(@_,1); +} +sub vmrlf { + vmrl(@_,2); +} +sub vmrlg { + vmrl(@_,3); +} + +sub vpk { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe794,@_); +} +sub vpkh { + vpk(@_,1); +} +sub vpkf { + vpk(@_,2); +} +sub vpkg { + vpk(@_,3); +} + +sub vpks { + confess(err("ARGNUM")) if ($#_!=4); + VRRb(0xe797,@_); +} +sub vpksh { + vpks(@_,1,0); +} +sub vpksf { + vpks(@_,2,0); +} +sub vpksg { + vpks(@_,3,0); +} +sub vpkshs { + vpks(@_,1,1); +} +sub vpksfs { + vpks(@_,2,1); +} +sub vpksgs { + vpks(@_,3,1); +} + +sub vpkls { + confess(err("ARGNUM")) if ($#_!=4); + VRRb(0xe795,@_); +} +sub vpklsh { + vpkls(@_,1,0); +} +sub vpklsf { + vpkls(@_,2,0); +} +sub vpklsg { + vpkls(@_,3,0); +} +sub vpklshs { + vpkls(@_,1,1); +} +sub vpklsfs { + vpkls(@_,2,1); +} +sub vpklsgs { + vpkls(@_,3,1); +} + +sub vperm { + confess(err("ARGNUM")) if ($#_!=3); + VRRe(0xe78c,@_); +} + +sub vpdi { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe784,@_); +} + +sub vrep { + confess(err("ARGNUM")) if ($#_!=3); + VRIc(0xe74d,@_); +} +sub vrepb { + vrep(@_,0); +} +sub vreph { + vrep(@_,1); +} +sub vrepf { + vrep(@_,2); +} +sub vrepg { + vrep(@_,3); +} + +sub vrepi { + confess(err("ARGNUM")) if ($#_!=2); + VRIa(0xe745,@_); +} +sub vrepib { + vrepi(@_,0); +} +sub vrepih { + vrepi(@_,1); +} +sub vrepif { + vrepi(@_,2); +} +sub vrepig { + vrepi(@_,3); +} + +sub vscef { + confess(err("ARGNUM")) if ($#_!=2); + VRV(0xe71b,@_); +} +sub vsceg { + confess(err("ARGNUM")) if ($#_!=2); + VRV(0xe71a,@_); +} + +sub vsel { + confess(err("ARGNUM")) if ($#_!=3); + VRRe(0xe78d,@_); +} + +sub vseg { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe75f,@_); +} +sub vsegb { + vseg(@_,0); +} +sub vsegh { + vseg(@_,1); +} +sub vsegf { + vseg(@_,2); +} + +sub vst { + confess(err("ARGNUM")) if ($#_!=1); + VRX(0xe70e,@_); +} + +sub vsteb { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe708,@_); +} +sub vsteh { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe709,@_); +} +sub vstef { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe70b,@_); +} +sub vsteg { + confess(err("ARGNUM")) if ($#_!=2); + VRX(0xe70a,@_); +} + +sub vstm { + confess(err("ARGNUM")) if ($#_!=2); + VRSa(0xe73e,@_); +} + +sub vstl { + confess(err("ARGNUM")) if ($#_!=2); + VRSb(0xe73f,@_); +} + +sub vuph { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7d7,@_); +} +sub vuphb { + vuph(@_,0); +} +sub vuphh { + vuph(@_,1); +} +sub vuphf { + vuph(@_,2); +} + +sub vuplh { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7d5,@_); +} +sub vuplhb { + vuplh(@_,0); +} +sub vuplhh { + vuplh(@_,1); +} +sub vuplhf { + vuplh(@_,2); +} + +sub vupl { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7d6,@_); +} +sub vuplb { + vupl(@_,0); +} +sub vuplhw { + vupl(@_,1); +} +sub vuplf { + vupl(@_,2); +} + +sub vupll { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7d4,@_); +} +sub vupllb { + vupll(@_,0); +} +sub vupllh { + vupll(@_,1); +} +sub vupllf { + vupll(@_,2); +} + +# VX - Integer Instructions + +sub va { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7f3,@_); +} +sub vab { + va(@_,0); +} +sub vah { + va(@_,1); +} +sub vaf { + va(@_,2); +} +sub vag { + va(@_,3); +} +sub vaq { + va(@_,4); +} + +sub vacc { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7f1,@_); +} +sub vaccb { + vacc(@_,0); +} +sub vacch { + vacc(@_,1); +} +sub vaccf { + vacc(@_,2); +} +sub vaccg { + vacc(@_,3); +} +sub vaccq { + vacc(@_,4); +} + +sub vac { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7bb,@_); +} +sub vacq { + vac(@_,4); +} + +sub vaccc { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7b9,@_); +} +sub vacccq { + vaccc(@_,4); +} + +sub vn { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe768,@_); +} + +sub vnc { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe769,@_); +} + +sub vavg { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7f2,@_); +} +sub vavgb { + vavg(@_,0); +} +sub vavgh { + vavg(@_,1); +} +sub vavgf { + vavg(@_,2); +} +sub vavgg { + vavg(@_,3); +} + +sub vavgl { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7f0,@_); +} +sub vavglb { + vavgl(@_,0); +} +sub vavglh { + vavgl(@_,1); +} +sub vavglf { + vavgl(@_,2); +} +sub vavglg { + vavgl(@_,3); +} + +sub vcksm { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe766,@_); +} + +sub vec_ { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7db,@_); +} +sub vecb { + vec_(@_,0); +} +sub vech { + vec_(@_,1); +} +sub vecf { + vec_(@_,2); +} +sub vecg { + vec_(@_,3); +} + +sub vecl { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7d9,@_); +} +sub veclb { + vecl(@_,0); +} +sub veclh { + vecl(@_,1); +} +sub veclf { + vecl(@_,2); +} +sub veclg { + vecl(@_,3); +} + +sub vceq { + confess(err("ARGNUM")) if ($#_!=4); + VRRb(0xe7f8,@_); +} +sub vceqb { + vceq(@_,0,0); +} +sub vceqh { + vceq(@_,1,0); +} +sub vceqf { + vceq(@_,2,0); +} +sub vceqg { + vceq(@_,3,0); +} +sub vceqbs { + vceq(@_,0,1); +} +sub vceqhs { + vceq(@_,1,1); +} +sub vceqfs { + vceq(@_,2,1); +} +sub vceqgs { + vceq(@_,3,1); +} + +sub vch { + confess(err("ARGNUM")) if ($#_!=4); + VRRb(0xe7fb,@_); +} +sub vchb { + vch(@_,0,0); +} +sub vchh { + vch(@_,1,0); +} +sub vchf { + vch(@_,2,0); +} +sub vchg { + vch(@_,3,0); +} +sub vchbs { + vch(@_,0,1); +} +sub vchhs { + vch(@_,1,1); +} +sub vchfs { + vch(@_,2,1); +} +sub vchgs { + vch(@_,3,1); +} + +sub vchl { + confess(err("ARGNUM")) if ($#_!=4); + VRRb(0xe7f9,@_); +} +sub vchlb { + vchl(@_,0,0); +} +sub vchlh { + vchl(@_,1,0); +} +sub vchlf { + vchl(@_,2,0); +} +sub vchlg { + vchl(@_,3,0); +} +sub vchlbs { + vchl(@_,0,1); +} +sub vchlhs { + vchl(@_,1,1); +} +sub vchlfs { + vchl(@_,2,1); +} +sub vchlgs { + vchl(@_,3,1); +} + +sub vclz { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe753,@_); +} +sub vclzb { + vclz(@_,0); +} +sub vclzh { + vclz(@_,1); +} +sub vclzf { + vclz(@_,2); +} +sub vclzg { + vclz(@_,3); +} + +sub vctz { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe752,@_); +} +sub vctzb { + vctz(@_,0); +} +sub vctzh { + vctz(@_,1); +} +sub vctzf { + vctz(@_,2); +} +sub vctzg { + vctz(@_,3); +} + +sub vx { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe76d,@_); +} + +sub vgfm { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7b4,@_); +} +sub vgfmb { + vgfm(@_,0); +} +sub vgfmh { + vgfm(@_,1); +} +sub vgfmf { + vgfm(@_,2); +} +sub vgfmg { + vgfm(@_,3); +} + +sub vgfma { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7bc,@_); +} +sub vgfmab { + vgfma(@_,0); +} +sub vgfmah { + vgfma(@_,1); +} +sub vgfmaf { + vgfma(@_,2); +} +sub vgfmag { + vgfma(@_,3); +} + +sub vlc { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7de,@_); +} +sub vlcb { + vlc(@_,0); +} +sub vlch { + vlc(@_,1); +} +sub vlcf { + vlc(@_,2); +} +sub vlcg { + vlc(@_,3); +} + +sub vlp { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe7df,@_); +} +sub vlpb { + vlp(@_,0); +} +sub vlph { + vlp(@_,1); +} +sub vlpf { + vlp(@_,2); +} +sub vlpg { + vlp(@_,3); +} + +sub vmx { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7ff,@_); +} +sub vmxb { + vmx(@_,0); +} +sub vmxh { + vmx(@_,1); +} +sub vmxf { + vmx(@_,2); +} +sub vmxg { + vmx(@_,3); +} + +sub vmxl { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7fd,@_); +} +sub vmxlb { + vmxl(@_,0); +} +sub vmxlh { + vmxl(@_,1); +} +sub vmxlf { + vmxl(@_,2); +} +sub vmxlg { + vmxl(@_,3); +} + +sub vmn { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7fe,@_); +} +sub vmnb { + vmn(@_,0); +} +sub vmnh { + vmn(@_,1); +} +sub vmnf { + vmn(@_,2); +} +sub vmng { + vmn(@_,3); +} + +sub vmnl { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7fc,@_); +} +sub vmnlb { + vmnl(@_,0); +} +sub vmnlh { + vmnl(@_,1); +} +sub vmnlf { + vmnl(@_,2); +} +sub vmnlg { + vmnl(@_,3); +} + +sub vmal { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7aa,@_); +} +sub vmalb { + vmal(@_,0); +} +sub vmalhw { + vmal(@_,1); +} +sub vmalf { + vmal(@_,2); +} + +sub vmah { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7ab,@_); +} +sub vmahb { + vmah(@_,0); +} +sub vmahh { + vmah(@_,1); +} +sub vmahf { + vmah(@_,2); +} + +sub vmalh { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7a9,@_); +} +sub vmalhb { + vmalh(@_,0); +} +sub vmalhh { + vmalh(@_,1); +} +sub vmalhf { + vmalh(@_,2); +} + +sub vmae { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7ae,@_); +} +sub vmaeb { + vmae(@_,0); +} +sub vmaeh { + vmae(@_,1); +} +sub vmaef { + vmae(@_,2); +} + +sub vmale { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7ac,@_); +} +sub vmaleb { + vmale(@_,0); +} +sub vmaleh { + vmale(@_,1); +} +sub vmalef { + vmale(@_,2); +} + +sub vmao { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7af,@_); +} +sub vmaob { + vmao(@_,0); +} +sub vmaoh { + vmao(@_,1); +} +sub vmaof { + vmao(@_,2); +} + +sub vmalo { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7ad,@_); +} +sub vmalob { + vmalo(@_,0); +} +sub vmaloh { + vmalo(@_,1); +} +sub vmalof { + vmalo(@_,2); +} + +sub vmh { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a3,@_); +} +sub vmhb { + vmh(@_,0); +} +sub vmhh { + vmh(@_,1); +} +sub vmhf { + vmh(@_,2); +} + +sub vmlh { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a1,@_); +} +sub vmlhb { + vmlh(@_,0); +} +sub vmlhh { + vmlh(@_,1); +} +sub vmlhf { + vmlh(@_,2); +} + +sub vml { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a2,@_); +} +sub vmlb { + vml(@_,0); +} +sub vmlhw { + vml(@_,1); +} +sub vmlf { + vml(@_,2); +} + +sub vme { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a6,@_); +} +sub vmeb { + vme(@_,0); +} +sub vmeh { + vme(@_,1); +} +sub vmef { + vme(@_,2); +} + +sub vmle { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a4,@_); +} +sub vmleb { + vmle(@_,0); +} +sub vmleh { + vmle(@_,1); +} +sub vmlef { + vmle(@_,2); +} + +sub vmo { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a7,@_); +} +sub vmob { + vmo(@_,0); +} +sub vmoh { + vmo(@_,1); +} +sub vmof { + vmo(@_,2); +} + +sub vmlo { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7a5,@_); +} +sub vmlob { + vmlo(@_,0); +} +sub vmloh { + vmlo(@_,1); +} +sub vmlof { + vmlo(@_,2); +} + +sub vno { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe76b,@_); +} +sub vnot { + vno(@_,$_[1]); +} + +sub vo { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe76a,@_); +} + +sub vpopct { + confess(err("ARGNUM")) if ($#_!=2); + VRRa(0xe750,@_); +} + +sub verllv { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe773,@_); +} +sub verllvb { + verllv(@_,0); +} +sub verllvh { + verllv(@_,1); +} +sub verllvf { + verllv(@_,2); +} +sub verllvg { + verllv(@_,3); +} + +sub verll { + confess(err("ARGNUM")) if ($#_!=3); + VRSa(0xe733,@_); +} +sub verllb { + verll(@_,0); +} +sub verllh { + verll(@_,1); +} +sub verllf { + verll(@_,2); +} +sub verllg { + verll(@_,3); +} + +sub verim { + confess(err("ARGNUM")) if ($#_!=4); + VRId(0xe772,@_); +} +sub verimb { + verim(@_,0); +} +sub verimh { + verim(@_,1); +} +sub verimf { + verim(@_,2); +} +sub verimg { + verim(@_,3); +} + +sub veslv { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe770,@_); +} +sub veslvb { + veslv(@_,0); +} +sub veslvh { + veslv(@_,1); +} +sub veslvf { + veslv(@_,2); +} +sub veslvg { + veslv(@_,3); +} + +sub vesl { + confess(err("ARGNUM")) if ($#_!=3); + VRSa(0xe730,@_); +} +sub veslb { + vesl(@_,0); +} +sub veslh { + vesl(@_,1); +} +sub veslf { + vesl(@_,2); +} +sub veslg { + vesl(@_,3); +} + +sub vesrav { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe77a,@_); +} +sub vesravb { + vesrav(@_,0); +} +sub vesravh { + vesrav(@_,1); +} +sub vesravf { + vesrav(@_,2); +} +sub vesravg { + vesrav(@_,3); +} + +sub vesra { + confess(err("ARGNUM")) if ($#_!=3); + VRSa(0xe73a,@_); +} +sub vesrab { + vesra(@_,0); +} +sub vesrah { + vesra(@_,1); +} +sub vesraf { + vesra(@_,2); +} +sub vesrag { + vesra(@_,3); +} + +sub vesrlv { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe778,@_); +} +sub vesrlvb { + vesrlv(@_,0); +} +sub vesrlvh { + vesrlv(@_,1); +} +sub vesrlvf { + vesrlv(@_,2); +} +sub vesrlvg { + vesrlv(@_,3); +} + +sub vesrl { + confess(err("ARGNUM")) if ($#_!=3); + VRSa(0xe738,@_); +} +sub vesrlb { + vesrl(@_,0); +} +sub vesrlh { + vesrl(@_,1); +} +sub vesrlf { + vesrl(@_,2); +} +sub vesrlg { + vesrl(@_,3); +} + +sub vsl { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe774,@_); +} + +sub vslb { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe775,@_); +} + +sub vsldb { + confess(err("ARGNUM")) if ($#_!=3); + VRId(0xe777,@_); +} + +sub vsra { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe77e,@_); +} + +sub vsrab { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe77f,@_); +} + +sub vsrl { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe77c,@_); +} + +sub vsrlb { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe77d,@_); +} + +sub vs { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7f7,@_); +} +sub vsb { + vs(@_,0); +} +sub vsh { + vs(@_,1); +} +sub vsf { + vs(@_,2); +} +sub vsg { + vs(@_,3); +} +sub vsq { + vs(@_,4); +} + +sub vscbi { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe7f5,@_); +} +sub vscbib { + vscbi(@_,0); +} +sub vscbih { + vscbi(@_,1); +} +sub vscbif { + vscbi(@_,2); +} +sub vscbig { + vscbi(@_,3); +} +sub vscbiq { + vscbi(@_,4); +} + +sub vsbi { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7bf,@_); +} +sub vsbiq { + vsbi(@_,4); +} + +sub vsbcbi { + confess(err("ARGNUM")) if ($#_!=4); + VRRd(0xe7bd,@_); +} +sub vsbcbiq { + vsbcbi(@_,4); +} + +sub vsumg { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe765,@_); +} +sub vsumgh { + vsumg(@_,1); +} +sub vsumgf { + vsumg(@_,2); +} + +sub vsumq { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe767,@_); +} +sub vsumqf { + vsumq(@_,2); +} +sub vsumqg { + vsumq(@_,3); +} + +sub vsum { + confess(err("ARGNUM")) if ($#_!=3); + VRRc(0xe764,@_); +} +sub vsumb { + vsum(@_,0); +} +sub vsumh { + vsum(@_,1); +} + +sub vtm { + confess(err("ARGNUM")) if ($#_!=1); + VRRa(0xe7d8,@_); +} + +# VX - String Instructions + +sub vfae { + confess(err("ARGNUM")) if ($#_<3||$#_>4); + VRRb(0xe782,@_); +} +sub vfaeb { + vfae(@_[0..2],0,$_[3]); +} +sub vfaeh { + vfae(@_[0..2],1,$_[3]); +} +sub vfaef { + vfae(@_[0..2],2,$_[3]); +} +sub vfaebs { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],0,0x1|$_[3]); +} +sub vfaehs { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],1,0x1|$_[3]); +} +sub vfaefs { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],2,0x1|$_[3]); +} +sub vfaezb { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],0,0x2|$_[3]); +} +sub vfaezh { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],1,0x2|$_[3]); +} +sub vfaezf { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],2,0x2|$_[3]); +} +sub vfaezbs { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],0,0x3|$_[3]); +} +sub vfaezhs { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],1,0x3|$_[3]); +} +sub vfaezfs { + $_[3]=0 if (!defined($_[3])); + vfae(@_[0..2],2,0x3|$_[3]); +} + +sub vfee { + confess(err("ARGNUM")) if ($#_<3||$#_>4); + VRRb(0xe780,@_); +} +sub vfeeb { + vfee(@_[0..2],0,$_[3]); +} +sub vfeeh { + vfee(@_[0..2],1,$_[3]); +} +sub vfeef { + vfee(@_[0..2],2,$_[3]); +} +sub vfeebs { + vfee(@_,0,1); +} +sub vfeehs { + vfee(@_,1,1); +} +sub vfeefs { + vfee(@_,2,1); +} +sub vfeezb { + vfee(@_,0,2); +} +sub vfeezh { + vfee(@_,1,2); +} +sub vfeezf { + vfee(@_,2,2); +} +sub vfeezbs { + vfee(@_,0,3); +} +sub vfeezhs { + vfee(@_,1,3); +} +sub vfeezfs { + vfee(@_,2,3); +} + +sub vfene { + confess(err("ARGNUM")) if ($#_<3||$#_>4); + VRRb(0xe781,@_); +} +sub vfeneb { + vfene(@_[0..2],0,$_[3]); +} +sub vfeneh { + vfene(@_[0..2],1,$_[3]); +} +sub vfenef { + vfene(@_[0..2],2,$_[3]); +} +sub vfenebs { + vfene(@_,0,1); +} +sub vfenehs { + vfene(@_,1,1); +} +sub vfenefs { + vfene(@_,2,1); +} +sub vfenezb { + vfene(@_,0,2); +} +sub vfenezh { + vfene(@_,1,2); +} +sub vfenezf { + vfene(@_,2,2); +} +sub vfenezbs { + vfene(@_,0,3); +} +sub vfenezhs { + vfene(@_,1,3); +} +sub vfenezfs { + vfene(@_,2,3); +} + +sub vistr { + confess(err("ARGNUM")) if ($#_<2||$#_>3); + VRRa(0xe75c,@_[0..2],0,$_[3]); +} +sub vistrb { + vistr(@_[0..1],0,$_[2]); +} +sub vistrh { + vistr(@_[0..1],1,$_[2]); +} +sub vistrf { + vistr(@_[0..1],2,$_[2]); +} +sub vistrbs { + vistr(@_,0,1); +} +sub vistrhs { + vistr(@_,1,1); +} +sub vistrfs { + vistr(@_,2,1); +} + +sub vstrc { + confess(err("ARGNUM")) if ($#_<4||$#_>5); + VRRd(0xe78a,@_); +} +sub vstrcb { + vstrc(@_[0..3],0,$_[4]); +} +sub vstrch { + vstrc(@_[0..3],1,$_[4]); +} +sub vstrcf { + vstrc(@_[0..3],2,$_[4]); +} +sub vstrcbs { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],0,0x1|$_[4]); +} +sub vstrchs { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],1,0x1|$_[4]); +} +sub vstrcfs { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],2,0x1|$_[4]); +} +sub vstrczb { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],0,0x2|$_[4]); +} +sub vstrczh { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],1,0x2|$_[4]); +} +sub vstrczf { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],2,0x2|$_[4]); +} +sub vstrczbs { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],0,0x3|$_[4]); +} +sub vstrczhs { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],1,0x3|$_[4]); +} +sub vstrczfs { + $_[4]=0 if (!defined($_[4])); + vstrc(@_[0..3],2,0x3|$_[4]); +} + +# VX - Floating-point Instructions + +sub vfa { + confess(err("ARGNUM")) if ($#_!=4); + VRRc(0xe7e3,@_); +} +sub vfadb { + vfa(@_,3,0); +} +sub wfadb { + vfa(@_,3,8); +} + +sub wfc { + confess(err("ARGNUM")) if ($#_!=3); + VRRa(0xe7cb,@_); +} +sub wfcdb { + wfc(@_,3,0); +} + +sub wfk { + confess(err("ARGNUM")) if ($#_!=3); + VRRa(0xe7ca,@_); +} +sub wfksb { + wfk(@_,2,0); +} +sub wfkdb { + wfk(@_,3,0); +} +sub wfkxb { + wfk(@_,4,0); +} + +sub vfce { + confess(err("ARGNUM")) if ($#_!=5); + VRRc(0xe7e8,@_); +} +sub vfcedb { + vfce(@_,3,0,0); +} +sub vfcedbs { + vfce(@_,3,0,1); +} +sub wfcedb { + vfce(@_,3,8,0); +} +sub wfcedbs { + vfce(@_,3,8,1); +} + +sub vfch { + confess(err("ARGNUM")) if ($#_!=5); + VRRc(0xe7eb,@_); +} +sub vfchdb { + vfch(@_,3,0,0); +} +sub vfchdbs { + vfch(@_,3,0,1); +} +sub wfchdb { + vfch(@_,3,8,0); +} +sub wfchdbs { + vfch(@_,3,8,1); +} + +sub vfche { + confess(err("ARGNUM")) if ($#_!=5); + VRRc(0xe7ea,@_); +} +sub vfchedb { + vfche(@_,3,0,0); +} +sub vfchedbs { + vfche(@_,3,0,1); +} +sub wfchedb { + vfche(@_,3,8,0); +} +sub wfchedbs { + vfche(@_,3,8,1); +} + +sub vcdg { + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7c3,@_); +} +sub vcdgb { + vcdg(@_[0..1],3,@_[2..3]); +} +sub wcdgb { + vcdg(@_[0..1],3,0x8|$_[2],$_[3]); +} + +sub vcdlg { + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7c1,@_); +} +sub vcdlgb { + vcdlg(@_[0..1],3,@_[2..3]); +} +sub wcdlgb { + vcdlg(@_[0..1],3,0x8|$_[2],$_[3]); +} + +sub vcgd { + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7c2,@_); +} +sub vcgdb { + vcgd(@_[0..1],3,@_[2..3]); +} +sub wcgdb { + vcgd(@_[0..1],3,0x8|$_[2],$_[3]); +} + +sub vclgd { + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7c0,@_); +} +sub vclgdb { + vclgd(@_[0..1],3,@_[2..3]); +} +sub wclgdb { + vclgd(@_[0..1],3,0x8|$_[2],$_[3]); +} + +sub vfd { + confess(err("ARGNUM")) if ($#_!=4); + VRRc(0xe7e5,@_); +} +sub vfddb { + vfd(@_,3,0); +} +sub wfddb { + vfd(@_,3,8); +} + +sub vfi { + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7c7,@_); +} +sub vfidb { + vfi(@_[0..1],3,@_[2..3]); +} +sub wfidb { + vfi(@_[0..1],3,0x8|$_[2],$_[3]); +} + +sub vlde { # deprecated, use vfll + confess(err("ARGNUM")) if ($#_!=3); + VRRa(0xe7c4,@_); +} +sub vldeb { # deprecated, use vflls + vlde(@_,2,0); +} +sub wldeb { # deprecated, use wflls + vlde(@_,2,8); +} + +sub vled { # deprecated, use vflr + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7c5,@_); +} +sub vledb { # deprecated, use vflrd + vled(@_[0..1],3,@_[2..3]); +} +sub wledb { # deprecated, use wflrd + vled(@_[0..1],3,0x8|$_[2],$_[3]); +} + +sub vfm { + confess(err("ARGNUM")) if ($#_!=4); + VRRc(0xe7e7,@_); +} +sub vfmdb { + vfm(@_,3,0); +} +sub wfmdb { + vfm(@_,3,8); +} + +sub vfma { + confess(err("ARGNUM")) if ($#_!=5); + VRRe(0xe78f,@_); +} +sub vfmadb { + vfma(@_,0,3); +} +sub wfmadb { + vfma(@_,8,3); +} + +sub vfms { + confess(err("ARGNUM")) if ($#_!=5); + VRRe(0xe78e,@_); +} +sub vfmsdb { + vfms(@_,0,3); +} +sub wfmsdb { + vfms(@_,8,3); +} + +sub vfpso { + confess(err("ARGNUM")) if ($#_!=4); + VRRa(0xe7cc,@_); +} +sub vfpsodb { + vfpso(@_[0..1],3,0,$_[2]); +} +sub wfpsodb { + vfpso(@_[0..1],3,8,$_[2]); +} +sub vflcdb { + vfpso(@_,3,0,0); +} +sub wflcdb { + vfpso(@_,3,8,0); +} +sub vflndb { + vfpso(@_,3,0,1); +} +sub wflndb { + vfpso(@_,3,8,1); +} +sub vflpdb { + vfpso(@_,3,0,2); +} +sub wflpdb { + vfpso(@_,3,8,2); +} + +sub vfsq { + confess(err("ARGNUM")) if ($#_!=3); + VRRa(0xe7ce,@_); +} +sub vfsqdb { + vfsq(@_,3,0); +} +sub wfsqdb { + vfsq(@_,3,8); +} + +sub vfs { + confess(err("ARGNUM")) if ($#_!=4); + VRRc(0xe7e2,@_); +} +sub vfsdb { + vfs(@_,3,0); +} +sub wfsdb { + vfs(@_,3,8); +} + +sub vftci { + confess(err("ARGNUM")) if ($#_!=4); + VRIe(0xe74a,@_); +} +sub vftcidb { + vftci(@_,3,0); +} +sub wftcidb { + vftci(@_,3,8); +} + +# VXE - Support Instructions + +sub vbperm { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe785,@_); +} + +sub vllezlf { + vllez(@_,6); +} + +# VXE - Integer Instructions + +sub vmsl { + confess(err("ARGNUM")) if ($#_!=5); + VRRd(0xe7b8,@_); +} +sub vmslg { + vmsl(@_[0..3],3,$_[4]); +} + +sub vnx { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe76c,@_); +} + +sub vnn { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe76e,@_); +} + +sub voc { + confess(err("ARGNUM")) if ($#_!=2); + VRRc(0xe76f,@_); +} + +sub vpopctb { + vpopct(@_,0); +} +sub vpopcth { + vpopct(@_,1); +} +sub vpopctf { + vpopct(@_,2); +} +sub vpopctg { + vpopct(@_,3); +} + +# VXE - Floating-Point Instructions + +sub vfasb { + vfa(@_,2,0); +} +sub wfasb { + vfa(@_,2,8); +} +sub wfaxb { + vfa(@_,4,8); +} + +sub wfcsb { + wfc(@_,2,0); +} +sub wfcxb { + wfc(@_,4,0); +} + +sub vfcesb { + vfce(@_,2,0,0); +} +sub vfcesbs { + vfce(@_,2,0,1); +} +sub wfcesb { + vfce(@_,2,8,0); +} +sub wfcesbs { + vfce(@_,2,8,1); +} +sub wfcexb { + vfce(@_,4,8,0); +} +sub wfcexbs { + vfce(@_,4,8,1); +} + +sub vfchsb { + vfch(@_,2,0,0); +} +sub vfchsbs { + vfch(@_,2,0,1); +} +sub wfchsb { + vfch(@_,2,8,0); +} +sub wfchsbs { + vfch(@_,2,8,1); +} +sub wfchxb { + vfch(@_,4,8,0); +} +sub wfchxbs { + vfch(@_,4,8,1); +} + +sub vfchesb { + vfche(@_,2,0,0); +} +sub vfchesbs { + vfche(@_,2,0,1); +} +sub wfchesb { + vfche(@_,2,8,0); +} +sub wfchesbs { + vfche(@_,2,8,1); +} +sub wfchexb { + vfche(@_,4,8,0); +} +sub wfchexbs { + vfche(@_,4,8,1); +} + +sub vfdsb { + vfd(@_,2,0); +} +sub wfdsb { + vfd(@_,2,8); +} +sub wfdxb { + vfd(@_,4,8); +} + +sub vfisb { + vfi(@_[0..1],2,@_[2..3]); +} +sub wfisb { + vfi(@_[0..1],2,0x8|$_[2],$_[3]); +} +sub wfixb { + vfi(@_[0..1],4,0x8|$_[2],$_[3]); +} + +sub vfll { + vlde(@_); +} +sub vflls { + vfll(@_,2,0); +} +sub wflls { + vfll(@_,2,8); +} +sub wflld { + vfll(@_,3,8); +} + +sub vflr { + vled(@_); +} +sub vflrd { + vflr(@_[0..1],3,@_[2..3]); +} +sub wflrd { + vflr(@_[0..1],3,0x8|$_[2],$_[3]); +} +sub wflrx { + vflr(@_[0..1],4,0x8|$_[2],$_[3]); +} + +sub vfmax { + confess(err("ARGNUM")) if ($#_!=5); + VRRc(0xe7ef,@_); +} +sub vfmaxsb { + vfmax(@_[0..2],2,0,$_[3]); +} +sub vfmaxdb { + vfmax(@_[0..2],3,0,$_[3]); +} +sub wfmaxsb { + vfmax(@_[0..2],2,8,$_[3]); +} +sub wfmaxdb { + vfmax(@_[0..2],3,8,$_[3]); +} +sub wfmaxxb { + vfmax(@_[0..2],4,8,$_[3]); +} + +sub vfmin { + confess(err("ARGNUM")) if ($#_!=5); + VRRc(0xe7ee,@_); +} +sub vfminsb { + vfmin(@_[0..2],2,0,$_[5]); +} +sub vfmindb { + vfmin(@_[0..2],3,0,$_[5]); +} +sub wfminsb { + vfmin(@_[0..2],2,8,$_[5]); +} +sub wfmindb { + vfmin(@_[0..2],3,8,$_[5]); +} +sub wfminxb { + vfmin(@_[0..2],4,8,$_[5]); +} + +sub vfmsb { + vfm(@_,2,0); +} +sub wfmsb { + vfm(@_,2,8); +} +sub wfmxb { + vfm(@_,4,8); +} + +sub vfmasb { + vfma(@_,0,2); +} +sub wfmasb { + vfma(@_,8,2); +} +sub wfmaxb { + vfma(@_,8,4); +} + +sub vfmssb { + vfms(@_,0,2); +} +sub wfmssb { + vfms(@_,8,2); +} +sub wfmsxb { + vfms(@_,8,4); +} + +sub vfnma { + confess(err("ARGNUM")) if ($#_!=5); + VRRe(0xe79f,@_); +} +sub vfnmasb { + vfnma(@_,0,2); +} +sub vfnmadb { + vfnma(@_,0,3); +} +sub wfnmasb { + vfnma(@_,8,2); +} +sub wfnmadb { + vfnma(@_,8,3); +} +sub wfnmaxb { + vfnma(@_,8,4); +} + +sub vfnms { + confess(err("ARGNUM")) if ($#_!=5); + VRRe(0xe79e,@_); +} +sub vfnmssb { + vfnms(@_,0,2); +} +sub vfnmsdb { + vfnms(@_,0,3); +} +sub wfnmssb { + vfnms(@_,8,2); +} +sub wfnmsdb { + vfnms(@_,8,3); +} +sub wfnmsxb { + vfnms(@_,8,4); +} + +sub vfpsosb { + vfpso(@_[0..1],2,0,$_[2]); +} +sub wfpsosb { + vfpso(@_[0..1],2,8,$_[2]); +} +sub vflcsb { + vfpso(@_,2,0,0); +} +sub wflcsb { + vfpso(@_,2,8,0); +} +sub vflnsb { + vfpso(@_,2,0,1); +} +sub wflnsb { + vfpso(@_,2,8,1); +} +sub vflpsb { + vfpso(@_,2,0,2); +} +sub wflpsb { + vfpso(@_,2,8,2); +} +sub vfpsoxb { + vfpso(@_[0..1],4,0,$_[2]); +} +sub wfpsoxb { + vfpso(@_[0..1],4,8,$_[2]); +} +sub vflcxb { + vfpso(@_,4,0,0); +} +sub wflcxb { + vfpso(@_,4,8,0); +} +sub vflnxb { + vfpso(@_,4,0,1); +} +sub wflnxb { + vfpso(@_,4,8,1); +} +sub vflpxb { + vfpso(@_,4,0,2); +} +sub wflpxb { + vfpso(@_,4,8,2); +} + +sub vfsqsb { + vfsq(@_,2,0); +} +sub wfsqsb { + vfsq(@_,2,8); +} +sub wfsqxb { + vfsq(@_,4,8); +} + +sub vfssb { + vfs(@_,2,0); +} +sub wfssb { + vfs(@_,2,8); +} +sub wfsxb { + vfs(@_,4,8); +} + +sub vftcisb { + vftci(@_,2,0); +} +sub wftcisb { + vftci(@_,2,8); +} +sub wftcixb { + vftci(@_,4,8); +} + +# VXD - Support Instructions + +sub vlrlr { + confess(err("ARGNUM")) if ($#_!=2); + VRSd(0xe637,@_); +} + +sub vlrl { + confess(err("ARGNUM")) if ($#_!=2); + VSI(0xe635,@_); +} + +sub vstrlr { + confess(err("ARGNUM")) if ($#_!=2); + VRSd(0xe63f,@_); +} + +sub vstrl { + confess(err("ARGNUM")) if ($#_!=2); + VSI(0xe63d,@_); +} + +sub vap { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe671,@_); +} + +sub vcp { + confess(err("ARGNUM")) if ($#_!=2); + VRRh(0xe677,@_); +} + +sub vcvb { + confess(err("ARGNUM")) if ($#_!=2); + VRRi(0xe650,@_); +} + +sub vcvbg { + confess(err("ARGNUM")) if ($#_!=2); + VRRi(0xe652,@_); +} + +sub vcvd { + confess(err("ARGNUM")) if ($#_!=3); + VRIi(0xe658,@_); +} + +sub vcvdg { + confess(err("ARGNUM")) if ($#_!=3); + VRIi(0xe65a,@_); +} + +sub vdp { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe67a,@_); +} + +sub vlip { + confess(err("ARGNUM")) if ($#_!=2); + VRIh(0xe649,@_); +} + +sub vmp { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe678,@_); +} + +sub vmsp { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe679,@_); +} + +sub vpkz { + confess(err("ARGNUM")) if ($#_!=2); + VSI(0xe634,@_); +} + +sub vpsop { + confess(err("ARGNUM")) if ($#_!=4); + VRIg(0xe65b,@_); +} + +sub vrp { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe67b,@_); +} + +sub vsdp { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe67e,@_); +} + +sub vsrp { + confess(err("ARGNUM")) if ($#_!=4); + VRIg(0xe659,@_); +} + +sub vsp { + confess(err("ARGNUM")) if ($#_!=4); + VRIf(0xe673,@_); +} + +sub vtp { + confess(err("ARGNUM")) if ($#_!=0); + VRRg(0xe65f,@_); +} + +sub vupkz { + confess(err("ARGNUM")) if ($#_!=2); + VSI(0xe63c,@_); +} + +# +# Instruction Formats +# + +sub RRE { + confess(err("ARGNUM")) if ($#_<0||2<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$r1,$r2)=(shift,get_R(shift),get_R(shift)); + + $out.="\t.long\t".sprintf("%#010x",($opcode<<16|$r1<<4|$r2)); + $out.="\t# $memn\t$ops\n" +} + +sub RRFb { + confess(err("ARGNUM")) if ($#_<3||4<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$r1,$r3,$r2,$m4)=(shift,get_R(shift),get_R(shift) + ,get_R(shift),get_M(shift)); + + $out.="\t.long\t" + .sprintf("%#010x",($opcode<<16|$r3<<12|$m4<<8|$r1<<4|$r2)); + $out.="\t# $memn\t$ops\n" +} + +sub S { + confess(err("ARGNUM")) if ($#_<0||1<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$d2,$b2)=(shift,get_DB(shift)); + + $out.="\t.long\t".sprintf("%#010x",($opcode<<16|$b2<<12|$d2)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIa { + confess(err("ARGNUM")) if ($#_<2||3<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$i2,$m3)=(shift,get_V(shift),get_I(shift,16), + get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)).","; + $out.=sprintf("%#06x",$i2).","; + $out.=sprintf("%#06x",($m3<<12|RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIb { + confess(err("ARGNUM")) if ($#_!=4); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$i2,$i3,$m4)=(shift,get_V(shift),get_I(shift,8), + ,get_I(shift,8),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)).","; + $out.=sprintf("%#06x",($i2<<8|$i3)).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIc { + confess(err("ARGNUM")) if ($#_!=4); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v3,$i2,$m4)=(shift,get_V(shift),get_V(shift), + ,get_I(shift,16),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v3&0xf)).","; + $out.=sprintf("%#06x",$i2).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRId { + confess(err("ARGNUM")) if ($#_<4||$#_>5); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$v3,$i4,$m5)=(shift,get_V(shift),get_V(shift), + ,get_V(shift),get_I(shift,8),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).","; + $out.=sprintf("%#06x",(($v3&0xf)<<12|$i4)).","; + $out.=sprintf("%#06x",($m5<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIe { + confess(err("ARGNUM")) if ($#_!=5); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$i3,$m4,$m5)=(shift,get_V(shift),get_V(shift), + ,get_I(shift,12),get_M(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).","; + $out.=sprintf("%#06x",($i3<<4|$m5)).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v2)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIf { + confess(err("ARGNUM")) if ($#_!=5); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$v3,$i4,$m5)=(shift,get_V(shift),get_V(shift), + ,get_V(shift),get_I(shift,8),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).","; + $out.=sprintf("%#06x",(($v3&0xf)<<12|$m5<<4)|$i4>>4).","; + $out.=sprintf("%#06x",(($i4&0xf)<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIg { + confess(err("ARGNUM")) if ($#_!=5); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$i3,$i4,$m5)=(shift,get_V(shift),get_V(shift), + ,get_I(shift,8),get_I(shift,8),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|($v2&0xf)).","; + $out.=sprintf("%#06x",($i4<<8|$m5<<4|$i3>>4)).","; + $out.=sprintf("%#06x",(($i3&0xf)<<12|RXB($v1,$v2)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIh { + confess(err("ARGNUM")) if ($#_!=3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$i2,$i3)=(shift,get_V(shift),get_I(shift,16), + get_I(shift,4)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)).","; + $out.=sprintf("%#06x",$i2).","; + $out.=sprintf("%#06x",($i3<<12|RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRIi { + confess(err("ARGNUM")) if ($#_!=4); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$r2,$i3,$m4)=(shift,get_V(shift),get_R(shift), + ,get_I(shift,8),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4)|$r2).","; + $out.=sprintf("%#06x",($m4<<4|$i3>>4)).","; + $out.=sprintf("%#06x",(($i3&0xf)<<12|RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRa { + confess(err("ARGNUM")) if ($#_<2||5<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$m3,$m4,$m5)=(shift,get_V(shift),get_V(shift), + get_M(shift),get_M(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",($m5<<4|$m4)).","; + $out.=sprintf("%#06x",($m3<<12|RXB($v1,$v2)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRb { + confess(err("ARGNUM")) if ($#_<3||5<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$v3,$m4,$m5)=(shift,get_V(shift),get_V(shift), + get_V(shift),get_M(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",(($v3&0xf)<<12|$m5<<4)).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRc { + confess(err("ARGNUM")) if ($#_<3||6<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$v3,$m4,$m5,$m6)=(shift,get_V(shift),get_V(shift), + get_V(shift),get_M(shift),get_M(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",(($v3&0xf)<<12|$m6<<4|$m5)).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v2,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRd { + confess(err("ARGNUM")) if ($#_<4||6<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$v3,$v4,$m5,$m6)=(shift,get_V(shift),get_V(shift), + get_V(shift),get_V(shift),get_M(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",(($v3&0xf)<<12|$m5<<8|$m6<<4)).","; + $out.=sprintf("%#06x",(($v4&0xf)<<12|RXB($v1,$v2,$v3,$v4)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRe { + confess(err("ARGNUM")) if ($#_<4||6<$#_); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$v3,$v4,$m5,$m6)=(shift,get_V(shift),get_V(shift), + get_V(shift),get_V(shift),get_M(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",(($v3&0xf)<<12|$m6<<8|$m5)).","; + $out.=sprintf("%#06x",(($v4&0xf)<<12|RXB($v1,$v2,$v3,$v4)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRf { + confess(err("ARGNUM")) if ($#_!=3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$r2,$r3)=(shift,get_V(shift),get_R(shift), + get_R(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|$r2)).","; + $out.=sprintf("%#06x",($r3<<12)).","; + $out.=sprintf("%#06x",(RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRg { + confess(err("ARGNUM")) if ($#_!=1); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1)=(shift,get_V(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf))).","; + $out.=sprintf("%#06x",0x0000).","; + $out.=sprintf("%#06x",(RXB(0,$v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRh { + confess(err("ARGNUM")) if ($#_<2||$#_>3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v2,$m3)=(shift,get_V(shift),get_V(shift), + get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf))).","; + $out.=sprintf("%#06x",(($v2&0xf)<<12|$m3<<4)).","; + $out.=sprintf("%#06x",(RXB(0,$v1,$v2)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRRi { + confess(err("ARGNUM")) if ($#_!=3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$r1,$v2,$m3)=(shift,get_R(shift),get_V(shift), + get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|$r1<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",($m3<<4))."\,"; + $out.=sprintf("%#06x",(RXB(0,$v2)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRSa { + confess(err("ARGNUM")) if ($#_<3||$#_>4); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$v3,$d2,$b2,$m4)=(shift,get_V(shift),get_V(shift), + get_DB(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v3&0xf))).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRSb { + confess(err("ARGNUM")) if ($#_<3||$#_>4); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$r3,$d2,$b2,$m4)=(shift,get_V(shift),get_R(shift), + get_DB(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|$r3)).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",($m4<<12|RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRSc { + confess(err("ARGNUM")) if ($#_!=4); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$r1,$v3,$d2,$b2,$m4)=(shift,get_R(shift),get_V(shift), + get_DB(shift),get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|$r1<<4|($v3&0xf))).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",($m4<<12|RXB(0,$v3)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRSd { + confess(err("ARGNUM")) if ($#_!=3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$r3,$d2,$b2)=(shift,get_V(shift),get_R(shift), + get_DB(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|$r3)).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",(($v1&0xf)<<12|RXB(0,0,0,$v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRV { + confess(err("ARGNUM")) if ($#_<2||$#_>3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$d2,$v2,$b2,$m3)=(shift,get_V(shift),get_DVB(shift), + get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($v2&0xf))).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",($m3<<12|RXB($v1,$v2)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VRX { + confess(err("ARGNUM")) if ($#_<2||$#_>3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$d2,$x2,$b2,$m3)=(shift,get_V(shift),get_DXB(shift), + get_M(shift)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|($v1&0xf)<<4|($x2))).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",($m3<<12|RXB($v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +sub VSI { + confess(err("ARGNUM")) if ($#_!=3); + my $ops=join(',',@_[1..$#_]); + my $memn=(caller(1))[3]; + $memn=~s/^.*:://; + my ($opcode,$v1,$d2,$b2,$i3)=(shift,get_V(shift),get_DB(shift), + get_I(shift,8)); + + $out.="\t.word\t"; + $out.=sprintf("%#06x",($opcode&0xff00|$i3)).","; + $out.=sprintf("%#06x",($b2<<12|$d2)).","; + $out.=sprintf("%#06x",(($v1&0xf)<<12|RXB(0,0,0,$v1)<<8|$opcode&0xff)); + $out.="\t# $memn\t$ops\n" +} + +# +# Internal +# + +sub get_R { + confess(err("ARGNUM")) if ($#_!=0); + my $r; + + for (shift) { + if (!defined) { + $r=0; + } elsif (/^$GR$/) { + $r=$1; + } else { + confess(err("PARSE")); + } + } + confess(err("ARGRANGE")) if ($r&~0xf); + + return $r; +} + +sub get_V { + confess(err("ARGNUM")) if ($#_!=0); + my $v; + + for (shift) { + if (!defined) { + $v=0; + } elsif (/^$VR$/) { + $v=$1; + } else { + confess(err("PARSE")); + } + } + confess(err("ARGRANGE")) if ($v&~0x1f); + + return $v; +} + +sub get_I { + confess(err("ARGNUM")) if ($#_!=1); + my ($i,$bits)=(shift,shift); + + $i=defined($i)?(eval($i)):(0); + confess(err("PARSE")) if (!defined($i)); + confess(err("ARGRANGE")) if (abs($i)&~(2**$bits-1)); + + return $i&(2**$bits-1); +} + +sub get_M { + confess(err("ARGNUM")) if ($#_!=0); + my $m=shift; + + $m=defined($m)?(eval($m)):(0); + confess(err("PARSE")) if (!defined($m)); + confess(err("ARGRANGE")) if ($m&~0xf); + + return $m; +} + +sub get_DB +{ + confess(err("ARGNUM")) if ($#_!=0); + my ($d,$b); + + for (shift) { + if (!defined) { + ($d,$b)=(0,0); + } elsif (/^(.+)\($GR\)$/) { + ($d,$b)=(eval($1),$2); + confess(err("PARSE")) if (!defined($d)); + } elsif (/^(.+)$/) { + ($d,$b)=(eval($1),0); + confess(err("PARSE")) if (!defined($d)); + } else { + confess(err("PARSE")); + } + } + confess(err("ARGRANGE")) if ($d&~0xfff||$b&~0xf); + + return ($d,$b); +} + +sub get_DVB +{ + confess(err("ARGNUM")) if ($#_!=0); + my ($d,$v,$b); + + for (shift) { + if (!defined) { + ($d,$v,$b)=(0,0,0); + } elsif (/^(.+)\($VR,$GR\)$/) { + ($d,$v,$b)=(eval($1),$2,$3); + confess(err("PARSE")) if (!defined($d)); + } elsif (/^(.+)\($GR\)$/) { + ($d,$v,$b)=(eval($1),0,$2); + confess(err("PARSE")) if (!defined($d)); + } elsif (/^(.+)$/) { + ($d,$v,$b)=(eval($1),0,0); + confess(err("PARSE")) if (!defined($d)); + } else { + confess(err("PARSE")); + } + } + confess(err("ARGRANGE")) if ($d&~0xfff||$v&~0x1f||$b&~0xf); + + return ($d,$v,$b); +} + +sub get_DXB +{ + confess(err("ARGNUM")) if ($#_!=0); + my ($d,$x,$b); + + for (shift) { + if (!defined) { + ($d,$x,$b)=(0,0,0); + } elsif (/^(.+)\($GR,$GR\)$/) { + ($d,$x,$b)=(eval($1),$2,$3); + confess(err("PARSE")) if (!defined($d)); + } elsif (/^(.+)\($GR\)$/) { + ($d,$x,$b)=(eval($1),0,$2); + confess(err("PARSE")) if (!defined($d)); + } elsif (/^(.+)$/) { + ($d,$x,$b)=(eval($1),0,0); + confess(err("PARSE")) if (!defined($d)); + } else { + confess(err("PARSE")); + } + } + confess(err("ARGRANGE")) if ($d&~0xfff||$x&~0xf||$b&~0xf); + + return ($d,$x,$b); +} + +sub RXB +{ + confess(err("ARGNUM")) if ($#_<0||3<$#_); + my $rxb=0; + + $rxb|=0x08 if (defined($_[0])&&($_[0]&0x10)); + $rxb|=0x04 if (defined($_[1])&&($_[1]&0x10)); + $rxb|=0x02 if (defined($_[2])&&($_[2]&0x10)); + $rxb|=0x01 if (defined($_[3])&&($_[3]&0x10)); + + return $rxb; +} + +sub err { + my %ERR = + ( + ARGNUM => 'Wrong number of arguments', + ARGRANGE=> 'Argument out of range', + PARSE => 'Parse error', + ); + confess($ERR{ARGNUM}) if ($#_!=0); + + return $ERR{$_[0]}; +} + +1; diff --git a/crypto/ppccap.c b/crypto/ppccap.c index 42147624..e50f7574 100644 --- a/crypto/ppccap.c +++ b/crypto/ppccap.c @@ -168,16 +168,11 @@ void OPENSSL_altivec_probe(void); void OPENSSL_crypto207_probe(void); void OPENSSL_madd300_probe(void); -/* - * Use a weak reference to getauxval() so we can use it if it is available - * but don't break the build if it is not. Note that this is *link-time* - * feature detection, not *run-time*. In other words if we link with - * symbol present, it's expected to be present even at run-time. - */ -#if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) -extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); -#else -static unsigned long (*getauxval) (unsigned long) = NULL; +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 16) +# include +# define OSSL_IMPLEMENT_GETAUXVAL +# endif #endif /* I wish was universally available */ @@ -277,7 +272,8 @@ void OPENSSL_cpuid_setup(void) } #endif - if (getauxval != NULL) { +#ifdef OSSL_IMPLEMENT_GETAUXVAL + { unsigned long hwcap = getauxval(HWCAP); if (hwcap & HWCAP_FPU) { @@ -307,6 +303,7 @@ void OPENSSL_cpuid_setup(void) return; } +#endif sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 459bcbf3..c6ae8a45 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -34,7 +34,7 @@ static int rsa_param_encode(const EVP_PKEY *pkey, *pstr = NULL; /* If RSA it's just NULL type */ - if (pkey->ameth->pkey_id == EVP_PKEY_RSA) { + if (pkey->ameth->pkey_id != EVP_PKEY_RSA_PSS) { *pstrtype = V_ASN1_NULL; return 1; } @@ -58,7 +58,7 @@ static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg) int algptype; X509_ALGOR_get0(&algoid, &algptype, &algp, alg); - if (OBJ_obj2nid(algoid) == EVP_PKEY_RSA) + if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS) return 1; if (algptype == V_ASN1_UNDEF) return 1; @@ -109,7 +109,10 @@ static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) RSA_free(rsa); return 0; } - EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa); + if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa)) { + RSA_free(rsa); + return 0; + } return 1; } diff --git a/crypto/srp/srp_lib.c b/crypto/srp/srp_lib.c index c43d27ae..8cba189e 100644 --- a/crypto/srp/srp_lib.c +++ b/crypto/srp/srp_lib.c @@ -26,6 +26,7 @@ static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N) unsigned char *tmp = NULL; int numN = BN_num_bytes(N); BIGNUM *res = NULL; + if (x != N && BN_ucmp(x, N) >= 0) return NULL; if (y != N && BN_ucmp(y, N) >= 0) @@ -139,7 +140,8 @@ BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) || !EVP_DigestFinal_ex(ctxt, dig, NULL) || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)) goto err; - BN_bn2bin(s, cs); + if (BN_bn2bin(s, cs) < 0) + goto err; if (!EVP_DigestUpdate(ctxt, cs, BN_num_bytes(s))) goto err; diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index 4ed94b7f..d69e330c 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -614,10 +614,14 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0) goto err; N_bn_alloc = BN_bin2bn(tmp, len, NULL); + if (N_bn_alloc == NULL) + goto err; N_bn = N_bn_alloc; if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0) goto err; g_bn_alloc = BN_bin2bn(tmp, len, NULL); + if (g_bn_alloc == NULL) + goto err; g_bn = g_bn_alloc; defgNid = "*"; } else { @@ -639,15 +643,19 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, goto err; s = BN_bin2bn(tmp2, len, NULL); } + if (s == NULL) + goto err; if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) goto err; - BN_bn2bin(v, tmp); + if (BN_bn2bin(v, tmp) < 0) + goto err; vfsize = BN_num_bytes(v) * 2; if (((vf = OPENSSL_malloc(vfsize)) == NULL)) goto err; - t_tob64(vf, tmp, BN_num_bytes(v)); + if (!t_tob64(vf, tmp, BN_num_bytes(v))) + goto err; if (*salt == NULL) { char *tmp_salt; @@ -655,7 +663,10 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) { goto err; } - t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN); + if (!t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN)) { + OPENSSL_free(tmp_salt); + goto err; + } *salt = tmp_salt; } @@ -702,11 +713,15 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, goto err; salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); + if (salttmp == NULL) + goto err; } else { salttmp = *salt; } x = SRP_Calc_x(salttmp, user, pass); + if (x == NULL) + goto err; *verifier = BN_new(); if (*verifier == NULL) diff --git a/crypto/uid.c b/crypto/uid.c index 66356398..494dbdef 100644 --- a/crypto/uid.c +++ b/crypto/uid.c @@ -34,12 +34,13 @@ int OPENSSL_issetugid(void) # if defined(__GLIBC__) && defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2, 16) # include +# define OSSL_IMPLEMENT_GETAUXVAL # endif # endif int OPENSSL_issetugid(void) { -# ifdef AT_SECURE +# ifdef OSSL_IMPLEMENT_GETAUXVAL return getauxval(AT_SECURE) != 0; # else return getuid() != geteuid() || getgid() != getegid(); diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 6bcdafbd..fa8153d3 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -237,7 +237,7 @@ int X509_STORE_up_ref(X509_STORE *vfy) if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0) return 0; - REF_PRINT_COUNT("X509_STORE", a); + REF_PRINT_COUNT("X509_STORE", vfy); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } diff --git a/doc/man1/req.pod b/doc/man1/req.pod index 67cb8ad1..35176270 100644 --- a/doc/man1/req.pod +++ b/doc/man1/req.pod @@ -502,7 +502,7 @@ The actual permitted field names are any object identifier short or long names. These are compiled into OpenSSL and include the usual values such as commonName, countryName, localityName, organizationName, organizationalUnitName, stateOrProvinceName. Additionally emailAddress -is include as well as name, surname, givenName initials and dnQualifier. +is included as well as name, surname, givenName, initials, and dnQualifier. Additional object identifiers can be defined with the B or B options in the configuration file. Any additional fields diff --git a/doc/man1/x509.pod b/doc/man1/x509.pod index 8c096edf..75919ca7 100644 --- a/doc/man1/x509.pod +++ b/doc/man1/x509.pod @@ -173,7 +173,7 @@ options. See the B section for more information. =item B<-noout> -This option prevents output of the encoded version of the request. +This option prevents output of the encoded version of the certificate. =item B<-pubkey> diff --git a/doc/man3/CMS_get0_type.pod b/doc/man3/CMS_get0_type.pod index 96136509..bd45e140 100644 --- a/doc/man3/CMS_get0_type.pod +++ b/doc/man3/CMS_get0_type.pod @@ -16,7 +16,7 @@ CMS_get0_type, CMS_set1_eContentType, CMS_get0_eContentType, CMS_get0_content - =head1 DESCRIPTION CMS_get0_type() returns the content type of a CMS_ContentInfo structure as -and ASN1_OBJECT pointer. An application can then decide how to process the +an ASN1_OBJECT pointer. An application can then decide how to process the CMS_ContentInfo structure based on this value. CMS_set1_eContentType() sets the embedded content type of a CMS_ContentInfo @@ -60,7 +60,7 @@ embedded content as it is normally set by higher level functions. =head1 RETURN VALUES -CMS_get0_type() and CMS_get0_eContentType() return and ASN1_OBJECT structure. +CMS_get0_type() and CMS_get0_eContentType() return an ASN1_OBJECT structure. CMS_set1_eContentType() returns 1 for success or 0 if an error occurred. The error can be obtained from ERR_get_error(3). diff --git a/doc/man3/CONF_modules_load_file.pod b/doc/man3/CONF_modules_load_file.pod index 192a6499..037c7f25 100644 --- a/doc/man3/CONF_modules_load_file.pod +++ b/doc/man3/CONF_modules_load_file.pod @@ -28,13 +28,21 @@ reads configuration information from B. The following B are currently recognized: -B if set errors returned by individual +If B is set errors returned by individual configuration modules are ignored. If not set the first module error is considered fatal and no further modules are loaded. Normally any modules errors will add error information to the error queue. If B is set no error information is added. +If B is set the function unconditionally +returns success. +This is used by default in L to ignore any errors in +the default system-wide configuration file, as having all OpenSSL applications +fail to start when there are potentially minor issues in the file is too risky. +Applications calling B explicitly should not generally +set this flag. + If B is set configuration module loading from DSOs is disabled. diff --git a/doc/man3/OPENSSL_init_crypto.pod b/doc/man3/OPENSSL_init_crypto.pod index ea6b00dc..a8325614 100644 --- a/doc/man3/OPENSSL_init_crypto.pod +++ b/doc/man3/OPENSSL_init_crypto.pod @@ -2,10 +2,11 @@ =head1 NAME -OPENSSL_INIT_new, OPENSSL_INIT_set_config_appname, OPENSSL_INIT_free, -OPENSSL_init_crypto, OPENSSL_cleanup, -OPENSSL_atexit, OPENSSL_thread_stop - OpenSSL -initialisation and deinitialisation functions +OPENSSL_INIT_new, OPENSSL_INIT_set_config_filename, +OPENSSL_INIT_set_config_appname, OPENSSL_INIT_set_config_file_flags, +OPENSSL_INIT_free, OPENSSL_init_crypto, OPENSSL_cleanup, OPENSSL_atexit, +OPENSSL_thread_stop - OpenSSL initialisation +and deinitialisation functions =head1 SYNOPSIS @@ -17,6 +18,10 @@ initialisation and deinitialisation functions void OPENSSL_thread_stop(void); OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void); + int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *init, + const char* filename); + int OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *init, + unsigned long flags); int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *init, const char* name); void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *init); @@ -33,7 +38,7 @@ As of version 1.1.0 OpenSSL will automatically allocate all resources that it needs so no explicit initialisation is required. Similarly it will also automatically deinitialise as required. -However, there way be situations when explicit initialisation is desirable or +However, there may be situations when explicit initialisation is desirable or needed, for example when some non-default initialisation is required. The function OPENSSL_init_crypto() can be used for this purpose for libcrypto (see also L for the libssl @@ -96,7 +101,7 @@ B will be ignored. With this option an OpenSSL configuration file will be automatically loaded and used by calling OPENSSL_config(). This is not a default option for libcrypto. -From OpenSSL 1.1.1 this is a default option for libssl (see +As of OpenSSL 1.1.1 this is a default option for libssl (see L for further details about libssl initialisation). See the description of OPENSSL_INIT_new(), below. @@ -157,6 +162,13 @@ engines. This not a default option. With this option the library will register its fork handlers. See OPENSSL_fork_prepare(3) for details. +=item OPENSSL_INIT_NO_ATEXIT + +By default OpenSSL will attempt to clean itself up when the process exits via an +"atexit" handler. Using this option suppresses that behaviour. This means that +the application will have to clean up OpenSSL explicitly using +OPENSSL_cleanup(). + =back Multiple options may be combined together in a single call to @@ -196,12 +208,22 @@ the library when the thread exits. This should only be called directly if resources should be freed at an earlier time, or under the circumstances described in the NOTES section below. -The B flag will load a default configuration -file. For optional configuration file settings, an B -must be created and used. -The routines OPENSSL_init_new() and OPENSSL_INIT_set_config_appname() can -be used to allocate the object and set the application name, and then the -object can be released with OPENSSL_INIT_free() when done. +The B flag will load a configuration file, as with +L with NULL filename and application name and the +B, B and +B flags. +The filename, application name, and flags can be customized by providing a +non-null B object. +The object can be allocated via B. +The B function can be used to specify a +non-default filename, which is copied and need not refer to persistent storage. +Similarly, OPENSSL_INIT_set_config_appname() can be used to specify a +non-default application name. +Finally, OPENSSL_INIT_set_file_flags can be used to specify non-default flags. +If the B flag is not included, any errors in +the configuration file will cause an error return from B +or indirectly L. +The object can be released with OPENSSL_INIT_free() when done. =head1 NOTES diff --git a/include/internal/conf.h b/include/internal/conf.h index 2d5ce93e..389cdfd7 100644 --- a/include/internal/conf.h +++ b/include/internal/conf.h @@ -12,11 +12,18 @@ #include +#define DEFAULT_CONF_MFLAGS \ + (CONF_MFLAGS_DEFAULT_SECTION | \ + CONF_MFLAGS_IGNORE_MISSING_FILE | \ + CONF_MFLAGS_IGNORE_RETURN_CODES) + struct ossl_init_settings_st { + char *filename; char *appname; + unsigned long flags; }; -void openssl_config_int(const char *appname); +int openssl_config_int(const OPENSSL_INIT_SETTINGS *); void openssl_no_config_int(void); void conf_modules_free_int(void); diff --git a/include/internal/thread_once.h b/include/internal/thread_once.h index c7f0ab29..dcb0c689 100644 --- a/include/internal/thread_once.h +++ b/include/internal/thread_once.h @@ -9,6 +9,20 @@ #include +/* + * DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly + * once. It takes no arguments and returns and int result (1 for success or + * 0 for failure). Typical usage might be: + * + * DEFINE_RUN_ONCE(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ #define DEFINE_RUN_ONCE(init) \ static int init(void); \ int init##_ossl_ret_ = 0; \ @@ -17,10 +31,30 @@ init##_ossl_ret_ = init(); \ } \ static int init(void) + +/* + * DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly + * once that has been defined in another file via DEFINE_RUN_ONCE(). + */ #define DECLARE_RUN_ONCE(init) \ extern int init##_ossl_ret_; \ void init##_ossl_(void); +/* + * DEFINE_RUN_ONCE_STATIC: Define an initialiser function that should be run + * exactly once. This function will be declared as static within the file. It + * takes no arguments and returns and int result (1 for success or 0 for + * failure). Typical usage might be: + * + * DEFINE_RUN_ONCE_STATIC(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ #define DEFINE_RUN_ONCE_STATIC(init) \ static int init(void); \ static int init##_ossl_ret_ = 0; \ @@ -30,6 +64,46 @@ } \ static int init(void) +/* + * DEFINE_RUN_ONCE_STATIC_ALT: Define an alternative initialiser function. This + * function will be declared as static within the file. It takes no arguments + * and returns and int result (1 for success or 0 for failure). An alternative + * initialiser function is expected to be associated with a primary initialiser + * function defined via DEFINE_ONCE_STATIC where both functions use the same + * CRYPTO_ONCE object to synchronise. Where an alternative initialiser function + * is used only one of the primary or the alternative initialiser function will + * ever be called - and that function will be called exactly once. Definitition + * of an alternative initialiser function MUST occur AFTER the definition of the + * primiary initialiser function. + * + * Typical usage might be: + * + * DEFINE_RUN_ONCE_STATIC(myinitfunc) + * { + * do_some_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + * + * DEFINE_RUN_ONCE_STATIC_ALT(myaltinitfunc, myinitfunc) + * { + * do_some_alternative_initialisation(); + * if (init_is_successful()) + * return 1; + * + * return 0; + * } + */ +#define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \ + static int initalt(void); \ + static void initalt##_ossl_(void) \ + { \ + init##_ossl_ret_ = initalt(); \ + } \ + static int initalt(void) + /* * RUN_ONCE - use CRYPTO_THREAD_run_once, and check if the init succeeded * @once: pointer to static object of type CRYPTO_ONCE @@ -43,3 +117,21 @@ */ #define RUN_ONCE(once, init) \ (CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0) + +/* + * RUN_ONCE_ALT - use CRYPTO_THREAD_run_once, to run an alternative initialiser + * function and check if that initialisation succeeded + * @once: pointer to static object of type CRYPTO_ONCE + * @initalt: alternative initialiser function name that was previously given to + * DEFINE_RUN_ONCE_STATIC_ALT. This function must return 1 for + * success or 0 for failure. + * @init: primary initialiser function name that was previously given to + * DEFINE_RUN_ONCE_STATIC. This function must return 1 for success or + * 0 for failure. + * + * The return value is 1 on success (*) or 0 in case of error. + * + * (*) by convention, since the init function must return 1 on success. + */ +#define RUN_ONCE_ALT(once, initalt, init) \ + (CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0) diff --git a/include/openssl/bio.h b/include/openssl/bio.h index cdeacc8e..ed9d4895 100644 --- a/include/openssl/bio.h +++ b/include/openssl/bio.h @@ -641,16 +641,16 @@ int BIO_sock_non_fatal_error(int error); int BIO_fd_should_retry(int i); int BIO_fd_non_fatal_error(int error); int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), - void *u, const char *s, int len); + void *u, const void *s, int len); int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), - void *u, const char *s, int len, int indent); -int BIO_dump(BIO *b, const char *bytes, int len); -int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent); + void *u, const void *s, int len, int indent); +int BIO_dump(BIO *b, const void *bytes, int len); +int BIO_dump_indent(BIO *b, const void *bytes, int len, int indent); # ifndef OPENSSL_NO_STDIO -int BIO_dump_fp(FILE *fp, const char *s, int len); -int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent); +int BIO_dump_fp(FILE *fp, const void *s, int len); +int BIO_dump_indent_fp(FILE *fp, const void *s, int len, int indent); # endif -int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, +int BIO_hex_string(BIO *out, int indent, int width, const void *data, int datalen); # ifndef OPENSSL_NO_SOCK diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h index fc8f32bd..f9123021 100644 --- a/include/openssl/crypto.h +++ b/include/openssl/crypto.h @@ -379,7 +379,7 @@ int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); /* OPENSSL_INIT_ZLIB 0x00010000L */ # define OPENSSL_INIT_ATFORK 0x00020000L /* OPENSSL_INIT_BASE_ONLY 0x00040000L */ -/* FREE: 0x00080000L */ +# define OPENSSL_INIT_NO_ATEXIT 0x00080000L /* OPENSSL_INIT flag range 0x03f00000 reserved for OPENSSL_init_ssl() */ # define OPENSSL_INIT_NO_ADD_ALL_MACS 0x04000000L # define OPENSSL_INIT_ADD_ALL_MACS 0x08000000L @@ -405,8 +405,12 @@ void OPENSSL_thread_stop(void); /* Low-level control of initialization */ OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void); # ifndef OPENSSL_NO_STDIO +int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, + const char *config_filename); +void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, + unsigned long flags); int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, - const char *config_file); + const char *config_appname); # endif void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings); diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index 8c1b7ab0..c8960d0e 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/objects.pl * - * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 9af4ccb0..4d884f47 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -90,8 +90,6 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) int ssl3_change_cipher_state(SSL *s, int which) { unsigned char *p, *mac_secret; - unsigned char exp_key[EVP_MAX_KEY_LENGTH]; - unsigned char exp_iv[EVP_MAX_IV_LENGTH]; unsigned char *ms, *key, *iv; EVP_CIPHER_CTX *dd; const EVP_CIPHER *c; @@ -239,12 +237,8 @@ int ssl3_change_cipher_state(SSL *s, int which) } s->statem.enc_write_state = ENC_WRITE_STATE_VALID; - OPENSSL_cleanse(exp_key, sizeof(exp_key)); - OPENSSL_cleanse(exp_iv, sizeof(exp_iv)); return 1; err: - OPENSSL_cleanse(exp_key, sizeof(exp_key)); - OPENSSL_cleanse(exp_iv, sizeof(exp_iv)); return 0; } diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 3cf2e885..374f647b 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -173,6 +173,8 @@ static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = { EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef, /* GOST2012_512 */ EVP_PKEY_HMAC, + /* MD5/SHA1, SHA224, SHA512 */ + NID_undef, NID_undef, NID_undef }; static size_t ssl_mac_secret_size[SSL_MD_NUM_IDX]; diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c index 86e6a8d5..e766ee1d 100644 --- a/ssl/ssl_init.c +++ b/ssl/ssl_init.c @@ -134,7 +134,8 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings) return 1; } -DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_ssl_strings) +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings, + ossl_init_load_ssl_strings) { /* Do nothing in this case */ return 1; @@ -194,21 +195,23 @@ int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings) return 0; } - if (!OPENSSL_init_crypto(opts + opts |= OPENSSL_INIT_ADD_ALL_CIPHERS + | OPENSSL_INIT_ADD_ALL_DIGESTS + | OPENSSL_INIT_ADD_ALL_MACS; #ifndef OPENSSL_NO_AUTOLOAD_CONFIG - | OPENSSL_INIT_LOAD_CONFIG + if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) == 0) + opts |= OPENSSL_INIT_LOAD_CONFIG; #endif - | OPENSSL_INIT_ADD_ALL_CIPHERS - | OPENSSL_INIT_ADD_ALL_DIGESTS - | OPENSSL_INIT_ADD_ALL_MACS, - settings)) + + if (!OPENSSL_init_crypto(opts, settings)) return 0; if (!RUN_ONCE(&ssl_base, ossl_init_ssl_base)) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS) - && !RUN_ONCE(&ssl_strings, ossl_init_no_load_ssl_strings)) + && !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings, + ossl_init_load_ssl_strings)) return 0; if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS) diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index c5492184..773309a1 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -348,10 +348,12 @@ static const EXTENSION_DEFINITION ext_defs[] = { { /* * Special unsolicited ServerHello extension only used when - * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set + * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but + * ignore it. */ TLSEXT_TYPE_cryptopro_bug, - SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL }, { @@ -623,7 +625,12 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context, && type != TLSEXT_TYPE_cookie && type != TLSEXT_TYPE_renegotiate && type != TLSEXT_TYPE_signed_certificate_timestamp - && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0) { + && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0 +#ifndef OPENSSL_NO_GOST + && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0 + && type == TLSEXT_TYPE_cryptopro_bug) +#endif + ) { SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION); goto err; diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 3b6cbb76..53bc5ef3 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1112,13 +1112,6 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt) SSL_SESSION *sess = s->session; unsigned char *session_id; - if (!WPACKET_set_max_size(pkt, SSL3_RT_MAX_PLAIN_LENGTH)) { - /* Should not happen */ - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - return 0; - } - /* Work out what SSL/TLS/DTLS version to use */ protverr = ssl_set_client_hello_version(s); if (protverr != 0) { diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index adcc6261..9b58bd86 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -85,10 +85,6 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km, size_t num) int tls1_change_cipher_state(SSL *s, int which) { unsigned char *p, *mac_secret; - unsigned char tmp1[EVP_MAX_KEY_LENGTH]; - unsigned char tmp2[EVP_MAX_KEY_LENGTH]; - unsigned char iv1[EVP_MAX_IV_LENGTH * 2]; - unsigned char iv2[EVP_MAX_IV_LENGTH * 2]; unsigned char *ms, *key, *iv; EVP_CIPHER_CTX *dd; const EVP_CIPHER *c; @@ -408,16 +404,8 @@ int tls1_change_cipher_state(SSL *s, int which) printf("\n"); #endif - OPENSSL_cleanse(tmp1, sizeof(tmp1)); - OPENSSL_cleanse(tmp2, sizeof(tmp1)); - OPENSSL_cleanse(iv1, sizeof(iv1)); - OPENSSL_cleanse(iv2, sizeof(iv2)); return 1; err: - OPENSSL_cleanse(tmp1, sizeof(tmp1)); - OPENSSL_cleanse(tmp2, sizeof(tmp1)); - OPENSSL_cleanse(iv1, sizeof(iv1)); - OPENSSL_cleanse(iv2, sizeof(iv2)); return 0; } diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c index 17966c80..e6cd7057 100644 --- a/ssl/tls13_enc.c +++ b/ssl/tls13_enc.c @@ -41,7 +41,7 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret, * + bytes for the hash itself */ unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) + - + sizeof(label_prefix) + TLS13_MAX_LABEL_LEN + + (sizeof(label_prefix) - 1) + TLS13_MAX_LABEL_LEN + 1 + EVP_MAX_MD_SIZE]; WPACKET pkt; @@ -323,11 +323,9 @@ int tls13_setup_key_block(SSL *s) { const EVP_CIPHER *c; const EVP_MD *hash; - int mac_type = NID_undef; s->session->cipher = s->s3->tmp.new_cipher; - if (!ssl_cipher_get_evp - (s->session, &c, &hash, &mac_type, NULL, NULL, 0)) { + if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, NULL, 0)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return 0; diff --git a/test/bntest.c b/test/bntest.c index e760c64f..d042a3e2 100644 --- a/test/bntest.c +++ b/test/bntest.c @@ -519,6 +519,31 @@ static int test_modexp_mont5(void) if (!TEST_BN_eq(c, d)) goto err; + /* + * rsaz_1024_mul_avx2 expects fully-reduced inputs. + * BN_mod_exp_mont_consttime should reduce the input first. + */ + BN_hex2bn(&a, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2020202020DF"); + BN_hex2bn(&b, + "1FA53F26F8811C58BE0357897AA5E165693230BC9DF5F01DFA6A2D59229EC69D" + "9DE6A89C36E3B6957B22D6FAAD5A3C73AE587B710DBE92E83D3A9A3339A085CB" + "B58F508CA4F837924BB52CC1698B7FDC2FD74362456A595A5B58E38E38E38E38" + "E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E38E"); + BN_hex2bn(&n, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2020202020DF"); + BN_MONT_CTX_set(mont, n, ctx); + BN_mod_exp_mont_consttime(c, a, b, n, ctx, mont); + BN_zero(d); + if (!TEST_BN_eq(c, d)) + goto err; + /* Zero input */ BN_bntest_rand(p, 1024, 0, 0); BN_zero(a); diff --git a/test/build.info b/test/build.info index 0227212d..962af11e 100644 --- a/test/build.info +++ b/test/build.info @@ -392,7 +392,6 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=main PROGRAMS_NO_INST=shlibloadtest SOURCE[shlibloadtest]=shlibloadtest.c INCLUDE[shlibloadtest]=../include ../crypto/include - DEPEND[shlibloadtest]=libtestutil.a ENDIF IF[{- $disabled{shared} -}] diff --git a/test/certs/root-cert-rsa2.pem b/test/certs/root-cert-rsa2.pem new file mode 100644 index 00000000..b817fdf3 --- /dev/null +++ b/test/certs/root-cert-rsa2.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7DCCAdSgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 +IENBMCAXDTE2MDExNTA4MTk0OVoYDzIxMTYwMTE2MDgxOTQ5WjASMRAwDgYDVQQD +DAdSb290IENBMIIBHTAIBgRVCAEBBQADggEPADCCAQoCggEBAOHmAPUGvKBGOHkP +Px5xGRNtAt8rm3Zr/KywIe3WkQhCO6VjNexSW6CiSsXWAJQDl1o9uWco0n3jIVyk +7cY8jY6E0Z1Uwz3ZdKKWdmdx+cYaUHez/XjuW+DjjIkjwpoi7D7UN54HzcArVREX +OjRCHGkNOhiw7RWUXsb9nofGHOeUGpLAXwXBc0PlA94JkckkztiOi34u4DFI0YYq +alUmeugLNk6XseCkydpcaUsDgAhWg6Mfsiq4wUz+xbFN1MABqu2+ziW97mmt9gfN +biuhiVT1aOuYCe3JYGbLM2JKA7Bo1g6rX8E1VX79Ru6669y2oqPthX9337VoIkN+ +ZiQjr8UCAwEAAaNQME4wHQYDVR0OBBYEFI71Ja8em2uEPXyAmslTnE1y96NSMB8G +A1UdIwQYMBaAFI71Ja8em2uEPXyAmslTnE1y96NSMAwGA1UdEwQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBAJ0OIdog3uQ1pmsjv1Qtf1w4If1geOn5uK0EOj2wYBHt +NxlFn7l8d9+51QMZFO+RlQJ0s3Webyo1ReuaL2dMn2LGJhWMoSBAwrMALAENU3lv +8jioRbfO2OamsdpJpKxQUyUJYudNe+BoKNX/ry3rxezmsFsRr9nDMiJZpmBCXiMm +mFFJOJkG0CheexBbMkua4kyStIOwO4rb5bSHszVso/9ucdGHBSC7oRcJXoWSDjBx +PdQPPBK5g4yqL8Lz26ehgsmhRKL9k32eVyjDKcIzgpmgcPTfTqNbd1KHQJKx4ssb +7nEpGKHalSo5Oq5L9s9qYrUv37kwBY4OpJFtmGaodoI= +-----END CERTIFICATE----- diff --git a/test/drbg_cavs_test.c b/test/drbg_cavs_test.c index 4bb65f0f..99d44725 100644 --- a/test/drbg_cavs_test.c +++ b/test/drbg_cavs_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -106,12 +106,9 @@ static int single_kat_no_reseed(const struct drbg_kat *td) failures++; err: - if (buff != NULL) - OPENSSL_free(buff); - if (drbg != NULL) { - RAND_DRBG_uninstantiate(drbg); - RAND_DRBG_free(drbg); - } + OPENSSL_free(buff); + RAND_DRBG_uninstantiate(drbg); + RAND_DRBG_free(drbg); return failures == 0; } @@ -176,12 +173,9 @@ static int single_kat_pr_false(const struct drbg_kat *td) failures++; err: - if (buff != NULL) - OPENSSL_free(buff); - if (drbg != NULL) { - RAND_DRBG_uninstantiate(drbg); - RAND_DRBG_free(drbg); - } + OPENSSL_free(buff); + RAND_DRBG_uninstantiate(drbg); + RAND_DRBG_free(drbg); return failures == 0; } @@ -249,12 +243,9 @@ static int single_kat_pr_true(const struct drbg_kat *td) failures++; err: - if (buff != NULL) - OPENSSL_free(buff); - if (drbg != NULL) { - RAND_DRBG_uninstantiate(drbg); - RAND_DRBG_free(drbg); - } + OPENSSL_free(buff); + RAND_DRBG_uninstantiate(drbg); + RAND_DRBG_free(drbg); return failures == 0; } diff --git a/test/evp_test.c b/test/evp_test.c index f3dd79ba..eaedab2c 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -1761,15 +1761,18 @@ static int encode_test_init(EVP_TEST *t, const char *encoding) } else if (strcmp(encoding, "invalid") == 0) { edata->encoding = BASE64_INVALID_ENCODING; if (!TEST_ptr(t->expected_err = OPENSSL_strdup("DECODE_ERROR"))) - return 0; + goto err; } else { TEST_error("Bad encoding: %s." " Should be one of {canonical, valid, invalid}", encoding); - return 0; + goto err; } t->data = edata; return 1; +err: + OPENSSL_free(edata); + return 0; } static void encode_test_cleanup(EVP_TEST *t) @@ -1798,7 +1801,7 @@ static int encode_test_run(EVP_TEST *t) ENCODE_DATA *expected = t->data; unsigned char *encode_out = NULL, *decode_out = NULL; int output_len, chunk_len; - EVP_ENCODE_CTX *decode_ctx; + EVP_ENCODE_CTX *decode_ctx = NULL, *encode_ctx = NULL; if (!TEST_ptr(decode_ctx = EVP_ENCODE_CTX_new())) { t->err = "INTERNAL_ERROR"; @@ -1806,7 +1809,6 @@ static int encode_test_run(EVP_TEST *t) } if (expected->encoding == BASE64_CANONICAL_ENCODING) { - EVP_ENCODE_CTX *encode_ctx; if (!TEST_ptr(encode_ctx = EVP_ENCODE_CTX_new()) || !TEST_ptr(encode_out = @@ -1814,15 +1816,15 @@ static int encode_test_run(EVP_TEST *t) goto err; EVP_EncodeInit(encode_ctx); - EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len, - expected->input, expected->input_len); + if (!TEST_true(EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len, + expected->input, expected->input_len))) + goto err; + output_len = chunk_len; EVP_EncodeFinal(encode_ctx, encode_out + chunk_len, &chunk_len); output_len += chunk_len; - EVP_ENCODE_CTX_free(encode_ctx); - if (!memory_err_compare(t, "BAD_ENCODING", expected->output, expected->output_len, encode_out, output_len)) @@ -1860,6 +1862,7 @@ static int encode_test_run(EVP_TEST *t) OPENSSL_free(encode_out); OPENSSL_free(decode_out); EVP_ENCODE_CTX_free(decode_ctx); + EVP_ENCODE_CTX_free(encode_ctx); return 1; } diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t index 0db26452..9ddf2c9c 100644 --- a/test/recipes/25-test_verify.t +++ b/test/recipes/25-test_verify.t @@ -27,7 +27,7 @@ sub verify { run(app([@args])); } -plan tests => 134; +plan tests => 135; # Canonical success ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), @@ -361,6 +361,8 @@ ok(verify("some-names2", "sslserver", ["many-constraints"], ["many-constraints"] "Not too many names and constraints to check (2)"); ok(verify("some-names2", "sslserver", ["many-constraints"], ["many-constraints"], ), "Not too many names and constraints to check (3)"); +ok(verify("root-cert-rsa2", "sslserver", ["root-cert-rsa2"], [], "-check_ss_sig"), + "Public Key Algorithm rsa instead of rsaEncryption"); SKIP: { skip "Ed25519 is not supported by this OpenSSL build", 1 diff --git a/test/recipes/70-test_sslextension.t b/test/recipes/70-test_sslextension.t index 79466b61..e725b44f 100644 --- a/test/recipes/70-test_sslextension.t +++ b/test/recipes/70-test_sslextension.t @@ -88,9 +88,11 @@ sub inject_duplicate_extension foreach my $message (@{$proxy->message_list}) { if ($message->mt == $message_type) { my %extensions = %{$message->extension_data}; - # Add a duplicate (unknown) extension. - $message->set_extension(TLSProxy::Message::EXT_DUPLICATE_EXTENSION, ""); - $message->set_extension(TLSProxy::Message::EXT_DUPLICATE_EXTENSION, ""); + # Add a duplicate extension. We use cryptopro_bug since we never + # normally write that one, and it is allowed as unsolicited in the + # ServerHello + $message->set_extension(TLSProxy::Message::EXT_CRYPTOPRO_BUG_EXTENSION, ""); + $message->dupext(TLSProxy::Message::EXT_CRYPTOPRO_BUG_EXTENSION); $message->repack(); } } @@ -173,9 +175,23 @@ sub inject_unsolicited_extension $sent_unsolisited_extension = 1; } +sub inject_cryptopro_extension +{ + my $proxy = shift; + + # We're only interested in the initial ClientHello + if ($proxy->flight != 0) { + return; + } + + my $message = ${$proxy->message_list}[0]; + $message->set_extension(TLSProxy::Message::EXT_CRYPTOPRO_BUG_EXTENSION, ""); + $message->repack(); +} + # Test 1-2: Sending a duplicate extension should fail. $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; -plan tests => 7; +plan tests => 8; ok($fatal_alert, "Duplicate ClientHello extension"); $fatal_alert = 0; @@ -234,3 +250,11 @@ SKIP: { $proxy->start(); ok($fatal_alert, "Unsolicited server name extension (TLSv1.3)"); } + +#Test 8: Send the cryptopro extension in a ClientHello. Normally this is an +# unsolicited extension only ever seen in the ServerHello. We should +# ignore it in a ClientHello +$proxy->clear(); +$proxy->filter(\&inject_cryptopro_extension); +$proxy->start(); +ok(TLSProxy::Message->success(), "Cryptopro extension in ClientHello"); diff --git a/test/recipes/90-test_gost.t b/test/recipes/90-test_gost.t index ac214e2c..d4f27b89 100644 --- a/test/recipes/90-test_gost.t +++ b/test/recipes/90-test_gost.t @@ -12,11 +12,11 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; setup("test_gost"); # The GOST ciphers are dynamically loaded via the GOST engine, so we must be -# able to support that. The engine also uses DSA and CMS symbols, so we skip -# this test on no-dsa or no-cms. +# able to support that. The engine also uses DSA, CMS and CMAC symbols, so we +# skip this test on no-dsa, no-cms or no-cmac. plan skip_all => "GOST support is disabled in this OpenSSL build" if disabled("gost") || disabled("engine") || disabled("dynamic-engine") - || disabled("dsa") || disabled("cms"); + || disabled("dsa") || disabled("cms") || disabled("cmac"); plan skip_all => "TLSv1.3 or TLSv1.2 are disabled in this OpenSSL build" if disabled("tls1_3") || disabled("tls1_2"); diff --git a/test/recipes/90-test_shlibload.t b/test/recipes/90-test_shlibload.t index bb7fab07..ea8aeeb7 100644 --- a/test/recipes/90-test_shlibload.t +++ b/test/recipes/90-test_shlibload.t @@ -8,6 +8,7 @@ use OpenSSL::Test qw/:DEFAULT bldtop_dir bldtop_file/; use OpenSSL::Test::Utils; +use File::Temp qw(tempfile); #Load configdata.pm @@ -20,7 +21,7 @@ use configdata; plan skip_all => "Test only supported in a shared build" if disabled("shared"); plan skip_all => "Test is disabled on AIX" if config('target') =~ m|^aix|; -plan tests => 4; +plan tests => 10; # When libssl and libcrypto are compiled on Linux with "-rpath", but not # "--enable-new-dtags", the RPATH takes precedence over LD_LIBRARY_PATH, @@ -30,14 +31,31 @@ plan tests => 4; my $libcrypto = bldtop_file(shlib('libcrypto')); my $libssl = bldtop_file(shlib('libssl')); -ok(run(test(["shlibloadtest", "-crypto_first", $libcrypto, $libssl])), - "running shlibloadtest -crypto_first"); -ok(run(test(["shlibloadtest", "-ssl_first", $libcrypto, $libssl])), - "running shlibloadtest -ssl_first"); -ok(run(test(["shlibloadtest", "-just_crypto", $libcrypto, $libssl])), - "running shlibloadtest -just_crypto"); -ok(run(test(["shlibloadtest", "-dso_ref", $libcrypto, $libssl])), - "running shlibloadtest -dso_ref"); +(my $fh, my $filename) = tempfile(); +ok(run(test(["shlibloadtest", "-crypto_first", $libcrypto, $libssl, $filename])), + "running shlibloadtest -crypto_first $filename"); +ok(check_atexit($fh)); +unlink $filename; +($fh, $filename) = tempfile(); +ok(run(test(["shlibloadtest", "-ssl_first", $libcrypto, $libssl, $filename])), + "running shlibloadtest -ssl_first $filename"); +ok(check_atexit($fh)); +unlink $filename; +($fh, $filename) = tempfile(); +ok(run(test(["shlibloadtest", "-just_crypto", $libcrypto, $libssl, $filename])), + "running shlibloadtest -just_crypto $filename"); +ok(check_atexit($fh)); +unlink $filename; +($fh, $filename) = tempfile(); +ok(run(test(["shlibloadtest", "-dso_ref", $libcrypto, $libssl, $filename])), + "running shlibloadtest -dso_ref $filename"); +ok(check_atexit($fh)); +unlink $filename; +($fh, $filename) = tempfile(); +ok(run(test(["shlibloadtest", "-no_atexit", $libcrypto, $libssl, $filename])), + "running shlibloadtest -no_atexit $filename"); +ok(!check_atexit($fh)); +unlink $filename; sub shlib { my $lib = shift; @@ -49,3 +67,12 @@ sub shlib { $lib =~ s|\.\$\(SHLIB_VERSION_NUMBER\)|.$config{shlib_version}|; return $lib; } + +sub check_atexit { + my $fh = shift; + my $data = <$fh>; + + return 1 if (defined $data && $data =~ m/atexit\(\) run/); + + return 0; +} diff --git a/test/shlibloadtest.c b/test/shlibloadtest.c index 4c5d8010..6934b89d 100644 --- a/test/shlibloadtest.c +++ b/test/shlibloadtest.c @@ -14,13 +14,14 @@ #include #include #include "internal/dso_conf.h" -#include "testutil.h" typedef void DSO; typedef const SSL_METHOD * (*TLS_method_t)(void); typedef SSL_CTX * (*SSL_CTX_new_t)(const SSL_METHOD *meth); typedef void (*SSL_CTX_free_t)(SSL_CTX *); +typedef int (*OPENSSL_init_crypto_t)(uint64_t, void *); +typedef int (*OPENSSL_atexit_t)(void (*handler)(void)); typedef unsigned long (*ERR_get_error_t)(void); typedef unsigned long (*OPENSSL_version_major_t)(void); typedef unsigned long (*OPENSSL_version_minor_t)(void); @@ -32,12 +33,14 @@ typedef enum test_types_en { CRYPTO_FIRST, SSL_FIRST, JUST_CRYPTO, - DSO_REFTEST + DSO_REFTEST, + NO_ATEXIT } TEST_TYPE; static TEST_TYPE test_type; static const char *path_crypto; static const char *path_ssl; +static const char *path_atexit; #ifdef DSO_DLFCN @@ -101,6 +104,20 @@ static int shlib_close(SHLIB lib) #if defined(DSO_DLFCN) || defined(DSO_WIN32) +static int atexit_handler_done = 0; + +static void atexit_handler(void) +{ + FILE *atexit_file = fopen(path_atexit, "w"); + + if (atexit_file == NULL) + return; + + fprintf(atexit_file, "atexit() run\n"); + fclose(atexit_file); + atexit_handler_done++; +} + static int test_lib(void) { SHLIB ssllib = SHLIB_INIT; @@ -109,7 +126,7 @@ static int test_lib(void) union { void (*func)(void); SHLIB_SYM sym; - } symbols[4]; + } symbols[5]; TLS_method_t myTLS_method; SSL_CTX_new_t mySSL_CTX_new; SSL_CTX_free_t mySSL_CTX_free; @@ -117,65 +134,100 @@ static int test_lib(void) OPENSSL_version_major_t myOPENSSL_version_major; OPENSSL_version_minor_t myOPENSSL_version_minor; OPENSSL_version_patch_t myOPENSSL_version_patch; + OPENSSL_atexit_t myOPENSSL_atexit; int result = 0; switch (test_type) { case JUST_CRYPTO: - if (!TEST_true(shlib_load(path_crypto, &cryptolib))) - goto end; - break; - case CRYPTO_FIRST: - if (!TEST_true(shlib_load(path_crypto, &cryptolib)) - || !TEST_true(shlib_load(path_ssl, &ssllib))) - goto end; - break; - case SSL_FIRST: - if (!TEST_true(shlib_load(path_ssl, &ssllib)) - || !TEST_true(shlib_load(path_crypto, &cryptolib))) - goto end; - break; case DSO_REFTEST: - if (!TEST_true(shlib_load(path_crypto, &cryptolib))) + case NO_ATEXIT: + case CRYPTO_FIRST: + if (!shlib_load(path_crypto, &cryptolib)) { + fprintf(stderr, "Failed to load libcrypto\n"); goto end; + } + if (test_type != CRYPTO_FIRST) + break; + /* Fall through */ + + case SSL_FIRST: + if (!shlib_load(path_ssl, &ssllib)) { + fprintf(stderr, "Failed to load libssl\n"); + goto end; + } + if (test_type != SSL_FIRST) + break; + if (!shlib_load(path_crypto, &cryptolib)) { + fprintf(stderr, "Failed to load libcrypto\n"); + goto end; + } break; } - if (test_type != JUST_CRYPTO && test_type != DSO_REFTEST) { - if (!TEST_true(shlib_sym(ssllib, "TLS_method", &symbols[0].sym)) - || !TEST_true(shlib_sym(ssllib, "SSL_CTX_new", &symbols[1].sym)) - || !TEST_true(shlib_sym(ssllib, "SSL_CTX_free", &symbols[2].sym))) + if (test_type == NO_ATEXIT) { + OPENSSL_init_crypto_t myOPENSSL_init_crypto; + + if (!shlib_sym(cryptolib, "OPENSSL_init_crypto", &symbols[0].sym)) { + fprintf(stderr, "Failed to load OPENSSL_init_crypto symbol\n"); goto end; + } + myOPENSSL_init_crypto = (OPENSSL_init_crypto_t)symbols[0].func; + if (!myOPENSSL_init_crypto(OPENSSL_INIT_NO_ATEXIT, NULL)) { + fprintf(stderr, "Failed to initialise libcrypto\n"); + goto end; + } + } + + if (test_type != JUST_CRYPTO + && test_type != DSO_REFTEST + && test_type != NO_ATEXIT) { + if (!shlib_sym(ssllib, "TLS_method", &symbols[0].sym) + || !shlib_sym(ssllib, "SSL_CTX_new", &symbols[1].sym) + || !shlib_sym(ssllib, "SSL_CTX_free", &symbols[2].sym)) { + fprintf(stderr, "Failed to load libssl symbols\n"); + goto end; + } myTLS_method = (TLS_method_t)symbols[0].func; mySSL_CTX_new = (SSL_CTX_new_t)symbols[1].func; mySSL_CTX_free = (SSL_CTX_free_t)symbols[2].func; - if (!TEST_ptr(ctx = mySSL_CTX_new(myTLS_method()))) + ctx = mySSL_CTX_new(myTLS_method()); + if (ctx == NULL) { + fprintf(stderr, "Failed to create SSL_CTX\n"); goto end; + } mySSL_CTX_free(ctx); } - if (!TEST_true(shlib_sym(cryptolib, "ERR_get_error", &symbols[0].sym)) - || !TEST_true(shlib_sym(cryptolib, "OPENSSL_version_major", - &symbols[1].sym)) - || !TEST_true(shlib_sym(cryptolib, "OPENSSL_version_minor", - &symbols[2].sym)) - || !TEST_true(shlib_sym(cryptolib, "OPENSSL_version_patch", - &symbols[3].sym))) + if (!shlib_sym(cryptolib, "ERR_get_error", &symbols[0].sym) + || !shlib_sym(cryptolib, "OPENSSL_version_major", &symbols[1].sym) + || !shlib_sym(cryptolib, "OPENSSL_version_minor", &symbols[2].sym) + || !shlib_sym(cryptolib, "OPENSSL_version_patch", &symbols[3].sym) + || !shlib_sym(cryptolib, "OPENSSL_atexit", &symbols[4].sym)) { + fprintf(stderr, "Failed to load libcrypto symbols\n"); goto end; + } myERR_get_error = (ERR_get_error_t)symbols[0].func; - if (!TEST_int_eq(myERR_get_error(), 0)) + if (myERR_get_error() != 0) { + fprintf(stderr, "Unexpected ERR_get_error() response\n"); goto end; + } - /* Make sure the libraries are a compatible version */ + /* Library and header version should be identical in this test */ myOPENSSL_version_major = (OPENSSL_version_major_t)symbols[1].func; myOPENSSL_version_minor = (OPENSSL_version_minor_t)symbols[2].func; myOPENSSL_version_patch = (OPENSSL_version_patch_t)symbols[3].func; - if (!TEST_int_eq(myOPENSSL_version_major(), OPENSSL_VERSION_MAJOR)) + if (myOPENSSL_version_major() != OPENSSL_VERSION_MAJOR + || myOPENSSL_version_minor() != OPENSSL_VERSION_MINOR + || myOPENSSL_version_patch() != OPENSSL_VERSION_PATCH) { + fprintf(stderr, "Invalid library version number\n"); goto end; - if (!TEST_int_ge(myOPENSSL_version_minor(), OPENSSL_VERSION_MINOR)) - goto end; - if (myOPENSSL_version_minor() == OPENSSL_VERSION_MINOR - && !TEST_int_ge(myOPENSSL_version_patch(), OPENSSL_VERSION_PATCH)) + } + + myOPENSSL_atexit = (OPENSSL_atexit_t)symbols[4].func; + if (!myOPENSSL_atexit(atexit_handler)) { + fprintf(stderr, "Failed to register atexit handler\n"); goto end; + } if (test_type == DSO_REFTEST) { # ifdef DSO_DLFCN @@ -190,10 +242,11 @@ static int test_lib(void) * will always return an error, because DSO_pathbyaddr() is not * implemented there. */ - if (!TEST_true(shlib_sym(cryptolib, "DSO_dsobyaddr", &symbols[0].sym)) - || !TEST_true(shlib_sym(cryptolib, "DSO_free", - &symbols[1].sym))) + if (!shlib_sym(cryptolib, "DSO_dsobyaddr", &symbols[0].sym) + || !shlib_sym(cryptolib, "DSO_free", &symbols[1].sym)) { + fprintf(stderr, "Unable to load DSO symbols\n"); goto end; + } myDSO_dsobyaddr = (DSO_dsobyaddr_t)symbols[0].func; myDSO_free = (DSO_free_t)symbols[1].func; @@ -201,34 +254,45 @@ static int test_lib(void) { DSO *hndl; /* use known symbol from crypto module */ - if (!TEST_ptr(hndl = myDSO_dsobyaddr((void (*)(void))ERR_get_error, 0))) + hndl = myDSO_dsobyaddr((void (*)(void))myERR_get_error, 0); + if (hndl == NULL) { + fprintf(stderr, "DSO_dsobyaddr() failed\n"); goto end; + } myDSO_free(hndl); } # endif /* DSO_DLFCN */ } - switch (test_type) { - case JUST_CRYPTO: - if (!TEST_true(shlib_close(cryptolib))) - goto end; - break; - case CRYPTO_FIRST: - if (!TEST_true(shlib_close(cryptolib)) - || !TEST_true(shlib_close(ssllib))) - goto end; - break; - case SSL_FIRST: - if (!TEST_true(shlib_close(ssllib)) - || !TEST_true(shlib_close(cryptolib))) - goto end; - break; - case DSO_REFTEST: - if (!TEST_true(shlib_close(cryptolib))) - goto end; - break; + if (!shlib_close(cryptolib)) { + fprintf(stderr, "Failed to close libcrypto\n"); + goto end; } + if (test_type == CRYPTO_FIRST || test_type == SSL_FIRST) { + if (!shlib_close(ssllib)) { + fprintf(stderr, "Failed to close libssl\n"); + goto end; + } + } + +# if defined(OPENSSL_NO_PINSHARED) \ + && defined(__GLIBC__) \ + && defined(__GLIBC_PREREQ) \ + && defined(OPENSSL_SYS_LINUX) +# if __GLIBC_PREREQ(2, 3) + /* + * If we didn't pin the so then we are hopefully on a platform that supports + * running atexit() on so unload. If not we might crash. We know this is + * true on linux since glibc 2.2.3 + */ + if (test_type != NO_ATEXIT && atexit_handler_done != 1) { + fprintf(stderr, "atexit() handler did not run\n"); + goto end; + } +# endif +# endif + result = 1; end: return result; @@ -236,9 +300,21 @@ end: #endif -int setup_tests(void) +/* + * shlibloadtest should not use the normal test framework because we don't want + * it to link against libcrypto (which the framework uses). The point of the + * test is to check dynamic loading and unloading of libcrypto/libssl. + */ +int main(int argc, char *argv[]) { - const char *p = test_get_argument(0); + const char *p; + + if (argc != 5) { + fprintf(stderr, "Incorrect number of arguments\n"); + return 1; + } + + p = argv[1]; if (strcmp(p, "-crypto_first") == 0) { test_type = CRYPTO_FIRST; @@ -247,17 +323,24 @@ int setup_tests(void) } else if (strcmp(p, "-just_crypto") == 0) { test_type = JUST_CRYPTO; } else if (strcmp(p, "-dso_ref") == 0) { - test_type = JUST_CRYPTO; + test_type = DSO_REFTEST; + } else if (strcmp(p, "-no_atexit") == 0) { + test_type = NO_ATEXIT; } else { - TEST_error("Unrecognised argument"); - return 0; + fprintf(stderr, "Unrecognised argument\n"); + return 1; + } + path_crypto = argv[2]; + path_ssl = argv[3]; + path_atexit = argv[4]; + if (path_crypto == NULL || path_ssl == NULL) { + fprintf(stderr, "Invalid libcrypto/libssl path\n"); + return 1; } - if (!TEST_ptr(path_crypto = test_get_argument(1)) - || !TEST_ptr(path_ssl = test_get_argument(2))) - return 0; #if defined(DSO_DLFCN) || defined(DSO_WIN32) - ADD_TEST(test_lib); + if (!test_lib()) + return 1; #endif - return 1; + return 0; } diff --git a/test/sslapitest.c b/test/sslapitest.c index d52380c2..1868eb31 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -657,7 +657,8 @@ static int execute_test_large_message(const SSL_METHOD *smeth, return testresult; } -#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) \ + && !defined(OPENSSL_NO_SOCK) /* sock must be connected */ static int ktls_chk_platform(int sock) @@ -6053,7 +6054,8 @@ int setup_tests(void) #endif } -#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) \ + && !defined(OPENSSL_NO_SOCK) ADD_TEST(test_ktls_client_server); ADD_TEST(test_ktls_no_client_server); ADD_TEST(test_ktls_client_no_server); diff --git a/test/ssltestlib.c b/test/ssltestlib.c index 50c71126..78c0e8eb 100644 --- a/test/ssltestlib.c +++ b/test/ssltestlib.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -436,7 +436,7 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, { MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio); MEMPACKET *thispkt = NULL, *looppkt, *nextpkt, *allpkts[3]; - int i, duprec = ctx->duprec > 0; + int i, duprec; const unsigned char *inu = (const unsigned char *)in; size_t len = ((inu[RECORD_LEN_HI] << 8) | inu[RECORD_LEN_LO]) + DTLS1_RT_HEADER_LENGTH; @@ -449,6 +449,8 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, if ((size_t)inl == len) duprec = 0; + else + duprec = ctx->duprec > 0; /* We don't support arbitrary injection when duplicating records */ if (duprec && pktnum != -1) @@ -663,7 +665,7 @@ int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm, #define MAXLOOPS 1000000 -#ifndef OPENSSL_NO_KTLS +#if !defined(OPENSSL_NO_KTLS) && !defined(OPENSSL_NO_SOCK) static int set_nb(int fd) { int flags; @@ -736,12 +738,6 @@ success: close(afd); return ret; } -#else -int create_test_sockets(int *cfd, int *sfd) -{ - return 0; -} -#endif int create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, SSL **cssl, int sfd, int cfd) @@ -775,6 +771,7 @@ int create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, BIO_free(c_to_s_bio); return 0; } +#endif /* * NOTE: Transfers control of the BIOs - this function will free them on error diff --git a/util/libcrypto.num b/util/libcrypto.num index 5439eafc..84db7a52 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4620,4 +4620,6 @@ CRYPTO_siv128_set_tag 4575 3_0_0 EXIST::FUNCTION:SIV CRYPTO_siv128_get_tag 4576 3_0_0 EXIST::FUNCTION:SIV CRYPTO_siv128_cleanup 4577 3_0_0 EXIST::FUNCTION:SIV CRYPTO_siv128_speed 4578 3_0_0 EXIST::FUNCTION:SIV -EVP_chacha20_poly1305_draft 4579 3_0_0 EXIST::FUNCTION:CHACHA,POLY1305_DRAFT +OPENSSL_INIT_set_config_filename 4579 3_0_0 EXIST::FUNCTION:STDIO +OPENSSL_INIT_set_config_file_flags 4580 3_0_0 EXIST::FUNCTION:STDIO +EVP_chacha20_poly1305_draft 4581 3_0_0 EXIST::FUNCTION:CHACHA,POLY1305_DRAFT diff --git a/util/perl/TLSProxy/Certificate.pm b/util/perl/TLSProxy/Certificate.pm index 70c9faea..03f66199 100644 --- a/util/perl/TLSProxy/Certificate.pm +++ b/util/perl/TLSProxy/Certificate.pm @@ -138,11 +138,6 @@ sub set_message_contents $extensions .= pack("n", $key); $extensions .= pack("n", length($extdata)); $extensions .= $extdata; - if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) { - $extensions .= pack("n", $key); - $extensions .= pack("n", length($extdata)); - $extensions .= $extdata; - } } $data = pack('C', length($self->context())); $data .= $self->context; diff --git a/util/perl/TLSProxy/ClientHello.pm b/util/perl/TLSProxy/ClientHello.pm index 7ae3dba9..c49bc236 100644 --- a/util/perl/TLSProxy/ClientHello.pm +++ b/util/perl/TLSProxy/ClientHello.pm @@ -124,11 +124,6 @@ sub extension_contents $extension .= pack("n", $key); $extension .= pack("n", length($extdata)); $extension .= $extdata; - if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) { - $extension .= pack("n", $key); - $extension .= pack("n", length($extdata)); - $extension .= $extdata; - } return $extension; } @@ -151,6 +146,8 @@ sub set_message_contents foreach my $key (keys %{$self->extension_data}) { next if ($key == TLSProxy::Message::EXT_PSK); $extensions .= $self->extension_contents($key); + #Add extension twice if we are duplicating that extension + $extensions .= $self->extension_contents($key) if ($key == $self->dupext); } #PSK extension always goes last... if (defined ${$self->extension_data}{TLSProxy::Message::EXT_PSK}) { diff --git a/util/perl/TLSProxy/EncryptedExtensions.pm b/util/perl/TLSProxy/EncryptedExtensions.pm index f56f3c42..4fd445b4 100644 --- a/util/perl/TLSProxy/EncryptedExtensions.pm +++ b/util/perl/TLSProxy/EncryptedExtensions.pm @@ -81,11 +81,6 @@ sub set_message_contents $extensions .= pack("n", $key); $extensions .= pack("n", length($extdata)); $extensions .= $extdata; - if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) { - $extensions .= pack("n", $key); - $extensions .= pack("n", length($extdata)); - $extensions .= $extdata; - } } $data = pack('n', length($extensions)); diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index 642afb58..71803698 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -86,10 +86,7 @@ use constant { EXT_SIG_ALGS_CERT => 50, EXT_RENEGOTIATE => 65281, EXT_NPN => 13172, - # This extension is an unofficial extension only ever written by OpenSSL - # (i.e. not read), and even then only when enabled. We use it to test - # handling of duplicate extensions. - EXT_DUPLICATE_EXTENSION => 0xfde8, + EXT_CRYPTOPRO_BUG_EXTENSION => 0xfde8, EXT_UNKNOWN => 0xfffe, #Unknown extension that should appear last EXT_FORCE_LAST => 0xffff @@ -420,7 +417,8 @@ sub new records => $records, mt => $mt, startoffset => $startoffset, - message_frag_lens => $message_frag_lens + message_frag_lens => $message_frag_lens, + dupext => -1 }; return bless $self, $class; @@ -575,6 +573,14 @@ sub encoded_length my $self = shift; return TLS_MESSAGE_HEADER_LENGTH + length($self->data); } +sub dupext +{ + my $self = shift; + if (@_) { + $self->{dupext} = shift; + } + return $self->{dupext}; +} sub successondata { my $class = shift; diff --git a/util/perl/TLSProxy/ServerHello.pm b/util/perl/TLSProxy/ServerHello.pm index 94e7ab5f..14eb813d 100644 --- a/util/perl/TLSProxy/ServerHello.pm +++ b/util/perl/TLSProxy/ServerHello.pm @@ -154,7 +154,7 @@ sub set_message_contents $extensions .= pack("n", $key); $extensions .= pack("n", length($extdata)); $extensions .= $extdata; - if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) { + if ($key == $self->dupext) { $extensions .= pack("n", $key); $extensions .= pack("n", length($extdata)); $extensions .= $extdata;