diff --git a/ACKNOWLEDGEMENTS b/ACKNOWLEDGEMENTS deleted file mode 100644 --- a/ACKNOWLEDGEMENTS +++ /dev/null @@ -1,2 +0,0 @@ -Please https://www.openssl.org/community/thanks.html for the current -acknowledgements. diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md new file mode 100644 --- /dev/null +++ b/ACKNOWLEDGEMENTS.md @@ -0,0 +1,6 @@ +Acknowlegements +=============== + +Please see our [Thanks!][] page for the current acknowledgements. + +[Thanks!]: https://www.openssl.org/community/thanks.html diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 --- a/AUTHORS +++ /dev/null @@ -1,42 +0,0 @@ -# This is the list of OpenSSL authors for copyright purposes. -# -# This does not necessarily list everyone who has contributed code, since in -# some cases, their employer may be the copyright holder. To see the full list -# of contributors, see the revision history in source control. -OpenSSL Software Services, Inc. -OpenSSL Software Foundation, Inc. - -# Individuals -Andy Polyakov -Ben Laurie -Ben Kaduk -Bernd Edlinger -Bodo Möller -David Benjamin -David von Oheimb -Dmitry Belyavskiy (Дмитрий Белявский) -Emilia Käsper -Eric Young -Geoff Thorpe -Holger Reif -Kurt Roeckx -Lutz Jänicke -Mark J. Cox -Matt Caswell -Matthias St. Pierre -Nicola Tuveri -Nils Larsch -Patrick Steuer -Paul Dale -Paul C. Sutton -Paul Yang -Ralf S. Engelschall -Rich Salz -Richard Levitte -Shane Lontis -Stephen Henson -Steve Marquess -Tim Hudson -Tomáš Mráz -Ulf Möller -Viktor Dukhovni diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,51 @@ +Authors +======= + +This is the list of OpenSSL authors for copyright purposes. +It does not necessarily list everyone who has contributed code, +since in some cases, their employer may be the copyright holder. +To see the full list of contributors, see the revision history in +source control. + +Groups +------ + + * OpenSSL Software Services, Inc. + * OpenSSL Software Foundation, Inc. + +Individuals +----------- + + * Andy Polyakov + * Ben Laurie + * Ben Kaduk + * Bernd Edlinger + * Bodo Möller + * David Benjamin + * David von Oheimb + * Dmitry Belyavskiy (Дмитрий Белявский) + * Emilia Käsper + * Eric Young + * Geoff Thorpe + * Holger Reif + * Kurt Roeckx + * Lutz Jänicke + * Mark J. Cox + * Matt Caswell + * Matthias St. Pierre + * Nicola Tuveri + * Nils Larsch + * Patrick Steuer + * Paul Dale + * Paul C. Sutton + * Paul Yang + * Ralf S. Engelschall + * Rich Salz + * Richard Levitte + * Shane Lontis + * Stephen Henson + * Steve Marquess + * Tim Hudson + * Tomáš Mráz + * Ulf Möller + * Viktor Dukhovni diff --git a/CHANGES b/CHANGES deleted file mode 100644 --- a/CHANGES +++ /dev/null @@ -1,13899 +0,0 @@ - - OpenSSL CHANGES - _______________ - - This is a high-level summary of the most important changes. - For a full list of changes, see the git commit log; for example, - https://github.com/openssl/openssl/commits/ and pick the appropriate - release branch. - - Changes between 1.1.1s and 1.1.1t [7 Feb 2023] - - *) Fixed X.400 address type confusion in X.509 GeneralName. - - There is a type confusion vulnerability relating to X.400 address processing - inside an X.509 GeneralName. X.400 addresses were parsed as an ASN1_STRING - but subsequently interpreted by GENERAL_NAME_cmp as an ASN1_TYPE. This - vulnerability may allow an attacker who can provide a certificate chain and - CRL (neither of which need have a valid signature) to pass arbitrary - pointers to a memcmp call, creating a possible read primitive, subject to - some constraints. Refer to the advisory for more information. Thanks to - David Benjamin for discovering this issue. (CVE-2023-0286) - - This issue has been fixed by changing the public header file definition of - GENERAL_NAME so that x400Address reflects the implementation. It was not - possible for any existing application to successfully use the existing - definition; however, if any application references the x400Address field - (e.g. in dead code), note that the type of this field has changed. There is - no ABI change. - [Hugo Landau] - - *) Fixed Use-after-free following BIO_new_NDEF. - - The public API function BIO_new_NDEF is a helper function used for - streaming ASN.1 data via a BIO. It is primarily used internally to OpenSSL - to support the SMIME, CMS and PKCS7 streaming capabilities, but may also - be called directly by end user applications. - - The function receives a BIO from the caller, prepends a new BIO_f_asn1 - filter BIO onto the front of it to form a BIO chain, and then returns - the new head of the BIO chain to the caller. Under certain conditions, - for example if a CMS recipient public key is invalid, the new filter BIO - is freed and the function returns a NULL result indicating a failure. - However, in this case, the BIO chain is not properly cleaned up and the - BIO passed by the caller still retains internal pointers to the previously - freed filter BIO. If the caller then goes on to call BIO_pop() on the BIO - then a use-after-free will occur. This will most likely result in a crash. - (CVE-2023-0215) - [Viktor Dukhovni, Matt Caswell] - - *) Fixed Double free after calling PEM_read_bio_ex. - - The function PEM_read_bio_ex() reads a PEM file from a BIO and parses and - decodes the "name" (e.g. "CERTIFICATE"), any header data and the payload - data. If the function succeeds then the "name_out", "header" and "data" - arguments are populated with pointers to buffers containing the relevant - decoded data. The caller is responsible for freeing those buffers. It is - possible to construct a PEM file that results in 0 bytes of payload data. - In this case PEM_read_bio_ex() will return a failure code but will populate - the header argument with a pointer to a buffer that has already been freed. - If the caller also frees this buffer then a double free will occur. This - will most likely lead to a crash. - - The functions PEM_read_bio() and PEM_read() are simple wrappers around - PEM_read_bio_ex() and therefore these functions are also directly affected. - - These functions are also called indirectly by a number of other OpenSSL - functions including PEM_X509_INFO_read_bio_ex() and - SSL_CTX_use_serverinfo_file() which are also vulnerable. Some OpenSSL - internal uses of these functions are not vulnerable because the caller does - not free the header argument if PEM_read_bio_ex() returns a failure code. - (CVE-2022-4450) - [Kurt Roeckx, Matt Caswell] - - *) Fixed Timing Oracle in RSA Decryption. - - A timing based side channel exists in the OpenSSL RSA Decryption - implementation which could be sufficient to recover a plaintext across - a network in a Bleichenbacher style attack. To achieve a successful - decryption an attacker would have to be able to send a very large number - of trial messages for decryption. The vulnerability affects all RSA padding - modes: PKCS#1 v1.5, RSA-OEAP and RSASVE. - (CVE-2022-4304) - [Dmitry Belyavsky, Hubert Kario] - - Changes between 1.1.1r and 1.1.1s [1 Nov 2022] - - *) Fixed a regression introduced in 1.1.1r version not refreshing the - certificate data to be signed before signing the certificate. - [Gibeom Gwon] - - Changes between 1.1.1q and 1.1.1r [11 Oct 2022] - - *) Fixed the linux-mips64 Configure target which was missing the - SIXTY_FOUR_BIT bn_ops flag. This was causing heap corruption on that - platform. - [Adam Joseph] - - *) Fixed a strict aliasing problem in bn_nist. Clang-14 optimisation was - causing incorrect results in some cases as a result. - [Paul Dale] - - *) Fixed SSL_pending() and SSL_has_pending() with DTLS which were failing to - report correct results in some cases - [Matt Caswell] - - *) Fixed a regression introduced in 1.1.1o for re-signing certificates with - different key sizes - [Todd Short] - - *) Added the loongarch64 target - [Shi Pujin] - - *) Fixed a DRBG seed propagation thread safety issue - [Bernd Edlinger] - - *) Fixed a memory leak in tls13_generate_secret - [Bernd Edlinger] - - *) Fixed reported performance degradation on aarch64. Restored the - implementation prior to commit 2621751 ("aes/asm/aesv8-armx.pl: avoid - 32-bit lane assignment in CTR mode") for 64bit targets only, since it is - reportedly 2-17% slower and the silicon errata only affects 32bit targets. - The new algorithm is still used for 32 bit targets. - [Bernd Edlinger] - - *) Added a missing header for memcmp that caused compilation failure on some - platforms - [Gregor Jasny] - - Changes between 1.1.1p and 1.1.1q [5 Jul 2022] - - *) AES OCB mode for 32-bit x86 platforms using the AES-NI assembly optimised - implementation would not encrypt the entirety of the data under some - circumstances. This could reveal sixteen bytes of data that was - preexisting in the memory that wasn't written. In the special case of - "in place" encryption, sixteen bytes of the plaintext would be revealed. - - Since OpenSSL does not support OCB based cipher suites for TLS and DTLS, - they are both unaffected. - (CVE-2022-2097) - [Alex Chernyakhovsky, David Benjamin, Alejandro Sedeño] - - Changes between 1.1.1o and 1.1.1p [21 Jun 2022] - - *) In addition to the c_rehash shell command injection identified in - CVE-2022-1292, further bugs where the c_rehash script does not - properly sanitise shell metacharacters to prevent command injection have been - fixed. - - When the CVE-2022-1292 was fixed it was not discovered that there - are other places in the script where the file names of certificates - being hashed were possibly passed to a command executed through the shell. - - This script is distributed by some operating systems in a manner where - it is automatically executed. On such operating systems, an attacker - could execute arbitrary commands with the privileges of the script. - - Use of the c_rehash script is considered obsolete and should be replaced - by the OpenSSL rehash command line tool. - (CVE-2022-2068) - [Daniel Fiala, Tomáš Mráz] - - *) When OpenSSL TLS client is connecting without any supported elliptic - curves and TLS-1.3 protocol is disabled the connection will no longer fail - if a ciphersuite that does not use a key exchange based on elliptic - curves can be negotiated. - [Tomáš Mráz] - - Changes between 1.1.1n and 1.1.1o [3 May 2022] - - *) Fixed a bug in the c_rehash script which was not properly sanitising shell - metacharacters to prevent command injection. This script is distributed - by some operating systems in a manner where it is automatically executed. - On such operating systems, an attacker could execute arbitrary commands - with the privileges of the script. - - Use of the c_rehash script is considered obsolete and should be replaced - by the OpenSSL rehash command line tool. - (CVE-2022-1292) - [Tomáš Mráz] - - Changes between 1.1.1m and 1.1.1n [15 Mar 2022] - - *) Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever - for non-prime moduli. - - Internally this function is used when parsing certificates that contain - elliptic curve public keys in compressed form or explicit elliptic curve - parameters with a base point encoded in compressed form. - - It is possible to trigger the infinite loop by crafting a certificate that - has invalid explicit curve parameters. - - Since certificate parsing happens prior to verification of the certificate - signature, any process that parses an externally supplied certificate may - thus be subject to a denial of service attack. The infinite loop can also - be reached when parsing crafted private keys as they can contain explicit - elliptic curve parameters. - - Thus vulnerable situations include: - - - TLS clients consuming server certificates - - TLS servers consuming client certificates - - Hosting providers taking certificates or private keys from customers - - Certificate authorities parsing certification requests from subscribers - - Anything else which parses ASN.1 elliptic curve parameters - - Also any other applications that use the BN_mod_sqrt() where the attacker - can control the parameter values are vulnerable to this DoS issue. - (CVE-2022-0778) - [Tomáš Mráz] - - *) Add ciphersuites based on DHE_PSK (RFC 4279) and ECDHE_PSK (RFC 5489) - to the list of ciphersuites providing Perfect Forward Secrecy as - required by SECLEVEL >= 3. - - [Dmitry Belyavskiy, Nicola Tuveri] - - Changes between 1.1.1l and 1.1.1m [14 Dec 2021] - - *) Avoid loading of a dynamic engine twice. - - [Bernd Edlinger] - - *) Fixed building on Debian with kfreebsd kernels - - [Mattias Ellert] - - *) Prioritise DANE TLSA issuer certs over peer certs - - [Viktor Dukhovni] - - *) Fixed random API for MacOS prior to 10.12 - - These MacOS versions don't support the CommonCrypto APIs - - [Lenny Primak] - - Changes between 1.1.1k and 1.1.1l [24 Aug 2021] - - *) Fixed an SM2 Decryption Buffer Overflow. - - In order to decrypt SM2 encrypted data an application is expected to call the - API function EVP_PKEY_decrypt(). Typically an application will call this - function twice. The first time, on entry, the "out" parameter can be NULL and, - on exit, the "outlen" parameter is populated with the buffer size required to - hold the decrypted plaintext. The application can then allocate a sufficiently - sized buffer and call EVP_PKEY_decrypt() again, but this time passing a non-NULL - value for the "out" parameter. - - A bug in the implementation of the SM2 decryption code means that the - calculation of the buffer size required to hold the plaintext returned by the - first call to EVP_PKEY_decrypt() can be smaller than the actual size required by - the second call. This can lead to a buffer overflow when EVP_PKEY_decrypt() is - called by the application a second time with a buffer that is too small. - - A malicious attacker who is able present SM2 content for decryption to an - application could cause attacker chosen data to overflow the buffer by up to a - maximum of 62 bytes altering the contents of other data held after the - buffer, possibly changing application behaviour or causing the application to - crash. The location of the buffer is application dependent but is typically - heap allocated. - (CVE-2021-3711) - [Matt Caswell] - - *) Fixed various read buffer overruns processing ASN.1 strings - - ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING - structure which contains a buffer holding the string data and a field holding - the buffer length. This contrasts with normal C strings which are repesented as - a buffer for the string data which is terminated with a NUL (0) byte. - - Although not a strict requirement, ASN.1 strings that are parsed using OpenSSL's - own "d2i" functions (and other similar parsing functions) as well as any string - whose value has been set with the ASN1_STRING_set() function will additionally - NUL terminate the byte array in the ASN1_STRING structure. - - However, it is possible for applications to directly construct valid ASN1_STRING - structures which do not NUL terminate the byte array by directly setting the - "data" and "length" fields in the ASN1_STRING array. This can also happen by - using the ASN1_STRING_set0() function. - - Numerous OpenSSL functions that print ASN.1 data have been found to assume that - the ASN1_STRING byte array will be NUL terminated, even though this is not - guaranteed for strings that have been directly constructed. Where an application - requests an ASN.1 structure to be printed, and where that ASN.1 structure - contains ASN1_STRINGs that have been directly constructed by the application - without NUL terminating the "data" field, then a read buffer overrun can occur. - - The same thing can also occur during name constraints processing of certificates - (for example if a certificate has been directly constructed by the application - instead of loading it via the OpenSSL parsing functions, and the certificate - contains non NUL terminated ASN1_STRING structures). It can also occur in the - X509_get1_email(), X509_REQ_get1_email() and X509_get1_ocsp() functions. - - If a malicious actor can cause an application to directly construct an - ASN1_STRING and then process it through one of the affected OpenSSL functions - then this issue could be hit. This might result in a crash (causing a Denial of - Service attack). It could also result in the disclosure of private memory - contents (such as private keys, or sensitive plaintext). - (CVE-2021-3712) - [Matt Caswell] - - Changes between 1.1.1j and 1.1.1k [25 Mar 2021] - - *) Fixed a problem with verifying a certificate chain when using the - X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks - of the certificates present in a certificate chain. It is not set by - default. - - Starting from OpenSSL version 1.1.1h a check to disallow certificates in - the chain that have explicitly encoded elliptic curve parameters was added - as an additional strict check. - - An error in the implementation of this check meant that the result of a - previous check to confirm that certificates in the chain are valid CA - certificates was overwritten. This effectively bypasses the check - that non-CA certificates must not be able to issue other certificates. - - If a "purpose" has been configured then there is a subsequent opportunity - for checks that the certificate is a valid CA. All of the named "purpose" - values implemented in libcrypto perform this check. Therefore, where - a purpose is set the certificate chain will still be rejected even when the - strict flag has been used. A purpose is set by default in libssl client and - server certificate verification routines, but it can be overridden or - removed by an application. - - In order to be affected, an application must explicitly set the - X509_V_FLAG_X509_STRICT verification flag and either not set a purpose - for the certificate verification or, in the case of TLS client or server - applications, override the default purpose. - (CVE-2021-3450) - [Tomáš Mráz] - - *) Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously - crafted renegotiation ClientHello message from a client. If a TLSv1.2 - renegotiation ClientHello omits the signature_algorithms extension (where - it was present in the initial ClientHello), but includes a - signature_algorithms_cert extension then a NULL pointer dereference will - result, leading to a crash and a denial of service attack. - - A server is only vulnerable if it has TLSv1.2 and renegotiation enabled - (which is the default configuration). OpenSSL TLS clients are not impacted - by this issue. - (CVE-2021-3449) - [Peter Kästle and Samuel Sapalski] - - Changes between 1.1.1i and 1.1.1j [16 Feb 2021] - - *) Fixed the X509_issuer_and_serial_hash() function. It attempts to - create a unique hash value based on the issuer and serial number data - contained within an X509 certificate. However it was failing to correctly - handle any errors that may occur while parsing the issuer field (which might - occur if the issuer field is maliciously constructed). This may subsequently - result in a NULL pointer deref and a crash leading to a potential denial of - service attack. - (CVE-2021-23841) - [Matt Caswell] - - *) Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING - padding mode to correctly check for rollback attacks. This is considered a - bug in OpenSSL 1.1.1 because it does not support SSLv2. In 1.0.2 this is - CVE-2021-23839. - [Matt Caswell] - - *) Fixed the EVP_CipherUpdate, EVP_EncryptUpdate and EVP_DecryptUpdate - functions. Previously they could overflow the output length argument in some - cases where the input length is close to the maximum permissable length for - an integer on the platform. In such cases the return value from the function - call would be 1 (indicating success), but the output length value would be - negative. This could cause applications to behave incorrectly or crash. - (CVE-2021-23840) - [Matt Caswell] - - *) Fixed SRP_Calc_client_key so that it runs in constant time. The previous - implementation called BN_mod_exp without setting BN_FLG_CONSTTIME. This - could be exploited in a side channel attack to recover the password. Since - the attack is local host only this is outside of the current OpenSSL - threat model and therefore no CVE is assigned. - - Thanks to Mohammed Sabt and Daniel De Almeida Braga for reporting this - issue. - [Matt Caswell] - - Changes between 1.1.1h and 1.1.1i [8 Dec 2020] - - *) Fixed NULL pointer deref in the GENERAL_NAME_cmp function - This function could crash if both GENERAL_NAMEs contain an EDIPARTYNAME. - If an attacker can control both items being compared then this could lead - to a possible denial of service attack. OpenSSL itself uses the - GENERAL_NAME_cmp function for two purposes: - 1) Comparing CRL distribution point names between an available CRL and a - CRL distribution point embedded in an X509 certificate - 2) When verifying that a timestamp response token signer matches the - timestamp authority name (exposed via the API functions - TS_RESP_verify_response and TS_RESP_verify_token) - (CVE-2020-1971) - [Matt Caswell] - - *) Add support for Apple Silicon M1 Macs with the darwin64-arm64-cc target. - [Stuart Carnie] - - *) The security callback, which can be customised by application code, supports - the security operation SSL_SECOP_TMP_DH. This is defined to take an EVP_PKEY - in the "other" parameter. In most places this is what is passed. All these - places occur server side. However there was one client side call of this - security operation and it passed a DH object instead. This is incorrect - according to the definition of SSL_SECOP_TMP_DH, and is inconsistent with all - of the other locations. Therefore this client side call has been changed to - pass an EVP_PKEY instead. - [Matt Caswell] - - *) In 1.1.1h, an expired trusted (root) certificate was not anymore rejected - when validating a certificate path. This check is restored in 1.1.1i. - [David von Oheimb] - - Changes between 1.1.1g and 1.1.1h [22 Sep 2020] - - *) Certificates with explicit curve parameters are now disallowed in - verification chains if the X509_V_FLAG_X509_STRICT flag is used. - [Tomas Mraz] - - *) The 'MinProtocol' and 'MaxProtocol' configuration commands now silently - ignore TLS protocol version bounds when configuring DTLS-based contexts, and - conversely, silently ignore DTLS protocol version bounds when configuring - TLS-based contexts. The commands can be repeated to set bounds of both - types. The same applies with the corresponding "min_protocol" and - "max_protocol" command-line switches, in case some application uses both TLS - and DTLS. - - SSL_CTX instances that are created for a fixed protocol version (e.g. - TLSv1_server_method()) also silently ignore version bounds. Previously - attempts to apply bounds to these protocol versions would result in an - error. Now only the "version-flexible" SSL_CTX instances are subject to - limits in configuration files in command-line options. - [Viktor Dukhovni] - - *) Handshake now fails if Extended Master Secret extension is dropped - on renegotiation. - [Tomas Mraz] - - *) Accidentally, an expired trusted (root) certificate is not anymore rejected - when validating a certificate path. - [David von Oheimb] - - *) The Oracle Developer Studio compiler will start reporting deprecated APIs - - Changes between 1.1.1f and 1.1.1g [21 Apr 2020] - - *) Fixed segmentation fault in SSL_check_chain() - Server or client applications that call the SSL_check_chain() function - during or after a TLS 1.3 handshake may crash due to a NULL pointer - dereference as a result of incorrect handling of the - "signature_algorithms_cert" TLS extension. The crash occurs if an invalid - or unrecognised signature algorithm is received from the peer. This could - be exploited by a malicious peer in a Denial of Service attack. - (CVE-2020-1967) - [Benjamin Kaduk] - - *) Added AES consttime code for no-asm configurations - an optional constant time support for AES was added - when building openssl for no-asm. - Enable with: ./config no-asm -DOPENSSL_AES_CONST_TIME - Disable with: ./config no-asm -DOPENSSL_NO_AES_CONST_TIME - At this time this feature is by default disabled. - It will be enabled by default in 3.0. - [Bernd Edlinger] - - Changes between 1.1.1e and 1.1.1f [31 Mar 2020] - - *) Revert the change of EOF detection while reading in libssl to avoid - regressions in applications depending on the current way of reporting - the EOF. As the existing method is not fully accurate the change to - reporting the EOF via SSL_ERROR_SSL is kept on the current development - branch and will be present in the 3.0 release. - [Tomas Mraz] - - *) Revised BN_generate_prime_ex to not avoid factors 3..17863 in p-1 - when primes for RSA keys are computed. - Since we previously always generated primes == 2 (mod 3) for RSA keys, - the 2-prime and 3-prime RSA modules were easy to distinguish, since - N = p*q = 1 (mod 3), but N = p*q*r = 2 (mod 3). Therefore fingerprinting - 2-prime vs. 3-prime RSA keys was possible by computing N mod 3. - This avoids possible fingerprinting of newly generated RSA modules. - [Bernd Edlinger] - - Changes between 1.1.1d and 1.1.1e [17 Mar 2020] - *) Properly detect EOF while reading in libssl. Previously if we hit an EOF - while reading in libssl then we would report an error back to the - application (SSL_ERROR_SYSCALL) but errno would be 0. We now add - an error to the stack (which means we instead return SSL_ERROR_SSL) and - therefore give a hint as to what went wrong. - [Matt Caswell] - - *) Check that ed25519 and ed448 are allowed by the security level. Previously - signature algorithms not using an MD were not being checked that they were - allowed by the security level. - [Kurt Roeckx] - - *) Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() - was not quite right. The behaviour was not consistent between resumption - and normal handshakes, and also not quite consistent with historical - behaviour. The behaviour in various scenarios has been clarified and - it has been updated to make it match historical behaviour as closely as - possible. - [Matt Caswell] - - *) [VMS only] The header files that the VMS compilers include automatically, - __DECC_INCLUDE_PROLOGUE.H and __DECC_INCLUDE_EPILOGUE.H, use pragmas that - the C++ compiler doesn't understand. This is a shortcoming in the - compiler, but can be worked around with __cplusplus guards. - - C++ applications that use OpenSSL libraries must be compiled using the - qualifier '/NAMES=(AS_IS,SHORTENED)' to be able to use all the OpenSSL - functions. Otherwise, only functions with symbols of less than 31 - characters can be used, as the linker will not be able to successfully - resolve symbols with longer names. - [Richard Levitte] - - *) Corrected the documentation of the return values from the EVP_DigestSign* - set of functions. The documentation mentioned negative values for some - errors, but this was never the case, so the mention of negative values - was removed. - - Code that followed the documentation and thereby check with something - like 'EVP_DigestSignInit(...) <= 0' will continue to work undisturbed. - [Richard Levitte] - - *) Fixed an an overflow bug in the x64_64 Montgomery squaring procedure - used in exponentiation with 512-bit moduli. No EC algorithms are - affected. Analysis suggests that attacks against 2-prime RSA1024, - 3-prime RSA1536, and DSA1024 as a result of this defect would be very - difficult to perform and are not believed likely. Attacks against DH512 - are considered just feasible. However, for an attack the target would - have to re-use the DH512 private key, which is not recommended anyway. - Also applications directly using the low level API BN_mod_exp may be - affected if they use BN_FLG_CONSTTIME. - (CVE-2019-1551) - [Andy Polyakov] - - *) Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. - The presence of this system service is determined at run-time. - [Richard Levitte] - - *) Added newline escaping functionality to a filename when using openssl dgst. - This output format is to replicate the output format found in the '*sum' - checksum programs. This aims to preserve backward compatibility. - [Matt Eaton, Richard Levitte, and Paul Dale] - - *) Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just - the first value. - [Jon Spillett] - - Changes between 1.1.1c and 1.1.1d [10 Sep 2019] - - *) Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random - number generator (RNG). This was intended to include protection in the - event of a fork() system call in order to ensure that the parent and child - processes did not share the same RNG state. However this protection was not - being used in the default case. - - A partial mitigation for this issue is that the output from a high - precision timer is mixed into the RNG state so the likelihood of a parent - and child process sharing state is significantly reduced. - - If an application already calls OPENSSL_init_crypto() explicitly using - OPENSSL_INIT_ATFORK then this problem does not occur at all. - (CVE-2019-1549) - [Matthias St. Pierre] - - *) For built-in EC curves, ensure an EC_GROUP built from the curve name is - used even when parsing explicit parameters, when loading a serialized key - or calling `EC_GROUP_new_from_ecpkparameters()`/ - `EC_GROUP_new_from_ecparameters()`. - This prevents bypass of security hardening and performance gains, - especially for curves with specialized EC_METHODs. - By default, if a key encoded with explicit parameters is loaded and later - serialized, the output is still encoded with explicit parameters, even if - internally a "named" EC_GROUP is used for computation. - [Nicola Tuveri] - - *) Compute ECC cofactors if not provided during EC_GROUP construction. Before - this change, EC_GROUP_set_generator would accept order and/or cofactor as - NULL. After this change, only the cofactor parameter can be NULL. It also - does some minimal sanity checks on the passed order. - (CVE-2019-1547) - [Billy Bob Brumley] - - *) Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey. - An attack is simple, if the first CMS_recipientInfo is valid but the - second CMS_recipientInfo is chosen ciphertext. If the second - recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct - encryption key will be replaced by garbage, and the message cannot be - decoded, but if the RSA decryption fails, the correct encryption key is - used and the recipient will not notice the attack. - As a work around for this potential attack the length of the decrypted - key must be equal to the cipher default key length, in case the - certifiate is not given and all recipientInfo are tried out. - The old behaviour can be re-enabled in the CMS code by setting the - CMS_DEBUG_DECRYPT flag. - (CVE-2019-1563) - [Bernd Edlinger] - - *) Early start up entropy quality from the DEVRANDOM seed source has been - improved for older Linux systems. The RAND subsystem will wait for - /dev/random to be producing output before seeding from /dev/urandom. - The seeded state is stored for future library initialisations using - a system global shared memory segment. The shared memory identifier - can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to - the desired value. The default identifier is 114. - [Paul Dale] - - *) Correct the extended master secret constant on EBCDIC systems. Without this - fix TLS connections between an EBCDIC system and a non-EBCDIC system that - negotiate EMS will fail. Unfortunately this also means that TLS connections - between EBCDIC systems with this fix, and EBCDIC systems without this - fix will fail if they negotiate EMS. - [Matt Caswell] - - *) Use Windows installation paths in the mingw builds - - Mingw isn't a POSIX environment per se, which means that Windows - paths should be used for installation. - (CVE-2019-1552) - [Richard Levitte] - - *) Changed DH_check to accept parameters with order q and 2q subgroups. - With order 2q subgroups the bit 0 of the private key is not secret - but DH_generate_key works around that by clearing bit 0 of the - private key for those. This avoids leaking bit 0 of the private key. - [Bernd Edlinger] - - *) Significantly reduce secure memory usage by the randomness pools. - [Paul Dale] - - *) Revert the DEVRANDOM_WAIT feature for Linux systems - - The DEVRANDOM_WAIT feature added a select() call to wait for the - /dev/random device to become readable before reading from the - /dev/urandom device. - - It turned out that this change had negative side effects on - performance which were not acceptable. After some discussion it - was decided to revert this feature and leave it up to the OS - resp. the platform maintainer to ensure a proper initialization - during early boot time. - [Matthias St. Pierre] - - Changes between 1.1.1b and 1.1.1c [28 May 2019] - - *) Add build tests for C++. These are generated files that only do one - thing, to include one public OpenSSL head file each. This tests that - the public header files can be usefully included in a C++ application. - - This test isn't enabled by default. It can be enabled with the option - 'enable-buildtest-c++'. - [Richard Levitte] - - *) Enable SHA3 pre-hashing for ECDSA and DSA. - [Patrick Steuer] - - *) Change the default RSA, DSA and DH size to 2048 bit instead of 1024. - This changes the size when using the genpkey app when no size is given. It - fixes an omission in earlier changes that changed all RSA, DSA and DH - generation apps to use 2048 bits by default. - [Kurt Roeckx] - - *) Reorganize the manual pages to consistently have RETURN VALUES, - EXAMPLES, SEE ALSO and HISTORY come in that order, and adjust - util/fix-doc-nits accordingly. - [Paul Yang, Joshua Lock] - - *) Add the missing accessor EVP_PKEY_get0_engine() - [Matt Caswell] - - *) Have apps like 's_client' and 's_server' output the signature scheme - along with other cipher suite parameters when debugging. - [Lorinczy Zsigmond] - - *) Make OPENSSL_config() error agnostic again. - [Richard Levitte] - - *) Do the error handling in RSA decryption constant time. - [Bernd Edlinger] - - *) Prevent over long nonces in ChaCha20-Poly1305. - - ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input - for every encryption operation. RFC 7539 specifies that the nonce value - (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length - and front pads the nonce with 0 bytes if it is less than 12 - bytes. However it also incorrectly allows a nonce to be set of up to 16 - bytes. In this case only the last 12 bytes are significant and any - additional leading bytes are ignored. - - It is a requirement of using this cipher that nonce values are - unique. Messages encrypted using a reused nonce value are susceptible to - serious confidentiality and integrity attacks. If an application changes - the default nonce length to be longer than 12 bytes and then makes a - change to the leading bytes of the nonce expecting the new value to be a - new unique nonce then such an application could inadvertently encrypt - messages with a reused nonce. - - Additionally the ignored bytes in a long nonce are not covered by the - integrity guarantee of this cipher. Any application that relies on the - integrity of these ignored leading bytes of a long nonce may be further - affected. Any OpenSSL internal use of this cipher, including in SSL/TLS, - is safe because no such use sets such a long nonce value. However user - applications that use this cipher directly and set a non-default nonce - length to be longer than 12 bytes may be vulnerable. - - This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk - Greef of Ronomon. - (CVE-2019-1543) - [Matt Caswell] - - *) Add DEVRANDOM_WAIT feature for Linux systems - - On older Linux systems where the getrandom() system call is not available, - OpenSSL normally uses the /dev/urandom device for seeding its CSPRNG. - Contrary to getrandom(), the /dev/urandom device will not block during - early boot when the kernel CSPRNG has not been seeded yet. - - To mitigate this known weakness, use select() to wait for /dev/random to - become readable before reading from /dev/urandom. - - *) Ensure that SM2 only uses SM3 as digest algorithm - [Paul Yang] - - Changes between 1.1.1a and 1.1.1b [26 Feb 2019] - - *) Added SCA hardening for modular field inversion in EC_GROUP through - a new dedicated field_inv() pointer in EC_METHOD. - This also addresses a leakage affecting conversions from projective - to affine coordinates. - [Billy Bob Brumley, Nicola Tuveri] - - *) Change the info callback signals for the start and end of a post-handshake - message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START - and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get - confused by this and assume that a TLSv1.2 renegotiation has started. This - can break KeyUpdate handling. Instead we no longer signal the start and end - of a post handshake message exchange (although the messages themselves are - still signalled). This could break some applications that were expecting - the old signals. However without this KeyUpdate is not usable for many - applications. - [Matt Caswell] - - *) Fix a bug in the computation of the endpoint-pair shared secret used - by DTLS over SCTP. This breaks interoperability with older versions - of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime - switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling - interoperability with such broken implementations. However, enabling - this switch breaks interoperability with correct implementations. - - *) Fix a use after free bug in d2i_X509_PUBKEY when overwriting a - re-used X509_PUBKEY object if the second PUBKEY is malformed. - [Bernd Edlinger] - - *) Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0(). - [Richard Levitte] - - *) Remove the 'dist' target and add a tarball building script. The - 'dist' target has fallen out of use, and it shouldn't be - necessary to configure just to create a source distribution. - [Richard Levitte] - - Changes between 1.1.1 and 1.1.1a [20 Nov 2018] - - *) Timing vulnerability in DSA signature generation - - The OpenSSL DSA signature algorithm has been shown to be vulnerable to a - timing side channel attack. An attacker could use variations in the signing - algorithm to recover the private key. - - This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser. - (CVE-2018-0734) - [Paul Dale] - - *) Timing vulnerability in ECDSA signature generation - - The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a - timing side channel attack. An attacker could use variations in the signing - algorithm to recover the private key. - - This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser. - (CVE-2018-0735) - [Paul Dale] - - *) Added EVP_PKEY_ECDH_KDF_X9_63 and ecdh_KDF_X9_63() as replacements for - the EVP_PKEY_ECDH_KDF_X9_62 KDF type and ECDH_KDF_X9_62(). The old names - are retained for backwards compatibility. - [Antoine Salon] - - *) Fixed the issue that RAND_add()/RAND_seed() silently discards random input - if its length exceeds 4096 bytes. The limit has been raised to a buffer size - of two gigabytes and the error handling improved. - - This issue was reported to OpenSSL by Dr. Falko Strenzke. It has been - categorized as a normal bug, not a security issue, because the DRBG reseeds - automatically and is fully functional even without additional randomness - provided by the application. - - Changes between 1.1.0i and 1.1.1 [11 Sep 2018] - - *) Add a new ClientHello callback. Provides a callback interface that gives - the application the ability to adjust the nascent SSL object at the - earliest stage of ClientHello processing, immediately after extensions have - been collected but before they have been processed. In particular, this - callback can adjust the supported TLS versions in response to the contents - of the ClientHello - [Benjamin Kaduk] - - *) Add SM2 base algorithm support. - [Jack Lloyd] - - *) s390x assembly pack: add (improved) hardware-support for the following - cryptographic primitives: sha3, shake, aes-gcm, aes-ccm, aes-ctr, aes-ofb, - aes-cfb/cfb8, aes-ecb. - [Patrick Steuer] - - *) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str - parameter is no longer accepted, as it leads to a corrupt table. NULL - pem_str is reserved for alias entries only. - [Richard Levitte] - - *) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder - step for prime curves. The new implementation is based on formulae from - differential addition-and-doubling in homogeneous projective coordinates - from Izu-Takagi "A fast parallel elliptic curve multiplication resistant - against side channel attacks" and Brier-Joye "Weierstrass Elliptic Curves - and Side-Channel Attacks" Eq. (8) for y-coordinate recovery, modified - to work in projective coordinates. - [Billy Bob Brumley, Nicola Tuveri] - - *) Change generating and checking of primes so that the error rate of not - being prime depends on the intended use based on the size of the input. - For larger primes this will result in more rounds of Miller-Rabin. - The maximal error rate for primes with more than 1080 bits is lowered - to 2^-128. - [Kurt Roeckx, Annie Yousar] - - *) Increase the number of Miller-Rabin rounds for DSA key generating to 64. - [Kurt Roeckx] - - *) The 'tsget' script is renamed to 'tsget.pl', to avoid confusion when - moving between systems, and to avoid confusion when a Windows build is - done with mingw vs with MSVC. For POSIX installs, there's still a - symlink or copy named 'tsget' to avoid that confusion as well. - [Richard Levitte] - - *) Revert blinding in ECDSA sign and instead make problematic addition - length-invariant. Switch even to fixed-length Montgomery multiplication. - [Andy Polyakov] - - *) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder - step for binary curves. The new implementation is based on formulae from - differential addition-and-doubling in mixed Lopez-Dahab projective - coordinates, modified to independently blind the operands. - [Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri] - - *) Add a scaffold to optionally enhance the Montgomery ladder implementation - for `ec_scalar_mul_ladder` (formerly `ec_mul_consttime`) allowing - EC_METHODs to implement their own specialized "ladder step", to take - advantage of more favorable coordinate systems or more efficient - differential addition-and-doubling algorithms. - [Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri] - - *) Modified the random device based seed sources to keep the relevant - file descriptors open rather than reopening them on each access. - This allows such sources to operate in a chroot() jail without - the associated device nodes being available. This behaviour can be - controlled using RAND_keep_random_devices_open(). - [Paul Dale] - - *) Numerous side-channel attack mitigations have been applied. This may have - performance impacts for some algorithms for the benefit of improved - security. Specific changes are noted in this change log by their respective - authors. - [Matt Caswell] - - *) AIX shared library support overhaul. Switch to AIX "natural" way of - handling shared libraries, which means collecting shared objects of - different versions and bitnesses in one common archive. This allows to - mitigate conflict between 1.0 and 1.1 side-by-side installations. It - doesn't affect the way 3rd party applications are linked, only how - multi-version installation is managed. - [Andy Polyakov] - - *) Make ec_group_do_inverse_ord() more robust and available to other - EC cryptosystems, so that irrespective of BN_FLG_CONSTTIME, SCA - mitigations are applied to the fallback BN_mod_inverse(). - When using this function rather than BN_mod_inverse() directly, new - EC cryptosystem implementations are then safer-by-default. - [Billy Bob Brumley] - - *) Add coordinate blinding for EC_POINT and implement projective - coordinate blinding for generic prime curves as a countermeasure to - chosen point SCA attacks. - [Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley] - - *) Add blinding to ECDSA and DSA signatures to protect against side channel - attacks discovered by Keegan Ryan (NCC Group). - [Matt Caswell] - - *) Enforce checking in the pkeyutl command line app to ensure that the input - length does not exceed the maximum supported digest length when performing - a sign, verify or verifyrecover operation. - [Matt Caswell] - - *) SSL_MODE_AUTO_RETRY is enabled by default. Applications that use blocking - I/O in combination with something like select() or poll() will hang. This - can be turned off again using SSL_CTX_clear_mode(). - Many applications do not properly handle non-application data records, and - TLS 1.3 sends more of such records. Setting SSL_MODE_AUTO_RETRY works - around the problems in those applications, but can also break some. - It's recommended to read the manpages about SSL_read(), SSL_write(), - SSL_get_error(), SSL_shutdown(), SSL_CTX_set_mode() and - SSL_CTX_set_read_ahead() again. - [Kurt Roeckx] - - *) When unlocking a pass phrase protected PEM file or PKCS#8 container, we - now allow empty (zero character) pass phrases. - [Richard Levitte] - - *) Apply blinding to binary field modular inversion and remove patent - pending (OPENSSL_SUN_GF2M_DIV) BN_GF2m_mod_div implementation. - [Billy Bob Brumley] - - *) Deprecate ec2_mult.c and unify scalar multiplication code paths for - binary and prime elliptic curves. - [Billy Bob Brumley] - - *) Remove ECDSA nonce padding: EC_POINT_mul is now responsible for - constant time fixed point multiplication. - [Billy Bob Brumley] - - *) Revise elliptic curve scalar multiplication with timing attack - defenses: ec_wNAF_mul redirects to a constant time implementation - when computing fixed point and variable point multiplication (which - in OpenSSL are mostly used with secret scalars in keygen, sign, - ECDH derive operations). - [Billy Bob Brumley, Nicola Tuveri, Cesar Pereida García, - Sohaib ul Hassan] - - *) Updated CONTRIBUTING - [Rich Salz] - - *) Updated DRBG / RAND to request nonce and additional low entropy - randomness from the system. - [Matthias St. Pierre] - - *) Updated 'openssl rehash' to use OpenSSL consistent default. - [Richard Levitte] - - *) Moved the load of the ssl_conf module to libcrypto, which helps - loading engines that libssl uses before libssl is initialised. - [Matt Caswell] - - *) Added EVP_PKEY_sign() and EVP_PKEY_verify() for EdDSA - [Matt Caswell] - - *) Fixed X509_NAME_ENTRY_set to get multi-valued RDNs right in all cases. - [Ingo Schwarze, Rich Salz] - - *) Added output of accepting IP address and port for 'openssl s_server' - [Richard Levitte] - - *) Added a new API for TLSv1.3 ciphersuites: - SSL_CTX_set_ciphersuites() - SSL_set_ciphersuites() - [Matt Caswell] - - *) Memory allocation failures consistently add an error to the error - stack. - [Rich Salz] - - *) Don't use OPENSSL_ENGINES and OPENSSL_CONF environment values - in libcrypto when run as setuid/setgid. - [Bernd Edlinger] - - *) Load any config file by default when libssl is used. - [Matt Caswell] - - *) Added new public header file and documentation - for the RAND_DRBG API. See manual page RAND_DRBG(7) for an overview. - [Matthias St. Pierre] - - *) QNX support removed (cannot find contributors to get their approval - for the license change). - [Rich Salz] - - *) TLSv1.3 replay protection for early data has been implemented. See the - SSL_read_early_data() man page for further details. - [Matt Caswell] - - *) Separated TLSv1.3 ciphersuite configuration out from TLSv1.2 ciphersuite - configuration. TLSv1.3 ciphersuites are not compatible with TLSv1.2 and - below. Similarly TLSv1.2 ciphersuites are not compatible with TLSv1.3. - In order to avoid issues where legacy TLSv1.2 ciphersuite configuration - would otherwise inadvertently disable all TLSv1.3 ciphersuites the - configuration has been separated out. See the ciphers man page or the - SSL_CTX_set_ciphersuites() man page for more information. - [Matt Caswell] - - *) On POSIX (BSD, Linux, ...) systems the ocsp(1) command running - in responder mode now supports the new "-multi" option, which - spawns the specified number of child processes to handle OCSP - requests. The "-timeout" option now also limits the OCSP - responder's patience to wait to receive the full client request - on a newly accepted connection. Child processes are respawned - as needed, and the CA index file is automatically reloaded - when changed. This makes it possible to run the "ocsp" responder - as a long-running service, making the OpenSSL CA somewhat more - feature-complete. In this mode, most diagnostic messages logged - after entering the event loop are logged via syslog(3) rather than - written to stderr. - [Viktor Dukhovni] - - *) Added support for X448 and Ed448. Heavily based on original work by - Mike Hamburg. - [Matt Caswell] - - *) Extend OSSL_STORE with capabilities to search and to narrow the set of - objects loaded. This adds the functions OSSL_STORE_expect() and - OSSL_STORE_find() as well as needed tools to construct searches and - get the search data out of them. - [Richard Levitte] - - *) Support for TLSv1.3 added. Note that users upgrading from an earlier - version of OpenSSL should review their configuration settings to ensure - that they are still appropriate for TLSv1.3. For further information see: - https://wiki.openssl.org/index.php/TLS1.3 - [Matt Caswell] - - *) Grand redesign of the OpenSSL random generator - - The default RAND method now utilizes an AES-CTR DRBG according to - NIST standard SP 800-90Ar1. The new random generator is essentially - a port of the default random generator from the OpenSSL FIPS 2.0 - object module. It is a hybrid deterministic random bit generator - using an AES-CTR bit stream and which seeds and reseeds itself - automatically using trusted system entropy sources. - - Some of its new features are: - o Support for multiple DRBG instances with seed chaining. - o The default RAND method makes use of a DRBG. - o There is a public and private DRBG instance. - o The DRBG instances are fork-safe. - o Keep all global DRBG instances on the secure heap if it is enabled. - o The public and private DRBG instance are per thread for lock free - operation - [Paul Dale, Benjamin Kaduk, Kurt Roeckx, Rich Salz, Matthias St. Pierre] - - *) Changed Configure so it only says what it does and doesn't dump - so much data. Instead, ./configdata.pm should be used as a script - to display all sorts of configuration data. - [Richard Levitte] - - *) Added processing of "make variables" to Configure. - [Richard Levitte] - - *) Added SHA512/224 and SHA512/256 algorithm support. - [Paul Dale] - - *) The last traces of Netware support, first removed in 1.1.0, have - now been removed. - [Rich Salz] - - *) Get rid of Makefile.shared, and in the process, make the processing - of certain files (rc.obj, or the .def/.map/.opt files produced from - the ordinal files) more visible and hopefully easier to trace and - debug (or make silent). - [Richard Levitte] - - *) Make it possible to have environment variable assignments as - arguments to config / Configure. - [Richard Levitte] - - *) Add multi-prime RSA (RFC 8017) support. - [Paul Yang] - - *) Add SM3 implemented according to GB/T 32905-2016 - [ Jack Lloyd , - Ronald Tse , - Erick Borsboom ] - - *) Add 'Maximum Fragment Length' TLS extension negotiation and support - as documented in RFC6066. - Based on a patch from Tomasz Moń - [Filipe Raimundo da Silva] - - *) Add SM4 implemented according to GB/T 32907-2016. - [ Jack Lloyd , - Ronald Tse , - Erick Borsboom ] - - *) Reimplement -newreq-nodes and ERR_error_string_n; the - original author does not agree with the license change. - [Rich Salz] - - *) Add ARIA AEAD TLS support. - [Jon Spillett] - - *) Some macro definitions to support VS6 have been removed. Visual - Studio 6 has not worked since 1.1.0 - [Rich Salz] - - *) Add ERR_clear_last_mark(), to allow callers to clear the last mark - without clearing the errors. - [Richard Levitte] - - *) Add "atfork" functions. If building on a system that without - pthreads, see doc/man3/OPENSSL_fork_prepare.pod for application - requirements. The RAND facility now uses/requires this. - [Rich Salz] - - *) Add SHA3. - [Andy Polyakov] - - *) The UI API becomes a permanent and integral part of libcrypto, i.e. - not possible to disable entirely. However, it's still possible to - disable the console reading UI method, UI_OpenSSL() (use UI_null() - as a fallback). - - To disable, configure with 'no-ui-console'. 'no-ui' is still - possible to use as an alias. Check at compile time with the - macro OPENSSL_NO_UI_CONSOLE. The macro OPENSSL_NO_UI is still - possible to check and is an alias for OPENSSL_NO_UI_CONSOLE. - [Richard Levitte] - - *) Add a STORE module, which implements a uniform and URI based reader of - stores that can contain keys, certificates, CRLs and numerous other - objects. The main API is loosely based on a few stdio functions, - and includes OSSL_STORE_open, OSSL_STORE_load, OSSL_STORE_eof, - OSSL_STORE_error and OSSL_STORE_close. - The implementation uses backends called "loaders" to implement arbitrary - URI schemes. There is one built in "loader" for the 'file' scheme. - [Richard Levitte] - - *) Add devcrypto engine. This has been implemented against cryptodev-linux, - then adjusted to work on FreeBSD 8.4 as well. - Enable by configuring with 'enable-devcryptoeng'. This is done by default - on BSD implementations, as cryptodev.h is assumed to exist on all of them. - [Richard Levitte] - - *) Module names can prefixed with OSSL_ or OPENSSL_. This affects - util/mkerr.pl, which is adapted to allow those prefixes, leading to - error code calls like this: - - OSSL_FOOerr(OSSL_FOO_F_SOMETHING, OSSL_FOO_R_WHATEVER); - - With this change, we claim the namespaces OSSL and OPENSSL in a manner - that can be encoded in C. For the foreseeable future, this will only - affect new modules. - [Richard Levitte and Tim Hudson] - - *) Removed BSD cryptodev engine. - [Rich Salz] - - *) Add a build target 'build_all_generated', to build all generated files - and only that. This can be used to prepare everything that requires - things like perl for a system that lacks perl and then move everything - to that system and do the rest of the build there. - [Richard Levitte] - - *) In the UI interface, make it possible to duplicate the user data. This - can be used by engines that need to retain the data for a longer time - than just the call where this user data is passed. - [Richard Levitte] - - *) Ignore the '-named_curve auto' value for compatibility of applications - with OpenSSL 1.0.2. - [Tomas Mraz ] - - *) Fragmented SSL/TLS alerts are no longer accepted. An alert message is 2 - bytes long. In theory it is permissible in SSLv3 - TLSv1.2 to fragment such - alerts across multiple records (some of which could be empty). In practice - it make no sense to send an empty alert record, or to fragment one. TLSv1.3 - prohibits this altogether and other libraries (BoringSSL, NSS) do not - support this at all. Supporting it adds significant complexity to the - record layer, and its removal is unlikely to cause interoperability - issues. - [Matt Caswell] - - *) Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed - with Z. These are meant to replace LONG and ZLONG and to be size safe. - The use of LONG and ZLONG is discouraged and scheduled for deprecation - in OpenSSL 1.2.0. - [Richard Levitte] - - *) Add the 'z' and 'j' modifiers to BIO_printf() et al formatting string, - 'z' is to be used for [s]size_t, and 'j' - with [u]int64_t. - [Richard Levitte, Andy Polyakov] - - *) Add EC_KEY_get0_engine(), which does for EC_KEY what RSA_get0_engine() - does for RSA, etc. - [Richard Levitte] - - *) Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target - platform rather than 'mingw'. - [Richard Levitte] - - *) The functions X509_STORE_add_cert and X509_STORE_add_crl return - success if they are asked to add an object which already exists - in the store. This change cascades to other functions which load - certificates and CRLs. - [Paul Dale] - - *) x86_64 assembly pack: annotate code with DWARF CFI directives to - facilitate stack unwinding even from assembly subroutines. - [Andy Polyakov] - - *) Remove VAX C specific definitions of OPENSSL_EXPORT, OPENSSL_EXTERN. - Also remove OPENSSL_GLOBAL entirely, as it became a no-op. - [Richard Levitte] - - *) Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c. - VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1, - which is the minimum version we support. - [Richard Levitte] - - *) Certificate time validation (X509_cmp_time) enforces stricter - compliance with RFC 5280. Fractional seconds and timezone offsets - are no longer allowed. - [Emilia Käsper] - - *) Add support for ARIA - [Paul Dale] - - *) s_client will now send the Server Name Indication (SNI) extension by - default unless the new "-noservername" option is used. The server name is - based on the host provided to the "-connect" option unless overridden by - using "-servername". - [Matt Caswell] - - *) Add support for SipHash - [Todd Short] - - *) OpenSSL now fails if it receives an unrecognised record type in TLS1.0 - or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to - prevent issues where no progress is being made and the peer continually - sends unrecognised record types, using up resources processing them. - [Matt Caswell] - - *) 'openssl passwd' can now produce SHA256 and SHA512 based output, - using the algorithm defined in - https://www.akkadia.org/drepper/SHA-crypt.txt - [Richard Levitte] - - *) Heartbeat support has been removed; the ABI is changed for now. - [Richard Levitte, Rich Salz] - - *) Support for SSL_OP_NO_ENCRYPT_THEN_MAC in SSL_CONF_cmd. - [Emilia Käsper] - - *) The RSA "null" method, which was partially supported to avoid patent - issues, has been replaced to always returns NULL. - [Rich Salz] - - - Changes between 1.1.0h and 1.1.0i [xx XXX xxxx] - - *) Client DoS due to large DH parameter - - During key agreement in a TLS handshake using a DH(E) based ciphersuite a - malicious server can send a very large prime value to the client. This will - cause the client to spend an unreasonably long period of time generating a - key for this prime resulting in a hang until the client has finished. This - could be exploited in a Denial Of Service attack. - - This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken - (CVE-2018-0732) - [Guido Vranken] - - *) Cache timing vulnerability in RSA Key Generation - - The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to - a cache timing side channel attack. An attacker with sufficient access to - mount cache timing attacks during the RSA key generation process could - recover the private key. - - This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera - Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia. - (CVE-2018-0737) - [Billy Brumley] - - *) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str - parameter is no longer accepted, as it leads to a corrupt table. NULL - pem_str is reserved for alias entries only. - [Richard Levitte] - - *) Revert blinding in ECDSA sign and instead make problematic addition - length-invariant. Switch even to fixed-length Montgomery multiplication. - [Andy Polyakov] - - *) Change generating and checking of primes so that the error rate of not - being prime depends on the intended use based on the size of the input. - For larger primes this will result in more rounds of Miller-Rabin. - The maximal error rate for primes with more than 1080 bits is lowered - to 2^-128. - [Kurt Roeckx, Annie Yousar] - - *) Increase the number of Miller-Rabin rounds for DSA key generating to 64. - [Kurt Roeckx] - - *) Add blinding to ECDSA and DSA signatures to protect against side channel - attacks discovered by Keegan Ryan (NCC Group). - [Matt Caswell] - - *) When unlocking a pass phrase protected PEM file or PKCS#8 container, we - now allow empty (zero character) pass phrases. - [Richard Levitte] - - *) Certificate time validation (X509_cmp_time) enforces stricter - compliance with RFC 5280. Fractional seconds and timezone offsets - are no longer allowed. - [Emilia Käsper] - - *) Fixed a text canonicalisation bug in CMS - - Where a CMS detached signature is used with text content the text goes - through a canonicalisation process first prior to signing or verifying a - signature. This process strips trailing space at the end of lines, converts - line terminators to CRLF and removes additional trailing line terminators - at the end of a file. A bug in the canonicalisation process meant that - some characters, such as form-feed, were incorrectly treated as whitespace - and removed. This is contrary to the specification (RFC5485). This fix - could mean that detached text data signed with an earlier version of - OpenSSL 1.1.0 may fail to verify using the fixed version, or text data - signed with a fixed OpenSSL may fail to verify with an earlier version of - OpenSSL 1.1.0. A workaround is to only verify the canonicalised text data - and use the "-binary" flag (for the "cms" command line application) or set - the SMIME_BINARY/PKCS7_BINARY/CMS_BINARY flags (if using CMS_verify()). - [Matt Caswell] - - Changes between 1.1.0g and 1.1.0h [27 Mar 2018] - - *) Constructed ASN.1 types with a recursive definition could exceed the stack - - Constructed ASN.1 types with a recursive definition (such as can be found - in PKCS7) could eventually exceed the stack given malicious input with - excessive recursion. This could result in a Denial Of Service attack. There - are no such structures used within SSL/TLS that come from untrusted sources - so this is considered safe. - - This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz - project. - (CVE-2018-0739) - [Matt Caswell] - - *) Incorrect CRYPTO_memcmp on HP-UX PA-RISC - - Because of an implementation bug the PA-RISC CRYPTO_memcmp function is - effectively reduced to only comparing the least significant bit of each - byte. This allows an attacker to forge messages that would be considered as - authenticated in an amount of tries lower than that guaranteed by the - security claims of the scheme. The module can only be compiled by the - HP-UX assembler, so that only HP-UX PA-RISC targets are affected. - - This issue was reported to OpenSSL on 2nd March 2018 by Peter Waltenberg - (IBM). - (CVE-2018-0733) - [Andy Polyakov] - - *) Add a build target 'build_all_generated', to build all generated files - and only that. This can be used to prepare everything that requires - things like perl for a system that lacks perl and then move everything - to that system and do the rest of the build there. - [Richard Levitte] - - *) Backport SSL_OP_NO_RENGOTIATION - - OpenSSL 1.0.2 and below had the ability to disable renegotiation using the - (undocumented) SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag. Due to the opacity - changes this is no longer possible in 1.1.0. Therefore the new - SSL_OP_NO_RENEGOTIATION option from 1.1.1-dev has been backported to - 1.1.0 to provide equivalent functionality. - - Note that if an application built against 1.1.0h headers (or above) is run - using an older version of 1.1.0 (prior to 1.1.0h) then the option will be - accepted but nothing will happen, i.e. renegotiation will not be prevented. - [Matt Caswell] - - *) Removed the OS390-Unix config target. It relied on a script that doesn't - exist. - [Rich Salz] - - *) rsaz_1024_mul_avx2 overflow bug on x86_64 - - There is an overflow bug in the AVX2 Montgomery multiplication procedure - used in exponentiation with 1024-bit moduli. No EC algorithms are affected. - Analysis suggests that attacks against RSA and DSA as a result of this - defect would be very difficult to perform and are not believed likely. - Attacks against DH1024 are considered just feasible, because most of the - work necessary to deduce information about a private key may be performed - offline. The amount of resources required for such an attack would be - significant. However, for an attack on TLS to be meaningful, the server - would have to share the DH1024 private key among multiple clients, which is - no longer an option since CVE-2016-0701. - - This only affects processors that support the AVX2 but not ADX extensions - like Intel Haswell (4th generation). - - This issue was reported to OpenSSL by David Benjamin (Google). The issue - was originally found via the OSS-Fuzz project. - (CVE-2017-3738) - [Andy Polyakov] - - Changes between 1.1.0f and 1.1.0g [2 Nov 2017] - - *) bn_sqrx8x_internal carry bug on x86_64 - - There is a carry propagating bug in the x86_64 Montgomery squaring - procedure. No EC algorithms are affected. Analysis suggests that attacks - against RSA and DSA as a result of this defect would be very difficult to - perform and are not believed likely. Attacks against DH are considered just - feasible (although very difficult) because most of the work necessary to - deduce information about a private key may be performed offline. The amount - of resources required for such an attack would be very significant and - likely only accessible to a limited number of attackers. An attacker would - additionally need online access to an unpatched system using the target - private key in a scenario with persistent DH parameters and a private - key that is shared between multiple clients. - - This only affects processors that support the BMI1, BMI2 and ADX extensions - like Intel Broadwell (5th generation) and later or AMD Ryzen. - - This issue was reported to OpenSSL by the OSS-Fuzz project. - (CVE-2017-3736) - [Andy Polyakov] - - *) Malformed X.509 IPAddressFamily could cause OOB read - - If an X.509 certificate has a malformed IPAddressFamily extension, - OpenSSL could do a one-byte buffer overread. The most likely result - would be an erroneous display of the certificate in text format. - - This issue was reported to OpenSSL by the OSS-Fuzz project. - (CVE-2017-3735) - [Rich Salz] - - Changes between 1.1.0e and 1.1.0f [25 May 2017] - - *) Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target - platform rather than 'mingw'. - [Richard Levitte] - - *) Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c. - VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1, - which is the minimum version we support. - [Richard Levitte] - - Changes between 1.1.0d and 1.1.0e [16 Feb 2017] - - *) Encrypt-Then-Mac renegotiation crash - - During a renegotiation handshake if the Encrypt-Then-Mac extension is - negotiated where it was not in the original handshake (or vice-versa) then - this can cause OpenSSL to crash (dependant on ciphersuite). Both clients - and servers are affected. - - This issue was reported to OpenSSL by Joe Orton (Red Hat). - (CVE-2017-3733) - [Matt Caswell] - - Changes between 1.1.0c and 1.1.0d [26 Jan 2017] - - *) Truncated packet could crash via OOB read - - If one side of an SSL/TLS path is running on a 32-bit host and a specific - cipher is being used, then a truncated packet can cause that host to - perform an out-of-bounds read, usually resulting in a crash. - - This issue was reported to OpenSSL by Robert Święcki of Google. - (CVE-2017-3731) - [Andy Polyakov] - - *) Bad (EC)DHE parameters cause a client crash - - If a malicious server supplies bad parameters for a DHE or ECDHE key - exchange then this can result in the client attempting to dereference a - NULL pointer leading to a client crash. This could be exploited in a Denial - of Service attack. - - This issue was reported to OpenSSL by Guido Vranken. - (CVE-2017-3730) - [Matt Caswell] - - *) BN_mod_exp may produce incorrect results on x86_64 - - There is a carry propagating bug in the x86_64 Montgomery squaring - procedure. No EC algorithms are affected. Analysis suggests that attacks - against RSA and DSA as a result of this defect would be very difficult to - perform and are not believed likely. Attacks against DH are considered just - feasible (although very difficult) because most of the work necessary to - deduce information about a private key may be performed offline. The amount - of resources required for such an attack would be very significant and - likely only accessible to a limited number of attackers. An attacker would - additionally need online access to an unpatched system using the target - private key in a scenario with persistent DH parameters and a private - key that is shared between multiple clients. For example this can occur by - default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very - similar to CVE-2015-3193 but must be treated as a separate problem. - - This issue was reported to OpenSSL by the OSS-Fuzz project. - (CVE-2017-3732) - [Andy Polyakov] - - Changes between 1.1.0b and 1.1.0c [10 Nov 2016] - - *) ChaCha20/Poly1305 heap-buffer-overflow - - TLS connections using *-CHACHA20-POLY1305 ciphersuites are susceptible to - a DoS attack by corrupting larger payloads. This can result in an OpenSSL - crash. This issue is not considered to be exploitable beyond a DoS. - - This issue was reported to OpenSSL by Robert Święcki (Google Security Team) - (CVE-2016-7054) - [Richard Levitte] - - *) CMS Null dereference - - Applications parsing invalid CMS structures can crash with a NULL pointer - dereference. This is caused by a bug in the handling of the ASN.1 CHOICE - type in OpenSSL 1.1.0 which can result in a NULL value being passed to the - structure callback if an attempt is made to free certain invalid encodings. - Only CHOICE structures using a callback which do not handle NULL value are - affected. - - This issue was reported to OpenSSL by Tyler Nighswander of ForAllSecure. - (CVE-2016-7053) - [Stephen Henson] - - *) Montgomery multiplication may produce incorrect results - - There is a carry propagating bug in the Broadwell-specific Montgomery - multiplication procedure that handles input lengths divisible by, but - longer than 256 bits. Analysis suggests that attacks against RSA, DSA - and DH private keys are impossible. This is because the subroutine in - question is not used in operations with the private key itself and an input - of the attacker's direct choice. Otherwise the bug can manifest itself as - transient authentication and key negotiation failures or reproducible - erroneous outcome of public-key operations with specially crafted input. - Among EC algorithms only Brainpool P-512 curves are affected and one - presumably can attack ECDH key negotiation. Impact was not analyzed in - detail, because pre-requisites for attack are considered unlikely. Namely - multiple clients have to choose the curve in question and the server has to - share the private key among them, neither of which is default behaviour. - Even then only clients that chose the curve will be affected. - - This issue was publicly reported as transient failures and was not - initially recognized as a security issue. Thanks to Richard Morgan for - providing reproducible case. - (CVE-2016-7055) - [Andy Polyakov] - - *) Removed automatic addition of RPATH in shared libraries and executables, - as this was a remainder from OpenSSL 1.0.x and isn't needed any more. - [Richard Levitte] - - Changes between 1.1.0a and 1.1.0b [26 Sep 2016] - - *) Fix Use After Free for large message sizes - - The patch applied to address CVE-2016-6307 resulted in an issue where if a - message larger than approx 16k is received then the underlying buffer to - store the incoming message is reallocated and moved. Unfortunately a - dangling pointer to the old location is left which results in an attempt to - write to the previously freed location. This is likely to result in a - crash, however it could potentially lead to execution of arbitrary code. - - This issue only affects OpenSSL 1.1.0a. - - This issue was reported to OpenSSL by Robert Święcki. - (CVE-2016-6309) - [Matt Caswell] - - Changes between 1.1.0 and 1.1.0a [22 Sep 2016] - - *) OCSP Status Request extension unbounded memory growth - - A malicious client can send an excessively large OCSP Status Request - extension. If that client continually requests renegotiation, sending a - large OCSP Status Request extension each time, then there will be unbounded - memory growth on the server. This will eventually lead to a Denial Of - Service attack through memory exhaustion. Servers with a default - configuration are vulnerable even if they do not support OCSP. Builds using - the "no-ocsp" build time option are not affected. - - This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) - (CVE-2016-6304) - [Matt Caswell] - - *) SSL_peek() hang on empty record - - OpenSSL 1.1.0 SSL/TLS will hang during a call to SSL_peek() if the peer - sends an empty record. This could be exploited by a malicious peer in a - Denial Of Service attack. - - This issue was reported to OpenSSL by Alex Gaynor. - (CVE-2016-6305) - [Matt Caswell] - - *) Excessive allocation of memory in tls_get_message_header() and - dtls1_preprocess_fragment() - - A (D)TLS message includes 3 bytes for its length in the header for the - message. This would allow for messages up to 16Mb in length. Messages of - this length are excessive and OpenSSL includes a check to ensure that a - peer is sending reasonably sized messages in order to avoid too much memory - being consumed to service a connection. A flaw in the logic of version - 1.1.0 means that memory for the message is allocated too early, prior to - the excessive message length check. Due to way memory is allocated in - OpenSSL this could mean an attacker could force up to 21Mb to be allocated - to service a connection. This could lead to a Denial of Service through - memory exhaustion. However, the excessive message length check still takes - place, and this would cause the connection to immediately fail. Assuming - that the application calls SSL_free() on the failed connection in a timely - manner then the 21Mb of allocated memory will then be immediately freed - again. Therefore the excessive memory allocation will be transitory in - nature. This then means that there is only a security impact if: - - 1) The application does not call SSL_free() in a timely manner in the event - that the connection fails - or - 2) The application is working in a constrained environment where there is - very little free memory - or - 3) The attacker initiates multiple connection attempts such that there are - multiple connections in a state where memory has been allocated for the - connection; SSL_free() has not yet been called; and there is insufficient - memory to service the multiple requests. - - Except in the instance of (1) above any Denial Of Service is likely to be - transitory because as soon as the connection fails the memory is - subsequently freed again in the SSL_free() call. However there is an - increased risk during this period of application crashes due to the lack of - memory - which would then mean a more serious Denial of Service. - - This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) - (CVE-2016-6307 and CVE-2016-6308) - [Matt Caswell] - - *) solaris-x86-cc, i.e. 32-bit configuration with vendor compiler, - had to be removed. Primary reason is that vendor assembler can't - assemble our modules with -KPIC flag. As result it, assembly - support, was not even available as option. But its lack means - lack of side-channel resistant code, which is incompatible with - security by todays standards. Fortunately gcc is readily available - prepackaged option, which we firmly point at... - [Andy Polyakov] - - Changes between 1.0.2h and 1.1.0 [25 Aug 2016] - - *) Windows command-line tool supports UTF-8 opt-in option for arguments - and console input. Setting OPENSSL_WIN32_UTF8 environment variable - (to any value) allows Windows user to access PKCS#12 file generated - with Windows CryptoAPI and protected with non-ASCII password, as well - as files generated under UTF-8 locale on Linux also protected with - non-ASCII password. - [Andy Polyakov] - - *) To mitigate the SWEET32 attack (CVE-2016-2183), 3DES cipher suites - have been disabled by default and removed from DEFAULT, just like RC4. - See the RC4 item below to re-enable both. - [Rich Salz] - - *) The method for finding the storage location for the Windows RAND seed file - has changed. First we check %RANDFILE%. If that is not set then we check - the directories %HOME%, %USERPROFILE% and %SYSTEMROOT% in that order. If - all else fails we fall back to C:\. - [Matt Caswell] - - *) The EVP_EncryptUpdate() function has had its return type changed from void - to int. A return of 0 indicates and error while a return of 1 indicates - success. - [Matt Caswell] - - *) The flags RSA_FLAG_NO_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME and - DH_FLAG_NO_EXP_CONSTTIME which previously provided the ability to switch - off the constant time implementation for RSA, DSA and DH have been made - no-ops and deprecated. - [Matt Caswell] - - *) Windows RAND implementation was simplified to only get entropy by - calling CryptGenRandom(). Various other RAND-related tickets - were also closed. - [Joseph Wylie Yandle, Rich Salz] - - *) The stack and lhash API's were renamed to start with OPENSSL_SK_ - and OPENSSL_LH_, respectively. The old names are available - with API compatibility. They new names are now completely documented. - [Rich Salz] - - *) Unify TYPE_up_ref(obj) methods signature. - SSL_CTX_up_ref(), SSL_up_ref(), X509_up_ref(), EVP_PKEY_up_ref(), - X509_CRL_up_ref(), X509_OBJECT_up_ref_count() methods are now returning an - int (instead of void) like all others TYPE_up_ref() methods. - So now these methods also check the return value of CRYPTO_atomic_add(), - and the validity of object reference counter. - [fdasilvayy@gmail.com] - - *) With Windows Visual Studio builds, the .pdb files are installed - alongside the installed libraries and executables. For a static - library installation, ossl_static.pdb is the associate compiler - generated .pdb file to be used when linking programs. - [Richard Levitte] - - *) Remove openssl.spec. Packaging files belong with the packagers. - [Richard Levitte] - - *) Automatic Darwin/OSX configuration has had a refresh, it will now - recognise x86_64 architectures automatically. You can still decide - to build for a different bitness with the environment variable - KERNEL_BITS (can be 32 or 64), for example: - - KERNEL_BITS=32 ./config - - [Richard Levitte] - - *) Change default algorithms in pkcs8 utility to use PKCS#5 v2.0, - 256 bit AES and HMAC with SHA256. - [Steve Henson] - - *) Remove support for MIPS o32 ABI on IRIX (and IRIX only). - [Andy Polyakov] - - *) Triple-DES ciphers have been moved from HIGH to MEDIUM. - [Rich Salz] - - *) To enable users to have their own config files and build file templates, - Configure looks in the directory indicated by the environment variable - OPENSSL_LOCAL_CONFIG_DIR as well as the in-source Configurations/ - directory. On VMS, OPENSSL_LOCAL_CONFIG_DIR is expected to be a logical - name and is used as is. - [Richard Levitte] - - *) The following datatypes were made opaque: X509_OBJECT, X509_STORE_CTX, - X509_STORE, X509_LOOKUP, and X509_LOOKUP_METHOD. The unused type - X509_CERT_FILE_CTX was removed. - [Rich Salz] - - *) "shared" builds are now the default. To create only static libraries use - the "no-shared" Configure option. - [Matt Caswell] - - *) Remove the no-aes, no-hmac, no-rsa, no-sha and no-md5 Configure options. - All of these option have not worked for some while and are fundamental - algorithms. - [Matt Caswell] - - *) Make various cleanup routines no-ops and mark them as deprecated. Most - global cleanup functions are no longer required because they are handled - via auto-deinit (see OPENSSL_init_crypto and OPENSSL_init_ssl man pages). - Explicitly de-initing can cause problems (e.g. where a library that uses - OpenSSL de-inits, but an application is still using it). The affected - functions are CONF_modules_free(), ENGINE_cleanup(), OBJ_cleanup(), - EVP_cleanup(), BIO_sock_cleanup(), CRYPTO_cleanup_all_ex_data(), - RAND_cleanup(), SSL_COMP_free_compression_methods(), ERR_free_strings() and - COMP_zlib_cleanup(). - [Matt Caswell] - - *) --strict-warnings no longer enables runtime debugging options - such as REF_DEBUG. Instead, debug options are automatically - enabled with '--debug' builds. - [Andy Polyakov, Emilia Käsper] - - *) Made DH and DH_METHOD opaque. The structures for managing DH objects - have been moved out of the public header files. New functions for managing - these have been added. - [Matt Caswell] - - *) Made RSA and RSA_METHOD opaque. The structures for managing RSA - objects have been moved out of the public header files. New - functions for managing these have been added. - [Richard Levitte] - - *) Made DSA and DSA_METHOD opaque. The structures for managing DSA objects - have been moved out of the public header files. New functions for managing - these have been added. - [Matt Caswell] - - *) Made BIO and BIO_METHOD opaque. The structures for managing BIOs have been - moved out of the public header files. New functions for managing these - have been added. - [Matt Caswell] - - *) Removed no-rijndael as a config option. Rijndael is an old name for AES. - [Matt Caswell] - - *) Removed the mk1mf build scripts. - [Richard Levitte] - - *) Headers are now wrapped, if necessary, with OPENSSL_NO_xxx, so - it is always safe to #include a header now. - [Rich Salz] - - *) Removed the aged BC-32 config and all its supporting scripts - [Richard Levitte] - - *) Removed support for Ultrix, Netware, and OS/2. - [Rich Salz] - - *) Add support for HKDF. - [Alessandro Ghedini] - - *) Add support for blake2b and blake2s - [Bill Cox] - - *) Added support for "pipelining". Ciphers that have the - EVP_CIPH_FLAG_PIPELINE flag set have a capability to process multiple - encryptions/decryptions simultaneously. There are currently no built-in - ciphers with this property but the expectation is that engines will be able - to offer it to significantly improve throughput. Support has been extended - into libssl so that multiple records for a single connection can be - processed in one go (for >=TLS 1.1). - [Matt Caswell] - - *) Added the AFALG engine. This is an async capable engine which is able to - offload work to the Linux kernel. In this initial version it only supports - AES128-CBC. The kernel must be version 4.1.0 or greater. - [Catriona Lucey] - - *) OpenSSL now uses a new threading API. It is no longer necessary to - set locking callbacks to use OpenSSL in a multi-threaded environment. There - are two supported threading models: pthreads and windows threads. It is - also possible to configure OpenSSL at compile time for "no-threads". The - old threading API should no longer be used. The functions have been - replaced with "no-op" compatibility macros. - [Alessandro Ghedini, Matt Caswell] - - *) Modify behavior of ALPN to invoke callback after SNI/servername - callback, such that updates to the SSL_CTX affect ALPN. - [Todd Short] - - *) Add SSL_CIPHER queries for authentication and key-exchange. - [Todd Short] - - *) Changes to the DEFAULT cipherlist: - - Prefer (EC)DHE handshakes over plain RSA. - - Prefer AEAD ciphers over legacy ciphers. - - Prefer ECDSA over RSA when both certificates are available. - - Prefer TLSv1.2 ciphers/PRF. - - Remove DSS, SEED, IDEA, CAMELLIA, and AES-CCM from the - default cipherlist. - [Emilia Käsper] - - *) Change the ECC default curve list to be this, in order: x25519, - secp256r1, secp521r1, secp384r1. - [Rich Salz] - - *) RC4 based libssl ciphersuites are now classed as "weak" ciphers and are - disabled by default. They can be re-enabled using the - enable-weak-ssl-ciphers option to Configure. - [Matt Caswell] - - *) If the server has ALPN configured, but supports no protocols that the - client advertises, send a fatal "no_application_protocol" alert. - This behaviour is SHALL in RFC 7301, though it isn't universally - implemented by other servers. - [Emilia Käsper] - - *) Add X25519 support. - Add ASN.1 and EVP_PKEY methods for X25519. This includes support - for public and private key encoding using the format documented in - draft-ietf-curdle-pkix-02. The corresponding EVP_PKEY method supports - key generation and key derivation. - - TLS support complies with draft-ietf-tls-rfc4492bis-08 and uses - X25519(29). - [Steve Henson] - - *) Deprecate SRP_VBASE_get_by_user. - SRP_VBASE_get_by_user had inconsistent memory management behaviour. - In order to fix an unavoidable memory leak (CVE-2016-0798), - SRP_VBASE_get_by_user was changed to ignore the "fake user" SRP - seed, even if the seed is configured. - - Users should use SRP_VBASE_get1_by_user instead. Note that in - SRP_VBASE_get1_by_user, caller must free the returned value. Note - also that even though configuring the SRP seed attempts to hide - invalid usernames by continuing the handshake with fake - credentials, this behaviour is not constant time and no strong - guarantees are made that the handshake is indistinguishable from - that of a valid user. - [Emilia Käsper] - - *) Configuration change; it's now possible to build dynamic engines - without having to build shared libraries and vice versa. This - only applies to the engines in engines/, those in crypto/engine/ - will always be built into libcrypto (i.e. "static"). - - Building dynamic engines is enabled by default; to disable, use - the configuration option "disable-dynamic-engine". - - The only requirements for building dynamic engines are the - presence of the DSO module and building with position independent - code, so they will also automatically be disabled if configuring - with "disable-dso" or "disable-pic". - - The macros OPENSSL_NO_STATIC_ENGINE and OPENSSL_NO_DYNAMIC_ENGINE - are also taken away from openssl/opensslconf.h, as they are - irrelevant. - [Richard Levitte] - - *) Configuration change; if there is a known flag to compile - position independent code, it will always be applied on the - libcrypto and libssl object files, and never on the application - object files. This means other libraries that use routines from - libcrypto / libssl can be made into shared libraries regardless - of how OpenSSL was configured. - - If this isn't desirable, the configuration options "disable-pic" - or "no-pic" can be used to disable the use of PIC. This will - also disable building shared libraries and dynamic engines. - [Richard Levitte] - - *) Removed JPAKE code. It was experimental and has no wide use. - [Rich Salz] - - *) The INSTALL_PREFIX Makefile variable has been renamed to - DESTDIR. That makes for less confusion on what this variable - is for. Also, the configuration option --install_prefix is - removed. - [Richard Levitte] - - *) Heartbeat for TLS has been removed and is disabled by default - for DTLS; configure with enable-heartbeats. Code that uses the - old #define's might need to be updated. - [Emilia Käsper, Rich Salz] - - *) Rename REF_CHECK to REF_DEBUG. - [Rich Salz] - - *) New "unified" build system - - The "unified" build system is aimed to be a common system for all - platforms we support. With it comes new support for VMS. - - This system builds supports building in a different directory tree - than the source tree. It produces one Makefile (for unix family - or lookalikes), or one descrip.mms (for VMS). - - The source of information to make the Makefile / descrip.mms is - small files called 'build.info', holding the necessary - information for each directory with source to compile, and a - template in Configurations, like unix-Makefile.tmpl or - descrip.mms.tmpl. - - With this change, the library names were also renamed on Windows - and on VMS. They now have names that are closer to the standard - on Unix, and include the major version number, and in certain - cases, the architecture they are built for. See "Notes on shared - libraries" in INSTALL. - - We rely heavily on the perl module Text::Template. - [Richard Levitte] - - *) Added support for auto-initialisation and de-initialisation of the library. - OpenSSL no longer requires explicit init or deinit routines to be called, - except in certain circumstances. See the OPENSSL_init_crypto() and - OPENSSL_init_ssl() man pages for further information. - [Matt Caswell] - - *) The arguments to the DTLSv1_listen function have changed. Specifically the - "peer" argument is now expected to be a BIO_ADDR object. - - *) Rewrite of BIO networking library. The BIO library lacked consistent - support of IPv6, and adding it required some more extensive - modifications. This introduces the BIO_ADDR and BIO_ADDRINFO types, - which hold all types of addresses and chains of address information. - It also introduces a new API, with functions like BIO_socket, - BIO_connect, BIO_listen, BIO_lookup and a rewrite of BIO_accept. - The source/sink BIOs BIO_s_connect, BIO_s_accept and BIO_s_datagram - have been adapted accordingly. - [Richard Levitte] - - *) RSA_padding_check_PKCS1_type_1 now accepts inputs with and without - the leading 0-byte. - [Emilia Käsper] - - *) CRIME protection: disable compression by default, even if OpenSSL is - compiled with zlib enabled. Applications can still enable compression - by calling SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION), or by - using the SSL_CONF library to configure compression. - [Emilia Käsper] - - *) The signature of the session callback configured with - SSL_CTX_sess_set_get_cb was changed. The read-only input buffer - was explicitly marked as 'const unsigned char*' instead of - 'unsigned char*'. - [Emilia Käsper] - - *) Always DPURIFY. Remove the use of uninitialized memory in the - RNG, and other conditional uses of DPURIFY. This makes -DPURIFY a no-op. - [Emilia Käsper] - - *) Removed many obsolete configuration items, including - DES_PTR, DES_RISC1, DES_RISC2, DES_INT - MD2_CHAR, MD2_INT, MD2_LONG - BF_PTR, BF_PTR2 - IDEA_SHORT, IDEA_LONG - RC2_SHORT, RC2_LONG, RC4_LONG, RC4_CHUNK, RC4_INDEX - [Rich Salz, with advice from Andy Polyakov] - - *) Many BN internals have been moved to an internal header file. - [Rich Salz with help from Andy Polyakov] - - *) Configuration and writing out the results from it has changed. - Files such as Makefile include/openssl/opensslconf.h and are now - produced through general templates, such as Makefile.in and - crypto/opensslconf.h.in and some help from the perl module - Text::Template. - - Also, the center of configuration information is no longer - Makefile. Instead, Configure produces a perl module in - configdata.pm which holds most of the config data (in the hash - table %config), the target data that comes from the target - configuration in one of the Configurations/*.conf files (in - %target). - [Richard Levitte] - - *) To clarify their intended purposes, the Configure options - --prefix and --openssldir change their semantics, and become more - straightforward and less interdependent. - - --prefix shall be used exclusively to give the location INSTALLTOP - where programs, scripts, libraries, include files and manuals are - going to be installed. The default is now /usr/local. - - --openssldir shall be used exclusively to give the default - location OPENSSLDIR where certificates, private keys, CRLs are - managed. This is also where the default openssl.cnf gets - installed. - If the directory given with this option is a relative path, the - values of both the --prefix value and the --openssldir value will - be combined to become OPENSSLDIR. - The default for --openssldir is INSTALLTOP/ssl. - - Anyone who uses --openssldir to specify where OpenSSL is to be - installed MUST change to use --prefix instead. - [Richard Levitte] - - *) The GOST engine was out of date and therefore it has been removed. An up - to date GOST engine is now being maintained in an external repository. - See: https://wiki.openssl.org/index.php/Binaries. Libssl still retains - support for GOST ciphersuites (these are only activated if a GOST engine - is present). - [Matt Caswell] - - *) EGD is no longer supported by default; use enable-egd when - configuring. - [Ben Kaduk and Rich Salz] - - *) The distribution now has Makefile.in files, which are used to - create Makefile's when Configure is run. *Configure must be run - before trying to build now.* - [Rich Salz] - - *) The return value for SSL_CIPHER_description() for error conditions - has changed. - [Rich Salz] - - *) Support for RFC6698/RFC7671 DANE TLSA peer authentication. - - Obtaining and performing DNSSEC validation of TLSA records is - the application's responsibility. The application provides - the TLSA records of its choice to OpenSSL, and these are then - used to authenticate the peer. - - The TLSA records need not even come from DNS. They can, for - example, be used to implement local end-entity certificate or - trust-anchor "pinning", where the "pin" data takes the form - of TLSA records, which can augment or replace verification - based on the usual WebPKI public certification authorities. - [Viktor Dukhovni] - - *) Revert default OPENSSL_NO_DEPRECATED setting. Instead OpenSSL - continues to support deprecated interfaces in default builds. - However, applications are strongly advised to compile their - source files with -DOPENSSL_API_COMPAT=0x10100000L, which hides - the declarations of all interfaces deprecated in 0.9.8, 1.0.0 - or the 1.1.0 releases. - - In environments in which all applications have been ported to - not use any deprecated interfaces OpenSSL's Configure script - should be used with the --api=1.1.0 option to entirely remove - support for the deprecated features from the library and - unconditionally disable them in the installed headers. - Essentially the same effect can be achieved with the "no-deprecated" - argument to Configure, except that this will always restrict - the build to just the latest API, rather than a fixed API - version. - - As applications are ported to future revisions of the API, - they should update their compile-time OPENSSL_API_COMPAT define - accordingly, but in most cases should be able to continue to - compile with later releases. - - The OPENSSL_API_COMPAT versions for 1.0.0, and 0.9.8 are - 0x10000000L and 0x00908000L, respectively. However those - versions did not support the OPENSSL_API_COMPAT feature, and - so applications are not typically tested for explicit support - of just the undeprecated features of either release. - [Viktor Dukhovni] - - *) Add support for setting the minimum and maximum supported protocol. - It can bet set via the SSL_set_min_proto_version() and - SSL_set_max_proto_version(), or via the SSL_CONF's MinProtocol and - MaxProtocol. It's recommended to use the new APIs to disable - protocols instead of disabling individual protocols using - SSL_set_options() or SSL_CONF's Protocol. This change also - removes support for disabling TLS 1.2 in the OpenSSL TLS - client at compile time by defining OPENSSL_NO_TLS1_2_CLIENT. - [Kurt Roeckx] - - *) Support for ChaCha20 and Poly1305 added to libcrypto and libssl. - [Andy Polyakov] - - *) New EC_KEY_METHOD, this replaces the older ECDSA_METHOD and ECDH_METHOD - and integrates ECDSA and ECDH functionality into EC. Implementations can - now redirect key generation and no longer need to convert to or from - ECDSA_SIG format. - - Note: the ecdsa.h and ecdh.h headers are now no longer needed and just - include the ec.h header file instead. - [Steve Henson] - - *) Remove support for all 40 and 56 bit ciphers. This includes all the export - ciphers who are no longer supported and drops support the ephemeral RSA key - exchange. The LOW ciphers currently doesn't have any ciphers in it. - [Kurt Roeckx] - - *) Made EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, EVP_CIPHER and HMAC_CTX - opaque. For HMAC_CTX, the following constructors and destructors - were added: - - HMAC_CTX *HMAC_CTX_new(void); - void HMAC_CTX_free(HMAC_CTX *ctx); - - For EVP_MD and EVP_CIPHER, complete APIs to create, fill and - destroy such methods has been added. See EVP_MD_meth_new(3) and - EVP_CIPHER_meth_new(3) for documentation. - - Additional changes: - 1) EVP_MD_CTX_cleanup(), EVP_CIPHER_CTX_cleanup() and - HMAC_CTX_cleanup() were removed. HMAC_CTX_reset() and - EVP_MD_CTX_reset() should be called instead to reinitialise - an already created structure. - 2) For consistency with the majority of our object creators and - destructors, EVP_MD_CTX_(create|destroy) were renamed to - EVP_MD_CTX_(new|free). The old names are retained as macros - for deprecated builds. - [Richard Levitte] - - *) Added ASYNC support. Libcrypto now includes the async sub-library to enable - cryptographic operations to be performed asynchronously as long as an - asynchronous capable engine is used. See the ASYNC_start_job() man page for - further details. Libssl has also had this capability integrated with the - introduction of the new mode SSL_MODE_ASYNC and associated error - SSL_ERROR_WANT_ASYNC. See the SSL_CTX_set_mode() and SSL_get_error() man - pages. This work was developed in partnership with Intel Corp. - [Matt Caswell] - - *) SSL_{CTX_}set_ecdh_auto() has been removed and ECDH is support is - always enabled now. If you want to disable the support you should - exclude it using the list of supported ciphers. This also means that the - "-no_ecdhe" option has been removed from s_server. - [Kurt Roeckx] - - *) SSL_{CTX}_set_tmp_ecdh() which can set 1 EC curve now internally calls - SSL_{CTX_}set1_curves() which can set a list. - [Kurt Roeckx] - - *) Remove support for SSL_{CTX_}set_tmp_ecdh_callback(). You should set the - curve you want to support using SSL_{CTX_}set1_curves(). - [Kurt Roeckx] - - *) State machine rewrite. The state machine code has been significantly - refactored in order to remove much duplication of code and solve issues - with the old code (see ssl/statem/README for further details). This change - does have some associated API changes. Notably the SSL_state() function - has been removed and replaced by SSL_get_state which now returns an - "OSSL_HANDSHAKE_STATE" instead of an int. SSL_set_state() has been removed - altogether. The previous handshake states defined in ssl.h and ssl3.h have - also been removed. - [Matt Caswell] - - *) All instances of the string "ssleay" in the public API were replaced - with OpenSSL (case-matching; e.g., OPENSSL_VERSION for #define's) - Some error codes related to internal RSA_eay API's were renamed. - [Rich Salz] - - *) The demo files in crypto/threads were moved to demo/threads. - [Rich Salz] - - *) Removed obsolete engines: 4758cca, aep, atalla, cswift, nuron, gmp, - sureware and ubsec. - [Matt Caswell, Rich Salz] - - *) New ASN.1 embed macro. - - New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the - structure is not allocated: it is part of the parent. That is instead of - - FOO *x; - - it must be: - - FOO x; - - This reduces memory fragmentation and make it impossible to accidentally - set a mandatory field to NULL. - - This currently only works for some fields specifically a SEQUENCE, CHOICE, - or ASN1_STRING type which is part of a parent SEQUENCE. Since it is - equivalent to ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or - SEQUENCE OF. - [Steve Henson] - - *) Remove EVP_CHECK_DES_KEY, a compile-time option that never compiled. - [Emilia Käsper] - - *) Removed DES and RC4 ciphersuites from DEFAULT. Also removed RC2 although - in 1.0.2 EXPORT was already removed and the only RC2 ciphersuite is also - an EXPORT one. COMPLEMENTOFDEFAULT has been updated accordingly to add - DES and RC4 ciphersuites. - [Matt Caswell] - - *) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs. - This changes the decoding behaviour for some invalid messages, - though the change is mostly in the more lenient direction, and - legacy behaviour is preserved as much as possible. - [Emilia Käsper] - - *) Fix no-stdio build. - [ David Woodhouse and also - Ivan Nestlerode ] - - *) New testing framework - The testing framework has been largely rewritten and is now using - perl and the perl modules Test::Harness and an extended variant of - Test::More called OpenSSL::Test to do its work. All test scripts in - test/ have been rewritten into test recipes, and all direct calls to - executables in test/Makefile have become individual recipes using the - simplified testing OpenSSL::Test::Simple. - - For documentation on our testing modules, do: - - perldoc test/testlib/OpenSSL/Test/Simple.pm - perldoc test/testlib/OpenSSL/Test.pm - - [Richard Levitte] - - *) Revamped memory debug; only -DCRYPTO_MDEBUG and -DCRYPTO_MDEBUG_ABORT - are used; the latter aborts on memory leaks (usually checked on exit). - Some undocumented "set malloc, etc., hooks" functions were removed - and others were changed. All are now documented. - [Rich Salz] - - *) In DSA_generate_parameters_ex, if the provided seed is too short, - return an error - [Rich Salz and Ismo Puustinen ] - - *) Rewrite PSK to support ECDHE_PSK, DHE_PSK and RSA_PSK. Add ciphersuites - from RFC4279, RFC4785, RFC5487, RFC5489. - - Thanks to Christian J. Dietrich and Giuseppe D'Angelo for the - original RSA_PSK patch. - [Steve Henson] - - *) Dropped support for the SSL3_FLAGS_DELAY_CLIENT_FINISHED flag. This SSLeay - era flag was never set throughout the codebase (only read). Also removed - SSL3_FLAGS_POP_BUFFER which was only used if - SSL3_FLAGS_DELAY_CLIENT_FINISHED was also set. - [Matt Caswell] - - *) Changed the default name options in the "ca", "crl", "req" and "x509" - to be "oneline" instead of "compat". - [Richard Levitte] - - *) Remove SSL_OP_TLS_BLOCK_PADDING_BUG. This is SSLeay legacy, we're - not aware of clients that still exhibit this bug, and the workaround - hasn't been working properly for a while. - [Emilia Käsper] - - *) The return type of BIO_number_read() and BIO_number_written() as well as - the corresponding num_read and num_write members in the BIO structure has - changed from unsigned long to uint64_t. On platforms where an unsigned - long is 32 bits (e.g. Windows) these counters could overflow if >4Gb is - transferred. - [Matt Caswell] - - *) Given the pervasive nature of TLS extensions it is inadvisable to run - OpenSSL without support for them. It also means that maintaining - the OPENSSL_NO_TLSEXT option within the code is very invasive (and probably - not well tested). Therefore the OPENSSL_NO_TLSEXT option has been removed. - [Matt Caswell] - - *) Removed support for the two export grade static DH ciphersuites - EXP-DH-RSA-DES-CBC-SHA and EXP-DH-DSS-DES-CBC-SHA. These two ciphersuites - were newly added (along with a number of other static DH ciphersuites) to - 1.0.2. However the two export ones have *never* worked since they were - introduced. It seems strange in any case to be adding new export - ciphersuites, and given "logjam" it also does not seem correct to fix them. - [Matt Caswell] - - *) Version negotiation has been rewritten. In particular SSLv23_method(), - SSLv23_client_method() and SSLv23_server_method() have been deprecated, - and turned into macros which simply call the new preferred function names - TLS_method(), TLS_client_method() and TLS_server_method(). All new code - should use the new names instead. Also as part of this change the ssl23.h - header file has been removed. - [Matt Caswell] - - *) Support for Kerberos ciphersuites in TLS (RFC2712) has been removed. This - code and the associated standard is no longer considered fit-for-purpose. - [Matt Caswell] - - *) RT2547 was closed. When generating a private key, try to make the - output file readable only by the owner. This behavior change might - be noticeable when interacting with other software. - - *) Documented all exdata functions. Added CRYPTO_free_ex_index. - Added a test. - [Rich Salz] - - *) Added HTTP GET support to the ocsp command. - [Rich Salz] - - *) Changed default digest for the dgst and enc commands from MD5 to - sha256 - [Rich Salz] - - *) RAND_pseudo_bytes has been deprecated. Users should use RAND_bytes instead. - [Matt Caswell] - - *) Added support for TLS extended master secret from - draft-ietf-tls-session-hash-03.txt. Thanks for Alfredo Pironti for an - initial patch which was a great help during development. - [Steve Henson] - - *) All libssl internal structures have been removed from the public header - files, and the OPENSSL_NO_SSL_INTERN option has been removed (since it is - now redundant). Users should not attempt to access internal structures - directly. Instead they should use the provided API functions. - [Matt Caswell] - - *) config has been changed so that by default OPENSSL_NO_DEPRECATED is used. - Access to deprecated functions can be re-enabled by running config with - "enable-deprecated". In addition applications wishing to use deprecated - functions must define OPENSSL_USE_DEPRECATED. Note that this new behaviour - will, by default, disable some transitive includes that previously existed - in the header files (e.g. ec.h will no longer, by default, include bn.h) - [Matt Caswell] - - *) Added support for OCB mode. OpenSSL has been granted a patent license - compatible with the OpenSSL license for use of OCB. Details are available - at https://www.openssl.org/source/OCB-patent-grant-OpenSSL.pdf. Support - for OCB can be removed by calling config with no-ocb. - [Matt Caswell] - - *) SSLv2 support has been removed. It still supports receiving a SSLv2 - compatible client hello. - [Kurt Roeckx] - - *) Increased the minimal RSA keysize from 256 to 512 bits [Rich Salz], - done while fixing the error code for the key-too-small case. - [Annie Yousar ] - - *) CA.sh has been removed; use CA.pl instead. - [Rich Salz] - - *) Removed old DES API. - [Rich Salz] - - *) Remove various unsupported platforms: - Sony NEWS4 - BEOS and BEOS_R5 - NeXT - SUNOS - MPE/iX - Sinix/ReliantUNIX RM400 - DGUX - NCR - Tandem - Cray - 16-bit platforms such as WIN16 - [Rich Salz] - - *) Clean up OPENSSL_NO_xxx #define's - Use setbuf() and remove OPENSSL_NO_SETVBUF_IONBF - Rename OPENSSL_SYSNAME_xxx to OPENSSL_SYS_xxx - OPENSSL_NO_EC{DH,DSA} merged into OPENSSL_NO_EC - OPENSSL_NO_RIPEMD160, OPENSSL_NO_RIPEMD merged into OPENSSL_NO_RMD160 - OPENSSL_NO_FP_API merged into OPENSSL_NO_STDIO - Remove OPENSSL_NO_BIO OPENSSL_NO_BUFFER OPENSSL_NO_CHAIN_VERIFY - OPENSSL_NO_EVP OPENSSL_NO_FIPS_ERR OPENSSL_NO_HASH_COMP - OPENSSL_NO_LHASH OPENSSL_NO_OBJECT OPENSSL_NO_SPEED OPENSSL_NO_STACK - OPENSSL_NO_X509 OPENSSL_NO_X509_VERIFY - Remove MS_STATIC; it's a relic from platforms <32 bits. - [Rich Salz] - - *) Cleaned up dead code - Remove all but one '#ifdef undef' which is to be looked at. - [Rich Salz] - - *) Clean up calling of xxx_free routines. - Just like free(), fix most of the xxx_free routines to accept - NULL. Remove the non-null checks from callers. Save much code. - [Rich Salz] - - *) Add secure heap for storage of private keys (when possible). - Add BIO_s_secmem(), CBIGNUM, etc. - Contributed by Akamai Technologies under our Corporate CLA. - [Rich Salz] - - *) Experimental support for a new, fast, unbiased prime candidate generator, - bn_probable_prime_dh_coprime(). Not currently used by any prime generator. - [Felix Laurie von Massenbach ] - - *) New output format NSS in the sess_id command line tool. This allows - exporting the session id and the master key in NSS keylog format. - [Martin Kaiser ] - - *) Harmonize version and its documentation. -f flag is used to display - compilation flags. - [mancha ] - - *) Fix eckey_priv_encode so it immediately returns an error upon a failure - in i2d_ECPrivateKey. Thanks to Ted Unangst for feedback on this issue. - [mancha ] - - *) Fix some double frees. These are not thought to be exploitable. - [mancha ] - - *) A missing bounds check in the handling of the TLS heartbeat extension - can be used to reveal up to 64k of memory to a connected client or - server. - - Thanks for Neel Mehta of Google Security for discovering this bug and to - Adam Langley and Bodo Moeller for - preparing the fix (CVE-2014-0160) - [Adam Langley, Bodo Moeller] - - *) Fix for the attack described in the paper "Recovering OpenSSL - ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack" - by Yuval Yarom and Naomi Benger. Details can be obtained from: - http://eprint.iacr.org/2014/140 - - Thanks to Yuval Yarom and Naomi Benger for discovering this - flaw and to Yuval Yarom for supplying a fix (CVE-2014-0076) - [Yuval Yarom and Naomi Benger] - - *) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file(): - this fixes a limitation in previous versions of OpenSSL. - [Steve Henson] - - *) Experimental encrypt-then-mac support. - - Experimental support for encrypt then mac from - draft-gutmann-tls-encrypt-then-mac-02.txt - - To enable it set the appropriate extension number (0x42 for the test - server) using e.g. -DTLSEXT_TYPE_encrypt_then_mac=0x42 - - For non-compliant peers (i.e. just about everything) this should have no - effect. - - WARNING: EXPERIMENTAL, SUBJECT TO CHANGE. - - [Steve Henson] - - *) Add EVP support for key wrapping algorithms, to avoid problems with - existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in - the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap - algorithms and include tests cases. - [Steve Henson] - - *) Extend CMS code to support RSA-PSS signatures and RSA-OAEP for - enveloped data. - [Steve Henson] - - *) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest, - MGF1 digest and OAEP label. - [Steve Henson] - - *) Make openssl verify return errors. - [Chris Palmer and Ben Laurie] - - *) New function ASN1_TIME_diff to calculate the difference between two - ASN1_TIME structures or one structure and the current time. - [Steve Henson] - - *) Update fips_test_suite to support multiple command line options. New - test to induce all self test errors in sequence and check expected - failures. - [Steve Henson] - - *) Add FIPS_{rsa,dsa,ecdsa}_{sign,verify} functions which digest and - sign or verify all in one operation. - [Steve Henson] - - *) Add fips_algvs: a multicall fips utility incorporating all the algorithm - test programs and fips_test_suite. Includes functionality to parse - the minimal script output of fipsalgest.pl directly. - [Steve Henson] - - *) Add authorisation parameter to FIPS_module_mode_set(). - [Steve Henson] - - *) Add FIPS selftest for ECDH algorithm using P-224 and B-233 curves. - [Steve Henson] - - *) Use separate DRBG fields for internal and external flags. New function - FIPS_drbg_health_check() to perform on demand health checking. Add - generation tests to fips_test_suite with reduced health check interval to - demonstrate periodic health checking. Add "nodh" option to - fips_test_suite to skip very slow DH test. - [Steve Henson] - - *) New function FIPS_get_cipherbynid() to lookup FIPS supported ciphers - based on NID. - [Steve Henson] - - *) More extensive health check for DRBG checking many more failure modes. - New function FIPS_selftest_drbg_all() to handle every possible DRBG - combination: call this in fips_test_suite. - [Steve Henson] - - *) Add support for canonical generation of DSA parameter 'g'. See - FIPS 186-3 A.2.3. - - *) Add support for HMAC DRBG from SP800-90. Update DRBG algorithm test and - POST to handle HMAC cases. - [Steve Henson] - - *) Add functions FIPS_module_version() and FIPS_module_version_text() - to return numerical and string versions of the FIPS module number. - [Steve Henson] - - *) Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and - FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implemented - outside the validated module in the FIPS capable OpenSSL. - [Steve Henson] - - *) Minor change to DRBG entropy callback semantics. In some cases - there is no multiple of the block length between min_len and - max_len. Allow the callback to return more than max_len bytes - of entropy but discard any extra: it is the callback's responsibility - to ensure that the extra data discarded does not impact the - requested amount of entropy. - [Steve Henson] - - *) Add PRNG security strength checks to RSA, DSA and ECDSA using - information in FIPS186-3, SP800-57 and SP800-131A. - [Steve Henson] - - *) CCM support via EVP. Interface is very similar to GCM case except we - must supply all data in one chunk (i.e. no update, final) and the - message length must be supplied if AAD is used. Add algorithm test - support. - [Steve Henson] - - *) Initial version of POST overhaul. Add POST callback to allow the status - of POST to be monitored and/or failures induced. Modify fips_test_suite - to use callback. Always run all selftests even if one fails. - [Steve Henson] - - *) XTS support including algorithm test driver in the fips_gcmtest program. - Note: this does increase the maximum key length from 32 to 64 bytes but - there should be no binary compatibility issues as existing applications - will never use XTS mode. - [Steve Henson] - - *) Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies - to OpenSSL RAND code and replace with a tiny FIPS RAND API which also - performs algorithm blocking for unapproved PRNG types. Also do not - set PRNG type in FIPS_mode_set(): leave this to the application. - Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with - the standard OpenSSL PRNG: set additional data to a date time vector. - [Steve Henson] - - *) Rename old X9.31 PRNG functions of the form FIPS_rand* to FIPS_x931*. - This shouldn't present any incompatibility problems because applications - shouldn't be using these directly and any that are will need to rethink - anyway as the X9.31 PRNG is now deprecated by FIPS 140-2 - [Steve Henson] - - *) Extensive self tests and health checking required by SP800-90 DRBG. - Remove strength parameter from FIPS_drbg_instantiate and always - instantiate at maximum supported strength. - [Steve Henson] - - *) Add ECDH code to fips module and fips_ecdhvs for primitives only testing. - [Steve Henson] - - *) New algorithm test program fips_dhvs to handle DH primitives only testing. - [Steve Henson] - - *) New function DH_compute_key_padded() to compute a DH key and pad with - leading zeroes if needed: this complies with SP800-56A et al. - [Steve Henson] - - *) Initial implementation of SP800-90 DRBGs for Hash and CTR. Not used by - anything, incomplete, subject to change and largely untested at present. - [Steve Henson] - - *) Modify fipscanisteronly build option to only build the necessary object - files by filtering FIPS_EX_OBJ through a perl script in crypto/Makefile. - [Steve Henson] - - *) Add experimental option FIPSSYMS to give all symbols in - fipscanister.o and FIPS or fips prefix. This will avoid - conflicts with future versions of OpenSSL. Add perl script - util/fipsas.pl to preprocess assembly language source files - and rename any affected symbols. - [Steve Henson] - - *) Add selftest checks and algorithm block of non-fips algorithms in - FIPS mode. Remove DES2 from selftests. - [Steve Henson] - - *) Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just - return internal method without any ENGINE dependencies. Add new - tiny fips sign and verify functions. - [Steve Henson] - - *) New build option no-ec2m to disable characteristic 2 code. - [Steve Henson] - - *) New build option "fipscanisteronly". This only builds fipscanister.o - and (currently) associated fips utilities. Uses the file Makefile.fips - instead of Makefile.org as the prototype. - [Steve Henson] - - *) Add some FIPS mode restrictions to GCM. Add internal IV generator. - Update fips_gcmtest to use IV generator. - [Steve Henson] - - *) Initial, experimental EVP support for AES-GCM. AAD can be input by - setting output buffer to NULL. The *Final function must be - called although it will not retrieve any additional data. The tag - can be set or retrieved with a ctrl. The IV length is by default 12 - bytes (96 bits) but can be set to an alternative value. If the IV - length exceeds the maximum IV length (currently 16 bytes) it cannot be - set before the key. - [Steve Henson] - - *) New flag in ciphers: EVP_CIPH_FLAG_CUSTOM_CIPHER. This means the - underlying do_cipher function handles all cipher semantics itself - including padding and finalisation. This is useful if (for example) - an ENGINE cipher handles block padding itself. The behaviour of - do_cipher is subtly changed if this flag is set: the return value - is the number of characters written to the output buffer (zero is - no longer an error code) or a negative error code. Also if the - input buffer is NULL and length 0 finalisation should be performed. - [Steve Henson] - - *) If a candidate issuer certificate is already part of the constructed - path ignore it: new debug notification X509_V_ERR_PATH_LOOP for this case. - [Steve Henson] - - *) Improve forward-security support: add functions - - void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, int (*cb)(SSL *ssl, int is_forward_secure)) - void SSL_set_not_resumable_session_callback(SSL *ssl, int (*cb)(SSL *ssl, int is_forward_secure)) - - for use by SSL/TLS servers; the callback function will be called whenever a - new session is created, and gets to decide whether the session may be - cached to make it resumable (return 0) or not (return 1). (As by the - SSL/TLS protocol specifications, the session_id sent by the server will be - empty to indicate that the session is not resumable; also, the server will - not generate RFC 4507 (RFC 5077) session tickets.) - - A simple reasonable callback implementation is to return is_forward_secure. - This parameter will be set to 1 or 0 depending on the ciphersuite selected - by the SSL/TLS server library, indicating whether it can provide forward - security. - [Emilia Käsper (Google)] - - *) New -verify_name option in command line utilities to set verification - parameters by name. - [Steve Henson] - - *) Initial CMAC implementation. WARNING: EXPERIMENTAL, API MAY CHANGE. - Add CMAC pkey methods. - [Steve Henson] - - *) Experimental renegotiation in s_server -www mode. If the client - browses /reneg connection is renegotiated. If /renegcert it is - renegotiated requesting a certificate. - [Steve Henson] - - *) Add an "external" session cache for debugging purposes to s_server. This - should help trace issues which normally are only apparent in deployed - multi-process servers. - [Steve Henson] - - *) Extensive audit of libcrypto with DEBUG_UNUSED. Fix many cases where - return value is ignored. NB. The functions RAND_add(), RAND_seed(), - BIO_set_cipher() and some obscure PEM functions were changed so they - can now return an error. The RAND changes required a change to the - RAND_METHOD structure. - [Steve Henson] - - *) New macro __owur for "OpenSSL Warn Unused Result". This makes use of - a gcc attribute to warn if the result of a function is ignored. This - is enable if DEBUG_UNUSED is set. Add to several functions in evp.h - whose return value is often ignored. - [Steve Henson] - - *) New -noct, -requestct, -requirect and -ctlogfile options for s_client. - These allow SCTs (signed certificate timestamps) to be requested and - validated when establishing a connection. - [Rob Percival ] - - Changes between 1.0.2g and 1.0.2h [3 May 2016] - - *) Prevent padding oracle in AES-NI CBC MAC check - - A MITM attacker can use a padding oracle attack to decrypt traffic - when the connection uses an AES CBC cipher and the server support - AES-NI. - - This issue was introduced as part of the fix for Lucky 13 padding - attack (CVE-2013-0169). The padding check was rewritten to be in - constant time by making sure that always the same bytes are read and - compared against either the MAC or padding bytes. But it no longer - checked that there was enough data to have both the MAC and padding - bytes. - - This issue was reported by Juraj Somorovsky using TLS-Attacker. - (CVE-2016-2107) - [Kurt Roeckx] - - *) Fix EVP_EncodeUpdate overflow - - An overflow can occur in the EVP_EncodeUpdate() function which is used for - Base64 encoding of binary data. If an attacker is able to supply very large - amounts of input data then a length check can overflow resulting in a heap - corruption. - - Internally to OpenSSL the EVP_EncodeUpdate() function is primarily used by - the PEM_write_bio* family of functions. These are mainly used within the - OpenSSL command line applications, so any application which processes data - from an untrusted source and outputs it as a PEM file should be considered - vulnerable to this issue. User applications that call these APIs directly - with large amounts of untrusted data may also be vulnerable. - - This issue was reported by Guido Vranken. - (CVE-2016-2105) - [Matt Caswell] - - *) Fix EVP_EncryptUpdate overflow - - An overflow can occur in the EVP_EncryptUpdate() function. If an attacker - is able to supply very large amounts of input data after a previous call to - EVP_EncryptUpdate() with a partial block then a length check can overflow - resulting in a heap corruption. Following an analysis of all OpenSSL - internal usage of the EVP_EncryptUpdate() function all usage is one of two - forms. The first form is where the EVP_EncryptUpdate() call is known to be - the first called function after an EVP_EncryptInit(), and therefore that - specific call must be safe. The second form is where the length passed to - EVP_EncryptUpdate() can be seen from the code to be some small value and - therefore there is no possibility of an overflow. Since all instances are - one of these two forms, it is believed that there can be no overflows in - internal code due to this problem. It should be noted that - EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths. - Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances - of these calls have also been analysed too and it is believed there are no - instances in internal usage where an overflow could occur. - - This issue was reported by Guido Vranken. - (CVE-2016-2106) - [Matt Caswell] - - *) Prevent ASN.1 BIO excessive memory allocation - - When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio() - a short invalid encoding can cause allocation of large amounts of memory - potentially consuming excessive resources or exhausting memory. - - Any application parsing untrusted data through d2i BIO functions is - affected. The memory based functions such as d2i_X509() are *not* affected. - Since the memory based functions are used by the TLS library, TLS - applications are not affected. - - This issue was reported by Brian Carpenter. - (CVE-2016-2109) - [Stephen Henson] - - *) EBCDIC overread - - ASN1 Strings that are over 1024 bytes can cause an overread in applications - using the X509_NAME_oneline() function on EBCDIC systems. This could result - in arbitrary stack data being returned in the buffer. - - This issue was reported by Guido Vranken. - (CVE-2016-2176) - [Matt Caswell] - - *) Modify behavior of ALPN to invoke callback after SNI/servername - callback, such that updates to the SSL_CTX affect ALPN. - [Todd Short] - - *) Remove LOW from the DEFAULT cipher list. This removes singles DES from the - default. - [Kurt Roeckx] - - *) Only remove the SSLv2 methods with the no-ssl2-method option. When the - methods are enabled and ssl2 is disabled the methods return NULL. - [Kurt Roeckx] - - Changes between 1.0.2f and 1.0.2g [1 Mar 2016] - - * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL. - Builds that are not configured with "enable-weak-ssl-ciphers" will not - provide any "EXPORT" or "LOW" strength ciphers. - [Viktor Dukhovni] - - * Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2 - is by default disabled at build-time. Builds that are not configured with - "enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used, - users who want to negotiate SSLv2 via the version-flexible SSLv23_method() - will need to explicitly call either of: - - SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2); - or - SSL_clear_options(ssl, SSL_OP_NO_SSLv2); - - as appropriate. Even if either of those is used, or the application - explicitly uses the version-specific SSLv2_method() or its client and - server variants, SSLv2 ciphers vulnerable to exhaustive search key - recovery have been removed. Specifically, the SSLv2 40-bit EXPORT - ciphers, and SSLv2 56-bit DES are no longer available. - (CVE-2016-0800) - [Viktor Dukhovni] - - *) Fix a double-free in DSA code - - A double free bug was discovered when OpenSSL parses malformed DSA private - keys and could lead to a DoS attack or memory corruption for applications - that receive DSA private keys from untrusted sources. This scenario is - considered rare. - - This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using - libFuzzer. - (CVE-2016-0705) - [Stephen Henson] - - *) Disable SRP fake user seed to address a server memory leak. - - Add a new method SRP_VBASE_get1_by_user that handles the seed properly. - - SRP_VBASE_get_by_user had inconsistent memory management behaviour. - In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user - was changed to ignore the "fake user" SRP seed, even if the seed - is configured. - - Users should use SRP_VBASE_get1_by_user instead. Note that in - SRP_VBASE_get1_by_user, caller must free the returned value. Note - also that even though configuring the SRP seed attempts to hide - invalid usernames by continuing the handshake with fake - credentials, this behaviour is not constant time and no strong - guarantees are made that the handshake is indistinguishable from - that of a valid user. - (CVE-2016-0798) - [Emilia Käsper] - - *) Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption - - In the BN_hex2bn function the number of hex digits is calculated using an - int value |i|. Later |bn_expand| is called with a value of |i * 4|. For - large values of |i| this can result in |bn_expand| not allocating any - memory because |i * 4| is negative. This can leave the internal BIGNUM data - field as NULL leading to a subsequent NULL ptr deref. For very large values - of |i|, the calculation |i * 4| could be a positive value smaller than |i|. - In this case memory is allocated to the internal BIGNUM data field, but it - is insufficiently sized leading to heap corruption. A similar issue exists - in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn - is ever called by user applications with very large untrusted hex/dec data. - This is anticipated to be a rare occurrence. - - All OpenSSL internal usage of these functions use data that is not expected - to be untrusted, e.g. config file data or application command line - arguments. If user developed applications generate config file data based - on untrusted data then it is possible that this could also lead to security - consequences. This is also anticipated to be rare. - - This issue was reported to OpenSSL by Guido Vranken. - (CVE-2016-0797) - [Matt Caswell] - - *) Fix memory issues in BIO_*printf functions - - The internal |fmtstr| function used in processing a "%s" format string in - the BIO_*printf functions could overflow while calculating the length of a - string and cause an OOB read when printing very long strings. - - Additionally the internal |doapr_outch| function can attempt to write to an - OOB memory location (at an offset from the NULL pointer) in the event of a - memory allocation failure. In 1.0.2 and below this could be caused where - the size of a buffer to be allocated is greater than INT_MAX. E.g. this - could be in processing a very long "%s" format string. Memory leaks can - also occur. - - The first issue may mask the second issue dependent on compiler behaviour. - These problems could enable attacks where large amounts of untrusted data - is passed to the BIO_*printf functions. If applications use these functions - in this way then they could be vulnerable. OpenSSL itself uses these - functions when printing out human-readable dumps of ASN.1 data. Therefore - applications that print this data could be vulnerable if the data is from - untrusted sources. OpenSSL command line applications could also be - vulnerable where they print out ASN.1 data, or if untrusted data is passed - as command line arguments. - - Libssl is not considered directly vulnerable. Additionally certificates etc - received via remote connections via libssl are also unlikely to be able to - trigger these issues because of message size limits enforced within libssl. - - This issue was reported to OpenSSL Guido Vranken. - (CVE-2016-0799) - [Matt Caswell] - - *) Side channel attack on modular exponentiation - - A side-channel attack was found which makes use of cache-bank conflicts on - the Intel Sandy-Bridge microarchitecture which could lead to the recovery - of RSA keys. The ability to exploit this issue is limited as it relies on - an attacker who has control of code in a thread running on the same - hyper-threaded core as the victim thread which is performing decryptions. - - This issue was reported to OpenSSL by Yuval Yarom, The University of - Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and - Nadia Heninger, University of Pennsylvania with more information at - http://cachebleed.info. - (CVE-2016-0702) - [Andy Polyakov] - - *) Change the req app to generate a 2048-bit RSA/DSA key by default, - if no keysize is specified with default_bits. This fixes an - omission in an earlier change that changed all RSA/DSA key generation - apps to use 2048 bits by default. - [Emilia Käsper] - - Changes between 1.0.2e and 1.0.2f [28 Jan 2016] - *) DH small subgroups - - Historically OpenSSL only ever generated DH parameters based on "safe" - primes. More recently (in version 1.0.2) support was provided for - generating X9.42 style parameter files such as those required for RFC 5114 - support. The primes used in such files may not be "safe". Where an - application is using DH configured with parameters based on primes that are - not "safe" then an attacker could use this fact to find a peer's private - DH exponent. This attack requires that the attacker complete multiple - handshakes in which the peer uses the same private DH exponent. For example - this could be used to discover a TLS server's private DH exponent if it's - reusing the private DH exponent or it's using a static DH ciphersuite. - - OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in - TLS. It is not on by default. If the option is not set then the server - reuses the same private DH exponent for the life of the server process and - would be vulnerable to this attack. It is believed that many popular - applications do set this option and would therefore not be at risk. - - The fix for this issue adds an additional check where a "q" parameter is - available (as is the case in X9.42 based parameters). This detects the - only known attack, and is the only possible defense for static DH - ciphersuites. This could have some performance impact. - - Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by - default and cannot be disabled. This could have some performance impact. - - This issue was reported to OpenSSL by Antonio Sanso (Adobe). - (CVE-2016-0701) - [Matt Caswell] - - *) SSLv2 doesn't block disabled ciphers - - A malicious client can negotiate SSLv2 ciphers that have been disabled on - the server and complete SSLv2 handshakes even if all SSLv2 ciphers have - been disabled, provided that the SSLv2 protocol was not also disabled via - SSL_OP_NO_SSLv2. - - This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram - and Sebastian Schinzel. - (CVE-2015-3197) - [Viktor Dukhovni] - - Changes between 1.0.2d and 1.0.2e [3 Dec 2015] - - *) BN_mod_exp may produce incorrect results on x86_64 - - There is a carry propagating bug in the x86_64 Montgomery squaring - procedure. No EC algorithms are affected. Analysis suggests that attacks - against RSA and DSA as a result of this defect would be very difficult to - perform and are not believed likely. Attacks against DH are considered just - feasible (although very difficult) because most of the work necessary to - deduce information about a private key may be performed offline. The amount - of resources required for such an attack would be very significant and - likely only accessible to a limited number of attackers. An attacker would - additionally need online access to an unpatched system using the target - private key in a scenario with persistent DH parameters and a private - key that is shared between multiple clients. For example this can occur by - default in OpenSSL DHE based SSL/TLS ciphersuites. - - This issue was reported to OpenSSL by Hanno Böck. - (CVE-2015-3193) - [Andy Polyakov] - - *) Certificate verify crash with missing PSS parameter - - The signature verification routines will crash with a NULL pointer - dereference if presented with an ASN.1 signature using the RSA PSS - algorithm and absent mask generation function parameter. Since these - routines are used to verify certificate signature algorithms this can be - used to crash any certificate verification operation and exploited in a - DoS attack. Any application which performs certificate verification is - vulnerable including OpenSSL clients and servers which enable client - authentication. - - This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG). - (CVE-2015-3194) - [Stephen Henson] - - *) X509_ATTRIBUTE memory leak - - When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak - memory. This structure is used by the PKCS#7 and CMS routines so any - application which reads PKCS#7 or CMS data from untrusted sources is - affected. SSL/TLS is not affected. - - This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using - libFuzzer. - (CVE-2015-3195) - [Stephen Henson] - - *) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs. - This changes the decoding behaviour for some invalid messages, - though the change is mostly in the more lenient direction, and - legacy behaviour is preserved as much as possible. - [Emilia Käsper] - - *) In DSA_generate_parameters_ex, if the provided seed is too short, - return an error - [Rich Salz and Ismo Puustinen ] - - Changes between 1.0.2c and 1.0.2d [9 Jul 2015] - - *) Alternate chains certificate forgery - - During certificate verification, OpenSSL will attempt to find an - alternative certificate chain if the first attempt to build such a chain - fails. An error in the implementation of this logic can mean that an - attacker could cause certain checks on untrusted certificates to be - bypassed, such as the CA flag, enabling them to use a valid leaf - certificate to act as a CA and "issue" an invalid certificate. - - This issue was reported to OpenSSL by Adam Langley/David Benjamin - (Google/BoringSSL). - [Matt Caswell] - - Changes between 1.0.2b and 1.0.2c [12 Jun 2015] - - *) Fix HMAC ABI incompatibility. The previous version introduced an ABI - incompatibility in the handling of HMAC. The previous ABI has now been - restored. - [Matt Caswell] - - Changes between 1.0.2a and 1.0.2b [11 Jun 2015] - - *) Malformed ECParameters causes infinite loop - - When processing an ECParameters structure OpenSSL enters an infinite loop - if the curve specified is over a specially malformed binary polynomial - field. - - This can be used to perform denial of service against any - system which processes public keys, certificate requests or - certificates. This includes TLS clients and TLS servers with - client authentication enabled. - - This issue was reported to OpenSSL by Joseph Barr-Pixton. - (CVE-2015-1788) - [Andy Polyakov] - - *) Exploitable out-of-bounds read in X509_cmp_time - - X509_cmp_time does not properly check the length of the ASN1_TIME - string and can read a few bytes out of bounds. In addition, - X509_cmp_time accepts an arbitrary number of fractional seconds in the - time string. - - An attacker can use this to craft malformed certificates and CRLs of - various sizes and potentially cause a segmentation fault, resulting in - a DoS on applications that verify certificates or CRLs. TLS clients - that verify CRLs are affected. TLS clients and servers with client - authentication enabled may be affected if they use custom verification - callbacks. - - This issue was reported to OpenSSL by Robert Swiecki (Google), and - independently by Hanno Böck. - (CVE-2015-1789) - [Emilia Käsper] - - *) PKCS7 crash with missing EnvelopedContent - - The PKCS#7 parsing code does not handle missing inner EncryptedContent - correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs - with missing content and trigger a NULL pointer dereference on parsing. - - Applications that decrypt PKCS#7 data or otherwise parse PKCS#7 - structures from untrusted sources are affected. OpenSSL clients and - servers are not affected. - - This issue was reported to OpenSSL by Michal Zalewski (Google). - (CVE-2015-1790) - [Emilia Käsper] - - *) CMS verify infinite loop with unknown hash function - - When verifying a signedData message the CMS code can enter an infinite loop - if presented with an unknown hash function OID. This can be used to perform - denial of service against any system which verifies signedData messages using - the CMS code. - This issue was reported to OpenSSL by Johannes Bauer. - (CVE-2015-1792) - [Stephen Henson] - - *) Race condition handling NewSessionTicket - - If a NewSessionTicket is received by a multi-threaded client when attempting to - reuse a previous ticket then a race condition can occur potentially leading to - a double free of the ticket data. - (CVE-2015-1791) - [Matt Caswell] - - *) Only support 256-bit or stronger elliptic curves with the - 'ecdh_auto' setting (server) or by default (client). Of supported - curves, prefer P-256 (both). - [Emilia Kasper] - - Changes between 1.0.2 and 1.0.2a [19 Mar 2015] - - *) ClientHello sigalgs DoS fix - - If a client connects to an OpenSSL 1.0.2 server and renegotiates with an - invalid signature algorithms extension a NULL pointer dereference will - occur. This can be exploited in a DoS attack against the server. - - This issue was was reported to OpenSSL by David Ramos of Stanford - University. - (CVE-2015-0291) - [Stephen Henson and Matt Caswell] - - *) Multiblock corrupted pointer fix - - OpenSSL 1.0.2 introduced the "multiblock" performance improvement. This - feature only applies on 64 bit x86 architecture platforms that support AES - NI instructions. A defect in the implementation of "multiblock" can cause - OpenSSL's internal write buffer to become incorrectly set to NULL when - using non-blocking IO. Typically, when the user application is using a - socket BIO for writing, this will only result in a failed connection. - However if some other BIO is used then it is likely that a segmentation - fault will be triggered, thus enabling a potential DoS attack. - - This issue was reported to OpenSSL by Daniel Danner and Rainer Mueller. - (CVE-2015-0290) - [Matt Caswell] - - *) Segmentation fault in DTLSv1_listen fix - - The DTLSv1_listen function is intended to be stateless and processes the - initial ClientHello from many peers. It is common for user code to loop - over the call to DTLSv1_listen until a valid ClientHello is received with - an associated cookie. A defect in the implementation of DTLSv1_listen means - that state is preserved in the SSL object from one invocation to the next - that can lead to a segmentation fault. Errors processing the initial - ClientHello can trigger this scenario. An example of such an error could be - that a DTLS1.0 only client is attempting to connect to a DTLS1.2 only - server. - - This issue was reported to OpenSSL by Per Allansson. - (CVE-2015-0207) - [Matt Caswell] - - *) Segmentation fault in ASN1_TYPE_cmp fix - - The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is - made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check - certificate signature algorithm consistency this can be used to crash any - certificate verification operation and exploited in a DoS attack. Any - application which performs certificate verification is vulnerable including - OpenSSL clients and servers which enable client authentication. - (CVE-2015-0286) - [Stephen Henson] - - *) Segmentation fault for invalid PSS parameters fix - - The signature verification routines will crash with a NULL pointer - dereference if presented with an ASN.1 signature using the RSA PSS - algorithm and invalid parameters. Since these routines are used to verify - certificate signature algorithms this can be used to crash any - certificate verification operation and exploited in a DoS attack. Any - application which performs certificate verification is vulnerable including - OpenSSL clients and servers which enable client authentication. - - This issue was was reported to OpenSSL by Brian Carpenter. - (CVE-2015-0208) - [Stephen Henson] - - *) ASN.1 structure reuse memory corruption fix - - Reusing a structure in ASN.1 parsing may allow an attacker to cause - memory corruption via an invalid write. Such reuse is and has been - strongly discouraged and is believed to be rare. - - Applications that parse structures containing CHOICE or ANY DEFINED BY - components may be affected. Certificate parsing (d2i_X509 and related - functions) are however not affected. OpenSSL clients and servers are - not affected. - (CVE-2015-0287) - [Stephen Henson] - - *) PKCS7 NULL pointer dereferences fix - - The PKCS#7 parsing code does not handle missing outer ContentInfo - correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with - missing content and trigger a NULL pointer dereference on parsing. - - Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or - otherwise parse PKCS#7 structures from untrusted sources are - affected. OpenSSL clients and servers are not affected. - - This issue was reported to OpenSSL by Michal Zalewski (Google). - (CVE-2015-0289) - [Emilia Käsper] - - *) DoS via reachable assert in SSLv2 servers fix - - A malicious client can trigger an OPENSSL_assert (i.e., an abort) in - servers that both support SSLv2 and enable export cipher suites by sending - a specially crafted SSLv2 CLIENT-MASTER-KEY message. - - This issue was discovered by Sean Burford (Google) and Emilia Käsper - (OpenSSL development team). - (CVE-2015-0293) - [Emilia Käsper] - - *) Empty CKE with client auth and DHE fix - - If client auth is used then a server can seg fault in the event of a DHE - ciphersuite being selected and a zero length ClientKeyExchange message - being sent by the client. This could be exploited in a DoS attack. - (CVE-2015-1787) - [Matt Caswell] - - *) Handshake with unseeded PRNG fix - - Under certain conditions an OpenSSL 1.0.2 client can complete a handshake - with an unseeded PRNG. The conditions are: - - The client is on a platform where the PRNG has not been seeded - automatically, and the user has not seeded manually - - A protocol specific client method version has been used (i.e. not - SSL_client_methodv23) - - A ciphersuite is used that does not require additional random data from - the PRNG beyond the initial ClientHello client random (e.g. PSK-RC4-SHA). - - If the handshake succeeds then the client random that has been used will - have been generated from a PRNG with insufficient entropy and therefore the - output may be predictable. - - For example using the following command with an unseeded openssl will - succeed on an unpatched platform: - - openssl s_client -psk 1a2b3c4d -tls1_2 -cipher PSK-RC4-SHA - (CVE-2015-0285) - [Matt Caswell] - - *) Use After Free following d2i_ECPrivatekey error fix - - A malformed EC private key file consumed via the d2i_ECPrivateKey function - could cause a use after free condition. This, in turn, could cause a double - free in several private key parsing functions (such as d2i_PrivateKey - or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption - for applications that receive EC private keys from untrusted - sources. This scenario is considered rare. - - This issue was discovered by the BoringSSL project and fixed in their - commit 517073cd4b. - (CVE-2015-0209) - [Matt Caswell] - - *) X509_to_X509_REQ NULL pointer deref fix - - The function X509_to_X509_REQ will crash with a NULL pointer dereference if - the certificate key is invalid. This function is rarely used in practice. - - This issue was discovered by Brian Carpenter. - (CVE-2015-0288) - [Stephen Henson] - - *) Removed the export ciphers from the DEFAULT ciphers - [Kurt Roeckx] - - Changes between 1.0.1l and 1.0.2 [22 Jan 2015] - - *) Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g. - ARMv5 through ARMv8, as opposite to "locking" it to single one. - So far those who have to target multiple platforms would compromise - and argue that binary targeting say ARMv5 would still execute on - ARMv8. "Universal" build resolves this compromise by providing - near-optimal performance even on newer platforms. - [Andy Polyakov] - - *) Accelerated NIST P-256 elliptic curve implementation for x86_64 - (other platforms pending). - [Shay Gueron & Vlad Krasnov (Intel Corp), Andy Polyakov] - - *) Add support for the SignedCertificateTimestampList certificate and - OCSP response extensions from RFC6962. - [Rob Stradling] - - *) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.) - for corner cases. (Certain input points at infinity could lead to - bogus results, with non-infinity inputs mapped to infinity too.) - [Bodo Moeller] - - *) Initial support for PowerISA 2.0.7, first implemented in POWER8. - This covers AES, SHA256/512 and GHASH. "Initial" means that most - common cases are optimized and there still is room for further - improvements. Vector Permutation AES for Altivec is also added. - [Andy Polyakov] - - *) Add support for little-endian ppc64 Linux target. - [Marcelo Cerri (IBM)] - - *) Initial support for AMRv8 ISA crypto extensions. This covers AES, - SHA1, SHA256 and GHASH. "Initial" means that most common cases - are optimized and there still is room for further improvements. - Both 32- and 64-bit modes are supported. - [Andy Polyakov, Ard Biesheuvel (Linaro)] - - *) Improved ARMv7 NEON support. - [Andy Polyakov] - - *) Support for SPARC Architecture 2011 crypto extensions, first - implemented in SPARC T4. This covers AES, DES, Camellia, SHA1, - SHA256/512, MD5, GHASH and modular exponentiation. - [Andy Polyakov, David Miller] - - *) Accelerated modular exponentiation for Intel processors, a.k.a. - RSAZ. - [Shay Gueron & Vlad Krasnov (Intel Corp)] - - *) Support for new and upcoming Intel processors, including AVX2, - BMI and SHA ISA extensions. This includes additional "stitched" - implementations, AESNI-SHA256 and GCM, and multi-buffer support - for TLS encrypt. - - This work was sponsored by Intel Corp. - [Andy Polyakov] - - *) Support for DTLS 1.2. This adds two sets of DTLS methods: DTLS_*_method() - supports both DTLS 1.2 and 1.0 and should use whatever version the peer - supports and DTLSv1_2_*_method() which supports DTLS 1.2 only. - [Steve Henson] - - *) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file(): - this fixes a limitation in previous versions of OpenSSL. - [Steve Henson] - - *) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest, - MGF1 digest and OAEP label. - [Steve Henson] - - *) Add EVP support for key wrapping algorithms, to avoid problems with - existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in - the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap - algorithms and include tests cases. - [Steve Henson] - - *) Add functions to allocate and set the fields of an ECDSA_METHOD - structure. - [Douglas E. Engert, Steve Henson] - - *) New functions OPENSSL_gmtime_diff and ASN1_TIME_diff to find the - difference in days and seconds between two tm or ASN1_TIME structures. - [Steve Henson] - - *) Add -rev test option to s_server to just reverse order of characters - received by client and send back to server. Also prints an abbreviated - summary of the connection parameters. - [Steve Henson] - - *) New option -brief for s_client and s_server to print out a brief summary - of connection parameters. - [Steve Henson] - - *) Add callbacks for arbitrary TLS extensions. - [Trevor Perrin and Ben Laurie] - - *) New option -crl_download in several openssl utilities to download CRLs - from CRLDP extension in certificates. - [Steve Henson] - - *) New options -CRL and -CRLform for s_client and s_server for CRLs. - [Steve Henson] - - *) New function X509_CRL_diff to generate a delta CRL from the difference - of two full CRLs. Add support to "crl" utility. - [Steve Henson] - - *) New functions to set lookup_crls function and to retrieve - X509_STORE from X509_STORE_CTX. - [Steve Henson] - - *) Print out deprecated issuer and subject unique ID fields in - certificates. - [Steve Henson] - - *) Extend OCSP I/O functions so they can be used for simple general purpose - HTTP as well as OCSP. New wrapper function which can be used to download - CRLs using the OCSP API. - [Steve Henson] - - *) Delegate command line handling in s_client/s_server to SSL_CONF APIs. - [Steve Henson] - - *) SSL_CONF* functions. These provide a common framework for application - configuration using configuration files or command lines. - [Steve Henson] - - *) SSL/TLS tracing code. This parses out SSL/TLS records using the - message callback and prints the results. Needs compile time option - "enable-ssl-trace". New options to s_client and s_server to enable - tracing. - [Steve Henson] - - *) New ctrl and macro to retrieve supported points extensions. - Print out extension in s_server and s_client. - [Steve Henson] - - *) New functions to retrieve certificate signature and signature - OID NID. - [Steve Henson] - - *) Add functions to retrieve and manipulate the raw cipherlist sent by a - client to OpenSSL. - [Steve Henson] - - *) New Suite B modes for TLS code. These use and enforce the requirements - of RFC6460: restrict ciphersuites, only permit Suite B algorithms and - only use Suite B curves. The Suite B modes can be set by using the - strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring. - [Steve Henson] - - *) New chain verification flags for Suite B levels of security. Check - algorithms are acceptable when flags are set in X509_verify_cert. - [Steve Henson] - - *) Make tls1_check_chain return a set of flags indicating checks passed - by a certificate chain. Add additional tests to handle client - certificates: checks for matching certificate type and issuer name - comparison. - [Steve Henson] - - *) If an attempt is made to use a signature algorithm not in the peer - preference list abort the handshake. If client has no suitable - signature algorithms in response to a certificate request do not - use the certificate. - [Steve Henson] - - *) If server EC tmp key is not in client preference list abort handshake. - [Steve Henson] - - *) Add support for certificate stores in CERT structure. This makes it - possible to have different stores per SSL structure or one store in - the parent SSL_CTX. Include distinct stores for certificate chain - verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN - to build and store a certificate chain in CERT structure: returning - an error if the chain cannot be built: this will allow applications - to test if a chain is correctly configured. - - Note: if the CERT based stores are not set then the parent SSL_CTX - store is used to retain compatibility with existing behaviour. - - [Steve Henson] - - *) New function ssl_set_client_disabled to set a ciphersuite disabled - mask based on the current session, check mask when sending client - hello and checking the requested ciphersuite. - [Steve Henson] - - *) New ctrls to retrieve and set certificate types in a certificate - request message. Print out received values in s_client. If certificate - types is not set with custom values set sensible values based on - supported signature algorithms. - [Steve Henson] - - *) Support for distinct client and server supported signature algorithms. - [Steve Henson] - - *) Add certificate callback. If set this is called whenever a certificate - is required by client or server. An application can decide which - certificate chain to present based on arbitrary criteria: for example - supported signature algorithms. Add very simple example to s_server. - This fixes many of the problems and restrictions of the existing client - certificate callback: for example you can now clear an existing - certificate and specify the whole chain. - [Steve Henson] - - *) Add new "valid_flags" field to CERT_PKEY structure which determines what - the certificate can be used for (if anything). Set valid_flags field - in new tls1_check_chain function. Simplify ssl_set_cert_masks which used - to have similar checks in it. - - Add new "cert_flags" field to CERT structure and include a "strict mode". - This enforces some TLS certificate requirements (such as only permitting - certificate signature algorithms contained in the supported algorithms - extension) which some implementations ignore: this option should be used - with caution as it could cause interoperability issues. - [Steve Henson] - - *) Update and tidy signature algorithm extension processing. Work out - shared signature algorithms based on preferences and peer algorithms - and print them out in s_client and s_server. Abort handshake if no - shared signature algorithms. - [Steve Henson] - - *) Add new functions to allow customised supported signature algorithms - for SSL and SSL_CTX structures. Add options to s_client and s_server - to support them. - [Steve Henson] - - *) New function SSL_certs_clear() to delete all references to certificates - from an SSL structure. Before this once a certificate had been added - it couldn't be removed. - [Steve Henson] - - *) Integrate hostname, email address and IP address checking with certificate - verification. New verify options supporting checking in openssl utility. - [Steve Henson] - - *) Fixes and wildcard matching support to hostname and email checking - functions. Add manual page. - [Florian Weimer (Red Hat Product Security Team)] - - *) New functions to check a hostname email or IP address against a - certificate. Add options x509 utility to print results of checks against - a certificate. - [Steve Henson] - - *) Fix OCSP checking. - [Rob Stradling and Ben Laurie] - - *) Initial experimental support for explicitly trusted non-root CAs. - OpenSSL still tries to build a complete chain to a root but if an - intermediate CA has a trust setting included that is used. The first - setting is used: whether to trust (e.g., -addtrust option to the x509 - utility) or reject. - [Steve Henson] - - *) Add -trusted_first option which attempts to find certificates in the - trusted store even if an untrusted chain is also supplied. - [Steve Henson] - - *) MIPS assembly pack updates: support for MIPS32r2 and SmartMIPS ASE, - platform support for Linux and Android. - [Andy Polyakov] - - *) Support for linux-x32, ILP32 environment in x86_64 framework. - [Andy Polyakov] - - *) Experimental multi-implementation support for FIPS capable OpenSSL. - When in FIPS mode the approved implementations are used as normal, - when not in FIPS mode the internal unapproved versions are used instead. - This means that the FIPS capable OpenSSL isn't forced to use the - (often lower performance) FIPS implementations outside FIPS mode. - [Steve Henson] - - *) Transparently support X9.42 DH parameters when calling - PEM_read_bio_DHparameters. This means existing applications can handle - the new parameter format automatically. - [Steve Henson] - - *) Initial experimental support for X9.42 DH parameter format: mainly - to support use of 'q' parameter for RFC5114 parameters. - [Steve Henson] - - *) Add DH parameters from RFC5114 including test data to dhtest. - [Steve Henson] - - *) Support for automatic EC temporary key parameter selection. If enabled - the most preferred EC parameters are automatically used instead of - hardcoded fixed parameters. Now a server just has to call: - SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically - support ECDH and use the most appropriate parameters. - [Steve Henson] - - *) Enhance and tidy EC curve and point format TLS extension code. Use - static structures instead of allocation if default values are used. - New ctrls to set curves we wish to support and to retrieve shared curves. - Print out shared curves in s_server. New options to s_server and s_client - to set list of supported curves. - [Steve Henson] - - *) New ctrls to retrieve supported signature algorithms and - supported curve values as an array of NIDs. Extend openssl utility - to print out received values. - [Steve Henson] - - *) Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert - between NIDs and the more common NIST names such as "P-256". Enhance - ecparam utility and ECC method to recognise the NIST names for curves. - [Steve Henson] - - *) Enhance SSL/TLS certificate chain handling to support different - chains for each certificate instead of one chain in the parent SSL_CTX. - [Steve Henson] - - *) Support for fixed DH ciphersuite client authentication: where both - server and client use DH certificates with common parameters. - [Steve Henson] - - *) Support for fixed DH ciphersuites: those requiring DH server - certificates. - [Steve Henson] - - *) New function i2d_re_X509_tbs for re-encoding the TBS portion of - the certificate. - Note: Related 1.0.2-beta specific macros X509_get_cert_info, - X509_CINF_set_modified, X509_CINF_get_issuer, X509_CINF_get_extensions and - X509_CINF_get_signature were reverted post internal team review. - - Changes between 1.0.1k and 1.0.1l [15 Jan 2015] - - *) Build fixes for the Windows and OpenVMS platforms - [Matt Caswell and Richard Levitte] - - Changes between 1.0.1j and 1.0.1k [8 Jan 2015] - - *) Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS - message can cause a segmentation fault in OpenSSL due to a NULL pointer - dereference. This could lead to a Denial Of Service attack. Thanks to - Markus Stenberg of Cisco Systems, Inc. for reporting this issue. - (CVE-2014-3571) - [Steve Henson] - - *) Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the - dtls1_buffer_record function under certain conditions. In particular this - could occur if an attacker sent repeated DTLS records with the same - sequence number but for the next epoch. The memory leak could be exploited - by an attacker in a Denial of Service attack through memory exhaustion. - Thanks to Chris Mueller for reporting this issue. - (CVE-2015-0206) - [Matt Caswell] - - *) Fix issue where no-ssl3 configuration sets method to NULL. When openssl is - built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl - method would be set to NULL which could later result in a NULL pointer - dereference. Thanks to Frank Schmirler for reporting this issue. - (CVE-2014-3569) - [Kurt Roeckx] - - *) Abort handshake if server key exchange message is omitted for ephemeral - ECDH ciphersuites. - - Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for - reporting this issue. - (CVE-2014-3572) - [Steve Henson] - - *) Remove non-export ephemeral RSA code on client and server. This code - violated the TLS standard by allowing the use of temporary RSA keys in - non-export ciphersuites and could be used by a server to effectively - downgrade the RSA key length used to a value smaller than the server - certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at - INRIA or reporting this issue. - (CVE-2015-0204) - [Steve Henson] - - *) Fixed issue where DH client certificates are accepted without verification. - An OpenSSL server will accept a DH certificate for client authentication - without the certificate verify message. This effectively allows a client to - authenticate without the use of a private key. This only affects servers - which trust a client certificate authority which issues certificates - containing DH keys: these are extremely rare and hardly ever encountered. - Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting - this issue. - (CVE-2015-0205) - [Steve Henson] - - *) Ensure that the session ID context of an SSL is updated when its - SSL_CTX is updated via SSL_set_SSL_CTX. - - The session ID context is typically set from the parent SSL_CTX, - and can vary with the CTX. - [Adam Langley] - - *) Fix various certificate fingerprint issues. - - By using non-DER or invalid encodings outside the signed portion of a - certificate the fingerprint can be changed without breaking the signature. - Although no details of the signed portion of the certificate can be changed - this can cause problems with some applications: e.g. those using the - certificate fingerprint for blacklists. - - 1. Reject signatures with non zero unused bits. - - If the BIT STRING containing the signature has non zero unused bits reject - the signature. All current signature algorithms require zero unused bits. - - 2. Check certificate algorithm consistency. - - Check the AlgorithmIdentifier inside TBS matches the one in the - certificate signature. NB: this will result in signature failure - errors for some broken certificates. - - Thanks to Konrad Kraszewski from Google for reporting this issue. - - 3. Check DSA/ECDSA signatures use DER. - - Re-encode DSA/ECDSA signatures and compare with the original received - signature. Return an error if there is a mismatch. - - This will reject various cases including garbage after signature - (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS - program for discovering this case) and use of BER or invalid ASN.1 INTEGERs - (negative or with leading zeroes). - - Further analysis was conducted and fixes were developed by Stephen Henson - of the OpenSSL core team. - - (CVE-2014-8275) - [Steve Henson] - - *) Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect - results on some platforms, including x86_64. This bug occurs at random - with a very low probability, and is not known to be exploitable in any - way, though its exact impact is difficult to determine. Thanks to Pieter - Wuille (Blockstream) who reported this issue and also suggested an initial - fix. Further analysis was conducted by the OpenSSL development team and - Adam Langley of Google. The final fix was developed by Andy Polyakov of - the OpenSSL core team. - (CVE-2014-3570) - [Andy Polyakov] - - *) Do not resume sessions on the server if the negotiated protocol - version does not match the session's version. Resuming with a different - version, while not strictly forbidden by the RFC, is of questionable - sanity and breaks all known clients. - [David Benjamin, Emilia Käsper] - - *) Tighten handling of the ChangeCipherSpec (CCS) message: reject - early CCS messages during renegotiation. (Note that because - renegotiation is encrypted, this early CCS was not exploitable.) - [Emilia Käsper] - - *) Tighten client-side session ticket handling during renegotiation: - ensure that the client only accepts a session ticket if the server sends - the extension anew in the ServerHello. Previously, a TLS client would - reuse the old extension state and thus accept a session ticket if one was - announced in the initial ServerHello. - - Similarly, ensure that the client requires a session ticket if one - was advertised in the ServerHello. Previously, a TLS client would - ignore a missing NewSessionTicket message. - [Emilia Käsper] - - Changes between 1.0.1i and 1.0.1j [15 Oct 2014] - - *) SRTP Memory Leak. - - A flaw in the DTLS SRTP extension parsing code allows an attacker, who - sends a carefully crafted handshake message, to cause OpenSSL to fail - to free up to 64k of memory causing a memory leak. This could be - exploited in a Denial Of Service attack. This issue affects OpenSSL - 1.0.1 server implementations for both SSL/TLS and DTLS regardless of - whether SRTP is used or configured. Implementations of OpenSSL that - have been compiled with OPENSSL_NO_SRTP defined are not affected. - - The fix was developed by the OpenSSL team. - (CVE-2014-3513) - [OpenSSL team] - - *) Session Ticket Memory Leak. - - When an OpenSSL SSL/TLS/DTLS server receives a session ticket the - integrity of that ticket is first verified. In the event of a session - ticket integrity check failing, OpenSSL will fail to free memory - causing a memory leak. By sending a large number of invalid session - tickets an attacker could exploit this issue in a Denial Of Service - attack. - (CVE-2014-3567) - [Steve Henson] - - *) Build option no-ssl3 is incomplete. - - When OpenSSL is configured with "no-ssl3" as a build option, servers - could accept and complete a SSL 3.0 handshake, and clients could be - configured to send them. - (CVE-2014-3568) - [Akamai and the OpenSSL team] - - *) Add support for TLS_FALLBACK_SCSV. - Client applications doing fallback retries should call - SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV). - (CVE-2014-3566) - [Adam Langley, Bodo Moeller] - - *) Add additional DigestInfo checks. - - Re-encode DigestInto in DER and check against the original when - verifying RSA signature: this will reject any improperly encoded - DigestInfo structures. - - Note: this is a precautionary measure and no attacks are currently known. - - [Steve Henson] - - Changes between 1.0.1h and 1.0.1i [6 Aug 2014] - - *) Fix SRP buffer overrun vulnerability. Invalid parameters passed to the - SRP code can be overrun an internal buffer. Add sanity check that - g, A, B < N to SRP code. - - Thanks to Sean Devlin and Watson Ladd of Cryptography Services, NCC - Group for discovering this issue. - (CVE-2014-3512) - [Steve Henson] - - *) A flaw in the OpenSSL SSL/TLS server code causes the server to negotiate - TLS 1.0 instead of higher protocol versions when the ClientHello message - is badly fragmented. This allows a man-in-the-middle attacker to force a - downgrade to TLS 1.0 even if both the server and the client support a - higher protocol version, by modifying the client's TLS records. - - Thanks to David Benjamin and Adam Langley (Google) for discovering and - researching this issue. - (CVE-2014-3511) - [David Benjamin] - - *) OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject - to a denial of service attack. A malicious server can crash the client - with a null pointer dereference (read) by specifying an anonymous (EC)DH - ciphersuite and sending carefully crafted handshake messages. - - Thanks to Felix Gröbert (Google) for discovering and researching this - issue. - (CVE-2014-3510) - [Emilia Käsper] - - *) By sending carefully crafted DTLS packets an attacker could cause openssl - to leak memory. This can be exploited through a Denial of Service attack. - Thanks to Adam Langley for discovering and researching this issue. - (CVE-2014-3507) - [Adam Langley] - - *) An attacker can force openssl to consume large amounts of memory whilst - processing DTLS handshake messages. This can be exploited through a - Denial of Service attack. - Thanks to Adam Langley for discovering and researching this issue. - (CVE-2014-3506) - [Adam Langley] - - *) An attacker can force an error condition which causes openssl to crash - whilst processing DTLS packets due to memory being freed twice. This - can be exploited through a Denial of Service attack. - Thanks to Adam Langley and Wan-Teh Chang for discovering and researching - this issue. - (CVE-2014-3505) - [Adam Langley] - - *) If a multithreaded client connects to a malicious server using a resumed - session and the server sends an ec point format extension it could write - up to 255 bytes to freed memory. - - Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this - issue. - (CVE-2014-3509) - [Gabor Tyukasz] - - *) A malicious server can crash an OpenSSL client with a null pointer - dereference (read) by specifying an SRP ciphersuite even though it was not - properly negotiated with the client. This can be exploited through a - Denial of Service attack. - - Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for - discovering and researching this issue. - (CVE-2014-5139) - [Steve Henson] - - *) A flaw in OBJ_obj2txt may cause pretty printing functions such as - X509_name_oneline, X509_name_print_ex et al. to leak some information - from the stack. Applications may be affected if they echo pretty printing - output to the attacker. - - Thanks to Ivan Fratric (Google) for discovering this issue. - (CVE-2014-3508) - [Emilia Käsper, and Steve Henson] - - *) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.) - for corner cases. (Certain input points at infinity could lead to - bogus results, with non-infinity inputs mapped to infinity too.) - [Bodo Moeller] - - Changes between 1.0.1g and 1.0.1h [5 Jun 2014] - - *) Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted - handshake can force the use of weak keying material in OpenSSL - SSL/TLS clients and servers. - - Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and - researching this issue. (CVE-2014-0224) - [KIKUCHI Masashi, Steve Henson] - - *) Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an - OpenSSL DTLS client the code can be made to recurse eventually crashing - in a DoS attack. - - Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue. - (CVE-2014-0221) - [Imre Rad, Steve Henson] - - *) Fix DTLS invalid fragment vulnerability. A buffer overrun attack can - be triggered by sending invalid DTLS fragments to an OpenSSL DTLS - client or server. This is potentially exploitable to run arbitrary - code on a vulnerable client or server. - - Thanks to Jüri Aedla for reporting this issue. (CVE-2014-0195) - [Jüri Aedla, Steve Henson] - - *) Fix bug in TLS code where clients enable anonymous ECDH ciphersuites - are subject to a denial of service attack. - - Thanks to Felix Gröbert and Ivan Fratric at Google for discovering - this issue. (CVE-2014-3470) - [Felix Gröbert, Ivan Fratric, Steve Henson] - - *) Harmonize version and its documentation. -f flag is used to display - compilation flags. - [mancha ] - - *) Fix eckey_priv_encode so it immediately returns an error upon a failure - in i2d_ECPrivateKey. - [mancha ] - - *) Fix some double frees. These are not thought to be exploitable. - [mancha ] - - Changes between 1.0.1f and 1.0.1g [7 Apr 2014] - - *) A missing bounds check in the handling of the TLS heartbeat extension - can be used to reveal up to 64k of memory to a connected client or - server. - - Thanks for Neel Mehta of Google Security for discovering this bug and to - Adam Langley and Bodo Moeller for - preparing the fix (CVE-2014-0160) - [Adam Langley, Bodo Moeller] - - *) Fix for the attack described in the paper "Recovering OpenSSL - ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack" - by Yuval Yarom and Naomi Benger. Details can be obtained from: - http://eprint.iacr.org/2014/140 - - Thanks to Yuval Yarom and Naomi Benger for discovering this - flaw and to Yuval Yarom for supplying a fix (CVE-2014-0076) - [Yuval Yarom and Naomi Benger] - - *) TLS pad extension: draft-agl-tls-padding-03 - - Workaround for the "TLS hang bug" (see FAQ and PR#2771): if the - TLS client Hello record length value would otherwise be > 255 and - less that 512 pad with a dummy extension containing zeroes so it - is at least 512 bytes long. - - [Adam Langley, Steve Henson] - - Changes between 1.0.1e and 1.0.1f [6 Jan 2014] - - *) Fix for TLS record tampering bug. A carefully crafted invalid - handshake could crash OpenSSL with a NULL pointer exception. - Thanks to Anton Johansson for reporting this issues. - (CVE-2013-4353) - - *) Keep original DTLS digest and encryption contexts in retransmission - structures so we can use the previous session parameters if they need - to be resent. (CVE-2013-6450) - [Steve Henson] - - *) Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which - avoids preferring ECDHE-ECDSA ciphers when the client appears to be - Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for - several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug - is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing - 10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer. - [Rob Stradling, Adam Langley] - - Changes between 1.0.1d and 1.0.1e [11 Feb 2013] - - *) Correct fix for CVE-2013-0169. The original didn't work on AES-NI - supporting platforms or when small records were transferred. - [Andy Polyakov, Steve Henson] - - Changes between 1.0.1c and 1.0.1d [5 Feb 2013] - - *) Make the decoding of SSLv3, TLS and DTLS CBC records constant time. - - This addresses the flaw in CBC record processing discovered by - Nadhem Alfardan and Kenny Paterson. Details of this attack can be found - at: http://www.isg.rhul.ac.uk/tls/ - - Thanks go to Nadhem Alfardan and Kenny Paterson of the Information - Security Group at Royal Holloway, University of London - (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and - Emilia Käsper for the initial patch. - (CVE-2013-0169) - [Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson] - - *) Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode - ciphersuites which can be exploited in a denial of service attack. - Thanks go to and to Adam Langley for discovering - and detecting this bug and to Wolfgang Ettlinger - for independently discovering this issue. - (CVE-2012-2686) - [Adam Langley] - - *) Return an error when checking OCSP signatures when key is NULL. - This fixes a DoS attack. (CVE-2013-0166) - [Steve Henson] - - *) Make openssl verify return errors. - [Chris Palmer and Ben Laurie] - - *) Call OCSP Stapling callback after ciphersuite has been chosen, so - the right response is stapled. Also change SSL_get_certificate() - so it returns the certificate actually sent. - See http://rt.openssl.org/Ticket/Display.html?id=2836. - [Rob Stradling ] - - *) Fix possible deadlock when decoding public keys. - [Steve Henson] - - *) Don't use TLS 1.0 record version number in initial client hello - if renegotiating. - [Steve Henson] - - Changes between 1.0.1b and 1.0.1c [10 May 2012] - - *) Sanity check record length before skipping explicit IV in TLS - 1.2, 1.1 and DTLS to fix DoS attack. - - Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic - fuzzing as a service testing platform. - (CVE-2012-2333) - [Steve Henson] - - *) Initialise tkeylen properly when encrypting CMS messages. - Thanks to Solar Designer of Openwall for reporting this issue. - [Steve Henson] - - *) In FIPS mode don't try to use composite ciphers as they are not - approved. - [Steve Henson] - - Changes between 1.0.1a and 1.0.1b [26 Apr 2012] - - *) OpenSSL 1.0.0 sets SSL_OP_ALL to 0x80000FFFL and OpenSSL 1.0.1 and - 1.0.1a set SSL_OP_NO_TLSv1_1 to 0x00000400L which would unfortunately - mean any application compiled against OpenSSL 1.0.0 headers setting - SSL_OP_ALL would also set SSL_OP_NO_TLSv1_1, unintentionally disabling - TLS 1.1 also. Fix this by changing the value of SSL_OP_NO_TLSv1_1 to - 0x10000000L Any application which was previously compiled against - OpenSSL 1.0.1 or 1.0.1a headers and which cares about SSL_OP_NO_TLSv1_1 - will need to be recompiled as a result. Letting be results in - inability to disable specifically TLS 1.1 and in client context, - in unlike event, limit maximum offered version to TLS 1.0 [see below]. - [Steve Henson] - - *) In order to ensure interoperability SSL_OP_NO_protocolX does not - disable just protocol X, but all protocols above X *if* there are - protocols *below* X still enabled. In more practical terms it means - that if application wants to disable TLS1.0 in favor of TLS1.1 and - above, it's not sufficient to pass SSL_OP_NO_TLSv1, one has to pass - SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2. This applies to - client side. - [Andy Polyakov] - - Changes between 1.0.1 and 1.0.1a [19 Apr 2012] - - *) Check for potentially exploitable overflows in asn1_d2i_read_bio - BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer - in CRYPTO_realloc_clean. - - Thanks to Tavis Ormandy, Google Security Team, for discovering this - issue and to Adam Langley for fixing it. - (CVE-2012-2110) - [Adam Langley (Google), Tavis Ormandy, Google Security Team] - - *) Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections. - [Adam Langley] - - *) Workarounds for some broken servers that "hang" if a client hello - record length exceeds 255 bytes. - - 1. Do not use record version number > TLS 1.0 in initial client - hello: some (but not all) hanging servers will now work. - 2. If we set OPENSSL_MAX_TLS1_2_CIPHER_LENGTH this will truncate - the number of ciphers sent in the client hello. This should be - set to an even number, such as 50, for example by passing: - -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 to config or Configure. - Most broken servers should now work. - 3. If all else fails setting OPENSSL_NO_TLS1_2_CLIENT will disable - TLS 1.2 client support entirely. - [Steve Henson] - - *) Fix SEGV in Vector Permutation AES module observed in OpenSSH. - [Andy Polyakov] - - Changes between 1.0.0h and 1.0.1 [14 Mar 2012] - - *) Add compatibility with old MDC2 signatures which use an ASN1 OCTET - STRING form instead of a DigestInfo. - [Steve Henson] - - *) The format used for MDC2 RSA signatures is inconsistent between EVP - and the RSA_sign/RSA_verify functions. This was made more apparent when - OpenSSL used RSA_sign/RSA_verify for some RSA signatures in particular - those which went through EVP_PKEY_METHOD in 1.0.0 and later. Detect - the correct format in RSA_verify so both forms transparently work. - [Steve Henson] - - *) Some servers which support TLS 1.0 can choke if we initially indicate - support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA - encrypted premaster secret. As a workaround use the maximum permitted - client version in client hello, this should keep such servers happy - and still work with previous versions of OpenSSL. - [Steve Henson] - - *) Add support for TLS/DTLS heartbeats. - [Robin Seggelmann ] - - *) Add support for SCTP. - [Robin Seggelmann ] - - *) Improved PRNG seeding for VOS. - [Paul Green ] - - *) Extensive assembler packs updates, most notably: - - - x86[_64]: AES-NI, PCLMULQDQ, RDRAND support; - - x86[_64]: SSSE3 support (SHA1, vector-permutation AES); - - x86_64: bit-sliced AES implementation; - - ARM: NEON support, contemporary platforms optimizations; - - s390x: z196 support; - - *: GHASH and GF(2^m) multiplication implementations; - - [Andy Polyakov] - - *) Make TLS-SRP code conformant with RFC 5054 API cleanup - (removal of unnecessary code) - [Peter Sylvester ] - - *) Add TLS key material exporter from RFC 5705. - [Eric Rescorla] - - *) Add DTLS-SRTP negotiation from RFC 5764. - [Eric Rescorla] - - *) Add Next Protocol Negotiation, - http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-00. Can be - disabled with a no-npn flag to config or Configure. Code donated - by Google. - [Adam Langley and Ben Laurie] - - *) Add optional 64-bit optimized implementations of elliptic curves NIST-P224, - NIST-P256, NIST-P521, with constant-time single point multiplication on - typical inputs. Compiler support for the nonstandard type __uint128_t is - required to use this (present in gcc 4.4 and later, for 64-bit builds). - Code made available under Apache License version 2.0. - - Specify "enable-ec_nistp_64_gcc_128" on the Configure (or config) command - line to include this in your build of OpenSSL, and run "make depend" (or - "make update"). This enables the following EC_METHODs: - - EC_GFp_nistp224_method() - EC_GFp_nistp256_method() - EC_GFp_nistp521_method() - - EC_GROUP_new_by_curve_name() will automatically use these (while - EC_GROUP_new_curve_GFp() currently prefers the more flexible - implementations). - [Emilia Käsper, Adam Langley, Bodo Moeller (Google)] - - *) Use type ossl_ssize_t instead of ssize_t which isn't available on - all platforms. Move ssize_t definition from e_os.h to the public - header file e_os2.h as it now appears in public header file cms.h - [Steve Henson] - - *) New -sigopt option to the ca, req and x509 utilities. Additional - signature parameters can be passed using this option and in - particular PSS. - [Steve Henson] - - *) Add RSA PSS signing function. This will generate and set the - appropriate AlgorithmIdentifiers for PSS based on those in the - corresponding EVP_MD_CTX structure. No application support yet. - [Steve Henson] - - *) Support for companion algorithm specific ASN1 signing routines. - New function ASN1_item_sign_ctx() signs a pre-initialised - EVP_MD_CTX structure and sets AlgorithmIdentifiers based on - the appropriate parameters. - [Steve Henson] - - *) Add new algorithm specific ASN1 verification initialisation function - to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1 - handling will be the same no matter what EVP_PKEY_METHOD is used. - Add a PSS handler to support verification of PSS signatures: checked - against a number of sample certificates. - [Steve Henson] - - *) Add signature printing for PSS. Add PSS OIDs. - [Steve Henson, Martin Kaiser ] - - *) Add algorithm specific signature printing. An individual ASN1 method - can now print out signatures instead of the standard hex dump. - - More complex signatures (e.g. PSS) can print out more meaningful - information. Include DSA version that prints out the signature - parameters r, s. - [Steve Henson] - - *) Password based recipient info support for CMS library: implementing - RFC3211. - [Steve Henson] - - *) Split password based encryption into PBES2 and PBKDF2 functions. This - neatly separates the code into cipher and PBE sections and is required - for some algorithms that split PBES2 into separate pieces (such as - password based CMS). - [Steve Henson] - - *) Session-handling fixes: - - Fix handling of connections that are resuming with a session ID, - but also support Session Tickets. - - Fix a bug that suppressed issuing of a new ticket if the client - presented a ticket with an expired session. - - Try to set the ticket lifetime hint to something reasonable. - - Make tickets shorter by excluding irrelevant information. - - On the client side, don't ignore renewed tickets. - [Adam Langley, Bodo Moeller (Google)] - - *) Fix PSK session representation. - [Bodo Moeller] - - *) Add RC4-MD5 and AESNI-SHA1 "stitched" implementations. - - This work was sponsored by Intel. - [Andy Polyakov] - - *) Add GCM support to TLS library. Some custom code is needed to split - the IV between the fixed (from PRF) and explicit (from TLS record) - portions. This adds all GCM ciphersuites supported by RFC5288 and - RFC5289. Generalise some AES* cipherstrings to include GCM and - add a special AESGCM string for GCM only. - [Steve Henson] - - *) Expand range of ctrls for AES GCM. Permit setting invocation - field on decrypt and retrieval of invocation field only on encrypt. - [Steve Henson] - - *) Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support. - As required by RFC5289 these ciphersuites cannot be used if for - versions of TLS earlier than 1.2. - [Steve Henson] - - *) For FIPS capable OpenSSL interpret a NULL default public key method - as unset and return the appropriate default but do *not* set the default. - This means we can return the appropriate method in applications that - switch between FIPS and non-FIPS modes. - [Steve Henson] - - *) Redirect HMAC and CMAC operations to FIPS module in FIPS mode. If an - ENGINE is used then we cannot handle that in the FIPS module so we - keep original code iff non-FIPS operations are allowed. - [Steve Henson] - - *) Add -attime option to openssl utilities. - [Peter Eckersley , Ben Laurie and Steve Henson] - - *) Redirect DSA and DH operations to FIPS module in FIPS mode. - [Steve Henson] - - *) Redirect ECDSA and ECDH operations to FIPS module in FIPS mode. Also use - FIPS EC methods unconditionally for now. - [Steve Henson] - - *) New build option no-ec2m to disable characteristic 2 code. - [Steve Henson] - - *) Backport libcrypto audit of return value checking from 1.1.0-dev; not - all cases can be covered as some introduce binary incompatibilities. - [Steve Henson] - - *) Redirect RSA operations to FIPS module including keygen, - encrypt, decrypt, sign and verify. Block use of non FIPS RSA methods. - [Steve Henson] - - *) Add similar low level API blocking to ciphers. - [Steve Henson] - - *) Low level digest APIs are not approved in FIPS mode: any attempt - to use these will cause a fatal error. Applications that *really* want - to use them can use the private_* version instead. - [Steve Henson] - - *) Redirect cipher operations to FIPS module for FIPS builds. - [Steve Henson] - - *) Redirect digest operations to FIPS module for FIPS builds. - [Steve Henson] - - *) Update build system to add "fips" flag which will link in fipscanister.o - for static and shared library builds embedding a signature if needed. - [Steve Henson] - - *) Output TLS supported curves in preference order instead of numerical - order. This is currently hardcoded for the highest order curves first. - This should be configurable so applications can judge speed vs strength. - [Steve Henson] - - *) Add TLS v1.2 server support for client authentication. - [Steve Henson] - - *) Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers - and enable MD5. - [Steve Henson] - - *) Functions FIPS_mode_set() and FIPS_mode() which call the underlying - FIPS modules versions. - [Steve Henson] - - *) Add TLS v1.2 client side support for client authentication. Keep cache - of handshake records longer as we don't know the hash algorithm to use - until after the certificate request message is received. - [Steve Henson] - - *) Initial TLS v1.2 client support. Add a default signature algorithms - extension including all the algorithms we support. Parse new signature - format in client key exchange. Relax some ECC signing restrictions for - TLS v1.2 as indicated in RFC5246. - [Steve Henson] - - *) Add server support for TLS v1.2 signature algorithms extension. Switch - to new signature format when needed using client digest preference. - All server ciphersuites should now work correctly in TLS v1.2. No client - support yet and no support for client certificates. - [Steve Henson] - - *) Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch - to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based - ciphersuites. At present only RSA key exchange ciphersuites work with - TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete - SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods - and version checking. - [Steve Henson] - - *) New option OPENSSL_NO_SSL_INTERN. If an application can be compiled - with this defined it will not be affected by any changes to ssl internal - structures. Add several utility functions to allow openssl application - to work with OPENSSL_NO_SSL_INTERN defined. - [Steve Henson] - - *) A long standing patch to add support for SRP from EdelWeb (Peter - Sylvester and Christophe Renou) was integrated. - [Christophe Renou , Peter Sylvester - , Tom Wu , and - Ben Laurie] - - *) Add functions to copy EVP_PKEY_METHOD and retrieve flags and id. - [Steve Henson] - - *) Permit abbreviated handshakes when renegotiating using the function - SSL_renegotiate_abbreviated(). - [Robin Seggelmann ] - - *) Add call to ENGINE_register_all_complete() to - ENGINE_load_builtin_engines(), so some implementations get used - automatically instead of needing explicit application support. - [Steve Henson] - - *) Add support for TLS key exporter as described in RFC5705. - [Robin Seggelmann , Steve Henson] - - *) Initial TLSv1.1 support. Since TLSv1.1 is very similar to TLS v1.0 only - a few changes are required: - - Add SSL_OP_NO_TLSv1_1 flag. - Add TLSv1_1 methods. - Update version checking logic to handle version 1.1. - Add explicit IV handling (ported from DTLS code). - Add command line options to s_client/s_server. - [Steve Henson] - - Changes between 1.0.0g and 1.0.0h [12 Mar 2012] - - *) Fix MMA (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) weakness - in CMS and PKCS7 code. When RSA decryption fails use a random key for - content decryption and always return the same error. Note: this attack - needs on average 2^20 messages so it only affects automated senders. The - old behaviour can be re-enabled in the CMS code by setting the - CMS_DEBUG_DECRYPT flag: this is useful for debugging and testing where - an MMA defence is not necessary. - Thanks to Ivan Nestlerode for discovering - this issue. (CVE-2012-0884) - [Steve Henson] - - *) Fix CVE-2011-4619: make sure we really are receiving a - client hello before rejecting multiple SGC restarts. Thanks to - Ivan Nestlerode for discovering this bug. - [Steve Henson] - - Changes between 1.0.0f and 1.0.0g [18 Jan 2012] - - *) Fix for DTLS DoS issue introduced by fix for CVE-2011-4109. - Thanks to Antonio Martin, Enterprise Secure Access Research and - Development, Cisco Systems, Inc. for discovering this bug and - preparing a fix. (CVE-2012-0050) - [Antonio Martin] - - Changes between 1.0.0e and 1.0.0f [4 Jan 2012] - - *) Nadhem Alfardan and Kenny Paterson have discovered an extension - of the Vaudenay padding oracle attack on CBC mode encryption - which enables an efficient plaintext recovery attack against - the OpenSSL implementation of DTLS. Their attack exploits timing - differences arising during decryption processing. A research - paper describing this attack can be found at: - http://www.isg.rhul.ac.uk/~kp/dtls.pdf - Thanks go to Nadhem Alfardan and Kenny Paterson of the Information - Security Group at Royal Holloway, University of London - (www.isg.rhul.ac.uk) for discovering this flaw and to Robin Seggelmann - and Michael Tuexen - for preparing the fix. (CVE-2011-4108) - [Robin Seggelmann, Michael Tuexen] - - *) Clear bytes used for block padding of SSL 3.0 records. - (CVE-2011-4576) - [Adam Langley (Google)] - - *) Only allow one SGC handshake restart for SSL/TLS. Thanks to George - Kadianakis for discovering this issue and - Adam Langley for preparing the fix. (CVE-2011-4619) - [Adam Langley (Google)] - - *) Check parameters are not NULL in GOST ENGINE. (CVE-2012-0027) - [Andrey Kulikov ] - - *) Prevent malformed RFC3779 data triggering an assertion failure. - Thanks to Andrew Chi, BBN Technologies, for discovering the flaw - and Rob Austein for fixing it. (CVE-2011-4577) - [Rob Austein ] - - *) Improved PRNG seeding for VOS. - [Paul Green ] - - *) Fix ssl_ciph.c set-up race. - [Adam Langley (Google)] - - *) Fix spurious failures in ecdsatest.c. - [Emilia Käsper (Google)] - - *) Fix the BIO_f_buffer() implementation (which was mixing different - interpretations of the '..._len' fields). - [Adam Langley (Google)] - - *) Fix handling of BN_BLINDING: now BN_BLINDING_invert_ex (rather than - BN_BLINDING_invert_ex) calls BN_BLINDING_update, ensuring that concurrent - threads won't reuse the same blinding coefficients. - - This also avoids the need to obtain the CRYPTO_LOCK_RSA_BLINDING - lock to call BN_BLINDING_invert_ex, and avoids one use of - BN_BLINDING_update for each BN_BLINDING structure (previously, - the last update always remained unused). - [Emilia Käsper (Google)] - - *) In ssl3_clear, preserve s3->init_extra along with s3->rbuf. - [Bob Buckholz (Google)] - - Changes between 1.0.0d and 1.0.0e [6 Sep 2011] - - *) Fix bug where CRLs with nextUpdate in the past are sometimes accepted - by initialising X509_STORE_CTX properly. (CVE-2011-3207) - [Kaspar Brand ] - - *) Fix SSL memory handling for (EC)DH ciphersuites, in particular - for multi-threaded use of ECDH. (CVE-2011-3210) - [Adam Langley (Google)] - - *) Fix x509_name_ex_d2i memory leak on bad inputs. - [Bodo Moeller] - - *) Remove hard coded ecdsaWithSHA1 signature tests in ssl code and check - signature public key algorithm by using OID xref utilities instead. - Before this you could only use some ECC ciphersuites with SHA1 only. - [Steve Henson] - - *) Add protection against ECDSA timing attacks as mentioned in the paper - by Billy Bob Brumley and Nicola Tuveri, see: - - http://eprint.iacr.org/2011/232.pdf - - [Billy Bob Brumley and Nicola Tuveri] - - Changes between 1.0.0c and 1.0.0d [8 Feb 2011] - - *) Fix parsing of OCSP stapling ClientHello extension. CVE-2011-0014 - [Neel Mehta, Adam Langley, Bodo Moeller (Google)] - - *) Fix bug in string printing code: if *any* escaping is enabled we must - escape the escape character (backslash) or the resulting string is - ambiguous. - [Steve Henson] - - Changes between 1.0.0b and 1.0.0c [2 Dec 2010] - - *) Disable code workaround for ancient and obsolete Netscape browsers - and servers: an attacker can use it in a ciphersuite downgrade attack. - Thanks to Martin Rex for discovering this bug. CVE-2010-4180 - [Steve Henson] - - *) Fixed J-PAKE implementation error, originally discovered by - Sebastien Martini, further info and confirmation from Stefan - Arentz and Feng Hao. Note that this fix is a security fix. CVE-2010-4252 - [Ben Laurie] - - Changes between 1.0.0a and 1.0.0b [16 Nov 2010] - - *) Fix extension code to avoid race conditions which can result in a buffer - overrun vulnerability: resumed sessions must not be modified as they can - be shared by multiple threads. CVE-2010-3864 - [Steve Henson] - - *) Fix WIN32 build system to correctly link an ENGINE directory into - a DLL. - [Steve Henson] - - Changes between 1.0.0 and 1.0.0a [01 Jun 2010] - - *) Check return value of int_rsa_verify in pkey_rsa_verifyrecover - (CVE-2010-1633) - [Steve Henson, Peter-Michael Hager ] - - Changes between 0.9.8n and 1.0.0 [29 Mar 2010] - - *) Add "missing" function EVP_CIPHER_CTX_copy(). This copies a cipher - context. The operation can be customised via the ctrl mechanism in - case ENGINEs want to include additional functionality. - [Steve Henson] - - *) Tolerate yet another broken PKCS#8 key format: private key value negative. - [Steve Henson] - - *) Add new -subject_hash_old and -issuer_hash_old options to x509 utility to - output hashes compatible with older versions of OpenSSL. - [Willy Weisz ] - - *) Fix compression algorithm handling: if resuming a session use the - compression algorithm of the resumed session instead of determining - it from client hello again. Don't allow server to change algorithm. - [Steve Henson] - - *) Add load_crls() function to apps tidying load_certs() too. Add option - to verify utility to allow additional CRLs to be included. - [Steve Henson] - - *) Update OCSP request code to permit adding custom headers to the request: - some responders need this. - [Steve Henson] - - *) The function EVP_PKEY_sign() returns <=0 on error: check return code - correctly. - [Julia Lawall ] - - *) Update verify callback code in apps/s_cb.c and apps/verify.c, it - needlessly dereferenced structures, used obsolete functions and - didn't handle all updated verify codes correctly. - [Steve Henson] - - *) Disable MD2 in the default configuration. - [Steve Henson] - - *) In BIO_pop() and BIO_push() use the ctrl argument (which was NULL) to - indicate the initial BIO being pushed or popped. This makes it possible - to determine whether the BIO is the one explicitly called or as a result - of the ctrl being passed down the chain. Fix BIO_pop() and SSL BIOs so - it handles reference counts correctly and doesn't zero out the I/O bio - when it is not being explicitly popped. WARNING: applications which - included workarounds for the old buggy behaviour will need to be modified - or they could free up already freed BIOs. - [Steve Henson] - - *) Extend the uni2asc/asc2uni => OPENSSL_uni2asc/OPENSSL_asc2uni - renaming to all platforms (within the 0.9.8 branch, this was - done conditionally on Netware platforms to avoid a name clash). - [Guenter ] - - *) Add ECDHE and PSK support to DTLS. - [Michael Tuexen ] - - *) Add CHECKED_STACK_OF macro to safestack.h, otherwise safestack can't - be used on C++. - [Steve Henson] - - *) Add "missing" function EVP_MD_flags() (without this the only way to - retrieve a digest flags is by accessing the structure directly. Update - EVP_MD_do_all*() and EVP_CIPHER_do_all*() to include the name a digest - or cipher is registered as in the "from" argument. Print out all - registered digests in the dgst usage message instead of manually - attempting to work them out. - [Steve Henson] - - *) If no SSLv2 ciphers are used don't use an SSLv2 compatible client hello: - this allows the use of compression and extensions. Change default cipher - string to remove SSLv2 ciphersuites. This effectively avoids ancient SSLv2 - by default unless an application cipher string requests it. - [Steve Henson] - - *) Alter match criteria in PKCS12_parse(). It used to try to use local - key ids to find matching certificates and keys but some PKCS#12 files - don't follow the (somewhat unwritten) rules and this strategy fails. - Now just gather all certificates together and the first private key - then look for the first certificate that matches the key. - [Steve Henson] - - *) Support use of registered digest and cipher names for dgst and cipher - commands instead of having to add each one as a special case. So now - you can do: - - openssl sha256 foo - - as well as: - - openssl dgst -sha256 foo - - and this works for ENGINE based algorithms too. - - [Steve Henson] - - *) Update Gost ENGINE to support parameter files. - [Victor B. Wagner ] - - *) Support GeneralizedTime in ca utility. - [Oliver Martin , Steve Henson] - - *) Enhance the hash format used for certificate directory links. The new - form uses the canonical encoding (meaning equivalent names will work - even if they aren't identical) and uses SHA1 instead of MD5. This form - is incompatible with the older format and as a result c_rehash should - be used to rebuild symbolic links. - [Steve Henson] - - *) Make PKCS#8 the default write format for private keys, replacing the - traditional format. This form is standardised, more secure and doesn't - include an implicit MD5 dependency. - [Steve Henson] - - *) Add a $gcc_devteam_warn option to Configure. The idea is that any code - committed to OpenSSL should pass this lot as a minimum. - [Steve Henson] - - *) Add session ticket override functionality for use by EAP-FAST. - [Jouni Malinen ] - - *) Modify HMAC functions to return a value. Since these can be implemented - in an ENGINE errors can occur. - [Steve Henson] - - *) Type-checked OBJ_bsearch_ex. - [Ben Laurie] - - *) Type-checked OBJ_bsearch. Also some constification necessitated - by type-checking. Still to come: TXT_DB, bsearch(?), - OBJ_bsearch_ex, qsort, CRYPTO_EX_DATA, ASN1_VALUE, ASN1_STRING, - CONF_VALUE. - [Ben Laurie] - - *) New function OPENSSL_gmtime_adj() to add a specific number of days and - seconds to a tm structure directly, instead of going through OS - specific date routines. This avoids any issues with OS routines such - as the year 2038 bug. New *_adj() functions for ASN1 time structures - and X509_time_adj_ex() to cover the extended range. The existing - X509_time_adj() is still usable and will no longer have any date issues. - [Steve Henson] - - *) Delta CRL support. New use deltas option which will attempt to locate - and search any appropriate delta CRLs available. - - This work was sponsored by Google. - [Steve Henson] - - *) Support for CRLs partitioned by reason code. Reorganise CRL processing - code and add additional score elements. Validate alternate CRL paths - as part of the CRL checking and indicate a new error "CRL path validation - error" in this case. Applications wanting additional details can use - the verify callback and check the new "parent" field. If this is not - NULL CRL path validation is taking place. Existing applications won't - see this because it requires extended CRL support which is off by - default. - - This work was sponsored by Google. - [Steve Henson] - - *) Support for freshest CRL extension. - - This work was sponsored by Google. - [Steve Henson] - - *) Initial indirect CRL support. Currently only supported in the CRLs - passed directly and not via lookup. Process certificate issuer - CRL entry extension and lookup CRL entries by bother issuer name - and serial number. Check and process CRL issuer entry in IDP extension. - - This work was sponsored by Google. - [Steve Henson] - - *) Add support for distinct certificate and CRL paths. The CRL issuer - certificate is validated separately in this case. Only enabled if - an extended CRL support flag is set: this flag will enable additional - CRL functionality in future. - - This work was sponsored by Google. - [Steve Henson] - - *) Add support for policy mappings extension. - - This work was sponsored by Google. - [Steve Henson] - - *) Fixes to pathlength constraint, self issued certificate handling, - policy processing to align with RFC3280 and PKITS tests. - - This work was sponsored by Google. - [Steve Henson] - - *) Support for name constraints certificate extension. DN, email, DNS - and URI types are currently supported. - - This work was sponsored by Google. - [Steve Henson] - - *) To cater for systems that provide a pointer-based thread ID rather - than numeric, deprecate the current numeric thread ID mechanism and - replace it with a structure and associated callback type. This - mechanism allows a numeric "hash" to be extracted from a thread ID in - either case, and on platforms where pointers are larger than 'long', - mixing is done to help ensure the numeric 'hash' is usable even if it - can't be guaranteed unique. The default mechanism is to use "&errno" - as a pointer-based thread ID to distinguish between threads. - - Applications that want to provide their own thread IDs should now use - CRYPTO_THREADID_set_callback() to register a callback that will call - either CRYPTO_THREADID_set_numeric() or CRYPTO_THREADID_set_pointer(). - - Note that ERR_remove_state() is now deprecated, because it is tied - to the assumption that thread IDs are numeric. ERR_remove_state(0) - to free the current thread's error state should be replaced by - ERR_remove_thread_state(NULL). - - (This new approach replaces the functions CRYPTO_set_idptr_callback(), - CRYPTO_get_idptr_callback(), and CRYPTO_thread_idptr() that existed in - OpenSSL 0.9.9-dev between June 2006 and August 2008. Also, if an - application was previously providing a numeric thread callback that - was inappropriate for distinguishing threads, then uniqueness might - have been obtained with &errno that happened immediately in the - intermediate development versions of OpenSSL; this is no longer the - case, the numeric thread callback will now override the automatic use - of &errno.) - [Geoff Thorpe, with help from Bodo Moeller] - - *) Initial support for different CRL issuing certificates. This covers a - simple case where the self issued certificates in the chain exist and - the real CRL issuer is higher in the existing chain. - - This work was sponsored by Google. - [Steve Henson] - - *) Removed effectively defunct crypto/store from the build. - [Ben Laurie] - - *) Revamp of STACK to provide stronger type-checking. Still to come: - TXT_DB, bsearch(?), OBJ_bsearch, qsort, CRYPTO_EX_DATA, ASN1_VALUE, - ASN1_STRING, CONF_VALUE. - [Ben Laurie] - - *) Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer - RAM on SSL connections. This option can save about 34k per idle SSL. - [Nick Mathewson] - - *) Revamp of LHASH to provide stronger type-checking. Still to come: - STACK, TXT_DB, bsearch, qsort. - [Ben Laurie] - - *) Initial support for Cryptographic Message Syntax (aka CMS) based - on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility, - support for data, signedData, compressedData, digestedData and - encryptedData, envelopedData types included. Scripts to check against - RFC4134 examples draft and interop and consistency checks of many - content types and variants. - [Steve Henson] - - *) Add options to enc utility to support use of zlib compression BIO. - [Steve Henson] - - *) Extend mk1mf to support importing of options and assembly language - files from Configure script, currently only included in VC-WIN32. - The assembly language rules can now optionally generate the source - files from the associated perl scripts. - [Steve Henson] - - *) Implement remaining functionality needed to support GOST ciphersuites. - Interop testing has been performed using CryptoPro implementations. - [Victor B. Wagner ] - - *) s390x assembler pack. - [Andy Polyakov] - - *) ARMv4 assembler pack. ARMv4 refers to v4 and later ISA, not CPU - "family." - [Andy Polyakov] - - *) Implement Opaque PRF Input TLS extension as specified in - draft-rescorla-tls-opaque-prf-input-00.txt. Since this is not an - official specification yet and no extension type assignment by - IANA exists, this extension (for now) will have to be explicitly - enabled when building OpenSSL by providing the extension number - to use. For example, specify an option - - -DTLSEXT_TYPE_opaque_prf_input=0x9527 - - to the "config" or "Configure" script to enable the extension, - assuming extension number 0x9527 (which is a completely arbitrary - and unofficial assignment based on the MD5 hash of the Internet - Draft). Note that by doing so, you potentially lose - interoperability with other TLS implementations since these might - be using the same extension number for other purposes. - - SSL_set_tlsext_opaque_prf_input(ssl, src, len) is used to set the - opaque PRF input value to use in the handshake. This will create - an internal copy of the length-'len' string at 'src', and will - return non-zero for success. - - To get more control and flexibility, provide a callback function - by using - - SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb) - SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg) - - where - - int (*cb)(SSL *, void *peerinput, size_t len, void *arg); - void *arg; - - Callback function 'cb' will be called in handshakes, and is - expected to use SSL_set_tlsext_opaque_prf_input() as appropriate. - Argument 'arg' is for application purposes (the value as given to - SSL_CTX_set_tlsext_opaque_prf_input_callback_arg() will directly - be provided to the callback function). The callback function - has to return non-zero to report success: usually 1 to use opaque - PRF input just if possible, or 2 to enforce use of the opaque PRF - input. In the latter case, the library will abort the handshake - if opaque PRF input is not successfully negotiated. - - Arguments 'peerinput' and 'len' given to the callback function - will always be NULL and 0 in the case of a client. A server will - see the client's opaque PRF input through these variables if - available (NULL and 0 otherwise). Note that if the server - provides an opaque PRF input, the length must be the same as the - length of the client's opaque PRF input. - - Note that the callback function will only be called when creating - a new session (session resumption can resume whatever was - previously negotiated), and will not be called in SSL 2.0 - handshakes; thus, SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) or - SSL_set_options(ssl, SSL_OP_NO_SSLv2) is especially recommended - for applications that need to enforce opaque PRF input. - - [Bodo Moeller] - - *) Update ssl code to support digests other than SHA1+MD5 for handshake - MAC. - - [Victor B. Wagner ] - - *) Add RFC4507 support to OpenSSL. This includes the corrections in - RFC4507bis. The encrypted ticket format is an encrypted encoded - SSL_SESSION structure, that way new session features are automatically - supported. - - If a client application caches session in an SSL_SESSION structure - support is transparent because tickets are now stored in the encoded - SSL_SESSION. - - The SSL_CTX structure automatically generates keys for ticket - protection in servers so again support should be possible - with no application modification. - - If a client or server wishes to disable RFC4507 support then the option - SSL_OP_NO_TICKET can be set. - - Add a TLS extension debugging callback to allow the contents of any client - or server extensions to be examined. - - This work was sponsored by Google. - [Steve Henson] - - *) Final changes to avoid use of pointer pointer casts in OpenSSL. - OpenSSL should now compile cleanly on gcc 4.2 - [Peter Hartley , Steve Henson] - - *) Update SSL library to use new EVP_PKEY MAC API. Include generic MAC - support including streaming MAC support: this is required for GOST - ciphersuite support. - [Victor B. Wagner , Steve Henson] - - *) Add option -stream to use PKCS#7 streaming in smime utility. New - function i2d_PKCS7_bio_stream() and PEM_write_PKCS7_bio_stream() - to output in BER and PEM format. - [Steve Henson] - - *) Experimental support for use of HMAC via EVP_PKEY interface. This - allows HMAC to be handled via the EVP_DigestSign*() interface. The - EVP_PKEY "key" in this case is the HMAC key, potentially allowing - ENGINE support for HMAC keys which are unextractable. New -mac and - -macopt options to dgst utility. - [Steve Henson] - - *) New option -sigopt to dgst utility. Update dgst to use - EVP_Digest{Sign,Verify}*. These two changes make it possible to use - alternative signing parameters such as X9.31 or PSS in the dgst - utility. - [Steve Henson] - - *) Change ssl_cipher_apply_rule(), the internal function that does - the work each time a ciphersuite string requests enabling - ("foo+bar"), moving ("+foo+bar"), disabling ("-foo+bar", or - removing ("!foo+bar") a class of ciphersuites: Now it maintains - the order of disabled ciphersuites such that those ciphersuites - that most recently went from enabled to disabled not only stay - in order with respect to each other, but also have higher priority - than other disabled ciphersuites the next time ciphersuites are - enabled again. - - This means that you can now say, e.g., "PSK:-PSK:HIGH" to enable - the same ciphersuites as with "HIGH" alone, but in a specific - order where the PSK ciphersuites come first (since they are the - most recently disabled ciphersuites when "HIGH" is parsed). - - Also, change ssl_create_cipher_list() (using this new - functionality) such that between otherwise identical - ciphersuites, ephemeral ECDH is preferred over ephemeral DH in - the default order. - [Bodo Moeller] - - *) Change ssl_create_cipher_list() so that it automatically - arranges the ciphersuites in reasonable order before starting - to process the rule string. Thus, the definition for "DEFAULT" - (SSL_DEFAULT_CIPHER_LIST) now is just "ALL:!aNULL:!eNULL", but - remains equivalent to "AES:ALL:!aNULL:!eNULL:+aECDH:+kRSA:+RC4:@STRENGTH". - This makes it much easier to arrive at a reasonable default order - in applications for which anonymous ciphers are OK (meaning - that you can't actually use DEFAULT). - [Bodo Moeller; suggested by Victor Duchovni] - - *) Split the SSL/TLS algorithm mask (as used for ciphersuite string - processing) into multiple integers instead of setting - "SSL_MKEY_MASK" bits, "SSL_AUTH_MASK" bits, "SSL_ENC_MASK", - "SSL_MAC_MASK", and "SSL_SSL_MASK" bits all in a single integer. - (These masks as well as the individual bit definitions are hidden - away into the non-exported interface ssl/ssl_locl.h, so this - change to the definition of the SSL_CIPHER structure shouldn't - affect applications.) This give us more bits for each of these - categories, so there is no longer a need to coagulate AES128 and - AES256 into a single algorithm bit, and to coagulate Camellia128 - and Camellia256 into a single algorithm bit, which has led to all - kinds of kludges. - - Thus, among other things, the kludge introduced in 0.9.7m and - 0.9.8e for masking out AES256 independently of AES128 or masking - out Camellia256 independently of AES256 is not needed here in 0.9.9. - - With the change, we also introduce new ciphersuite aliases that - so far were missing: "AES128", "AES256", "CAMELLIA128", and - "CAMELLIA256". - [Bodo Moeller] - - *) Add support for dsa-with-SHA224 and dsa-with-SHA256. - Use the leftmost N bytes of the signature input if the input is - larger than the prime q (with N being the size in bytes of q). - [Nils Larsch] - - *) Very *very* experimental PKCS#7 streaming encoder support. Nothing uses - it yet and it is largely untested. - [Steve Henson] - - *) Add support for the ecdsa-with-SHA224/256/384/512 signature types. - [Nils Larsch] - - *) Initial incomplete changes to avoid need for function casts in OpenSSL - some compilers (gcc 4.2 and later) reject their use. Safestack is - reimplemented. Update ASN1 to avoid use of legacy functions. - [Steve Henson] - - *) Win32/64 targets are linked with Winsock2. - [Andy Polyakov] - - *) Add an X509_CRL_METHOD structure to allow CRL processing to be redirected - to external functions. This can be used to increase CRL handling - efficiency especially when CRLs are very large by (for example) storing - the CRL revoked certificates in a database. - [Steve Henson] - - *) Overhaul of by_dir code. Add support for dynamic loading of CRLs so - new CRLs added to a directory can be used. New command line option - -verify_return_error to s_client and s_server. This causes real errors - to be returned by the verify callback instead of carrying on no matter - what. This reflects the way a "real world" verify callback would behave. - [Steve Henson] - - *) GOST engine, supporting several GOST algorithms and public key formats. - Kindly donated by Cryptocom. - [Cryptocom] - - *) Partial support for Issuing Distribution Point CRL extension. CRLs - partitioned by DP are handled but no indirect CRL or reason partitioning - (yet). Complete overhaul of CRL handling: now the most suitable CRL is - selected via a scoring technique which handles IDP and AKID in CRLs. - [Steve Henson] - - *) New X509_STORE_CTX callbacks lookup_crls() and lookup_certs() which - will ultimately be used for all verify operations: this will remove the - X509_STORE dependency on certificate verification and allow alternative - lookup methods. X509_STORE based implementations of these two callbacks. - [Steve Henson] - - *) Allow multiple CRLs to exist in an X509_STORE with matching issuer names. - Modify get_crl() to find a valid (unexpired) CRL if possible. - [Steve Henson] - - *) New function X509_CRL_match() to check if two CRLs are identical. Normally - this would be called X509_CRL_cmp() but that name is already used by - a function that just compares CRL issuer names. Cache several CRL - extensions in X509_CRL structure and cache CRLDP in X509. - [Steve Henson] - - *) Store a "canonical" representation of X509_NAME structure (ASN1 Name) - this maps equivalent X509_NAME structures into a consistent structure. - Name comparison can then be performed rapidly using memcmp(). - [Steve Henson] - - *) Non-blocking OCSP request processing. Add -timeout option to ocsp - utility. - [Steve Henson] - - *) Allow digests to supply their own micalg string for S/MIME type using - the ctrl EVP_MD_CTRL_MICALG. - [Steve Henson] - - *) During PKCS7 signing pass the PKCS7 SignerInfo structure to the - EVP_PKEY_METHOD before and after signing via the EVP_PKEY_CTRL_PKCS7_SIGN - ctrl. It can then customise the structure before and/or after signing - if necessary. - [Steve Henson] - - *) New function OBJ_add_sigid() to allow application defined signature OIDs - to be added to OpenSSLs internal tables. New function OBJ_sigid_free() - to free up any added signature OIDs. - [Steve Henson] - - *) New functions EVP_CIPHER_do_all(), EVP_CIPHER_do_all_sorted(), - EVP_MD_do_all() and EVP_MD_do_all_sorted() to enumerate internal - digest and cipher tables. New options added to openssl utility: - list-message-digest-algorithms and list-cipher-algorithms. - [Steve Henson] - - *) Change the array representation of binary polynomials: the list - of degrees of non-zero coefficients is now terminated with -1. - Previously it was terminated with 0, which was also part of the - value; thus, the array representation was not applicable to - polynomials where t^0 has coefficient zero. This change makes - the array representation useful in a more general context. - [Douglas Stebila] - - *) Various modifications and fixes to SSL/TLS cipher string - handling. For ECC, the code now distinguishes between fixed ECDH - with RSA certificates on the one hand and with ECDSA certificates - on the other hand, since these are separate ciphersuites. The - unused code for Fortezza ciphersuites has been removed. - - For consistency with EDH, ephemeral ECDH is now called "EECDH" - (not "ECDHE"). For consistency with the code for DH - certificates, use of ECDH certificates is now considered ECDH - authentication, not RSA or ECDSA authentication (the latter is - merely the CA's signing algorithm and not actively used in the - protocol). - - The temporary ciphersuite alias "ECCdraft" is no longer - available, and ECC ciphersuites are no longer excluded from "ALL" - and "DEFAULT". The following aliases now exist for RFC 4492 - ciphersuites, most of these by analogy with the DH case: - - kECDHr - ECDH cert, signed with RSA - kECDHe - ECDH cert, signed with ECDSA - kECDH - ECDH cert (signed with either RSA or ECDSA) - kEECDH - ephemeral ECDH - ECDH - ECDH cert or ephemeral ECDH - - aECDH - ECDH cert - aECDSA - ECDSA cert - ECDSA - ECDSA cert - - AECDH - anonymous ECDH - EECDH - non-anonymous ephemeral ECDH (equivalent to "kEECDH:-AECDH") - - [Bodo Moeller] - - *) Add additional S/MIME capabilities for AES and GOST ciphers if supported. - Use correct micalg parameters depending on digest(s) in signed message. - [Steve Henson] - - *) Add engine support for EVP_PKEY_ASN1_METHOD. Add functions to process - an ENGINE asn1 method. Support ENGINE lookups in the ASN1 code. - [Steve Henson] - - *) Initial engine support for EVP_PKEY_METHOD. New functions to permit - an engine to register a method. Add ENGINE lookups for methods and - functional reference processing. - [Steve Henson] - - *) New functions EVP_Digest{Sign,Verify)*. These are enhanced versions of - EVP_{Sign,Verify}* which allow an application to customise the signature - process. - [Steve Henson] - - *) New -resign option to smime utility. This adds one or more signers - to an existing PKCS#7 signedData structure. Also -md option to use an - alternative message digest algorithm for signing. - [Steve Henson] - - *) Tidy up PKCS#7 routines and add new functions to make it easier to - create PKCS7 structures containing multiple signers. Update smime - application to support multiple signers. - [Steve Henson] - - *) New -macalg option to pkcs12 utility to allow setting of an alternative - digest MAC. - [Steve Henson] - - *) Initial support for PKCS#5 v2.0 PRFs other than default SHA1 HMAC. - Reorganize PBE internals to lookup from a static table using NIDs, - add support for HMAC PBE OID translation. Add a EVP_CIPHER ctrl: - EVP_CTRL_PBE_PRF_NID this allows a cipher to specify an alternative - PRF which will be automatically used with PBES2. - [Steve Henson] - - *) Replace the algorithm specific calls to generate keys in "req" with the - new API. - [Steve Henson] - - *) Update PKCS#7 enveloped data routines to use new API. This is now - supported by any public key method supporting the encrypt operation. A - ctrl is added to allow the public key algorithm to examine or modify - the PKCS#7 RecipientInfo structure if it needs to: for RSA this is - a no op. - [Steve Henson] - - *) Add a ctrl to asn1 method to allow a public key algorithm to express - a default digest type to use. In most cases this will be SHA1 but some - algorithms (such as GOST) need to specify an alternative digest. The - return value indicates how strong the preference is 1 means optional and - 2 is mandatory (that is it is the only supported type). Modify - ASN1_item_sign() to accept a NULL digest argument to indicate it should - use the default md. Update openssl utilities to use the default digest - type for signing if it is not explicitly indicated. - [Steve Henson] - - *) Use OID cross reference table in ASN1_sign() and ASN1_verify(). New - EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant - signing method from the key type. This effectively removes the link - between digests and public key types. - [Steve Henson] - - *) Add an OID cross reference table and utility functions. Its purpose is to - translate between signature OIDs such as SHA1WithrsaEncryption and SHA1, - rsaEncryption. This will allow some of the algorithm specific hackery - needed to use the correct OID to be removed. - [Steve Henson] - - *) Remove algorithm specific dependencies when setting PKCS7_SIGNER_INFO - structures for PKCS7_sign(). They are now set up by the relevant public - key ASN1 method. - [Steve Henson] - - *) Add provisional EC pkey method with support for ECDSA and ECDH. - [Steve Henson] - - *) Add support for key derivation (agreement) in the API, DH method and - pkeyutl. - [Steve Henson] - - *) Add DSA pkey method and DH pkey methods, extend DH ASN1 method to support - public and private key formats. As a side effect these add additional - command line functionality not previously available: DSA signatures can be - generated and verified using pkeyutl and DH key support and generation in - pkey, genpkey. - [Steve Henson] - - *) BeOS support. - [Oliver Tappe ] - - *) New make target "install_html_docs" installs HTML renditions of the - manual pages. - [Oliver Tappe ] - - *) New utility "genpkey" this is analogous to "genrsa" etc except it can - generate keys for any algorithm. Extend and update EVP_PKEY_METHOD to - support key and parameter generation and add initial key generation - functionality for RSA. - [Steve Henson] - - *) Add functions for main EVP_PKEY_method operations. The undocumented - functions EVP_PKEY_{encrypt,decrypt} have been renamed to - EVP_PKEY_{encrypt,decrypt}_old. - [Steve Henson] - - *) Initial definitions for EVP_PKEY_METHOD. This will be a high level public - key API, doesn't do much yet. - [Steve Henson] - - *) New function EVP_PKEY_asn1_get0_info() to retrieve information about - public key algorithms. New option to openssl utility: - "list-public-key-algorithms" to print out info. - [Steve Henson] - - *) Implement the Supported Elliptic Curves Extension for - ECC ciphersuites from draft-ietf-tls-ecc-12.txt. - [Douglas Stebila] - - *) Don't free up OIDs in OBJ_cleanup() if they are in use by EVP_MD or - EVP_CIPHER structures to avoid later problems in EVP_cleanup(). - [Steve Henson] - - *) New utilities pkey and pkeyparam. These are similar to algorithm specific - utilities such as rsa, dsa, dsaparam etc except they process any key - type. - [Steve Henson] - - *) Transfer public key printing routines to EVP_PKEY_ASN1_METHOD. New - functions EVP_PKEY_print_public(), EVP_PKEY_print_private(), - EVP_PKEY_print_param() to print public key data from an EVP_PKEY - structure. - [Steve Henson] - - *) Initial support for pluggable public key ASN1. - De-spaghettify the public key ASN1 handling. Move public and private - key ASN1 handling to a new EVP_PKEY_ASN1_METHOD structure. Relocate - algorithm specific handling to a single module within the relevant - algorithm directory. Add functions to allow (near) opaque processing - of public and private key structures. - [Steve Henson] - - *) Implement the Supported Point Formats Extension for - ECC ciphersuites from draft-ietf-tls-ecc-12.txt. - [Douglas Stebila] - - *) Add initial support for RFC 4279 PSK TLS ciphersuites. Add members - for the psk identity [hint] and the psk callback functions to the - SSL_SESSION, SSL and SSL_CTX structure. - - New ciphersuites: - PSK-RC4-SHA, PSK-3DES-EDE-CBC-SHA, PSK-AES128-CBC-SHA, - PSK-AES256-CBC-SHA - - New functions: - SSL_CTX_use_psk_identity_hint - SSL_get_psk_identity_hint - SSL_get_psk_identity - SSL_use_psk_identity_hint - - [Mika Kousa and Pasi Eronen of Nokia Corporation] - - *) Add RFC 3161 compliant time stamp request creation, response generation - and response verification functionality. - [Zoltán Glózik , The OpenTSA Project] - - *) Add initial support for TLS extensions, specifically for the server_name - extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now - have new members for a host name. The SSL data structure has an - additional member SSL_CTX *initial_ctx so that new sessions can be - stored in that context to allow for session resumption, even after the - SSL has been switched to a new SSL_CTX in reaction to a client's - server_name extension. - - New functions (subject to change): - - SSL_get_servername() - SSL_get_servername_type() - SSL_set_SSL_CTX() - - New CTRL codes and macros (subject to change): - - SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - - SSL_CTX_set_tlsext_servername_callback() - SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG - - SSL_CTX_set_tlsext_servername_arg() - SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name() - - openssl s_client has a new '-servername ...' option. - - openssl s_server has new options '-servername_host ...', '-cert2 ...', - '-key2 ...', '-servername_fatal' (subject to change). This allows - testing the HostName extension for a specific single host name ('-cert' - and '-key' remain fallbacks for handshakes without HostName - negotiation). If the unrecognized_name alert has to be sent, this by - default is a warning; it becomes fatal with the '-servername_fatal' - option. - - [Peter Sylvester, Remy Allais, Christophe Renou] - - *) Whirlpool hash implementation is added. - [Andy Polyakov] - - *) BIGNUM code on 64-bit SPARCv9 targets is switched from bn(64,64) to - bn(64,32). Because of instruction set limitations it doesn't have - any negative impact on performance. This was done mostly in order - to make it possible to share assembler modules, such as bn_mul_mont - implementations, between 32- and 64-bit builds without hassle. - [Andy Polyakov] - - *) Move code previously exiled into file crypto/ec/ec2_smpt.c - to ec2_smpl.c, and no longer require the OPENSSL_EC_BIN_PT_COMP - macro. - [Bodo Moeller] - - *) New candidate for BIGNUM assembler implementation, bn_mul_mont, - dedicated Montgomery multiplication procedure, is introduced. - BN_MONT_CTX is modified to allow bn_mul_mont to reach for higher - "64-bit" performance on certain 32-bit targets. - [Andy Polyakov] - - *) New option SSL_OP_NO_COMP to disable use of compression selectively - in SSL structures. New SSL ctrl to set maximum send fragment size. - Save memory by setting the I/O buffer sizes dynamically instead of - using the maximum available value. - [Steve Henson] - - *) New option -V for 'openssl ciphers'. This prints the ciphersuite code - in addition to the text details. - [Bodo Moeller] - - *) Very, very preliminary EXPERIMENTAL support for printing of general - ASN1 structures. This currently produces rather ugly output and doesn't - handle several customised structures at all. - [Steve Henson] - - *) Integrated support for PVK file format and some related formats such - as MS PUBLICKEYBLOB and PRIVATEKEYBLOB. Command line switches to support - these in the 'rsa' and 'dsa' utilities. - [Steve Henson] - - *) Support for PKCS#1 RSAPublicKey format on rsa utility command line. - [Steve Henson] - - *) Remove the ancient ASN1_METHOD code. This was only ever used in one - place for the (very old) "NETSCAPE" format certificates which are now - handled using new ASN1 code equivalents. - [Steve Henson] - - *) Let the TLSv1_method() etc. functions return a 'const' SSL_METHOD - pointer and make the SSL_METHOD parameter in SSL_CTX_new, - SSL_CTX_set_ssl_version and SSL_set_ssl_method 'const'. - [Nils Larsch] - - *) Modify CRL distribution points extension code to print out previously - unsupported fields. Enhance extension setting code to allow setting of - all fields. - [Steve Henson] - - *) Add print and set support for Issuing Distribution Point CRL extension. - [Steve Henson] - - *) Change 'Configure' script to enable Camellia by default. - [NTT] - - Changes between 0.9.8m and 0.9.8n [24 Mar 2010] - - *) When rejecting SSL/TLS records due to an incorrect version number, never - update s->server with a new major version number. As of - - OpenSSL 0.9.8m if 'short' is a 16-bit type, - - OpenSSL 0.9.8f if 'short' is longer than 16 bits, - the previous behavior could result in a read attempt at NULL when - receiving specific incorrect SSL/TLS records once record payload - protection is active. (CVE-2010-0740) - [Bodo Moeller, Adam Langley ] - - *) Fix for CVE-2010-0433 where some kerberos enabled versions of OpenSSL - could be crashed if the relevant tables were not present (e.g. chrooted). - [Tomas Hoger ] - - Changes between 0.9.8l and 0.9.8m [25 Feb 2010] - - *) Always check bn_wexpand() return values for failure. (CVE-2009-3245) - [Martin Olsson, Neel Mehta] - - *) Fix X509_STORE locking: Every 'objs' access requires a lock (to - accommodate for stack sorting, always a write lock!). - [Bodo Moeller] - - *) On some versions of WIN32 Heap32Next is very slow. This can cause - excessive delays in the RAND_poll(): over a minute. As a workaround - include a time check in the inner Heap32Next loop too. - [Steve Henson] - - *) The code that handled flushing of data in SSL/TLS originally used the - BIO_CTRL_INFO ctrl to see if any data was pending first. This caused - the problem outlined in PR#1949. The fix suggested there however can - trigger problems with buggy BIO_CTRL_WPENDING (e.g. some versions - of Apache). So instead simplify the code to flush unconditionally. - This should be fine since flushing with no data to flush is a no op. - [Steve Henson] - - *) Handle TLS versions 2.0 and later properly and correctly use the - highest version of TLS/SSL supported. Although TLS >= 2.0 is some way - off ancient servers have a habit of sticking around for a while... - [Steve Henson] - - *) Modify compression code so it frees up structures without using the - ex_data callbacks. This works around a problem where some applications - call CRYPTO_cleanup_all_ex_data() before application exit (e.g. when - restarting) then use compression (e.g. SSL with compression) later. - This results in significant per-connection memory leaks and - has caused some security issues including CVE-2008-1678 and - CVE-2009-4355. - [Steve Henson] - - *) Constify crypto/cast (i.e., ): a CAST_KEY doesn't - change when encrypting or decrypting. - [Bodo Moeller] - - *) Add option SSL_OP_LEGACY_SERVER_CONNECT which will allow clients to - connect and renegotiate with servers which do not support RI. - Until RI is more widely deployed this option is enabled by default. - [Steve Henson] - - *) Add "missing" ssl ctrls to clear options and mode. - [Steve Henson] - - *) If client attempts to renegotiate and doesn't support RI respond with - a no_renegotiation alert as required by RFC5746. Some renegotiating - TLS clients will continue a connection gracefully when they receive - the alert. Unfortunately OpenSSL mishandled this alert and would hang - waiting for a server hello which it will never receive. Now we treat a - received no_renegotiation alert as a fatal error. This is because - applications requesting a renegotiation might well expect it to succeed - and would have no code in place to handle the server denying it so the - only safe thing to do is to terminate the connection. - [Steve Henson] - - *) Add ctrl macro SSL_get_secure_renegotiation_support() which returns 1 if - peer supports secure renegotiation and 0 otherwise. Print out peer - renegotiation support in s_client/s_server. - [Steve Henson] - - *) Replace the highly broken and deprecated SPKAC certification method with - the updated NID creation version. This should correctly handle UTF8. - [Steve Henson] - - *) Implement RFC5746. Re-enable renegotiation but require the extension - as needed. Unfortunately, SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION - turns out to be a bad idea. It has been replaced by - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION which can be set with - SSL_CTX_set_options(). This is really not recommended unless you - know what you are doing. - [Eric Rescorla , Ben Laurie, Steve Henson] - - *) Fixes to stateless session resumption handling. Use initial_ctx when - issuing and attempting to decrypt tickets in case it has changed during - servername handling. Use a non-zero length session ID when attempting - stateless session resumption: this makes it possible to determine if - a resumption has occurred immediately after receiving server hello - (several places in OpenSSL subtly assume this) instead of later in - the handshake. - [Steve Henson] - - *) The functions ENGINE_ctrl(), OPENSSL_isservice(), - CMS_get1_RecipientRequest() and RAND_bytes() can return <=0 on error - fixes for a few places where the return code is not checked - correctly. - [Julia Lawall ] - - *) Add --strict-warnings option to Configure script to include devteam - warnings in other configurations. - [Steve Henson] - - *) Add support for --libdir option and LIBDIR variable in makefiles. This - makes it possible to install openssl libraries in locations which - have names other than "lib", for example "/usr/lib64" which some - systems need. - [Steve Henson, based on patch from Jeremy Utley] - - *) Don't allow the use of leading 0x80 in OIDs. This is a violation of - X690 8.9.12 and can produce some misleading textual output of OIDs. - [Steve Henson, reported by Dan Kaminsky] - - *) Delete MD2 from algorithm tables. This follows the recommendation in - several standards that it is not used in new applications due to - several cryptographic weaknesses. For binary compatibility reasons - the MD2 API is still compiled in by default. - [Steve Henson] - - *) Add compression id to {d2i,i2d}_SSL_SESSION so it is correctly saved - and restored. - [Steve Henson] - - *) Rename uni2asc and asc2uni functions to OPENSSL_uni2asc and - OPENSSL_asc2uni conditionally on Netware platforms to avoid a name - clash. - [Guenter ] - - *) Fix the server certificate chain building code to use X509_verify_cert(), - it used to have an ad-hoc builder which was unable to cope with anything - other than a simple chain. - [David Woodhouse , Steve Henson] - - *) Don't check self signed certificate signatures in X509_verify_cert() - by default (a flag can override this): it just wastes time without - adding any security. As a useful side effect self signed root CAs - with non-FIPS digests are now usable in FIPS mode. - [Steve Henson] - - *) In dtls1_process_out_of_seq_message() the check if the current message - is already buffered was missing. For every new message was memory - allocated, allowing an attacker to perform an denial of service attack - with sending out of seq handshake messages until there is no memory - left. Additionally every future message was buffered, even if the - sequence number made no sense and would be part of another handshake. - So only messages with sequence numbers less than 10 in advance will be - buffered. (CVE-2009-1378) - [Robin Seggelmann, discovered by Daniel Mentz] - - *) Records are buffered if they arrive with a future epoch to be - processed after finishing the corresponding handshake. There is - currently no limitation to this buffer allowing an attacker to perform - a DOS attack with sending records with future epochs until there is no - memory left. This patch adds the pqueue_size() function to determine - the size of a buffer and limits the record buffer to 100 entries. - (CVE-2009-1377) - [Robin Seggelmann, discovered by Daniel Mentz] - - *) Keep a copy of frag->msg_header.frag_len so it can be used after the - parent structure is freed. (CVE-2009-1379) - [Daniel Mentz] - - *) Handle non-blocking I/O properly in SSL_shutdown() call. - [Darryl Miles ] - - *) Add 2.5.4.* OIDs - [Ilya O. ] - - Changes between 0.9.8k and 0.9.8l [5 Nov 2009] - - *) Disable renegotiation completely - this fixes a severe security - problem (CVE-2009-3555) at the cost of breaking all - renegotiation. Renegotiation can be re-enabled by setting - SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION in s3->flags at - run-time. This is really not recommended unless you know what - you're doing. - [Ben Laurie] - - Changes between 0.9.8j and 0.9.8k [25 Mar 2009] - - *) Don't set val to NULL when freeing up structures, it is freed up by - underlying code. If sizeof(void *) > sizeof(long) this can result in - zeroing past the valid field. (CVE-2009-0789) - [Paolo Ganci ] - - *) Fix bug where return value of CMS_SignerInfo_verify_content() was not - checked correctly. This would allow some invalid signed attributes to - appear to verify correctly. (CVE-2009-0591) - [Ivan Nestlerode ] - - *) Reject UniversalString and BMPString types with invalid lengths. This - prevents a crash in ASN1_STRING_print_ex() which assumes the strings have - a legal length. (CVE-2009-0590) - [Steve Henson] - - *) Set S/MIME signing as the default purpose rather than setting it - unconditionally. This allows applications to override it at the store - level. - [Steve Henson] - - *) Permit restricted recursion of ASN1 strings. This is needed in practice - to handle some structures. - [Steve Henson] - - *) Improve efficiency of mem_gets: don't search whole buffer each time - for a '\n' - [Jeremy Shapiro ] - - *) New -hex option for openssl rand. - [Matthieu Herrb] - - *) Print out UTF8String and NumericString when parsing ASN1. - [Steve Henson] - - *) Support NumericString type for name components. - [Steve Henson] - - *) Allow CC in the environment to override the automatically chosen - compiler. Note that nothing is done to ensure flags work with the - chosen compiler. - [Ben Laurie] - - Changes between 0.9.8i and 0.9.8j [07 Jan 2009] - - *) Properly check EVP_VerifyFinal() and similar return values - (CVE-2008-5077). - [Ben Laurie, Bodo Moeller, Google Security Team] - - *) Enable TLS extensions by default. - [Ben Laurie] - - *) Allow the CHIL engine to be loaded, whether the application is - multithreaded or not. (This does not release the developer from the - obligation to set up the dynamic locking callbacks.) - [Sander Temme ] - - *) Use correct exit code if there is an error in dgst command. - [Steve Henson; problem pointed out by Roland Dirlewanger] - - *) Tweak Configure so that you need to say "experimental-jpake" to enable - JPAKE, and need to use -DOPENSSL_EXPERIMENTAL_JPAKE in applications. - [Bodo Moeller] - - *) Add experimental JPAKE support, including demo authentication in - s_client and s_server. - [Ben Laurie] - - *) Set the comparison function in v3_addr_canonize(). - [Rob Austein ] - - *) Add support for XMPP STARTTLS in s_client. - [Philip Paeps ] - - *) Change the server-side SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG behavior - to ensure that even with this option, only ciphersuites in the - server's preference list will be accepted. (Note that the option - applies only when resuming a session, so the earlier behavior was - just about the algorithm choice for symmetric cryptography.) - [Bodo Moeller] - - Changes between 0.9.8h and 0.9.8i [15 Sep 2008] - - *) Fix NULL pointer dereference if a DTLS server received - ChangeCipherSpec as first record (CVE-2009-1386). - [PR #1679] - - *) Fix a state transition in s3_srvr.c and d1_srvr.c - (was using SSL3_ST_CW_CLNT_HELLO_B, should be ..._ST_SW_SRVR_...). - [Nagendra Modadugu] - - *) The fix in 0.9.8c that supposedly got rid of unsafe - double-checked locking was incomplete for RSA blinding, - addressing just one layer of what turns out to have been - doubly unsafe triple-checked locking. - - So now fix this for real by retiring the MONT_HELPER macro - in crypto/rsa/rsa_eay.c. - - [Bodo Moeller; problem pointed out by Marius Schilder] - - *) Various precautionary measures: - - - Avoid size_t integer overflow in HASH_UPDATE (md32_common.h). - - - Avoid a buffer overflow in d2i_SSL_SESSION() (ssl_asn1.c). - (NB: This would require knowledge of the secret session ticket key - to exploit, in which case you'd be SOL either way.) - - - Change bn_nist.c so that it will properly handle input BIGNUMs - outside the expected range. - - - Enforce the 'num' check in BN_div() (bn_div.c) for non-BN_DEBUG - builds. - - [Neel Mehta, Bodo Moeller] - - *) Allow engines to be "soft loaded" - i.e. optionally don't die if - the load fails. Useful for distros. - [Ben Laurie and the FreeBSD team] - - *) Add support for Local Machine Keyset attribute in PKCS#12 files. - [Steve Henson] - - *) Fix BN_GF2m_mod_arr() top-bit cleanup code. - [Huang Ying] - - *) Expand ENGINE to support engine supplied SSL client certificate functions. - - This work was sponsored by Logica. - [Steve Henson] - - *) Add CryptoAPI ENGINE to support use of RSA and DSA keys held in Windows - keystores. Support for SSL/TLS client authentication too. - Not compiled unless enable-capieng specified to Configure. - - This work was sponsored by Logica. - [Steve Henson] - - *) Fix bug in X509_ATTRIBUTE creation: don't set attribute using - ASN1_TYPE_set1 if MBSTRING flag set. This bug would crash certain - attribute creation routines such as certificate requests and PKCS#12 - files. - [Steve Henson] - - Changes between 0.9.8g and 0.9.8h [28 May 2008] - - *) Fix flaw if 'Server Key exchange message' is omitted from a TLS - handshake which could lead to a client crash as found using the - Codenomicon TLS test suite (CVE-2008-1672) - [Steve Henson, Mark Cox] - - *) Fix double free in TLS server name extensions which could lead to - a remote crash found by Codenomicon TLS test suite (CVE-2008-0891) - [Joe Orton] - - *) Clear error queue in SSL_CTX_use_certificate_chain_file() - - Clear the error queue to ensure that error entries left from - older function calls do not interfere with the correct operation. - [Lutz Jaenicke, Erik de Castro Lopo] - - *) Remove root CA certificates of commercial CAs: - - The OpenSSL project does not recommend any specific CA and does not - have any policy with respect to including or excluding any CA. - Therefore it does not make any sense to ship an arbitrary selection - of root CA certificates with the OpenSSL software. - [Lutz Jaenicke] - - *) RSA OAEP patches to fix two separate invalid memory reads. - The first one involves inputs when 'lzero' is greater than - 'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes - before the beginning of from). The second one involves inputs where - the 'db' section contains nothing but zeroes (there is a one-byte - invalid read after the end of 'db'). - [Ivan Nestlerode ] - - *) Partial backport from 0.9.9-dev: - - Introduce bn_mul_mont (dedicated Montgomery multiplication - procedure) as a candidate for BIGNUM assembler implementation. - While 0.9.9-dev uses assembler for various architectures, only - x86_64 is available by default here in the 0.9.8 branch, and - 32-bit x86 is available through a compile-time setting. - - To try the 32-bit x86 assembler implementation, use Configure - option "enable-montasm" (which exists only for this backport). - - As "enable-montasm" for 32-bit x86 disclaims code stability - anyway, in this constellation we activate additional code - backported from 0.9.9-dev for further performance improvements, - namely BN_from_montgomery_word. (To enable this otherwise, - e.g. x86_64, try "-DMONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD".) - - [Andy Polyakov (backport partially by Bodo Moeller)] - - *) Add TLS session ticket callback. This allows an application to set - TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed - values. This is useful for key rollover for example where several key - sets may exist with different names. - [Steve Henson] - - *) Reverse ENGINE-internal logic for caching default ENGINE handles. - This was broken until now in 0.9.8 releases, such that the only way - a registered ENGINE could be used (assuming it initialises - successfully on the host) was to explicitly set it as the default - for the relevant algorithms. This is in contradiction with 0.9.7 - behaviour and the documentation. With this fix, when an ENGINE is - registered into a given algorithm's table of implementations, the - 'uptodate' flag is reset so that auto-discovery will be used next - time a new context for that algorithm attempts to select an - implementation. - [Ian Lister (tweaked by Geoff Thorpe)] - - *) Backport of CMS code to OpenSSL 0.9.8. This differs from the 0.9.9 - implementation in the following ways: - - Lack of EVP_PKEY_ASN1_METHOD means algorithm parameters have to be - hard coded. - - Lack of BER streaming support means one pass streaming processing is - only supported if data is detached: setting the streaming flag is - ignored for embedded content. - - CMS support is disabled by default and must be explicitly enabled - with the enable-cms configuration option. - [Steve Henson] - - *) Update the GMP engine glue to do direct copies between BIGNUM and - mpz_t when openssl and GMP use the same limb size. Otherwise the - existing "conversion via a text string export" trick is still used. - [Paul Sheer ] - - *) Zlib compression BIO. This is a filter BIO which compressed and - uncompresses any data passed through it. - [Steve Henson] - - *) Add AES_wrap_key() and AES_unwrap_key() functions to implement - RFC3394 compatible AES key wrapping. - [Steve Henson] - - *) Add utility functions to handle ASN1 structures. ASN1_STRING_set0(): - sets string data without copying. X509_ALGOR_set0() and - X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier) - data. Attribute function X509at_get0_data_by_OBJ(): retrieves data - from an X509_ATTRIBUTE structure optionally checking it occurs only - once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied - data. - [Steve Henson] - - *) Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set() - to get the expected BN_FLG_CONSTTIME behavior. - [Bodo Moeller (Google)] - - *) Netware support: - - - fixed wrong usage of ioctlsocket() when build for LIBC BSD sockets - - fixed do_tests.pl to run the test suite with CLIB builds too (CLIB_OPT) - - added some more tests to do_tests.pl - - fixed RunningProcess usage so that it works with newer LIBC NDKs too - - removed usage of BN_LLONG for CLIB builds to avoid runtime dependency - - added new Configure targets netware-clib-bsdsock, netware-clib-gcc, - netware-clib-bsdsock-gcc, netware-libc-bsdsock-gcc - - various changes to netware.pl to enable gcc-cross builds on Win32 - platform - - changed crypto/bio/b_sock.c to work with macro functions (CLIB BSD) - - various changes to fix missing prototype warnings - - fixed x86nasm.pl to create correct asm files for NASM COFF output - - added AES, WHIRLPOOL and CPUID assembler code to build files - - added missing AES assembler make rules to mk1mf.pl - - fixed order of includes in apps/ocsp.c so that e_os.h settings apply - [Guenter Knauf ] - - *) Implement certificate status request TLS extension defined in RFC3546. - A client can set the appropriate parameters and receive the encoded - OCSP response via a callback. A server can query the supplied parameters - and set the encoded OCSP response in the callback. Add simplified examples - to s_client and s_server. - [Steve Henson] - - Changes between 0.9.8f and 0.9.8g [19 Oct 2007] - - *) Fix various bugs: - + Binary incompatibility of ssl_ctx_st structure - + DTLS interoperation with non-compliant servers - + Don't call get_session_cb() without proposed session - + Fix ia64 assembler code - [Andy Polyakov, Steve Henson] - - Changes between 0.9.8e and 0.9.8f [11 Oct 2007] - - *) DTLS Handshake overhaul. There were longstanding issues with - OpenSSL DTLS implementation, which were making it impossible for - RFC 4347 compliant client to communicate with OpenSSL server. - Unfortunately just fixing these incompatibilities would "cut off" - pre-0.9.8f clients. To allow for hassle free upgrade post-0.9.8e - server keeps tolerating non RFC compliant syntax. The opposite is - not true, 0.9.8f client can not communicate with earlier server. - This update even addresses CVE-2007-4995. - [Andy Polyakov] - - *) Changes to avoid need for function casts in OpenSSL: some compilers - (gcc 4.2 and later) reject their use. - [Kurt Roeckx , Peter Hartley , - Steve Henson] - - *) Add RFC4507 support to OpenSSL. This includes the corrections in - RFC4507bis. The encrypted ticket format is an encrypted encoded - SSL_SESSION structure, that way new session features are automatically - supported. - - If a client application caches session in an SSL_SESSION structure - support is transparent because tickets are now stored in the encoded - SSL_SESSION. - - The SSL_CTX structure automatically generates keys for ticket - protection in servers so again support should be possible - with no application modification. - - If a client or server wishes to disable RFC4507 support then the option - SSL_OP_NO_TICKET can be set. - - Add a TLS extension debugging callback to allow the contents of any client - or server extensions to be examined. - - This work was sponsored by Google. - [Steve Henson] - - *) Add initial support for TLS extensions, specifically for the server_name - extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now - have new members for a host name. The SSL data structure has an - additional member SSL_CTX *initial_ctx so that new sessions can be - stored in that context to allow for session resumption, even after the - SSL has been switched to a new SSL_CTX in reaction to a client's - server_name extension. - - New functions (subject to change): - - SSL_get_servername() - SSL_get_servername_type() - SSL_set_SSL_CTX() - - New CTRL codes and macros (subject to change): - - SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - - SSL_CTX_set_tlsext_servername_callback() - SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG - - SSL_CTX_set_tlsext_servername_arg() - SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name() - - openssl s_client has a new '-servername ...' option. - - openssl s_server has new options '-servername_host ...', '-cert2 ...', - '-key2 ...', '-servername_fatal' (subject to change). This allows - testing the HostName extension for a specific single host name ('-cert' - and '-key' remain fallbacks for handshakes without HostName - negotiation). If the unrecognized_name alert has to be sent, this by - default is a warning; it becomes fatal with the '-servername_fatal' - option. - - [Peter Sylvester, Remy Allais, Christophe Renou, Steve Henson] - - *) Add AES and SSE2 assembly language support to VC++ build. - [Steve Henson] - - *) Mitigate attack on final subtraction in Montgomery reduction. - [Andy Polyakov] - - *) Fix crypto/ec/ec_mult.c to work properly with scalars of value 0 - (which previously caused an internal error). - [Bodo Moeller] - - *) Squeeze another 10% out of IGE mode when in != out. - [Ben Laurie] - - *) AES IGE mode speedup. - [Dean Gaudet (Google)] - - *) Add the Korean symmetric 128-bit cipher SEED (see - http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp) and - add SEED ciphersuites from RFC 4162: - - TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA" - TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA" - TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA" - TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA" - - To minimize changes between patchlevels in the OpenSSL 0.9.8 - series, SEED remains excluded from compilation unless OpenSSL - is configured with 'enable-seed'. - [KISA, Bodo Moeller] - - *) Mitigate branch prediction attacks, which can be practical if a - single processor is shared, allowing a spy process to extract - information. For detailed background information, see - http://eprint.iacr.org/2007/039 (O. Aciicmez, S. Gueron, - J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL - and Necessary Software Countermeasures"). The core of the change - are new versions BN_div_no_branch() and - BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(), - respectively, which are slower, but avoid the security-relevant - conditional branches. These are automatically called by BN_div() - and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one - of the input BIGNUMs. Also, BN_is_bit_set() has been changed to - remove a conditional branch. - - BN_FLG_CONSTTIME is the new name for the previous - BN_FLG_EXP_CONSTTIME flag, since it now affects more than just - modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag - in the exponent causes BN_mod_exp_mont() to use the alternative - implementation in BN_mod_exp_mont_consttime().) The old name - remains as a deprecated alias. - - Similarly, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general - RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses - constant-time implementations for more than just exponentiation. - Here too the old name is kept as a deprecated alias. - - BN_BLINDING_new() will now use BN_dup() for the modulus so that - the BN_BLINDING structure gets an independent copy of the - modulus. This means that the previous "BIGNUM *m" argument to - BN_BLINDING_new() and to BN_BLINDING_create_param() now - essentially becomes "const BIGNUM *m", although we can't actually - change this in the header file before 0.9.9. It allows - RSA_setup_blinding() to use BN_with_flags() on the modulus to - enable BN_FLG_CONSTTIME. - - [Matthew D Wood (Intel Corp)] - - *) In the SSL/TLS server implementation, be strict about session ID - context matching (which matters if an application uses a single - external cache for different purposes). Previously, - out-of-context reuse was forbidden only if SSL_VERIFY_PEER was - set. This did ensure strict client verification, but meant that, - with applications using a single external cache for quite - different requirements, clients could circumvent ciphersuite - restrictions for a given session ID context by starting a session - in a different context. - [Bodo Moeller] - - *) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that - a ciphersuite string such as "DEFAULT:RSA" cannot enable - authentication-only ciphersuites. - [Bodo Moeller] - - *) Update the SSL_get_shared_ciphers() fix CVE-2006-3738 which was - not complete and could lead to a possible single byte overflow - (CVE-2007-5135) [Ben Laurie] - - Changes between 0.9.8d and 0.9.8e [23 Feb 2007] - - *) Since AES128 and AES256 (and similarly Camellia128 and - Camellia256) share a single mask bit in the logic of - ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a - kludge to work properly if AES128 is available and AES256 isn't - (or if Camellia128 is available and Camellia256 isn't). - [Victor Duchovni] - - *) Fix the BIT STRING encoding generated by crypto/ec/ec_asn1.c - (within i2d_ECPrivateKey, i2d_ECPKParameters, i2d_ECParameters): - When a point or a seed is encoded in a BIT STRING, we need to - prevent the removal of trailing zero bits to get the proper DER - encoding. (By default, crypto/asn1/a_bitstr.c assumes the case - of a NamedBitList, for which trailing 0 bits need to be removed.) - [Bodo Moeller] - - *) Have SSL/TLS server implementation tolerate "mismatched" record - protocol version while receiving ClientHello even if the - ClientHello is fragmented. (The server can't insist on the - particular protocol version it has chosen before the ServerHello - message has informed the client about his choice.) - [Bodo Moeller] - - *) Add RFC 3779 support. - [Rob Austein for ARIN, Ben Laurie] - - *) Load error codes if they are not already present instead of using a - static variable. This allows them to be cleanly unloaded and reloaded. - Improve header file function name parsing. - [Steve Henson] - - *) extend SMTP and IMAP protocol emulation in s_client to use EHLO - or CAPABILITY handshake as required by RFCs. - [Goetz Babin-Ebell] - - Changes between 0.9.8c and 0.9.8d [28 Sep 2006] - - *) Introduce limits to prevent malicious keys being able to - cause a denial of service. (CVE-2006-2940) - [Steve Henson, Bodo Moeller] - - *) Fix ASN.1 parsing of certain invalid structures that can result - in a denial of service. (CVE-2006-2937) [Steve Henson] - - *) Fix buffer overflow in SSL_get_shared_ciphers() function. - (CVE-2006-3738) [Tavis Ormandy and Will Drewry, Google Security Team] - - *) Fix SSL client code which could crash if connecting to a - malicious SSLv2 server. (CVE-2006-4343) - [Tavis Ormandy and Will Drewry, Google Security Team] - - *) Since 0.9.8b, ciphersuite strings naming explicit ciphersuites - match only those. Before that, "AES256-SHA" would be interpreted - as a pattern and match "AES128-SHA" too (since AES128-SHA got - the same strength classification in 0.9.7h) as we currently only - have a single AES bit in the ciphersuite description bitmap. - That change, however, also applied to ciphersuite strings such as - "RC4-MD5" that intentionally matched multiple ciphersuites -- - namely, SSL 2.0 ciphersuites in addition to the more common ones - from SSL 3.0/TLS 1.0. - - So we change the selection algorithm again: Naming an explicit - ciphersuite selects this one ciphersuite, and any other similar - ciphersuite (same bitmap) from *other* protocol versions. - Thus, "RC4-MD5" again will properly select both the SSL 2.0 - ciphersuite and the SSL 3.0/TLS 1.0 ciphersuite. - - Since SSL 2.0 does not have any ciphersuites for which the - 128/256 bit distinction would be relevant, this works for now. - The proper fix will be to use different bits for AES128 and - AES256, which would have avoided the problems from the beginning; - however, bits are scarce, so we can only do this in a new release - (not just a patchlevel) when we can change the SSL_CIPHER - definition to split the single 'unsigned long mask' bitmap into - multiple values to extend the available space. - - [Bodo Moeller] - - Changes between 0.9.8b and 0.9.8c [05 Sep 2006] - - *) Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher - (CVE-2006-4339) [Ben Laurie and Google Security Team] - - *) Add AES IGE and biIGE modes. - [Ben Laurie] - - *) Change the Unix randomness entropy gathering to use poll() when - possible instead of select(), since the latter has some - undesirable limitations. - [Darryl Miles via Richard Levitte and Bodo Moeller] - - *) Disable "ECCdraft" ciphersuites more thoroughly. Now special - treatment in ssl/ssl_ciph.s makes sure that these ciphersuites - cannot be implicitly activated as part of, e.g., the "AES" alias. - However, please upgrade to OpenSSL 0.9.9[-dev] for - non-experimental use of the ECC ciphersuites to get TLS extension - support, which is required for curve and point format negotiation - to avoid potential handshake problems. - [Bodo Moeller] - - *) Disable rogue ciphersuites: - - - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5") - - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5") - - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5") - - The latter two were purportedly from - draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really - appear there. - - Also deactivate the remaining ciphersuites from - draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as - unofficial, and the ID has long expired. - [Bodo Moeller] - - *) Fix RSA blinding Heisenbug (problems sometimes occurred on - dual-core machines) and other potential thread-safety issues. - [Bodo Moeller] - - *) Add the symmetric cipher Camellia (128-bit, 192-bit, 256-bit key - versions), which is now available for royalty-free use - (see http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html). - Also, add Camellia TLS ciphersuites from RFC 4132. - - To minimize changes between patchlevels in the OpenSSL 0.9.8 - series, Camellia remains excluded from compilation unless OpenSSL - is configured with 'enable-camellia'. - [NTT] - - *) Disable the padding bug check when compression is in use. The padding - bug check assumes the first packet is of even length, this is not - necessarily true if compression is enabled and can result in false - positives causing handshake failure. The actual bug test is ancient - code so it is hoped that implementations will either have fixed it by - now or any which still have the bug do not support compression. - [Steve Henson] - - Changes between 0.9.8a and 0.9.8b [04 May 2006] - - *) When applying a cipher rule check to see if string match is an explicit - cipher suite and only match that one cipher suite if it is. - [Steve Henson] - - *) Link in manifests for VC++ if needed. - [Austin Ziegler ] - - *) Update support for ECC-based TLS ciphersuites according to - draft-ietf-tls-ecc-12.txt with proposed changes (but without - TLS extensions, which are supported starting with the 0.9.9 - branch, not in the OpenSSL 0.9.8 branch). - [Douglas Stebila] - - *) New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() to support - opaque EVP_CIPHER_CTX handling. - [Steve Henson] - - *) Fixes and enhancements to zlib compression code. We now only use - "zlib1.dll" and use the default __cdecl calling convention on Win32 - to conform with the standards mentioned here: - http://www.zlib.net/DLL_FAQ.txt - Static zlib linking now works on Windows and the new --with-zlib-include - --with-zlib-lib options to Configure can be used to supply the location - of the headers and library. Gracefully handle case where zlib library - can't be loaded. - [Steve Henson] - - *) Several fixes and enhancements to the OID generation code. The old code - sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't - handle numbers larger than ULONG_MAX, truncated printing and had a - non standard OBJ_obj2txt() behaviour. - [Steve Henson] - - *) Add support for building of engines under engine/ as shared libraries - under VC++ build system. - [Steve Henson] - - *) Corrected the numerous bugs in the Win32 path splitter in DSO. - Hopefully, we will not see any false combination of paths any more. - [Richard Levitte] - - Changes between 0.9.8 and 0.9.8a [11 Oct 2005] - - *) Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING - (part of SSL_OP_ALL). This option used to disable the - countermeasure against man-in-the-middle protocol-version - rollback in the SSL 2.0 server implementation, which is a bad - idea. (CVE-2005-2969) - - [Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center - for Information Security, National Institute of Advanced Industrial - Science and Technology [AIST], Japan)] - - *) Add two function to clear and return the verify parameter flags. - [Steve Henson] - - *) Keep cipherlists sorted in the source instead of sorting them at - runtime, thus removing the need for a lock. - [Nils Larsch] - - *) Avoid some small subgroup attacks in Diffie-Hellman. - [Nick Mathewson and Ben Laurie] - - *) Add functions for well-known primes. - [Nick Mathewson] - - *) Extended Windows CE support. - [Satoshi Nakamura and Andy Polyakov] - - *) Initialize SSL_METHOD structures at compile time instead of during - runtime, thus removing the need for a lock. - [Steve Henson] - - *) Make PKCS7_decrypt() work even if no certificate is supplied by - attempting to decrypt each encrypted key in turn. Add support to - smime utility. - [Steve Henson] - - Changes between 0.9.7h and 0.9.8 [05 Jul 2005] - - [NB: OpenSSL 0.9.7i and later 0.9.7 patch levels were released after - OpenSSL 0.9.8.] - - *) Add libcrypto.pc and libssl.pc for those who feel they need them. - [Richard Levitte] - - *) Change CA.sh and CA.pl so they don't bundle the CSR and the private - key into the same file any more. - [Richard Levitte] - - *) Add initial support for Win64, both IA64 and AMD64/x64 flavors. - [Andy Polyakov] - - *) Add -utf8 command line and config file option to 'ca'. - [Stefan and Geoff Thorpe] - - *) Add attribute functions to EVP_PKEY structure. Modify - PKCS12_create() to recognize a CSP name attribute and - use it. Make -CSP option work again in pkcs12 utility. - [Steve Henson] - - *) Add new functionality to the bn blinding code: - - automatic re-creation of the BN_BLINDING parameters after - a fixed number of uses (currently 32) - - add new function for parameter creation - - introduce flags to control the update behaviour of the - BN_BLINDING parameters - - hide BN_BLINDING structure - Add a second BN_BLINDING slot to the RSA structure to improve - performance when a single RSA object is shared among several - threads. - [Nils Larsch] - - *) Add support for DTLS. - [Nagendra Modadugu and Ben Laurie] - - *) Add support for DER encoded private keys (SSL_FILETYPE_ASN1) - to SSL_CTX_use_PrivateKey_file() and SSL_use_PrivateKey_file() - [Walter Goulet] - - *) Remove buggy and incomplete DH cert support from - ssl/ssl_rsa.c and ssl/s3_both.c - [Nils Larsch] - - *) Use SHA-1 instead of MD5 as the default digest algorithm for - the apps/openssl applications. - [Nils Larsch] - - *) Compile clean with "-Wall -Wmissing-prototypes - -Wstrict-prototypes -Wmissing-declarations -Werror". Currently - DEBUG_SAFESTACK must also be set. - [Ben Laurie] - - *) Change ./Configure so that certain algorithms can be disabled by default. - The new counterpiece to "no-xxx" is "enable-xxx". - - The patented RC5 and MDC2 algorithms will now be disabled unless - "enable-rc5" and "enable-mdc2", respectively, are specified. - - (IDEA remains enabled despite being patented. This is because IDEA - is frequently required for interoperability, and there is no license - fee for non-commercial use. As before, "no-idea" can be used to - avoid this algorithm.) - - [Bodo Moeller] - - *) Add processing of proxy certificates (see RFC 3820). This work was - sponsored by KTH (The Royal Institute of Technology in Stockholm) and - EGEE (Enabling Grids for E-science in Europe). - [Richard Levitte] - - *) RC4 performance overhaul on modern architectures/implementations, such - as Intel P4, IA-64 and AMD64. - [Andy Polyakov] - - *) New utility extract-section.pl. This can be used specify an alternative - section number in a pod file instead of having to treat each file as - a separate case in Makefile. This can be done by adding two lines to the - pod file: - - =for comment openssl_section:XXX - - The blank line is mandatory. - - [Steve Henson] - - *) New arguments -certform, -keyform and -pass for s_client and s_server - to allow alternative format key and certificate files and passphrase - sources. - [Steve Henson] - - *) New structure X509_VERIFY_PARAM which combines current verify parameters, - update associated structures and add various utility functions. - - Add new policy related verify parameters, include policy checking in - standard verify code. Enhance 'smime' application with extra parameters - to support policy checking and print out. - [Steve Henson] - - *) Add a new engine to support VIA PadLock ACE extensions in the VIA C3 - Nehemiah processors. These extensions support AES encryption in hardware - as well as RNG (though RNG support is currently disabled). - [Michal Ludvig , with help from Andy Polyakov] - - *) Deprecate BN_[get|set]_params() functions (they were ignored internally). - [Geoff Thorpe] - - *) New FIPS 180-2 algorithms, SHA-224/-256/-384/-512 are implemented. - [Andy Polyakov and a number of other people] - - *) Improved PowerPC platform support. Most notably BIGNUM assembler - implementation contributed by IBM. - [Suresh Chari, Peter Waltenberg, Andy Polyakov] - - *) The new 'RSA_generate_key_ex' function now takes a BIGNUM for the public - exponent rather than 'unsigned long'. There is a corresponding change to - the new 'rsa_keygen' element of the RSA_METHOD structure. - [Jelte Jansen, Geoff Thorpe] - - *) Functionality for creating the initial serial number file is now - moved from CA.pl to the 'ca' utility with a new option -create_serial. - - (Before OpenSSL 0.9.7e, CA.pl used to initialize the serial - number file to 1, which is bound to cause problems. To avoid - the problems while respecting compatibility between different 0.9.7 - patchlevels, 0.9.7e employed 'openssl x509 -next_serial' in - CA.pl for serial number initialization. With the new release 0.9.8, - we can fix the problem directly in the 'ca' utility.) - [Steve Henson] - - *) Reduced header interdependencies by declaring more opaque objects in - ossl_typ.h. As a consequence, including some headers (eg. engine.h) will - give fewer recursive includes, which could break lazy source code - so - this change is covered by the OPENSSL_NO_DEPRECATED symbol. As always, - developers should define this symbol when building and using openssl to - ensure they track the recommended behaviour, interfaces, [etc], but - backwards-compatible behaviour prevails when this isn't defined. - [Geoff Thorpe] - - *) New function X509_POLICY_NODE_print() which prints out policy nodes. - [Steve Henson] - - *) Add new EVP function EVP_CIPHER_CTX_rand_key and associated functionality. - This will generate a random key of the appropriate length based on the - cipher context. The EVP_CIPHER can provide its own random key generation - routine to support keys of a specific form. This is used in the des and - 3des routines to generate a key of the correct parity. Update S/MIME - code to use new functions and hence generate correct parity DES keys. - Add EVP_CHECK_DES_KEY #define to return an error if the key is not - valid (weak or incorrect parity). - [Steve Henson] - - *) Add a local set of CRLs that can be used by X509_verify_cert() as well - as looking them up. This is useful when the verified structure may contain - CRLs, for example PKCS#7 signedData. Modify PKCS7_verify() to use any CRLs - present unless the new PKCS7_NO_CRL flag is asserted. - [Steve Henson] - - *) Extend ASN1 oid configuration module. It now additionally accepts the - syntax: - - shortName = some long name, 1.2.3.4 - [Steve Henson] - - *) Reimplemented the BN_CTX implementation. There is now no more static - limitation on the number of variables it can handle nor the depth of the - "stack" handling for BN_CTX_start()/BN_CTX_end() pairs. The stack - information can now expand as required, and rather than having a single - static array of bignums, BN_CTX now uses a linked-list of such arrays - allowing it to expand on demand whilst maintaining the usefulness of - BN_CTX's "bundling". - [Geoff Thorpe] - - *) Add a missing BN_CTX parameter to the 'rsa_mod_exp' callback in RSA_METHOD - to allow all RSA operations to function using a single BN_CTX. - [Geoff Thorpe] - - *) Preliminary support for certificate policy evaluation and checking. This - is initially intended to pass the tests outlined in "Conformance Testing - of Relying Party Client Certificate Path Processing Logic" v1.07. - [Steve Henson] - - *) bn_dup_expand() has been deprecated, it was introduced in 0.9.7 and - remained unused and not that useful. A variety of other little bignum - tweaks and fixes have also been made continuing on from the audit (see - below). - [Geoff Thorpe] - - *) Constify all or almost all d2i, c2i, s2i and r2i functions, along with - associated ASN1, EVP and SSL functions and old ASN1 macros. - [Richard Levitte] - - *) BN_zero() only needs to set 'top' and 'neg' to zero for correct results, - and this should never fail. So the return value from the use of - BN_set_word() (which can fail due to needless expansion) is now deprecated; - if OPENSSL_NO_DEPRECATED is defined, BN_zero() is a void macro. - [Geoff Thorpe] - - *) BN_CTX_get() should return zero-valued bignums, providing the same - initialised value as BN_new(). - [Geoff Thorpe, suggested by Ulf Möller] - - *) Support for inhibitAnyPolicy certificate extension. - [Steve Henson] - - *) An audit of the BIGNUM code is underway, for which debugging code is - enabled when BN_DEBUG is defined. This makes stricter enforcements on what - is considered valid when processing BIGNUMs, and causes execution to - assert() when a problem is discovered. If BN_DEBUG_RAND is defined, - further steps are taken to deliberately pollute unused data in BIGNUM - structures to try and expose faulty code further on. For now, openssl will - (in its default mode of operation) continue to tolerate the inconsistent - forms that it has tolerated in the past, but authors and packagers should - consider trying openssl and their own applications when compiled with - these debugging symbols defined. It will help highlight potential bugs in - their own code, and will improve the test coverage for OpenSSL itself. At - some point, these tighter rules will become openssl's default to improve - maintainability, though the assert()s and other overheads will remain only - in debugging configurations. See bn.h for more details. - [Geoff Thorpe, Nils Larsch, Ulf Möller] - - *) BN_CTX_init() has been deprecated, as BN_CTX is an opaque structure - that can only be obtained through BN_CTX_new() (which implicitly - initialises it). The presence of this function only made it possible - to overwrite an existing structure (and cause memory leaks). - [Geoff Thorpe] - - *) Because of the callback-based approach for implementing LHASH as a - template type, lh_insert() adds opaque objects to hash-tables and - lh_doall() or lh_doall_arg() are typically used with a destructor callback - to clean up those corresponding objects before destroying the hash table - (and losing the object pointers). So some over-zealous constifications in - LHASH have been relaxed so that lh_insert() does not take (nor store) the - objects as "const" and the lh_doall[_arg] callback wrappers are not - prototyped to have "const" restrictions on the object pointers they are - given (and so aren't required to cast them away any more). - [Geoff Thorpe] - - *) The tmdiff.h API was so ugly and minimal that our own timing utility - (speed) prefers to use its own implementation. The two implementations - haven't been consolidated as yet (volunteers?) but the tmdiff API has had - its object type properly exposed (MS_TM) instead of casting to/from "char - *". This may still change yet if someone realises MS_TM and "ms_time_***" - aren't necessarily the greatest nomenclatures - but this is what was used - internally to the implementation so I've used that for now. - [Geoff Thorpe] - - *) Ensure that deprecated functions do not get compiled when - OPENSSL_NO_DEPRECATED is defined. Some "openssl" subcommands and a few of - the self-tests were still using deprecated key-generation functions so - these have been updated also. - [Geoff Thorpe] - - *) Reorganise PKCS#7 code to separate the digest location functionality - into PKCS7_find_digest(), digest addition into PKCS7_bio_add_digest(). - New function PKCS7_set_digest() to set the digest type for PKCS#7 - digestedData type. Add additional code to correctly generate the - digestedData type and add support for this type in PKCS7 initialization - functions. - [Steve Henson] - - *) New function PKCS7_set0_type_other() this initializes a PKCS7 - structure of type "other". - [Steve Henson] - - *) Fix prime generation loop in crypto/bn/bn_prime.pl by making - sure the loop does correctly stop and breaking ("division by zero") - modulus operations are not performed. The (pre-generated) prime - table crypto/bn/bn_prime.h was already correct, but it could not be - re-generated on some platforms because of the "division by zero" - situation in the script. - [Ralf S. Engelschall] - - *) Update support for ECC-based TLS ciphersuites according to - draft-ietf-tls-ecc-03.txt: the KDF1 key derivation function with - SHA-1 now is only used for "small" curves (where the - representation of a field element takes up to 24 bytes); for - larger curves, the field element resulting from ECDH is directly - used as premaster secret. - [Douglas Stebila (Sun Microsystems Laboratories)] - - *) Add code for kP+lQ timings to crypto/ec/ectest.c, and add SEC2 - curve secp160r1 to the tests. - [Douglas Stebila (Sun Microsystems Laboratories)] - - *) Add the possibility to load symbols globally with DSO. - [Götz Babin-Ebell via Richard Levitte] - - *) Add the functions ERR_set_mark() and ERR_pop_to_mark() for better - control of the error stack. - [Richard Levitte] - - *) Add support for STORE in ENGINE. - [Richard Levitte] - - *) Add the STORE type. The intention is to provide a common interface - to certificate and key stores, be they simple file-based stores, or - HSM-type store, or LDAP stores, or... - NOTE: The code is currently UNTESTED and isn't really used anywhere. - [Richard Levitte] - - *) Add a generic structure called OPENSSL_ITEM. This can be used to - pass a list of arguments to any function as well as provide a way - for a function to pass data back to the caller. - [Richard Levitte] - - *) Add the functions BUF_strndup() and BUF_memdup(). BUF_strndup() - works like BUF_strdup() but can be used to duplicate a portion of - a string. The copy gets NUL-terminated. BUF_memdup() duplicates - a memory area. - [Richard Levitte] - - *) Add the function sk_find_ex() which works like sk_find(), but will - return an index to an element even if an exact match couldn't be - found. The index is guaranteed to point at the element where the - searched-for key would be inserted to preserve sorting order. - [Richard Levitte] - - *) Add the function OBJ_bsearch_ex() which works like OBJ_bsearch() but - takes an extra flags argument for optional functionality. Currently, - the following flags are defined: - - OBJ_BSEARCH_VALUE_ON_NOMATCH - This one gets OBJ_bsearch_ex() to return a pointer to the first - element where the comparing function returns a negative or zero - number. - - OBJ_BSEARCH_FIRST_VALUE_ON_MATCH - This one gets OBJ_bsearch_ex() to return a pointer to the first - element where the comparing function returns zero. This is useful - if there are more than one element where the comparing function - returns zero. - [Richard Levitte] - - *) Make it possible to create self-signed certificates with 'openssl ca' - in such a way that the self-signed certificate becomes part of the - CA database and uses the same mechanisms for serial number generation - as all other certificate signing. The new flag '-selfsign' enables - this functionality. Adapt CA.sh and CA.pl.in. - [Richard Levitte] - - *) Add functionality to check the public key of a certificate request - against a given private. This is useful to check that a certificate - request can be signed by that key (self-signing). - [Richard Levitte] - - *) Make it possible to have multiple active certificates with the same - subject in the CA index file. This is done only if the keyword - 'unique_subject' is set to 'no' in the main CA section (default - if 'CA_default') of the configuration file. The value is saved - with the database itself in a separate index attribute file, - named like the index file with '.attr' appended to the name. - [Richard Levitte] - - *) Generate multi-valued AVAs using '+' notation in config files for - req and dirName. - [Steve Henson] - - *) Support for nameConstraints certificate extension. - [Steve Henson] - - *) Support for policyConstraints certificate extension. - [Steve Henson] - - *) Support for policyMappings certificate extension. - [Steve Henson] - - *) Make sure the default DSA_METHOD implementation only uses its - dsa_mod_exp() and/or bn_mod_exp() handlers if they are non-NULL, - and change its own handlers to be NULL so as to remove unnecessary - indirection. This lets alternative implementations fallback to the - default implementation more easily. - [Geoff Thorpe] - - *) Support for directoryName in GeneralName related extensions - in config files. - [Steve Henson] - - *) Make it possible to link applications using Makefile.shared. - Make that possible even when linking against static libraries! - [Richard Levitte] - - *) Support for single pass processing for S/MIME signing. This now - means that S/MIME signing can be done from a pipe, in addition - cleartext signing (multipart/signed type) is effectively streaming - and the signed data does not need to be all held in memory. - - This is done with a new flag PKCS7_STREAM. When this flag is set - PKCS7_sign() only initializes the PKCS7 structure and the actual signing - is done after the data is output (and digests calculated) in - SMIME_write_PKCS7(). - [Steve Henson] - - *) Add full support for -rpath/-R, both in shared libraries and - applications, at least on the platforms where it's known how - to do it. - [Richard Levitte] - - *) In crypto/ec/ec_mult.c, implement fast point multiplication with - precomputation, based on wNAF splitting: EC_GROUP_precompute_mult() - will now compute a table of multiples of the generator that - makes subsequent invocations of EC_POINTs_mul() or EC_POINT_mul() - faster (notably in the case of a single point multiplication, - scalar * generator). - [Nils Larsch, Bodo Moeller] - - *) IPv6 support for certificate extensions. The various extensions - which use the IP:a.b.c.d can now take IPv6 addresses using the - formats of RFC1884 2.2 . IPv6 addresses are now also displayed - correctly. - [Steve Henson] - - *) Added an ENGINE that implements RSA by performing private key - exponentiations with the GMP library. The conversions to and from - GMP's mpz_t format aren't optimised nor are any montgomery forms - cached, and on x86 it appears OpenSSL's own performance has caught up. - However there are likely to be other architectures where GMP could - provide a boost. This ENGINE is not built in by default, but it can be - specified at Configure time and should be accompanied by the necessary - linker additions, eg; - ./config -DOPENSSL_USE_GMP -lgmp - [Geoff Thorpe] - - *) "openssl engine" will not display ENGINE/DSO load failure errors when - testing availability of engines with "-t" - the old behaviour is - produced by increasing the feature's verbosity with "-tt". - [Geoff Thorpe] - - *) ECDSA routines: under certain error conditions uninitialized BN objects - could be freed. Solution: make sure initialization is performed early - enough. (Reported and fix supplied by Nils Larsch - via PR#459) - [Lutz Jaenicke] - - *) Key-generation can now be implemented in RSA_METHOD, DSA_METHOD - and DH_METHOD (eg. by ENGINE implementations) to override the normal - software implementations. For DSA and DH, parameter generation can - also be overridden by providing the appropriate method callbacks. - [Geoff Thorpe] - - *) Change the "progress" mechanism used in key-generation and - primality testing to functions that take a new BN_GENCB pointer in - place of callback/argument pairs. The new API functions have "_ex" - postfixes and the older functions are reimplemented as wrappers for - the new ones. The OPENSSL_NO_DEPRECATED symbol can be used to hide - declarations of the old functions to help (graceful) attempts to - migrate to the new functions. Also, the new key-generation API - functions operate on a caller-supplied key-structure and return - success/failure rather than returning a key or NULL - this is to - help make "keygen" another member function of RSA_METHOD etc. - - Example for using the new callback interface: - - int (*my_callback)(int a, int b, BN_GENCB *cb) = ...; - void *my_arg = ...; - BN_GENCB my_cb; - - BN_GENCB_set(&my_cb, my_callback, my_arg); - - return BN_is_prime_ex(some_bignum, BN_prime_checks, NULL, &cb); - /* For the meaning of a, b in calls to my_callback(), see the - * documentation of the function that calls the callback. - * cb will point to my_cb; my_arg can be retrieved as cb->arg. - * my_callback should return 1 if it wants BN_is_prime_ex() - * to continue, or 0 to stop. - */ - - [Geoff Thorpe] - - *) Change the ZLIB compression method to be stateful, and make it - available to TLS with the number defined in - draft-ietf-tls-compression-04.txt. - [Richard Levitte] - - *) Add the ASN.1 structures and functions for CertificatePair, which - is defined as follows (according to X.509_4thEditionDraftV6.pdf): - - CertificatePair ::= SEQUENCE { - forward [0] Certificate OPTIONAL, - reverse [1] Certificate OPTIONAL, - -- at least one of the pair shall be present -- } - - Also implement the PEM functions to read and write certificate - pairs, and defined the PEM tag as "CERTIFICATE PAIR". - - This needed to be defined, mostly for the sake of the LDAP - attribute crossCertificatePair, but may prove useful elsewhere as - well. - [Richard Levitte] - - *) Make it possible to inhibit symlinking of shared libraries in - Makefile.shared, for Cygwin's sake. - [Richard Levitte] - - *) Extend the BIGNUM API by creating a function - void BN_set_negative(BIGNUM *a, int neg); - and a macro that behave like - int BN_is_negative(const BIGNUM *a); - - to avoid the need to access 'a->neg' directly in applications. - [Nils Larsch] - - *) Implement fast modular reduction for pseudo-Mersenne primes - used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c). - EC_GROUP_new_curve_GFp() will now automatically use this - if applicable. - [Nils Larsch ] - - *) Add new lock type (CRYPTO_LOCK_BN). - [Bodo Moeller] - - *) Change the ENGINE framework to automatically load engines - dynamically from specific directories unless they could be - found to already be built in or loaded. Move all the - current engines except for the cryptodev one to a new - directory engines/. - The engines in engines/ are built as shared libraries if - the "shared" options was given to ./Configure or ./config. - Otherwise, they are inserted in libcrypto.a. - /usr/local/ssl/engines is the default directory for dynamic - engines, but that can be overridden at configure time through - the usual use of --prefix and/or --openssldir, and at run - time with the environment variable OPENSSL_ENGINES. - [Geoff Thorpe and Richard Levitte] - - *) Add Makefile.shared, a helper makefile to build shared - libraries. Adapt Makefile.org. - [Richard Levitte] - - *) Add version info to Win32 DLLs. - [Peter 'Luna' Runestig" ] - - *) Add new 'medium level' PKCS#12 API. Certificates and keys - can be added using this API to created arbitrary PKCS#12 - files while avoiding the low level API. - - New options to PKCS12_create(), key or cert can be NULL and - will then be omitted from the output file. The encryption - algorithm NIDs can be set to -1 for no encryption, the mac - iteration count can be set to 0 to omit the mac. - - Enhance pkcs12 utility by making the -nokeys and -nocerts - options work when creating a PKCS#12 file. New option -nomac - to omit the mac, NONE can be set for an encryption algorithm. - New code is modified to use the enhanced PKCS12_create() - instead of the low level API. - [Steve Henson] - - *) Extend ASN1 encoder to support indefinite length constructed - encoding. This can output sequences tags and octet strings in - this form. Modify pk7_asn1.c to support indefinite length - encoding. This is experimental and needs additional code to - be useful, such as an ASN1 bio and some enhanced streaming - PKCS#7 code. - - Extend template encode functionality so that tagging is passed - down to the template encoder. - [Steve Henson] - - *) Let 'openssl req' fail if an argument to '-newkey' is not - recognized instead of using RSA as a default. - [Bodo Moeller] - - *) Add support for ECC-based ciphersuites from draft-ietf-tls-ecc-01.txt. - As these are not official, they are not included in "ALL"; - the "ECCdraft" ciphersuite group alias can be used to select them. - [Vipul Gupta and Sumit Gupta (Sun Microsystems Laboratories)] - - *) Add ECDH engine support. - [Nils Gura and Douglas Stebila (Sun Microsystems Laboratories)] - - *) Add ECDH in new directory crypto/ecdh/. - [Douglas Stebila (Sun Microsystems Laboratories)] - - *) Let BN_rand_range() abort with an error after 100 iterations - without success (which indicates a broken PRNG). - [Bodo Moeller] - - *) Change BN_mod_sqrt() so that it verifies that the input value - is really the square of the return value. (Previously, - BN_mod_sqrt would show GIGO behaviour.) - [Bodo Moeller] - - *) Add named elliptic curves over binary fields from X9.62, SECG, - and WAP/WTLS; add OIDs that were still missing. - - [Sheueling Chang Shantz and Douglas Stebila - (Sun Microsystems Laboratories)] - - *) Extend the EC library for elliptic curves over binary fields - (new files ec2_smpl.c, ec2_smpt.c, ec2_mult.c in crypto/ec/). - New EC_METHOD: - - EC_GF2m_simple_method - - New API functions: - - EC_GROUP_new_curve_GF2m - EC_GROUP_set_curve_GF2m - EC_GROUP_get_curve_GF2m - EC_POINT_set_affine_coordinates_GF2m - EC_POINT_get_affine_coordinates_GF2m - EC_POINT_set_compressed_coordinates_GF2m - - Point compression for binary fields is disabled by default for - patent reasons (compile with OPENSSL_EC_BIN_PT_COMP defined to - enable it). - - As binary polynomials are represented as BIGNUMs, various members - of the EC_GROUP and EC_POINT data structures can be shared - between the implementations for prime fields and binary fields; - the above ..._GF2m functions (except for EX_GROUP_new_curve_GF2m) - are essentially identical to their ..._GFp counterparts. - (For simplicity, the '..._GFp' prefix has been dropped from - various internal method names.) - - An internal 'field_div' method (similar to 'field_mul' and - 'field_sqr') has been added; this is used only for binary fields. - - [Sheueling Chang Shantz and Douglas Stebila - (Sun Microsystems Laboratories)] - - *) Optionally dispatch EC_POINT_mul(), EC_POINT_precompute_mult() - through methods ('mul', 'precompute_mult'). - - The generic implementations (now internally called 'ec_wNAF_mul' - and 'ec_wNAF_precomputed_mult') remain the default if these - methods are undefined. - - [Sheueling Chang Shantz and Douglas Stebila - (Sun Microsystems Laboratories)] - - *) New function EC_GROUP_get_degree, which is defined through - EC_METHOD. For curves over prime fields, this returns the bit - length of the modulus. - - [Sheueling Chang Shantz and Douglas Stebila - (Sun Microsystems Laboratories)] - - *) New functions EC_GROUP_dup, EC_POINT_dup. - (These simply call ..._new and ..._copy). - - [Sheueling Chang Shantz and Douglas Stebila - (Sun Microsystems Laboratories)] - - *) Add binary polynomial arithmetic software in crypto/bn/bn_gf2m.c. - Polynomials are represented as BIGNUMs (where the sign bit is not - used) in the following functions [macros]: - - BN_GF2m_add - BN_GF2m_sub [= BN_GF2m_add] - BN_GF2m_mod [wrapper for BN_GF2m_mod_arr] - BN_GF2m_mod_mul [wrapper for BN_GF2m_mod_mul_arr] - BN_GF2m_mod_sqr [wrapper for BN_GF2m_mod_sqr_arr] - BN_GF2m_mod_inv - BN_GF2m_mod_exp [wrapper for BN_GF2m_mod_exp_arr] - BN_GF2m_mod_sqrt [wrapper for BN_GF2m_mod_sqrt_arr] - BN_GF2m_mod_solve_quad [wrapper for BN_GF2m_mod_solve_quad_arr] - BN_GF2m_cmp [= BN_ucmp] - - (Note that only the 'mod' functions are actually for fields GF(2^m). - BN_GF2m_add() is misnomer, but this is for the sake of consistency.) - - For some functions, an the irreducible polynomial defining a - field can be given as an 'unsigned int[]' with strictly - decreasing elements giving the indices of those bits that are set; - i.e., p[] represents the polynomial - f(t) = t^p[0] + t^p[1] + ... + t^p[k] - where - p[0] > p[1] > ... > p[k] = 0. - This applies to the following functions: - - BN_GF2m_mod_arr - BN_GF2m_mod_mul_arr - BN_GF2m_mod_sqr_arr - BN_GF2m_mod_inv_arr [wrapper for BN_GF2m_mod_inv] - BN_GF2m_mod_div_arr [wrapper for BN_GF2m_mod_div] - BN_GF2m_mod_exp_arr - BN_GF2m_mod_sqrt_arr - BN_GF2m_mod_solve_quad_arr - BN_GF2m_poly2arr - BN_GF2m_arr2poly - - Conversion can be performed by the following functions: - - BN_GF2m_poly2arr - BN_GF2m_arr2poly - - bntest.c has additional tests for binary polynomial arithmetic. - - Two implementations for BN_GF2m_mod_div() are available. - The default algorithm simply uses BN_GF2m_mod_inv() and - BN_GF2m_mod_mul(). The alternative algorithm is compiled in only - if OPENSSL_SUN_GF2M_DIV is defined (patent pending; read the - copyright notice in crypto/bn/bn_gf2m.c before enabling it). - - [Sheueling Chang Shantz and Douglas Stebila - (Sun Microsystems Laboratories)] - - *) Add new error code 'ERR_R_DISABLED' that can be used when some - functionality is disabled at compile-time. - [Douglas Stebila ] - - *) Change default behaviour of 'openssl asn1parse' so that more - information is visible when viewing, e.g., a certificate: - - Modify asn1_parse2 (crypto/asn1/asn1_par.c) so that in non-'dump' - mode the content of non-printable OCTET STRINGs is output in a - style similar to INTEGERs, but with '[HEX DUMP]' prepended to - avoid the appearance of a printable string. - [Nils Larsch ] - - *) Add 'asn1_flag' and 'asn1_form' member to EC_GROUP with access - functions - EC_GROUP_set_asn1_flag() - EC_GROUP_get_asn1_flag() - EC_GROUP_set_point_conversion_form() - EC_GROUP_get_point_conversion_form() - These control ASN1 encoding details: - - Curves (i.e., groups) are encoded explicitly unless asn1_flag - has been set to OPENSSL_EC_NAMED_CURVE. - - Points are encoded in uncompressed form by default; options for - asn1_for are as for point2oct, namely - POINT_CONVERSION_COMPRESSED - POINT_CONVERSION_UNCOMPRESSED - POINT_CONVERSION_HYBRID - - Also add 'seed' and 'seed_len' members to EC_GROUP with access - functions - EC_GROUP_set_seed() - EC_GROUP_get0_seed() - EC_GROUP_get_seed_len() - This is used only for ASN1 purposes (so far). - [Nils Larsch ] - - *) Add 'field_type' member to EC_METHOD, which holds the NID - of the appropriate field type OID. The new function - EC_METHOD_get_field_type() returns this value. - [Nils Larsch ] - - *) Add functions - EC_POINT_point2bn() - EC_POINT_bn2point() - EC_POINT_point2hex() - EC_POINT_hex2point() - providing useful interfaces to EC_POINT_point2oct() and - EC_POINT_oct2point(). - [Nils Larsch ] - - *) Change internals of the EC library so that the functions - EC_GROUP_set_generator() - EC_GROUP_get_generator() - EC_GROUP_get_order() - EC_GROUP_get_cofactor() - are implemented directly in crypto/ec/ec_lib.c and not dispatched - to methods, which would lead to unnecessary code duplication when - adding different types of curves. - [Nils Larsch with input by Bodo Moeller] - - *) Implement compute_wNAF (crypto/ec/ec_mult.c) without BIGNUM - arithmetic, and such that modified wNAFs are generated - (which avoid length expansion in many cases). - [Bodo Moeller] - - *) Add a function EC_GROUP_check_discriminant() (defined via - EC_METHOD) that verifies that the curve discriminant is non-zero. - - Add a function EC_GROUP_check() that makes some sanity tests - on a EC_GROUP, its generator and order. This includes - EC_GROUP_check_discriminant(). - [Nils Larsch ] - - *) Add ECDSA in new directory crypto/ecdsa/. - - Add applications 'openssl ecparam' and 'openssl ecdsa' - (these are based on 'openssl dsaparam' and 'openssl dsa'). - - ECDSA support is also included in various other files across the - library. Most notably, - - 'openssl req' now has a '-newkey ecdsa:file' option; - - EVP_PKCS82PKEY (crypto/evp/evp_pkey.c) now can handle ECDSA; - - X509_PUBKEY_get (crypto/asn1/x_pubkey.c) and - d2i_PublicKey (crypto/asn1/d2i_pu.c) have been modified to make - them suitable for ECDSA where domain parameters must be - extracted before the specific public key; - - ECDSA engine support has been added. - [Nils Larsch ] - - *) Include some named elliptic curves, and add OIDs from X9.62, - SECG, and WAP/WTLS. Each curve can be obtained from the new - function - EC_GROUP_new_by_curve_name(), - and the list of available named curves can be obtained with - EC_get_builtin_curves(). - Also add a 'curve_name' member to EC_GROUP objects, which can be - accessed via - EC_GROUP_set_curve_name() - EC_GROUP_get_curve_name() - [Nils Larsch ] - - *) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that - a ciphersuite string such as "DEFAULT:RSA" cannot enable - authentication-only ciphersuites. - [Bodo Moeller] - - *) Since AES128 and AES256 share a single mask bit in the logic of - ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a - kludge to work properly if AES128 is available and AES256 isn't. - [Victor Duchovni] - - *) Expand security boundary to match 1.1.1 module. - [Steve Henson] - - *) Remove redundant features: hash file source, editing of test vectors - modify fipsld to use external fips_premain.c signature. - [Steve Henson] - - *) New perl script mkfipsscr.pl to create shell scripts or batch files to - run algorithm test programs. - [Steve Henson] - - *) Make algorithm test programs more tolerant of whitespace. - [Steve Henson] - - *) Have SSL/TLS server implementation tolerate "mismatched" record - protocol version while receiving ClientHello even if the - ClientHello is fragmented. (The server can't insist on the - particular protocol version it has chosen before the ServerHello - message has informed the client about his choice.) - [Bodo Moeller] - - *) Load error codes if they are not already present instead of using a - static variable. This allows them to be cleanly unloaded and reloaded. - [Steve Henson] - - Changes between 0.9.7k and 0.9.7l [28 Sep 2006] - - *) Introduce limits to prevent malicious keys being able to - cause a denial of service. (CVE-2006-2940) - [Steve Henson, Bodo Moeller] - - *) Fix ASN.1 parsing of certain invalid structures that can result - in a denial of service. (CVE-2006-2937) [Steve Henson] - - *) Fix buffer overflow in SSL_get_shared_ciphers() function. - (CVE-2006-3738) [Tavis Ormandy and Will Drewry, Google Security Team] - - *) Fix SSL client code which could crash if connecting to a - malicious SSLv2 server. (CVE-2006-4343) - [Tavis Ormandy and Will Drewry, Google Security Team] - - *) Change ciphersuite string processing so that an explicit - ciphersuite selects this one ciphersuite (so that "AES256-SHA" - will no longer include "AES128-SHA"), and any other similar - ciphersuite (same bitmap) from *other* protocol versions (so that - "RC4-MD5" will still include both the SSL 2.0 ciphersuite and the - SSL 3.0/TLS 1.0 ciphersuite). This is a backport combining - changes from 0.9.8b and 0.9.8d. - [Bodo Moeller] - - Changes between 0.9.7j and 0.9.7k [05 Sep 2006] - - *) Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher - (CVE-2006-4339) [Ben Laurie and Google Security Team] - - *) Change the Unix randomness entropy gathering to use poll() when - possible instead of select(), since the latter has some - undesirable limitations. - [Darryl Miles via Richard Levitte and Bodo Moeller] - - *) Disable rogue ciphersuites: - - - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5") - - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5") - - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5") - - The latter two were purportedly from - draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really - appear there. - - Also deactivate the remaining ciphersuites from - draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as - unofficial, and the ID has long expired. - [Bodo Moeller] - - *) Fix RSA blinding Heisenbug (problems sometimes occurred on - dual-core machines) and other potential thread-safety issues. - [Bodo Moeller] - - Changes between 0.9.7i and 0.9.7j [04 May 2006] - - *) Adapt fipsld and the build system to link against the validated FIPS - module in FIPS mode. - [Steve Henson] - - *) Fixes for VC++ 2005 build under Windows. - [Steve Henson] - - *) Add new Windows build target VC-32-GMAKE for VC++. This uses GNU make - from a Windows bash shell such as MSYS. It is autodetected from the - "config" script when run from a VC++ environment. Modify standard VC++ - build to use fipscanister.o from the GNU make build. - [Steve Henson] - - Changes between 0.9.7h and 0.9.7i [14 Oct 2005] - - *) Wrapped the definition of EVP_MAX_MD_SIZE in a #ifdef OPENSSL_FIPS. - The value now differs depending on if you build for FIPS or not. - BEWARE! A program linked with a shared FIPSed libcrypto can't be - safely run with a non-FIPSed libcrypto, as it may crash because of - the difference induced by this change. - [Andy Polyakov] - - Changes between 0.9.7g and 0.9.7h [11 Oct 2005] - - *) Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING - (part of SSL_OP_ALL). This option used to disable the - countermeasure against man-in-the-middle protocol-version - rollback in the SSL 2.0 server implementation, which is a bad - idea. (CVE-2005-2969) - - [Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center - for Information Security, National Institute of Advanced Industrial - Science and Technology [AIST], Japan)] - - *) Minimal support for X9.31 signatures and PSS padding modes. This is - mainly for FIPS compliance and not fully integrated at this stage. - [Steve Henson] - - *) For DSA signing, unless DSA_FLAG_NO_EXP_CONSTTIME is set, perform - the exponentiation using a fixed-length exponent. (Otherwise, - the information leaked through timing could expose the secret key - after many signatures; cf. Bleichenbacher's attack on DSA with - biased k.) - [Bodo Moeller] - - *) Make a new fixed-window mod_exp implementation the default for - RSA, DSA, and DH private-key operations so that the sequence of - squares and multiplies and the memory access pattern are - independent of the particular secret key. This will mitigate - cache-timing and potential related attacks. - - BN_mod_exp_mont_consttime() is the new exponentiation implementation, - and this is automatically used by BN_mod_exp_mont() if the new flag - BN_FLG_EXP_CONSTTIME is set for the exponent. RSA, DSA, and DH - will use this BN flag for private exponents unless the flag - RSA_FLAG_NO_EXP_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME, or - DH_FLAG_NO_EXP_CONSTTIME, respectively, is set. - - [Matthew D Wood (Intel Corp), with some changes by Bodo Moeller] - - *) Change the client implementation for SSLv23_method() and - SSLv23_client_method() so that is uses the SSL 3.0/TLS 1.0 - Client Hello message format if the SSL_OP_NO_SSLv2 option is set. - (Previously, the SSL 2.0 backwards compatible Client Hello - message format would be used even with SSL_OP_NO_SSLv2.) - [Bodo Moeller] - - *) Add support for smime-type MIME parameter in S/MIME messages which some - clients need. - [Steve Henson] - - *) New function BN_MONT_CTX_set_locked() to set montgomery parameters in - a threadsafe manner. Modify rsa code to use new function and add calls - to dsa and dh code (which had race conditions before). - [Steve Henson] - - *) Include the fixed error library code in the C error file definitions - instead of fixing them up at runtime. This keeps the error code - structures constant. - [Steve Henson] - - Changes between 0.9.7f and 0.9.7g [11 Apr 2005] - - [NB: OpenSSL 0.9.7h and later 0.9.7 patch levels were released after - OpenSSL 0.9.8.] - - *) Fixes for newer kerberos headers. NB: the casts are needed because - the 'length' field is signed on one version and unsigned on another - with no (?) obvious way to tell the difference, without these VC++ - complains. Also the "definition" of FAR (blank) is no longer included - nor is the error ENOMEM. KRB5_PRIVATE has to be set to 1 to pick up - some needed definitions. - [Steve Henson] - - *) Undo Cygwin change. - [Ulf Möller] - - *) Added support for proxy certificates according to RFC 3820. - Because they may be a security thread to unaware applications, - they must be explicitly allowed in run-time. See - docs/HOWTO/proxy_certificates.txt for further information. - [Richard Levitte] - - Changes between 0.9.7e and 0.9.7f [22 Mar 2005] - - *) Use (SSL_RANDOM_VALUE - 4) bytes of pseudo random data when generating - server and client random values. Previously - (SSL_RANDOM_VALUE - sizeof(time_t)) would be used which would result in - less random data when sizeof(time_t) > 4 (some 64 bit platforms). - - This change has negligible security impact because: - - 1. Server and client random values still have 24 bytes of pseudo random - data. - - 2. Server and client random values are sent in the clear in the initial - handshake. - - 3. The master secret is derived using the premaster secret (48 bytes in - size for static RSA ciphersuites) as well as client server and random - values. - - The OpenSSL team would like to thank the UK NISCC for bringing this issue - to our attention. - - [Stephen Henson, reported by UK NISCC] - - *) Use Windows randomness collection on Cygwin. - [Ulf Möller] - - *) Fix hang in EGD/PRNGD query when communication socket is closed - prematurely by EGD/PRNGD. - [Darren Tucker via Lutz Jänicke, resolves #1014] - - *) Prompt for pass phrases when appropriate for PKCS12 input format. - [Steve Henson] - - *) Back-port of selected performance improvements from development - branch, as well as improved support for PowerPC platforms. - [Andy Polyakov] - - *) Add lots of checks for memory allocation failure, error codes to indicate - failure and freeing up memory if a failure occurs. - [Nauticus Networks SSL Team , Steve Henson] - - *) Add new -passin argument to dgst. - [Steve Henson] - - *) Perform some character comparisons of different types in X509_NAME_cmp: - this is needed for some certificates that re-encode DNs into UTF8Strings - (in violation of RFC3280) and can't or won't issue name rollover - certificates. - [Steve Henson] - - *) Make an explicit check during certificate validation to see that - the CA setting in each certificate on the chain is correct. As a - side effect always do the following basic checks on extensions, - not just when there's an associated purpose to the check: - - - if there is an unhandled critical extension (unless the user - has chosen to ignore this fault) - - if the path length has been exceeded (if one is set at all) - - that certain extensions fit the associated purpose (if one has - been given) - [Richard Levitte] - - Changes between 0.9.7d and 0.9.7e [25 Oct 2004] - - *) Avoid a race condition when CRLs are checked in a multi threaded - environment. This would happen due to the reordering of the revoked - entries during signature checking and serial number lookup. Now the - encoding is cached and the serial number sort performed under a lock. - Add new STACK function sk_is_sorted(). - [Steve Henson] - - *) Add Delta CRL to the extension code. - [Steve Henson] - - *) Various fixes to s3_pkt.c so alerts are sent properly. - [David Holmes ] - - *) Reduce the chances of duplicate issuer name and serial numbers (in - violation of RFC3280) using the OpenSSL certificate creation utilities. - This is done by creating a random 64 bit value for the initial serial - number when a serial number file is created or when a self signed - certificate is created using 'openssl req -x509'. The initial serial - number file is created using 'openssl x509 -next_serial' in CA.pl - rather than being initialized to 1. - [Steve Henson] - - Changes between 0.9.7c and 0.9.7d [17 Mar 2004] - - *) Fix null-pointer assignment in do_change_cipher_spec() revealed - by using the Codenomicon TLS Test Tool (CVE-2004-0079) - [Joe Orton, Steve Henson] - - *) Fix flaw in SSL/TLS handshaking when using Kerberos ciphersuites - (CVE-2004-0112) - [Joe Orton, Steve Henson] - - *) Make it possible to have multiple active certificates with the same - subject in the CA index file. This is done only if the keyword - 'unique_subject' is set to 'no' in the main CA section (default - if 'CA_default') of the configuration file. The value is saved - with the database itself in a separate index attribute file, - named like the index file with '.attr' appended to the name. - [Richard Levitte] - - *) X509 verify fixes. Disable broken certificate workarounds when - X509_V_FLAGS_X509_STRICT is set. Check CRL issuer has cRLSign set if - keyUsage extension present. Don't accept CRLs with unhandled critical - extensions: since verify currently doesn't process CRL extensions this - rejects a CRL with *any* critical extensions. Add new verify error codes - for these cases. - [Steve Henson] - - *) When creating an OCSP nonce use an OCTET STRING inside the extnValue. - A clarification of RFC2560 will require the use of OCTET STRINGs and - some implementations cannot handle the current raw format. Since OpenSSL - copies and compares OCSP nonces as opaque blobs without any attempt at - parsing them this should not create any compatibility issues. - [Steve Henson] - - *) New md flag EVP_MD_CTX_FLAG_REUSE this allows md_data to be reused when - calling EVP_MD_CTX_copy_ex() to avoid calling OPENSSL_malloc(). Without - this HMAC (and other) operations are several times slower than OpenSSL - < 0.9.7. - [Steve Henson] - - *) Print out GeneralizedTime and UTCTime in ASN1_STRING_print_ex(). - [Peter Sylvester ] - - *) Use the correct content when signing type "other". - [Steve Henson] - - Changes between 0.9.7b and 0.9.7c [30 Sep 2003] - - *) Fix various bugs revealed by running the NISCC test suite: - - Stop out of bounds reads in the ASN1 code when presented with - invalid tags (CVE-2003-0543 and CVE-2003-0544). - - Free up ASN1_TYPE correctly if ANY type is invalid (CVE-2003-0545). - - If verify callback ignores invalid public key errors don't try to check - certificate signature with the NULL public key. - - [Steve Henson] - - *) New -ignore_err option in ocsp application to stop the server - exiting on the first error in a request. - [Steve Henson] - - *) In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate - if the server requested one: as stated in TLS 1.0 and SSL 3.0 - specifications. - [Steve Henson] - - *) In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional - extra data after the compression methods not only for TLS 1.0 - but also for SSL 3.0 (as required by the specification). - [Bodo Moeller; problem pointed out by Matthias Loepfe] - - *) Change X509_certificate_type() to mark the key as exported/exportable - when it's 512 *bits* long, not 512 bytes. - [Richard Levitte] - - *) Change AES_cbc_encrypt() so it outputs exact multiple of - blocks during encryption. - [Richard Levitte] - - *) Various fixes to base64 BIO and non blocking I/O. On write - flushes were not handled properly if the BIO retried. On read - data was not being buffered properly and had various logic bugs. - This also affects blocking I/O when the data being decoded is a - certain size. - [Steve Henson] - - *) Various S/MIME bugfixes and compatibility changes: - output correct application/pkcs7 MIME type if - PKCS7_NOOLDMIMETYPE is set. Tolerate some broken signatures. - Output CR+LF for EOL if PKCS7_CRLFEOL is set (this makes opening - of files as .eml work). Correctly handle very long lines in MIME - parser. - [Steve Henson] - - Changes between 0.9.7a and 0.9.7b [10 Apr 2003] - - *) Countermeasure against the Klima-Pokorny-Rosa extension of - Bleichbacher's attack on PKCS #1 v1.5 padding: treat - a protocol version number mismatch like a decryption error - in ssl3_get_client_key_exchange (ssl/s3_srvr.c). - [Bodo Moeller] - - *) Turn on RSA blinding by default in the default implementation - to avoid a timing attack. Applications that don't want it can call - RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING. - They would be ill-advised to do so in most cases. - [Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller] - - *) Change RSA blinding code so that it works when the PRNG is not - seeded (in this case, the secret RSA exponent is abused as - an unpredictable seed -- if it is not unpredictable, there - is no point in blinding anyway). Make RSA blinding thread-safe - by remembering the creator's thread ID in rsa->blinding and - having all other threads use local one-time blinding factors - (this requires more computation than sharing rsa->blinding, but - avoids excessive locking; and if an RSA object is not shared - between threads, blinding will still be very fast). - [Bodo Moeller] - - *) Fixed a typo bug that would cause ENGINE_set_default() to set an - ENGINE as defaults for all supported algorithms irrespective of - the 'flags' parameter. 'flags' is now honoured, so applications - should make sure they are passing it correctly. - [Geoff Thorpe] - - *) Target "mingw" now allows native Windows code to be generated in - the Cygwin environment as well as with the MinGW compiler. - [Ulf Moeller] - - Changes between 0.9.7 and 0.9.7a [19 Feb 2003] - - *) In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked - via timing by performing a MAC computation even if incorrect - block cipher padding has been found. This is a countermeasure - against active attacks where the attacker has to distinguish - between bad padding and a MAC verification error. (CVE-2003-0078) - - [Bodo Moeller; problem pointed out by Brice Canvel (EPFL), - Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and - Martin Vuagnoux (EPFL, Ilion)] - - *) Make the no-err option work as intended. The intention with no-err - is not to have the whole error stack handling routines removed from - libcrypto, it's only intended to remove all the function name and - reason texts, thereby removing some of the footprint that may not - be interesting if those errors aren't displayed anyway. - - NOTE: it's still possible for any application or module to have its - own set of error texts inserted. The routines are there, just not - used by default when no-err is given. - [Richard Levitte] - - *) Add support for FreeBSD on IA64. - [dirk.meyer@dinoex.sub.org via Richard Levitte, resolves #454] - - *) Adjust DES_cbc_cksum() so it returns the same value as the MIT - Kerberos function mit_des_cbc_cksum(). Before this change, - the value returned by DES_cbc_cksum() was like the one from - mit_des_cbc_cksum(), except the bytes were swapped. - [Kevin Greaney and Richard Levitte] - - *) Allow an application to disable the automatic SSL chain building. - Before this a rather primitive chain build was always performed in - ssl3_output_cert_chain(): an application had no way to send the - correct chain if the automatic operation produced an incorrect result. - - Now the chain builder is disabled if either: - - 1. Extra certificates are added via SSL_CTX_add_extra_chain_cert(). - - 2. The mode flag SSL_MODE_NO_AUTO_CHAIN is set. - - The reasoning behind this is that an application would not want the - auto chain building to take place if extra chain certificates are - present and it might also want a means of sending no additional - certificates (for example the chain has two certificates and the - root is omitted). - [Steve Henson] - - *) Add the possibility to build without the ENGINE framework. - [Steven Reddie via Richard Levitte] - - *) Under Win32 gmtime() can return NULL: check return value in - OPENSSL_gmtime(). Add error code for case where gmtime() fails. - [Steve Henson] - - *) DSA routines: under certain error conditions uninitialized BN objects - could be freed. Solution: make sure initialization is performed early - enough. (Reported and fix supplied by Ivan D Nestlerode , - Nils Larsch via PR#459) - [Lutz Jaenicke] - - *) Another fix for SSLv2 session ID handling: the session ID was incorrectly - checked on reconnect on the client side, therefore session resumption - could still fail with a "ssl session id is different" error. This - behaviour is masked when SSL_OP_ALL is used due to - SSL_OP_MICROSOFT_SESS_ID_BUG being set. - Behaviour observed by Crispin Flowerday as - followup to PR #377. - [Lutz Jaenicke] - - *) IA-32 assembler support enhancements: unified ELF targets, support - for SCO/Caldera platforms, fix for Cygwin shared build. - [Andy Polyakov] - - *) Add support for FreeBSD on sparc64. As a consequence, support for - FreeBSD on non-x86 processors is separate from x86 processors on - the config script, much like the NetBSD support. - [Richard Levitte & Kris Kennaway ] - - Changes between 0.9.6h and 0.9.7 [31 Dec 2002] - - [NB: OpenSSL 0.9.6i and later 0.9.6 patch levels were released after - OpenSSL 0.9.7.] - - *) Fix session ID handling in SSLv2 client code: the SERVER FINISHED - code (06) was taken as the first octet of the session ID and the last - octet was ignored consequently. As a result SSLv2 client side session - caching could not have worked due to the session ID mismatch between - client and server. - Behaviour observed by Crispin Flowerday as - PR #377. - [Lutz Jaenicke] - - *) Change the declaration of needed Kerberos libraries to use EX_LIBS - instead of the special (and badly supported) LIBKRB5. LIBKRB5 is - removed entirely. - [Richard Levitte] - - *) The hw_ncipher.c engine requires dynamic locks. Unfortunately, it - seems that in spite of existing for more than a year, many application - author have done nothing to provide the necessary callbacks, which - means that this particular engine will not work properly anywhere. - This is a very unfortunate situation which forces us, in the name - of usability, to give the hw_ncipher.c a static lock, which is part - of libcrypto. - NOTE: This is for the 0.9.7 series ONLY. This hack will never - appear in 0.9.8 or later. We EXPECT application authors to have - dealt properly with this when 0.9.8 is released (unless we actually - make such changes in the libcrypto locking code that changes will - have to be made anyway). - [Richard Levitte] - - *) In asn1_d2i_read_bio() repeatedly call BIO_read() until all content - octets have been read, EOF or an error occurs. Without this change - some truncated ASN1 structures will not produce an error. - [Steve Henson] - - *) Disable Heimdal support, since it hasn't been fully implemented. - Still give the possibility to force the use of Heimdal, but with - warnings and a request that patches get sent to openssl-dev. - [Richard Levitte] - - *) Add the VC-CE target, introduce the WINCE sysname, and add - INSTALL.WCE and appropriate conditionals to make it build. - [Steven Reddie via Richard Levitte] - - *) Change the DLL names for Cygwin to cygcrypto-x.y.z.dll and - cygssl-x.y.z.dll, where x, y and z are the major, minor and - edit numbers of the version. - [Corinna Vinschen and Richard Levitte] - - *) Introduce safe string copy and catenation functions - (BUF_strlcpy() and BUF_strlcat()). - [Ben Laurie (CHATS) and Richard Levitte] - - *) Avoid using fixed-size buffers for one-line DNs. - [Ben Laurie (CHATS)] - - *) Add BUF_MEM_grow_clean() to avoid information leakage when - resizing buffers containing secrets, and use where appropriate. - [Ben Laurie (CHATS)] - - *) Avoid using fixed size buffers for configuration file location. - [Ben Laurie (CHATS)] - - *) Avoid filename truncation for various CA files. - [Ben Laurie (CHATS)] - - *) Use sizeof in preference to magic numbers. - [Ben Laurie (CHATS)] - - *) Avoid filename truncation in cert requests. - [Ben Laurie (CHATS)] - - *) Add assertions to check for (supposedly impossible) buffer - overflows. - [Ben Laurie (CHATS)] - - *) Don't cache truncated DNS entries in the local cache (this could - potentially lead to a spoofing attack). - [Ben Laurie (CHATS)] - - *) Fix various buffers to be large enough for hex/decimal - representations in a platform independent manner. - [Ben Laurie (CHATS)] - - *) Add CRYPTO_realloc_clean() to avoid information leakage when - resizing buffers containing secrets, and use where appropriate. - [Ben Laurie (CHATS)] - - *) Add BIO_indent() to avoid much slightly worrying code to do - indents. - [Ben Laurie (CHATS)] - - *) Convert sprintf()/BIO_puts() to BIO_printf(). - [Ben Laurie (CHATS)] - - *) buffer_gets() could terminate with the buffer only half - full. Fixed. - [Ben Laurie (CHATS)] - - *) Add assertions to prevent user-supplied crypto functions from - overflowing internal buffers by having large block sizes, etc. - [Ben Laurie (CHATS)] - - *) New OPENSSL_assert() macro (similar to assert(), but enabled - unconditionally). - [Ben Laurie (CHATS)] - - *) Eliminate unused copy of key in RC4. - [Ben Laurie (CHATS)] - - *) Eliminate unused and incorrectly sized buffers for IV in pem.h. - [Ben Laurie (CHATS)] - - *) Fix off-by-one error in EGD path. - [Ben Laurie (CHATS)] - - *) If RANDFILE path is too long, ignore instead of truncating. - [Ben Laurie (CHATS)] - - *) Eliminate unused and incorrectly sized X.509 structure - CBCParameter. - [Ben Laurie (CHATS)] - - *) Eliminate unused and dangerous function knumber(). - [Ben Laurie (CHATS)] - - *) Eliminate unused and dangerous structure, KSSL_ERR. - [Ben Laurie (CHATS)] - - *) Protect against overlong session ID context length in an encoded - session object. Since these are local, this does not appear to be - exploitable. - [Ben Laurie (CHATS)] - - *) Change from security patch (see 0.9.6e below) that did not affect - the 0.9.6 release series: - - Remote buffer overflow in SSL3 protocol - an attacker could - supply an oversized master key in Kerberos-enabled versions. - (CVE-2002-0657) - [Ben Laurie (CHATS)] - - *) Change the SSL kerb5 codes to match RFC 2712. - [Richard Levitte] - - *) Make -nameopt work fully for req and add -reqopt switch. - [Michael Bell , Steve Henson] - - *) The "block size" for block ciphers in CFB and OFB mode should be 1. - [Steve Henson, reported by Yngve Nysaeter Pettersen ] - - *) Make sure tests can be performed even if the corresponding algorithms - have been removed entirely. This was also the last step to make - OpenSSL compilable with DJGPP under all reasonable conditions. - [Richard Levitte, Doug Kaufman ] - - *) Add cipher selection rules COMPLEMENTOFALL and COMPLEMENTOFDEFAULT - to allow version independent disabling of normally unselected ciphers, - which may be activated as a side-effect of selecting a single cipher. - - (E.g., cipher list string "RSA" enables ciphersuites that are left - out of "ALL" because they do not provide symmetric encryption. - "RSA:!COMPLEMEMENTOFALL" avoids these unsafe ciphersuites.) - [Lutz Jaenicke, Bodo Moeller] - - *) Add appropriate support for separate platform-dependent build - directories. The recommended way to make a platform-dependent - build directory is the following (tested on Linux), maybe with - some local tweaks: - - # Place yourself outside of the OpenSSL source tree. In - # this example, the environment variable OPENSSL_SOURCE - # is assumed to contain the absolute OpenSSL source directory. - mkdir -p objtree/"`uname -s`-`uname -r`-`uname -m`" - cd objtree/"`uname -s`-`uname -r`-`uname -m`" - (cd $OPENSSL_SOURCE; find . -type f) | while read F; do - mkdir -p `dirname $F` - ln -s $OPENSSL_SOURCE/$F $F - done - - To be absolutely sure not to disturb the source tree, a "make clean" - is a good thing. If it isn't successful, don't worry about it, - it probably means the source directory is very clean. - [Richard Levitte] - - *) Make sure any ENGINE control commands make local copies of string - pointers passed to them whenever necessary. Otherwise it is possible - the caller may have overwritten (or deallocated) the original string - data when a later ENGINE operation tries to use the stored values. - [Götz Babin-Ebell ] - - *) Improve diagnostics in file reading and command-line digests. - [Ben Laurie aided and abetted by Solar Designer ] - - *) Add AES modes CFB and OFB to the object database. Correct an - error in AES-CFB decryption. - [Richard Levitte] - - *) Remove most calls to EVP_CIPHER_CTX_cleanup() in evp_enc.c, this - allows existing EVP_CIPHER_CTX structures to be reused after - calling EVP_*Final(). This behaviour is used by encryption - BIOs and some applications. This has the side effect that - applications must explicitly clean up cipher contexts with - EVP_CIPHER_CTX_cleanup() or they will leak memory. - [Steve Henson] - - *) Check the values of dna and dnb in bn_mul_recursive before calling - bn_mul_comba (a non zero value means the a or b arrays do not contain - n2 elements) and fallback to bn_mul_normal if either is not zero. - [Steve Henson] - - *) Fix escaping of non-ASCII characters when using the -subj option - of the "openssl req" command line tool. (Robert Joop ) - [Lutz Jaenicke] - - *) Make object definitions compliant to LDAP (RFC2256): SN is the short - form for "surname", serialNumber has no short form. - Use "mail" as the short name for "rfc822Mailbox" according to RFC2798; - therefore remove "mail" short name for "internet 7". - The OID for unique identifiers in X509 certificates is - x500UniqueIdentifier, not uniqueIdentifier. - Some more OID additions. (Michael Bell ) - [Lutz Jaenicke] - - *) Add an "init" command to the ENGINE config module and auto initialize - ENGINEs. Without any "init" command the ENGINE will be initialized - after all ctrl commands have been executed on it. If init=1 the - ENGINE is initialized at that point (ctrls before that point are run - on the uninitialized ENGINE and after on the initialized one). If - init=0 then the ENGINE will not be initialized at all. - [Steve Henson] - - *) Fix the 'app_verify_callback' interface so that the user-defined - argument is actually passed to the callback: In the - SSL_CTX_set_cert_verify_callback() prototype, the callback - declaration has been changed from - int (*cb)() - into - int (*cb)(X509_STORE_CTX *,void *); - in ssl_verify_cert_chain (ssl/ssl_cert.c), the call - i=s->ctx->app_verify_callback(&ctx) - has been changed into - i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg). - - To update applications using SSL_CTX_set_cert_verify_callback(), - a dummy argument can be added to their callback functions. - [D. K. Smetters ] - - *) Added the '4758cca' ENGINE to support IBM 4758 cards. - [Maurice Gittens , touchups by Geoff Thorpe] - - *) Add and OPENSSL_LOAD_CONF define which will cause - OpenSSL_add_all_algorithms() to load the openssl.cnf config file. - This allows older applications to transparently support certain - OpenSSL features: such as crypto acceleration and dynamic ENGINE loading. - Two new functions OPENSSL_add_all_algorithms_noconf() which will never - load the config file and OPENSSL_add_all_algorithms_conf() which will - always load it have also been added. - [Steve Henson] - - *) Add the OFB, CFB and CTR (all with 128 bit feedback) to AES. - Adjust NIDs and EVP layer. - [Stephen Sprunk and Richard Levitte] - - *) Config modules support in openssl utility. - - Most commands now load modules from the config file, - though in a few (such as version) this isn't done - because it couldn't be used for anything. - - In the case of ca and req the config file used is - the same as the utility itself: that is the -config - command line option can be used to specify an - alternative file. - [Steve Henson] - - *) Move default behaviour from OPENSSL_config(). If appname is NULL - use "openssl_conf" if filename is NULL use default openssl config file. - [Steve Henson] - - *) Add an argument to OPENSSL_config() to allow the use of an alternative - config section name. Add a new flag to tolerate a missing config file - and move code to CONF_modules_load_file(). - [Steve Henson] - - *) Support for crypto accelerator cards from Accelerated Encryption - Processing, www.aep.ie. (Use engine 'aep') - The support was copied from 0.9.6c [engine] and adapted/corrected - to work with the new engine framework. - [AEP Inc. and Richard Levitte] - - *) Support for SureWare crypto accelerator cards from Baltimore - Technologies. (Use engine 'sureware') - The support was copied from 0.9.6c [engine] and adapted - to work with the new engine framework. - [Richard Levitte] - - *) Have the CHIL engine fork-safe (as defined by nCipher) and actually - make the newer ENGINE framework commands for the CHIL engine work. - [Toomas Kiisk and Richard Levitte] - - *) Make it possible to produce shared libraries on ReliantUNIX. - [Robert Dahlem via Richard Levitte] - - *) Add the configuration target debug-linux-ppro. - Make 'openssl rsa' use the general key loading routines - implemented in apps.c, and make those routines able to - handle the key format FORMAT_NETSCAPE and the variant - FORMAT_IISSGC. - [Toomas Kiisk via Richard Levitte] - - *) Fix a crashbug and a logic bug in hwcrhk_load_pubkey(). - [Toomas Kiisk via Richard Levitte] - - *) Add -keyform to rsautl, and document -engine. - [Richard Levitte, inspired by Toomas Kiisk ] - - *) Change BIO_new_file (crypto/bio/bss_file.c) to use new - BIO_R_NO_SUCH_FILE error code rather than the generic - ERR_R_SYS_LIB error code if fopen() fails with ENOENT. - [Ben Laurie] - - *) Add new functions - ERR_peek_last_error - ERR_peek_last_error_line - ERR_peek_last_error_line_data. - These are similar to - ERR_peek_error - ERR_peek_error_line - ERR_peek_error_line_data, - but report on the latest error recorded rather than the first one - still in the error queue. - [Ben Laurie, Bodo Moeller] - - *) default_algorithms option in ENGINE config module. This allows things - like: - default_algorithms = ALL - default_algorithms = RSA, DSA, RAND, CIPHERS, DIGESTS - [Steve Henson] - - *) Preliminary ENGINE config module. - [Steve Henson] - - *) New experimental application configuration code. - [Steve Henson] - - *) Change the AES code to follow the same name structure as all other - symmetric ciphers, and behave the same way. Move everything to - the directory crypto/aes, thereby obsoleting crypto/rijndael. - [Stephen Sprunk and Richard Levitte] - - *) SECURITY: remove unsafe setjmp/signal interaction from ui_openssl.c. - [Ben Laurie and Theo de Raadt] - - *) Add option to output public keys in req command. - [Massimiliano Pala madwolf@openca.org] - - *) Use wNAFs in EC_POINTs_mul() for improved efficiency - (up to about 10% better than before for P-192 and P-224). - [Bodo Moeller] - - *) New functions/macros - - SSL_CTX_set_msg_callback(ctx, cb) - SSL_CTX_set_msg_callback_arg(ctx, arg) - SSL_set_msg_callback(ssl, cb) - SSL_set_msg_callback_arg(ssl, arg) - - to request calling a callback function - - void cb(int write_p, int version, int content_type, - const void *buf, size_t len, SSL *ssl, void *arg) - - whenever a protocol message has been completely received - (write_p == 0) or sent (write_p == 1). Here 'version' is the - protocol version according to which the SSL library interprets - the current protocol message (SSL2_VERSION, SSL3_VERSION, or - TLS1_VERSION). 'content_type' is 0 in the case of SSL 2.0, or - the content type as defined in the SSL 3.0/TLS 1.0 protocol - specification (change_cipher_spec(20), alert(21), handshake(22)). - 'buf' and 'len' point to the actual message, 'ssl' to the - SSL object, and 'arg' is the application-defined value set by - SSL[_CTX]_set_msg_callback_arg(). - - 'openssl s_client' and 'openssl s_server' have new '-msg' options - to enable a callback that displays all protocol messages. - [Bodo Moeller] - - *) Change the shared library support so shared libraries are built as - soon as the corresponding static library is finished, and thereby get - openssl and the test programs linked against the shared library. - This still only happens when the keyword "shard" has been given to - the configuration scripts. - - NOTE: shared library support is still an experimental thing, and - backward binary compatibility is still not guaranteed. - ["Maciej W. Rozycki" and Richard Levitte] - - *) Add support for Subject Information Access extension. - [Peter Sylvester ] - - *) Make BUF_MEM_grow() behaviour more consistent: Initialise to zero - additional bytes when new memory had to be allocated, not just - when reusing an existing buffer. - [Bodo Moeller] - - *) New command line and configuration option 'utf8' for the req command. - This allows field values to be specified as UTF8 strings. - [Steve Henson] - - *) Add -multi and -mr options to "openssl speed" - giving multiple parallel - runs for the former and machine-readable output for the latter. - [Ben Laurie] - - *) Add '-noemailDN' option to 'openssl ca'. This prevents inclusion - of the e-mail address in the DN (i.e., it will go into a certificate - extension only). The new configuration file option 'email_in_dn = no' - has the same effect. - [Massimiliano Pala madwolf@openca.org] - - *) Change all functions with names starting with des_ to be starting - with DES_ instead. Add wrappers that are compatible with libdes, - but are named _ossl_old_des_*. Finally, add macros that map the - des_* symbols to the corresponding _ossl_old_des_* if libdes - compatibility is desired. If OpenSSL 0.9.6c compatibility is - desired, the des_* symbols will be mapped to DES_*, with one - exception. - - Since we provide two compatibility mappings, the user needs to - define the macro OPENSSL_DES_LIBDES_COMPATIBILITY if libdes - compatibility is desired. The default (i.e., when that macro - isn't defined) is OpenSSL 0.9.6c compatibility. - - There are also macros that enable and disable the support of old - des functions altogether. Those are OPENSSL_ENABLE_OLD_DES_SUPPORT - and OPENSSL_DISABLE_OLD_DES_SUPPORT. If none or both of those - are defined, the default will apply: to support the old des routines. - - In either case, one must include openssl/des.h to get the correct - definitions. Do not try to just include openssl/des_old.h, that - won't work. - - NOTE: This is a major break of an old API into a new one. Software - authors are encouraged to switch to the DES_ style functions. Some - time in the future, des_old.h and the libdes compatibility functions - will be disable (i.e. OPENSSL_DISABLE_OLD_DES_SUPPORT will be the - default), and then completely removed. - [Richard Levitte] - - *) Test for certificates which contain unsupported critical extensions. - If such a certificate is found during a verify operation it is - rejected by default: this behaviour can be overridden by either - handling the new error X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION or - by setting the verify flag X509_V_FLAG_IGNORE_CRITICAL. A new function - X509_supported_extension() has also been added which returns 1 if a - particular extension is supported. - [Steve Henson] - - *) Modify the behaviour of EVP cipher functions in similar way to digests - to retain compatibility with existing code. - [Steve Henson] - - *) Modify the behaviour of EVP_DigestInit() and EVP_DigestFinal() to retain - compatibility with existing code. In particular the 'ctx' parameter does - not have to be to be initialized before the call to EVP_DigestInit() and - it is tidied up after a call to EVP_DigestFinal(). New function - EVP_DigestFinal_ex() which does not tidy up the ctx. Similarly function - EVP_MD_CTX_copy() changed to not require the destination to be - initialized valid and new function EVP_MD_CTX_copy_ex() added which - requires the destination to be valid. - - Modify all the OpenSSL digest calls to use EVP_DigestInit_ex(), - EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex(). - [Steve Henson] - - *) Change ssl3_get_message (ssl/s3_both.c) and the functions using it - so that complete 'Handshake' protocol structures are kept in memory - instead of overwriting 'msg_type' and 'length' with 'body' data. - [Bodo Moeller] - - *) Add an implementation of SSL_add_dir_cert_subjects_to_stack for Win32. - [Massimo Santin via Richard Levitte] - - *) Major restructuring to the underlying ENGINE code. This includes - reduction of linker bloat, separation of pure "ENGINE" manipulation - (initialisation, etc) from functionality dealing with implementations - of specific crypto interfaces. This change also introduces integrated - support for symmetric ciphers and digest implementations - so ENGINEs - can now accelerate these by providing EVP_CIPHER and EVP_MD - implementations of their own. This is detailed in crypto/engine/README - as it couldn't be adequately described here. However, there are a few - API changes worth noting - some RSA, DSA, DH, and RAND functions that - were changed in the original introduction of ENGINE code have now - reverted back - the hooking from this code to ENGINE is now a good - deal more passive and at run-time, operations deal directly with - RSA_METHODs, DSA_METHODs (etc) as they did before, rather than - dereferencing through an ENGINE pointer any more. Also, the ENGINE - functions dealing with BN_MOD_EXP[_CRT] handlers have been removed - - they were not being used by the framework as there is no concept of a - BIGNUM_METHOD and they could not be generalised to the new - 'ENGINE_TABLE' mechanism that underlies the new code. Similarly, - ENGINE_cpy() has been removed as it cannot be consistently defined in - the new code. - [Geoff Thorpe] - - *) Change ASN1_GENERALIZEDTIME_check() to allow fractional seconds. - [Steve Henson] - - *) Change mkdef.pl to sort symbols that get the same entry number, - and make sure the automatically generated functions ERR_load_* - become part of libeay.num as well. - [Richard Levitte] - - *) New function SSL_renegotiate_pending(). This returns true once - renegotiation has been requested (either SSL_renegotiate() call - or HelloRequest/ClientHello received from the peer) and becomes - false once a handshake has been completed. - (For servers, SSL_renegotiate() followed by SSL_do_handshake() - sends a HelloRequest, but does not ensure that a handshake takes - place. SSL_renegotiate_pending() is useful for checking if the - client has followed the request.) - [Bodo Moeller] - - *) New SSL option SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION. - By default, clients may request session resumption even during - renegotiation (if session ID contexts permit); with this option, - session resumption is possible only in the first handshake. - - SSL_OP_ALL is now 0x00000FFFL instead of 0x000FFFFFL. This makes - more bits available for options that should not be part of - SSL_OP_ALL (such as SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION). - [Bodo Moeller] - - *) Add some demos for certificate and certificate request creation. - [Steve Henson] - - *) Make maximum certificate chain size accepted from the peer application - settable (SSL*_get/set_max_cert_list()), as proposed by - "Douglas E. Engert" . - [Lutz Jaenicke] - - *) Add support for shared libraries for Unixware-7 - (Boyd Lynn Gerber ). - [Lutz Jaenicke] - - *) Add a "destroy" handler to ENGINEs that allows structural cleanup to - be done prior to destruction. Use this to unload error strings from - ENGINEs that load their own error strings. NB: This adds two new API - functions to "get" and "set" this destroy handler in an ENGINE. - [Geoff Thorpe] - - *) Alter all existing ENGINE implementations (except "openssl" and - "openbsd") to dynamically instantiate their own error strings. This - makes them more flexible to be built both as statically-linked ENGINEs - and self-contained shared-libraries loadable via the "dynamic" ENGINE. - Also, add stub code to each that makes building them as self-contained - shared-libraries easier (see README.ENGINE). - [Geoff Thorpe] - - *) Add a "dynamic" ENGINE that provides a mechanism for binding ENGINE - implementations into applications that are completely implemented in - self-contained shared-libraries. The "dynamic" ENGINE exposes control - commands that can be used to configure what shared-library to load and - to control aspects of the way it is handled. Also, made an update to - the README.ENGINE file that brings its information up-to-date and - provides some information and instructions on the "dynamic" ENGINE - (ie. how to use it, how to build "dynamic"-loadable ENGINEs, etc). - [Geoff Thorpe] - - *) Make it possible to unload ranges of ERR strings with a new - "ERR_unload_strings" function. - [Geoff Thorpe] - - *) Add a copy() function to EVP_MD. - [Ben Laurie] - - *) Make EVP_MD routines take a context pointer instead of just the - md_data void pointer. - [Ben Laurie] - - *) Add flags to EVP_MD and EVP_MD_CTX. EVP_MD_FLAG_ONESHOT indicates - that the digest can only process a single chunk of data - (typically because it is provided by a piece of - hardware). EVP_MD_CTX_FLAG_ONESHOT indicates that the application - is only going to provide a single chunk of data, and hence the - framework needn't accumulate the data for oneshot drivers. - [Ben Laurie] - - *) As with "ERR", make it possible to replace the underlying "ex_data" - functions. This change also alters the storage and management of global - ex_data state - it's now all inside ex_data.c and all "class" code (eg. - RSA, BIO, SSL_CTX, etc) no longer stores its own STACKS and per-class - index counters. The API functions that use this state have been changed - to take a "class_index" rather than pointers to the class's local STACK - and counter, and there is now an API function to dynamically create new - classes. This centralisation allows us to (a) plug a lot of the - thread-safety problems that existed, and (b) makes it possible to clean - up all allocated state using "CRYPTO_cleanup_all_ex_data()". W.r.t. (b) - such data would previously have always leaked in application code and - workarounds were in place to make the memory debugging turn a blind eye - to it. Application code that doesn't use this new function will still - leak as before, but their memory debugging output will announce it now - rather than letting it slide. - - Besides the addition of CRYPTO_cleanup_all_ex_data(), another API change - induced by the "ex_data" overhaul is that X509_STORE_CTX_init() now - has a return value to indicate success or failure. - [Geoff Thorpe] - - *) Make it possible to replace the underlying "ERR" functions such that the - global state (2 LHASH tables and 2 locks) is only used by the "default" - implementation. This change also adds two functions to "get" and "set" - the implementation prior to it being automatically set the first time - any other ERR function takes place. Ie. an application can call "get", - pass the return value to a module it has just loaded, and that module - can call its own "set" function using that value. This means the - module's "ERR" operations will use (and modify) the error state in the - application and not in its own statically linked copy of OpenSSL code. - [Geoff Thorpe] - - *) Give DH, DSA, and RSA types their own "**_up_ref()" function to increment - reference counts. This performs normal REF_PRINT/REF_CHECK macros on - the operation, and provides a more encapsulated way for external code - (crypto/evp/ and ssl/) to do this. Also changed the evp and ssl code - to use these functions rather than manually incrementing the counts. - - Also rename "DSO_up()" function to more descriptive "DSO_up_ref()". - [Geoff Thorpe] - - *) Add EVP test program. - [Ben Laurie] - - *) Add symmetric cipher support to ENGINE. Expect the API to change! - [Ben Laurie] - - *) New CRL functions: X509_CRL_set_version(), X509_CRL_set_issuer_name() - X509_CRL_set_lastUpdate(), X509_CRL_set_nextUpdate(), X509_CRL_sort(), - X509_REVOKED_set_serialNumber(), and X509_REVOKED_set_revocationDate(). - These allow a CRL to be built without having to access X509_CRL fields - directly. Modify 'ca' application to use new functions. - [Steve Henson] - - *) Move SSL_OP_TLS_ROLLBACK_BUG out of the SSL_OP_ALL list of recommended - bug workarounds. Rollback attack detection is a security feature. - The problem will only arise on OpenSSL servers when TLSv1 is not - available (sslv3_server_method() or SSL_OP_NO_TLSv1). - Software authors not wanting to support TLSv1 will have special reasons - for their choice and can explicitly enable this option. - [Bodo Moeller, Lutz Jaenicke] - - *) Rationalise EVP so it can be extended: don't include a union of - cipher/digest structures, add init/cleanup functions for EVP_MD_CTX - (similar to those existing for EVP_CIPHER_CTX). - Usage example: - - EVP_MD_CTX md; - - EVP_MD_CTX_init(&md); /* new function call */ - EVP_DigestInit(&md, EVP_sha1()); - EVP_DigestUpdate(&md, in, len); - EVP_DigestFinal(&md, out, NULL); - EVP_MD_CTX_cleanup(&md); /* new function call */ - - [Ben Laurie] - - *) Make DES key schedule conform to the usual scheme, as well as - correcting its structure. This means that calls to DES functions - now have to pass a pointer to a des_key_schedule instead of a - plain des_key_schedule (which was actually always a pointer - anyway): E.g., - - des_key_schedule ks; - - des_set_key_checked(..., &ks); - des_ncbc_encrypt(..., &ks, ...); - - (Note that a later change renames 'des_...' into 'DES_...'.) - [Ben Laurie] - - *) Initial reduction of linker bloat: the use of some functions, such as - PEM causes large amounts of unused functions to be linked in due to - poor organisation. For example pem_all.c contains every PEM function - which has a knock on effect of linking in large amounts of (unused) - ASN1 code. Grouping together similar functions and splitting unrelated - functions prevents this. - [Steve Henson] - - *) Cleanup of EVP macros. - [Ben Laurie] - - *) Change historical references to {NID,SN,LN}_des_ede and ede3 to add the - correct _ecb suffix. - [Ben Laurie] - - *) Add initial OCSP responder support to ocsp application. The - revocation information is handled using the text based index - use by the ca application. The responder can either handle - requests generated internally, supplied in files (for example - via a CGI script) or using an internal minimal server. - [Steve Henson] - - *) Add configuration choices to get zlib compression for TLS. - [Richard Levitte] - - *) Changes to Kerberos SSL for RFC 2712 compliance: - 1. Implemented real KerberosWrapper, instead of just using - KRB5 AP_REQ message. [Thanks to Simon Wilkinson ] - 2. Implemented optional authenticator field of KerberosWrapper. - - Added openssl-style ASN.1 macros for Kerberos ticket, ap_req, - and authenticator structs; see crypto/krb5/. - - Generalized Kerberos calls to support multiple Kerberos libraries. - [Vern Staats , - Jeffrey Altman - via Richard Levitte] - - *) Cause 'openssl speed' to use fully hard-coded DSA keys as it - already does with RSA. testdsa.h now has 'priv_key/pub_key' - values for each of the key sizes rather than having just - parameters (and 'speed' generating keys each time). - [Geoff Thorpe] - - *) Speed up EVP routines. - Before: -encrypt -type 8 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes -des-cbc 4408.85k 5560.51k 5778.46k 5862.20k 5825.16k -des-cbc 4389.55k 5571.17k 5792.23k 5846.91k 5832.11k -des-cbc 4394.32k 5575.92k 5807.44k 5848.37k 5841.30k -decrypt -des-cbc 3482.66k 5069.49k 5496.39k 5614.16k 5639.28k -des-cbc 3480.74k 5068.76k 5510.34k 5609.87k 5635.52k -des-cbc 3483.72k 5067.62k 5504.60k 5708.01k 5724.80k - After: -encrypt -des-cbc 4660.16k 5650.19k 5807.19k 5827.13k 5783.32k -decrypt -des-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k - [Ben Laurie] - - *) Added the OS2-EMX target. - ["Brian Havard" and Richard Levitte] - - *) Rewrite apps to use NCONF routines instead of the old CONF. New functions - to support NCONF routines in extension code. New function CONF_set_nconf() - to allow functions which take an NCONF to also handle the old LHASH - structure: this means that the old CONF compatible routines can be - retained (in particular wrt extensions) without having to duplicate the - code. New function X509V3_add_ext_nconf_sk to add extensions to a stack. - [Steve Henson] - - *) Enhance the general user interface with mechanisms for inner control - and with possibilities to have yes/no kind of prompts. - [Richard Levitte] - - *) Change all calls to low level digest routines in the library and - applications to use EVP. Add missing calls to HMAC_cleanup() and - don't assume HMAC_CTX can be copied using memcpy(). - [Verdon Walker , Steve Henson] - - *) Add the possibility to control engines through control names but with - arbitrary arguments instead of just a string. - Change the key loaders to take a UI_METHOD instead of a callback - function pointer. NOTE: this breaks binary compatibility with earlier - versions of OpenSSL [engine]. - Adapt the nCipher code for these new conditions and add a card insertion - callback. - [Richard Levitte] - - *) Enhance the general user interface with mechanisms to better support - dialog box interfaces, application-defined prompts, the possibility - to use defaults (for example default passwords from somewhere else) - and interrupts/cancellations. - [Richard Levitte] - - *) Tidy up PKCS#12 attribute handling. Add support for the CSP name - attribute in PKCS#12 files, add new -CSP option to pkcs12 utility. - [Steve Henson] - - *) Fix a memory leak in 'sk_dup()' in the case reallocation fails. (Also - tidy up some unnecessarily weird code in 'sk_new()'). - [Geoff, reported by Diego Tartara ] - - *) Change the key loading routines for ENGINEs to use the same kind - callback (pem_password_cb) as all other routines that need this - kind of callback. - [Richard Levitte] - - *) Increase ENTROPY_NEEDED to 32 bytes, as Rijndael can operate with - 256 bit (=32 byte) keys. Of course seeding with more entropy bytes - than this minimum value is recommended. - [Lutz Jaenicke] - - *) New random seeder for OpenVMS, using the system process statistics - that are easily reachable. - [Richard Levitte] - - *) Windows apparently can't transparently handle global - variables defined in DLLs. Initialisations such as: - - const ASN1_ITEM *it = &ASN1_INTEGER_it; - - won't compile. This is used by the any applications that need to - declare their own ASN1 modules. This was fixed by adding the option - EXPORT_VAR_AS_FN to all Win32 platforms, although this isn't strictly - needed for static libraries under Win32. - [Steve Henson] - - *) New functions X509_PURPOSE_set() and X509_TRUST_set() to handle - setting of purpose and trust fields. New X509_STORE trust and - purpose functions and tidy up setting in other SSL functions. - [Steve Henson] - - *) Add copies of X509_STORE_CTX fields and callbacks to X509_STORE - structure. These are inherited by X509_STORE_CTX when it is - initialised. This allows various defaults to be set in the - X509_STORE structure (such as flags for CRL checking and custom - purpose or trust settings) for functions which only use X509_STORE_CTX - internally such as S/MIME. - - Modify X509_STORE_CTX_purpose_inherit() so it only sets purposes and - trust settings if they are not set in X509_STORE. This allows X509_STORE - purposes and trust (in S/MIME for example) to override any set by default. - - Add command line options for CRL checking to smime, s_client and s_server - applications. - [Steve Henson] - - *) Initial CRL based revocation checking. If the CRL checking flag(s) - are set then the CRL is looked up in the X509_STORE structure and - its validity and signature checked, then if the certificate is found - in the CRL the verify fails with a revoked error. - - Various new CRL related callbacks added to X509_STORE_CTX structure. - - Command line options added to 'verify' application to support this. - - This needs some additional work, such as being able to handle multiple - CRLs with different times, extension based lookup (rather than just - by subject name) and ultimately more complete V2 CRL extension - handling. - [Steve Henson] - - *) Add a general user interface API (crypto/ui/). This is designed - to replace things like des_read_password and friends (backward - compatibility functions using this new API are provided). - The purpose is to remove prompting functions from the DES code - section as well as provide for prompting through dialog boxes in - a window system and the like. - [Richard Levitte] - - *) Add "ex_data" support to ENGINE so implementations can add state at a - per-structure level rather than having to store it globally. - [Geoff] - - *) Make it possible for ENGINE structures to be copied when retrieved by - ENGINE_by_id() if the ENGINE specifies a new flag: ENGINE_FLAGS_BY_ID_COPY. - This causes the "original" ENGINE structure to act like a template, - analogous to the RSA vs. RSA_METHOD type of separation. Because of this - operational state can be localised to each ENGINE structure, despite the - fact they all share the same "methods". New ENGINE structures returned in - this case have no functional references and the return value is the single - structural reference. This matches the single structural reference returned - by ENGINE_by_id() normally, when it is incremented on the pre-existing - ENGINE structure. - [Geoff] - - *) Fix ASN1 decoder when decoding type ANY and V_ASN1_OTHER: since this - needs to match any other type at all we need to manually clear the - tag cache. - [Steve Henson] - - *) Changes to the "openssl engine" utility to include; - - verbosity levels ('-v', '-vv', and '-vvv') that provide information - about an ENGINE's available control commands. - - executing control commands from command line arguments using the - '-pre' and '-post' switches. '-post' is only used if '-t' is - specified and the ENGINE is successfully initialised. The syntax for - the individual commands are colon-separated, for example; - openssl engine chil -pre FORK_CHECK:0 -pre SO_PATH:/lib/test.so - [Geoff] - - *) New dynamic control command support for ENGINEs. ENGINEs can now - declare their own commands (numbers), names (strings), descriptions, - and input types for run-time discovery by calling applications. A - subset of these commands are implicitly classed as "executable" - depending on their input type, and only these can be invoked through - the new string-based API function ENGINE_ctrl_cmd_string(). (Eg. this - can be based on user input, config files, etc). The distinction is - that "executable" commands cannot return anything other than a boolean - result and can only support numeric or string input, whereas some - discoverable commands may only be for direct use through - ENGINE_ctrl(), eg. supporting the exchange of binary data, function - pointers, or other custom uses. The "executable" commands are to - support parameterisations of ENGINE behaviour that can be - unambiguously defined by ENGINEs and used consistently across any - OpenSSL-based application. Commands have been added to all the - existing hardware-supporting ENGINEs, noticeably "SO_PATH" to allow - control over shared-library paths without source code alterations. - [Geoff] - - *) Changed all ENGINE implementations to dynamically allocate their - ENGINEs rather than declaring them statically. Apart from this being - necessary with the removal of the ENGINE_FLAGS_MALLOCED distinction, - this also allows the implementations to compile without using the - internal engine_int.h header. - [Geoff] - - *) Minor adjustment to "rand" code. RAND_get_rand_method() now returns a - 'const' value. Any code that should be able to modify a RAND_METHOD - should already have non-const pointers to it (ie. they should only - modify their own ones). - [Geoff] - - *) Made a variety of little tweaks to the ENGINE code. - - "atalla" and "ubsec" string definitions were moved from header files - to C code. "nuron" string definitions were placed in variables - rather than hard-coded - allowing parameterisation of these values - later on via ctrl() commands. - - Removed unused "#if 0"'d code. - - Fixed engine list iteration code so it uses ENGINE_free() to release - structural references. - - Constified the RAND_METHOD element of ENGINE structures. - - Constified various get/set functions as appropriate and added - missing functions (including a catch-all ENGINE_cpy that duplicates - all ENGINE values onto a new ENGINE except reference counts/state). - - Removed NULL parameter checks in get/set functions. Setting a method - or function to NULL is a way of cancelling out a previously set - value. Passing a NULL ENGINE parameter is just plain stupid anyway - and doesn't justify the extra error symbols and code. - - Deprecate the ENGINE_FLAGS_MALLOCED define and move the area for - flags from engine_int.h to engine.h. - - Changed prototypes for ENGINE handler functions (init(), finish(), - ctrl(), key-load functions, etc) to take an (ENGINE*) parameter. - [Geoff] - - *) Implement binary inversion algorithm for BN_mod_inverse in addition - to the algorithm using long division. The binary algorithm can be - used only if the modulus is odd. On 32-bit systems, it is faster - only for relatively small moduli (roughly 20-30% for 128-bit moduli, - roughly 5-15% for 256-bit moduli), so we use it only for moduli - up to 450 bits. In 64-bit environments, the binary algorithm - appears to be advantageous for much longer moduli; here we use it - for moduli up to 2048 bits. - [Bodo Moeller] - - *) Rewrite CHOICE field setting in ASN1_item_ex_d2i(). The old code - could not support the combine flag in choice fields. - [Steve Henson] - - *) Add a 'copy_extensions' option to the 'ca' utility. This copies - extensions from a certificate request to the certificate. - [Steve Henson] - - *) Allow multiple 'certopt' and 'nameopt' options to be separated - by commas. Add 'namopt' and 'certopt' options to the 'ca' config - file: this allows the display of the certificate about to be - signed to be customised, to allow certain fields to be included - or excluded and extension details. The old system didn't display - multicharacter strings properly, omitted fields not in the policy - and couldn't display additional details such as extensions. - [Steve Henson] - - *) Function EC_POINTs_mul for multiple scalar multiplication - of an arbitrary number of elliptic curve points - \sum scalars[i]*points[i], - optionally including the generator defined for the EC_GROUP: - scalar*generator + \sum scalars[i]*points[i]. - - EC_POINT_mul is a simple wrapper function for the typical case - that the point list has just one item (besides the optional - generator). - [Bodo Moeller] - - *) First EC_METHODs for curves over GF(p): - - EC_GFp_simple_method() uses the basic BN_mod_mul and BN_mod_sqr - operations and provides various method functions that can also - operate with faster implementations of modular arithmetic. - - EC_GFp_mont_method() reuses most functions that are part of - EC_GFp_simple_method, but uses Montgomery arithmetic. - - [Bodo Moeller; point addition and point doubling - implementation directly derived from source code provided by - Lenka Fibikova ] - - *) Framework for elliptic curves (crypto/ec/ec.h, crypto/ec/ec_lcl.h, - crypto/ec/ec_lib.c): - - Curves are EC_GROUP objects (with an optional group generator) - based on EC_METHODs that are built into the library. - - Points are EC_POINT objects based on EC_GROUP objects. - - Most of the framework would be able to handle curves over arbitrary - finite fields, but as there are no obvious types for fields other - than GF(p), some functions are limited to that for now. - [Bodo Moeller] - - *) Add the -HTTP option to s_server. It is similar to -WWW, but requires - that the file contains a complete HTTP response. - [Richard Levitte] - - *) Add the ec directory to mkdef.pl and mkfiles.pl. In mkdef.pl - change the def and num file printf format specifier from "%-40sXXX" - to "%-39s XXX". The latter will always guarantee a space after the - field while the former will cause them to run together if the field - is 40 of more characters long. - [Steve Henson] - - *) Constify the cipher and digest 'method' functions and structures - and modify related functions to take constant EVP_MD and EVP_CIPHER - pointers. - [Steve Henson] - - *) Hide BN_CTX structure details in bn_lcl.h instead of publishing them - in . Also further increase BN_CTX_NUM to 32. - [Bodo Moeller] - - *) Modify EVP_Digest*() routines so they now return values. Although the - internal software routines can never fail additional hardware versions - might. - [Steve Henson] - - *) Clean up crypto/err/err.h and change some error codes to avoid conflicts: - - Previously ERR_R_FATAL was too small and coincided with ERR_LIB_PKCS7 - (= ERR_R_PKCS7_LIB); it is now 64 instead of 32. - - ASN1 error codes - ERR_R_NESTED_ASN1_ERROR - ... - ERR_R_MISSING_ASN1_EOS - were 4 .. 9, conflicting with - ERR_LIB_RSA (= ERR_R_RSA_LIB) - ... - ERR_LIB_PEM (= ERR_R_PEM_LIB). - They are now 58 .. 63 (i.e., just below ERR_R_FATAL). - - Add new error code 'ERR_R_INTERNAL_ERROR'. - [Bodo Moeller] - - *) Don't overuse locks in crypto/err/err.c: For data retrieval, CRYPTO_r_lock - suffices. - [Bodo Moeller] - - *) New option '-subj arg' for 'openssl req' and 'openssl ca'. This - sets the subject name for a new request or supersedes the - subject name in a given request. Formats that can be parsed are - 'CN=Some Name, OU=myOU, C=IT' - and - 'CN=Some Name/OU=myOU/C=IT'. - - Add options '-batch' and '-verbose' to 'openssl req'. - [Massimiliano Pala ] - - *) Introduce the possibility to access global variables through - functions on platform were that's the best way to handle exporting - global variables in shared libraries. To enable this functionality, - one must configure with "EXPORT_VAR_AS_FN" or defined the C macro - "OPENSSL_EXPORT_VAR_AS_FUNCTION" in crypto/opensslconf.h (the latter - is normally done by Configure or something similar). - - To implement a global variable, use the macro OPENSSL_IMPLEMENT_GLOBAL - in the source file (foo.c) like this: - - OPENSSL_IMPLEMENT_GLOBAL(int,foo)=1; - OPENSSL_IMPLEMENT_GLOBAL(double,bar); - - To declare a global variable, use the macros OPENSSL_DECLARE_GLOBAL - and OPENSSL_GLOBAL_REF in the header file (foo.h) like this: - - OPENSSL_DECLARE_GLOBAL(int,foo); - #define foo OPENSSL_GLOBAL_REF(foo) - OPENSSL_DECLARE_GLOBAL(double,bar); - #define bar OPENSSL_GLOBAL_REF(bar) - - The #defines are very important, and therefore so is including the - header file everywhere where the defined globals are used. - - The macro OPENSSL_EXPORT_VAR_AS_FUNCTION also affects the definition - of ASN.1 items, but that structure is a bit different. - - The largest change is in util/mkdef.pl which has been enhanced with - better and easier to understand logic to choose which symbols should - go into the Windows .def files as well as a number of fixes and code - cleanup (among others, algorithm keywords are now sorted - lexicographically to avoid constant rewrites). - [Richard Levitte] - - *) In BN_div() keep a copy of the sign of 'num' before writing the - result to 'rm' because if rm==num the value will be overwritten - and produce the wrong result if 'num' is negative: this caused - problems with BN_mod() and BN_nnmod(). - [Steve Henson] - - *) Function OCSP_request_verify(). This checks the signature on an - OCSP request and verifies the signer certificate. The signer - certificate is just checked for a generic purpose and OCSP request - trust settings. - [Steve Henson] - - *) Add OCSP_check_validity() function to check the validity of OCSP - responses. OCSP responses are prepared in real time and may only - be a few seconds old. Simply checking that the current time lies - between thisUpdate and nextUpdate max reject otherwise valid responses - caused by either OCSP responder or client clock inaccuracy. Instead - we allow thisUpdate and nextUpdate to fall within a certain period of - the current time. The age of the response can also optionally be - checked. Two new options -validity_period and -status_age added to - ocsp utility. - [Steve Henson] - - *) If signature or public key algorithm is unrecognized print out its - OID rather that just UNKNOWN. - [Steve Henson] - - *) Change OCSP_cert_to_id() to tolerate a NULL subject certificate and - OCSP_cert_id_new() a NULL serialNumber. This allows a partial certificate - ID to be generated from the issuer certificate alone which can then be - passed to OCSP_id_issuer_cmp(). - [Steve Henson] - - *) New compilation option ASN1_ITEM_FUNCTIONS. This causes the new - ASN1 modules to export functions returning ASN1_ITEM pointers - instead of the ASN1_ITEM structures themselves. This adds several - new macros which allow the underlying ASN1 function/structure to - be accessed transparently. As a result code should not use ASN1_ITEM - references directly (such as &X509_it) but instead use the relevant - macros (such as ASN1_ITEM_rptr(X509)). This option is to allow - use of the new ASN1 code on platforms where exporting structures - is problematical (for example in shared libraries) but exporting - functions returning pointers to structures is not. - [Steve Henson] - - *) Add support for overriding the generation of SSL/TLS session IDs. - These callbacks can be registered either in an SSL_CTX or per SSL. - The purpose of this is to allow applications to control, if they wish, - the arbitrary values chosen for use as session IDs, particularly as it - can be useful for session caching in multiple-server environments. A - command-line switch for testing this (and any client code that wishes - to use such a feature) has been added to "s_server". - [Geoff Thorpe, Lutz Jaenicke] - - *) Modify mkdef.pl to recognise and parse preprocessor conditionals - of the form '#if defined(...) || defined(...) || ...' and - '#if !defined(...) && !defined(...) && ...'. This also avoids - the growing number of special cases it was previously handling. - [Richard Levitte] - - *) Make all configuration macros available for application by making - sure they are available in opensslconf.h, by giving them names starting - with "OPENSSL_" to avoid conflicts with other packages and by making - sure e_os2.h will cover all platform-specific cases together with - opensslconf.h. - Additionally, it is now possible to define configuration/platform- - specific names (called "system identities"). In the C code, these - are prefixed with "OPENSSL_SYSNAME_". e_os2.h will create another - macro with the name beginning with "OPENSSL_SYS_", which is determined - from "OPENSSL_SYSNAME_*" or compiler-specific macros depending on - what is available. - [Richard Levitte] - - *) New option -set_serial to 'req' and 'x509' this allows the serial - number to use to be specified on the command line. Previously self - signed certificates were hard coded with serial number 0 and the - CA options of 'x509' had to use a serial number in a file which was - auto incremented. - [Steve Henson] - - *) New options to 'ca' utility to support V2 CRL entry extensions. - Currently CRL reason, invalidity date and hold instruction are - supported. Add new CRL extensions to V3 code and some new objects. - [Steve Henson] - - *) New function EVP_CIPHER_CTX_set_padding() this is used to - disable standard block padding (aka PKCS#5 padding) in the EVP - API, which was previously mandatory. This means that the data is - not padded in any way and so the total length much be a multiple - of the block size, otherwise an error occurs. - [Steve Henson] - - *) Initial (incomplete) OCSP SSL support. - [Steve Henson] - - *) New function OCSP_parse_url(). This splits up a URL into its host, - port and path components: primarily to parse OCSP URLs. New -url - option to ocsp utility. - [Steve Henson] - - *) New nonce behavior. The return value of OCSP_check_nonce() now - reflects the various checks performed. Applications can decide - whether to tolerate certain situations such as an absent nonce - in a response when one was present in a request: the ocsp application - just prints out a warning. New function OCSP_add1_basic_nonce() - this is to allow responders to include a nonce in a response even if - the request is nonce-less. - [Steve Henson] - - *) Disable stdin buffering in load_cert (apps/apps.c) so that no certs are - skipped when using openssl x509 multiple times on a single input file, - e.g. "(openssl x509 -out cert1; openssl x509 -out cert2) ] - - *) New OCSP verify flag OCSP_TRUSTOTHER. When set the "other" certificates - passed by the function are trusted implicitly. If any of them signed the - response then it is assumed to be valid and is not verified. - [Steve Henson] - - *) In PKCS7_set_type() initialise content_type in PKCS7_ENC_CONTENT - to data. This was previously part of the PKCS7 ASN1 code. This - was causing problems with OpenSSL created PKCS#12 and PKCS#7 structures. - [Steve Henson, reported by Kenneth R. Robinette - ] - - *) Add CRYPTO_push_info() and CRYPTO_pop_info() calls to new ASN1 - routines: without these tracing memory leaks is very painful. - Fix leaks in PKCS12 and PKCS7 routines. - [Steve Henson] - - *) Make X509_time_adj() cope with the new behaviour of ASN1_TIME_new(). - Previously it initialised the 'type' argument to V_ASN1_UTCTIME which - effectively meant GeneralizedTime would never be used. Now it - is initialised to -1 but X509_time_adj() now has to check the value - and use ASN1_TIME_set() if the value is not V_ASN1_UTCTIME or - V_ASN1_GENERALIZEDTIME, without this it always uses GeneralizedTime. - [Steve Henson, reported by Kenneth R. Robinette - ] - - *) Fixes to BN_to_ASN1_INTEGER when bn is zero. This would previously - result in a zero length in the ASN1_INTEGER structure which was - not consistent with the structure when d2i_ASN1_INTEGER() was used - and would cause ASN1_INTEGER_cmp() to fail. Enhance s2i_ASN1_INTEGER() - to cope with hex and negative integers. Fix bug in i2a_ASN1_INTEGER() - where it did not print out a minus for negative ASN1_INTEGER. - [Steve Henson] - - *) Add summary printout to ocsp utility. The various functions which - convert status values to strings have been renamed to: - OCSP_response_status_str(), OCSP_cert_status_str() and - OCSP_crl_reason_str() and are no longer static. New options - to verify nonce values and to disable verification. OCSP response - printout format cleaned up. - [Steve Henson] - - *) Add additional OCSP certificate checks. These are those specified - in RFC2560. This consists of two separate checks: the CA of the - certificate being checked must either be the OCSP signer certificate - or the issuer of the OCSP signer certificate. In the latter case the - OCSP signer certificate must contain the OCSP signing extended key - usage. This check is performed by attempting to match the OCSP - signer or the OCSP signer CA to the issuerNameHash and issuerKeyHash - in the OCSP_CERTID structures of the response. - [Steve Henson] - - *) Initial OCSP certificate verification added to OCSP_basic_verify() - and related routines. This uses the standard OpenSSL certificate - verify routines to perform initial checks (just CA validity) and - to obtain the certificate chain. Then additional checks will be - performed on the chain. Currently the root CA is checked to see - if it is explicitly trusted for OCSP signing. This is used to set - a root CA as a global signing root: that is any certificate that - chains to that CA is an acceptable OCSP signing certificate. - [Steve Henson] - - *) New '-extfile ...' option to 'openssl ca' for reading X.509v3 - extensions from a separate configuration file. - As when reading extensions from the main configuration file, - the '-extensions ...' option may be used for specifying the - section to use. - [Massimiliano Pala ] - - *) New OCSP utility. Allows OCSP requests to be generated or - read. The request can be sent to a responder and the output - parsed, outputted or printed in text form. Not complete yet: - still needs to check the OCSP response validity. - [Steve Henson] - - *) New subcommands for 'openssl ca': - 'openssl ca -status ' prints the status of the cert with - the given serial number (according to the index file). - 'openssl ca -updatedb' updates the expiry status of certificates - in the index file. - [Massimiliano Pala ] - - *) New '-newreq-nodes' command option to CA.pl. This is like - '-newreq', but calls 'openssl req' with the '-nodes' option - so that the resulting key is not encrypted. - [Damien Miller ] - - *) New configuration for the GNU Hurd. - [Jonathan Bartlett via Richard Levitte] - - *) Initial code to implement OCSP basic response verify. This - is currently incomplete. Currently just finds the signer's - certificate and verifies the signature on the response. - [Steve Henson] - - *) New SSLeay_version code SSLEAY_DIR to determine the compiled-in - value of OPENSSLDIR. This is available via the new '-d' option - to 'openssl version', and is also included in 'openssl version -a'. - [Bodo Moeller] - - *) Allowing defining memory allocation callbacks that will be given - file name and line number information in additional arguments - (a const char* and an int). The basic functionality remains, as - well as the original possibility to just replace malloc(), - realloc() and free() by functions that do not know about these - additional arguments. To register and find out the current - settings for extended allocation functions, the following - functions are provided: - - CRYPTO_set_mem_ex_functions - CRYPTO_set_locked_mem_ex_functions - CRYPTO_get_mem_ex_functions - CRYPTO_get_locked_mem_ex_functions - - These work the same way as CRYPTO_set_mem_functions and friends. - CRYPTO_get_[locked_]mem_functions now writes 0 where such an - extended allocation function is enabled. - Similarly, CRYPTO_get_[locked_]mem_ex_functions writes 0 where - a conventional allocation function is enabled. - [Richard Levitte, Bodo Moeller] - - *) Finish off removing the remaining LHASH function pointer casts. - There should no longer be any prototype-casting required when using - the LHASH abstraction, and any casts that remain are "bugs". See - the callback types and macros at the head of lhash.h for details - (and "OBJ_cleanup" in crypto/objects/obj_dat.c as an example). - [Geoff Thorpe] - - *) Add automatic query of EGD sockets in RAND_poll() for the unix variant. - If /dev/[u]random devices are not available or do not return enough - entropy, EGD style sockets (served by EGD or PRNGD) will automatically - be queried. - The locations /var/run/egd-pool, /dev/egd-pool, /etc/egd-pool, and - /etc/entropy will be queried once each in this sequence, querying stops - when enough entropy was collected without querying more sockets. - [Lutz Jaenicke] - - *) Change the Unix RAND_poll() variant to be able to poll several - random devices, as specified by DEVRANDOM, until a sufficient amount - of data has been collected. We spend at most 10 ms on each file - (select timeout) and read in non-blocking mode. DEVRANDOM now - defaults to the list "/dev/urandom", "/dev/random", "/dev/srandom" - (previously it was just the string "/dev/urandom"), so on typical - platforms the 10 ms delay will never occur. - Also separate out the Unix variant to its own file, rand_unix.c. - For VMS, there's a currently-empty rand_vms.c. - [Richard Levitte] - - *) Move OCSP client related routines to ocsp_cl.c. These - provide utility functions which an application needing - to issue a request to an OCSP responder and analyse the - response will typically need: as opposed to those which an - OCSP responder itself would need which will be added later. - - OCSP_request_sign() signs an OCSP request with an API similar - to PKCS7_sign(). OCSP_response_status() returns status of OCSP - response. OCSP_response_get1_basic() extracts basic response - from response. OCSP_resp_find_status(): finds and extracts status - information from an OCSP_CERTID structure (which will be created - when the request structure is built). These are built from lower - level functions which work on OCSP_SINGLERESP structures but - won't normally be used unless the application wishes to examine - extensions in the OCSP response for example. - - Replace nonce routines with a pair of functions. - OCSP_request_add1_nonce() adds a nonce value and optionally - generates a random value. OCSP_check_nonce() checks the - validity of the nonce in an OCSP response. - [Steve Henson] - - *) Change function OCSP_request_add() to OCSP_request_add0_id(). - This doesn't copy the supplied OCSP_CERTID and avoids the - need to free up the newly created id. Change return type - to OCSP_ONEREQ to return the internal OCSP_ONEREQ structure. - This can then be used to add extensions to the request. - Deleted OCSP_request_new(), since most of its functionality - is now in OCSP_REQUEST_new() (and the case insensitive name - clash) apart from the ability to set the request name which - will be added elsewhere. - [Steve Henson] - - *) Update OCSP API. Remove obsolete extensions argument from - various functions. Extensions are now handled using the new - OCSP extension code. New simple OCSP HTTP function which - can be used to send requests and parse the response. - [Steve Henson] - - *) Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new - ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN - uses the special reorder version of SET OF to sort the attributes - and reorder them to match the encoded order. This resolves a long - standing problem: a verify on a PKCS7 structure just after signing - it used to fail because the attribute order did not match the - encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes: - it uses the received order. This is necessary to tolerate some broken - software that does not order SET OF. This is handled by encoding - as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class) - to produce the required SET OF. - [Steve Henson] - - *) Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and - OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header - files to get correct declarations of the ASN.1 item variables. - [Richard Levitte] - - *) Rewrite of PKCS#12 code to use new ASN1 functionality. Replace many - PKCS#12 macros with real functions. Fix two unrelated ASN1 bugs: - asn1_check_tlen() would sometimes attempt to use 'ctx' when it was - NULL and ASN1_TYPE was not dereferenced properly in asn1_ex_c2i(). - New ASN1 macro: DECLARE_ASN1_ITEM() which just declares the relevant - ASN1_ITEM and no wrapper functions. - [Steve Henson] - - *) New functions or ASN1_item_d2i_fp() and ASN1_item_d2i_bio(). These - replace the old function pointer based I/O routines. Change most of - the *_d2i_bio() and *_d2i_fp() functions to use these. - [Steve Henson] - - *) Enhance mkdef.pl to be more accepting about spacing in C preprocessor - lines, recognize more "algorithms" that can be deselected, and make - it complain about algorithm deselection that isn't recognised. - [Richard Levitte] - - *) New ASN1 functions to handle dup, sign, verify, digest, pack and - unpack operations in terms of ASN1_ITEM. Modify existing wrappers - to use new functions. Add NO_ASN1_OLD which can be set to remove - some old style ASN1 functions: this can be used to determine if old - code will still work when these eventually go away. - [Steve Henson] - - *) New extension functions for OCSP structures, these follow the - same conventions as certificates and CRLs. - [Steve Henson] - - *) New function X509V3_add1_i2d(). This automatically encodes and - adds an extension. Its behaviour can be customised with various - flags to append, replace or delete. Various wrappers added for - certificates and CRLs. - [Steve Henson] - - *) Fix to avoid calling the underlying ASN1 print routine when - an extension cannot be parsed. Correct a typo in the - OCSP_SERVICELOC extension. Tidy up print OCSP format. - [Steve Henson] - - *) Make mkdef.pl parse some of the ASN1 macros and add appropriate - entries for variables. - [Steve Henson] - - *) Add functionality to apps/openssl.c for detecting locking - problems: As the program is single-threaded, all we have - to do is register a locking callback using an array for - storing which locks are currently held by the program. - [Bodo Moeller] - - *) Use a lock around the call to CRYPTO_get_ex_new_index() in - SSL_get_ex_data_X509_STORE_idx(), which is used in - ssl_verify_cert_chain() and thus can be called at any time - during TLS/SSL handshakes so that thread-safety is essential. - Unfortunately, the ex_data design is not at all suited - for multi-threaded use, so it probably should be abolished. - [Bodo Moeller] - - *) Added Broadcom "ubsec" ENGINE to OpenSSL. - [Broadcom, tweaked and integrated by Geoff Thorpe] - - *) Move common extension printing code to new function - X509V3_print_extensions(). Reorganise OCSP print routines and - implement some needed OCSP ASN1 functions. Add OCSP extensions. - [Steve Henson] - - *) New function X509_signature_print() to remove duplication in some - print routines. - [Steve Henson] - - *) Add a special meaning when SET OF and SEQUENCE OF flags are both - set (this was treated exactly the same as SET OF previously). This - is used to reorder the STACK representing the structure to match the - encoding. This will be used to get round a problem where a PKCS7 - structure which was signed could not be verified because the STACK - order did not reflect the encoded order. - [Steve Henson] - - *) Reimplement the OCSP ASN1 module using the new code. - [Steve Henson] - - *) Update the X509V3 code to permit the use of an ASN1_ITEM structure - for its ASN1 operations. The old style function pointers still exist - for now but they will eventually go away. - [Steve Henson] - - *) Merge in replacement ASN1 code from the ASN1 branch. This almost - completely replaces the old ASN1 functionality with a table driven - encoder and decoder which interprets an ASN1_ITEM structure describing - the ASN1 module. Compatibility with the existing ASN1 API (i2d,d2i) is - largely maintained. Almost all of the old asn1_mac.h macro based ASN1 - has also been converted to the new form. - [Steve Henson] - - *) Change BN_mod_exp_recp so that negative moduli are tolerated - (the sign is ignored). Similarly, ignore the sign in BN_MONT_CTX_set - so that BN_mod_exp_mont and BN_mod_exp_mont_word work - for negative moduli. - [Bodo Moeller] - - *) Fix BN_uadd and BN_usub: Always return non-negative results instead - of not touching the result's sign bit. - [Bodo Moeller] - - *) BN_div bugfix: If the result is 0, the sign (res->neg) must not be - set. - [Bodo Moeller] - - *) Changed the LHASH code to use prototypes for callbacks, and created - macros to declare and implement thin (optionally static) functions - that provide type-safety and avoid function pointer casting for the - type-specific callbacks. - [Geoff Thorpe] - - *) Added Kerberos Cipher Suites to be used with TLS, as written in - RFC 2712. - [Veers Staats , - Jeffrey Altman , via Richard Levitte] - - *) Reformat the FAQ so the different questions and answers can be divided - in sections depending on the subject. - [Richard Levitte] - - *) Have the zlib compression code load ZLIB.DLL dynamically under - Windows. - [Richard Levitte] - - *) New function BN_mod_sqrt for computing square roots modulo a prime - (using the probabilistic Tonelli-Shanks algorithm unless - p == 3 (mod 4) or p == 5 (mod 8), which are cases that can - be handled deterministically). - [Lenka Fibikova , Bodo Moeller] - - *) Make BN_mod_inverse faster by explicitly handling small quotients - in the Euclid loop. (Speed gain about 20% for small moduli [256 or - 512 bits], about 30% for larger ones [1024 or 2048 bits].) - [Bodo Moeller] - - *) New function BN_kronecker. - [Bodo Moeller] - - *) Fix BN_gcd so that it works on negative inputs; the result is - positive unless both parameters are zero. - Previously something reasonably close to an infinite loop was - possible because numbers could be growing instead of shrinking - in the implementation of Euclid's algorithm. - [Bodo Moeller] - - *) Fix BN_is_word() and BN_is_one() macros to take into account the - sign of the number in question. - - Fix BN_is_word(a,w) to work correctly for w == 0. - - The old BN_is_word(a,w) macro is now called BN_abs_is_word(a,w) - because its test if the absolute value of 'a' equals 'w'. - Note that BN_abs_is_word does *not* handle w == 0 reliably; - it exists mostly for use in the implementations of BN_is_zero(), - BN_is_one(), and BN_is_word(). - [Bodo Moeller] - - *) New function BN_swap. - [Bodo Moeller] - - *) Use BN_nnmod instead of BN_mod in crypto/bn/bn_exp.c so that - the exponentiation functions are more likely to produce reasonable - results on negative inputs. - [Bodo Moeller] - - *) Change BN_mod_mul so that the result is always non-negative. - Previously, it could be negative if one of the factors was negative; - I don't think anyone really wanted that behaviour. - [Bodo Moeller] - - *) Move BN_mod_... functions into new file crypto/bn/bn_mod.c - (except for exponentiation, which stays in crypto/bn/bn_exp.c, - and BN_mod_mul_reciprocal, which stays in crypto/bn/bn_recp.c) - and add new functions: - - BN_nnmod - BN_mod_sqr - BN_mod_add - BN_mod_add_quick - BN_mod_sub - BN_mod_sub_quick - BN_mod_lshift1 - BN_mod_lshift1_quick - BN_mod_lshift - BN_mod_lshift_quick - - These functions always generate non-negative results. - - BN_nnmod otherwise is like BN_mod (if BN_mod computes a remainder r - such that |m| < r < 0, BN_nnmod will output rem + |m| instead). - - BN_mod_XXX_quick(r, a, [b,] m) generates the same result as - BN_mod_XXX(r, a, [b,] m, ctx), but requires that a [and b] - be reduced modulo m. - [Lenka Fibikova , Bodo Moeller] - -#if 0 - The following entry accidentally appeared in the CHANGES file - distributed with OpenSSL 0.9.7. The modifications described in - it do *not* apply to OpenSSL 0.9.7. - - *) Remove a few calls to bn_wexpand() in BN_sqr() (the one in there - was actually never needed) and in BN_mul(). The removal in BN_mul() - required a small change in bn_mul_part_recursive() and the addition - of the functions bn_cmp_part_words(), bn_sub_part_words() and - bn_add_part_words(), which do the same thing as bn_cmp_words(), - bn_sub_words() and bn_add_words() except they take arrays with - differing sizes. - [Richard Levitte] -#endif - - *) In 'openssl passwd', verify passwords read from the terminal - unless the '-salt' option is used (which usually means that - verification would just waste user's time since the resulting - hash is going to be compared with some given password hash) - or the new '-noverify' option is used. - - This is an incompatible change, but it does not affect - non-interactive use of 'openssl passwd' (passwords on the command - line, '-stdin' option, '-in ...' option) and thus should not - cause any problems. - [Bodo Moeller] - - *) Remove all references to RSAref, since there's no more need for it. - [Richard Levitte] - - *) Make DSO load along a path given through an environment variable - (SHLIB_PATH) with shl_load(). - [Richard Levitte] - - *) Constify the ENGINE code as a result of BIGNUM constification. - Also constify the RSA code and most things related to it. In a - few places, most notable in the depth of the ASN.1 code, ugly - casts back to non-const were required (to be solved at a later - time) - [Richard Levitte] - - *) Make it so the openssl application has all engines loaded by default. - [Richard Levitte] - - *) Constify the BIGNUM routines a little more. - [Richard Levitte] - - *) Add the following functions: - - ENGINE_load_cswift() - ENGINE_load_chil() - ENGINE_load_atalla() - ENGINE_load_nuron() - ENGINE_load_builtin_engines() - - That way, an application can itself choose if external engines that - are built-in in OpenSSL shall ever be used or not. The benefit is - that applications won't have to be linked with libdl or other dso - libraries unless it's really needed. - - Changed 'openssl engine' to load all engines on demand. - Changed the engine header files to avoid the duplication of some - declarations (they differed!). - [Richard Levitte] - - *) 'openssl engine' can now list capabilities. - [Richard Levitte] - - *) Better error reporting in 'openssl engine'. - [Richard Levitte] - - *) Never call load_dh_param(NULL) in s_server. - [Bodo Moeller] - - *) Add engine application. It can currently list engines by name and - identity, and test if they are actually available. - [Richard Levitte] - - *) Improve RPM specification file by forcing symbolic linking and making - sure the installed documentation is also owned by root.root. - [Damien Miller ] - - *) Give the OpenSSL applications more possibilities to make use of - keys (public as well as private) handled by engines. - [Richard Levitte] - - *) Add OCSP code that comes from CertCo. - [Richard Levitte] - - *) Add VMS support for the Rijndael code. - [Richard Levitte] - - *) Added untested support for Nuron crypto accelerator. - [Ben Laurie] - - *) Add support for external cryptographic devices. This code was - previously distributed separately as the "engine" branch. - [Geoff Thorpe, Richard Levitte] - - *) Rework the filename-translation in the DSO code. It is now possible to - have far greater control over how a "name" is turned into a filename - depending on the operating environment and any oddities about the - different shared library filenames on each system. - [Geoff Thorpe] - - *) Support threads on FreeBSD-elf in Configure. - [Richard Levitte] - - *) Fix for SHA1 assembly problem with MASM: it produces - warnings about corrupt line number information when assembling - with debugging information. This is caused by the overlapping - of two sections. - [Bernd Matthes , Steve Henson] - - *) NCONF changes. - NCONF_get_number() has no error checking at all. As a replacement, - NCONF_get_number_e() is defined (_e for "error checking") and is - promoted strongly. The old NCONF_get_number is kept around for - binary backward compatibility. - Make it possible for methods to load from something other than a BIO, - by providing a function pointer that is given a name instead of a BIO. - For example, this could be used to load configuration data from an - LDAP server. - [Richard Levitte] - - *) Fix for non blocking accept BIOs. Added new I/O special reason - BIO_RR_ACCEPT to cover this case. Previously use of accept BIOs - with non blocking I/O was not possible because no retry code was - implemented. Also added new SSL code SSL_WANT_ACCEPT to cover - this case. - [Steve Henson] - - *) Added the beginnings of Rijndael support. - [Ben Laurie] - - *) Fix for bug in DirectoryString mask setting. Add support for - X509_NAME_print_ex() in 'req' and X509_print_ex() function - to allow certificate printing to more controllable, additional - 'certopt' option to 'x509' to allow new printing options to be - set. - [Steve Henson] - - *) Clean old EAY MD5 hack from e_os.h. - [Richard Levitte] - - Changes between 0.9.6l and 0.9.6m [17 Mar 2004] - - *) Fix null-pointer assignment in do_change_cipher_spec() revealed - by using the Codenomicon TLS Test Tool (CVE-2004-0079) - [Joe Orton, Steve Henson] - - Changes between 0.9.6k and 0.9.6l [04 Nov 2003] - - *) Fix additional bug revealed by the NISCC test suite: - - Stop bug triggering large recursion when presented with - certain ASN.1 tags (CVE-2003-0851) - [Steve Henson] - - Changes between 0.9.6j and 0.9.6k [30 Sep 2003] - - *) Fix various bugs revealed by running the NISCC test suite: - - Stop out of bounds reads in the ASN1 code when presented with - invalid tags (CVE-2003-0543 and CVE-2003-0544). - - If verify callback ignores invalid public key errors don't try to check - certificate signature with the NULL public key. - - [Steve Henson] - - *) In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate - if the server requested one: as stated in TLS 1.0 and SSL 3.0 - specifications. - [Steve Henson] - - *) In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional - extra data after the compression methods not only for TLS 1.0 - but also for SSL 3.0 (as required by the specification). - [Bodo Moeller; problem pointed out by Matthias Loepfe] - - *) Change X509_certificate_type() to mark the key as exported/exportable - when it's 512 *bits* long, not 512 bytes. - [Richard Levitte] - - Changes between 0.9.6i and 0.9.6j [10 Apr 2003] - - *) Countermeasure against the Klima-Pokorny-Rosa extension of - Bleichbacher's attack on PKCS #1 v1.5 padding: treat - a protocol version number mismatch like a decryption error - in ssl3_get_client_key_exchange (ssl/s3_srvr.c). - [Bodo Moeller] - - *) Turn on RSA blinding by default in the default implementation - to avoid a timing attack. Applications that don't want it can call - RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING. - They would be ill-advised to do so in most cases. - [Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller] - - *) Change RSA blinding code so that it works when the PRNG is not - seeded (in this case, the secret RSA exponent is abused as - an unpredictable seed -- if it is not unpredictable, there - is no point in blinding anyway). Make RSA blinding thread-safe - by remembering the creator's thread ID in rsa->blinding and - having all other threads use local one-time blinding factors - (this requires more computation than sharing rsa->blinding, but - avoids excessive locking; and if an RSA object is not shared - between threads, blinding will still be very fast). - [Bodo Moeller] - - Changes between 0.9.6h and 0.9.6i [19 Feb 2003] - - *) In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked - via timing by performing a MAC computation even if incorrect - block cipher padding has been found. This is a countermeasure - against active attacks where the attacker has to distinguish - between bad padding and a MAC verification error. (CVE-2003-0078) - - [Bodo Moeller; problem pointed out by Brice Canvel (EPFL), - Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and - Martin Vuagnoux (EPFL, Ilion)] - - Changes between 0.9.6g and 0.9.6h [5 Dec 2002] - - *) New function OPENSSL_cleanse(), which is used to cleanse a section of - memory from its contents. This is done with a counter that will - place alternating values in each byte. This can be used to solve - two issues: 1) the removal of calls to memset() by highly optimizing - compilers, and 2) cleansing with other values than 0, since those can - be read through on certain media, for example a swap space on disk. - [Geoff Thorpe] - - *) Bugfix: client side session caching did not work with external caching, - because the session->cipher setting was not restored when reloading - from the external cache. This problem was masked, when - SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG (part of SSL_OP_ALL) was set. - (Found by Steve Haslam .) - [Lutz Jaenicke] - - *) Fix client_certificate (ssl/s2_clnt.c): The permissible total - length of the REQUEST-CERTIFICATE message is 18 .. 34, not 17 .. 33. - [Zeev Lieber ] - - *) Undo an undocumented change introduced in 0.9.6e which caused - repeated calls to OpenSSL_add_all_ciphers() and - OpenSSL_add_all_digests() to be ignored, even after calling - EVP_cleanup(). - [Richard Levitte] - - *) Change the default configuration reader to deal with last line not - being properly terminated. - [Richard Levitte] - - *) Change X509_NAME_cmp() so it applies the special rules on handling - DN values that are of type PrintableString, as well as RDNs of type - emailAddress where the value has the type ia5String. - [stefank@valicert.com via Richard Levitte] - - *) Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half - the job SSL_SESS_CACHE_NO_INTERNAL_LOOKUP was inconsistently - doing, define a new flag (SSL_SESS_CACHE_NO_INTERNAL) to be - the bitwise-OR of the two for use by the majority of applications - wanting this behaviour, and update the docs. The documented - behaviour and actual behaviour were inconsistent and had been - changing anyway, so this is more a bug-fix than a behavioural - change. - [Geoff Thorpe, diagnosed by Nadav Har'El] - - *) Don't impose a 16-byte length minimum on session IDs in ssl/s3_clnt.c - (the SSL 3.0 and TLS 1.0 specifications allow any length up to 32 bytes). - [Bodo Moeller] - - *) Fix initialization code race conditions in - SSLv23_method(), SSLv23_client_method(), SSLv23_server_method(), - SSLv2_method(), SSLv2_client_method(), SSLv2_server_method(), - SSLv3_method(), SSLv3_client_method(), SSLv3_server_method(), - TLSv1_method(), TLSv1_client_method(), TLSv1_server_method(), - ssl2_get_cipher_by_char(), - ssl3_get_cipher_by_char(). - [Patrick McCormick , Bodo Moeller] - - *) Reorder cleanup sequence in SSL_CTX_free(): only remove the ex_data after - the cached sessions are flushed, as the remove_cb() might use ex_data - contents. Bug found by Sam Varshavchik - (see [openssl.org #212]). - [Geoff Thorpe, Lutz Jaenicke] - - *) Fix typo in OBJ_txt2obj which incorrectly passed the content - length, instead of the encoding length to d2i_ASN1_OBJECT. - [Steve Henson] - - Changes between 0.9.6f and 0.9.6g [9 Aug 2002] - - *) [In 0.9.6g-engine release:] - Fix crypto/engine/vendor_defns/cswift.h for WIN32 (use '_stdcall'). - [Lynn Gazis ] - - Changes between 0.9.6e and 0.9.6f [8 Aug 2002] - - *) Fix ASN1 checks. Check for overflow by comparing with LONG_MAX - and get fix the header length calculation. - [Florian Weimer , - Alon Kantor (and others), - Steve Henson] - - *) Use proper error handling instead of 'assertions' in buffer - overflow checks added in 0.9.6e. This prevents DoS (the - assertions could call abort()). - [Arne Ansper , Bodo Moeller] - - Changes between 0.9.6d and 0.9.6e [30 Jul 2002] - - *) Add various sanity checks to asn1_get_length() to reject - the ASN1 length bytes if they exceed sizeof(long), will appear - negative or the content length exceeds the length of the - supplied buffer. - [Steve Henson, Adi Stav , James Yonan ] - - *) Fix cipher selection routines: ciphers without encryption had no flags - for the cipher strength set and where therefore not handled correctly - by the selection routines (PR #130). - [Lutz Jaenicke] - - *) Fix EVP_dsa_sha macro. - [Nils Larsch] - - *) New option - SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - for disabling the SSL 3.0/TLS 1.0 CBC vulnerability countermeasure - that was added in OpenSSL 0.9.6d. - - As the countermeasure turned out to be incompatible with some - broken SSL implementations, the new option is part of SSL_OP_ALL. - SSL_OP_ALL is usually employed when compatibility with weird SSL - implementations is desired (e.g. '-bugs' option to 's_client' and - 's_server'), so the new option is automatically set in many - applications. - [Bodo Moeller] - - *) Changes in security patch: - - Changes marked "(CHATS)" were sponsored by the Defense Advanced - Research Projects Agency (DARPA) and Air Force Research Laboratory, - Air Force Materiel Command, USAF, under agreement number - F30602-01-2-0537. - - *) Add various sanity checks to asn1_get_length() to reject - the ASN1 length bytes if they exceed sizeof(long), will appear - negative or the content length exceeds the length of the - supplied buffer. (CVE-2002-0659) - [Steve Henson, Adi Stav , James Yonan ] - - *) Assertions for various potential buffer overflows, not known to - happen in practice. - [Ben Laurie (CHATS)] - - *) Various temporary buffers to hold ASCII versions of integers were - too small for 64 bit platforms. (CVE-2002-0655) - [Matthew Byng-Maddick and Ben Laurie (CHATS)> - - *) Remote buffer overflow in SSL3 protocol - an attacker could - supply an oversized session ID to a client. (CVE-2002-0656) - [Ben Laurie (CHATS)] - - *) Remote buffer overflow in SSL2 protocol - an attacker could - supply an oversized client master key. (CVE-2002-0656) - [Ben Laurie (CHATS)] - - Changes between 0.9.6c and 0.9.6d [9 May 2002] - - *) Fix crypto/asn1/a_sign.c so that 'parameters' is omitted (not - encoded as NULL) with id-dsa-with-sha1. - [Nils Larsch ; problem pointed out by Bodo Moeller] - - *) Check various X509_...() return values in apps/req.c. - [Nils Larsch ] - - *) Fix BASE64 decode (EVP_DecodeUpdate) for data with CR/LF ended lines: - an end-of-file condition would erroneously be flagged, when the CRLF - was just at the end of a processed block. The bug was discovered when - processing data through a buffering memory BIO handing the data to a - BASE64-decoding BIO. Bug fund and patch submitted by Pavel Tsekov - and Nedelcho Stanev. - [Lutz Jaenicke] - - *) Implement a countermeasure against a vulnerability recently found - in CBC ciphersuites in SSL 3.0/TLS 1.0: Send an empty fragment - before application data chunks to avoid the use of known IVs - with data potentially chosen by the attacker. - [Bodo Moeller] - - *) Fix length checks in ssl3_get_client_hello(). - [Bodo Moeller] - - *) TLS/SSL library bugfix: use s->s3->in_read_app_data differently - to prevent ssl3_read_internal() from incorrectly assuming that - ssl3_read_bytes() found application data while handshake - processing was enabled when in fact s->s3->in_read_app_data was - merely automatically cleared during the initial handshake. - [Bodo Moeller; problem pointed out by Arne Ansper ] - - *) Fix object definitions for Private and Enterprise: they were not - recognized in their shortname (=lowercase) representation. Extend - obj_dat.pl to issue an error when using undefined keywords instead - of silently ignoring the problem (Svenning Sorensen - ). - [Lutz Jaenicke] - - *) Fix DH_generate_parameters() so that it works for 'non-standard' - generators, i.e. generators other than 2 and 5. (Previously, the - code did not properly initialise the 'add' and 'rem' values to - BN_generate_prime().) - - In the new general case, we do not insist that 'generator' is - actually a primitive root: This requirement is rather pointless; - a generator of the order-q subgroup is just as good, if not - better. - [Bodo Moeller] - - *) Map new X509 verification errors to alerts. Discovered and submitted by - Tom Wu . - [Lutz Jaenicke] - - *) Fix ssl3_pending() (ssl/s3_lib.c) to prevent SSL_pending() from - returning non-zero before the data has been completely received - when using non-blocking I/O. - [Bodo Moeller; problem pointed out by John Hughes] - - *) Some of the ciphers missed the strength entry (SSL_LOW etc). - [Ben Laurie, Lutz Jaenicke] - - *) Fix bug in SSL_clear(): bad sessions were not removed (found by - Yoram Zahavi ). - [Lutz Jaenicke] - - *) Add information about CygWin 1.3 and on, and preserve proper - configuration for the versions before that. - [Corinna Vinschen and Richard Levitte] - - *) Make removal from session cache (SSL_CTX_remove_session()) more robust: - check whether we deal with a copy of a session and do not delete from - the cache in this case. Problem reported by "Izhar Shoshani Levi" - . - [Lutz Jaenicke] - - *) Do not store session data into the internal session cache, if it - is never intended to be looked up (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP - flag is set). Proposed by Aslam . - [Lutz Jaenicke] - - *) Have ASN1_BIT_STRING_set_bit() really clear a bit when the requested - value is 0. - [Richard Levitte] - - *) [In 0.9.6d-engine release:] - Fix a crashbug and a logic bug in hwcrhk_load_pubkey(). - [Toomas Kiisk via Richard Levitte] - - *) Add the configuration target linux-s390x. - [Neale Ferguson via Richard Levitte] - - *) The earlier bugfix for the SSL3_ST_SW_HELLO_REQ_C case of - ssl3_accept (ssl/s3_srvr.c) incorrectly used a local flag - variable as an indication that a ClientHello message has been - received. As the flag value will be lost between multiple - invocations of ssl3_accept when using non-blocking I/O, the - function may not be aware that a handshake has actually taken - place, thus preventing a new session from being added to the - session cache. - - To avoid this problem, we now set s->new_session to 2 instead of - using a local variable. - [Lutz Jaenicke, Bodo Moeller] - - *) Bugfix: Return -1 from ssl3_get_server_done (ssl3/s3_clnt.c) - if the SSL_R_LENGTH_MISMATCH error is detected. - [Geoff Thorpe, Bodo Moeller] - - *) New 'shared_ldflag' column in Configure platform table. - [Richard Levitte] - - *) Fix EVP_CIPHER_mode macro. - ["Dan S. Camper" ] - - *) Fix ssl3_read_bytes (ssl/s3_pkt.c): To ignore messages of unknown - type, we must throw them away by setting rr->length to 0. - [D P Chang ] - - Changes between 0.9.6b and 0.9.6c [21 dec 2001] - - *) Fix BN_rand_range bug pointed out by Dominikus Scherkl - . (The previous implementation - worked incorrectly for those cases where range = 10..._2 and - 3*range is two bits longer than range.) - [Bodo Moeller] - - *) Only add signing time to PKCS7 structures if it is not already - present. - [Steve Henson] - - *) Fix crypto/objects/objects.h: "ld-ce" should be "id-ce", - OBJ_ld_ce should be OBJ_id_ce. - Also some ip-pda OIDs in crypto/objects/objects.txt were - incorrect (cf. RFC 3039). - [Matt Cooper, Frederic Giudicelli, Bodo Moeller] - - *) Release CRYPTO_LOCK_DYNLOCK when CRYPTO_destroy_dynlockid() - returns early because it has nothing to do. - [Andy Schneider ] - - *) [In 0.9.6c-engine release:] - Fix mutex callback return values in crypto/engine/hw_ncipher.c. - [Andy Schneider ] - - *) [In 0.9.6c-engine release:] - Add support for Cryptographic Appliance's keyserver technology. - (Use engine 'keyclient') - [Cryptographic Appliances and Geoff Thorpe] - - *) Add a configuration entry for OS/390 Unix. The C compiler 'c89' - is called via tools/c89.sh because arguments have to be - rearranged (all '-L' options must appear before the first object - modules). - [Richard Shapiro ] - - *) [In 0.9.6c-engine release:] - Add support for Broadcom crypto accelerator cards, backported - from 0.9.7. - [Broadcom, Nalin Dahyabhai , Mark Cox] - - *) [In 0.9.6c-engine release:] - Add support for SureWare crypto accelerator cards from - Baltimore Technologies. (Use engine 'sureware') - [Baltimore Technologies and Mark Cox] - - *) [In 0.9.6c-engine release:] - Add support for crypto accelerator cards from Accelerated - Encryption Processing, www.aep.ie. (Use engine 'aep') - [AEP Inc. and Mark Cox] - - *) Add a configuration entry for gcc on UnixWare. - [Gary Benson ] - - *) Change ssl/s2_clnt.c and ssl/s2_srvr.c so that received handshake - messages are stored in a single piece (fixed-length part and - variable-length part combined) and fix various bugs found on the way. - [Bodo Moeller] - - *) Disable caching in BIO_gethostbyname(), directly use gethostbyname() - instead. BIO_gethostbyname() does not know what timeouts are - appropriate, so entries would stay in cache even when they have - become invalid. - [Bodo Moeller; problem pointed out by Rich Salz - - *) Change ssl23_get_client_hello (ssl/s23_srvr.c) behaviour when - faced with a pathologically small ClientHello fragment that does - not contain client_version: Instead of aborting with an error, - simply choose the highest available protocol version (i.e., - TLS 1.0 unless it is disabled). In practice, ClientHello - messages are never sent like this, but this change gives us - strictly correct behaviour at least for TLS. - [Bodo Moeller] - - *) Fix SSL handshake functions and SSL_clear() such that SSL_clear() - never resets s->method to s->ctx->method when called from within - one of the SSL handshake functions. - [Bodo Moeller; problem pointed out by Niko Baric] - - *) In ssl3_get_client_hello (ssl/s3_srvr.c), generate a fatal alert - (sent using the client's version number) if client_version is - smaller than the protocol version in use. Also change - ssl23_get_client_hello (ssl/s23_srvr.c) to select TLS 1.0 if - the client demanded SSL 3.0 but only TLS 1.0 is enabled; then - the client will at least see that alert. - [Bodo Moeller] - - *) Fix ssl3_get_message (ssl/s3_both.c) to handle message fragmentation - correctly. - [Bodo Moeller] - - *) Avoid infinite loop in ssl3_get_message (ssl/s3_both.c) if a - client receives HelloRequest while in a handshake. - [Bodo Moeller; bug noticed by Andy Schneider ] - - *) Bugfix in ssl3_accept (ssl/s3_srvr.c): Case SSL3_ST_SW_HELLO_REQ_C - should end in 'break', not 'goto end' which circumvents various - cleanups done in state SSL_ST_OK. But session related stuff - must be disabled for SSL_ST_OK in the case that we just sent a - HelloRequest. - - Also avoid some overhead by not calling ssl_init_wbio_buffer() - before just sending a HelloRequest. - [Bodo Moeller, Eric Rescorla ] - - *) Fix ssl/s3_enc.c, ssl/t1_enc.c and ssl/s3_pkt.c so that we don't - reveal whether illegal block cipher padding was found or a MAC - verification error occurred. (Neither SSLerr() codes nor alerts - are directly visible to potential attackers, but the information - may leak via logfiles.) - - Similar changes are not required for the SSL 2.0 implementation - because the number of padding bytes is sent in clear for SSL 2.0, - and the extra bytes are just ignored. However ssl/s2_pkt.c - failed to verify that the purported number of padding bytes is in - the legal range. - [Bodo Moeller] - - *) Add OpenUNIX-8 support including shared libraries - (Boyd Lynn Gerber ). - [Lutz Jaenicke] - - *) Improve RSA_padding_check_PKCS1_OAEP() check again to avoid - 'wristwatch attack' using huge encoding parameters (cf. - James H. Manger's CRYPTO 2001 paper). Note that the - RSA_PKCS1_OAEP_PADDING case of RSA_private_decrypt() does not use - encoding parameters and hence was not vulnerable. - [Bodo Moeller] - - *) BN_sqr() bug fix. - [Ulf Möller, reported by Jim Ellis ] - - *) Rabin-Miller test analyses assume uniformly distributed witnesses, - so use BN_pseudo_rand_range() instead of using BN_pseudo_rand() - followed by modular reduction. - [Bodo Moeller; pointed out by Adam Young ] - - *) Add BN_pseudo_rand_range() with obvious functionality: BN_rand_range() - equivalent based on BN_pseudo_rand() instead of BN_rand(). - [Bodo Moeller] - - *) s3_srvr.c: allow sending of large client certificate lists (> 16 kB). - This function was broken, as the check for a new client hello message - to handle SGC did not allow these large messages. - (Tracked down by "Douglas E. Engert" .) - [Lutz Jaenicke] - - *) Add alert descriptions for TLSv1 to SSL_alert_desc_string[_long](). - [Lutz Jaenicke] - - *) Fix buggy behaviour of BIO_get_num_renegotiates() and BIO_ctrl() - for BIO_C_GET_WRITE_BUF_SIZE ("Stephen Hinton" ). - [Lutz Jaenicke] - - *) Rework the configuration and shared library support for Tru64 Unix. - The configuration part makes use of modern compiler features and - still retains old compiler behavior for those that run older versions - of the OS. The shared library support part includes a variant that - uses the RPATH feature, and is available through the special - configuration target "alpha-cc-rpath", which will never be selected - automatically. - [Tim Mooney via Richard Levitte] - - *) In ssl3_get_key_exchange (ssl/s3_clnt.c), call ssl3_get_message() - with the same message size as in ssl3_get_certificate_request(). - Otherwise, if no ServerKeyExchange message occurs, CertificateRequest - messages might inadvertently be reject as too long. - [Petr Lampa ] - - *) Enhanced support for IA-64 Unix platforms (well, Linux and HP-UX). - [Andy Polyakov] - - *) Modified SSL library such that the verify_callback that has been set - specifically for an SSL object with SSL_set_verify() is actually being - used. Before the change, a verify_callback set with this function was - ignored and the verify_callback() set in the SSL_CTX at the time of - the call was used. New function X509_STORE_CTX_set_verify_cb() introduced - to allow the necessary settings. - [Lutz Jaenicke] - - *) Initialize static variable in crypto/dsa/dsa_lib.c and crypto/dh/dh_lib.c - explicitly to NULL, as at least on Solaris 8 this seems not always to be - done automatically (in contradiction to the requirements of the C - standard). This made problems when used from OpenSSH. - [Lutz Jaenicke] - - *) In OpenSSL 0.9.6a and 0.9.6b, crypto/dh/dh_key.c ignored - dh->length and always used - - BN_rand_range(priv_key, dh->p). - - BN_rand_range() is not necessary for Diffie-Hellman, and this - specific range makes Diffie-Hellman unnecessarily inefficient if - dh->length (recommended exponent length) is much smaller than the - length of dh->p. We could use BN_rand_range() if the order of - the subgroup was stored in the DH structure, but we only have - dh->length. - - So switch back to - - BN_rand(priv_key, l, ...) - - where 'l' is dh->length if this is defined, or BN_num_bits(dh->p)-1 - otherwise. - [Bodo Moeller] - - *) In - - RSA_eay_public_encrypt - RSA_eay_private_decrypt - RSA_eay_private_encrypt (signing) - RSA_eay_public_decrypt (signature verification) - - (default implementations for RSA_public_encrypt, - RSA_private_decrypt, RSA_private_encrypt, RSA_public_decrypt), - always reject numbers >= n. - [Bodo Moeller] - - *) In crypto/rand/md_rand.c, use a new short-time lock CRYPTO_LOCK_RAND2 - to synchronize access to 'locking_thread'. This is necessary on - systems where access to 'locking_thread' (an 'unsigned long' - variable) is not atomic. - [Bodo Moeller] - - *) In crypto/rand/md_rand.c, set 'locking_thread' to current thread's ID - *before* setting the 'crypto_lock_rand' flag. The previous code had - a race condition if 0 is a valid thread ID. - [Travis Vitek ] - - *) Add support for shared libraries under Irix. - [Albert Chin-A-Young ] - - *) Add configuration option to build on Linux on both big-endian and - little-endian MIPS. - [Ralf Baechle ] - - *) Add the possibility to create shared libraries on HP-UX. - [Richard Levitte] - - Changes between 0.9.6a and 0.9.6b [9 Jul 2001] - - *) Change ssleay_rand_bytes (crypto/rand/md_rand.c) - to avoid a SSLeay/OpenSSL PRNG weakness pointed out by - Markku-Juhani O. Saarinen : - PRNG state recovery was possible based on the output of - one PRNG request appropriately sized to gain knowledge on - 'md' followed by enough consecutive 1-byte PRNG requests - to traverse all of 'state'. - - 1. When updating 'md_local' (the current thread's copy of 'md') - during PRNG output generation, hash all of the previous - 'md_local' value, not just the half used for PRNG output. - - 2. Make the number of bytes from 'state' included into the hash - independent from the number of PRNG bytes requested. - - The first measure alone would be sufficient to avoid - Markku-Juhani's attack. (Actually it had never occurred - to me that the half of 'md_local' used for chaining was the - half from which PRNG output bytes were taken -- I had always - assumed that the secret half would be used.) The second - measure makes sure that additional data from 'state' is never - mixed into 'md_local' in small portions; this heuristically - further strengthens the PRNG. - [Bodo Moeller] - - *) Fix crypto/bn/asm/mips3.s. - [Andy Polyakov] - - *) When only the key is given to "enc", the IV is undefined. Print out - an error message in this case. - [Lutz Jaenicke] - - *) Handle special case when X509_NAME is empty in X509 printing routines. - [Steve Henson] - - *) In dsa_do_verify (crypto/dsa/dsa_ossl.c), verify that r and s are - positive and less than q. - [Bodo Moeller] - - *) Don't change *pointer in CRYPTO_add_lock() is add_lock_callback is - used: it isn't thread safe and the add_lock_callback should handle - that itself. - [Paul Rose ] - - *) Verify that incoming data obeys the block size in - ssl3_enc (ssl/s3_enc.c) and tls1_enc (ssl/t1_enc.c). - [Bodo Moeller] - - *) Fix OAEP check. - [Ulf Möller, Bodo Möller] - - *) The countermeasure against Bleichbacher's attack on PKCS #1 v1.5 - RSA encryption was accidentally removed in s3_srvr.c in OpenSSL 0.9.5 - when fixing the server behaviour for backwards-compatible 'client - hello' messages. (Note that the attack is impractical against - SSL 3.0 and TLS 1.0 anyway because length and version checking - means that the probability of guessing a valid ciphertext is - around 2^-40; see section 5 in Bleichenbacher's CRYPTO '98 - paper.) - - Before 0.9.5, the countermeasure (hide the error by generating a - random 'decryption result') did not work properly because - ERR_clear_error() was missing, meaning that SSL_get_error() would - detect the supposedly ignored error. - - Both problems are now fixed. - [Bodo Moeller] - - *) In crypto/bio/bf_buff.c, increase DEFAULT_BUFFER_SIZE to 4096 - (previously it was 1024). - [Bodo Moeller] - - *) Fix for compatibility mode trust settings: ignore trust settings - unless some valid trust or reject settings are present. - [Steve Henson] - - *) Fix for blowfish EVP: its a variable length cipher. - [Steve Henson] - - *) Fix various bugs related to DSA S/MIME verification. Handle missing - parameters in DSA public key structures and return an error in the - DSA routines if parameters are absent. - [Steve Henson] - - *) In versions up to 0.9.6, RAND_file_name() resorted to file ".rnd" - in the current directory if neither $RANDFILE nor $HOME was set. - RAND_file_name() in 0.9.6a returned NULL in this case. This has - caused some confusion to Windows users who haven't defined $HOME. - Thus RAND_file_name() is changed again: e_os.h can define a - DEFAULT_HOME, which will be used if $HOME is not set. - For Windows, we use "C:"; on other platforms, we still require - environment variables. - - *) Move 'if (!initialized) RAND_poll()' into regions protected by - CRYPTO_LOCK_RAND. This is not strictly necessary, but avoids - having multiple threads call RAND_poll() concurrently. - [Bodo Moeller] - - *) In crypto/rand/md_rand.c, replace 'add_do_not_lock' flag by a - combination of a flag and a thread ID variable. - Otherwise while one thread is in ssleay_rand_bytes (which sets the - flag), *other* threads can enter ssleay_add_bytes without obeying - the CRYPTO_LOCK_RAND lock (and may even illegally release the lock - that they do not hold after the first thread unsets add_do_not_lock). - [Bodo Moeller] - - *) Change bctest again: '-x' expressions are not available in all - versions of 'test'. - [Bodo Moeller] - - Changes between 0.9.6 and 0.9.6a [5 Apr 2001] - - *) Fix a couple of memory leaks in PKCS7_dataDecode() - [Steve Henson, reported by Heyun Zheng ] - - *) Change Configure and Makefiles to provide EXE_EXT, which will contain - the default extension for executables, if any. Also, make the perl - scripts that use symlink() to test if it really exists and use "cp" - if it doesn't. All this made OpenSSL compilable and installable in - CygWin. - [Richard Levitte] - - *) Fix for asn1_GetSequence() for indefinite length constructed data. - If SEQUENCE is length is indefinite just set c->slen to the total - amount of data available. - [Steve Henson, reported by shige@FreeBSD.org] - [This change does not apply to 0.9.7.] - - *) Change bctest to avoid here-documents inside command substitution - (workaround for FreeBSD /bin/sh bug). - For compatibility with Ultrix, avoid shell functions (introduced - in the bctest version that searches along $PATH). - [Bodo Moeller] - - *) Rename 'des_encrypt' to 'des_encrypt1'. This avoids the clashes - with des_encrypt() defined on some operating systems, like Solaris - and UnixWare. - [Richard Levitte] - - *) Check the result of RSA-CRT (see D. Boneh, R. DeMillo, R. Lipton: - On the Importance of Eliminating Errors in Cryptographic - Computations, J. Cryptology 14 (2001) 2, 101-119, - http://theory.stanford.edu/~dabo/papers/faults.ps.gz). - [Ulf Moeller] - - *) MIPS assembler BIGNUM division bug fix. - [Andy Polyakov] - - *) Disabled incorrect Alpha assembler code. - [Richard Levitte] - - *) Fix PKCS#7 decode routines so they correctly update the length - after reading an EOC for the EXPLICIT tag. - [Steve Henson] - [This change does not apply to 0.9.7.] - - *) Fix bug in PKCS#12 key generation routines. This was triggered - if a 3DES key was generated with a 0 initial byte. Include - PKCS12_BROKEN_KEYGEN compilation option to retain the old - (but broken) behaviour. - [Steve Henson] - - *) Enhance bctest to search for a working bc along $PATH and print - it when found. - [Tim Rice via Richard Levitte] - - *) Fix memory leaks in err.c: free err_data string if necessary; - don't write to the wrong index in ERR_set_error_data. - [Bodo Moeller] - - *) Implement ssl23_peek (analogous to ssl23_read), which previously - did not exist. - [Bodo Moeller] - - *) Replace rdtsc with _emit statements for VC++ version 5. - [Jeremy Cooper ] - - *) Make it possible to reuse SSLv2 sessions. - [Richard Levitte] - - *) In copy_email() check for >= 0 as a return value for - X509_NAME_get_index_by_NID() since 0 is a valid index. - [Steve Henson reported by Massimiliano Pala ] - - *) Avoid coredump with unsupported or invalid public keys by checking if - X509_get_pubkey() fails in PKCS7_verify(). Fix memory leak when - PKCS7_verify() fails with non detached data. - [Steve Henson] - - *) Don't use getenv in library functions when run as setuid/setgid. - New function OPENSSL_issetugid(). - [Ulf Moeller] - - *) Avoid false positives in memory leak detection code (crypto/mem_dbg.c) - due to incorrect handling of multi-threading: - - 1. Fix timing glitch in the MemCheck_off() portion of CRYPTO_mem_ctrl(). - - 2. Fix logical glitch in is_MemCheck_on() aka CRYPTO_is_mem_check_on(). - - 3. Count how many times MemCheck_off() has been called so that - nested use can be treated correctly. This also avoids - inband-signalling in the previous code (which relied on the - assumption that thread ID 0 is impossible). - [Bodo Moeller] - - *) Add "-rand" option also to s_client and s_server. - [Lutz Jaenicke] - - *) Fix CPU detection on Irix 6.x. - [Kurt Hockenbury and - "Bruce W. Forsberg" ] - - *) Fix X509_NAME bug which produced incorrect encoding if X509_NAME - was empty. - [Steve Henson] - [This change does not apply to 0.9.7.] - - *) Use the cached encoding of an X509_NAME structure rather than - copying it. This is apparently the reason for the libsafe "errors" - but the code is actually correct. - [Steve Henson] - - *) Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent - Bleichenbacher's DSA attack. - Extend BN_[pseudo_]rand: As before, top=1 forces the highest two bits - to be set and top=0 forces the highest bit to be set; top=-1 is new - and leaves the highest bit random. - [Ulf Moeller, Bodo Moeller] - - *) In the NCONF_...-based implementations for CONF_... queries - (crypto/conf/conf_lib.c), if the input LHASH is NULL, avoid using - a temporary CONF structure with the data component set to NULL - (which gives segmentation faults in lh_retrieve). - Instead, use NULL for the CONF pointer in CONF_get_string and - CONF_get_number (which may use environment variables) and directly - return NULL from CONF_get_section. - [Bodo Moeller] - - *) Fix potential buffer overrun for EBCDIC. - [Ulf Moeller] - - *) Tolerate nonRepudiation as being valid for S/MIME signing and certSign - keyUsage if basicConstraints absent for a CA. - [Steve Henson] - - *) Make SMIME_write_PKCS7() write mail header values with a format that - is more generally accepted (no spaces before the semicolon), since - some programs can't parse those values properly otherwise. Also make - sure BIO's that break lines after each write do not create invalid - headers. - [Richard Levitte] - - *) Make the CRL encoding routines work with empty SEQUENCE OF. The - macros previously used would not encode an empty SEQUENCE OF - and break the signature. - [Steve Henson] - [This change does not apply to 0.9.7.] - - *) Zero the premaster secret after deriving the master secret in - DH ciphersuites. - [Steve Henson] - - *) Add some EVP_add_digest_alias registrations (as found in - OpenSSL_add_all_digests()) to SSL_library_init() - aka OpenSSL_add_ssl_algorithms(). This provides improved - compatibility with peers using X.509 certificates - with unconventional AlgorithmIdentifier OIDs. - [Bodo Moeller] - - *) Fix for Irix with NO_ASM. - ["Bruce W. Forsberg" ] - - *) ./config script fixes. - [Ulf Moeller, Richard Levitte] - - *) Fix 'openssl passwd -1'. - [Bodo Moeller] - - *) Change PKCS12_key_gen_asc() so it can cope with non null - terminated strings whose length is passed in the passlen - parameter, for example from PEM callbacks. This was done - by adding an extra length parameter to asc2uni(). - [Steve Henson, reported by ] - - *) Fix C code generated by 'openssl dsaparam -C': If a BN_bin2bn - call failed, free the DSA structure. - [Bodo Moeller] - - *) Fix to uni2asc() to cope with zero length Unicode strings. - These are present in some PKCS#12 files. - [Steve Henson] - - *) Increase s2->wbuf allocation by one byte in ssl2_new (ssl/s2_lib.c). - Otherwise do_ssl_write (ssl/s2_pkt.c) will write beyond buffer limits - when writing a 32767 byte record. - [Bodo Moeller; problem reported by Eric Day ] - - *) In RSA_eay_public_{en,ed}crypt and RSA_eay_mod_exp (rsa_eay.c), - obtain lock CRYPTO_LOCK_RSA before setting rsa->_method_mod_{n,p,q}. - - (RSA objects have a reference count access to which is protected - by CRYPTO_LOCK_RSA [see rsa_lib.c, s3_srvr.c, ssl_cert.c, ssl_rsa.c], - so they are meant to be shared between threads.) - [Bodo Moeller, Geoff Thorpe; original patch submitted by - "Reddie, Steven" ] - - *) Fix a deadlock in CRYPTO_mem_leaks(). - [Bodo Moeller] - - *) Use better test patterns in bntest. - [Ulf Möller] - - *) rand_win.c fix for Borland C. - [Ulf Möller] - - *) BN_rshift bugfix for n == 0. - [Bodo Moeller] - - *) Add a 'bctest' script that checks for some known 'bc' bugs - so that 'make test' does not abort just because 'bc' is broken. - [Bodo Moeller] - - *) Store verify_result within SSL_SESSION also for client side to - avoid potential security hole. (Re-used sessions on the client side - always resulted in verify_result==X509_V_OK, not using the original - result of the server certificate verification.) - [Lutz Jaenicke] - - *) Fix ssl3_pending: If the record in s->s3->rrec is not of type - SSL3_RT_APPLICATION_DATA, return 0. - Similarly, change ssl2_pending to return 0 if SSL_in_init(s) is true. - [Bodo Moeller] - - *) Fix SSL_peek: - Both ssl2_peek and ssl3_peek, which were totally broken in earlier - releases, have been re-implemented by renaming the previous - implementations of ssl2_read and ssl3_read to ssl2_read_internal - and ssl3_read_internal, respectively, and adding 'peek' parameters - to them. The new ssl[23]_{read,peek} functions are calls to - ssl[23]_read_internal with the 'peek' flag set appropriately. - A 'peek' parameter has also been added to ssl3_read_bytes, which - does the actual work for ssl3_read_internal. - [Bodo Moeller] - - *) Initialise "ex_data" member of RSA/DSA/DH structures prior to calling - the method-specific "init()" handler. Also clean up ex_data after - calling the method-specific "finish()" handler. Previously, this was - happening the other way round. - [Geoff Thorpe] - - *) Increase BN_CTX_NUM (the number of BIGNUMs in a BN_CTX) to 16. - The previous value, 12, was not always sufficient for BN_mod_exp(). - [Bodo Moeller] - - *) Make sure that shared libraries get the internal name engine with - the full version number and not just 0. This should mark the - shared libraries as not backward compatible. Of course, this should - be changed again when we can guarantee backward binary compatibility. - [Richard Levitte] - - *) Fix typo in get_cert_by_subject() in by_dir.c - [Jean-Marc Desperrier ] - - *) Rework the system to generate shared libraries: - - - Make note of the expected extension for the shared libraries and - if there is a need for symbolic links from for example libcrypto.so.0 - to libcrypto.so.0.9.7. There is extended info in Configure for - that. - - - Make as few rebuilds of the shared libraries as possible. - - - Still avoid linking the OpenSSL programs with the shared libraries. - - - When installing, install the shared libraries separately from the - static ones. - [Richard Levitte] - - *) Fix SSL_CTX_set_read_ahead macro to actually use its argument. - - Copy SSL_CTX's read_ahead flag to SSL object directly in SSL_new - and not in SSL_clear because the latter is also used by the - accept/connect functions; previously, the settings made by - SSL_set_read_ahead would be lost during the handshake. - [Bodo Moeller; problems reported by Anders Gertz ] - - *) Correct util/mkdef.pl to be selective about disabled algorithms. - Previously, it would create entries for disabled algorithms no - matter what. - [Richard Levitte] - - *) Added several new manual pages for SSL_* function. - [Lutz Jaenicke] - - Changes between 0.9.5a and 0.9.6 [24 Sep 2000] - - *) In ssl23_get_client_hello, generate an error message when faced - with an initial SSL 3.0/TLS record that is too small to contain the - first two bytes of the ClientHello message, i.e. client_version. - (Note that this is a pathologic case that probably has never happened - in real life.) The previous approach was to use the version number - from the record header as a substitute; but our protocol choice - should not depend on that one because it is not authenticated - by the Finished messages. - [Bodo Moeller] - - *) More robust randomness gathering functions for Windows. - [Jeffrey Altman ] - - *) For compatibility reasons if the flag X509_V_FLAG_ISSUER_CHECK is - not set then we don't setup the error code for issuer check errors - to avoid possibly overwriting other errors which the callback does - handle. If an application does set the flag then we assume it knows - what it is doing and can handle the new informational codes - appropriately. - [Steve Henson] - - *) Fix for a nasty bug in ASN1_TYPE handling. ASN1_TYPE is used for - a general "ANY" type, as such it should be able to decode anything - including tagged types. However it didn't check the class so it would - wrongly interpret tagged types in the same way as their universal - counterpart and unknown types were just rejected. Changed so that the - tagged and unknown types are handled in the same way as a SEQUENCE: - that is the encoding is stored intact. There is also a new type - "V_ASN1_OTHER" which is used when the class is not universal, in this - case we have no idea what the actual type is so we just lump them all - together. - [Steve Henson] - - *) On VMS, stdout may very well lead to a file that is written to - in a record-oriented fashion. That means that every write() will - write a separate record, which will be read separately by the - programs trying to read from it. This can be very confusing. - - The solution is to put a BIO filter in the way that will buffer - text until a linefeed is reached, and then write everything a - line at a time, so every record written will be an actual line, - not chunks of lines and not (usually doesn't happen, but I've - seen it once) several lines in one record. BIO_f_linebuffer() is - the answer. - - Currently, it's a VMS-only method, because that's where it has - been tested well enough. - [Richard Levitte] - - *) Remove 'optimized' squaring variant in BN_mod_mul_montgomery, - it can return incorrect results. - (Note: The buggy variant was not enabled in OpenSSL 0.9.5a, - but it was in 0.9.6-beta[12].) - [Bodo Moeller] - - *) Disable the check for content being present when verifying detached - signatures in pk7_smime.c. Some versions of Netscape (wrongly) - include zero length content when signing messages. - [Steve Henson] - - *) New BIO_shutdown_wr macro, which invokes the BIO_C_SHUTDOWN_WR - BIO_ctrl (for BIO pairs). - [Bodo Möller] - - *) Add DSO method for VMS. - [Richard Levitte] - - *) Bug fix: Montgomery multiplication could produce results with the - wrong sign. - [Ulf Möller] - - *) Add RPM specification openssl.spec and modify it to build three - packages. The default package contains applications, application - documentation and run-time libraries. The devel package contains - include files, static libraries and function documentation. The - doc package contains the contents of the doc directory. The original - openssl.spec was provided by Damien Miller . - [Richard Levitte] - - *) Add a large number of documentation files for many SSL routines. - [Lutz Jaenicke ] - - *) Add a configuration entry for Sony News 4. - [NAKAJI Hiroyuki ] - - *) Don't set the two most significant bits to one when generating a - random number < q in the DSA library. - [Ulf Möller] - - *) New SSL API mode 'SSL_MODE_AUTO_RETRY'. This disables the default - behaviour that SSL_read may result in SSL_ERROR_WANT_READ (even if - the underlying transport is blocking) if a handshake took place. - (The default behaviour is needed by applications such as s_client - and s_server that use select() to determine when to use SSL_read; - but for applications that know in advance when to expect data, it - just makes things more complicated.) - [Bodo Moeller] - - *) Add RAND_egd_bytes(), which gives control over the number of bytes read - from EGD. - [Ben Laurie] - - *) Add a few more EBCDIC conditionals that make `req' and `x509' - work better on such systems. - [Martin Kraemer ] - - *) Add two demo programs for PKCS12_parse() and PKCS12_create(). - Update PKCS12_parse() so it copies the friendlyName and the - keyid to the certificates aux info. - [Steve Henson] - - *) Fix bug in PKCS7_verify() which caused an infinite loop - if there was more than one signature. - [Sven Uszpelkat ] - - *) Major change in util/mkdef.pl to include extra information - about each symbol, as well as presenting variables as well - as functions. This change means that there's n more need - to rebuild the .num files when some algorithms are excluded. - [Richard Levitte] - - *) Allow the verify time to be set by an application, - rather than always using the current time. - [Steve Henson] - - *) Phase 2 verify code reorganisation. The certificate - verify code now looks up an issuer certificate by a - number of criteria: subject name, authority key id - and key usage. It also verifies self signed certificates - by the same criteria. The main comparison function is - X509_check_issued() which performs these checks. - - Lot of changes were necessary in order to support this - without completely rewriting the lookup code. - - Authority and subject key identifier are now cached. - - The LHASH 'certs' is X509_STORE has now been replaced - by a STACK_OF(X509_OBJECT). This is mainly because an - LHASH can't store or retrieve multiple objects with - the same hash value. - - As a result various functions (which were all internal - use only) have changed to handle the new X509_STORE - structure. This will break anything that messed round - with X509_STORE internally. - - The functions X509_STORE_add_cert() now checks for an - exact match, rather than just subject name. - - The X509_STORE API doesn't directly support the retrieval - of multiple certificates matching a given criteria, however - this can be worked round by performing a lookup first - (which will fill the cache with candidate certificates) - and then examining the cache for matches. This is probably - the best we can do without throwing out X509_LOOKUP - entirely (maybe later...). - - The X509_VERIFY_CTX structure has been enhanced considerably. - - All certificate lookup operations now go via a get_issuer() - callback. Although this currently uses an X509_STORE it - can be replaced by custom lookups. This is a simple way - to bypass the X509_STORE hackery necessary to make this - work and makes it possible to use more efficient techniques - in future. A very simple version which uses a simple - STACK for its trusted certificate store is also provided - using X509_STORE_CTX_trusted_stack(). - - The verify_cb() and verify() callbacks now have equivalents - in the X509_STORE_CTX structure. - - X509_STORE_CTX also has a 'flags' field which can be used - to customise the verify behaviour. - [Steve Henson] - - *) Add new PKCS#7 signing option PKCS7_NOSMIMECAP which - excludes S/MIME capabilities. - [Steve Henson] - - *) When a certificate request is read in keep a copy of the - original encoding of the signed data and use it when outputting - again. Signatures then use the original encoding rather than - a decoded, encoded version which may cause problems if the - request is improperly encoded. - [Steve Henson] - - *) For consistency with other BIO_puts implementations, call - buffer_write(b, ...) directly in buffer_puts instead of calling - BIO_write(b, ...). - - In BIO_puts, increment b->num_write as in BIO_write. - [Peter.Sylvester@EdelWeb.fr] - - *) Fix BN_mul_word for the case where the word is 0. (We have to use - BN_zero, we may not return a BIGNUM with an array consisting of - words set to zero.) - [Bodo Moeller] - - *) Avoid calling abort() from within the library when problems are - detected, except if preprocessor symbols have been defined - (such as REF_CHECK, BN_DEBUG etc.). - [Bodo Moeller] - - *) New openssl application 'rsautl'. This utility can be - used for low level RSA operations. DER public key - BIO/fp routines also added. - [Steve Henson] - - *) New Configure entry and patches for compiling on QNX 4. - [Andreas Schneider ] - - *) A demo state-machine implementation was sponsored by - Nuron (http://www.nuron.com/) and is now available in - demos/state_machine. - [Ben Laurie] - - *) New options added to the 'dgst' utility for signature - generation and verification. - [Steve Henson] - - *) Unrecognized PKCS#7 content types are now handled via a - catch all ASN1_TYPE structure. This allows unsupported - types to be stored as a "blob" and an application can - encode and decode it manually. - [Steve Henson] - - *) Fix various signed/unsigned issues to make a_strex.c - compile under VC++. - [Oscar Jacobsson ] - - *) ASN1 fixes. i2d_ASN1_OBJECT was not returning the correct - length if passed a buffer. ASN1_INTEGER_to_BN failed - if passed a NULL BN and its argument was negative. - [Steve Henson, pointed out by Sven Heiberg ] - - *) Modification to PKCS#7 encoding routines to output definite - length encoding. Since currently the whole structures are in - memory there's not real point in using indefinite length - constructed encoding. However if OpenSSL is compiled with - the flag PKCS7_INDEFINITE_ENCODING the old form is used. - [Steve Henson] - - *) Added BIO_vprintf() and BIO_vsnprintf(). - [Richard Levitte] - - *) Added more prefixes to parse for in the strings written - through a logging bio, to cover all the levels that are available - through syslog. The prefixes are now: - - PANIC, EMERG, EMR => LOG_EMERG - ALERT, ALR => LOG_ALERT - CRIT, CRI => LOG_CRIT - ERROR, ERR => LOG_ERR - WARNING, WARN, WAR => LOG_WARNING - NOTICE, NOTE, NOT => LOG_NOTICE - INFO, INF => LOG_INFO - DEBUG, DBG => LOG_DEBUG - - and as before, if none of those prefixes are present at the - beginning of the string, LOG_ERR is chosen. - - On Win32, the LOG_* levels are mapped according to this: - - LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR => EVENTLOG_ERROR_TYPE - LOG_WARNING => EVENTLOG_WARNING_TYPE - LOG_NOTICE, LOG_INFO, LOG_DEBUG => EVENTLOG_INFORMATION_TYPE - - [Richard Levitte] - - *) Made it possible to reconfigure with just the configuration - argument "reconf" or "reconfigure". The command line arguments - are stored in Makefile.ssl in the variable CONFIGURE_ARGS, - and are retrieved from there when reconfiguring. - [Richard Levitte] - - *) MD4 implemented. - [Assar Westerlund , Richard Levitte] - - *) Add the arguments -CAfile and -CApath to the pkcs12 utility. - [Richard Levitte] - - *) The obj_dat.pl script was messing up the sorting of object - names. The reason was that it compared the quoted version - of strings as a result "OCSP" > "OCSP Signing" because - " > SPACE. Changed script to store unquoted versions of - names and add quotes on output. It was also omitting some - names from the lookup table if they were given a default - value (that is if SN is missing it is given the same - value as LN and vice versa), these are now added on the - grounds that if an object has a name we should be able to - look it up. Finally added warning output when duplicate - short or long names are found. - [Steve Henson] - - *) Changes needed for Tandem NSK. - [Scott Uroff ] - - *) Fix SSL 2.0 rollback checking: Due to an off-by-one error in - RSA_padding_check_SSLv23(), special padding was never detected - and thus the SSL 3.0/TLS 1.0 countermeasure against protocol - version rollback attacks was not effective. - - In s23_clnt.c, don't use special rollback-attack detection padding - (RSA_SSLV23_PADDING) if SSL 2.0 is the only protocol enabled in the - client; similarly, in s23_srvr.c, don't do the rollback check if - SSL 2.0 is the only protocol enabled in the server. - [Bodo Moeller] - - *) Make it possible to get hexdumps of unprintable data with 'openssl - asn1parse'. By implication, the functions ASN1_parse_dump() and - BIO_dump_indent() are added. - [Richard Levitte] - - *) New functions ASN1_STRING_print_ex() and X509_NAME_print_ex() - these print out strings and name structures based on various - flags including RFC2253 support and proper handling of - multibyte characters. Added options to the 'x509' utility - to allow the various flags to be set. - [Steve Henson] - - *) Various fixes to use ASN1_TIME instead of ASN1_UTCTIME. - Also change the functions X509_cmp_current_time() and - X509_gmtime_adj() work with an ASN1_TIME structure, - this will enable certificates using GeneralizedTime in validity - dates to be checked. - [Steve Henson] - - *) Make the NEG_PUBKEY_BUG code (which tolerates invalid - negative public key encodings) on by default, - NO_NEG_PUBKEY_BUG can be set to disable it. - [Steve Henson] - - *) New function c2i_ASN1_OBJECT() which acts on ASN1_OBJECT - content octets. An i2c_ASN1_OBJECT is unnecessary because - the encoding can be trivially obtained from the structure. - [Steve Henson] - - *) crypto/err.c locking bugfix: Use write locks (CRYPTO_w_[un]lock), - not read locks (CRYPTO_r_[un]lock). - [Bodo Moeller] - - *) A first attempt at creating official support for shared - libraries through configuration. I've kept it so the - default is static libraries only, and the OpenSSL programs - are always statically linked for now, but there are - preparations for dynamic linking in place. - This has been tested on Linux and Tru64. - [Richard Levitte] - - *) Randomness polling function for Win9x, as described in: - Peter Gutmann, Software Generation of Practically Strong - Random Numbers. - [Ulf Möller] - - *) Fix so PRNG is seeded in req if using an already existing - DSA key. - [Steve Henson] - - *) New options to smime application. -inform and -outform - allow alternative formats for the S/MIME message including - PEM and DER. The -content option allows the content to be - specified separately. This should allow things like Netscape - form signing output easier to verify. - [Steve Henson] - - *) Fix the ASN1 encoding of tags using the 'long form'. - [Steve Henson] - - *) New ASN1 functions, i2c_* and c2i_* for INTEGER and BIT - STRING types. These convert content octets to and from the - underlying type. The actual tag and length octets are - already assumed to have been read in and checked. These - are needed because all other string types have virtually - identical handling apart from the tag. By having versions - of the ASN1 functions that just operate on content octets - IMPLICIT tagging can be handled properly. It also allows - the ASN1_ENUMERATED code to be cut down because ASN1_ENUMERATED - and ASN1_INTEGER are identical apart from the tag. - [Steve Henson] - - *) Change the handling of OID objects as follows: - - - New object identifiers are inserted in objects.txt, following - the syntax given in objects.README. - - objects.pl is used to process obj_mac.num and create a new - obj_mac.h. - - obj_dat.pl is used to create a new obj_dat.h, using the data in - obj_mac.h. - - This is currently kind of a hack, and the perl code in objects.pl - isn't very elegant, but it works as I intended. The simplest way - to check that it worked correctly is to look in obj_dat.h and - check the array nid_objs and make sure the objects haven't moved - around (this is important!). Additions are OK, as well as - consistent name changes. - [Richard Levitte] - - *) Add BSD-style MD5-based passwords to 'openssl passwd' (option '-1'). - [Bodo Moeller] - - *) Addition of the command line parameter '-rand file' to 'openssl req'. - The given file adds to whatever has already been seeded into the - random pool through the RANDFILE configuration file option or - environment variable, or the default random state file. - [Richard Levitte] - - *) mkstack.pl now sorts each macro group into lexical order. - Previously the output order depended on the order the files - appeared in the directory, resulting in needless rewriting - of safestack.h . - [Steve Henson] - - *) Patches to make OpenSSL compile under Win32 again. Mostly - work arounds for the VC++ problem that it treats func() as - func(void). Also stripped out the parts of mkdef.pl that - added extra typesafe functions: these no longer exist. - [Steve Henson] - - *) Reorganisation of the stack code. The macros are now all - collected in safestack.h . Each macro is defined in terms of - a "stack macro" of the form SKM_(type, a, b). The - DEBUG_SAFESTACK is now handled in terms of function casts, - this has the advantage of retaining type safety without the - use of additional functions. If DEBUG_SAFESTACK is not defined - then the non typesafe macros are used instead. Also modified the - mkstack.pl script to handle the new form. Needs testing to see - if which (if any) compilers it chokes and maybe make DEBUG_SAFESTACK - the default if no major problems. Similar behaviour for ASN1_SET_OF - and PKCS12_STACK_OF. - [Steve Henson] - - *) When some versions of IIS use the 'NET' form of private key the - key derivation algorithm is different. Normally MD5(password) is - used as a 128 bit RC4 key. In the modified case - MD5(MD5(password) + "SGCKEYSALT") is used instead. Added some - new functions i2d_RSA_NET(), d2i_RSA_NET() etc which are the same - as the old Netscape_RSA functions except they have an additional - 'sgckey' parameter which uses the modified algorithm. Also added - an -sgckey command line option to the rsa utility. Thanks to - Adrian Peck for posting details of the modified - algorithm to openssl-dev. - [Steve Henson] - - *) The evp_local.h macros were using 'c.##kname' which resulted in - invalid expansion on some systems (SCO 5.0.5 for example). - Corrected to 'c.kname'. - [Phillip Porch ] - - *) New X509_get1_email() and X509_REQ_get1_email() functions that return - a STACK of email addresses from a certificate or request, these look - in the subject name and the subject alternative name extensions and - omit any duplicate addresses. - [Steve Henson] - - *) Re-implement BN_mod_exp2_mont using independent (and larger) windows. - This makes DSA verification about 2 % faster. - [Bodo Moeller] - - *) Increase maximum window size in BN_mod_exp_... to 6 bits instead of 5 - (meaning that now 2^5 values will be precomputed, which is only 4 KB - plus overhead for 1024 bit moduli). - This makes exponentiations about 0.5 % faster for 1024 bit - exponents (as measured by "openssl speed rsa2048"). - [Bodo Moeller] - - *) Rename memory handling macros to avoid conflicts with other - software: - Malloc => OPENSSL_malloc - Malloc_locked => OPENSSL_malloc_locked - Realloc => OPENSSL_realloc - Free => OPENSSL_free - [Richard Levitte] - - *) New function BN_mod_exp_mont_word for small bases (roughly 15% - faster than BN_mod_exp_mont, i.e. 7% for a full DH exchange). - [Bodo Moeller] - - *) CygWin32 support. - [John Jarvie ] - - *) The type-safe stack code has been rejigged. It is now only compiled - in when OpenSSL is configured with the DEBUG_SAFESTACK option and - by default all type-specific stack functions are "#define"d back to - standard stack functions. This results in more streamlined output - but retains the type-safety checking possibilities of the original - approach. - [Geoff Thorpe] - - *) The STACK code has been cleaned up, and certain type declarations - that didn't make a lot of sense have been brought in line. This has - also involved a cleanup of sorts in safestack.h to more correctly - map type-safe stack functions onto their plain stack counterparts. - This work has also resulted in a variety of "const"ifications of - lots of the code, especially "_cmp" operations which should normally - be prototyped with "const" parameters anyway. - [Geoff Thorpe] - - *) When generating bytes for the first time in md_rand.c, 'stir the pool' - by seeding with STATE_SIZE dummy bytes (with zero entropy count). - (The PRNG state consists of two parts, the large pool 'state' and 'md', - where all of 'md' is used each time the PRNG is used, but 'state' - is used only indexed by a cyclic counter. As entropy may not be - well distributed from the beginning, 'md' is important as a - chaining variable. However, the output function chains only half - of 'md', i.e. 80 bits. ssleay_rand_add, on the other hand, chains - all of 'md', and seeding with STATE_SIZE dummy bytes will result - in all of 'state' being rewritten, with the new values depending - on virtually all of 'md'. This overcomes the 80 bit limitation.) - [Bodo Moeller] - - *) In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when - the handshake is continued after ssl_verify_cert_chain(); - otherwise, if SSL_VERIFY_NONE is set, remaining error codes - can lead to 'unexplainable' connection aborts later. - [Bodo Moeller; problem tracked down by Lutz Jaenicke] - - *) Major EVP API cipher revision. - Add hooks for extra EVP features. This allows various cipher - parameters to be set in the EVP interface. Support added for variable - key length ciphers via the EVP_CIPHER_CTX_set_key_length() function and - setting of RC2 and RC5 parameters. - - Modify EVP_OpenInit() and EVP_SealInit() to cope with variable key length - ciphers. - - Remove lots of duplicated code from the EVP library. For example *every* - cipher init() function handles the 'iv' in the same way according to the - cipher mode. They also all do nothing if the 'key' parameter is NULL and - for CFB and OFB modes they zero ctx->num. - - New functionality allows removal of S/MIME code RC2 hack. - - Most of the routines have the same form and so can be declared in terms - of macros. - - By shifting this to the top level EVP_CipherInit() it can be removed from - all individual ciphers. If the cipher wants to handle IVs or keys - differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT - flags. - - Change lots of functions like EVP_EncryptUpdate() to now return a - value: although software versions of the algorithms cannot fail - any installed hardware versions can. - [Steve Henson] - - *) Implement SSL_OP_TLS_ROLLBACK_BUG: In ssl3_get_client_key_exchange, if - this option is set, tolerate broken clients that send the negotiated - protocol version number instead of the requested protocol version - number. - [Bodo Moeller] - - *) Call dh_tmp_cb (set by ..._TMP_DH_CB) with correct 'is_export' flag; - i.e. non-zero for export ciphersuites, zero otherwise. - Previous versions had this flag inverted, inconsistent with - rsa_tmp_cb (..._TMP_RSA_CB). - [Bodo Moeller; problem reported by Amit Chopra] - - *) Add missing DSA library text string. Work around for some IIS - key files with invalid SEQUENCE encoding. - [Steve Henson] - - *) Add a document (doc/standards.txt) that list all kinds of standards - and so on that are implemented in OpenSSL. - [Richard Levitte] - - *) Enhance c_rehash script. Old version would mishandle certificates - with the same subject name hash and wouldn't handle CRLs at all. - Added -fingerprint option to crl utility, to support new c_rehash - features. - [Steve Henson] - - *) Eliminate non-ANSI declarations in crypto.h and stack.h. - [Ulf Möller] - - *) Fix for SSL server purpose checking. Server checking was - rejecting certificates which had extended key usage present - but no ssl client purpose. - [Steve Henson, reported by Rene Grosser ] - - *) Make PKCS#12 code work with no password. The PKCS#12 spec - is a little unclear about how a blank password is handled. - Since the password in encoded as a BMPString with terminating - double NULL a zero length password would end up as just the - double NULL. However no password at all is different and is - handled differently in the PKCS#12 key generation code. NS - treats a blank password as zero length. MSIE treats it as no - password on export: but it will try both on import. We now do - the same: PKCS12_parse() tries zero length and no password if - the password is set to "" or NULL (NULL is now a valid password: - it wasn't before) as does the pkcs12 application. - [Steve Henson] - - *) Bugfixes in apps/x509.c: Avoid a memory leak; and don't use - perror when PEM_read_bio_X509_REQ fails, the error message must - be obtained from the error queue. - [Bodo Moeller] - - *) Avoid 'thread_hash' memory leak in crypto/err/err.c by freeing - it in ERR_remove_state if appropriate, and change ERR_get_state - accordingly to avoid race conditions (this is necessary because - thread_hash is no longer constant once set). - [Bodo Moeller] - - *) Bugfix for linux-elf makefile.one. - [Ulf Möller] - - *) RSA_get_default_method() will now cause a default - RSA_METHOD to be chosen if one doesn't exist already. - Previously this was only set during a call to RSA_new() - or RSA_new_method(NULL) meaning it was possible for - RSA_get_default_method() to return NULL. - [Geoff Thorpe] - - *) Added native name translation to the existing DSO code - that will convert (if the flag to do so is set) filenames - that are sufficiently small and have no path information - into a canonical native form. Eg. "blah" converted to - "libblah.so" or "blah.dll" etc. - [Geoff Thorpe] - - *) New function ERR_error_string_n(e, buf, len) which is like - ERR_error_string(e, buf), but writes at most 'len' bytes - including the 0 terminator. For ERR_error_string_n, 'buf' - may not be NULL. - [Damien Miller , Bodo Moeller] - - *) CONF library reworked to become more general. A new CONF - configuration file reader "class" is implemented as well as a - new functions (NCONF_*, for "New CONF") to handle it. The now - old CONF_* functions are still there, but are reimplemented to - work in terms of the new functions. Also, a set of functions - to handle the internal storage of the configuration data is - provided to make it easier to write new configuration file - reader "classes" (I can definitely see something reading a - configuration file in XML format, for example), called _CONF_*, - or "the configuration storage API"... - - The new configuration file reading functions are: - - NCONF_new, NCONF_free, NCONF_load, NCONF_load_fp, NCONF_load_bio, - NCONF_get_section, NCONF_get_string, NCONF_get_numbre - - NCONF_default, NCONF_WIN32 - - NCONF_dump_fp, NCONF_dump_bio - - NCONF_default and NCONF_WIN32 are method (or "class") choosers, - NCONF_new creates a new CONF object. This works in the same way - as other interfaces in OpenSSL, like the BIO interface. - NCONF_dump_* dump the internal storage of the configuration file, - which is useful for debugging. All other functions take the same - arguments as the old CONF_* functions with the exception of the - first that must be a `CONF *' instead of a `LHASH *'. - - To make it easier to use the new classes with the old CONF_* functions, - the function CONF_set_default_method is provided. - [Richard Levitte] - - *) Add '-tls1' option to 'openssl ciphers', which was already - mentioned in the documentation but had not been implemented. - (This option is not yet really useful because even the additional - experimental TLS 1.0 ciphers are currently treated as SSL 3.0 ciphers.) - [Bodo Moeller] - - *) Initial DSO code added into libcrypto for letting OpenSSL (and - OpenSSL-based applications) load shared libraries and bind to - them in a portable way. - [Geoff Thorpe, with contributions from Richard Levitte] - - Changes between 0.9.5 and 0.9.5a [1 Apr 2000] - - *) Make sure _lrotl and _lrotr are only used with MSVC. - - *) Use lock CRYPTO_LOCK_RAND correctly in ssleay_rand_status - (the default implementation of RAND_status). - - *) Rename openssl x509 option '-crlext', which was added in 0.9.5, - to '-clrext' (= clear extensions), as intended and documented. - [Bodo Moeller; inconsistency pointed out by Michael Attili - ] - - *) Fix for HMAC. It wasn't zeroing the rest of the block if the key length - was larger than the MD block size. - [Steve Henson, pointed out by Yost William ] - - *) Modernise PKCS12_parse() so it uses STACK_OF(X509) for its ca argument - fix a leak when the ca argument was passed as NULL. Stop X509_PUBKEY_set() - using the passed key: if the passed key was a private key the result - of X509_print(), for example, would be to print out all the private key - components. - [Steve Henson] - - *) des_quad_cksum() byte order bug fix. - [Ulf Möller, using the problem description in krb4-0.9.7, where - the solution is attributed to Derrick J Brashear ] - - *) Fix so V_ASN1_APP_CHOOSE works again: however its use is strongly - discouraged. - [Steve Henson, pointed out by Brian Korver ] - - *) For easily testing in shell scripts whether some command - 'openssl XXX' exists, the new pseudo-command 'openssl no-XXX' - returns with exit code 0 iff no command of the given name is available. - 'no-XXX' is printed in this case, 'XXX' otherwise. In both cases, - the output goes to stdout and nothing is printed to stderr. - Additional arguments are always ignored. - - Since for each cipher there is a command of the same name, - the 'no-cipher' compilation switches can be tested this way. - - ('openssl no-XXX' is not able to detect pseudo-commands such - as 'quit', 'list-XXX-commands', or 'no-XXX' itself.) - [Bodo Moeller] - - *) Update test suite so that 'make test' succeeds in 'no-rsa' configuration. - [Bodo Moeller] - - *) For SSL_[CTX_]set_tmp_dh, don't create a DH key if SSL_OP_SINGLE_DH_USE - is set; it will be thrown away anyway because each handshake creates - its own key. - ssl_cert_dup, which is used by SSL_new, now copies DH keys in addition - to parameters -- in previous versions (since OpenSSL 0.9.3) the - 'default key' from SSL_CTX_set_tmp_dh would always be lost, meaning - you effectively got SSL_OP_SINGLE_DH_USE when using this macro. - [Bodo Moeller] - - *) New s_client option -ign_eof: EOF at stdin is ignored, and - 'Q' and 'R' lose their special meanings (quit/renegotiate). - This is part of what -quiet does; unlike -quiet, -ign_eof - does not suppress any output. - [Richard Levitte] - - *) Add compatibility options to the purpose and trust code. The - purpose X509_PURPOSE_ANY is "any purpose" which automatically - accepts a certificate or CA, this was the previous behaviour, - with all the associated security issues. - - X509_TRUST_COMPAT is the old trust behaviour: only and - automatically trust self signed roots in certificate store. A - new trust setting X509_TRUST_DEFAULT is used to specify that - a purpose has no associated trust setting and it should instead - use the value in the default purpose. - [Steve Henson] - - *) Fix the PKCS#8 DSA private key code so it decodes keys again - and fix a memory leak. - [Steve Henson] - - *) In util/mkerr.pl (which implements 'make errors'), preserve - reason strings from the previous version of the .c file, as - the default to have only downcase letters (and digits) in - automatically generated reasons codes is not always appropriate. - [Bodo Moeller] - - *) In ERR_load_ERR_strings(), build an ERR_LIB_SYS error reason table - using strerror. Previously, ERR_reason_error_string() returned - library names as reason strings for SYSerr; but SYSerr is a special - case where small numbers are errno values, not library numbers. - [Bodo Moeller] - - *) Add '-dsaparam' option to 'openssl dhparam' application. This - converts DSA parameters into DH parameters. (When creating parameters, - DSA_generate_parameters is used.) - [Bodo Moeller] - - *) Include 'length' (recommended exponent length) in C code generated - by 'openssl dhparam -C'. - [Bodo Moeller] - - *) The second argument to set_label in perlasm was already being used - so couldn't be used as a "file scope" flag. Moved to third argument - which was free. - [Steve Henson] - - *) In PEM_ASN1_write_bio and some other functions, use RAND_pseudo_bytes - instead of RAND_bytes for encryption IVs and salts. - [Bodo Moeller] - - *) Include RAND_status() into RAND_METHOD instead of implementing - it only for md_rand.c Otherwise replacing the PRNG by calling - RAND_set_rand_method would be impossible. - [Bodo Moeller] - - *) Don't let DSA_generate_key() enter an infinite loop if the random - number generation fails. - [Bodo Moeller] - - *) New 'rand' application for creating pseudo-random output. - [Bodo Moeller] - - *) Added configuration support for Linux/IA64 - [Rolf Haberrecker ] - - *) Assembler module support for Mingw32. - [Ulf Möller] - - *) Shared library support for HPUX (in shlib/). - [Lutz Jaenicke and Anonymous] - - *) Shared library support for Solaris gcc. - [Lutz Behnke ] - - Changes between 0.9.4 and 0.9.5 [28 Feb 2000] - - *) PKCS7_encrypt() was adding text MIME headers twice because they - were added manually and by SMIME_crlf_copy(). - [Steve Henson] - - *) In bntest.c don't call BN_rand with zero bits argument. - [Steve Henson, pointed out by Andrew W. Gray ] - - *) BN_mul bugfix: In bn_mul_part_recursion() only the a>a[n] && b>b[n] - case was implemented. This caused BN_div_recp() to fail occasionally. - [Ulf Möller] - - *) Add an optional second argument to the set_label() in the perl - assembly language builder. If this argument exists and is set - to 1 it signals that the assembler should use a symbol whose - scope is the entire file, not just the current function. This - is needed with MASM which uses the format label:: for this scope. - [Steve Henson, pointed out by Peter Runestig ] - - *) Change the ASN1 types so they are typedefs by default. Before - almost all types were #define'd to ASN1_STRING which was causing - STACK_OF() problems: you couldn't declare STACK_OF(ASN1_UTF8STRING) - for example. - [Steve Henson] - - *) Change names of new functions to the new get1/get0 naming - convention: After 'get1', the caller owns a reference count - and has to call ..._free; 'get0' returns a pointer to some - data structure without incrementing reference counters. - (Some of the existing 'get' functions increment a reference - counter, some don't.) - Similarly, 'set1' and 'add1' functions increase reference - counters or duplicate objects. - [Steve Henson] - - *) Allow for the possibility of temp RSA key generation failure: - the code used to assume it always worked and crashed on failure. - [Steve Henson] - - *) Fix potential buffer overrun problem in BIO_printf(). - [Ulf Möller, using public domain code by Patrick Powell; problem - pointed out by David Sacerdote ] - - *) Support EGD . New functions - RAND_egd() and RAND_status(). In the command line application, - the EGD socket can be specified like a seed file using RANDFILE - or -rand. - [Ulf Möller] - - *) Allow the string CERTIFICATE to be tolerated in PKCS#7 structures. - Some CAs (e.g. Verisign) distribute certificates in this form. - [Steve Henson] - - *) Remove the SSL_ALLOW_ADH compile option and set the default cipher - list to exclude them. This means that no special compilation option - is needed to use anonymous DH: it just needs to be included in the - cipher list. - [Steve Henson] - - *) Change the EVP_MD_CTX_type macro so its meaning consistent with - EVP_MD_type. The old functionality is available in a new macro called - EVP_MD_md(). Change code that uses it and update docs. - [Steve Henson] - - *) ..._ctrl functions now have corresponding ..._callback_ctrl functions - where the 'void *' argument is replaced by a function pointer argument. - Previously 'void *' was abused to point to functions, which works on - many platforms, but is not correct. As these functions are usually - called by macros defined in OpenSSL header files, most source code - should work without changes. - [Richard Levitte] - - *) (which is created by Configure) now contains - sections with information on -D... compiler switches used for - compiling the library so that applications can see them. To enable - one of these sections, a pre-processor symbol OPENSSL_..._DEFINES - must be defined. E.g., - #define OPENSSL_ALGORITHM_DEFINES - #include - defines all pertinent NO_ symbols, such as NO_IDEA, NO_RSA, etc. - [Richard Levitte, Ulf and Bodo Möller] - - *) Bugfix: Tolerate fragmentation and interleaving in the SSL 3/TLS - record layer. - [Bodo Moeller] - - *) Change the 'other' type in certificate aux info to a STACK_OF - X509_ALGOR. Although not an AlgorithmIdentifier as such it has - the required ASN1 format: arbitrary types determined by an OID. - [Steve Henson] - - *) Add some PEM_write_X509_REQ_NEW() functions and a command line - argument to 'req'. This is not because the function is newer or - better than others it just uses the work 'NEW' in the certificate - request header lines. Some software needs this. - [Steve Henson] - - *) Reorganise password command line arguments: now passwords can be - obtained from various sources. Delete the PEM_cb function and make - it the default behaviour: i.e. if the callback is NULL and the - usrdata argument is not NULL interpret it as a null terminated pass - phrase. If usrdata and the callback are NULL then the pass phrase - is prompted for as usual. - [Steve Henson] - - *) Add support for the Compaq Atalla crypto accelerator. If it is installed, - the support is automatically enabled. The resulting binaries will - autodetect the card and use it if present. - [Ben Laurie and Compaq Inc.] - - *) Work around for Netscape hang bug. This sends certificate request - and server done in one record. Since this is perfectly legal in the - SSL/TLS protocol it isn't a "bug" option and is on by default. See - the bugs/SSLv3 entry for more info. - [Steve Henson] - - *) HP-UX tune-up: new unified configs, HP C compiler bug workaround. - [Andy Polyakov] - - *) Add -rand argument to smime and pkcs12 applications and read/write - of seed file. - [Steve Henson] - - *) New 'passwd' tool for crypt(3) and apr1 password hashes. - [Bodo Moeller] - - *) Add command line password options to the remaining applications. - [Steve Henson] - - *) Bug fix for BN_div_recp() for numerators with an even number of - bits. - [Ulf Möller] - - *) More tests in bntest.c, and changed test_bn output. - [Ulf Möller] - - *) ./config recognizes MacOS X now. - [Andy Polyakov] - - *) Bug fix for BN_div() when the first words of num and divisor are - equal (it gave wrong results if (rem=(n1-q*d0)&BN_MASK2) < d0). - [Ulf Möller] - - *) Add support for various broken PKCS#8 formats, and command line - options to produce them. - [Steve Henson] - - *) New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to - get temporary BIGNUMs from a BN_CTX. - [Ulf Möller] - - *) Correct return values in BN_mod_exp_mont() and BN_mod_exp2_mont() - for p == 0. - [Ulf Möller] - - *) Change the SSLeay_add_all_*() functions to OpenSSL_add_all_*() and - include a #define from the old name to the new. The original intent - was that statically linked binaries could for example just call - SSLeay_add_all_ciphers() to just add ciphers to the table and not - link with digests. This never worked because SSLeay_add_all_digests() - and SSLeay_add_all_ciphers() were in the same source file so calling - one would link with the other. They are now in separate source files. - [Steve Henson] - - *) Add a new -notext option to 'ca' and a -pubkey option to 'spkac'. - [Steve Henson] - - *) Use a less unusual form of the Miller-Rabin primality test (it used - a binary algorithm for exponentiation integrated into the Miller-Rabin - loop, our standard modexp algorithms are faster). - [Bodo Moeller] - - *) Support for the EBCDIC character set completed. - [Martin Kraemer ] - - *) Source code cleanups: use const where appropriate, eliminate casts, - use void * instead of char * in lhash. - [Ulf Möller] - - *) Bugfix: ssl3_send_server_key_exchange was not restartable - (the state was not changed to SSL3_ST_SW_KEY_EXCH_B, and because of - this the server could overwrite ephemeral keys that the client - has already seen). - [Bodo Moeller] - - *) Turn DSA_is_prime into a macro that calls BN_is_prime, - using 50 iterations of the Rabin-Miller test. - - DSA_generate_parameters now uses BN_is_prime_fasttest (with 50 - iterations of the Rabin-Miller test as required by the appendix - to FIPS PUB 186[-1]) instead of DSA_is_prime. - As BN_is_prime_fasttest includes trial division, DSA parameter - generation becomes much faster. - - This implies a change for the callback functions in DSA_is_prime - and DSA_generate_parameters: The callback function is called once - for each positive witness in the Rabin-Miller test, not just - occasionally in the inner loop; and the parameters to the - callback function now provide an iteration count for the outer - loop rather than for the current invocation of the inner loop. - DSA_generate_parameters additionally can call the callback - function with an 'iteration count' of -1, meaning that a - candidate has passed the trial division test (when q is generated - from an application-provided seed, trial division is skipped). - [Bodo Moeller] - - *) New function BN_is_prime_fasttest that optionally does trial - division before starting the Rabin-Miller test and has - an additional BN_CTX * argument (whereas BN_is_prime always - has to allocate at least one BN_CTX). - 'callback(1, -1, cb_arg)' is called when a number has passed the - trial division stage. - [Bodo Moeller] - - *) Fix for bug in CRL encoding. The validity dates weren't being handled - as ASN1_TIME. - [Steve Henson] - - *) New -pkcs12 option to CA.pl script to write out a PKCS#12 file. - [Steve Henson] - - *) New function BN_pseudo_rand(). - [Ulf Möller] - - *) Clean up BN_mod_mul_montgomery(): replace the broken (and unreadable) - bignum version of BN_from_montgomery() with the working code from - SSLeay 0.9.0 (the word based version is faster anyway), and clean up - the comments. - [Ulf Möller] - - *) Avoid a race condition in s2_clnt.c (function get_server_hello) that - made it impossible to use the same SSL_SESSION data structure in - SSL2 clients in multiple threads. - [Bodo Moeller] - - *) The return value of RAND_load_file() no longer counts bytes obtained - by stat(). RAND_load_file(..., -1) is new and uses the complete file - to seed the PRNG (previously an explicit byte count was required). - [Ulf Möller, Bodo Möller] - - *) Clean up CRYPTO_EX_DATA functions, some of these didn't have prototypes - used (char *) instead of (void *) and had casts all over the place. - [Steve Henson] - - *) Make BN_generate_prime() return NULL on error if ret!=NULL. - [Ulf Möller] - - *) Retain source code compatibility for BN_prime_checks macro: - BN_is_prime(..., BN_prime_checks, ...) now uses - BN_prime_checks_for_size to determine the appropriate number of - Rabin-Miller iterations. - [Ulf Möller] - - *) Diffie-Hellman uses "safe" primes: DH_check() return code renamed to - DH_CHECK_P_NOT_SAFE_PRIME. - (Check if this is true? OpenPGP calls them "strong".) - [Ulf Möller] - - *) Merge the functionality of "dh" and "gendh" programs into a new program - "dhparam". The old programs are retained for now but will handle DH keys - (instead of parameters) in future. - [Steve Henson] - - *) Make the ciphers, s_server and s_client programs check the return values - when a new cipher list is set. - [Steve Henson] - - *) Enhance the SSL/TLS cipher mechanism to correctly handle the TLS 56bit - ciphers. Before when the 56bit ciphers were enabled the sorting was - wrong. - - The syntax for the cipher sorting has been extended to support sorting by - cipher-strength (using the strength_bits hard coded in the tables). - The new command is "@STRENGTH" (see also doc/apps/ciphers.pod). - - Fix a bug in the cipher-command parser: when supplying a cipher command - string with an "undefined" symbol (neither command nor alphanumeric - [A-Za-z0-9], ssl_set_cipher_list used to hang in an endless loop. Now - an error is flagged. - - Due to the strength-sorting extension, the code of the - ssl_create_cipher_list() function was completely rearranged. I hope that - the readability was also increased :-) - [Lutz Jaenicke ] - - *) Minor change to 'x509' utility. The -CAcreateserial option now uses 1 - for the first serial number and places 2 in the serial number file. This - avoids problems when the root CA is created with serial number zero and - the first user certificate has the same issuer name and serial number - as the root CA. - [Steve Henson] - - *) Fixes to X509_ATTRIBUTE utilities, change the 'req' program so it uses - the new code. Add documentation for this stuff. - [Steve Henson] - - *) Changes to X509_ATTRIBUTE utilities. These have been renamed from - X509_*() to X509at_*() on the grounds that they don't handle X509 - structures and behave in an analogous way to the X509v3 functions: - they shouldn't be called directly but wrapper functions should be used - instead. - - So we also now have some wrapper functions that call the X509at functions - when passed certificate requests. (TO DO: similar things can be done with - PKCS#7 signed and unsigned attributes, PKCS#12 attributes and a few other - things. Some of these need some d2i or i2d and print functionality - because they handle more complex structures.) - [Steve Henson] - - *) Add missing #ifndefs that caused missing symbols when building libssl - as a shared library without RSA. Use #ifndef NO_SSL2 instead of - NO_RSA in ssl/s2*.c. - [Kris Kennaway , modified by Ulf Möller] - - *) Precautions against using the PRNG uninitialized: RAND_bytes() now - has a return value which indicates the quality of the random data - (1 = ok, 0 = not seeded). Also an error is recorded on the thread's - error queue. New function RAND_pseudo_bytes() generates output that is - guaranteed to be unique but not unpredictable. RAND_add is like - RAND_seed, but takes an extra argument for an entropy estimate - (RAND_seed always assumes full entropy). - [Ulf Möller] - - *) Do more iterations of Rabin-Miller probable prime test (specifically, - 3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes - instead of only 2 for all lengths; see BN_prime_checks_for_size definition - in crypto/bn/bn_prime.c for the complete table). This guarantees a - false-positive rate of at most 2^-80 for random input. - [Bodo Moeller] - - *) Rewrite ssl3_read_n (ssl/s3_pkt.c) avoiding a couple of bugs. - [Bodo Moeller] - - *) New function X509_CTX_rget_chain() (renamed to X509_CTX_get1_chain - in the 0.9.5 release), this returns the chain - from an X509_CTX structure with a dup of the stack and all - the X509 reference counts upped: so the stack will exist - after X509_CTX_cleanup() has been called. Modify pkcs12.c - to use this. - - Also make SSL_SESSION_print() print out the verify return - code. - [Steve Henson] - - *) Add manpage for the pkcs12 command. Also change the default - behaviour so MAC iteration counts are used unless the new - -nomaciter option is used. This improves file security and - only older versions of MSIE (4.0 for example) need it. - [Steve Henson] - - *) Honor the no-xxx Configure options when creating .DEF files. - [Ulf Möller] - - *) Add PKCS#10 attributes to field table: challengePassword, - unstructuredName and unstructuredAddress. These are taken from - draft PKCS#9 v2.0 but are compatible with v1.2 provided no - international characters are used. - - More changes to X509_ATTRIBUTE code: allow the setting of types - based on strings. Remove the 'loc' parameter when adding - attributes because these will be a SET OF encoding which is sorted - in ASN1 order. - [Steve Henson] - - *) Initial changes to the 'req' utility to allow request generation - automation. This will allow an application to just generate a template - file containing all the field values and have req construct the - request. - - Initial support for X509_ATTRIBUTE handling. Stacks of these are - used all over the place including certificate requests and PKCS#7 - structures. They are currently handled manually where necessary with - some primitive wrappers for PKCS#7. The new functions behave in a - manner analogous to the X509 extension functions: they allow - attributes to be looked up by NID and added. - - Later something similar to the X509V3 code would be desirable to - automatically handle the encoding, decoding and printing of the - more complex types. The string types like challengePassword can - be handled by the string table functions. - - Also modified the multi byte string table handling. Now there is - a 'global mask' which masks out certain types. The table itself - can use the flag STABLE_NO_MASK to ignore the mask setting: this - is useful when for example there is only one permissible type - (as in countryName) and using the mask might result in no valid - types at all. - [Steve Henson] - - *) Clean up 'Finished' handling, and add functions SSL_get_finished and - SSL_get_peer_finished to allow applications to obtain the latest - Finished messages sent to the peer or expected from the peer, - respectively. (SSL_get_peer_finished is usually the Finished message - actually received from the peer, otherwise the protocol will be aborted.) - - As the Finished message are message digests of the complete handshake - (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can - be used for external authentication procedures when the authentication - provided by SSL/TLS is not desired or is not enough. - [Bodo Moeller] - - *) Enhanced support for Alpha Linux is added. Now ./config checks if - the host supports BWX extension and if Compaq C is present on the - $PATH. Just exploiting of the BWX extension results in 20-30% - performance kick for some algorithms, e.g. DES and RC4 to mention - a couple. Compaq C in turn generates ~20% faster code for MD5 and - SHA1. - [Andy Polyakov] - - *) Add support for MS "fast SGC". This is arguably a violation of the - SSL3/TLS protocol. Netscape SGC does two handshakes: the first with - weak crypto and after checking the certificate is SGC a second one - with strong crypto. MS SGC stops the first handshake after receiving - the server certificate message and sends a second client hello. Since - a server will typically do all the time consuming operations before - expecting any further messages from the client (server key exchange - is the most expensive) there is little difference between the two. - - To get OpenSSL to support MS SGC we have to permit a second client - hello message after we have sent server done. In addition we have to - reset the MAC if we do get this second client hello. - [Steve Henson] - - *) Add a function 'd2i_AutoPrivateKey()' this will automatically decide - if a DER encoded private key is RSA or DSA traditional format. Changed - d2i_PrivateKey_bio() to use it. This is only needed for the "traditional" - format DER encoded private key. Newer code should use PKCS#8 format which - has the key type encoded in the ASN1 structure. Added DER private key - support to pkcs8 application. - [Steve Henson] - - *) SSL 3/TLS 1 servers now don't request certificates when an anonymous - ciphersuites has been selected (as required by the SSL 3/TLS 1 - specifications). Exception: When SSL_VERIFY_FAIL_IF_NO_PEER_CERT - is set, we interpret this as a request to violate the specification - (the worst that can happen is a handshake failure, and 'correct' - behaviour would result in a handshake failure anyway). - [Bodo Moeller] - - *) In SSL_CTX_add_session, take into account that there might be multiple - SSL_SESSION structures with the same session ID (e.g. when two threads - concurrently obtain them from an external cache). - The internal cache can handle only one SSL_SESSION with a given ID, - so if there's a conflict, we now throw out the old one to achieve - consistency. - [Bodo Moeller] - - *) Add OIDs for idea and blowfish in CBC mode. This will allow both - to be used in PKCS#5 v2.0 and S/MIME. Also add checking to - some routines that use cipher OIDs: some ciphers do not have OIDs - defined and so they cannot be used for S/MIME and PKCS#5 v2.0 for - example. - [Steve Henson] - - *) Simplify the trust setting structure and code. Now we just have - two sequences of OIDs for trusted and rejected settings. These will - typically have values the same as the extended key usage extension - and any application specific purposes. - - The trust checking code now has a default behaviour: it will just - check for an object with the same NID as the passed id. Functions can - be provided to override either the default behaviour or the behaviour - for a given id. SSL client, server and email already have functions - in place for compatibility: they check the NID and also return "trusted" - if the certificate is self signed. - [Steve Henson] - - *) Add d2i,i2d bio/fp functions for PrivateKey: these convert the - traditional format into an EVP_PKEY structure. - [Steve Henson] - - *) Add a password callback function PEM_cb() which either prompts for - a password if usr_data is NULL or otherwise assumes it is a null - terminated password. Allow passwords to be passed on command line - environment or config files in a few more utilities. - [Steve Henson] - - *) Add a bunch of DER and PEM functions to handle PKCS#8 format private - keys. Add some short names for PKCS#8 PBE algorithms and allow them - to be specified on the command line for the pkcs8 and pkcs12 utilities. - Update documentation. - [Steve Henson] - - *) Support for ASN1 "NULL" type. This could be handled before by using - ASN1_TYPE but there wasn't any function that would try to read a NULL - and produce an error if it couldn't. For compatibility we also have - ASN1_NULL_new() and ASN1_NULL_free() functions but these are faked and - don't allocate anything because they don't need to. - [Steve Henson] - - *) Initial support for MacOS is now provided. Examine INSTALL.MacOS - for details. - [Andy Polyakov, Roy Woods ] - - *) Rebuild of the memory allocation routines used by OpenSSL code and - possibly others as well. The purpose is to make an interface that - provide hooks so anyone can build a separate set of allocation and - deallocation routines to be used by OpenSSL, for example memory - pool implementations, or something else, which was previously hard - since Malloc(), Realloc() and Free() were defined as macros having - the values malloc, realloc and free, respectively (except for Win32 - compilations). The same is provided for memory debugging code. - OpenSSL already comes with functionality to find memory leaks, but - this gives people a chance to debug other memory problems. - - With these changes, a new set of functions and macros have appeared: - - CRYPTO_set_mem_debug_functions() [F] - CRYPTO_get_mem_debug_functions() [F] - CRYPTO_dbg_set_options() [F] - CRYPTO_dbg_get_options() [F] - CRYPTO_malloc_debug_init() [M] - - The memory debug functions are NULL by default, unless the library - is compiled with CRYPTO_MDEBUG or friends is defined. If someone - wants to debug memory anyway, CRYPTO_malloc_debug_init() (which - gives the standard debugging functions that come with OpenSSL) or - CRYPTO_set_mem_debug_functions() (tells OpenSSL to use functions - provided by the library user) must be used. When the standard - debugging functions are used, CRYPTO_dbg_set_options can be used to - request additional information: - CRYPTO_dbg_set_options(V_CYRPTO_MDEBUG_xxx) corresponds to setting - the CRYPTO_MDEBUG_xxx macro when compiling the library. - - Also, things like CRYPTO_set_mem_functions will always give the - expected result (the new set of functions is used for allocation - and deallocation) at all times, regardless of platform and compiler - options. - - To finish it up, some functions that were never use in any other - way than through macros have a new API and new semantic: - - CRYPTO_dbg_malloc() - CRYPTO_dbg_realloc() - CRYPTO_dbg_free() - - All macros of value have retained their old syntax. - [Richard Levitte and Bodo Moeller] - - *) Some S/MIME fixes. The OID for SMIMECapabilities was wrong, the - ordering of SMIMECapabilities wasn't in "strength order" and there - was a missing NULL in the AlgorithmIdentifier for the SHA1 signature - algorithm. - [Steve Henson] - - *) Some ASN1 types with illegal zero length encoding (INTEGER, - ENUMERATED and OBJECT IDENTIFIER) choked the ASN1 routines. - [Frans Heymans , modified by Steve Henson] - - *) Merge in my S/MIME library for OpenSSL. This provides a simple - S/MIME API on top of the PKCS#7 code, a MIME parser (with enough - functionality to handle multipart/signed properly) and a utility - called 'smime' to call all this stuff. This is based on code I - originally wrote for Celo who have kindly allowed it to be - included in OpenSSL. - [Steve Henson] - - *) Add variants des_set_key_checked and des_set_key_unchecked of - des_set_key (aka des_key_sched). Global variable des_check_key - decides which of these is called by des_set_key; this way - des_check_key behaves as it always did, but applications and - the library itself, which was buggy for des_check_key == 1, - have a cleaner way to pick the version they need. - [Bodo Moeller] - - *) New function PKCS12_newpass() which changes the password of a - PKCS12 structure. - [Steve Henson] - - *) Modify X509_TRUST and X509_PURPOSE so it also uses a static and - dynamic mix. In both cases the ids can be used as an index into the - table. Also modified the X509_TRUST_add() and X509_PURPOSE_add() - functions so they accept a list of the field values and the - application doesn't need to directly manipulate the X509_TRUST - structure. - [Steve Henson] - - *) Modify the ASN1_STRING_TABLE stuff so it also uses bsearch and doesn't - need initialising. - [Steve Henson] - - *) Modify the way the V3 extension code looks up extensions. This now - works in a similar way to the object code: we have some "standard" - extensions in a static table which is searched with OBJ_bsearch() - and the application can add dynamic ones if needed. The file - crypto/x509v3/ext_dat.h now has the info: this file needs to be - updated whenever a new extension is added to the core code and kept - in ext_nid order. There is a simple program 'tabtest.c' which checks - this. New extensions are not added too often so this file can readily - be maintained manually. - - There are two big advantages in doing things this way. The extensions - can be looked up immediately and no longer need to be "added" using - X509V3_add_standard_extensions(): this function now does nothing. - [Side note: I get *lots* of email saying the extension code doesn't - work because people forget to call this function] - Also no dynamic allocation is done unless new extensions are added: - so if we don't add custom extensions there is no need to call - X509V3_EXT_cleanup(). - [Steve Henson] - - *) Modify enc utility's salting as follows: make salting the default. Add a - magic header, so unsalted files fail gracefully instead of just decrypting - to garbage. This is because not salting is a big security hole, so people - should be discouraged from doing it. - [Ben Laurie] - - *) Fixes and enhancements to the 'x509' utility. It allowed a message - digest to be passed on the command line but it only used this - parameter when signing a certificate. Modified so all relevant - operations are affected by the digest parameter including the - -fingerprint and -x509toreq options. Also -x509toreq choked if a - DSA key was used because it didn't fix the digest. - [Steve Henson] - - *) Initial certificate chain verify code. Currently tests the untrusted - certificates for consistency with the verify purpose (which is set - when the X509_STORE_CTX structure is set up) and checks the pathlength. - - There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour: - this is because it will reject chains with invalid extensions whereas - every previous version of OpenSSL and SSLeay made no checks at all. - - Trust code: checks the root CA for the relevant trust settings. Trust - settings have an initial value consistent with the verify purpose: e.g. - if the verify purpose is for SSL client use it expects the CA to be - trusted for SSL client use. However the default value can be changed to - permit custom trust settings: one example of this would be to only trust - certificates from a specific "secure" set of CAs. - - Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions - which should be used for version portability: especially since the - verify structure is likely to change more often now. - - SSL integration. Add purpose and trust to SSL_CTX and SSL and functions - to set them. If not set then assume SSL clients will verify SSL servers - and vice versa. - - Two new options to the verify program: -untrusted allows a set of - untrusted certificates to be passed in and -purpose which sets the - intended purpose of the certificate. If a purpose is set then the - new chain verify code is used to check extension consistency. - [Steve Henson] - - *) Support for the authority information access extension. - [Steve Henson] - - *) Modify RSA and DSA PEM read routines to transparently handle - PKCS#8 format private keys. New *_PUBKEY_* functions that handle - public keys in a format compatible with certificate - SubjectPublicKeyInfo structures. Unfortunately there were already - functions called *_PublicKey_* which used various odd formats so - these are retained for compatibility: however the DSA variants were - never in a public release so they have been deleted. Changed dsa/rsa - utilities to handle the new format: note no releases ever handled public - keys so we should be OK. - - The primary motivation for this change is to avoid the same fiasco - that dogs private keys: there are several incompatible private key - formats some of which are standard and some OpenSSL specific and - require various evil hacks to allow partial transparent handling and - even then it doesn't work with DER formats. Given the option anything - other than PKCS#8 should be dumped: but the other formats have to - stay in the name of compatibility. - - With public keys and the benefit of hindsight one standard format - is used which works with EVP_PKEY, RSA or DSA structures: though - it clearly returns an error if you try to read the wrong kind of key. - - Added a -pubkey option to the 'x509' utility to output the public key. - Also rename the EVP_PKEY_get_*() to EVP_PKEY_rget_*() - (renamed to EVP_PKEY_get1_*() in the OpenSSL 0.9.5 release) and add - EVP_PKEY_rset_*() functions (renamed to EVP_PKEY_set1_*()) - that do the same as the EVP_PKEY_assign_*() except they up the - reference count of the added key (they don't "swallow" the - supplied key). - [Steve Henson] - - *) Fixes to crypto/x509/by_file.c the code to read in certificates and - CRLs would fail if the file contained no certificates or no CRLs: - added a new function to read in both types and return the number - read: this means that if none are read it will be an error. The - DER versions of the certificate and CRL reader would always fail - because it isn't possible to mix certificates and CRLs in DER format - without choking one or the other routine. Changed this to just read - a certificate: this is the best we can do. Also modified the code - in apps/verify.c to take notice of return codes: it was previously - attempting to read in certificates from NULL pointers and ignoring - any errors: this is one reason why the cert and CRL reader seemed - to work. It doesn't check return codes from the default certificate - routines: these may well fail if the certificates aren't installed. - [Steve Henson] - - *) Code to support otherName option in GeneralName. - [Steve Henson] - - *) First update to verify code. Change the verify utility - so it warns if it is passed a self signed certificate: - for consistency with the normal behaviour. X509_verify - has been modified to it will now verify a self signed - certificate if *exactly* the same certificate appears - in the store: it was previously impossible to trust a - single self signed certificate. This means that: - openssl verify ss.pem - now gives a warning about a self signed certificate but - openssl verify -CAfile ss.pem ss.pem - is OK. - [Steve Henson] - - *) For servers, store verify_result in SSL_SESSION data structure - (and add it to external session representation). - This is needed when client certificate verifications fails, - but an application-provided verification callback (set by - SSL_CTX_set_cert_verify_callback) allows accepting the session - anyway (i.e. leaves x509_store_ctx->error != X509_V_OK - but returns 1): When the session is reused, we have to set - ssl->verify_result to the appropriate error code to avoid - security holes. - [Bodo Moeller, problem pointed out by Lutz Jaenicke] - - *) Fix a bug in the new PKCS#7 code: it didn't consider the - case in PKCS7_dataInit() where the signed PKCS7 structure - didn't contain any existing data because it was being created. - [Po-Cheng Chen , slightly modified by Steve Henson] - - *) Add a salt to the key derivation routines in enc.c. This - forms the first 8 bytes of the encrypted file. Also add a - -S option to allow a salt to be input on the command line. - [Steve Henson] - - *) New function X509_cmp(). Oddly enough there wasn't a function - to compare two certificates. We do this by working out the SHA1 - hash and comparing that. X509_cmp() will be needed by the trust - code. - [Steve Henson] - - *) SSL_get1_session() is like SSL_get_session(), but increments - the reference count in the SSL_SESSION returned. - [Geoff Thorpe ] - - *) Fix for 'req': it was adding a null to request attributes. - Also change the X509_LOOKUP and X509_INFO code to handle - certificate auxiliary information. - [Steve Henson] - - *) Add support for 40 and 64 bit RC2 and RC4 algorithms: document - the 'enc' command. - [Steve Henson] - - *) Add the possibility to add extra information to the memory leak - detecting output, to form tracebacks, showing from where each - allocation was originated: CRYPTO_push_info("constant string") adds - the string plus current file name and line number to a per-thread - stack, CRYPTO_pop_info() does the obvious, CRYPTO_remove_all_info() - is like calling CYRPTO_pop_info() until the stack is empty. - Also updated memory leak detection code to be multi-thread-safe. - [Richard Levitte] - - *) Add options -text and -noout to pkcs7 utility and delete the - encryption options which never did anything. Update docs. - [Steve Henson] - - *) Add options to some of the utilities to allow the pass phrase - to be included on either the command line (not recommended on - OSes like Unix) or read from the environment. Update the - manpages and fix a few bugs. - [Steve Henson] - - *) Add a few manpages for some of the openssl commands. - [Steve Henson] - - *) Fix the -revoke option in ca. It was freeing up memory twice, - leaking and not finding already revoked certificates. - [Steve Henson] - - *) Extensive changes to support certificate auxiliary information. - This involves the use of X509_CERT_AUX structure and X509_AUX - functions. An X509_AUX function such as PEM_read_X509_AUX() - can still read in a certificate file in the usual way but it - will also read in any additional "auxiliary information". By - doing things this way a fair degree of compatibility can be - retained: existing certificates can have this information added - using the new 'x509' options. - - Current auxiliary information includes an "alias" and some trust - settings. The trust settings will ultimately be used in enhanced - certificate chain verification routines: currently a certificate - can only be trusted if it is self signed and then it is trusted - for all purposes. - [Steve Henson] - - *) Fix assembler for Alpha (tested only on DEC OSF not Linux or *BSD). - The problem was that one of the replacement routines had not been working - since SSLeay releases. For now the offending routine has been replaced - with non-optimised assembler. Even so, this now gives around 95% - performance improvement for 1024 bit RSA signs. - [Mark Cox] - - *) Hack to fix PKCS#7 decryption when used with some unorthodox RC2 - handling. Most clients have the effective key size in bits equal to - the key length in bits: so a 40 bit RC2 key uses a 40 bit (5 byte) key. - A few however don't do this and instead use the size of the decrypted key - to determine the RC2 key length and the AlgorithmIdentifier to determine - the effective key length. In this case the effective key length can still - be 40 bits but the key length can be 168 bits for example. This is fixed - by manually forcing an RC2 key into the EVP_PKEY structure because the - EVP code can't currently handle unusual RC2 key sizes: it always assumes - the key length and effective key length are equal. - [Steve Henson] - - *) Add a bunch of functions that should simplify the creation of - X509_NAME structures. Now you should be able to do: - X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0); - and have it automatically work out the correct field type and fill in - the structures. The more adventurous can try: - X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0); - and it will (hopefully) work out the correct multibyte encoding. - [Steve Henson] - - *) Change the 'req' utility to use the new field handling and multibyte - copy routines. Before the DN field creation was handled in an ad hoc - way in req, ca, and x509 which was rather broken and didn't support - BMPStrings or UTF8Strings. Since some software doesn't implement - BMPStrings or UTF8Strings yet, they can be enabled using the config file - using the dirstring_type option. See the new comment in the default - openssl.cnf for more info. - [Steve Henson] - - *) Make crypto/rand/md_rand.c more robust: - - Assure unique random numbers after fork(). - - Make sure that concurrent threads access the global counter and - md serializably so that we never lose entropy in them - or use exactly the same state in multiple threads. - Access to the large state is not always serializable because - the additional locking could be a performance killer, and - md should be large enough anyway. - [Bodo Moeller] - - *) New file apps/app_rand.c with commonly needed functionality - for handling the random seed file. - - Use the random seed file in some applications that previously did not: - ca, - dsaparam -genkey (which also ignored its '-rand' option), - s_client, - s_server, - x509 (when signing). - Except on systems with /dev/urandom, it is crucial to have a random - seed file at least for key creation, DSA signing, and for DH exchanges; - for RSA signatures we could do without one. - - gendh and gendsa (unlike genrsa) used to read only the first byte - of each file listed in the '-rand' option. The function as previously - found in genrsa is now in app_rand.c and is used by all programs - that support '-rand'. - [Bodo Moeller] - - *) In RAND_write_file, use mode 0600 for creating files; - don't just chmod when it may be too late. - [Bodo Moeller] - - *) Report an error from X509_STORE_load_locations - when X509_LOOKUP_load_file or X509_LOOKUP_add_dir failed. - [Bill Perry] - - *) New function ASN1_mbstring_copy() this copies a string in either - ASCII, Unicode, Universal (4 bytes per character) or UTF8 format - into an ASN1_STRING type. A mask of permissible types is passed - and it chooses the "minimal" type to use or an error if not type - is suitable. - [Steve Henson] - - *) Add function equivalents to the various macros in asn1.h. The old - macros are retained with an M_ prefix. Code inside the library can - use the M_ macros. External code (including the openssl utility) - should *NOT* in order to be "shared library friendly". - [Steve Henson] - - *) Add various functions that can check a certificate's extensions - to see if it usable for various purposes such as SSL client, - server or S/MIME and CAs of these types. This is currently - VERY EXPERIMENTAL but will ultimately be used for certificate chain - verification. Also added a -purpose flag to x509 utility to - print out all the purposes. - [Steve Henson] - - *) Add a CRYPTO_EX_DATA to X509 certificate structure and associated - functions. - [Steve Henson] - - *) New X509V3_{X509,CRL,REVOKED}_get_d2i() functions. These will search - for, obtain and decode and extension and obtain its critical flag. - This allows all the necessary extension code to be handled in a - single function call. - [Steve Henson] - - *) RC4 tune-up featuring 30-40% performance improvement on most RISC - platforms. See crypto/rc4/rc4_enc.c for further details. - [Andy Polyakov] - - *) New -noout option to asn1parse. This causes no output to be produced - its main use is when combined with -strparse and -out to extract data - from a file (which may not be in ASN.1 format). - [Steve Henson] - - *) Fix for pkcs12 program. It was hashing an invalid certificate pointer - when producing the local key id. - [Richard Levitte ] - - *) New option -dhparam in s_server. This allows a DH parameter file to be - stated explicitly. If it is not stated then it tries the first server - certificate file. The previous behaviour hard coded the filename - "server.pem". - [Steve Henson] - - *) Add -pubin and -pubout options to the rsa and dsa commands. These allow - a public key to be input or output. For example: - openssl rsa -in key.pem -pubout -out pubkey.pem - Also added necessary DSA public key functions to handle this. - [Steve Henson] - - *) Fix so PKCS7_dataVerify() doesn't crash if no certificates are contained - in the message. This was handled by allowing - X509_find_by_issuer_and_serial() to tolerate a NULL passed to it. - [Steve Henson, reported by Sampo Kellomaki ] - - *) Fix for bug in d2i_ASN1_bytes(): other ASN1 functions add an extra null - to the end of the strings whereas this didn't. This would cause problems - if strings read with d2i_ASN1_bytes() were later modified. - [Steve Henson, reported by Arne Ansper ] - - *) Fix for base64 decode bug. When a base64 bio reads only one line of - data and it contains EOF it will end up returning an error. This is - caused by input 46 bytes long. The cause is due to the way base64 - BIOs find the start of base64 encoded data. They do this by trying a - trial decode on each line until they find one that works. When they - do a flag is set and it starts again knowing it can pass all the - data directly through the decoder. Unfortunately it doesn't reset - the context it uses. This means that if EOF is reached an attempt - is made to pass two EOFs through the context and this causes the - resulting error. This can also cause other problems as well. As is - usual with these problems it takes *ages* to find and the fix is - trivial: move one line. - [Steve Henson, reported by ian@uns.ns.ac.yu (Ivan Nejgebauer) ] - - *) Ugly workaround to get s_client and s_server working under Windows. The - old code wouldn't work because it needed to select() on sockets and the - tty (for keypresses and to see if data could be written). Win32 only - supports select() on sockets so we select() with a 1s timeout on the - sockets and then see if any characters are waiting to be read, if none - are present then we retry, we also assume we can always write data to - the tty. This isn't nice because the code then blocks until we've - received a complete line of data and it is effectively polling the - keyboard at 1s intervals: however it's quite a bit better than not - working at all :-) A dedicated Windows application might handle this - with an event loop for example. - [Steve Henson] - - *) Enhance RSA_METHOD structure. Now there are two extra methods, rsa_sign - and rsa_verify. When the RSA_FLAGS_SIGN_VER option is set these functions - will be called when RSA_sign() and RSA_verify() are used. This is useful - if rsa_pub_dec() and rsa_priv_enc() equivalents are not available. - For this to work properly RSA_public_decrypt() and RSA_private_encrypt() - should *not* be used: RSA_sign() and RSA_verify() must be used instead. - This necessitated the support of an extra signature type NID_md5_sha1 - for SSL signatures and modifications to the SSL library to use it instead - of calling RSA_public_decrypt() and RSA_private_encrypt(). - [Steve Henson] - - *) Add new -verify -CAfile and -CApath options to the crl program, these - will lookup a CRL issuers certificate and verify the signature in a - similar way to the verify program. Tidy up the crl program so it - no longer accesses structures directly. Make the ASN1 CRL parsing a bit - less strict. It will now permit CRL extensions even if it is not - a V2 CRL: this will allow it to tolerate some broken CRLs. - [Steve Henson] - - *) Initialize all non-automatic variables each time one of the openssl - sub-programs is started (this is necessary as they may be started - multiple times from the "OpenSSL>" prompt). - [Lennart Bang, Bodo Moeller] - - *) Preliminary compilation option RSA_NULL which disables RSA crypto without - removing all other RSA functionality (this is what NO_RSA does). This - is so (for example) those in the US can disable those operations covered - by the RSA patent while allowing storage and parsing of RSA keys and RSA - key generation. - [Steve Henson] - - *) Non-copying interface to BIO pairs. - (still largely untested) - [Bodo Moeller] - - *) New function ANS1_tag2str() to convert an ASN1 tag to a descriptive - ASCII string. This was handled independently in various places before. - [Steve Henson] - - *) New functions UTF8_getc() and UTF8_putc() that parse and generate - UTF8 strings a character at a time. - [Steve Henson] - - *) Use client_version from client hello to select the protocol - (s23_srvr.c) and for RSA client key exchange verification - (s3_srvr.c), as required by the SSL 3.0/TLS 1.0 specifications. - [Bodo Moeller] - - *) Add various utility functions to handle SPKACs, these were previously - handled by poking round in the structure internals. Added new function - NETSCAPE_SPKI_print() to print out SPKAC and a new utility 'spkac' to - print, verify and generate SPKACs. Based on an original idea from - Massimiliano Pala but extensively modified. - [Steve Henson] - - *) RIPEMD160 is operational on all platforms and is back in 'make test'. - [Andy Polyakov] - - *) Allow the config file extension section to be overwritten on the - command line. Based on an original idea from Massimiliano Pala - . The new option is called -extensions - and can be applied to ca, req and x509. Also -reqexts to override - the request extensions in req and -crlexts to override the crl extensions - in ca. - [Steve Henson] - - *) Add new feature to the SPKAC handling in ca. Now you can include - the same field multiple times by preceding it by "XXXX." for example: - 1.OU="Unit name 1" - 2.OU="Unit name 2" - this is the same syntax as used in the req config file. - [Steve Henson] - - *) Allow certificate extensions to be added to certificate requests. These - are specified in a 'req_extensions' option of the req section of the - config file. They can be printed out with the -text option to req but - are otherwise ignored at present. - [Steve Henson] - - *) Fix a horrible bug in enc_read() in crypto/evp/bio_enc.c: if the first - data read consists of only the final block it would not decrypted because - EVP_CipherUpdate() would correctly report zero bytes had been decrypted. - A misplaced 'break' also meant the decrypted final block might not be - copied until the next read. - [Steve Henson] - - *) Initial support for DH_METHOD. Again based on RSA_METHOD. Also added - a few extra parameters to the DH structure: these will be useful if - for example we want the value of 'q' or implement X9.42 DH. - [Steve Henson] - - *) Initial support for DSA_METHOD. This is based on the RSA_METHOD and - provides hooks that allow the default DSA functions or functions on a - "per key" basis to be replaced. This allows hardware acceleration and - hardware key storage to be handled without major modification to the - library. Also added low level modexp hooks and CRYPTO_EX structure and - associated functions. - [Steve Henson] - - *) Add a new flag to memory BIOs, BIO_FLAG_MEM_RDONLY. This marks the BIO - as "read only": it can't be written to and the buffer it points to will - not be freed. Reading from a read only BIO is much more efficient than - a normal memory BIO. This was added because there are several times when - an area of memory needs to be read from a BIO. The previous method was - to create a memory BIO and write the data to it, this results in two - copies of the data and an O(n^2) reading algorithm. There is a new - function BIO_new_mem_buf() which creates a read only memory BIO from - an area of memory. Also modified the PKCS#7 routines to use read only - memory BIOs. - [Steve Henson] - - *) Bugfix: ssl23_get_client_hello did not work properly when called in - state SSL23_ST_SR_CLNT_HELLO_B, i.e. when the first 7 bytes of - a SSLv2-compatible client hello for SSLv3 or TLSv1 could be read, - but a retry condition occurred while trying to read the rest. - [Bodo Moeller] - - *) The PKCS7_ENC_CONTENT_new() function was setting the content type as - NID_pkcs7_encrypted by default: this was wrong since this should almost - always be NID_pkcs7_data. Also modified the PKCS7_set_type() to handle - the encrypted data type: this is a more sensible place to put it and it - allows the PKCS#12 code to be tidied up that duplicated this - functionality. - [Steve Henson] - - *) Changed obj_dat.pl script so it takes its input and output files on - the command line. This should avoid shell escape redirection problems - under Win32. - [Steve Henson] - - *) Initial support for certificate extension requests, these are included - in things like Xenroll certificate requests. Included functions to allow - extensions to be obtained and added. - [Steve Henson] - - *) -crlf option to s_client and s_server for sending newlines as - CRLF (as required by many protocols). - [Bodo Moeller] - - Changes between 0.9.3a and 0.9.4 [09 Aug 1999] - - *) Install libRSAglue.a when OpenSSL is built with RSAref. - [Ralf S. Engelschall] - - *) A few more ``#ifndef NO_FP_API / #endif'' pairs for consistency. - [Andrija Antonijevic ] - - *) Fix -startdate and -enddate (which was missing) arguments to 'ca' - program. - [Steve Henson] - - *) New function DSA_dup_DH, which duplicates DSA parameters/keys as - DH parameters/keys (q is lost during that conversion, but the resulting - DH parameters contain its length). - - For 1024-bit p, DSA_generate_parameters followed by DSA_dup_DH is - much faster than DH_generate_parameters (which creates parameters - where p = 2*q + 1), and also the smaller q makes DH computations - much more efficient (160-bit exponentiation instead of 1024-bit - exponentiation); so this provides a convenient way to support DHE - ciphersuites in SSL/TLS servers (see ssl/ssltest.c). It is of - utter importance to use - SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); - or - SSL_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); - when such DH parameters are used, because otherwise small subgroup - attacks may become possible! - [Bodo Moeller] - - *) Avoid memory leak in i2d_DHparams. - [Bodo Moeller] - - *) Allow the -k option to be used more than once in the enc program: - this allows the same encrypted message to be read by multiple recipients. - [Steve Henson] - - *) New function OBJ_obj2txt(buf, buf_len, a, no_name), this converts - an ASN1_OBJECT to a text string. If the "no_name" parameter is set then - it will always use the numerical form of the OID, even if it has a short - or long name. - [Steve Henson] - - *) Added an extra RSA flag: RSA_FLAG_EXT_PKEY. Previously the rsa_mod_exp - method only got called if p,q,dmp1,dmq1,iqmp components were present, - otherwise bn_mod_exp was called. In the case of hardware keys for example - no private key components need be present and it might store extra data - in the RSA structure, which cannot be accessed from bn_mod_exp. - By setting RSA_FLAG_EXT_PKEY rsa_mod_exp will always be called for - private key operations. - [Steve Henson] - - *) Added support for SPARC Linux. - [Andy Polyakov] - - *) pem_password_cb function type incompatibly changed from - typedef int pem_password_cb(char *buf, int size, int rwflag); - to - ....(char *buf, int size, int rwflag, void *userdata); - so that applications can pass data to their callbacks: - The PEM[_ASN1]_{read,write}... functions and macros now take an - additional void * argument, which is just handed through whenever - the password callback is called. - [Damien Miller ; tiny changes by Bodo Moeller] - - New function SSL_CTX_set_default_passwd_cb_userdata. - - Compatibility note: As many C implementations push function arguments - onto the stack in reverse order, the new library version is likely to - interoperate with programs that have been compiled with the old - pem_password_cb definition (PEM_whatever takes some data that - happens to be on the stack as its last argument, and the callback - just ignores this garbage); but there is no guarantee whatsoever that - this will work. - - *) The -DPLATFORM="\"$(PLATFORM)\"" definition and the similar -DCFLAGS=... - (both in crypto/Makefile.ssl for use by crypto/cversion.c) caused - problems not only on Windows, but also on some Unix platforms. - To avoid problematic command lines, these definitions are now in an - auto-generated file crypto/buildinf.h (created by crypto/Makefile.ssl - for standard "make" builds, by util/mk1mf.pl for "mk1mf" builds). - [Bodo Moeller] - - *) MIPS III/IV assembler module is reimplemented. - [Andy Polyakov] - - *) More DES library cleanups: remove references to srand/rand and - delete an unused file. - [Ulf Möller] - - *) Add support for the free Netwide assembler (NASM) under Win32, - since not many people have MASM (ml) and it can be hard to obtain. - This is currently experimental but it seems to work OK and pass all - the tests. Check out INSTALL.W32 for info. - [Steve Henson] - - *) Fix memory leaks in s3_clnt.c: All non-anonymous SSL3/TLS1 connections - without temporary keys kept an extra copy of the server key, - and connections with temporary keys did not free everything in case - of an error. - [Bodo Moeller] - - *) New function RSA_check_key and new openssl rsa option -check - for verifying the consistency of RSA keys. - [Ulf Moeller, Bodo Moeller] - - *) Various changes to make Win32 compile work: - 1. Casts to avoid "loss of data" warnings in p5_crpt2.c - 2. Change unsigned int to int in b_dump.c to avoid "signed/unsigned - comparison" warnings. - 3. Add sk__sort to DEF file generator and do make update. - [Steve Henson] - - *) Add a debugging option to PKCS#5 v2 key generation function: when - you #define DEBUG_PKCS5V2 passwords, salts, iteration counts and - derived keys are printed to stderr. - [Steve Henson] - - *) Copy the flags in ASN1_STRING_dup(). - [Roman E. Pavlov ] - - *) The x509 application mishandled signing requests containing DSA - keys when the signing key was also DSA and the parameters didn't match. - - It was supposed to omit the parameters when they matched the signing key: - the verifying software was then supposed to automatically use the CA's - parameters if they were absent from the end user certificate. - - Omitting parameters is no longer recommended. The test was also - the wrong way round! This was probably due to unusual behaviour in - EVP_cmp_parameters() which returns 1 if the parameters match. - This meant that parameters were omitted when they *didn't* match and - the certificate was useless. Certificates signed with 'ca' didn't have - this bug. - [Steve Henson, reported by Doug Erickson ] - - *) Memory leak checking (-DCRYPTO_MDEBUG) had some problems. - The interface is as follows: - Applications can use - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) aka MemCheck_start(), - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) aka MemCheck_stop(); - "off" is now the default. - The library internally uses - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) aka MemCheck_off(), - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) aka MemCheck_on() - to disable memory-checking temporarily. - - Some inconsistent states that previously were possible (and were - even the default) are now avoided. - - -DCRYPTO_MDEBUG_TIME is new and additionally stores the current time - with each memory chunk allocated; this is occasionally more helpful - than just having a counter. - - -DCRYPTO_MDEBUG_THREAD is also new and adds the thread ID. - - -DCRYPTO_MDEBUG_ALL enables all of the above, plus any future - extensions. - [Bodo Moeller] - - *) Introduce "mode" for SSL structures (with defaults in SSL_CTX), - which largely parallels "options", but is for changing API behaviour, - whereas "options" are about protocol behaviour. - Initial "mode" flags are: - - SSL_MODE_ENABLE_PARTIAL_WRITE Allow SSL_write to report success when - a single record has been written. - SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Don't insist that SSL_write - retries use the same buffer location. - (But all of the contents must be - copied!) - [Bodo Moeller] - - *) Bugfix: SSL_set_options ignored its parameter, only SSL_CTX_set_options - worked. - - *) Fix problems with no-hmac etc. - [Ulf Möller, pointed out by Brian Wellington ] - - *) New functions RSA_get_default_method(), RSA_set_method() and - RSA_get_method(). These allows replacement of RSA_METHODs without having - to mess around with the internals of an RSA structure. - [Steve Henson] - - *) Fix memory leaks in DSA_do_sign and DSA_is_prime. - Also really enable memory leak checks in openssl.c and in some - test programs. - [Chad C. Mulligan, Bodo Moeller] - - *) Fix a bug in d2i_ASN1_INTEGER() and i2d_ASN1_INTEGER() which can mess - up the length of negative integers. This has now been simplified to just - store the length when it is first determined and use it later, rather - than trying to keep track of where data is copied and updating it to - point to the end. - [Steve Henson, reported by Brien Wheeler - ] - - *) Add a new function PKCS7_signatureVerify. This allows the verification - of a PKCS#7 signature but with the signing certificate passed to the - function itself. This contrasts with PKCS7_dataVerify which assumes the - certificate is present in the PKCS#7 structure. This isn't always the - case: certificates can be omitted from a PKCS#7 structure and be - distributed by "out of band" means (such as a certificate database). - [Steve Henson] - - *) Complete the PEM_* macros with DECLARE_PEM versions to replace the - function prototypes in pem.h, also change util/mkdef.pl to add the - necessary function names. - [Steve Henson] - - *) mk1mf.pl (used by Windows builds) did not properly read the - options set by Configure in the top level Makefile, and Configure - was not even able to write more than one option correctly. - Fixed, now "no-idea no-rc5 -DCRYPTO_MDEBUG" etc. works as intended. - [Bodo Moeller] - - *) New functions CONF_load_bio() and CONF_load_fp() to allow a config - file to be loaded from a BIO or FILE pointer. The BIO version will - for example allow memory BIOs to contain config info. - [Steve Henson] - - *) New function "CRYPTO_num_locks" that returns CRYPTO_NUM_LOCKS. - Whoever hopes to achieve shared-library compatibility across versions - must use this, not the compile-time macro. - (Exercise 0.9.4: Which is the minimum library version required by - such programs?) - Note: All this applies only to multi-threaded programs, others don't - need locks. - [Bodo Moeller] - - *) Add missing case to s3_clnt.c state machine -- one of the new SSL tests - through a BIO pair triggered the default case, i.e. - SSLerr(...,SSL_R_UNKNOWN_STATE). - [Bodo Moeller] - - *) New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications - can use the SSL library even if none of the specific BIOs is - appropriate. - [Bodo Moeller] - - *) Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value - for the encoded length. - [Jeon KyoungHo ] - - *) Add initial documentation of the X509V3 functions. - [Steve Henson] - - *) Add a new pair of functions PEM_write_PKCS8PrivateKey() and - PEM_write_bio_PKCS8PrivateKey() that are equivalent to - PEM_write_PrivateKey() and PEM_write_bio_PrivateKey() but use the more - secure PKCS#8 private key format with a high iteration count. - [Steve Henson] - - *) Fix determination of Perl interpreter: A perl or perl5 - _directory_ in $PATH was also accepted as the interpreter. - [Ralf S. Engelschall] - - *) Fix demos/sign/sign.c: well there wasn't anything strictly speaking - wrong with it but it was very old and did things like calling - PEM_ASN1_read() directly and used MD5 for the hash not to mention some - unusual formatting. - [Steve Henson] - - *) Fix demos/selfsign.c: it used obsolete and deleted functions, changed - to use the new extension code. - [Steve Henson] - - *) Implement the PEM_read/PEM_write functions in crypto/pem/pem_all.c - with macros. This should make it easier to change their form, add extra - arguments etc. Fix a few PEM prototypes which didn't have cipher as a - constant. - [Steve Henson] - - *) Add to configuration table a new entry that can specify an alternative - name for unistd.h (for pre-POSIX systems); we need this for NeXTstep, - according to Mark Crispin . - [Bodo Moeller] - -#if 0 - *) DES CBC did not update the IV. Weird. - [Ben Laurie] -#else - des_cbc_encrypt does not update the IV, but des_ncbc_encrypt does. - Changing the behaviour of the former might break existing programs -- - where IV updating is needed, des_ncbc_encrypt can be used. -#endif - - *) When bntest is run from "make test" it drives bc to check its - calculations, as well as internally checking them. If an internal check - fails, it needs to cause bc to give a non-zero result or make test carries - on without noticing the failure. Fixed. - [Ben Laurie] - - *) DES library cleanups. - [Ulf Möller] - - *) Add support for PKCS#5 v2.0 PBE algorithms. This will permit PKCS#8 to be - used with any cipher unlike PKCS#5 v1.5 which can at most handle 64 bit - ciphers. NOTE: although the key derivation function has been verified - against some published test vectors it has not been extensively tested - yet. Added a -v2 "cipher" option to pkcs8 application to allow the use - of v2.0. - [Steve Henson] - - *) Instead of "mkdir -p", which is not fully portable, use new - Perl script "util/mkdir-p.pl". - [Bodo Moeller] - - *) Rewrite the way password based encryption (PBE) is handled. It used to - assume that the ASN1 AlgorithmIdentifier parameter was a PBEParameter - structure. This was true for the PKCS#5 v1.5 and PKCS#12 PBE algorithms - but doesn't apply to PKCS#5 v2.0 where it can be something else. Now - the 'parameter' field of the AlgorithmIdentifier is passed to the - underlying key generation function so it must do its own ASN1 parsing. - This has also changed the EVP_PBE_CipherInit() function which now has a - 'parameter' argument instead of literal salt and iteration count values - and the function EVP_PBE_ALGOR_CipherInit() has been deleted. - [Steve Henson] - - *) Support for PKCS#5 v1.5 compatible password based encryption algorithms - and PKCS#8 functionality. New 'pkcs8' application linked to openssl. - Needed to change the PEM_STRING_EVP_PKEY value which was just "PRIVATE - KEY" because this clashed with PKCS#8 unencrypted string. Since this - value was just used as a "magic string" and not used directly its - value doesn't matter. - [Steve Henson] - - *) Introduce some semblance of const correctness to BN. Shame C doesn't - support mutable. - [Ben Laurie] - - *) "linux-sparc64" configuration (ultrapenguin). - [Ray Miller ] - "linux-sparc" configuration. - [Christian Forster ] - - *) config now generates no-xxx options for missing ciphers. - [Ulf Möller] - - *) Support the EBCDIC character set (work in progress). - File ebcdic.c not yet included because it has a different license. - [Martin Kraemer ] - - *) Support BS2000/OSD-POSIX. - [Martin Kraemer ] - - *) Make callbacks for key generation use void * instead of char *. - [Ben Laurie] - - *) Make S/MIME samples compile (not yet tested). - [Ben Laurie] - - *) Additional typesafe stacks. - [Ben Laurie] - - *) New configuration variants "bsdi-elf-gcc" (BSD/OS 4.x). - [Bodo Moeller] - - - Changes between 0.9.3 and 0.9.3a [29 May 1999] - - *) New configuration variant "sco5-gcc". - - *) Updated some demos. - [Sean O Riordain, Wade Scholine] - - *) Add missing BIO_free at exit of pkcs12 application. - [Wu Zhigang] - - *) Fix memory leak in conf.c. - [Steve Henson] - - *) Updates for Win32 to assembler version of MD5. - [Steve Henson] - - *) Set #! path to perl in apps/der_chop to where we found it - instead of using a fixed path. - [Bodo Moeller] - - *) SHA library changes for irix64-mips4-cc. - [Andy Polyakov] - - *) Improvements for VMS support. - [Richard Levitte] - - - Changes between 0.9.2b and 0.9.3 [24 May 1999] - - *) Bignum library bug fix. IRIX 6 passes "make test" now! - This also avoids the problems with SC4.2 and unpatched SC5. - [Andy Polyakov ] - - *) New functions sk_num, sk_value and sk_set to replace the previous macros. - These are required because of the typesafe stack would otherwise break - existing code. If old code used a structure member which used to be STACK - and is now STACK_OF (for example cert in a PKCS7_SIGNED structure) with - sk_num or sk_value it would produce an error because the num, data members - are not present in STACK_OF. Now it just produces a warning. sk_set - replaces the old method of assigning a value to sk_value - (e.g. sk_value(x, i) = y) which the library used in a few cases. Any code - that does this will no longer work (and should use sk_set instead) but - this could be regarded as a "questionable" behaviour anyway. - [Steve Henson] - - *) Fix most of the other PKCS#7 bugs. The "experimental" code can now - correctly handle encrypted S/MIME data. - [Steve Henson] - - *) Change type of various DES function arguments from des_cblock - (which means, in function argument declarations, pointer to char) - to des_cblock * (meaning pointer to array with 8 char elements), - which allows the compiler to do more typechecking; it was like - that back in SSLeay, but with lots of ugly casts. - - Introduce new type const_des_cblock. - [Bodo Moeller] - - *) Reorganise the PKCS#7 library and get rid of some of the more obvious - problems: find RecipientInfo structure that matches recipient certificate - and initialise the ASN1 structures properly based on passed cipher. - [Steve Henson] - - *) Belatedly make the BN tests actually check the results. - [Ben Laurie] - - *) Fix the encoding and decoding of negative ASN1 INTEGERS and conversion - to and from BNs: it was completely broken. New compilation option - NEG_PUBKEY_BUG to allow for some broken certificates that encode public - key elements as negative integers. - [Steve Henson] - - *) Reorganize and speed up MD5. - [Andy Polyakov ] - - *) VMS support. - [Richard Levitte ] - - *) New option -out to asn1parse to allow the parsed structure to be - output to a file. This is most useful when combined with the -strparse - option to examine the output of things like OCTET STRINGS. - [Steve Henson] - - *) Make SSL library a little more fool-proof by not requiring any longer - that SSL_set_{accept,connect}_state be called before - SSL_{accept,connect} may be used (SSL_set_..._state is omitted - in many applications because usually everything *appeared* to work as - intended anyway -- now it really works as intended). - [Bodo Moeller] - - *) Move openssl.cnf out of lib/. - [Ulf Möller] - - *) Fix various things to let OpenSSL even pass ``egcc -pipe -O2 -Wall - -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes - -Wmissing-declarations -Wnested-externs -Winline'' with EGCS 1.1.2+ - [Ralf S. Engelschall] - - *) Various fixes to the EVP and PKCS#7 code. It may now be able to - handle PKCS#7 enveloped data properly. - [Sebastian Akerman , modified by Steve] - - *) Create a duplicate of the SSL_CTX's CERT in SSL_new instead of - copying pointers. The cert_st handling is changed by this in - various ways (and thus what used to be known as ctx->default_cert - is now called ctx->cert, since we don't resort to s->ctx->[default_]cert - any longer when s->cert does not give us what we need). - ssl_cert_instantiate becomes obsolete by this change. - As soon as we've got the new code right (possibly it already is?), - we have solved a couple of bugs of the earlier code where s->cert - was used as if it could not have been shared with other SSL structures. - - Note that using the SSL API in certain dirty ways now will result - in different behaviour than observed with earlier library versions: - Changing settings for an SSL_CTX *ctx after having done s = SSL_new(ctx) - does not influence s as it used to. - - In order to clean up things more thoroughly, inside SSL_SESSION - we don't use CERT any longer, but a new structure SESS_CERT - that holds per-session data (if available); currently, this is - the peer's certificate chain and, for clients, the server's certificate - and temporary key. CERT holds only those values that can have - meaningful defaults in an SSL_CTX. - [Bodo Moeller] - - *) New function X509V3_EXT_i2d() to create an X509_EXTENSION structure - from the internal representation. Various PKCS#7 fixes: remove some - evil casts and set the enc_dig_alg field properly based on the signing - key type. - [Steve Henson] - - *) Allow PKCS#12 password to be set from the command line or the - environment. Let 'ca' get its config file name from the environment - variables "OPENSSL_CONF" or "SSLEAY_CONF" (for consistency with 'req' - and 'x509'). - [Steve Henson] - - *) Allow certificate policies extension to use an IA5STRING for the - organization field. This is contrary to the PKIX definition but - VeriSign uses it and IE5 only recognises this form. Document 'x509' - extension option. - [Steve Henson] - - *) Add PEDANTIC compiler flag to allow compilation with gcc -pedantic, - without disallowing inline assembler and the like for non-pedantic builds. - [Ben Laurie] - - *) Support Borland C++ builder. - [Janez Jere , modified by Ulf Möller] - - *) Support Mingw32. - [Ulf Möller] - - *) SHA-1 cleanups and performance enhancements. - [Andy Polyakov ] - - *) Sparc v8plus assembler for the bignum library. - [Andy Polyakov ] - - *) Accept any -xxx and +xxx compiler options in Configure. - [Ulf Möller] - - *) Update HPUX configuration. - [Anonymous] - - *) Add missing sk__unshift() function to safestack.h - [Ralf S. Engelschall] - - *) New function SSL_CTX_use_certificate_chain_file that sets the - "extra_cert"s in addition to the certificate. (This makes sense - only for "PEM" format files, as chains as a whole are not - DER-encoded.) - [Bodo Moeller] - - *) Support verify_depth from the SSL API. - x509_vfy.c had what can be considered an off-by-one-error: - Its depth (which was not part of the external interface) - was actually counting the number of certificates in a chain; - now it really counts the depth. - [Bodo Moeller] - - *) Bugfix in crypto/x509/x509_cmp.c: The SSLerr macro was used - instead of X509err, which often resulted in confusing error - messages since the error codes are not globally unique - (e.g. an alleged error in ssl3_accept when a certificate - didn't match the private key). - - *) New function SSL_CTX_set_session_id_context that allows to set a default - value (so that you don't need SSL_set_session_id_context for each - connection using the SSL_CTX). - [Bodo Moeller] - - *) OAEP decoding bug fix. - [Ulf Möller] - - *) Support INSTALL_PREFIX for package builders, as proposed by - David Harris. - [Bodo Moeller] - - *) New Configure options "threads" and "no-threads". For systems - where the proper compiler options are known (currently Solaris - and Linux), "threads" is the default. - [Bodo Moeller] - - *) New script util/mklink.pl as a faster substitute for util/mklink.sh. - [Bodo Moeller] - - *) Install various scripts to $(OPENSSLDIR)/misc, not to - $(INSTALLTOP)/bin -- they shouldn't clutter directories - such as /usr/local/bin. - [Bodo Moeller] - - *) "make linux-shared" to build shared libraries. - [Niels Poppe ] - - *) New Configure option no- (rsa, idea, rc5, ...). - [Ulf Möller] - - *) Add the PKCS#12 API documentation to openssl.txt. Preliminary support for - extension adding in x509 utility. - [Steve Henson] - - *) Remove NOPROTO sections and error code comments. - [Ulf Möller] - - *) Partial rewrite of the DEF file generator to now parse the ANSI - prototypes. - [Steve Henson] - - *) New Configure options --prefix=DIR and --openssldir=DIR. - [Ulf Möller] - - *) Complete rewrite of the error code script(s). It is all now handled - by one script at the top level which handles error code gathering, - header rewriting and C source file generation. It should be much better - than the old method: it now uses a modified version of Ulf's parser to - read the ANSI prototypes in all header files (thus the old K&R definitions - aren't needed for error creation any more) and do a better job of - translating function codes into names. The old 'ASN1 error code embedded - in a comment' is no longer necessary and it doesn't use .err files which - have now been deleted. Also the error code call doesn't have to appear all - on one line (which resulted in some large lines...). - [Steve Henson] - - *) Change #include filenames from to . - [Bodo Moeller] - - *) Change behaviour of ssl2_read when facing length-0 packets: Don't return - 0 (which usually indicates a closed connection), but continue reading. - [Bodo Moeller] - - *) Fix some race conditions. - [Bodo Moeller] - - *) Add support for CRL distribution points extension. Add Certificate - Policies and CRL distribution points documentation. - [Steve Henson] - - *) Move the autogenerated header file parts to crypto/opensslconf.h. - [Ulf Möller] - - *) Fix new 56-bit DES export ciphersuites: they were using 7 bytes instead of - 8 of keying material. Merlin has also confirmed interop with this fix - between OpenSSL and Baltimore C/SSL 2.0 and J/SSL 2.0. - [Merlin Hughes ] - - *) Fix lots of warnings. - [Richard Levitte ] - - *) In add_cert_dir() in crypto/x509/by_dir.c, break out of the loop if - the directory spec didn't end with a LIST_SEPARATOR_CHAR. - [Richard Levitte ] - - *) Fix problems with sizeof(long) == 8. - [Andy Polyakov ] - - *) Change functions to ANSI C. - [Ulf Möller] - - *) Fix typos in error codes. - [Martin Kraemer , Ulf Möller] - - *) Remove defunct assembler files from Configure. - [Ulf Möller] - - *) SPARC v8 assembler BIGNUM implementation. - [Andy Polyakov ] - - *) Support for Certificate Policies extension: both print and set. - Various additions to support the r2i method this uses. - [Steve Henson] - - *) A lot of constification, and fix a bug in X509_NAME_oneline() that could - return a const string when you are expecting an allocated buffer. - [Ben Laurie] - - *) Add support for ASN1 types UTF8String and VISIBLESTRING, also the CHOICE - types DirectoryString and DisplayText. - [Steve Henson] - - *) Add code to allow r2i extensions to access the configuration database, - add an LHASH database driver and add several ctx helper functions. - [Steve Henson] - - *) Fix an evil bug in bn_expand2() which caused various BN functions to - fail when they extended the size of a BIGNUM. - [Steve Henson] - - *) Various utility functions to handle SXNet extension. Modify mkdef.pl to - support typesafe stack. - [Steve Henson] - - *) Fix typo in SSL_[gs]et_options(). - [Nils Frostberg ] - - *) Delete various functions and files that belonged to the (now obsolete) - old X509V3 handling code. - [Steve Henson] - - *) New Configure option "rsaref". - [Ulf Möller] - - *) Don't auto-generate pem.h. - [Bodo Moeller] - - *) Introduce type-safe ASN.1 SETs. - [Ben Laurie] - - *) Convert various additional casted stacks to type-safe STACK_OF() variants. - [Ben Laurie, Ralf S. Engelschall, Steve Henson] - - *) Introduce type-safe STACKs. This will almost certainly break lots of code - that links with OpenSSL (well at least cause lots of warnings), but fear - not: the conversion is trivial, and it eliminates loads of evil casts. A - few STACKed things have been converted already. Feel free to convert more. - In the fullness of time, I'll do away with the STACK type altogether. - [Ben Laurie] - - *) Add `openssl ca -revoke ' facility which revokes a certificate - specified in by updating the entry in the index.txt file. - This way one no longer has to edit the index.txt file manually for - revoking a certificate. The -revoke option does the gory details now. - [Massimiliano Pala , Ralf S. Engelschall] - - *) Fix `openssl crl -noout -text' combination where `-noout' killed the - `-text' option at all and this way the `-noout -text' combination was - inconsistent in `openssl crl' with the friends in `openssl x509|rsa|dsa'. - [Ralf S. Engelschall] - - *) Make sure a corresponding plain text error message exists for the - X509_V_ERR_CERT_REVOKED/23 error number which can occur when a - verify callback function determined that a certificate was revoked. - [Ralf S. Engelschall] - - *) Bugfix: In test/testenc, don't test "openssl " for - ciphers that were excluded, e.g. by -DNO_IDEA. Also, test - all available ciphers including rc5, which was forgotten until now. - In order to let the testing shell script know which algorithms - are available, a new (up to now undocumented) command - "openssl list-cipher-commands" is used. - [Bodo Moeller] - - *) Bugfix: s_client occasionally would sleep in select() when - it should have checked SSL_pending() first. - [Bodo Moeller] - - *) New functions DSA_do_sign and DSA_do_verify to provide access to - the raw DSA values prior to ASN.1 encoding. - [Ulf Möller] - - *) Tweaks to Configure - [Niels Poppe ] - - *) Add support for PKCS#5 v2.0 ASN1 PBES2 structures. No other support, - yet... - [Steve Henson] - - *) New variables $(RANLIB) and $(PERL) in the Makefiles. - [Ulf Möller] - - *) New config option to avoid instructions that are illegal on the 80386. - The default code is faster, but requires at least a 486. - [Ulf Möller] - - *) Got rid of old SSL2_CLIENT_VERSION (inconsistently used) and - SSL2_SERVER_VERSION (not used at all) macros, which are now the - same as SSL2_VERSION anyway. - [Bodo Moeller] - - *) New "-showcerts" option for s_client. - [Bodo Moeller] - - *) Still more PKCS#12 integration. Add pkcs12 application to openssl - application. Various cleanups and fixes. - [Steve Henson] - - *) More PKCS#12 integration. Add new pkcs12 directory with Makefile.ssl and - modify error routines to work internally. Add error codes and PBE init - to library startup routines. - [Steve Henson] - - *) Further PKCS#12 integration. Added password based encryption, PKCS#8 and - packing functions to asn1 and evp. Changed function names and error - codes along the way. - [Steve Henson] - - *) PKCS12 integration: and so it begins... First of several patches to - slowly integrate PKCS#12 functionality into OpenSSL. Add PKCS#12 - objects to objects.h - [Steve Henson] - - *) Add a new 'indent' option to some X509V3 extension code. Initial ASN1 - and display support for Thawte strong extranet extension. - [Steve Henson] - - *) Add LinuxPPC support. - [Jeff Dubrule ] - - *) Get rid of redundant BN file bn_mulw.c, and rename bn_div64 to - bn_div_words in alpha.s. - [Hannes Reinecke and Ben Laurie] - - *) Make sure the RSA OAEP test is skipped under -DRSAref because - OAEP isn't supported when OpenSSL is built with RSAref. - [Ulf Moeller ] - - *) Move definitions of IS_SET/IS_SEQUENCE inside crypto/asn1/asn1.h - so they no longer are missing under -DNOPROTO. - [Soren S. Jorvang ] - - - Changes between 0.9.1c and 0.9.2b [22 Mar 1999] - - *) Make SSL_get_peer_cert_chain() work in servers. Unfortunately, it still - doesn't work when the session is reused. Coming soon! - [Ben Laurie] - - *) Fix a security hole, that allows sessions to be reused in the wrong - context thus bypassing client cert protection! All software that uses - client certs and session caches in multiple contexts NEEDS PATCHING to - allow session reuse! A fuller solution is in the works. - [Ben Laurie, problem pointed out by Holger Reif, Bodo Moeller (and ???)] - - *) Some more source tree cleanups (removed obsolete files - crypto/bf/asm/bf586.pl, test/test.txt and crypto/sha/asm/f.s; changed - permission on "config" script to be executable) and a fix for the INSTALL - document. - [Ulf Moeller ] - - *) Remove some legacy and erroneous uses of malloc, free instead of - Malloc, Free. - [Lennart Bang , with minor changes by Steve] - - *) Make rsa_oaep_test return non-zero on error. - [Ulf Moeller ] - - *) Add support for native Solaris shared libraries. Configure - solaris-sparc-sc4-pic, make, then run shlib/solaris-sc4.sh. It'd be nice - if someone would make that last step automatic. - [Matthias Loepfe ] - - *) ctx_size was not built with the right compiler during "make links". Fixed. - [Ben Laurie] - - *) Change the meaning of 'ALL' in the cipher list. It now means "everything - except NULL ciphers". This means the default cipher list will no longer - enable NULL ciphers. They need to be specifically enabled e.g. with - the string "DEFAULT:eNULL". - [Steve Henson] - - *) Fix to RSA private encryption routines: if p < q then it would - occasionally produce an invalid result. This will only happen with - externally generated keys because OpenSSL (and SSLeay) ensure p > q. - [Steve Henson] - - *) Be less restrictive and allow also `perl util/perlpath.pl - /path/to/bin/perl' in addition to `perl util/perlpath.pl /path/to/bin', - because this way one can also use an interpreter named `perl5' (which is - usually the name of Perl 5.xxx on platforms where an Perl 4.x is still - installed as `perl'). - [Matthias Loepfe ] - - *) Let util/clean-depend.pl work also with older Perl 5.00x versions. - [Matthias Loepfe ] - - *) Fix Makefile.org so CC,CFLAG etc are passed to 'make links' add - advapi32.lib to Win32 build and change the pem test comparison - to fc.exe (thanks to Ulrich Kroener for the - suggestion). Fix misplaced ASNI prototypes and declarations in evp.h - and crypto/des/ede_cbcm_enc.c. - [Steve Henson] - - *) DES quad checksum was broken on big-endian architectures. Fixed. - [Ben Laurie] - - *) Comment out two functions in bio.h that aren't implemented. Fix up the - Win32 test batch file so it (might) work again. The Win32 test batch file - is horrible: I feel ill.... - [Steve Henson] - - *) Move various #ifdefs around so NO_SYSLOG, NO_DIRENT etc are now selected - in e_os.h. Audit of header files to check ANSI and non ANSI - sections: 10 functions were absent from non ANSI section and not exported - from Windows DLLs. Fixed up libeay.num for new functions. - [Steve Henson] - - *) Make `openssl version' output lines consistent. - [Ralf S. Engelschall] - - *) Fix Win32 symbol export lists for BIO functions: Added - BIO_get_ex_new_index, BIO_get_ex_num, BIO_get_ex_data and BIO_set_ex_data - to ms/libeay{16,32}.def. - [Ralf S. Engelschall] - - *) Second round of fixing the OpenSSL perl/ stuff. It now at least compiled - fine under Unix and passes some trivial tests I've now added. But the - whole stuff is horribly incomplete, so a README.1ST with a disclaimer was - added to make sure no one expects that this stuff really works in the - OpenSSL 0.9.2 release. Additionally I've started to clean the XS sources - up and fixed a few little bugs and inconsistencies in OpenSSL.{pm,xs} and - openssl_bio.xs. - [Ralf S. Engelschall] - - *) Fix the generation of two part addresses in perl. - [Kenji Miyake , integrated by Ben Laurie] - - *) Add config entry for Linux on MIPS. - [John Tobey ] - - *) Make links whenever Configure is run, unless we are on Windoze. - [Ben Laurie] - - *) Permit extensions to be added to CRLs using crl_section in openssl.cnf. - Currently only issuerAltName and AuthorityKeyIdentifier make any sense - in CRLs. - [Steve Henson] - - *) Add a useful kludge to allow package maintainers to specify compiler and - other platforms details on the command line without having to patch the - Configure script every time: One now can use ``perl Configure - :
'', i.e. platform ids are allowed to have details appended - to them (separated by colons). This is treated as there would be a static - pre-configured entry in Configure's %table under key with value -
and ``perl Configure '' is called. So, when you want to - perform a quick test-compile under FreeBSD 3.1 with pgcc and without - assembler stuff you can use ``perl Configure "FreeBSD-elf:pgcc:-O6:::"'' - now, which overrides the FreeBSD-elf entry on-the-fly. - [Ralf S. Engelschall] - - *) Disable new TLS1 ciphersuites by default: they aren't official yet. - [Ben Laurie] - - *) Allow DSO flags like -fpic, -fPIC, -KPIC etc. to be specified - on the `perl Configure ...' command line. This way one can compile - OpenSSL libraries with Position Independent Code (PIC) which is needed - for linking it into DSOs. - [Ralf S. Engelschall] - - *) Remarkably, export ciphers were totally broken and no-one had noticed! - Fixed. - [Ben Laurie] - - *) Cleaned up the LICENSE document: The official contact for any license - questions now is the OpenSSL core team under openssl-core@openssl.org. - And add a paragraph about the dual-license situation to make sure people - recognize that _BOTH_ the OpenSSL license _AND_ the SSLeay license apply - to the OpenSSL toolkit. - [Ralf S. Engelschall] - - *) General source tree makefile cleanups: Made `making xxx in yyy...' - display consistent in the source tree and replaced `/bin/rm' by `rm'. - Additionally cleaned up the `make links' target: Remove unnecessary - semicolons, subsequent redundant removes, inline point.sh into mklink.sh - to speed processing and no longer clutter the display with confusing - stuff. Instead only the actually done links are displayed. - [Ralf S. Engelschall] - - *) Permit null encryption ciphersuites, used for authentication only. It used - to be necessary to set the preprocessor define SSL_ALLOW_ENULL to do this. - It is now necessary to set SSL_FORBID_ENULL to prevent the use of null - encryption. - [Ben Laurie] - - *) Add a bunch of fixes to the PKCS#7 stuff. It used to sometimes reorder - signed attributes when verifying signatures (this would break them), - the detached data encoding was wrong and public keys obtained using - X509_get_pubkey() weren't freed. - [Steve Henson] - - *) Add text documentation for the BUFFER functions. Also added a work around - to a Win95 console bug. This was triggered by the password read stuff: the - last character typed gets carried over to the next fread(). If you were - generating a new cert request using 'req' for example then the last - character of the passphrase would be CR which would then enter the first - field as blank. - [Steve Henson] - - *) Added the new `Includes OpenSSL Cryptography Software' button as - doc/openssl_button.{gif,html} which is similar in style to the old SSLeay - button and can be used by applications based on OpenSSL to show the - relationship to the OpenSSL project. - [Ralf S. Engelschall] - - *) Remove confusing variables in function signatures in files - ssl/ssl_lib.c and ssl/ssl.h. - [Lennart Bong ] - - *) Don't install bss_file.c under PREFIX/include/ - [Lennart Bong ] - - *) Get the Win32 compile working again. Modify mkdef.pl so it can handle - functions that return function pointers and has support for NT specific - stuff. Fix mk1mf.pl and VC-32.pl to support NT differences also. Various - #ifdef WIN32 and WINNTs sprinkled about the place and some changes from - unsigned to signed types: this was killing the Win32 compile. - [Steve Henson] - - *) Add new certificate file to stack functions, - SSL_add_dir_cert_subjects_to_stack() and - SSL_add_file_cert_subjects_to_stack(). These largely supplant - SSL_load_client_CA_file(), and can be used to add multiple certs easily - to a stack (usually this is then handed to SSL_CTX_set_client_CA_list()). - This means that Apache-SSL and similar packages don't have to mess around - to add as many CAs as they want to the preferred list. - [Ben Laurie] - - *) Experiment with doxygen documentation. Currently only partially applied to - ssl/ssl_lib.c. - See http://www.stack.nl/~dimitri/doxygen/index.html, and run doxygen with - openssl.doxy as the configuration file. - [Ben Laurie] - - *) Get rid of remaining C++-style comments which strict C compilers hate. - [Ralf S. Engelschall, pointed out by Carlos Amengual] - - *) Changed BN_RECURSION in bn_mont.c to BN_RECURSION_MONT so it is not - compiled in by default: it has problems with large keys. - [Steve Henson] - - *) Add a bunch of SSL_xxx() functions for configuring the temporary RSA and - DH private keys and/or callback functions which directly correspond to - their SSL_CTX_xxx() counterparts but work on a per-connection basis. This - is needed for applications which have to configure certificates on a - per-connection basis (e.g. Apache+mod_ssl) instead of a per-context basis - (e.g. s_server). - For the RSA certificate situation is makes no difference, but - for the DSA certificate situation this fixes the "no shared cipher" - problem where the OpenSSL cipher selection procedure failed because the - temporary keys were not overtaken from the context and the API provided - no way to reconfigure them. - The new functions now let applications reconfigure the stuff and they - are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh, - SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback. Additionally a new - non-public-API function ssl_cert_instantiate() is used as a helper - function and also to reduce code redundancy inside ssl_rsa.c. - [Ralf S. Engelschall] - - *) Move s_server -dcert and -dkey options out of the undocumented feature - area because they are useful for the DSA situation and should be - recognized by the users. - [Ralf S. Engelschall] - - *) Fix the cipher decision scheme for export ciphers: the export bits are - *not* within SSL_MKEY_MASK or SSL_AUTH_MASK, they are within - SSL_EXP_MASK. So, the original variable has to be used instead of the - already masked variable. - [Richard Levitte ] - - *) Fix 'port' variable from `int' to `unsigned int' in crypto/bio/b_sock.c - [Richard Levitte ] - - *) Change type of another md_len variable in pk7_doit.c:PKCS7_dataFinal() - from `int' to `unsigned int' because it's a length and initialized by - EVP_DigestFinal() which expects an `unsigned int *'. - [Richard Levitte ] - - *) Don't hard-code path to Perl interpreter on shebang line of Configure - script. Instead use the usual Shell->Perl transition trick. - [Ralf S. Engelschall] - - *) Make `openssl x509 -noout -modulus' functional also for DSA certificates - (in addition to RSA certificates) to match the behaviour of `openssl dsa - -noout -modulus' as it's already the case for `openssl rsa -noout - -modulus'. For RSA the -modulus is the real "modulus" while for DSA - currently the public key is printed (a decision which was already done by - `openssl dsa -modulus' in the past) which serves a similar purpose. - Additionally the NO_RSA no longer completely removes the whole -modulus - option; it now only avoids using the RSA stuff. Same applies to NO_DSA - now, too. - [Ralf S. Engelschall] - - *) Add Arne Ansper's reliable BIO - this is an encrypted, block-digested - BIO. See the source (crypto/evp/bio_ok.c) for more info. - [Arne Ansper ] - - *) Dump the old yucky req code that tried (and failed) to allow raw OIDs - to be added. Now both 'req' and 'ca' can use new objects defined in the - config file. - [Steve Henson] - - *) Add cool BIO that does syslog (or event log on NT). - [Arne Ansper , integrated by Ben Laurie] - - *) Add support for new TLS ciphersuites, TLS_RSA_EXPORT56_WITH_RC4_56_MD5, - TLS_RSA_EXPORT56_WITH_RC2_CBC_56_MD5 and - TLS_RSA_EXPORT56_WITH_DES_CBC_SHA, as specified in "56-bit Export Cipher - Suites For TLS", draft-ietf-tls-56-bit-ciphersuites-00.txt. - [Ben Laurie] - - *) Add preliminary config info for new extension code. - [Steve Henson] - - *) Make RSA_NO_PADDING really use no padding. - [Ulf Moeller ] - - *) Generate errors when private/public key check is done. - [Ben Laurie] - - *) Overhaul for 'crl' utility. New function X509_CRL_print. Partial support - for some CRL extensions and new objects added. - [Steve Henson] - - *) Really fix the ASN1 IMPLICIT bug this time... Partial support for private - key usage extension and fuller support for authority key id. - [Steve Henson] - - *) Add OAEP encryption for the OpenSSL crypto library. OAEP is the improved - padding method for RSA, which is recommended for new applications in PKCS - #1 v2.0 (RFC 2437, October 1998). - OAEP (Optimal Asymmetric Encryption Padding) has better theoretical - foundations than the ad-hoc padding used in PKCS #1 v1.5. It is secure - against Bleichbacher's attack on RSA. - [Ulf Moeller , reformatted, corrected and integrated by - Ben Laurie] - - *) Updates to the new SSL compression code - [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)] - - *) Fix so that the version number in the master secret, when passed - via RSA, checks that if TLS was proposed, but we roll back to SSLv3 - (because the server will not accept higher), that the version number - is 0x03,0x01, not 0x03,0x00 - [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)] - - *) Run extensive memory leak checks on SSL apps. Fixed *lots* of memory - leaks in ssl/ relating to new X509_get_pubkey() behaviour. Also fixes - in apps/ and an unrelated leak in crypto/dsa/dsa_vrf.c - [Steve Henson] - - *) Support for RAW extensions where an arbitrary extension can be - created by including its DER encoding. See apps/openssl.cnf for - an example. - [Steve Henson] - - *) Make sure latest Perl versions don't interpret some generated C array - code as Perl array code in the crypto/err/err_genc.pl script. - [Lars Weber <3weber@informatik.uni-hamburg.de>] - - *) Modify ms/do_ms.bat to not generate assembly language makefiles since - not many people have the assembler. Various Win32 compilation fixes and - update to the INSTALL.W32 file with (hopefully) more accurate Win32 - build instructions. - [Steve Henson] - - *) Modify configure script 'Configure' to automatically create crypto/date.h - file under Win32 and also build pem.h from pem.org. New script - util/mkfiles.pl to create the MINFO file on environments that can't do a - 'make files': perl util/mkfiles.pl >MINFO should work. - [Steve Henson] - - *) Major rework of DES function declarations, in the pursuit of correctness - and purity. As a result, many evil casts evaporated, and some weirdness, - too. You may find this causes warnings in your code. Zapping your evil - casts will probably fix them. Mostly. - [Ben Laurie] - - *) Fix for a typo in asn1.h. Bug fix to object creation script - obj_dat.pl. It considered a zero in an object definition to mean - "end of object": none of the objects in objects.h have any zeros - so it wasn't spotted. - [Steve Henson, reported by Erwann ABALEA ] - - *) Add support for Triple DES Cipher Block Chaining with Output Feedback - Masking (CBCM). In the absence of test vectors, the best I have been able - to do is check that the decrypt undoes the encrypt, so far. Send me test - vectors if you have them. - [Ben Laurie] - - *) Correct calculation of key length for export ciphers (too much space was - allocated for null ciphers). This has not been tested! - [Ben Laurie] - - *) Modifications to the mkdef.pl for Win32 DEF file creation. The usage - message is now correct (it understands "crypto" and "ssl" on its - command line). There is also now an "update" option. This will update - the util/ssleay.num and util/libeay.num files with any new functions. - If you do a: - perl util/mkdef.pl crypto ssl update - it will update them. - [Steve Henson] - - *) Overhauled the Perl interface (perl/*): - - ported BN stuff to OpenSSL's different BN library - - made the perl/ source tree CVS-aware - - renamed the package from SSLeay to OpenSSL (the files still contain - their history because I've copied them in the repository) - - removed obsolete files (the test scripts will be replaced - by better Test::Harness variants in the future) - [Ralf S. Engelschall] - - *) First cut for a very conservative source tree cleanup: - 1. merge various obsolete readme texts into doc/ssleay.txt - where we collect the old documents and readme texts. - 2. remove the first part of files where I'm already sure that we no - longer need them because of three reasons: either they are just temporary - files which were left by Eric or they are preserved original files where - I've verified that the diff is also available in the CVS via "cvs diff - -rSSLeay_0_8_1b" or they were renamed (as it was definitely the case for - the crypto/md/ stuff). - [Ralf S. Engelschall] - - *) More extension code. Incomplete support for subject and issuer alt - name, issuer and authority key id. Change the i2v function parameters - and add an extra 'crl' parameter in the X509V3_CTX structure: guess - what that's for :-) Fix to ASN1 macro which messed up - IMPLICIT tag and add f_enum.c which adds a2i, i2a for ENUMERATED. - [Steve Henson] - - *) Preliminary support for ENUMERATED type. This is largely copied from the - INTEGER code. - [Steve Henson] - - *) Add new function, EVP_MD_CTX_copy() to replace frequent use of memcpy. - [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)] - - *) Make sure `make rehash' target really finds the `openssl' program. - [Ralf S. Engelschall, Matthias Loepfe ] - - *) Squeeze another 7% of speed out of MD5 assembler, at least on a P2. I'd - like to hear about it if this slows down other processors. - [Ben Laurie] - - *) Add CygWin32 platform information to Configure script. - [Alan Batie ] - - *) Fixed ms/32all.bat script: `no_asm' -> `no-asm' - [Rainer W. Gerling ] - - *) New program nseq to manipulate netscape certificate sequences - [Steve Henson] - - *) Modify crl2pkcs7 so it supports multiple -certfile arguments. Fix a - few typos. - [Steve Henson] - - *) Fixes to BN code. Previously the default was to define BN_RECURSION - but the BN code had some problems that would cause failures when - doing certificate verification and some other functions. - [Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)] - - *) Add ASN1 and PEM code to support netscape certificate sequences. - [Steve Henson] - - *) Add ASN1 and PEM code to support netscape certificate sequences. - [Steve Henson] - - *) Add several PKIX and private extended key usage OIDs. - [Steve Henson] - - *) Modify the 'ca' program to handle the new extension code. Modify - openssl.cnf for new extension format, add comments. - [Steve Henson] - - *) More X509 V3 changes. Fix typo in v3_bitstr.c. Add support to 'req' - and add a sample to openssl.cnf so req -x509 now adds appropriate - CA extensions. - [Steve Henson] - - *) Continued X509 V3 changes. Add to other makefiles, integrate with the - error code, add initial support to X509_print() and x509 application. - [Steve Henson] - - *) Takes a deep breath and start adding X509 V3 extension support code. Add - files in crypto/x509v3. Move original stuff to crypto/x509v3/old. All this - stuff is currently isolated and isn't even compiled yet. - [Steve Henson] - - *) Continuing patches for GeneralizedTime. Fix up certificate and CRL - ASN1 to use ASN1_TIME and modify print routines to use ASN1_TIME_print. - Removed the versions check from X509 routines when loading extensions: - this allows certain broken certificates that don't set the version - properly to be processed. - [Steve Henson] - - *) Deal with irritating shit to do with dependencies, in YAAHW (Yet Another - Ad Hoc Way) - Makefile.ssls now all contain local dependencies, which - can still be regenerated with "make depend". - [Ben Laurie] - - *) Spelling mistake in C version of CAST-128. - [Ben Laurie, reported by Jeremy Hylton ] - - *) Changes to the error generation code. The perl script err-code.pl - now reads in the old error codes and retains the old numbers, only - adding new ones if necessary. It also only changes the .err files if new - codes are added. The makefiles have been modified to only insert errors - when needed (to avoid needlessly modifying header files). This is done - by only inserting errors if the .err file is newer than the auto generated - C file. To rebuild all the error codes from scratch (the old behaviour) - either modify crypto/Makefile.ssl to pass the -regen flag to err_code.pl - or delete all the .err files. - [Steve Henson] - - *) CAST-128 was incorrectly implemented for short keys. The C version has - been fixed, but is untested. The assembler versions are also fixed, but - new assembler HAS NOT BEEN GENERATED FOR WIN32 - the Makefile needs fixing - to regenerate it if needed. - [Ben Laurie, reported (with fix for C version) by Jun-ichiro itojun - Hagino ] - - *) File was opened incorrectly in randfile.c. - [Ulf Möller ] - - *) Beginning of support for GeneralizedTime. d2i, i2d, check and print - functions. Also ASN1_TIME suite which is a CHOICE of UTCTime or - GeneralizedTime. ASN1_TIME is the proper type used in certificates et - al: it's just almost always a UTCTime. Note this patch adds new error - codes so do a "make errors" if there are problems. - [Steve Henson] - - *) Correct Linux 1 recognition in config. - [Ulf Möller ] - - *) Remove pointless MD5 hash when using DSA keys in ca. - [Anonymous ] - - *) Generate an error if given an empty string as a cert directory. Also - generate an error if handed NULL (previously returned 0 to indicate an - error, but didn't set one). - [Ben Laurie, reported by Anonymous ] - - *) Add prototypes to SSL methods. Make SSL_write's buffer const, at last. - [Ben Laurie] - - *) Fix the dummy function BN_ref_mod_exp() in rsaref.c to have the correct - parameters. This was causing a warning which killed off the Win32 compile. - [Steve Henson] - - *) Remove C++ style comments from crypto/bn/bn_local.h. - [Neil Costigan ] - - *) The function OBJ_txt2nid was broken. It was supposed to return a nid - based on a text string, looking up short and long names and finally - "dot" format. The "dot" format stuff didn't work. Added new function - OBJ_txt2obj to do the same but return an ASN1_OBJECT and rewrote - OBJ_txt2nid to use it. OBJ_txt2obj can also return objects even if the - OID is not part of the table. - [Steve Henson] - - *) Add prototypes to X509 lookup/verify methods, fixing a bug in - X509_LOOKUP_by_alias(). - [Ben Laurie] - - *) Sort openssl functions by name. - [Ben Laurie] - - *) Get the gendsa program working (hopefully) and add it to app list. Remove - encryption from sample DSA keys (in case anyone is interested the password - was "1234"). - [Steve Henson] - - *) Make _all_ *_free functions accept a NULL pointer. - [Frans Heymans ] - - *) If a DH key is generated in s3_srvr.c, don't blow it by trying to use - NULL pointers. - [Anonymous ] - - *) s_server should send the CAfile as acceptable CAs, not its own cert. - [Bodo Moeller <3moeller@informatik.uni-hamburg.de>] - - *) Don't blow it for numeric -newkey arguments to apps/req. - [Bodo Moeller <3moeller@informatik.uni-hamburg.de>] - - *) Temp key "for export" tests were wrong in s3_srvr.c. - [Anonymous ] - - *) Add prototype for temp key callback functions - SSL_CTX_set_tmp_{rsa,dh}_callback(). - [Ben Laurie] - - *) Make DH_free() tolerate being passed a NULL pointer (like RSA_free() and - DSA_free()). Make X509_PUBKEY_set() check for errors in d2i_PublicKey(). - [Steve Henson] - - *) X509_name_add_entry() freed the wrong thing after an error. - [Arne Ansper ] - - *) rsa_eay.c would attempt to free a NULL context. - [Arne Ansper ] - - *) BIO_s_socket() had a broken should_retry() on Windoze. - [Arne Ansper ] - - *) BIO_f_buffer() didn't pass on BIO_CTRL_FLUSH. - [Arne Ansper ] - - *) Make sure the already existing X509_STORE->depth variable is initialized - in X509_STORE_new(), but document the fact that this variable is still - unused in the certificate verification process. - [Ralf S. Engelschall] - - *) Fix the various library and apps files to free up pkeys obtained from - X509_PUBKEY_get() et al. Also allow x509.c to handle netscape extensions. - [Steve Henson] - - *) Fix reference counting in X509_PUBKEY_get(). This makes - demos/maurice/example2.c work, amongst others, probably. - [Steve Henson and Ben Laurie] - - *) First cut of a cleanup for apps/. First the `ssleay' program is now named - `openssl' and second, the shortcut symlinks for the `openssl ' - are no longer created. This way we have a single and consistent command - line interface `openssl ', similar to `cvs '. - [Ralf S. Engelschall, Paul Sutton and Ben Laurie] - - *) ca.c: move test for DSA keys inside #ifndef NO_DSA. Make pubkey - BIT STRING wrapper always have zero unused bits. - [Steve Henson] - - *) Add CA.pl, perl version of CA.sh, add extended key usage OID. - [Steve Henson] - - *) Make the top-level INSTALL documentation easier to understand. - [Paul Sutton] - - *) Makefiles updated to exit if an error occurs in a sub-directory - make (including if user presses ^C) [Paul Sutton] - - *) Make Montgomery context stuff explicit in RSA data structure. - [Ben Laurie] - - *) Fix build order of pem and err to allow for generated pem.h. - [Ben Laurie] - - *) Fix renumbering bug in X509_NAME_delete_entry(). - [Ben Laurie] - - *) Enhanced the err-ins.pl script so it makes the error library number - global and can add a library name. This is needed for external ASN1 and - other error libraries. - [Steve Henson] - - *) Fixed sk_insert which never worked properly. - [Steve Henson] - - *) Fix ASN1 macros so they can handle indefinite length constructed - EXPLICIT tags. Some non standard certificates use these: they can now - be read in. - [Steve Henson] - - *) Merged the various old/obsolete SSLeay documentation files (doc/xxx.doc) - into a single doc/ssleay.txt bundle. This way the information is still - preserved but no longer messes up this directory. Now it's new room for - the new set of documentation files. - [Ralf S. Engelschall] - - *) SETs were incorrectly DER encoded. This was a major pain, because they - shared code with SEQUENCEs, which aren't coded the same. This means that - almost everything to do with SETs or SEQUENCEs has either changed name or - number of arguments. - [Ben Laurie, based on a partial fix by GP Jayan ] - - *) Fix test data to work with the above. - [Ben Laurie] - - *) Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but - was already fixed by Eric for 0.9.1 it seems. - [Ben Laurie - pointed out by Ulf Möller ] - - *) Autodetect FreeBSD3. - [Ben Laurie] - - *) Fix various bugs in Configure. This affects the following platforms: - nextstep - ncr-scde - unixware-2.0 - unixware-2.0-pentium - sco5-cc. - [Ben Laurie] - - *) Eliminate generated files from CVS. Reorder tests to regenerate files - before they are needed. - [Ben Laurie] - - *) Generate Makefile.ssl from Makefile.org (to keep CVS happy). - [Ben Laurie] - - - Changes between 0.9.1b and 0.9.1c [23-Dec-1998] - - *) Added OPENSSL_VERSION_NUMBER to crypto/crypto.h and - changed SSLeay to OpenSSL in version strings. - [Ralf S. Engelschall] - - *) Some fixups to the top-level documents. - [Paul Sutton] - - *) Fixed the nasty bug where rsaref.h was not found under compile-time - because the symlink to include/ was missing. - [Ralf S. Engelschall] - - *) Incorporated the popular no-RSA/DSA-only patches - which allow to compile a RSA-free SSLeay. - [Andrew Cooke / Interrader Ldt., Ralf S. Engelschall] - - *) Fixed nasty rehash problem under `make -f Makefile.ssl links' - when "ssleay" is still not found. - [Ralf S. Engelschall] - - *) Added more platforms to Configure: Cray T3E, HPUX 11, - [Ralf S. Engelschall, Beckmann ] - - *) Updated the README file. - [Ralf S. Engelschall] - - *) Added various .cvsignore files in the CVS repository subdirs - to make a "cvs update" really silent. - [Ralf S. Engelschall] - - *) Recompiled the error-definition header files and added - missing symbols to the Win32 linker tables. - [Ralf S. Engelschall] - - *) Cleaned up the top-level documents; - o new files: CHANGES and LICENSE - o merged VERSION, HISTORY* and README* files a CHANGES.SSLeay - o merged COPYRIGHT into LICENSE - o removed obsolete TODO file - o renamed MICROSOFT to INSTALL.W32 - [Ralf S. Engelschall] - - *) Removed dummy files from the 0.9.1b source tree: - crypto/asn1/x crypto/bio/cd crypto/bio/fg crypto/bio/grep crypto/bio/vi - crypto/bn/asm/......add.c crypto/bn/asm/a.out crypto/dsa/f crypto/md5/f - crypto/pem/gmon.out crypto/perlasm/f crypto/pkcs7/build crypto/rsa/f - crypto/sha/asm/f crypto/threads/f ms/zzz ssl/f ssl/f.mak test/f - util/f.mak util/pl/f util/pl/f.mak crypto/bf/bf_locl.old apps/f - [Ralf S. Engelschall] - - *) Added various platform portability fixes. - [Mark J. Cox] - - *) The Genesis of the OpenSSL rpject: - We start with the latest (unreleased) SSLeay version 0.9.1b which Eric A. - Young and Tim J. Hudson created while they were working for C2Net until - summer 1998. - [The OpenSSL Project] - - - Changes between 0.9.0b and 0.9.1b [not released] - - *) Updated a few CA certificates under certs/ - [Eric A. Young] - - *) Changed some BIGNUM api stuff. - [Eric A. Young] - - *) Various platform ports: OpenBSD, Ultrix, IRIX 64bit, NetBSD, - DGUX x86, Linux Alpha, etc. - [Eric A. Young] - - *) New COMP library [crypto/comp/] for SSL Record Layer Compression: - RLE (dummy implemented) and ZLIB (really implemented when ZLIB is - available). - [Eric A. Young] - - *) Add -strparse option to asn1pars program which parses nested - binary structures - [Dr Stephen Henson ] - - *) Added "oid_file" to ssleay.cnf for "ca" and "req" programs. - [Eric A. Young] - - *) DSA fix for "ca" program. - [Eric A. Young] - - *) Added "-genkey" option to "dsaparam" program. - [Eric A. Young] - - *) Added RIPE MD160 (rmd160) message digest. - [Eric A. Young] - - *) Added -a (all) option to "ssleay version" command. - [Eric A. Young] - - *) Added PLATFORM define which is the id given to Configure. - [Eric A. Young] - - *) Added MemCheck_XXXX functions to crypto/mem.c for memory checking. - [Eric A. Young] - - *) Extended the ASN.1 parser routines. - [Eric A. Young] - - *) Extended BIO routines to support REUSEADDR, seek, tell, etc. - [Eric A. Young] - - *) Added a BN_CTX to the BN library. - [Eric A. Young] - - *) Fixed the weak key values in DES library - [Eric A. Young] - - *) Changed API in EVP library for cipher aliases. - [Eric A. Young] - - *) Added support for RC2/64bit cipher. - [Eric A. Young] - - *) Converted the lhash library to the crypto/mem.c functions. - [Eric A. Young] - - *) Added more recognized ASN.1 object ids. - [Eric A. Young] - - *) Added more RSA padding checks for SSL/TLS. - [Eric A. Young] - - *) Added BIO proxy/filter functionality. - [Eric A. Young] - - *) Added extra_certs to SSL_CTX which can be used - send extra CA certificates to the client in the CA cert chain sending - process. It can be configured with SSL_CTX_add_extra_chain_cert(). - [Eric A. Young] - - *) Now Fortezza is denied in the authentication phase because - this is key exchange mechanism is not supported by SSLeay at all. - [Eric A. Young] - - *) Additional PKCS1 checks. - [Eric A. Young] - - *) Support the string "TLSv1" for all TLS v1 ciphers. - [Eric A. Young] - - *) Added function SSL_get_ex_data_X509_STORE_CTX_idx() which gives the - ex_data index of the SSL context in the X509_STORE_CTX ex_data. - [Eric A. Young] - - *) Fixed a few memory leaks. - [Eric A. Young] - - *) Fixed various code and comment typos. - [Eric A. Young] - - *) A minor bug in ssl/s3_clnt.c where there would always be 4 0 - bytes sent in the client random. - [Edward Bishop ] diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,19753 @@ +OpenSSL CHANGES +=============== + +This is a high-level summary of the most important changes. +For a full list of changes, see the [git commit log][log] and +pick the appropriate release branch. + + [log]: https://github.com/openssl/openssl/commits/ + +OpenSSL Releases +---------------- + + - [OpenSSL 3.0](#openssl-30) + - [OpenSSL 1.1.1](#openssl-111) + - [OpenSSL 1.1.0](#openssl-110) + - [OpenSSL 1.0.2](#openssl-102) + - [OpenSSL 1.0.1](#openssl-101) + - [OpenSSL 1.0.0](#openssl-100) + - [OpenSSL 0.9.x](#openssl-09x) + +OpenSSL 3.0 +----------- + +For OpenSSL 3.0 a [Migration guide][] has been added, so the CHANGES entries +listed here are only a brief description. +The migration guide contains more detailed information related to new features, +breaking changes, and mappings for the large list of deprecated functions. + +[Migration guide]: https://github.com/openssl/openssl/tree/master/doc/man7/migration_guide.pod + +### Changes between 3.0.7 and 3.0.8 [7 Feb 2023] + + * Fixed NULL dereference during PKCS7 data verification. + + A NULL pointer can be dereferenced when signatures are being + verified on PKCS7 signed or signedAndEnveloped data. In case the hash + algorithm used for the signature is known to the OpenSSL library but + the implementation of the hash algorithm is not available the digest + initialization will fail. There is a missing check for the return + value from the initialization function which later leads to invalid + usage of the digest API most likely leading to a crash. + ([CVE-2023-0401]) + + PKCS7 data is processed by the SMIME library calls and also by the + time stamp (TS) library calls. The TLS implementation in OpenSSL does + not call these functions however third party applications would be + affected if they call these functions to verify signatures on untrusted + data. + + *Tomáš Mráz* + + * Fixed X.400 address type confusion in X.509 GeneralName. + + There is a type confusion vulnerability relating to X.400 address processing + inside an X.509 GeneralName. X.400 addresses were parsed as an ASN1_STRING + but the public structure definition for GENERAL_NAME incorrectly specified + the type of the x400Address field as ASN1_TYPE. This field is subsequently + interpreted by the OpenSSL function GENERAL_NAME_cmp as an ASN1_TYPE rather + than an ASN1_STRING. + + When CRL checking is enabled (i.e. the application sets the + X509_V_FLAG_CRL_CHECK flag), this vulnerability may allow an attacker to + pass arbitrary pointers to a memcmp call, enabling them to read memory + contents or enact a denial of service. + ([CVE-2023-0286]) + + *Hugo Landau* + + * Fixed NULL dereference validating DSA public key. + + An invalid pointer dereference on read can be triggered when an + application tries to check a malformed DSA public key by the + EVP_PKEY_public_check() function. This will most likely lead + to an application crash. This function can be called on public + keys supplied from untrusted sources which could allow an attacker + to cause a denial of service attack. + + The TLS implementation in OpenSSL does not call this function + but applications might call the function if there are additional + security requirements imposed by standards such as FIPS 140-3. + ([CVE-2023-0217]) + + *Shane Lontis, Tomáš Mráz* + + * Fixed Invalid pointer dereference in d2i_PKCS7 functions. + + An invalid pointer dereference on read can be triggered when an + application tries to load malformed PKCS7 data with the + d2i_PKCS7(), d2i_PKCS7_bio() or d2i_PKCS7_fp() functions. + + The result of the dereference is an application crash which could + lead to a denial of service attack. The TLS implementation in OpenSSL + does not call this function however third party applications might + call these functions on untrusted data. + ([CVE-2023-0216]) + + *Tomáš Mráz* + + * Fixed Use-after-free following BIO_new_NDEF. + + The public API function BIO_new_NDEF is a helper function used for + streaming ASN.1 data via a BIO. It is primarily used internally to OpenSSL + to support the SMIME, CMS and PKCS7 streaming capabilities, but may also + be called directly by end user applications. + + The function receives a BIO from the caller, prepends a new BIO_f_asn1 + filter BIO onto the front of it to form a BIO chain, and then returns + the new head of the BIO chain to the caller. Under certain conditions, + for example if a CMS recipient public key is invalid, the new filter BIO + is freed and the function returns a NULL result indicating a failure. + However, in this case, the BIO chain is not properly cleaned up and the + BIO passed by the caller still retains internal pointers to the previously + freed filter BIO. If the caller then goes on to call BIO_pop() on the BIO + then a use-after-free will occur. This will most likely result in a crash. + ([CVE-2023-0215]) + + *Viktor Dukhovni, Matt Caswell* + + * Fixed Double free after calling PEM_read_bio_ex. + + The function PEM_read_bio_ex() reads a PEM file from a BIO and parses and + decodes the "name" (e.g. "CERTIFICATE"), any header data and the payload + data. If the function succeeds then the "name_out", "header" and "data" + arguments are populated with pointers to buffers containing the relevant + decoded data. The caller is responsible for freeing those buffers. It is + possible to construct a PEM file that results in 0 bytes of payload data. + In this case PEM_read_bio_ex() will return a failure code but will populate + the header argument with a pointer to a buffer that has already been freed. + If the caller also frees this buffer then a double free will occur. This + will most likely lead to a crash. + + The functions PEM_read_bio() and PEM_read() are simple wrappers around + PEM_read_bio_ex() and therefore these functions are also directly affected. + + These functions are also called indirectly by a number of other OpenSSL + functions including PEM_X509_INFO_read_bio_ex() and + SSL_CTX_use_serverinfo_file() which are also vulnerable. Some OpenSSL + internal uses of these functions are not vulnerable because the caller does + not free the header argument if PEM_read_bio_ex() returns a failure code. + ([CVE-2022-4450]) + + *Kurt Roeckx, Matt Caswell* + + * Fixed Timing Oracle in RSA Decryption. + + A timing based side channel exists in the OpenSSL RSA Decryption + implementation which could be sufficient to recover a plaintext across + a network in a Bleichenbacher style attack. To achieve a successful + decryption an attacker would have to be able to send a very large number + of trial messages for decryption. The vulnerability affects all RSA padding + modes: PKCS#1 v1.5, RSA-OEAP and RSASVE. + ([CVE-2022-4304]) + + *Dmitry Belyavsky, Hubert Kario* + + * Fixed X.509 Name Constraints Read Buffer Overflow. + + A read buffer overrun can be triggered in X.509 certificate verification, + specifically in name constraint checking. The read buffer overrun might + result in a crash which could lead to a denial of service attack. + In a TLS client, this can be triggered by connecting to a malicious + server. In a TLS server, this can be triggered if the server requests + client authentication and a malicious client connects. + ([CVE-2022-4203]) + + *Viktor Dukhovni* + + * Fixed X.509 Policy Constraints Double Locking security issue. + + If an X.509 certificate contains a malformed policy constraint and + policy processing is enabled, then a write lock will be taken twice + recursively. On some operating systems (most widely: Windows) this + results in a denial of service when the affected process hangs. Policy + processing being enabled on a publicly facing server is not considered + to be a common setup. + ([CVE-2022-3996]) + + *Paul Dale* + + * Our provider implementations of `OSSL_FUNC_KEYMGMT_EXPORT` and + `OSSL_FUNC_KEYMGMT_GET_PARAMS` for EC and SM2 keys now honor + `OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT` as set (and + default to `POINT_CONVERSION_UNCOMPRESSED`) when exporting + `OSSL_PKEY_PARAM_PUB_KEY`, instead of unconditionally using + `POINT_CONVERSION_COMPRESSED` as in previous 3.x releases. + For symmetry, our implementation of `EVP_PKEY_ASN1_METHOD->export_to` + for legacy EC and SM2 keys is also changed similarly to honor the + equivalent conversion format flag as specified in the underlying + `EC_KEY` object being exported to a provider, when this function is + called through `EVP_PKEY_export()`. + + *Nicola Tuveri* + +### Changes between 3.0.6 and 3.0.7 [1 Nov 2022] + + * Fixed two buffer overflows in punycode decoding functions. + + A buffer overrun can be triggered in X.509 certificate verification, + specifically in name constraint checking. Note that this occurs after + certificate chain signature verification and requires either a CA to + have signed the malicious certificate or for the application to continue + certificate verification despite failure to construct a path to a trusted + issuer. + + In a TLS client, this can be triggered by connecting to a malicious + server. In a TLS server, this can be triggered if the server requests + client authentication and a malicious client connects. + + An attacker can craft a malicious email address to overflow + an arbitrary number of bytes containing the `.` character (decimal 46) + on the stack. This buffer overflow could result in a crash (causing a + denial of service). + ([CVE-2022-3786]) + + An attacker can craft a malicious email address to overflow four + attacker-controlled bytes on the stack. This buffer overflow could + result in a crash (causing a denial of service) or potentially remote code + execution depending on stack layout for any given platform/compiler. + ([CVE-2022-3602]) + + *Paul Dale* + + * Removed all references to invalid OSSL_PKEY_PARAM_RSA names for CRT + parameters in OpenSSL code. + Applications should not use the names OSSL_PKEY_PARAM_RSA_FACTOR, + OSSL_PKEY_PARAM_RSA_EXPONENT and OSSL_PKEY_PARAM_RSA_COEFFICIENT. + Use the numbered names such as OSSL_PKEY_PARAM_RSA_FACTOR1 instead. + Using these invalid names may cause algorithms to use slower methods + that ignore the CRT parameters. + + *Shane Lontis* + + * Fixed a regression introduced in 3.0.6 version raising errors on some stack + operations. + + *Tomáš Mráz* + + * Fixed a regression introduced in 3.0.6 version not refreshing the certificate + data to be signed before signing the certificate. + + *Gibeom Gwon* + + * Added RIPEMD160 to the default provider. + + *Paul Dale* + + * Ensured that the key share group sent or accepted for the key exchange + is allowed for the protocol version. + + *Matt Caswell* + +### Changes between 3.0.5 and 3.0.6 [11 Oct 2022] + + * OpenSSL supports creating a custom cipher via the legacy + EVP_CIPHER_meth_new() function and associated function calls. This function + was deprecated in OpenSSL 3.0 and application authors are instead encouraged + to use the new provider mechanism in order to implement custom ciphers. + + OpenSSL versions 3.0.0 to 3.0.5 incorrectly handle legacy custom ciphers + passed to the EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2() and + EVP_CipherInit_ex2() functions (as well as other similarly named encryption + and decryption initialisation functions). Instead of using the custom cipher + directly it incorrectly tries to fetch an equivalent cipher from the + available providers. An equivalent cipher is found based on the NID passed to + EVP_CIPHER_meth_new(). This NID is supposed to represent the unique NID for a + given cipher. However it is possible for an application to incorrectly pass + NID_undef as this value in the call to EVP_CIPHER_meth_new(). When NID_undef + is used in this way the OpenSSL encryption/decryption initialisation function + will match the NULL cipher as being equivalent and will fetch this from the + available providers. This will succeed if the default provider has been + loaded (or if a third party provider has been loaded that offers this + cipher). Using the NULL cipher means that the plaintext is emitted as the + ciphertext. + + Applications are only affected by this issue if they call + EVP_CIPHER_meth_new() using NID_undef and subsequently use it in a call to an + encryption/decryption initialisation function. Applications that only use + SSL/TLS are not impacted by this issue. + ([CVE-2022-3358]) + + *Matt Caswell* + + * Fix LLVM vs Apple LLVM version numbering confusion that caused build failures + on MacOS 10.11 + + *Richard Levitte* + + * Fixed the linux-mips64 Configure target which was missing the + SIXTY_FOUR_BIT bn_ops flag. This was causing heap corruption on that + platform. + + *Adam Joseph* + + * Fix handling of a ticket key callback that returns 0 in TLSv1.3 to not send a + ticket + + *Matt Caswell* + + * Correctly handle a retransmitted ClientHello in DTLS + + *Matt Caswell* + + * Fixed detection of ktls support in cross-compile environment on Linux + + *Tomas Mraz* + + * Fixed some regressions and test failures when running the 3.0.0 FIPS provider + against 3.0.x + + *Paul Dale* + + * Fixed SSL_pending() and SSL_has_pending() with DTLS which were failing to + report correct results in some cases + + *Matt Caswell* + + * Fix UWP builds by defining VirtualLock + + *Charles Milette* + + * For known safe primes use the minimum key length according to RFC 7919. + Longer private key sizes unnecessarily raise the cycles needed to compute the + shared secret without any increase of the real security. This fixes a + regression from 1.1.1 where these shorter keys were generated for the known + safe primes. + + *Tomas Mraz* + + * Added the loongarch64 target + + *Shi Pujin* + + * Fixed EC ASM flag passing. Flags for ASM implementations of EC curves were + only passed to the FIPS provider and not to the default or legacy provider. + + *Juergen Christ* + + * Fixed reported performance degradation on aarch64. Restored the + implementation prior to commit 2621751 ("aes/asm/aesv8-armx.pl: avoid + 32-bit lane assignment in CTR mode") for 64bit targets only, since it is + reportedly 2-17% slower and the silicon errata only affects 32bit targets. + The new algorithm is still used for 32 bit targets. + + *Bernd Edlinger* + + * Added a missing header for memcmp that caused compilation failure on some + platforms + + *Gregor Jasny* + +### Changes between 3.0.4 and 3.0.5 [5 Jul 2022] + + * The OpenSSL 3.0.4 release introduced a serious bug in the RSA + implementation for X86_64 CPUs supporting the AVX512IFMA instructions. + This issue makes the RSA implementation with 2048 bit private keys + incorrect on such machines and memory corruption will happen during + the computation. As a consequence of the memory corruption an attacker + may be able to trigger a remote code execution on the machine performing + the computation. + + SSL/TLS servers or other servers using 2048 bit RSA private keys running + on machines supporting AVX512IFMA instructions of the X86_64 architecture + are affected by this issue. + ([CVE-2022-2274]) + + *Xi Ruoyao* + + * AES OCB mode for 32-bit x86 platforms using the AES-NI assembly optimised + implementation would not encrypt the entirety of the data under some + circumstances. This could reveal sixteen bytes of data that was + preexisting in the memory that wasn't written. In the special case of + "in place" encryption, sixteen bytes of the plaintext would be revealed. + + Since OpenSSL does not support OCB based cipher suites for TLS and DTLS, + they are both unaffected. + ([CVE-2022-2097]) + + *Alex Chernyakhovsky, David Benjamin, Alejandro Sedeño* + +### Changes between 3.0.3 and 3.0.4 [21 Jun 2022] + + * In addition to the c_rehash shell command injection identified in + CVE-2022-1292, further bugs where the c_rehash script does not + properly sanitise shell metacharacters to prevent command injection have been + fixed. + + When the CVE-2022-1292 was fixed it was not discovered that there + are other places in the script where the file names of certificates + being hashed were possibly passed to a command executed through the shell. + + This script is distributed by some operating systems in a manner where + it is automatically executed. On such operating systems, an attacker + could execute arbitrary commands with the privileges of the script. + + Use of the c_rehash script is considered obsolete and should be replaced + by the OpenSSL rehash command line tool. + (CVE-2022-2068) + + *Daniel Fiala, Tomáš Mráz* + + * Case insensitive string comparison no longer uses locales. It has instead + been directly implemented. + + *Paul Dale* + +### Changes between 3.0.2 and 3.0.3 [3 May 2022] + + * Case insensitive string comparison is reimplemented via new locale-agnostic + comparison functions OPENSSL_str[n]casecmp always using the POSIX locale for + comparison. The previous implementation had problems when the Turkish locale + was used. + + *Dmitry Belyavskiy* + + * Fixed a bug in the c_rehash script which was not properly sanitising shell + metacharacters to prevent command injection. This script is distributed by + some operating systems in a manner where it is automatically executed. On + such operating systems, an attacker could execute arbitrary commands with the + privileges of the script. + + Use of the c_rehash script is considered obsolete and should be replaced + by the OpenSSL rehash command line tool. + (CVE-2022-1292) + + *Tomáš Mráz* + + * Fixed a bug in the function `OCSP_basic_verify` that verifies the signer + certificate on an OCSP response. The bug caused the function in the case + where the (non-default) flag OCSP_NOCHECKS is used to return a postivie + response (meaning a successful verification) even in the case where the + response signing certificate fails to verify. + + It is anticipated that most users of `OCSP_basic_verify` will not use the + OCSP_NOCHECKS flag. In this case the `OCSP_basic_verify` function will return + a negative value (indicating a fatal error) in the case of a certificate + verification failure. The normal expected return value in this case would be + 0. + + This issue also impacts the command line OpenSSL "ocsp" application. When + verifying an ocsp response with the "-no_cert_checks" option the command line + application will report that the verification is successful even though it + has in fact failed. In this case the incorrect successful response will also + be accompanied by error messages showing the failure and contradicting the + apparently successful result. + ([CVE-2022-1343]) + + *Matt Caswell* + + * Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the + AAD data as the MAC key. This made the MAC key trivially predictable. + + An attacker could exploit this issue by performing a man-in-the-middle attack + to modify data being sent from one endpoint to an OpenSSL 3.0 recipient such + that the modified data would still pass the MAC integrity check. + + Note that data sent from an OpenSSL 3.0 endpoint to a non-OpenSSL 3.0 + endpoint will always be rejected by the recipient and the connection will + fail at that point. Many application protocols require data to be sent from + the client to the server first. Therefore, in such a case, only an OpenSSL + 3.0 server would be impacted when talking to a non-OpenSSL 3.0 client. + + If both endpoints are OpenSSL 3.0 then the attacker could modify data being + sent in both directions. In this case both clients and servers could be + affected, regardless of the application protocol. + + Note that in the absence of an attacker this bug means that an OpenSSL 3.0 + endpoint communicating with a non-OpenSSL 3.0 endpoint will fail to complete + the handshake when using this ciphersuite. + + The confidentiality of data is not impacted by this issue, i.e. an attacker + cannot decrypt data that has been encrypted using this ciphersuite - they can + only modify it. + + In order for this attack to work both endpoints must legitimately negotiate + the RC4-MD5 ciphersuite. This ciphersuite is not compiled by default in + OpenSSL 3.0, and is not available within the default provider or the default + ciphersuite list. This ciphersuite will never be used if TLSv1.3 has been + negotiated. In order for an OpenSSL 3.0 endpoint to use this ciphersuite the + following must have occurred: + + 1) OpenSSL must have been compiled with the (non-default) compile time option + enable-weak-ssl-ciphers + + 2) OpenSSL must have had the legacy provider explicitly loaded (either + through application code or via configuration) + + 3) The ciphersuite must have been explicitly added to the ciphersuite list + + 4) The libssl security level must have been set to 0 (default is 1) + + 5) A version of SSL/TLS below TLSv1.3 must have been negotiated + + 6) Both endpoints must negotiate the RC4-MD5 ciphersuite in preference to any + others that both endpoints have in common + (CVE-2022-1434) + + *Matt Caswell* + + * Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory + occuppied by the removed hash table entries. + + This function is used when decoding certificates or keys. If a long lived + process periodically decodes certificates or keys its memory usage will + expand without bounds and the process might be terminated by the operating + system causing a denial of service. Also traversing the empty hash table + entries will take increasingly more time. + + Typically such long lived processes might be TLS clients or TLS servers + configured to accept client certificate authentication. + (CVE-2022-1473) + + *Hugo Landau, Aliaksei Levin* + + * The functions `OPENSSL_LH_stats` and `OPENSSL_LH_stats_bio` now only report + the `num_items`, `num_nodes` and `num_alloc_nodes` statistics. All other + statistics are no longer supported. For compatibility, these statistics are + still listed in the output but are now always reported as zero. + + *Hugo Landau* + +### Changes between 3.0.1 and 3.0.2 [15 Mar 2022] + + * Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever + for non-prime moduli. + + Internally this function is used when parsing certificates that contain + elliptic curve public keys in compressed form or explicit elliptic curve + parameters with a base point encoded in compressed form. + + It is possible to trigger the infinite loop by crafting a certificate that + has invalid explicit curve parameters. + + Since certificate parsing happens prior to verification of the certificate + signature, any process that parses an externally supplied certificate may thus + be subject to a denial of service attack. The infinite loop can also be + reached when parsing crafted private keys as they can contain explicit + elliptic curve parameters. + + Thus vulnerable situations include: + + - TLS clients consuming server certificates + - TLS servers consuming client certificates + - Hosting providers taking certificates or private keys from customers + - Certificate authorities parsing certification requests from subscribers + - Anything else which parses ASN.1 elliptic curve parameters + + Also any other applications that use the BN_mod_sqrt() where the attacker + can control the parameter values are vulnerable to this DoS issue. + ([CVE-2022-0778]) + + *Tomáš Mráz* + + * Add ciphersuites based on DHE_PSK (RFC 4279) and ECDHE_PSK (RFC 5489) + to the list of ciphersuites providing Perfect Forward Secrecy as + required by SECLEVEL >= 3. + + *Dmitry Belyavskiy, Nicola Tuveri* + + * Made the AES constant time code for no-asm configurations + optional due to the resulting 95% performance degradation. + The AES constant time code can be enabled, for no assembly + builds, with: ./config no-asm -DOPENSSL_AES_CONST_TIME + + *Paul Dale* + + * Fixed PEM_write_bio_PKCS8PrivateKey() to make it possible to use empty + passphrase strings. + + *Darshan Sen* + + * The negative return value handling of the certificate verification callback + was reverted. The replacement is to set the verification retry state with + the SSL_set_retry_verify() function. + + *Tomáš Mráz* + +### Changes between 3.0.0 and 3.0.1 [14 Dec 2021] + + * Fixed invalid handling of X509_verify_cert() internal errors in libssl + Internally libssl in OpenSSL calls X509_verify_cert() on the client side to + verify a certificate supplied by a server. That function may return a + negative return value to indicate an internal error (for example out of + memory). Such a negative return value is mishandled by OpenSSL and will cause + an IO function (such as SSL_connect() or SSL_do_handshake()) to not indicate + success and a subsequent call to SSL_get_error() to return the value + SSL_ERROR_WANT_RETRY_VERIFY. This return value is only supposed to be + returned by OpenSSL if the application has previously called + SSL_CTX_set_cert_verify_callback(). Since most applications do not do this + the SSL_ERROR_WANT_RETRY_VERIFY return value from SSL_get_error() will be + totally unexpected and applications may not behave correctly as a result. The + exact behaviour will depend on the application but it could result in + crashes, infinite loops or other similar incorrect responses. + + This issue is made more serious in combination with a separate bug in OpenSSL + 3.0 that will cause X509_verify_cert() to indicate an internal error when + processing a certificate chain. This will occur where a certificate does not + include the Subject Alternative Name extension but where a Certificate + Authority has enforced name constraints. This issue can occur even with valid + chains. + ([CVE-2021-4044]) + + *Matt Caswell* + + * Corrected a few file name and file reference bugs in the build, + installation and setup scripts, which lead to installation verification + failures. Slightly enhanced the installation verification script. + + *Richard Levitte* + + * Fixed EVP_PKEY_eq() to make it possible to use it with strictly private + keys. + + *Richard Levitte* + + * Fixed PVK encoder to properly query for the passphrase. + + *Tomáš Mráz* + + * Multiple fixes in the OSSL_HTTP API functions. + + *David von Oheimb* + + * Allow sign extension in OSSL_PARAM_allocate_from_text() for the + OSSL_PARAM_INTEGER data type and return error on negative numbers + used with the OSSL_PARAM_UNSIGNED_INTEGER data type. Make + OSSL_PARAM_BLD_push_BN{,_pad}() return an error on negative numbers. + + *Richard Levitte* + + * Allow copying uninitialized digest contexts with EVP_MD_CTX_copy_ex. + + *Tomáš Mráz* + + * Fixed detection of ARMv7 and ARM64 CPU features on FreeBSD. + + *Allan Jude* + + * Multiple threading fixes. + + *Matt Caswell* + + * Added NULL digest implementation to keep compatibility with 1.1.1 version. + + *Tomáš Mráz* + + * Allow fetching an operation from the provider that owns an unexportable key + as a fallback if that is still allowed by the property query. + + *Richard Levitte* + +### Changes between 1.1.1 and 3.0.0 [7 sep 2021] + + * TLS_MAX_VERSION, DTLS_MAX_VERSION and DTLS_MIN_VERSION constants are now + deprecated. + + *Matt Caswell* + + * The `OPENSSL_s390xcap` environment variable can be used to set bits in the + S390X capability vector to zero. This simplifies testing of different code + paths on S390X architecture. + + *Patrick Steuer* + + * Encrypting more than 2^64 TLS records with AES-GCM is disallowed + as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness Requirements from + SP 800-38D". The communication will fail at this point. + + *Paul Dale* + + * The EC_GROUP_clear_free() function is deprecated as there is nothing + confidential in EC_GROUP data. + + *Nicola Tuveri* + + * The byte order mark (BOM) character is ignored if encountered at the + beginning of a PEM-formatted file. + + *Dmitry Belyavskiy* + + * Added CMS support for the Russian GOST algorithms. + + *Dmitry Belyavskiy* + + * Due to move of the implementation of cryptographic operations + to the providers, validation of various operation parameters can + be postponed until the actual operation is executed where previously + it happened immediately when an operation parameter was set. + + For example when setting an unsupported curve with + EVP_PKEY_CTX_set_ec_paramgen_curve_nid() this function call will not + fail but later keygen operations with the EVP_PKEY_CTX will fail. + + *OpenSSL team members and many third party contributors* + + * The EVP_get_cipherbyname() function will return NULL for algorithms such as + "AES-128-SIV", "AES-128-CBC-CTS" and "CAMELLIA-128-CBC-CTS" which were + previously only accessible via low level interfaces. Use EVP_CIPHER_fetch() + instead to retrieve these algorithms from a provider. + + *Shane Lontis* + + * On build targets where the multilib postfix is set in the build + configuration the libdir directory was changing based on whether + the lib directory with the multilib postfix exists on the system + or not. This unpredictable behavior was removed and eventual + multilib postfix is now always added to the default libdir. Use + `--libdir=lib` to override the libdir if adding the postfix is + undesirable. + + *Jan Lána* + + * The triple DES key wrap functionality now conforms to RFC 3217 but is + no longer interoperable with OpenSSL 1.1.1. + + *Paul Dale* + + * The ERR_GET_FUNC() function was removed. With the loss of meaningful + function codes, this function can only cause problems for calling + applications. + + *Paul Dale* + + * Add a configurable flag to output date formats as ISO 8601. Does not + change the default date format. + + *William Edmisten* + + * Version of MSVC earlier than 1300 could get link warnings, which could + be suppressed if the undocumented -DI_CAN_LIVE_WITH_LNK4049 was set. + Support for this flag has been removed. + + *Rich Salz* + + * Rework and make DEBUG macros consistent. Remove unused -DCONF_DEBUG, + -DBN_CTX_DEBUG, and REF_PRINT. Add a new tracing category and use it for + printing reference counts. Rename -DDEBUG_UNUSED to -DUNUSED_RESULT_DEBUG + Fix BN_DEBUG_RAND so it compiles and, when set, force DEBUG_RAND to be set + also. Rename engine_debug_ref to be ENGINE_REF_PRINT also for consistency. + + *Rich Salz* + + * The signatures of the functions to get and set options on SSL and + SSL_CTX objects changed from "unsigned long" to "uint64_t" type. + Some source code changes may be required. + + *Rich Salz* + + * The public definitions of conf_method_st and conf_st have been + deprecated. They will be made opaque in a future release. + + *Rich Salz and Tomáš Mráz* + + * Client-initiated renegotiation is disabled by default. To allow it, use + the -client_renegotiation option, the SSL_OP_ALLOW_CLIENT_RENEGOTIATION + flag, or the "ClientRenegotiation" config parameter as appropriate. + + *Rich Salz* + + * Add "abspath" and "includedir" pragma's to config files, to prevent, + or modify relative pathname inclusion. + + *Rich Salz* + + * OpenSSL includes a cryptographic module that is intended to be FIPS 140-2 + validated. Please consult the README-FIPS and + README-PROVIDERS files, as well as the migration guide. + + *OpenSSL team members and many third party contributors* + + * For the key types DH and DHX the allowed settable parameters are now different. + + *Shane Lontis* + + * The openssl commands that read keys, certificates, and CRLs now + automatically detect the PEM or DER format of the input files. + + *David von Oheimb, Richard Levitte, and Tomáš Mráz* + + * Added enhanced PKCS#12 APIs which accept a library context. + + *Jon Spillett* + + * The default manual page suffix ($MANSUFFIX) has been changed to "ossl" + + *Matt Caswell* + + * Added support for Kernel TLS (KTLS). + + *Boris Pismenny, John Baldwin and Andrew Gallatin* + + * Support for RFC 5746 secure renegotiation is now required by default for + SSL or TLS connections to succeed. + + *Benjamin Kaduk* + + * The signature of the `copy` functional parameter of the + EVP_PKEY_meth_set_copy() function has changed so its `src` argument is + now `const EVP_PKEY_CTX *` instead of `EVP_PKEY_CTX *`. Similarly + the signature of the `pub_decode` functional parameter of the + EVP_PKEY_asn1_set_public() function has changed so its `pub` argument is + now `const X509_PUBKEY *` instead of `X509_PUBKEY *`. + + *David von Oheimb* + + * The error return values from some control calls (ctrl) have changed. + + *Paul Dale* + + * A public key check is now performed during EVP_PKEY_derive_set_peer(). + + *Shane Lontis* + + * Many functions in the EVP_ namespace that are getters of values from + implementations or contexts were renamed to include get or get0 in their + names. Old names are provided as macro aliases for compatibility and + are not deprecated. + + *Tomáš Mráz* + + * The EVP_PKEY_CTRL_PKCS7_ENCRYPT, EVP_PKEY_CTRL_PKCS7_DECRYPT, + EVP_PKEY_CTRL_PKCS7_SIGN, EVP_PKEY_CTRL_CMS_ENCRYPT, + EVP_PKEY_CTRL_CMS_DECRYPT, and EVP_PKEY_CTRL_CMS_SIGN control operations + are deprecated. + + *Tomáš Mráz* + + * The EVP_PKEY_public_check() and EVP_PKEY_param_check() functions now work for + more key types. + + * The output from the command line applications may have minor + changes. + + *Paul Dale* + + * The output from numerous "printing" may have minor changes. + + *David von Oheimb* + + * Windows thread synchronization uses read/write primitives (SRWLock) when + supported by the OS, otherwise CriticalSection continues to be used. + + *Vincent Drake* + + * Add filter BIO BIO_f_readbuffer() that allows BIO_tell() and BIO_seek() to + work on read only BIO source/sinks that do not support these functions. + This allows piping or redirection of a file BIO using stdin to be buffered + into memory. This is used internally in OSSL_DECODER_from_bio(). + + *Shane Lontis* + + * OSSL_STORE_INFO_get_type() may now return an additional value. In 1.1.1 + this function would return one of the values OSSL_STORE_INFO_NAME, + OSSL_STORE_INFO_PKEY, OSSL_STORE_INFO_PARAMS, OSSL_STORE_INFO_CERT or + OSSL_STORE_INFO_CRL. Decoded public keys would previously have been reported + as type OSSL_STORE_INFO_PKEY in 1.1.1. In 3.0 decoded public keys are now + reported as having the new type OSSL_STORE_INFO_PUBKEY. Applications + using this function should be amended to handle the changed return value. + + *Richard Levitte* + + * Improved adherence to Enhanced Security Services (ESS, RFC 2634 and RFC 5035) + for the TSP and CMS Advanced Electronic Signatures (CAdES) implementations. + As required by RFC 5035 check both ESSCertID and ESSCertIDv2 if both present. + Correct the semantics of checking the validation chain in case ESSCertID{,v2} + contains more than one certificate identifier: This means that all + certificates referenced there MUST be part of the validation chain. + + *David von Oheimb* + + * The implementation of older EVP ciphers related to CAST, IDEA, SEED, RC2, RC4, + RC5, DESX and DES have been moved to the legacy provider. + + *Matt Caswell* + + * The implementation of the EVP digests MD2, MD4, MDC2, WHIRLPOOL and + RIPEMD-160 have been moved to the legacy provider. + + *Matt Caswell* + + * The deprecated function EVP_PKEY_get0() now returns NULL being called for a + provided key. + + *Dmitry Belyavskiy* + + * The deprecated functions EVP_PKEY_get0_RSA(), + EVP_PKEY_get0_DSA(), EVP_PKEY_get0_EC_KEY(), EVP_PKEY_get0_DH(), + EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305() and EVP_PKEY_get0_siphash() as + well as the similarly named "get1" functions behave differently in + OpenSSL 3.0. + + *Matt Caswell* + + * A number of functions handling low-level keys or engines were deprecated + including EVP_PKEY_set1_engine(), EVP_PKEY_get0_engine(), EVP_PKEY_assign(), + EVP_PKEY_get0(), EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305() and + EVP_PKEY_get0_siphash(). + + *Matt Caswell* + + * PKCS#5 PBKDF1 key derivation has been moved from PKCS5_PBE_keyivgen() into + the legacy crypto provider as an EVP_KDF. Applications requiring this KDF + will need to load the legacy crypto provider. This includes these PBE + algorithms which use this KDF: + - NID_pbeWithMD2AndDES_CBC + - NID_pbeWithMD5AndDES_CBC + - NID_pbeWithSHA1AndRC2_CBC + - NID_pbeWithMD2AndRC2_CBC + - NID_pbeWithMD5AndRC2_CBC + - NID_pbeWithSHA1AndDES_CBC + + *Jon Spillett* + + * Deprecated obsolete BIO_set_callback(), BIO_get_callback(), and + BIO_debug_callback() functions. + + *Tomáš Mráz* + + * Deprecated obsolete EVP_PKEY_CTX_get0_dh_kdf_ukm() and + EVP_PKEY_CTX_get0_ecdh_kdf_ukm() functions. + + *Tomáš Mráz* + + * The RAND_METHOD APIs have been deprecated. + + *Paul Dale* + + * The SRP APIs have been deprecated. + + *Matt Caswell* + + * Add a compile time option to prevent the caching of provider fetched + algorithms. This is enabled by including the no-cached-fetch option + at configuration time. + + *Paul Dale* + + * pkcs12 now uses defaults of PBKDF2, AES and SHA-256, with a MAC iteration + count of PKCS12_DEFAULT_ITER. + + *Tomáš Mráz and Sahana Prasad* + + * The openssl speed command does not use low-level API calls anymore. + + *Tomáš Mráz* + + * Parallel dual-prime 1024-bit modular exponentiation for AVX512_IFMA + capable processors. + + *Ilya Albrekht, Sergey Kirillov, Andrey Matyukov (Intel Corp)* + + * Combining the Configure options no-ec and no-dh no longer disables TLSv1.3. + + *Matt Caswell* + + * Implemented support for fully "pluggable" TLSv1.3 groups. This means that + providers may supply their own group implementations (using either the "key + exchange" or the "key encapsulation" methods) which will automatically be + detected and used by libssl. + + *Matt Caswell, Nicola Tuveri* + + * The undocumented function X509_certificate_type() has been deprecated; + + *Rich Salz* + + * Deprecated the obsolete BN_pseudo_rand() and BN_pseudo_rand_range(). + + *Tomáš Mráz* + + * Removed RSA padding mode for SSLv23 (which was only used for + SSLv2). This includes the functions RSA_padding_check_SSLv23() and + RSA_padding_add_SSLv23() and the `-ssl` option in the deprecated + `rsautl` command. + + *Rich Salz* + + * Deprecated the obsolete X9.31 RSA key generation related functions. + + * While a callback function set via `SSL_CTX_set_cert_verify_callback()` + is not allowed to return a value > 1, this is no more taken as failure. + + *Viktor Dukhovni and David von Oheimb* + + * Deprecated the obsolete X9.31 RSA key generation related functions + BN_X931_generate_Xpq(), BN_X931_derive_prime_ex(), and + BN_X931_generate_prime_ex(). + + *Tomáš Mráz* + + * The default key generation method for the regular 2-prime RSA keys was + changed to the FIPS 186-4 B.3.6 method. + + *Shane Lontis* + + * Deprecated the BN_is_prime_ex() and BN_is_prime_fasttest_ex() functions. + + *Kurt Roeckx* + + * Deprecated EVP_MD_CTX_set_update_fn() and EVP_MD_CTX_update_fn(). + + *Rich Salz* + + * Deprecated the type OCSP_REQ_CTX and the functions OCSP_REQ_CTX_*() and + replaced with OSSL_HTTP_REQ_CTX and the functions OSSL_HTTP_REQ_CTX_*(). + + *Rich Salz, Richard Levitte, and David von Oheimb* + + * Deprecated `X509_http_nbio()` and `X509_CRL_http_nbio()`. + + *David von Oheimb* + + * Deprecated `OCSP_parse_url()`. + + *David von Oheimb* + + * Validation of SM2 keys has been separated from the validation of regular EC + keys. + + *Nicola Tuveri* + + * Behavior of the `pkey` app is changed, when using the `-check` or `-pubcheck` + switches: a validation failure triggers an early exit, returning a failure + exit status to the parent process. + + *Nicola Tuveri* + + * Changed behavior of SSL_CTX_set_ciphersuites() and SSL_set_ciphersuites() + to ignore unknown ciphers. + + *Otto Hollmann* + + * The `-cipher-commands` and `-digest-commands` options + of the command line utility `list` have been deprecated. + Instead use the `-cipher-algorithms` and `-digest-algorithms` options. + + *Dmitry Belyavskiy* + + * Added convenience functions for generating asymmetric key pairs: + The 'quick' one-shot (yet somewhat limited) function L + and macros for the most common cases: and L. + + *David von Oheimb* + + * All of the low level EC_KEY functions have been deprecated. + + *Shane Lontis, Paul Dale, Richard Levitte, and Tomáš Mráz* + + * Deprecated all the libcrypto and libssl error string loading + functions. + + *Richard Levitte* + + * The functions SSL_CTX_set_tmp_dh_callback and SSL_set_tmp_dh_callback, as + well as the macros SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() have been + deprecated. + + *Matt Caswell* + + * The `-crypt` option to the `passwd` command line tool has been removed. + + *Paul Dale* + + * The -C option to the `x509`, `dhparam`, `dsaparam`, and `ecparam` commands + were removed. + + *Rich Salz* + + * Add support for AES Key Wrap inverse ciphers to the EVP layer. + + *Shane Lontis* + + * Deprecated EVP_PKEY_set1_tls_encodedpoint() and + EVP_PKEY_get1_tls_encodedpoint(). + + *Matt Caswell* + + * The security callback, which can be customised by application code, supports + the security operation SSL_SECOP_TMP_DH. One location of the "other" parameter + was incorrectly passing a DH object. It now passed an EVP_PKEY in all cases. + + *Matt Caswell* + + * Add PKCS7_get_octet_string() and PKCS7_type_is_other() to the public + interface. Their functionality remains unchanged. + + *Jordan Montgomery* + + * Added new option for 'openssl list', '-providers', which will display the + list of loaded providers, their names, version and status. It optionally + displays their gettable parameters. + + *Paul Dale* + + * Removed EVP_PKEY_set_alias_type(). + + *Richard Levitte* + + * Deprecated `EVP_PKEY_CTX_set_rsa_keygen_pubexp()` and introduced + `EVP_PKEY_CTX_set1_rsa_keygen_pubexp()`, which is now preferred. + + *Jeremy Walch* + + * Changed all "STACK" functions to be macros instead of inline functions. Macro + parameters are still checked for type safety at compile time via helper + inline functions. + + *Matt Caswell* + + * Remove the RAND_DRBG API + + *Paul Dale and Matthias St. Pierre* + + * Allow `SSL_set1_host()` and `SSL_add1_host()` to take IP literal addresses + as well as actual hostnames. + + *David Woodhouse* + + * The 'MinProtocol' and 'MaxProtocol' configuration commands now silently + ignore TLS protocol version bounds when configuring DTLS-based contexts, and + conversely, silently ignore DTLS protocol version bounds when configuring + TLS-based contexts. The commands can be repeated to set bounds of both + types. The same applies with the corresponding "min_protocol" and + "max_protocol" command-line switches, in case some application uses both TLS + and DTLS. + + SSL_CTX instances that are created for a fixed protocol version (e.g. + `TLSv1_server_method()`) also silently ignore version bounds. Previously + attempts to apply bounds to these protocol versions would result in an + error. Now only the "version-flexible" SSL_CTX instances are subject to + limits in configuration files in command-line options. + + *Viktor Dukhovni* + + * Deprecated the `ENGINE` API. Engines should be replaced with providers + going forward. + + *Paul Dale* + + * Reworked the recorded ERR codes to make better space for system errors. + To distinguish them, the macro `ERR_SYSTEM_ERROR()` indicates if the + given code is a system error (true) or an OpenSSL error (false). + + *Richard Levitte* + + * Reworked the test perl framework to better allow parallel testing. + + *Nicola Tuveri and David von Oheimb* + + * Added ciphertext stealing algorithms AES-128-CBC-CTS, AES-192-CBC-CTS and + AES-256-CBC-CTS to the providers. CS1, CS2 and CS3 variants are supported. + + *Shane Lontis* + + * 'Configure' has been changed to figure out the configuration target if + none is given on the command line. Consequently, the 'config' script is + now only a mere wrapper. All documentation is changed to only mention + 'Configure'. + + *Rich Salz and Richard Levitte* + + * Added a library context `OSSL_LIB_CTX` that applications as well as + other libraries can use to form a separate context within which + libcrypto operations are performed. + + *Richard Levitte* + + * Added various `_ex` functions to the OpenSSL API that support using + a non-default `OSSL_LIB_CTX`. + + *OpenSSL team* + + * Handshake now fails if Extended Master Secret extension is dropped + on renegotiation. + + *Tomáš Mráz* + + * Dropped interactive mode from the `openssl` program. + + *Richard Levitte* + + * Deprecated `EVP_PKEY_cmp()` and `EVP_PKEY_cmp_parameters()`. + + *David von Oheimb and Shane Lontis* + + * Deprecated `EC_METHOD_get_field_type()`. + + *Billy Bob Brumley* + + * Deprecated EC_GFp_simple_method(), EC_GFp_mont_method(), + EC_GF2m_simple_method(), EC_GFp_nist_method(), EC_GFp_nistp224_method() + EC_GFp_nistp256_method(), and EC_GFp_nistp521_method(). + + *Billy Bob Brumley* + + * Deprecated EC_GROUP_new(), EC_GROUP_method_of(), and EC_POINT_method_of(). + + *Billy Bob Brumley* + + * Add CAdES-BES signature verification support, mostly derived + from ESSCertIDv2 TS (RFC 5816) contribution by Marek Klein. + + *Filipe Raimundo da Silva* + + * Add CAdES-BES signature scheme and attributes support (RFC 5126) to CMS API. + + *Antonio Iacono* + + * Added the AuthEnvelopedData content type structure (RFC 5083) with AES-GCM + parameter (RFC 5084) for the Cryptographic Message Syntax (CMS). + + *Jakub Zelenka* + + * Deprecated EC_POINT_make_affine() and EC_POINTs_make_affine(). + + *Billy Bob Brumley* + + * Deprecated EC_GROUP_precompute_mult(), EC_GROUP_have_precompute_mult(), and + EC_KEY_precompute_mult(). + + *Billy Bob Brumley* + + * Deprecated EC_POINTs_mul(). + + *Billy Bob Brumley* + + * Removed FIPS_mode() and FIPS_mode_set(). + + *Shane Lontis* + + * The SSL option SSL_OP_IGNORE_UNEXPECTED_EOF is introduced. + + *Dmitry Belyavskiy* + + * Deprecated EC_POINT_set_Jprojective_coordinates_GFp() and + EC_POINT_get_Jprojective_coordinates_GFp(). + + *Billy Bob Brumley* + + * Added OSSL_PARAM_BLD to the public interface. This allows OSSL_PARAM + arrays to be more easily constructed via a series of utility functions. + Create a parameter builder using OSSL_PARAM_BLD_new(), add parameters using + the various push functions and finally convert to a passable OSSL_PARAM + array using OSSL_PARAM_BLD_to_param(). + + *Paul Dale* + + * The security strength of SHA1 and MD5 based signatures in TLS has been + reduced. + + *Kurt Roeckx* + + * Added EVP_PKEY_set_type_by_keymgmt(), to initialise an EVP_PKEY to + contain a provider side internal key. + + *Richard Levitte* + + * ASN1_verify(), ASN1_digest() and ASN1_sign() have been deprecated. + + *Richard Levitte* + + * Project text documents not yet having a proper file name extension + (`HACKING`, `LICENSE`, `NOTES*`, `README*`, `VERSION`) have been renamed to + `*.md` as far as reasonable, else `*.txt`, for better use with file managers. + + *David von Oheimb* + + * The main project documents (README, NEWS, CHANGES, INSTALL, SUPPORT) + have been converted to Markdown with the goal to produce documents + which not only look pretty when viewed online in the browser, but + remain well readable inside a plain text editor. + + To achieve this goal, a 'minimalistic' Markdown style has been applied + which avoids formatting elements that interfere too much with the + reading flow in the text file. For example, it + + * avoids [ATX headings][] and uses [setext headings][] instead + (which works for `

` and `

` headings only). + * avoids [inline links][] and uses [reference links][] instead. + * avoids [fenced code blocks][] and uses [indented code blocks][] instead. + + [ATX headings]: https://github.github.com/gfm/#atx-headings + [setext headings]: https://github.github.com/gfm/#setext-headings + [inline links]: https://github.github.com/gfm/#inline-link + [reference links]: https://github.github.com/gfm/#reference-link + [fenced code blocks]: https://github.github.com/gfm/#fenced-code-blocks + [indented code blocks]: https://github.github.com/gfm/#indented-code-blocks + + *Matthias St. Pierre* + + * The test suite is changed to preserve results of each test recipe. + A new directory test-runs/ with subdirectories named like the + test recipes are created in the build tree for this purpose. + + *Richard Levitte* + + * Added an implementation of CMP and CRMF (RFC 4210, RFC 4211 RFC 6712). + This adds `crypto/cmp/`, `crpyto/crmf/`, `apps/cmp.c`, and `test/cmp_*`. + See L and L as starting points. + + *David von Oheimb, Martin Peylo* + + * Generalized the HTTP client code from `crypto/ocsp/` into `crpyto/http/`. + It supports arbitrary request and response content types, GET redirection, + TLS, connections via HTTP(S) proxies, connections and exchange via + user-defined BIOs (allowing implicit connections), persistent connections, + and timeout checks. See L etc. for details. + The legacy OCSP-focused (and only partly documented) API + is retained for backward compatibility, while most of it is deprecated. + + *David von Oheimb* + + * Added `util/check-format.pl`, a tool for checking adherence to the + OpenSSL coding style . + The checks performed are incomplete and yield some false positives. + Still the tool should be useful for detecting most typical glitches. + + *David von Oheimb* + + * `BIO_do_connect()` and `BIO_do_handshake()` have been extended: + If domain name resolution yields multiple IP addresses all of them are tried + after `connect()` failures. + + *David von Oheimb* + + * All of the low level RSA functions have been deprecated. + + *Paul Dale* + + * X509 certificates signed using SHA1 are no longer allowed at security + level 1 and above. + + *Kurt Roeckx* + + * The command line utilities dhparam, dsa, gendsa and dsaparam have been + modified to use PKEY APIs. These commands are now in maintenance mode + and no new features will be added to them. + + *Paul Dale* + + * The command line utility rsautl has been deprecated. + + *Paul Dale* + + * The command line utilities genrsa and rsa have been modified to use PKEY + APIs. They now write PKCS#8 keys by default. These commands are now in + maintenance mode and no new features will be added to them. + + *Paul Dale* + + * All of the low level DH functions have been deprecated. + + *Paul Dale and Matt Caswell* + + * All of the low level DSA functions have been deprecated. + + *Paul Dale* + + * Reworked the treatment of EC EVP_PKEYs with the SM2 curve to + automatically become EVP_PKEY_SM2 rather than EVP_PKEY_EC. + + *Richard Levitte* + + * Deprecated low level ECDH and ECDSA functions. + + *Paul Dale* + + * Deprecated EVP_PKEY_decrypt_old() and EVP_PKEY_encrypt_old(). + + *Richard Levitte* + + * Enhanced the documentation of EVP_PKEY_get_size(), EVP_PKEY_get_bits() + and EVP_PKEY_get_security_bits(). Especially EVP_PKEY_get_size() needed + a new formulation to include all the things it can be used for, + as well as words of caution. + + *Richard Levitte* + + * The SSL_CTX_set_tlsext_ticket_key_cb(3) function has been deprecated. + + *Paul Dale* + + * All of the low level HMAC functions have been deprecated. + + *Paul Dale and David von Oheimb* + + * Over two thousand fixes were made to the documentation, including: + - Common options (such as -rand/-writerand, TLS version control, etc) + were refactored and point to newly-enhanced descriptions in openssl.pod. + - Added style conformance for all options (with help from Richard Levitte), + documented all reported missing options, added a CI build to check + that all options are documented and that no unimplemented options + are documented. + - Documented some internals, such as all use of environment variables. + - Addressed all internal broken L<> references. + + *Rich Salz* + + * All of the low level CMAC functions have been deprecated. + + *Paul Dale* + + * The low-level MD2, MD4, MD5, MDC2, RIPEMD160 and Whirlpool digest + functions have been deprecated. + + *Paul Dale and David von Oheimb* + + * Corrected the documentation of the return values from the `EVP_DigestSign*` + set of functions. The documentation mentioned negative values for some + errors, but this was never the case, so the mention of negative values + was removed. + + Code that followed the documentation and thereby check with something + like `EVP_DigestSignInit(...) <= 0` will continue to work undisturbed. + + *Richard Levitte* + + * All of the low level cipher functions have been deprecated. + + *Matt Caswell and Paul Dale* + + * Removed include/openssl/opensslconf.h.in and replaced it with + include/openssl/configuration.h.in, which differs in not including + . A short header include/openssl/opensslconf.h + was added to include both. + + This allows internal hacks where one might need to modify the set + of configured macros, for example this if deprecated symbols are + still supposed to be available internally: + + #include + + #undef OPENSSL_NO_DEPRECATED + #define OPENSSL_SUPPRESS_DEPRECATED + + #include + + This should not be used by applications that use the exported + symbols, as that will lead to linking errors. + + *Richard Levitte* + + * Fixed an overflow bug in the x64_64 Montgomery squaring procedure + used in exponentiation with 512-bit moduli. No EC algorithms are + affected. Analysis suggests that attacks against 2-prime RSA1024, + 3-prime RSA1536, and DSA1024 as a result of this defect would be very + difficult to perform and are not believed likely. Attacks against DH512 + are considered just feasible. However, for an attack the target would + have to re-use the DH512 private key, which is not recommended anyway. + Also applications directly using the low-level API BN_mod_exp may be + affected if they use BN_FLG_CONSTTIME. + ([CVE-2019-1551]) + + *Andy Polyakov* + + * Most memory-debug features have been deprecated, and the functionality + replaced with no-ops. + + *Rich Salz* + + * Added documentation for the STACK API. + + *Rich Salz* + + * Introduced a new method type and API, OSSL_ENCODER, to represent + generic encoders. These do the same sort of job that PEM writers + and d2i functions do, but with support for methods supplied by + providers, and the possibility for providers to support other + formats as well. + + *Richard Levitte* + + * Introduced a new method type and API, OSSL_DECODER, to represent + generic decoders. These do the same sort of job that PEM readers + and i2d functions do, but with support for methods supplied by + providers, and the possibility for providers to support other + formats as well. + + *Richard Levitte* + + * Added a .pragma directive to the syntax of configuration files, to + allow varying behavior in a supported and predictable manner. + Currently added pragma: + + .pragma dollarid:on + + This allows dollar signs to be a keyword character unless it's + followed by a opening brace or parenthesis. This is useful for + platforms where dollar signs are commonly used in names, such as + volume names and system directory names on VMS. + + *Richard Levitte* + + * Added functionality to create an EVP_PKEY from user data. + + *Richard Levitte* + + * Change the interpretation of the '--api' configuration option to + mean that this is a desired API compatibility level with no + further meaning. The previous interpretation, that this would + also mean to remove all deprecated symbols up to and including + the given version, no requires that 'no-deprecated' is also used + in the configuration. + + When building applications, the desired API compatibility level + can be set with the OPENSSL_API_COMPAT macro like before. For + API compatibility version below 3.0, the old style numerical + value is valid as before, such as -DOPENSSL_API_COMPAT=0x10100000L. + For version 3.0 and on, the value is expected to be the decimal + value calculated from the major and minor version like this: + + MAJOR * 10000 + MINOR * 100 + + Examples: + + -DOPENSSL_API_COMPAT=30000 For 3.0 + -DOPENSSL_API_COMPAT=30200 For 3.2 + + To hide declarations that are deprecated up to and including the + given API compatibility level, -DOPENSSL_NO_DEPRECATED must be + given when building the application as well. + + *Richard Levitte* + + * Added the X509_LOOKUP_METHOD called X509_LOOKUP_store, to allow + access to certificate and CRL stores via URIs and OSSL_STORE + loaders. + + This adds the following functions: + + - X509_LOOKUP_store() + - X509_STORE_load_file() + - X509_STORE_load_path() + - X509_STORE_load_store() + - SSL_add_store_cert_subjects_to_stack() + - SSL_CTX_set_default_verify_store() + - SSL_CTX_load_verify_file() + - SSL_CTX_load_verify_dir() + - SSL_CTX_load_verify_store() + + *Richard Levitte* + + * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. + The presence of this system service is determined at run-time. + + *Richard Levitte* + + * Added functionality to create an EVP_PKEY context based on data + for methods from providers. This takes an algorithm name and a + property query string and simply stores them, with the intent + that any operation that uses this context will use those strings + to fetch the needed methods implicitly, thereby making the port + of application written for pre-3.0 OpenSSL easier. + + *Richard Levitte* + + * The undocumented function NCONF_WIN32() has been deprecated; for + conversion details see the HISTORY section of doc/man5/config.pod + + *Rich Salz* + + * Introduced the new functions EVP_DigestSignInit_ex() and + EVP_DigestVerifyInit_ex(). The macros EVP_DigestSignUpdate() and + EVP_DigestVerifyUpdate() have been converted to functions. See the man + pages for further details. + + *Matt Caswell* + + * Over two thousand fixes were made to the documentation, including: + adding missing command flags, better style conformance, documentation + of internals, etc. + + *Rich Salz, Richard Levitte* + + * s390x assembly pack: add hardware-support for P-256, P-384, P-521, + X25519, X448, Ed25519 and Ed448. + + *Patrick Steuer* + + * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just + the first value. + + *Jon Spillett* + + * Deprecated the public definition of `ERR_STATE` as well as the function + `ERR_get_state()`. This is done in preparation of making `ERR_STATE` an + opaque type. + + *Richard Levitte* + + * Added ERR functionality to give callers access to the stored function + names that have replaced the older function code based functions. + + New functions are ERR_peek_error_func(), ERR_peek_last_error_func(), + ERR_peek_error_data(), ERR_peek_last_error_data(), ERR_get_error_all(), + ERR_peek_error_all() and ERR_peek_last_error_all(). + + Deprecate ERR functions ERR_get_error_line(), ERR_get_error_line_data(), + ERR_peek_error_line_data(), ERR_peek_last_error_line_data() and + ERR_func_error_string(). + + *Richard Levitte* + + * Extended testing to be verbose for failing tests only. The make variables + VERBOSE_FAILURE or VF can be used to enable this: + + $ make VF=1 test # Unix + $ mms /macro=(VF=1) test ! OpenVMS + $ nmake VF=1 test # Windows + + *Richard Levitte* + + * Added the `-copy_extensions` option to the `x509` command for use with + `-req` and `-x509toreq`. When given with the `copy` or `copyall` argument, + all extensions in the request are copied to the certificate or vice versa. + + *David von Oheimb*, *Kirill Stefanenkov * + + * Added the `-copy_extensions` option to the `req` command for use with + `-x509`. When given with the `copy` or `copyall` argument, + all extensions in the certification request are copied to the certificate. + + *David von Oheimb* + + * The `x509`, `req`, and `ca` commands now make sure that X.509v3 certificates + they generate are by default RFC 5280 compliant in the following sense: + There is a subjectKeyIdentifier extension with a hash value of the public key + and for not self-signed certs there is an authorityKeyIdentifier extension + with a keyIdentifier field or issuer information identifying the signing key. + This is done unless some configuration overrides the new default behavior, + such as `subjectKeyIdentifier = none` and `authorityKeyIdentifier = none`. + + *David von Oheimb* + + * Added several checks to `X509_verify_cert()` according to requirements in + RFC 5280 in case `X509_V_FLAG_X509_STRICT` is set + (which may be done by using the CLI option `-x509_strict`): + * The basicConstraints of CA certificates must be marked critical. + * CA certificates must explicitly include the keyUsage extension. + * If a pathlenConstraint is given the key usage keyCertSign must be allowed. + * The issuer name of any certificate must not be empty. + * The subject name of CA certs, certs with keyUsage crlSign, + and certs without subjectAlternativeName must not be empty. + * If a subjectAlternativeName extension is given it must not be empty. + * The signatureAlgorithm field and the cert signature must be consistent. + * Any given authorityKeyIdentifier and any given subjectKeyIdentifier + must not be marked critical. + * The authorityKeyIdentifier must be given for X.509v3 certs + unless they are self-signed. + * The subjectKeyIdentifier must be given for all X.509v3 CA certs. + + *David von Oheimb* + + * Certificate verification using `X509_verify_cert()` meanwhile rejects EC keys + with explicit curve parameters (specifiedCurve) as required by RFC 5480. + + *Tomáš Mráz* + + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters, when loading a encoded key + or calling `EC_GROUP_new_from_ecpkparameters()`/ + `EC_GROUP_new_from_ecparameters()`. + This prevents bypass of security hardening and performance gains, + especially for curves with specialized EC_METHODs. + By default, if a key encoded with explicit parameters is loaded and later + encoded, the output is still encoded with explicit parameters, even if + internally a "named" EC_GROUP is used for computation. + + *Nicola Tuveri* + + * Compute ECC cofactors if not provided during EC_GROUP construction. Before + this change, EC_GROUP_set_generator would accept order and/or cofactor as + NULL. After this change, only the cofactor parameter can be NULL. It also + does some minimal sanity checks on the passed order. + ([CVE-2019-1547]) + + *Billy Bob Brumley* + + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey. + An attack is simple, if the first CMS_recipientInfo is valid but the + second CMS_recipientInfo is chosen ciphertext. If the second + recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct + encryption key will be replaced by garbage, and the message cannot be + decoded, but if the RSA decryption fails, the correct encryption key is + used and the recipient will not notice the attack. + As a work around for this potential attack the length of the decrypted + key must be equal to the cipher default key length, in case the + certifiate is not given and all recipientInfo are tried out. + The old behaviour can be re-enabled in the CMS code by setting the + CMS_DEBUG_DECRYPT flag. + + *Bernd Edlinger* + + * Early start up entropy quality from the DEVRANDOM seed source has been + improved for older Linux systems. The RAND subsystem will wait for + /dev/random to be producing output before seeding from /dev/urandom. + The seeded state is stored for future library initialisations using + a system global shared memory segment. The shared memory identifier + can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to + the desired value. The default identifier is 114. + + *Paul Dale* + + * Revised BN_generate_prime_ex to not avoid factors 2..17863 in p-1 + when primes for RSA keys are computed. + Since we previously always generated primes == 2 (mod 3) for RSA keys, + the 2-prime and 3-prime RSA modules were easy to distinguish, since + `N = p*q = 1 (mod 3)`, but `N = p*q*r = 2 (mod 3)`. Therefore fingerprinting + 2-prime vs. 3-prime RSA keys was possible by computing N mod 3. + This avoids possible fingerprinting of newly generated RSA modules. + + *Bernd Edlinger* + + * Correct the extended master secret constant on EBCDIC systems. Without this + fix TLS connections between an EBCDIC system and a non-EBCDIC system that + negotiate EMS will fail. Unfortunately this also means that TLS connections + between EBCDIC systems with this fix, and EBCDIC systems without this + fix will fail if they negotiate EMS. + + *Matt Caswell* + + * Changed the library initialisation so that the config file is now loaded + by default. This was already the case for libssl. It now occurs for both + libcrypto and libssl. Use the OPENSSL_INIT_NO_LOAD_CONFIG option to + `OPENSSL_init_crypto()` to suppress automatic loading of a config file. + + *Matt Caswell* + + * Introduced new error raising macros, `ERR_raise()` and `ERR_raise_data()`, + where the former acts as a replacement for `ERR_put_error()`, and the + latter replaces the combination `ERR_put_error()` + `ERR_add_error_data()`. + `ERR_raise_data()` adds more flexibility by taking a format string and + an arbitrary number of arguments following it, to be processed with + `BIO_snprintf()`. + + *Richard Levitte* + + * Introduced a new function, `OSSL_PROVIDER_available()`, which can be used + to check if a named provider is loaded and available. When called, it + will also activate all fallback providers if such are still present. + + *Richard Levitte* + + * Enforce a minimum DH modulus size of 512 bits. + + *Bernd Edlinger* + + * Changed DH parameters to generate the order q subgroup instead of 2q. + Previously generated DH parameters are still accepted by DH_check + but DH_generate_key works around that by clearing bit 0 of the + private key for those. This avoids leaking bit 0 of the private key. + + *Bernd Edlinger* + + * Significantly reduce secure memory usage by the randomness pools. + + *Paul Dale* + + * `{CRYPTO,OPENSSL}_mem_debug_{push,pop}` are now no-ops and have been + deprecated. + + *Rich Salz* + + * A new type, EVP_KEYEXCH, has been introduced to represent key exchange + algorithms. An implementation of a key exchange algorithm can be obtained + by using the function EVP_KEYEXCH_fetch(). An EVP_KEYEXCH algorithm can be + used in a call to EVP_PKEY_derive_init_ex() which works in a similar way to + the older EVP_PKEY_derive_init() function. See the man pages for the new + functions for further details. + + *Matt Caswell* + + * The EVP_PKEY_CTX_set_dh_pad() macro has now been converted to a function. + + *Matt Caswell* + + * Removed the function names from error messages and deprecated the + xxx_F_xxx define's. + + *Richard Levitte* + + * Removed NextStep support and the macro OPENSSL_UNISTD + + *Rich Salz* + + * Removed DES_check_key. Also removed OPENSSL_IMPLEMENT_GLOBAL, + OPENSSL_GLOBAL_REF, OPENSSL_DECLARE_GLOBAL. + Also removed "export var as function" capability; we do not export + variables, only functions. + + *Rich Salz* + + * RC5_32_set_key has been changed to return an int type, with 0 indicating + an error and 1 indicating success. In previous versions of OpenSSL this + was a void type. If a key was set longer than the maximum possible this + would crash. + + *Matt Caswell* + + * Support SM2 signing and verification schemes with X509 certificate. + + *Paul Yang* + + * Use SHA256 as the default digest for TS query in the `ts` app. + + *Tomáš Mráz* + + * Change PBKDF2 to conform to SP800-132 instead of the older PKCS5 RFC2898. + + *Shane Lontis* + + * Default cipher lists/suites are now available via a function, the + #defines are deprecated. + + *Todd Short* + + * Add target VC-WIN32-UWP, VC-WIN64A-UWP, VC-WIN32-ARM-UWP and + VC-WIN64-ARM-UWP in Windows OneCore target for making building libraries + for Windows Store apps easier. Also, the "no-uplink" option has been added. + + *Kenji Mouri* + + * Join the directories crypto/x509 and crypto/x509v3 + + *Richard Levitte* + + * Added command 'openssl kdf' that uses the EVP_KDF API. + + *Shane Lontis* + + * Added command 'openssl mac' that uses the EVP_MAC API. + + *Shane Lontis* + + * Added OPENSSL_info() to get diverse built-in OpenSSL data, such + as default directories. Also added the command 'openssl info' + for scripting purposes. + + *Richard Levitte* + + * The functions AES_ige_encrypt() and AES_bi_ige_encrypt() have been + deprecated. + + *Matt Caswell* + + * Add prediction resistance to the DRBG reseeding process. + + *Paul Dale* + + * Limit the number of blocks in a data unit for AES-XTS to 2^20 as + mandated by IEEE Std 1619-2018. + + *Paul Dale* + + * Added newline escaping functionality to a filename when using openssl dgst. + This output format is to replicate the output format found in the `*sum` + checksum programs. This aims to preserve backward compatibility. + + *Matt Eaton, Richard Levitte, and Paul Dale* + + * Removed the heartbeat message in DTLS feature, as it has very + little usage and doesn't seem to fulfill a valuable purpose. + The configuration option is now deprecated. + + *Richard Levitte* + + * Changed the output of 'openssl {digestname} < file' to display the + digest name in its output. + + *Richard Levitte* + + * Added a new generic trace API which provides support for enabling + instrumentation through trace output. + + *Richard Levitte & Matthias St. Pierre* + + * Added build tests for C++. These are generated files that only do one + thing, to include one public OpenSSL head file each. This tests that + the public header files can be usefully included in a C++ application. + + This test isn't enabled by default. It can be enabled with the option + 'enable-buildtest-c++'. + + *Richard Levitte* + + * Added KB KDF (EVP_KDF_KB) to EVP_KDF. + + *Robbie Harwood* + + * Added SSH KDF (EVP_KDF_SSHKDF) and KRB5 KDF (EVP_KDF_KRB5KDF) to EVP_KDF. + + *Simo Sorce* + + * Added Single Step KDF (EVP_KDF_SS), X963 KDF, and X942 KDF to EVP_KDF. + + *Shane Lontis* + + * Added KMAC to EVP_MAC. + + *Shane Lontis* + + * Added property based algorithm implementation selection framework to + the core. + + *Paul Dale* + + * Added SCA hardening for modular field inversion in EC_GROUP through + a new dedicated field_inv() pointer in EC_METHOD. + This also addresses a leakage affecting conversions from projective + to affine coordinates. + + *Billy Bob Brumley, Nicola Tuveri* + + * Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF + implementations. This includes an EVP_PKEY to EVP_KDF bridge for + those algorithms that were already supported through the EVP_PKEY API + (scrypt, TLS1 PRF and HKDF). The low-level KDF functions for PBKDF2 + and scrypt are now wrappers that call EVP_KDF. + + *David Makepeace* + + * Build devcrypto engine as a dynamic engine. + + *Eneas U de Queiroz* + + * Add keyed BLAKE2 to EVP_MAC. + + *Antoine Salon* + + * Fix a bug in the computation of the endpoint-pair shared secret used + by DTLS over SCTP. This breaks interoperability with older versions + of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime + switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling + interoperability with such broken implementations. However, enabling + this switch breaks interoperability with correct implementations. + + * Fix a use after free bug in d2i_X509_PUBKEY when overwriting a + re-used X509_PUBKEY object if the second PUBKEY is malformed. + + *Bernd Edlinger* + + * Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0(). + + *Richard Levitte* + + * Changed the license to the Apache License v2.0. + + *Richard Levitte* + + * Switch to a new version scheme using three numbers MAJOR.MINOR.PATCH. + + - Major releases (indicated by incrementing the MAJOR release number) + may introduce incompatible API/ABI changes. + - Minor releases (indicated by incrementing the MINOR release number) + may introduce new features but retain API/ABI compatibility. + - Patch releases (indicated by incrementing the PATCH number) + are intended for bug fixes and other improvements of existing + features only (like improving performance or adding documentation) + and retain API/ABI compatibility. + + *Richard Levitte* + + * Add support for RFC5297 SIV mode (siv128), including AES-SIV. + + *Todd Short* + + * Remove the 'dist' target and add a tarball building script. The + 'dist' target has fallen out of use, and it shouldn't be + necessary to configure just to create a source distribution. + + *Richard Levitte* + + * Recreate the OS390-Unix config target. It no longer relies on a + special script like it did for OpenSSL pre-1.1.0. + + *Richard Levitte* + + * Instead of having the source directories listed in Configure, add + a 'build.info' keyword SUBDIRS to indicate what sub-directories to + look into. + + *Richard Levitte* + + * Add GMAC to EVP_MAC. + + *Paul Dale* + + * Ported the HMAC, CMAC and SipHash EVP_PKEY_METHODs to EVP_MAC. + + *Richard Levitte* + + * Added EVP_MAC, an EVP layer MAC API, to simplify adding MAC + implementations. This includes a generic EVP_PKEY to EVP_MAC bridge, + to facilitate the continued use of MACs through raw private keys in + functionality such as `EVP_DigestSign*` and `EVP_DigestVerify*`. + + *Richard Levitte* + + * Deprecate ECDH_KDF_X9_62(). + + *Antoine Salon* + + * Added EVP_PKEY_ECDH_KDF_X9_63 and ecdh_KDF_X9_63() as replacements for + the EVP_PKEY_ECDH_KDF_X9_62 KDF type and ECDH_KDF_X9_62(). The old names + are retained for backwards compatibility. + + *Antoine Salon* + + * AES-XTS mode now enforces that its two keys are different to mitigate + the attacked described in "Efficient Instantiations of Tweakable + Blockciphers and Refinements to Modes OCB and PMAC" by Phillip Rogaway. + Details of this attack can be obtained from: + + + *Paul Dale* + + * Rename the object files, i.e. give them other names than in previous + versions. Their names now include the name of the final product, as + well as its type mnemonic (bin, lib, shlib). + + *Richard Levitte* + + * Added new option for 'openssl list', '-objects', which will display the + list of built in objects, i.e. OIDs with names. + + *Richard Levitte* + + * Added the options `-crl_lastupdate` and `-crl_nextupdate` to `openssl ca`, + allowing the `lastUpdate` and `nextUpdate` fields in the generated CRL to + be set explicitly. + + *Chris Novakovic* + + * Added support for Linux Kernel TLS data-path. The Linux Kernel data-path + improves application performance by removing data copies and providing + applications with zero-copy system calls such as sendfile and splice. + + *Boris Pismenny* + + * The SSL option SSL_OP_CLEANSE_PLAINTEXT is introduced. + + *Martin Elshuber* + + * `PKCS12_parse` now maintains the order of the parsed certificates + when outputting them via `*ca` (rather than reversing it). + + *David von Oheimb* + + * Deprecated pthread fork support methods. + + *Randall S. Becker* + + * Added support for FFDHE key exchange in TLS 1.3. + + *Raja Ashok* + + * Added a new concept for OpenSSL plugability: providers. This + functionality is designed to replace the ENGINE API and ENGINE + implementations, and to be much more dynamic, allowing provider + authors to introduce new algorithms among other things, as long as + there's an API that supports the algorithm type. + + With this concept comes a new core API for interaction between + libcrypto and provider implementations. Public libcrypto functions + that want to use providers do so through this core API. + + The main documentation for this core API is found in + doc/man7/provider.pod, doc/man7/provider-base.pod, and they in turn + refer to other manuals describing the API specific for supported + algorithm types (also called operations). + + *The OpenSSL team* + +OpenSSL 1.1.1 +------------- + +### Changes between 1.1.1l and 1.1.1m [xx XXX xxxx] + + * Avoid loading of a dynamic engine twice. + + *Bernd Edlinger* + + * Prioritise DANE TLSA issuer certs over peer certs + + *Viktor Dukhovni* + + * Fixed random API for MacOS prior to 10.12 + + These MacOS versions don't support the CommonCrypto APIs + + *Lenny Primak* + +### Changes between 1.1.1k and 1.1.1l [24 Aug 2021] + + * Fixed an SM2 Decryption Buffer Overflow. + + In order to decrypt SM2 encrypted data an application is expected to + call the API function EVP_PKEY_decrypt(). Typically an application will + call this function twice. The first time, on entry, the "out" parameter + can be NULL and, on exit, the "outlen" parameter is populated with the + buffer size required to hold the decrypted plaintext. The application + can then allocate a sufficiently sized buffer and call EVP_PKEY_decrypt() + again, but this time passing a non-NULL value for the "out" parameter. + + A bug in the implementation of the SM2 decryption code means that the + calculation of the buffer size required to hold the plaintext returned + by the first call to EVP_PKEY_decrypt() can be smaller than the actual + size required by the second call. This can lead to a buffer overflow + when EVP_PKEY_decrypt() is called by the application a second time with + a buffer that is too small. + + A malicious attacker who is able present SM2 content for decryption to + an application could cause attacker chosen data to overflow the buffer + by up to a maximum of 62 bytes altering the contents of other data held + after the buffer, possibly changing application behaviour or causing + the application to crash. The location of the buffer is application + dependent but is typically heap allocated. + ([CVE-2021-3711]) + + *Matt Caswell* + + * Fixed various read buffer overruns processing ASN.1 strings + + ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING + structure which contains a buffer holding the string data and a field + holding the buffer length. This contrasts with normal C strings which + are repesented as a buffer for the string data which is terminated + with a NUL (0) byte. + + Although not a strict requirement, ASN.1 strings that are parsed using + OpenSSL's own "d2i" functions (and other similar parsing functions) as + well as any string whose value has been set with the ASN1_STRING_set() + function will additionally NUL terminate the byte array in the + ASN1_STRING structure. + + However, it is possible for applications to directly construct valid + ASN1_STRING structures which do not NUL terminate the byte array by + directly setting the "data" and "length" fields in the ASN1_STRING + array. This can also happen by using the ASN1_STRING_set0() function. + + Numerous OpenSSL functions that print ASN.1 data have been found to + assume that the ASN1_STRING byte array will be NUL terminated, even + though this is not guaranteed for strings that have been directly + constructed. Where an application requests an ASN.1 structure to be + printed, and where that ASN.1 structure contains ASN1_STRINGs that have + been directly constructed by the application without NUL terminating + the "data" field, then a read buffer overrun can occur. + + The same thing can also occur during name constraints processing + of certificates (for example if a certificate has been directly + constructed by the application instead of loading it via the OpenSSL + parsing functions, and the certificate contains non NUL terminated + ASN1_STRING structures). It can also occur in the X509_get1_email(), + X509_REQ_get1_email() and X509_get1_ocsp() functions. + + If a malicious actor can cause an application to directly construct an + ASN1_STRING and then process it through one of the affected OpenSSL + functions then this issue could be hit. This might result in a crash + (causing a Denial of Service attack). It could also result in the + disclosure of private memory contents (such as private keys, or + sensitive plaintext). + ([CVE-2021-3712]) + + *Matt Caswell* + +### Changes between 1.1.1j and 1.1.1k [25 Mar 2021] + + * Fixed a problem with verifying a certificate chain when using the + X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks of + the certificates present in a certificate chain. It is not set by default. + + Starting from OpenSSL version 1.1.1h a check to disallow certificates in + the chain that have explicitly encoded elliptic curve parameters was added + as an additional strict check. + + An error in the implementation of this check meant that the result of a + previous check to confirm that certificates in the chain are valid CA + certificates was overwritten. This effectively bypasses the check + that non-CA certificates must not be able to issue other certificates. + + If a "purpose" has been configured then there is a subsequent opportunity + for checks that the certificate is a valid CA. All of the named "purpose" + values implemented in libcrypto perform this check. Therefore, where + a purpose is set the certificate chain will still be rejected even when the + strict flag has been used. A purpose is set by default in libssl client and + server certificate verification routines, but it can be overridden or + removed by an application. + + In order to be affected, an application must explicitly set the + X509_V_FLAG_X509_STRICT verification flag and either not set a purpose + for the certificate verification or, in the case of TLS client or server + applications, override the default purpose. + ([CVE-2021-3450]) + + *Tomáš Mráz* + + * Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously + crafted renegotiation ClientHello message from a client. If a TLSv1.2 + renegotiation ClientHello omits the signature_algorithms extension (where it + was present in the initial ClientHello), but includes a + signature_algorithms_cert extension then a NULL pointer dereference will + result, leading to a crash and a denial of service attack. + + A server is only vulnerable if it has TLSv1.2 and renegotiation enabled + (which is the default configuration). OpenSSL TLS clients are not impacted by + this issue. + ([CVE-2021-3449]) + + *Peter Kästle and Samuel Sapalski* + +### Changes between 1.1.1i and 1.1.1j [16 Feb 2021] + + * Fixed the X509_issuer_and_serial_hash() function. It attempts to + create a unique hash value based on the issuer and serial number data + contained within an X509 certificate. However it was failing to correctly + handle any errors that may occur while parsing the issuer field (which might + occur if the issuer field is maliciously constructed). This may subsequently + result in a NULL pointer deref and a crash leading to a potential denial of + service attack. + ([CVE-2021-23841]) + + *Matt Caswell* + + * Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING + padding mode to correctly check for rollback attacks. This is considered a + bug in OpenSSL 1.1.1 because it does not support SSLv2. In 1.0.2 this is + CVE-2021-23839. + + *Matt Caswell* + + Fixed the EVP_CipherUpdate, EVP_EncryptUpdate and EVP_DecryptUpdate + functions. Previously they could overflow the output length argument in some + cases where the input length is close to the maximum permissable length for + an integer on the platform. In such cases the return value from the function + call would be 1 (indicating success), but the output length value would be + negative. This could cause applications to behave incorrectly or crash. + ([CVE-2021-23840]) + + *Matt Caswell* + + * Fixed SRP_Calc_client_key so that it runs in constant time. The previous + implementation called BN_mod_exp without setting BN_FLG_CONSTTIME. This + could be exploited in a side channel attack to recover the password. Since + the attack is local host only this is outside of the current OpenSSL + threat model and therefore no CVE is assigned. + + Thanks to Mohammed Sabt and Daniel De Almeida Braga for reporting this + issue. + + *Matt Caswell* + +### Changes between 1.1.1h and 1.1.1i [8 Dec 2020] + + * Fixed NULL pointer deref in the GENERAL_NAME_cmp function + This function could crash if both GENERAL_NAMEs contain an EDIPARTYNAME. + If an attacker can control both items being compared then this could lead + to a possible denial of service attack. OpenSSL itself uses the + GENERAL_NAME_cmp function for two purposes: + 1) Comparing CRL distribution point names between an available CRL and a + CRL distribution point embedded in an X509 certificate + 2) When verifying that a timestamp response token signer matches the + timestamp authority name (exposed via the API functions + TS_RESP_verify_response and TS_RESP_verify_token) + ([CVE-2020-1971]) + + *Matt Caswell* + +### Changes between 1.1.1g and 1.1.1h [22 Sep 2020] + + * Certificates with explicit curve parameters are now disallowed in + verification chains if the X509_V_FLAG_X509_STRICT flag is used. + + *Tomáš Mráz* + + * The 'MinProtocol' and 'MaxProtocol' configuration commands now silently + ignore TLS protocol version bounds when configuring DTLS-based contexts, and + conversely, silently ignore DTLS protocol version bounds when configuring + TLS-based contexts. The commands can be repeated to set bounds of both + types. The same applies with the corresponding "min_protocol" and + "max_protocol" command-line switches, in case some application uses both TLS + and DTLS. + + SSL_CTX instances that are created for a fixed protocol version (e.g. + TLSv1_server_method()) also silently ignore version bounds. Previously + attempts to apply bounds to these protocol versions would result in an + error. Now only the "version-flexible" SSL_CTX instances are subject to + limits in configuration files in command-line options. + + *Viktor Dukhovni* + + * Handshake now fails if Extended Master Secret extension is dropped + on renegotiation. + + *Tomáš Mráz* + + * The Oracle Developer Studio compiler will start reporting deprecated APIs + +### Changes between 1.1.1f and 1.1.1g [21 Apr 2020] + + * Fixed segmentation fault in SSL_check_chain() + Server or client applications that call the SSL_check_chain() function + during or after a TLS 1.3 handshake may crash due to a NULL pointer + dereference as a result of incorrect handling of the + "signature_algorithms_cert" TLS extension. The crash occurs if an invalid + or unrecognised signature algorithm is received from the peer. This could + be exploited by a malicious peer in a Denial of Service attack. + ([CVE-2020-1967]) + + *Benjamin Kaduk* + + * Added AES consttime code for no-asm configurations + an optional constant time support for AES was added + when building openssl for no-asm. + Enable with: ./config no-asm -DOPENSSL_AES_CONST_TIME + Disable with: ./config no-asm -DOPENSSL_NO_AES_CONST_TIME + At this time this feature is by default disabled. + It will be enabled by default in 3.0. + + *Bernd Edlinger* + +### Changes between 1.1.1e and 1.1.1f [31 Mar 2020] + + * Revert the change of EOF detection while reading in libssl to avoid + regressions in applications depending on the current way of reporting + the EOF. As the existing method is not fully accurate the change to + reporting the EOF via SSL_ERROR_SSL is kept on the current development + branch and will be present in the 3.0 release. + + *Tomáš Mráz* + + * Revised BN_generate_prime_ex to not avoid factors 3..17863 in p-1 + when primes for RSA keys are computed. + Since we previously always generated primes == 2 (mod 3) for RSA keys, + the 2-prime and 3-prime RSA modules were easy to distinguish, since + N = p*q = 1 (mod 3), but N = p*q*r = 2 (mod 3). Therefore fingerprinting + 2-prime vs. 3-prime RSA keys was possible by computing N mod 3. + This avoids possible fingerprinting of newly generated RSA modules. + + *Bernd Edlinger* + +### Changes between 1.1.1d and 1.1.1e [17 Mar 2020] + + * Properly detect EOF while reading in libssl. Previously if we hit an EOF + while reading in libssl then we would report an error back to the + application (SSL_ERROR_SYSCALL) but errno would be 0. We now add + an error to the stack (which means we instead return SSL_ERROR_SSL) and + therefore give a hint as to what went wrong. + + *Matt Caswell* + + * Check that ed25519 and ed448 are allowed by the security level. Previously + signature algorithms not using an MD were not being checked that they were + allowed by the security level. + + *Kurt Roeckx* + + * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() + was not quite right. The behaviour was not consistent between resumption + and normal handshakes, and also not quite consistent with historical + behaviour. The behaviour in various scenarios has been clarified and + it has been updated to make it match historical behaviour as closely as + possible. + + *Matt Caswell* + + * *[VMS only]* The header files that the VMS compilers include automatically, + `__DECC_INCLUDE_PROLOGUE.H` and `__DECC_INCLUDE_EPILOGUE.H`, use pragmas + that the C++ compiler doesn't understand. This is a shortcoming in the + compiler, but can be worked around with `__cplusplus` guards. + + C++ applications that use OpenSSL libraries must be compiled using the + qualifier `/NAMES=(AS_IS,SHORTENED)` to be able to use all the OpenSSL + functions. Otherwise, only functions with symbols of less than 31 + characters can be used, as the linker will not be able to successfully + resolve symbols with longer names. + + *Richard Levitte* + + * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. + The presence of this system service is determined at run-time. + + *Richard Levitte* + + * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just + the first value. + + *Jon Spillett* + +### Changes between 1.1.1c and 1.1.1d [10 Sep 2019] + + * Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random + number generator (RNG). This was intended to include protection in the + event of a fork() system call in order to ensure that the parent and child + processes did not share the same RNG state. However this protection was not + being used in the default case. + + A partial mitigation for this issue is that the output from a high + precision timer is mixed into the RNG state so the likelihood of a parent + and child process sharing state is significantly reduced. + + If an application already calls OPENSSL_init_crypto() explicitly using + OPENSSL_INIT_ATFORK then this problem does not occur at all. + ([CVE-2019-1549]) + + *Matthias St. Pierre* + + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters, when loading a encoded key + or calling `EC_GROUP_new_from_ecpkparameters()`/ + `EC_GROUP_new_from_ecparameters()`. + This prevents bypass of security hardening and performance gains, + especially for curves with specialized EC_METHODs. + By default, if a key encoded with explicit parameters is loaded and later + encoded, the output is still encoded with explicit parameters, even if + internally a "named" EC_GROUP is used for computation. + + *Nicola Tuveri* + + * Compute ECC cofactors if not provided during EC_GROUP construction. Before + this change, EC_GROUP_set_generator would accept order and/or cofactor as + NULL. After this change, only the cofactor parameter can be NULL. It also + does some minimal sanity checks on the passed order. + ([CVE-2019-1547]) + + *Billy Bob Brumley* + + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey. + An attack is simple, if the first CMS_recipientInfo is valid but the + second CMS_recipientInfo is chosen ciphertext. If the second + recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct + encryption key will be replaced by garbage, and the message cannot be + decoded, but if the RSA decryption fails, the correct encryption key is + used and the recipient will not notice the attack. + As a work around for this potential attack the length of the decrypted + key must be equal to the cipher default key length, in case the + certifiate is not given and all recipientInfo are tried out. + The old behaviour can be re-enabled in the CMS code by setting the + CMS_DEBUG_DECRYPT flag. + ([CVE-2019-1563]) + + *Bernd Edlinger* + + * Early start up entropy quality from the DEVRANDOM seed source has been + improved for older Linux systems. The RAND subsystem will wait for + /dev/random to be producing output before seeding from /dev/urandom. + The seeded state is stored for future library initialisations using + a system global shared memory segment. The shared memory identifier + can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to + the desired value. The default identifier is 114. + + *Paul Dale* + + * Correct the extended master secret constant on EBCDIC systems. Without this + fix TLS connections between an EBCDIC system and a non-EBCDIC system that + negotiate EMS will fail. Unfortunately this also means that TLS connections + between EBCDIC systems with this fix, and EBCDIC systems without this + fix will fail if they negotiate EMS. + + *Matt Caswell* + + * Use Windows installation paths in the mingw builds + + Mingw isn't a POSIX environment per se, which means that Windows + paths should be used for installation. + ([CVE-2019-1552]) + + *Richard Levitte* + + * Changed DH_check to accept parameters with order q and 2q subgroups. + With order 2q subgroups the bit 0 of the private key is not secret + but DH_generate_key works around that by clearing bit 0 of the + private key for those. This avoids leaking bit 0 of the private key. + + *Bernd Edlinger* + + * Significantly reduce secure memory usage by the randomness pools. + + *Paul Dale* + + * Revert the DEVRANDOM_WAIT feature for Linux systems + + The DEVRANDOM_WAIT feature added a select() call to wait for the + /dev/random device to become readable before reading from the + /dev/urandom device. + + It turned out that this change had negative side effects on + performance which were not acceptable. After some discussion it + was decided to revert this feature and leave it up to the OS + resp. the platform maintainer to ensure a proper initialization + during early boot time. + + *Matthias St. Pierre* + +### Changes between 1.1.1b and 1.1.1c [28 May 2019] + + * Add build tests for C++. These are generated files that only do one + thing, to include one public OpenSSL head file each. This tests that + the public header files can be usefully included in a C++ application. + + This test isn't enabled by default. It can be enabled with the option + 'enable-buildtest-c++'. + + *Richard Levitte* + + * Enable SHA3 pre-hashing for ECDSA and DSA. + + *Patrick Steuer* + + * Change the default RSA, DSA and DH size to 2048 bit instead of 1024. + This changes the size when using the `genpkey` command when no size is given. + It fixes an omission in earlier changes that changed all RSA, DSA and DH + generation commands to use 2048 bits by default. + + *Kurt Roeckx* + + * Reorganize the manual pages to consistently have RETURN VALUES, + EXAMPLES, SEE ALSO and HISTORY come in that order, and adjust + util/fix-doc-nits accordingly. + + *Paul Yang, Joshua Lock* + + * Add the missing accessor EVP_PKEY_get0_engine() + + *Matt Caswell* + + * Have commands like `s_client` and `s_server` output the signature scheme + along with other cipher suite parameters when debugging. + + *Lorinczy Zsigmond* + + * Make OPENSSL_config() error agnostic again. + + *Richard Levitte* + + * Do the error handling in RSA decryption constant time. + + *Bernd Edlinger* + + * Prevent over long nonces in ChaCha20-Poly1305. + + ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input + for every encryption operation. RFC 7539 specifies that the nonce value + (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length + and front pads the nonce with 0 bytes if it is less than 12 + bytes. However it also incorrectly allows a nonce to be set of up to 16 + bytes. In this case only the last 12 bytes are significant and any + additional leading bytes are ignored. + + It is a requirement of using this cipher that nonce values are + unique. Messages encrypted using a reused nonce value are susceptible to + serious confidentiality and integrity attacks. If an application changes + the default nonce length to be longer than 12 bytes and then makes a + change to the leading bytes of the nonce expecting the new value to be a + new unique nonce then such an application could inadvertently encrypt + messages with a reused nonce. + + Additionally the ignored bytes in a long nonce are not covered by the + integrity guarantee of this cipher. Any application that relies on the + integrity of these ignored leading bytes of a long nonce may be further + affected. Any OpenSSL internal use of this cipher, including in SSL/TLS, + is safe because no such use sets such a long nonce value. However user + applications that use this cipher directly and set a non-default nonce + length to be longer than 12 bytes may be vulnerable. + + This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk + Greef of Ronomon. + ([CVE-2019-1543]) + + *Matt Caswell* + + * Add DEVRANDOM_WAIT feature for Linux systems + + On older Linux systems where the getrandom() system call is not available, + OpenSSL normally uses the /dev/urandom device for seeding its CSPRNG. + Contrary to getrandom(), the /dev/urandom device will not block during + early boot when the kernel CSPRNG has not been seeded yet. + + To mitigate this known weakness, use select() to wait for /dev/random to + become readable before reading from /dev/urandom. + + * Ensure that SM2 only uses SM3 as digest algorithm + + *Paul Yang* + +### Changes between 1.1.1a and 1.1.1b [26 Feb 2019] + + * Change the info callback signals for the start and end of a post-handshake + message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START + and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get + confused by this and assume that a TLSv1.2 renegotiation has started. This + can break KeyUpdate handling. Instead we no longer signal the start and end + of a post handshake message exchange (although the messages themselves are + still signalled). This could break some applications that were expecting + the old signals. However without this KeyUpdate is not usable for many + applications. + + *Matt Caswell* + +### Changes between 1.1.1 and 1.1.1a [20 Nov 2018] + + * Timing vulnerability in DSA signature generation + + The OpenSSL DSA signature algorithm has been shown to be vulnerable to a + timing side channel attack. An attacker could use variations in the signing + algorithm to recover the private key. + + This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser. + ([CVE-2018-0734]) + + *Paul Dale* + + * Timing vulnerability in ECDSA signature generation + + The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a + timing side channel attack. An attacker could use variations in the signing + algorithm to recover the private key. + + This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser. + ([CVE-2018-0735]) + + *Paul Dale* + + * Fixed the issue that RAND_add()/RAND_seed() silently discards random input + if its length exceeds 4096 bytes. The limit has been raised to a buffer size + of two gigabytes and the error handling improved. + + This issue was reported to OpenSSL by Dr. Falko Strenzke. It has been + categorized as a normal bug, not a security issue, because the DRBG reseeds + automatically and is fully functional even without additional randomness + provided by the application. + +### Changes between 1.1.0i and 1.1.1 [11 Sep 2018] + + * Add a new ClientHello callback. Provides a callback interface that gives + the application the ability to adjust the nascent SSL object at the + earliest stage of ClientHello processing, immediately after extensions have + been collected but before they have been processed. In particular, this + callback can adjust the supported TLS versions in response to the contents + of the ClientHello + + *Benjamin Kaduk* + + * Add SM2 base algorithm support. + + *Jack Lloyd* + + * s390x assembly pack: add (improved) hardware-support for the following + cryptographic primitives: sha3, shake, aes-gcm, aes-ccm, aes-ctr, aes-ofb, + aes-cfb/cfb8, aes-ecb. + + *Patrick Steuer* + + * Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str + parameter is no longer accepted, as it leads to a corrupt table. NULL + pem_str is reserved for alias entries only. + + *Richard Levitte* + + * Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder + step for prime curves. The new implementation is based on formulae from + differential addition-and-doubling in homogeneous projective coordinates + from Izu-Takagi "A fast parallel elliptic curve multiplication resistant + against side channel attacks" and Brier-Joye "Weierstrass Elliptic Curves + and Side-Channel Attacks" Eq. (8) for y-coordinate recovery, modified + to work in projective coordinates. + + *Billy Bob Brumley, Nicola Tuveri* + + * Change generating and checking of primes so that the error rate of not + being prime depends on the intended use based on the size of the input. + For larger primes this will result in more rounds of Miller-Rabin. + The maximal error rate for primes with more than 1080 bits is lowered + to 2^-128. + + *Kurt Roeckx, Annie Yousar* + + * Increase the number of Miller-Rabin rounds for DSA key generating to 64. + + *Kurt Roeckx* + + * The 'tsget' script is renamed to 'tsget.pl', to avoid confusion when + moving between systems, and to avoid confusion when a Windows build is + done with mingw vs with MSVC. For POSIX installs, there's still a + symlink or copy named 'tsget' to avoid that confusion as well. + + *Richard Levitte* + + * Revert blinding in ECDSA sign and instead make problematic addition + length-invariant. Switch even to fixed-length Montgomery multiplication. + + *Andy Polyakov* + + * Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder + step for binary curves. The new implementation is based on formulae from + differential addition-and-doubling in mixed Lopez-Dahab projective + coordinates, modified to independently blind the operands. + + *Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri* + + * Add a scaffold to optionally enhance the Montgomery ladder implementation + for `ec_scalar_mul_ladder` (formerly `ec_mul_consttime`) allowing + EC_METHODs to implement their own specialized "ladder step", to take + advantage of more favorable coordinate systems or more efficient + differential addition-and-doubling algorithms. + + *Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri* + + * Modified the random device based seed sources to keep the relevant + file descriptors open rather than reopening them on each access. + This allows such sources to operate in a chroot() jail without + the associated device nodes being available. This behaviour can be + controlled using RAND_keep_random_devices_open(). + + *Paul Dale* + + * Numerous side-channel attack mitigations have been applied. This may have + performance impacts for some algorithms for the benefit of improved + security. Specific changes are noted in this change log by their respective + authors. + + *Matt Caswell* + + * AIX shared library support overhaul. Switch to AIX "natural" way of + handling shared libraries, which means collecting shared objects of + different versions and bitnesses in one common archive. This allows to + mitigate conflict between 1.0 and 1.1 side-by-side installations. It + doesn't affect the way 3rd party applications are linked, only how + multi-version installation is managed. + + *Andy Polyakov* + + * Make ec_group_do_inverse_ord() more robust and available to other + EC cryptosystems, so that irrespective of BN_FLG_CONSTTIME, SCA + mitigations are applied to the fallback BN_mod_inverse(). + When using this function rather than BN_mod_inverse() directly, new + EC cryptosystem implementations are then safer-by-default. + + *Billy Bob Brumley* + + * Add coordinate blinding for EC_POINT and implement projective + coordinate blinding for generic prime curves as a countermeasure to + chosen point SCA attacks. + + *Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley* + + * Add blinding to ECDSA and DSA signatures to protect against side channel + attacks discovered by Keegan Ryan (NCC Group). + + *Matt Caswell* + + * Enforce checking in the `pkeyutl` command to ensure that the input + length does not exceed the maximum supported digest length when performing + a sign, verify or verifyrecover operation. + + *Matt Caswell* + + * SSL_MODE_AUTO_RETRY is enabled by default. Applications that use blocking + I/O in combination with something like select() or poll() will hang. This + can be turned off again using SSL_CTX_clear_mode(). + Many applications do not properly handle non-application data records, and + TLS 1.3 sends more of such records. Setting SSL_MODE_AUTO_RETRY works + around the problems in those applications, but can also break some. + It's recommended to read the manpages about SSL_read(), SSL_write(), + SSL_get_error(), SSL_shutdown(), SSL_CTX_set_mode() and + SSL_CTX_set_read_ahead() again. + + *Kurt Roeckx* + + * When unlocking a pass phrase protected PEM file or PKCS#8 container, we + now allow empty (zero character) pass phrases. + + *Richard Levitte* + + * Apply blinding to binary field modular inversion and remove patent + pending (OPENSSL_SUN_GF2M_DIV) BN_GF2m_mod_div implementation. + + *Billy Bob Brumley* + + * Deprecate ec2_mult.c and unify scalar multiplication code paths for + binary and prime elliptic curves. + + *Billy Bob Brumley* + + * Remove ECDSA nonce padding: EC_POINT_mul is now responsible for + constant time fixed point multiplication. + + *Billy Bob Brumley* + + * Revise elliptic curve scalar multiplication with timing attack + defenses: ec_wNAF_mul redirects to a constant time implementation + when computing fixed point and variable point multiplication (which + in OpenSSL are mostly used with secret scalars in keygen, sign, + ECDH derive operations). + *Billy Bob Brumley, Nicola Tuveri, Cesar Pereida García, + Sohaib ul Hassan* + + * Updated CONTRIBUTING + + *Rich Salz* + + * Updated DRBG / RAND to request nonce and additional low entropy + randomness from the system. + + *Matthias St. Pierre* + + * Updated 'openssl rehash' to use OpenSSL consistent default. + + *Richard Levitte* + + * Moved the load of the ssl_conf module to libcrypto, which helps + loading engines that libssl uses before libssl is initialised. + + *Matt Caswell* + + * Added EVP_PKEY_sign() and EVP_PKEY_verify() for EdDSA + + *Matt Caswell* + + * Fixed X509_NAME_ENTRY_set to get multi-valued RDNs right in all cases. + + *Ingo Schwarze, Rich Salz* + + * Added output of accepting IP address and port for 'openssl s_server' + + *Richard Levitte* + + * Added a new API for TLSv1.3 ciphersuites: + SSL_CTX_set_ciphersuites() + SSL_set_ciphersuites() + + *Matt Caswell* + + * Memory allocation failures consistently add an error to the error + stack. + + *Rich Salz* + + * Don't use OPENSSL_ENGINES and OPENSSL_CONF environment values + in libcrypto when run as setuid/setgid. + + *Bernd Edlinger* + + * Load any config file by default when libssl is used. + + *Matt Caswell* + + * Added new public header file and documentation + for the RAND_DRBG API. See manual page RAND_DRBG(7) for an overview. + + *Matthias St. Pierre* + + * QNX support removed (cannot find contributors to get their approval + for the license change). + + *Rich Salz* + + * TLSv1.3 replay protection for early data has been implemented. See the + SSL_read_early_data() man page for further details. + + *Matt Caswell* + + * Separated TLSv1.3 ciphersuite configuration out from TLSv1.2 ciphersuite + configuration. TLSv1.3 ciphersuites are not compatible with TLSv1.2 and + below. Similarly TLSv1.2 ciphersuites are not compatible with TLSv1.3. + In order to avoid issues where legacy TLSv1.2 ciphersuite configuration + would otherwise inadvertently disable all TLSv1.3 ciphersuites the + configuration has been separated out. See the ciphers man page or the + SSL_CTX_set_ciphersuites() man page for more information. + + *Matt Caswell* + + * On POSIX (BSD, Linux, ...) systems the ocsp(1) command running + in responder mode now supports the new "-multi" option, which + spawns the specified number of child processes to handle OCSP + requests. The "-timeout" option now also limits the OCSP + responder's patience to wait to receive the full client request + on a newly accepted connection. Child processes are respawned + as needed, and the CA index file is automatically reloaded + when changed. This makes it possible to run the "ocsp" responder + as a long-running service, making the OpenSSL CA somewhat more + feature-complete. In this mode, most diagnostic messages logged + after entering the event loop are logged via syslog(3) rather than + written to stderr. + + *Viktor Dukhovni* + + * Added support for X448 and Ed448. Heavily based on original work by + Mike Hamburg. + + *Matt Caswell* + + * Extend OSSL_STORE with capabilities to search and to narrow the set of + objects loaded. This adds the functions OSSL_STORE_expect() and + OSSL_STORE_find() as well as needed tools to construct searches and + get the search data out of them. + + *Richard Levitte* + + * Support for TLSv1.3 added. Note that users upgrading from an earlier + version of OpenSSL should review their configuration settings to ensure + that they are still appropriate for TLSv1.3. For further information see: + + + *Matt Caswell* + + * Grand redesign of the OpenSSL random generator + + The default RAND method now utilizes an AES-CTR DRBG according to + NIST standard SP 800-90Ar1. The new random generator is essentially + a port of the default random generator from the OpenSSL FIPS 2.0 + object module. It is a hybrid deterministic random bit generator + using an AES-CTR bit stream and which seeds and reseeds itself + automatically using trusted system entropy sources. + + Some of its new features are: + - Support for multiple DRBG instances with seed chaining. + - The default RAND method makes use of a DRBG. + - There is a public and private DRBG instance. + - The DRBG instances are fork-safe. + - Keep all global DRBG instances on the secure heap if it is enabled. + - The public and private DRBG instance are per thread for lock free + operation + + *Paul Dale, Benjamin Kaduk, Kurt Roeckx, Rich Salz, Matthias St. Pierre* + + * Changed Configure so it only says what it does and doesn't dump + so much data. Instead, ./configdata.pm should be used as a script + to display all sorts of configuration data. + + *Richard Levitte* + + * Added processing of "make variables" to Configure. + + *Richard Levitte* + + * Added SHA512/224 and SHA512/256 algorithm support. + + *Paul Dale* + + * The last traces of Netware support, first removed in 1.1.0, have + now been removed. + + *Rich Salz* + + * Get rid of Makefile.shared, and in the process, make the processing + of certain files (rc.obj, or the .def/.map/.opt files produced from + the ordinal files) more visible and hopefully easier to trace and + debug (or make silent). + + *Richard Levitte* + + * Make it possible to have environment variable assignments as + arguments to config / Configure. + + *Richard Levitte* + + * Add multi-prime RSA (RFC 8017) support. + + *Paul Yang* + + * Add SM3 implemented according to GB/T 32905-2016 + *Jack Lloyd ,* + *Ronald Tse ,* + *Erick Borsboom * + + * Add 'Maximum Fragment Length' TLS extension negotiation and support + as documented in RFC6066. + Based on a patch from Tomasz Moń + + *Filipe Raimundo da Silva* + + * Add SM4 implemented according to GB/T 32907-2016. + *Jack Lloyd ,* + *Ronald Tse ,* + *Erick Borsboom * + + * Reimplement -newreq-nodes and ERR_error_string_n; the + original author does not agree with the license change. + + *Rich Salz* + + * Add ARIA AEAD TLS support. + + *Jon Spillett* + + * Some macro definitions to support VS6 have been removed. Visual + Studio 6 has not worked since 1.1.0 + + *Rich Salz* + + * Add ERR_clear_last_mark(), to allow callers to clear the last mark + without clearing the errors. + + *Richard Levitte* + + * Add "atfork" functions. If building on a system that without + pthreads, see doc/man3/OPENSSL_fork_prepare.pod for application + requirements. The RAND facility now uses/requires this. + + *Rich Salz* + + * Add SHA3. + + *Andy Polyakov* + + * The UI API becomes a permanent and integral part of libcrypto, i.e. + not possible to disable entirely. However, it's still possible to + disable the console reading UI method, UI_OpenSSL() (use UI_null() + as a fallback). + + To disable, configure with 'no-ui-console'. 'no-ui' is still + possible to use as an alias. Check at compile time with the + macro OPENSSL_NO_UI_CONSOLE. The macro OPENSSL_NO_UI is still + possible to check and is an alias for OPENSSL_NO_UI_CONSOLE. + + *Richard Levitte* + + * Add a STORE module, which implements a uniform and URI based reader of + stores that can contain keys, certificates, CRLs and numerous other + objects. The main API is loosely based on a few stdio functions, + and includes OSSL_STORE_open, OSSL_STORE_load, OSSL_STORE_eof, + OSSL_STORE_error and OSSL_STORE_close. + The implementation uses backends called "loaders" to implement arbitrary + URI schemes. There is one built in "loader" for the 'file' scheme. + + *Richard Levitte* + + * Add devcrypto engine. This has been implemented against cryptodev-linux, + then adjusted to work on FreeBSD 8.4 as well. + Enable by configuring with 'enable-devcryptoeng'. This is done by default + on BSD implementations, as cryptodev.h is assumed to exist on all of them. + + *Richard Levitte* + + * Module names can prefixed with OSSL_ or OPENSSL_. This affects + util/mkerr.pl, which is adapted to allow those prefixes, leading to + error code calls like this: + + OSSL_FOOerr(OSSL_FOO_F_SOMETHING, OSSL_FOO_R_WHATEVER); + + With this change, we claim the namespaces OSSL and OPENSSL in a manner + that can be encoded in C. For the foreseeable future, this will only + affect new modules. + + *Richard Levitte and Tim Hudson* + + * Removed BSD cryptodev engine. + + *Rich Salz* + + * Add a build target 'build_all_generated', to build all generated files + and only that. This can be used to prepare everything that requires + things like perl for a system that lacks perl and then move everything + to that system and do the rest of the build there. + + *Richard Levitte* + + * In the UI interface, make it possible to duplicate the user data. This + can be used by engines that need to retain the data for a longer time + than just the call where this user data is passed. + + *Richard Levitte* + + * Ignore the '-named_curve auto' value for compatibility of applications + with OpenSSL 1.0.2. + + *Tomáš Mráz * + + * Fragmented SSL/TLS alerts are no longer accepted. An alert message is 2 + bytes long. In theory it is permissible in SSLv3 - TLSv1.2 to fragment such + alerts across multiple records (some of which could be empty). In practice + it make no sense to send an empty alert record, or to fragment one. TLSv1.3 + prohibits this altogether and other libraries (BoringSSL, NSS) do not + support this at all. Supporting it adds significant complexity to the + record layer, and its removal is unlikely to cause interoperability + issues. + + *Matt Caswell* + + * Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed + with Z. These are meant to replace LONG and ZLONG and to be size safe. + The use of LONG and ZLONG is discouraged and scheduled for deprecation + in OpenSSL 1.2.0. + + *Richard Levitte* + + * Add the 'z' and 'j' modifiers to BIO_printf() et al formatting string, + 'z' is to be used for [s]size_t, and 'j' - with [u]int64_t. + + *Richard Levitte, Andy Polyakov* + + * Add EC_KEY_get0_engine(), which does for EC_KEY what RSA_get0_engine() + does for RSA, etc. + + *Richard Levitte* + + * Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target + platform rather than 'mingw'. + + *Richard Levitte* + + * The functions X509_STORE_add_cert and X509_STORE_add_crl return + success if they are asked to add an object which already exists + in the store. This change cascades to other functions which load + certificates and CRLs. + + *Paul Dale* + + * x86_64 assembly pack: annotate code with DWARF CFI directives to + facilitate stack unwinding even from assembly subroutines. + + *Andy Polyakov* + + * Remove VAX C specific definitions of OPENSSL_EXPORT, OPENSSL_EXTERN. + Also remove OPENSSL_GLOBAL entirely, as it became a no-op. + + *Richard Levitte* + + * Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c. + VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1, + which is the minimum version we support. + + *Richard Levitte* + + * Certificate time validation (X509_cmp_time) enforces stricter + compliance with RFC 5280. Fractional seconds and timezone offsets + are no longer allowed. + + *Emilia Käsper* + + * Add support for ARIA + + *Paul Dale* + + * s_client will now send the Server Name Indication (SNI) extension by + default unless the new "-noservername" option is used. The server name is + based on the host provided to the "-connect" option unless overridden by + using "-servername". + + *Matt Caswell* + + * Add support for SipHash + + *Todd Short* + + * OpenSSL now fails if it receives an unrecognised record type in TLS1.0 + or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to + prevent issues where no progress is being made and the peer continually + sends unrecognised record types, using up resources processing them. + + *Matt Caswell* + + * 'openssl passwd' can now produce SHA256 and SHA512 based output, + using the algorithm defined in + + + *Richard Levitte* + + * Heartbeat support has been removed; the ABI is changed for now. + + *Richard Levitte, Rich Salz* + + * Support for SSL_OP_NO_ENCRYPT_THEN_MAC in SSL_CONF_cmd. + + *Emilia Käsper* + + * The RSA "null" method, which was partially supported to avoid patent + issues, has been replaced to always returns NULL. + + *Rich Salz* + +OpenSSL 1.1.0 +------------- + +### Changes between 1.1.0k and 1.1.0l [10 Sep 2019] + + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters, when loading a encoded key + or calling `EC_GROUP_new_from_ecpkparameters()`/ + `EC_GROUP_new_from_ecparameters()`. + This prevents bypass of security hardening and performance gains, + especially for curves with specialized EC_METHODs. + By default, if a key encoded with explicit parameters is loaded and later + encoded, the output is still encoded with explicit parameters, even if + internally a "named" EC_GROUP is used for computation. + + *Nicola Tuveri* + + * Compute ECC cofactors if not provided during EC_GROUP construction. Before + this change, EC_GROUP_set_generator would accept order and/or cofactor as + NULL. After this change, only the cofactor parameter can be NULL. It also + does some minimal sanity checks on the passed order. + ([CVE-2019-1547]) + + *Billy Bob Brumley* + + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey. + An attack is simple, if the first CMS_recipientInfo is valid but the + second CMS_recipientInfo is chosen ciphertext. If the second + recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct + encryption key will be replaced by garbage, and the message cannot be + decoded, but if the RSA decryption fails, the correct encryption key is + used and the recipient will not notice the attack. + As a work around for this potential attack the length of the decrypted + key must be equal to the cipher default key length, in case the + certifiate is not given and all recipientInfo are tried out. + The old behaviour can be re-enabled in the CMS code by setting the + CMS_DEBUG_DECRYPT flag. + ([CVE-2019-1563]) + + *Bernd Edlinger* + + * Use Windows installation paths in the mingw builds + + Mingw isn't a POSIX environment per se, which means that Windows + paths should be used for installation. + ([CVE-2019-1552]) + + *Richard Levitte* + +### Changes between 1.1.0j and 1.1.0k [28 May 2019] + + * Change the default RSA, DSA and DH size to 2048 bit instead of 1024. + This changes the size when using the `genpkey` command when no size is given. + It fixes an omission in earlier changes that changed all RSA, DSA and DH + generation commands to use 2048 bits by default. + + *Kurt Roeckx* + + * Prevent over long nonces in ChaCha20-Poly1305. + + ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input + for every encryption operation. RFC 7539 specifies that the nonce value + (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length + and front pads the nonce with 0 bytes if it is less than 12 + bytes. However it also incorrectly allows a nonce to be set of up to 16 + bytes. In this case only the last 12 bytes are significant and any + additional leading bytes are ignored. + + It is a requirement of using this cipher that nonce values are + unique. Messages encrypted using a reused nonce value are susceptible to + serious confidentiality and integrity attacks. If an application changes + the default nonce length to be longer than 12 bytes and then makes a + change to the leading bytes of the nonce expecting the new value to be a + new unique nonce then such an application could inadvertently encrypt + messages with a reused nonce. + + Additionally the ignored bytes in a long nonce are not covered by the + integrity guarantee of this cipher. Any application that relies on the + integrity of these ignored leading bytes of a long nonce may be further + affected. Any OpenSSL internal use of this cipher, including in SSL/TLS, + is safe because no such use sets such a long nonce value. However user + applications that use this cipher directly and set a non-default nonce + length to be longer than 12 bytes may be vulnerable. + + This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk + Greef of Ronomon. + ([CVE-2019-1543]) + + *Matt Caswell* + + * Added SCA hardening for modular field inversion in EC_GROUP through + a new dedicated field_inv() pointer in EC_METHOD. + This also addresses a leakage affecting conversions from projective + to affine coordinates. + + *Billy Bob Brumley, Nicola Tuveri* + + * Fix a use after free bug in d2i_X509_PUBKEY when overwriting a + re-used X509_PUBKEY object if the second PUBKEY is malformed. + + *Bernd Edlinger* + + * Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0(). + + *Richard Levitte* + + * Remove the 'dist' target and add a tarball building script. The + 'dist' target has fallen out of use, and it shouldn't be + necessary to configure just to create a source distribution. + + *Richard Levitte* + +### Changes between 1.1.0i and 1.1.0j [20 Nov 2018] + + * Timing vulnerability in DSA signature generation + + The OpenSSL DSA signature algorithm has been shown to be vulnerable to a + timing side channel attack. An attacker could use variations in the signing + algorithm to recover the private key. + + This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser. + ([CVE-2018-0734]) + + *Paul Dale* + + * Timing vulnerability in ECDSA signature generation + + The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a + timing side channel attack. An attacker could use variations in the signing + algorithm to recover the private key. + + This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser. + ([CVE-2018-0735]) + + *Paul Dale* + + * Add coordinate blinding for EC_POINT and implement projective + coordinate blinding for generic prime curves as a countermeasure to + chosen point SCA attacks. + + *Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley* + +### Changes between 1.1.0h and 1.1.0i [14 Aug 2018] + + * Client DoS due to large DH parameter + + During key agreement in a TLS handshake using a DH(E) based ciphersuite a + malicious server can send a very large prime value to the client. This will + cause the client to spend an unreasonably long period of time generating a + key for this prime resulting in a hang until the client has finished. This + could be exploited in a Denial Of Service attack. + + This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken + ([CVE-2018-0732]) + + *Guido Vranken* + + * Cache timing vulnerability in RSA Key Generation + + The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to + a cache timing side channel attack. An attacker with sufficient access to + mount cache timing attacks during the RSA key generation process could + recover the private key. + + This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera + Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia. + ([CVE-2018-0737]) + + *Billy Brumley* + + * Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str + parameter is no longer accepted, as it leads to a corrupt table. NULL + pem_str is reserved for alias entries only. + + *Richard Levitte* + + * Revert blinding in ECDSA sign and instead make problematic addition + length-invariant. Switch even to fixed-length Montgomery multiplication. + + *Andy Polyakov* + + * Change generating and checking of primes so that the error rate of not + being prime depends on the intended use based on the size of the input. + For larger primes this will result in more rounds of Miller-Rabin. + The maximal error rate for primes with more than 1080 bits is lowered + to 2^-128. + + *Kurt Roeckx, Annie Yousar* + + * Increase the number of Miller-Rabin rounds for DSA key generating to 64. + + *Kurt Roeckx* + + * Add blinding to ECDSA and DSA signatures to protect against side channel + attacks discovered by Keegan Ryan (NCC Group). + + *Matt Caswell* + + * When unlocking a pass phrase protected PEM file or PKCS#8 container, we + now allow empty (zero character) pass phrases. + + *Richard Levitte* + + * Certificate time validation (X509_cmp_time) enforces stricter + compliance with RFC 5280. Fractional seconds and timezone offsets + are no longer allowed. + + *Emilia Käsper* + + * Fixed a text canonicalisation bug in CMS + + Where a CMS detached signature is used with text content the text goes + through a canonicalisation process first prior to signing or verifying a + signature. This process strips trailing space at the end of lines, converts + line terminators to CRLF and removes additional trailing line terminators + at the end of a file. A bug in the canonicalisation process meant that + some characters, such as form-feed, were incorrectly treated as whitespace + and removed. This is contrary to the specification (RFC5485). This fix + could mean that detached text data signed with an earlier version of + OpenSSL 1.1.0 may fail to verify using the fixed version, or text data + signed with a fixed OpenSSL may fail to verify with an earlier version of + OpenSSL 1.1.0. A workaround is to only verify the canonicalised text data + and use the "-binary" flag (for the "cms" command line application) or set + the SMIME_BINARY/PKCS7_BINARY/CMS_BINARY flags (if using CMS_verify()). + + *Matt Caswell* + +### Changes between 1.1.0g and 1.1.0h [27 Mar 2018] + + * Constructed ASN.1 types with a recursive definition could exceed the stack + + Constructed ASN.1 types with a recursive definition (such as can be found + in PKCS7) could eventually exceed the stack given malicious input with + excessive recursion. This could result in a Denial Of Service attack. There + are no such structures used within SSL/TLS that come from untrusted sources + so this is considered safe. + + This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz + project. + ([CVE-2018-0739]) + + *Matt Caswell* + + * Incorrect CRYPTO_memcmp on HP-UX PA-RISC + + Because of an implementation bug the PA-RISC CRYPTO_memcmp function is + effectively reduced to only comparing the least significant bit of each + byte. This allows an attacker to forge messages that would be considered as + authenticated in an amount of tries lower than that guaranteed by the + security claims of the scheme. The module can only be compiled by the + HP-UX assembler, so that only HP-UX PA-RISC targets are affected. + + This issue was reported to OpenSSL on 2nd March 2018 by Peter Waltenberg + (IBM). + ([CVE-2018-0733]) + + *Andy Polyakov* + + * Add a build target 'build_all_generated', to build all generated files + and only that. This can be used to prepare everything that requires + things like perl for a system that lacks perl and then move everything + to that system and do the rest of the build there. + + *Richard Levitte* + + * Backport SSL_OP_NO_RENGOTIATION + + OpenSSL 1.0.2 and below had the ability to disable renegotiation using the + (undocumented) SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag. Due to the opacity + changes this is no longer possible in 1.1.0. Therefore the new + SSL_OP_NO_RENEGOTIATION option from 1.1.1-dev has been backported to + 1.1.0 to provide equivalent functionality. + + Note that if an application built against 1.1.0h headers (or above) is run + using an older version of 1.1.0 (prior to 1.1.0h) then the option will be + accepted but nothing will happen, i.e. renegotiation will not be prevented. + + *Matt Caswell* + + * Removed the OS390-Unix config target. It relied on a script that doesn't + exist. + + *Rich Salz* + + * rsaz_1024_mul_avx2 overflow bug on x86_64 + + There is an overflow bug in the AVX2 Montgomery multiplication procedure + used in exponentiation with 1024-bit moduli. No EC algorithms are affected. + Analysis suggests that attacks against RSA and DSA as a result of this + defect would be very difficult to perform and are not believed likely. + Attacks against DH1024 are considered just feasible, because most of the + work necessary to deduce information about a private key may be performed + offline. The amount of resources required for such an attack would be + significant. However, for an attack on TLS to be meaningful, the server + would have to share the DH1024 private key among multiple clients, which is + no longer an option since CVE-2016-0701. + + This only affects processors that support the AVX2 but not ADX extensions + like Intel Haswell (4th generation). + + This issue was reported to OpenSSL by David Benjamin (Google). The issue + was originally found via the OSS-Fuzz project. + ([CVE-2017-3738]) + + *Andy Polyakov* + +### Changes between 1.1.0f and 1.1.0g [2 Nov 2017] + + * bn_sqrx8x_internal carry bug on x86_64 + + There is a carry propagating bug in the x86_64 Montgomery squaring + procedure. No EC algorithms are affected. Analysis suggests that attacks + against RSA and DSA as a result of this defect would be very difficult to + perform and are not believed likely. Attacks against DH are considered just + feasible (although very difficult) because most of the work necessary to + deduce information about a private key may be performed offline. The amount + of resources required for such an attack would be very significant and + likely only accessible to a limited number of attackers. An attacker would + additionally need online access to an unpatched system using the target + private key in a scenario with persistent DH parameters and a private + key that is shared between multiple clients. + + This only affects processors that support the BMI1, BMI2 and ADX extensions + like Intel Broadwell (5th generation) and later or AMD Ryzen. + + This issue was reported to OpenSSL by the OSS-Fuzz project. + ([CVE-2017-3736]) + + *Andy Polyakov* + + * Malformed X.509 IPAddressFamily could cause OOB read + + If an X.509 certificate has a malformed IPAddressFamily extension, + OpenSSL could do a one-byte buffer overread. The most likely result + would be an erroneous display of the certificate in text format. + + This issue was reported to OpenSSL by the OSS-Fuzz project. + ([CVE-2017-3735]) + + *Rich Salz* + +### Changes between 1.1.0e and 1.1.0f [25 May 2017] + + * Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target + platform rather than 'mingw'. + + *Richard Levitte* + + * Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c. + VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1, + which is the minimum version we support. + + *Richard Levitte* + +### Changes between 1.1.0d and 1.1.0e [16 Feb 2017] + + * Encrypt-Then-Mac renegotiation crash + + During a renegotiation handshake if the Encrypt-Then-Mac extension is + negotiated where it was not in the original handshake (or vice-versa) then + this can cause OpenSSL to crash (dependant on ciphersuite). Both clients + and servers are affected. + + This issue was reported to OpenSSL by Joe Orton (Red Hat). + ([CVE-2017-3733]) + + *Matt Caswell* + +### Changes between 1.1.0c and 1.1.0d [26 Jan 2017] + + * Truncated packet could crash via OOB read + + If one side of an SSL/TLS path is running on a 32-bit host and a specific + cipher is being used, then a truncated packet can cause that host to + perform an out-of-bounds read, usually resulting in a crash. + + This issue was reported to OpenSSL by Robert Święcki of Google. + ([CVE-2017-3731]) + + *Andy Polyakov* + + * Bad (EC)DHE parameters cause a client crash + + If a malicious server supplies bad parameters for a DHE or ECDHE key + exchange then this can result in the client attempting to dereference a + NULL pointer leading to a client crash. This could be exploited in a Denial + of Service attack. + + This issue was reported to OpenSSL by Guido Vranken. + ([CVE-2017-3730]) + + *Matt Caswell* + + * BN_mod_exp may produce incorrect results on x86_64 + + There is a carry propagating bug in the x86_64 Montgomery squaring + procedure. No EC algorithms are affected. Analysis suggests that attacks + against RSA and DSA as a result of this defect would be very difficult to + perform and are not believed likely. Attacks against DH are considered just + feasible (although very difficult) because most of the work necessary to + deduce information about a private key may be performed offline. The amount + of resources required for such an attack would be very significant and + likely only accessible to a limited number of attackers. An attacker would + additionally need online access to an unpatched system using the target + private key in a scenario with persistent DH parameters and a private + key that is shared between multiple clients. For example this can occur by + default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very + similar to CVE-2015-3193 but must be treated as a separate problem. + + This issue was reported to OpenSSL by the OSS-Fuzz project. + ([CVE-2017-3732]) + + *Andy Polyakov* + +### Changes between 1.1.0b and 1.1.0c [10 Nov 2016] + + * ChaCha20/Poly1305 heap-buffer-overflow + + TLS connections using `*-CHACHA20-POLY1305` ciphersuites are susceptible to + a DoS attack by corrupting larger payloads. This can result in an OpenSSL + crash. This issue is not considered to be exploitable beyond a DoS. + + This issue was reported to OpenSSL by Robert Święcki (Google Security Team) + ([CVE-2016-7054]) + + *Richard Levitte* + + * CMS Null dereference + + Applications parsing invalid CMS structures can crash with a NULL pointer + dereference. This is caused by a bug in the handling of the ASN.1 CHOICE + type in OpenSSL 1.1.0 which can result in a NULL value being passed to the + structure callback if an attempt is made to free certain invalid encodings. + Only CHOICE structures using a callback which do not handle NULL value are + affected. + + This issue was reported to OpenSSL by Tyler Nighswander of ForAllSecure. + ([CVE-2016-7053]) + + *Stephen Henson* + + * Montgomery multiplication may produce incorrect results + + There is a carry propagating bug in the Broadwell-specific Montgomery + multiplication procedure that handles input lengths divisible by, but + longer than 256 bits. Analysis suggests that attacks against RSA, DSA + and DH private keys are impossible. This is because the subroutine in + question is not used in operations with the private key itself and an input + of the attacker's direct choice. Otherwise the bug can manifest itself as + transient authentication and key negotiation failures or reproducible + erroneous outcome of public-key operations with specially crafted input. + Among EC algorithms only Brainpool P-512 curves are affected and one + presumably can attack ECDH key negotiation. Impact was not analyzed in + detail, because pre-requisites for attack are considered unlikely. Namely + multiple clients have to choose the curve in question and the server has to + share the private key among them, neither of which is default behaviour. + Even then only clients that chose the curve will be affected. + + This issue was publicly reported as transient failures and was not + initially recognized as a security issue. Thanks to Richard Morgan for + providing reproducible case. + ([CVE-2016-7055]) + + *Andy Polyakov* + + * Removed automatic addition of RPATH in shared libraries and executables, + as this was a remainder from OpenSSL 1.0.x and isn't needed any more. + + *Richard Levitte* + +### Changes between 1.1.0a and 1.1.0b [26 Sep 2016] + + * Fix Use After Free for large message sizes + + The patch applied to address CVE-2016-6307 resulted in an issue where if a + message larger than approx 16k is received then the underlying buffer to + store the incoming message is reallocated and moved. Unfortunately a + dangling pointer to the old location is left which results in an attempt to + write to the previously freed location. This is likely to result in a + crash, however it could potentially lead to execution of arbitrary code. + + This issue only affects OpenSSL 1.1.0a. + + This issue was reported to OpenSSL by Robert Święcki. + ([CVE-2016-6309]) + + *Matt Caswell* + +### Changes between 1.1.0 and 1.1.0a [22 Sep 2016] + + * OCSP Status Request extension unbounded memory growth + + A malicious client can send an excessively large OCSP Status Request + extension. If that client continually requests renegotiation, sending a + large OCSP Status Request extension each time, then there will be unbounded + memory growth on the server. This will eventually lead to a Denial Of + Service attack through memory exhaustion. Servers with a default + configuration are vulnerable even if they do not support OCSP. Builds using + the "no-ocsp" build time option are not affected. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6304]) + + *Matt Caswell* + + * SSL_peek() hang on empty record + + OpenSSL 1.1.0 SSL/TLS will hang during a call to SSL_peek() if the peer + sends an empty record. This could be exploited by a malicious peer in a + Denial Of Service attack. + + This issue was reported to OpenSSL by Alex Gaynor. + ([CVE-2016-6305]) + + *Matt Caswell* + + * Excessive allocation of memory in tls_get_message_header() and + dtls1_preprocess_fragment() + + A (D)TLS message includes 3 bytes for its length in the header for the + message. This would allow for messages up to 16Mb in length. Messages of + this length are excessive and OpenSSL includes a check to ensure that a + peer is sending reasonably sized messages in order to avoid too much memory + being consumed to service a connection. A flaw in the logic of version + 1.1.0 means that memory for the message is allocated too early, prior to + the excessive message length check. Due to way memory is allocated in + OpenSSL this could mean an attacker could force up to 21Mb to be allocated + to service a connection. This could lead to a Denial of Service through + memory exhaustion. However, the excessive message length check still takes + place, and this would cause the connection to immediately fail. Assuming + that the application calls SSL_free() on the failed connection in a timely + manner then the 21Mb of allocated memory will then be immediately freed + again. Therefore the excessive memory allocation will be transitory in + nature. This then means that there is only a security impact if: + + 1) The application does not call SSL_free() in a timely manner in the event + that the connection fails + or + 2) The application is working in a constrained environment where there is + very little free memory + or + 3) The attacker initiates multiple connection attempts such that there are + multiple connections in a state where memory has been allocated for the + connection; SSL_free() has not yet been called; and there is insufficient + memory to service the multiple requests. + + Except in the instance of (1) above any Denial Of Service is likely to be + transitory because as soon as the connection fails the memory is + subsequently freed again in the SSL_free() call. However there is an + increased risk during this period of application crashes due to the lack of + memory - which would then mean a more serious Denial of Service. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + (CVE-2016-6307 and CVE-2016-6308) + + *Matt Caswell* + + * solaris-x86-cc, i.e. 32-bit configuration with vendor compiler, + had to be removed. Primary reason is that vendor assembler can't + assemble our modules with -KPIC flag. As result it, assembly + support, was not even available as option. But its lack means + lack of side-channel resistant code, which is incompatible with + security by todays standards. Fortunately gcc is readily available + prepackaged option, which we firmly point at... + + *Andy Polyakov* + +### Changes between 1.0.2h and 1.1.0 [25 Aug 2016] + + * Windows command-line tool supports UTF-8 opt-in option for arguments + and console input. Setting OPENSSL_WIN32_UTF8 environment variable + (to any value) allows Windows user to access PKCS#12 file generated + with Windows CryptoAPI and protected with non-ASCII password, as well + as files generated under UTF-8 locale on Linux also protected with + non-ASCII password. + + *Andy Polyakov* + + * To mitigate the SWEET32 attack ([CVE-2016-2183]), 3DES cipher suites + have been disabled by default and removed from DEFAULT, just like RC4. + See the RC4 item below to re-enable both. + + *Rich Salz* + + * The method for finding the storage location for the Windows RAND seed file + has changed. First we check %RANDFILE%. If that is not set then we check + the directories %HOME%, %USERPROFILE% and %SYSTEMROOT% in that order. If + all else fails we fall back to C:\. + + *Matt Caswell* + + * The EVP_EncryptUpdate() function has had its return type changed from void + to int. A return of 0 indicates and error while a return of 1 indicates + success. + + *Matt Caswell* + + * The flags RSA_FLAG_NO_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME and + DH_FLAG_NO_EXP_CONSTTIME which previously provided the ability to switch + off the constant time implementation for RSA, DSA and DH have been made + no-ops and deprecated. + + *Matt Caswell* + + * Windows RAND implementation was simplified to only get entropy by + calling CryptGenRandom(). Various other RAND-related tickets + were also closed. + + *Joseph Wylie Yandle, Rich Salz* + + * The stack and lhash API's were renamed to start with `OPENSSL_SK_` + and `OPENSSL_LH_`, respectively. The old names are available + with API compatibility. They new names are now completely documented. + + *Rich Salz* + + * Unify TYPE_up_ref(obj) methods signature. + SSL_CTX_up_ref(), SSL_up_ref(), X509_up_ref(), EVP_PKEY_up_ref(), + X509_CRL_up_ref(), X509_OBJECT_up_ref_count() methods are now returning an + int (instead of void) like all others TYPE_up_ref() methods. + So now these methods also check the return value of CRYPTO_atomic_add(), + and the validity of object reference counter. + + *fdasilvayy@gmail.com* + + * With Windows Visual Studio builds, the .pdb files are installed + alongside the installed libraries and executables. For a static + library installation, ossl_static.pdb is the associate compiler + generated .pdb file to be used when linking programs. + + *Richard Levitte* + + * Remove openssl.spec. Packaging files belong with the packagers. + + *Richard Levitte* + + * Automatic Darwin/OSX configuration has had a refresh, it will now + recognise x86_64 architectures automatically. You can still decide + to build for a different bitness with the environment variable + KERNEL_BITS (can be 32 or 64), for example: + + KERNEL_BITS=32 ./config + + *Richard Levitte* + + * Change default algorithms in pkcs8 utility to use PKCS#5 v2.0, + 256 bit AES and HMAC with SHA256. + + *Steve Henson* + + * Remove support for MIPS o32 ABI on IRIX (and IRIX only). + + *Andy Polyakov* + + * Triple-DES ciphers have been moved from HIGH to MEDIUM. + + *Rich Salz* + + * To enable users to have their own config files and build file templates, + Configure looks in the directory indicated by the environment variable + OPENSSL_LOCAL_CONFIG_DIR as well as the in-source Configurations/ + directory. On VMS, OPENSSL_LOCAL_CONFIG_DIR is expected to be a logical + name and is used as is. + + *Richard Levitte* + + * The following datatypes were made opaque: X509_OBJECT, X509_STORE_CTX, + X509_STORE, X509_LOOKUP, and X509_LOOKUP_METHOD. The unused type + X509_CERT_FILE_CTX was removed. + + *Rich Salz* + + * "shared" builds are now the default. To create only static libraries use + the "no-shared" Configure option. + + *Matt Caswell* + + * Remove the no-aes, no-hmac, no-rsa, no-sha and no-md5 Configure options. + All of these option have not worked for some while and are fundamental + algorithms. + + *Matt Caswell* + + * Make various cleanup routines no-ops and mark them as deprecated. Most + global cleanup functions are no longer required because they are handled + via auto-deinit (see OPENSSL_init_crypto and OPENSSL_init_ssl man pages). + Explicitly de-initing can cause problems (e.g. where a library that uses + OpenSSL de-inits, but an application is still using it). The affected + functions are CONF_modules_free(), ENGINE_cleanup(), OBJ_cleanup(), + EVP_cleanup(), BIO_sock_cleanup(), CRYPTO_cleanup_all_ex_data(), + RAND_cleanup(), SSL_COMP_free_compression_methods(), ERR_free_strings() and + COMP_zlib_cleanup(). + + *Matt Caswell* + + * --strict-warnings no longer enables runtime debugging options + such as REF_DEBUG. Instead, debug options are automatically + enabled with '--debug' builds. + + *Andy Polyakov, Emilia Käsper* + + * Made DH and DH_METHOD opaque. The structures for managing DH objects + have been moved out of the public header files. New functions for managing + these have been added. + + *Matt Caswell* + + * Made RSA and RSA_METHOD opaque. The structures for managing RSA + objects have been moved out of the public header files. New + functions for managing these have been added. + + *Richard Levitte* + + * Made DSA and DSA_METHOD opaque. The structures for managing DSA objects + have been moved out of the public header files. New functions for managing + these have been added. + + *Matt Caswell* + + * Made BIO and BIO_METHOD opaque. The structures for managing BIOs have been + moved out of the public header files. New functions for managing these + have been added. + + *Matt Caswell* + + * Removed no-rijndael as a config option. Rijndael is an old name for AES. + + *Matt Caswell* + + * Removed the mk1mf build scripts. + + *Richard Levitte* + + * Headers are now wrapped, if necessary, with OPENSSL_NO_xxx, so + it is always safe to #include a header now. + + *Rich Salz* + + * Removed the aged BC-32 config and all its supporting scripts + + *Richard Levitte* + + * Removed support for Ultrix, Netware, and OS/2. + + *Rich Salz* + + * Add support for HKDF. + + *Alessandro Ghedini* + + * Add support for blake2b and blake2s + + *Bill Cox* + + * Added support for "pipelining". Ciphers that have the + EVP_CIPH_FLAG_PIPELINE flag set have a capability to process multiple + encryptions/decryptions simultaneously. There are currently no built-in + ciphers with this property but the expectation is that engines will be able + to offer it to significantly improve throughput. Support has been extended + into libssl so that multiple records for a single connection can be + processed in one go (for >=TLS 1.1). + + *Matt Caswell* + + * Added the AFALG engine. This is an async capable engine which is able to + offload work to the Linux kernel. In this initial version it only supports + AES128-CBC. The kernel must be version 4.1.0 or greater. + + *Catriona Lucey* + + * OpenSSL now uses a new threading API. It is no longer necessary to + set locking callbacks to use OpenSSL in a multi-threaded environment. There + are two supported threading models: pthreads and windows threads. It is + also possible to configure OpenSSL at compile time for "no-threads". The + old threading API should no longer be used. The functions have been + replaced with "no-op" compatibility macros. + + *Alessandro Ghedini, Matt Caswell* + + * Modify behavior of ALPN to invoke callback after SNI/servername + callback, such that updates to the SSL_CTX affect ALPN. + + *Todd Short* + + * Add SSL_CIPHER queries for authentication and key-exchange. + + *Todd Short* + + * Changes to the DEFAULT cipherlist: + - Prefer (EC)DHE handshakes over plain RSA. + - Prefer AEAD ciphers over legacy ciphers. + - Prefer ECDSA over RSA when both certificates are available. + - Prefer TLSv1.2 ciphers/PRF. + - Remove DSS, SEED, IDEA, CAMELLIA, and AES-CCM from the + default cipherlist. + + *Emilia Käsper* + + * Change the ECC default curve list to be this, in order: x25519, + secp256r1, secp521r1, secp384r1. + + *Rich Salz* + + * RC4 based libssl ciphersuites are now classed as "weak" ciphers and are + disabled by default. They can be re-enabled using the + enable-weak-ssl-ciphers option to Configure. + + *Matt Caswell* + + * If the server has ALPN configured, but supports no protocols that the + client advertises, send a fatal "no_application_protocol" alert. + This behaviour is SHALL in RFC 7301, though it isn't universally + implemented by other servers. + + *Emilia Käsper* + + * Add X25519 support. + Add ASN.1 and EVP_PKEY methods for X25519. This includes support + for public and private key encoding using the format documented in + draft-ietf-curdle-pkix-02. The corresponding EVP_PKEY method supports + key generation and key derivation. + + TLS support complies with draft-ietf-tls-rfc4492bis-08 and uses + X25519(29). + + *Steve Henson* + + * Deprecate SRP_VBASE_get_by_user. + SRP_VBASE_get_by_user had inconsistent memory management behaviour. + In order to fix an unavoidable memory leak ([CVE-2016-0798]), + SRP_VBASE_get_by_user was changed to ignore the "fake user" SRP + seed, even if the seed is configured. + + Users should use SRP_VBASE_get1_by_user instead. Note that in + SRP_VBASE_get1_by_user, caller must free the returned value. Note + also that even though configuring the SRP seed attempts to hide + invalid usernames by continuing the handshake with fake + credentials, this behaviour is not constant time and no strong + guarantees are made that the handshake is indistinguishable from + that of a valid user. + + *Emilia Käsper* + + * Configuration change; it's now possible to build dynamic engines + without having to build shared libraries and vice versa. This + only applies to the engines in `engines/`, those in `crypto/engine/` + will always be built into libcrypto (i.e. "static"). + + Building dynamic engines is enabled by default; to disable, use + the configuration option "disable-dynamic-engine". + + The only requirements for building dynamic engines are the + presence of the DSO module and building with position independent + code, so they will also automatically be disabled if configuring + with "disable-dso" or "disable-pic". + + The macros OPENSSL_NO_STATIC_ENGINE and OPENSSL_NO_DYNAMIC_ENGINE + are also taken away from openssl/opensslconf.h, as they are + irrelevant. + + *Richard Levitte* + + * Configuration change; if there is a known flag to compile + position independent code, it will always be applied on the + libcrypto and libssl object files, and never on the application + object files. This means other libraries that use routines from + libcrypto / libssl can be made into shared libraries regardless + of how OpenSSL was configured. + + If this isn't desirable, the configuration options "disable-pic" + or "no-pic" can be used to disable the use of PIC. This will + also disable building shared libraries and dynamic engines. + + *Richard Levitte* + + * Removed JPAKE code. It was experimental and has no wide use. + + *Rich Salz* + + * The INSTALL_PREFIX Makefile variable has been renamed to + DESTDIR. That makes for less confusion on what this variable + is for. Also, the configuration option --install_prefix is + removed. + + *Richard Levitte* + + * Heartbeat for TLS has been removed and is disabled by default + for DTLS; configure with enable-heartbeats. Code that uses the + old #define's might need to be updated. + + *Emilia Käsper, Rich Salz* + + * Rename REF_CHECK to REF_DEBUG. + + *Rich Salz* + + * New "unified" build system + + The "unified" build system is aimed to be a common system for all + platforms we support. With it comes new support for VMS. + + This system builds supports building in a different directory tree + than the source tree. It produces one Makefile (for unix family + or lookalikes), or one descrip.mms (for VMS). + + The source of information to make the Makefile / descrip.mms is + small files called 'build.info', holding the necessary + information for each directory with source to compile, and a + template in Configurations, like unix-Makefile.tmpl or + descrip.mms.tmpl. + + With this change, the library names were also renamed on Windows + and on VMS. They now have names that are closer to the standard + on Unix, and include the major version number, and in certain + cases, the architecture they are built for. See "Notes on shared + libraries" in INSTALL. + + We rely heavily on the perl module Text::Template. + + *Richard Levitte* + + * Added support for auto-initialisation and de-initialisation of the library. + OpenSSL no longer requires explicit init or deinit routines to be called, + except in certain circumstances. See the OPENSSL_init_crypto() and + OPENSSL_init_ssl() man pages for further information. + + *Matt Caswell* + + * The arguments to the DTLSv1_listen function have changed. Specifically the + "peer" argument is now expected to be a BIO_ADDR object. + + * Rewrite of BIO networking library. The BIO library lacked consistent + support of IPv6, and adding it required some more extensive + modifications. This introduces the BIO_ADDR and BIO_ADDRINFO types, + which hold all types of addresses and chains of address information. + It also introduces a new API, with functions like BIO_socket, + BIO_connect, BIO_listen, BIO_lookup and a rewrite of BIO_accept. + The source/sink BIOs BIO_s_connect, BIO_s_accept and BIO_s_datagram + have been adapted accordingly. + + *Richard Levitte* + + * RSA_padding_check_PKCS1_type_1 now accepts inputs with and without + the leading 0-byte. + + *Emilia Käsper* + + * CRIME protection: disable compression by default, even if OpenSSL is + compiled with zlib enabled. Applications can still enable compression + by calling SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION), or by + using the SSL_CONF library to configure compression. + + *Emilia Käsper* + + * The signature of the session callback configured with + SSL_CTX_sess_set_get_cb was changed. The read-only input buffer + was explicitly marked as `const unsigned char*` instead of + `unsigned char*`. + + *Emilia Käsper* + + * Always DPURIFY. Remove the use of uninitialized memory in the + RNG, and other conditional uses of DPURIFY. This makes -DPURIFY a no-op. + + *Emilia Käsper* + + * Removed many obsolete configuration items, including + DES_PTR, DES_RISC1, DES_RISC2, DES_INT + MD2_CHAR, MD2_INT, MD2_LONG + BF_PTR, BF_PTR2 + IDEA_SHORT, IDEA_LONG + RC2_SHORT, RC2_LONG, RC4_LONG, RC4_CHUNK, RC4_INDEX + + *Rich Salz, with advice from Andy Polyakov* + + * Many BN internals have been moved to an internal header file. + + *Rich Salz with help from Andy Polyakov* + + * Configuration and writing out the results from it has changed. + Files such as Makefile include/openssl/opensslconf.h and are now + produced through general templates, such as Makefile.in and + crypto/opensslconf.h.in and some help from the perl module + Text::Template. + + Also, the center of configuration information is no longer + Makefile. Instead, Configure produces a perl module in + configdata.pm which holds most of the config data (in the hash + table %config), the target data that comes from the target + configuration in one of the `Configurations/*.conf` files (in + %target). + + *Richard Levitte* + + * To clarify their intended purposes, the Configure options + --prefix and --openssldir change their semantics, and become more + straightforward and less interdependent. + + --prefix shall be used exclusively to give the location INSTALLTOP + where programs, scripts, libraries, include files and manuals are + going to be installed. The default is now /usr/local. + + --openssldir shall be used exclusively to give the default + location OPENSSLDIR where certificates, private keys, CRLs are + managed. This is also where the default openssl.cnf gets + installed. + If the directory given with this option is a relative path, the + values of both the --prefix value and the --openssldir value will + be combined to become OPENSSLDIR. + The default for --openssldir is INSTALLTOP/ssl. + + Anyone who uses --openssldir to specify where OpenSSL is to be + installed MUST change to use --prefix instead. + + *Richard Levitte* + + * The GOST engine was out of date and therefore it has been removed. An up + to date GOST engine is now being maintained in an external repository. + See: . Libssl still retains + support for GOST ciphersuites (these are only activated if a GOST engine + is present). + + *Matt Caswell* + + * EGD is no longer supported by default; use enable-egd when + configuring. + + *Ben Kaduk and Rich Salz* + + * The distribution now has Makefile.in files, which are used to + create Makefile's when Configure is run. *Configure must be run + before trying to build now.* + + *Rich Salz* + + * The return value for SSL_CIPHER_description() for error conditions + has changed. + + *Rich Salz* + + * Support for RFC6698/RFC7671 DANE TLSA peer authentication. + + Obtaining and performing DNSSEC validation of TLSA records is + the application's responsibility. The application provides + the TLSA records of its choice to OpenSSL, and these are then + used to authenticate the peer. + + The TLSA records need not even come from DNS. They can, for + example, be used to implement local end-entity certificate or + trust-anchor "pinning", where the "pin" data takes the form + of TLSA records, which can augment or replace verification + based on the usual WebPKI public certification authorities. + + *Viktor Dukhovni* + + * Revert default OPENSSL_NO_DEPRECATED setting. Instead OpenSSL + continues to support deprecated interfaces in default builds. + However, applications are strongly advised to compile their + source files with -DOPENSSL_API_COMPAT=0x10100000L, which hides + the declarations of all interfaces deprecated in 0.9.8, 1.0.0 + or the 1.1.0 releases. + + In environments in which all applications have been ported to + not use any deprecated interfaces OpenSSL's Configure script + should be used with the --api=1.1.0 option to entirely remove + support for the deprecated features from the library and + unconditionally disable them in the installed headers. + Essentially the same effect can be achieved with the "no-deprecated" + argument to Configure, except that this will always restrict + the build to just the latest API, rather than a fixed API + version. + + As applications are ported to future revisions of the API, + they should update their compile-time OPENSSL_API_COMPAT define + accordingly, but in most cases should be able to continue to + compile with later releases. + + The OPENSSL_API_COMPAT versions for 1.0.0, and 0.9.8 are + 0x10000000L and 0x00908000L, respectively. However those + versions did not support the OPENSSL_API_COMPAT feature, and + so applications are not typically tested for explicit support + of just the undeprecated features of either release. + + *Viktor Dukhovni* + + * Add support for setting the minimum and maximum supported protocol. + It can bet set via the SSL_set_min_proto_version() and + SSL_set_max_proto_version(), or via the SSL_CONF's MinProtocol and + MaxProtocol. It's recommended to use the new APIs to disable + protocols instead of disabling individual protocols using + SSL_set_options() or SSL_CONF's Protocol. This change also + removes support for disabling TLS 1.2 in the OpenSSL TLS + client at compile time by defining OPENSSL_NO_TLS1_2_CLIENT. + + *Kurt Roeckx* + + * Support for ChaCha20 and Poly1305 added to libcrypto and libssl. + + *Andy Polyakov* + + * New EC_KEY_METHOD, this replaces the older ECDSA_METHOD and ECDH_METHOD + and integrates ECDSA and ECDH functionality into EC. Implementations can + now redirect key generation and no longer need to convert to or from + ECDSA_SIG format. + + Note: the ecdsa.h and ecdh.h headers are now no longer needed and just + include the ec.h header file instead. + + *Steve Henson* + + * Remove support for all 40 and 56 bit ciphers. This includes all the export + ciphers who are no longer supported and drops support the ephemeral RSA key + exchange. The LOW ciphers currently doesn't have any ciphers in it. + + *Kurt Roeckx* + + * Made EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, EVP_CIPHER and HMAC_CTX + opaque. For HMAC_CTX, the following constructors and destructors + were added: + + HMAC_CTX *HMAC_CTX_new(void); + void HMAC_CTX_free(HMAC_CTX *ctx); + + For EVP_MD and EVP_CIPHER, complete APIs to create, fill and + destroy such methods has been added. See EVP_MD_meth_new(3) and + EVP_CIPHER_meth_new(3) for documentation. + + Additional changes: + 1) `EVP_MD_CTX_cleanup()`, `EVP_CIPHER_CTX_cleanup()` and + `HMAC_CTX_cleanup()` were removed. `HMAC_CTX_reset()` and + `EVP_MD_CTX_reset()` should be called instead to reinitialise + an already created structure. + 2) For consistency with the majority of our object creators and + destructors, `EVP_MD_CTX_(create|destroy)` were renamed to + `EVP_MD_CTX_(new|free)`. The old names are retained as macros + for deprecated builds. + + *Richard Levitte* + + * Added ASYNC support. Libcrypto now includes the async sub-library to enable + cryptographic operations to be performed asynchronously as long as an + asynchronous capable engine is used. See the ASYNC_start_job() man page for + further details. Libssl has also had this capability integrated with the + introduction of the new mode SSL_MODE_ASYNC and associated error + SSL_ERROR_WANT_ASYNC. See the SSL_CTX_set_mode() and SSL_get_error() man + pages. This work was developed in partnership with Intel Corp. + + *Matt Caswell* + + * SSL_{CTX_}set_ecdh_auto() has been removed and ECDH is support is + always enabled now. If you want to disable the support you should + exclude it using the list of supported ciphers. This also means that the + "-no_ecdhe" option has been removed from s_server. + + *Kurt Roeckx* + + * SSL_{CTX}_set_tmp_ecdh() which can set 1 EC curve now internally calls + SSL_{CTX_}set1_curves() which can set a list. + + *Kurt Roeckx* + + * Remove support for SSL_{CTX_}set_tmp_ecdh_callback(). You should set the + curve you want to support using SSL_{CTX_}set1_curves(). + + *Kurt Roeckx* + + * State machine rewrite. The state machine code has been significantly + refactored in order to remove much duplication of code and solve issues + with the old code (see [ssl/statem/README.md](ssl/statem/README.md) for + further details). This change does have some associated API changes. + Notably the SSL_state() function has been removed and replaced by + SSL_get_state which now returns an "OSSL_HANDSHAKE_STATE" instead of an int. + SSL_set_state() has been removed altogether. The previous handshake states + defined in ssl.h and ssl3.h have also been removed. + + *Matt Caswell* + + * All instances of the string "ssleay" in the public API were replaced + with OpenSSL (case-matching; e.g., OPENSSL_VERSION for #define's) + Some error codes related to internal RSA_eay API's were renamed. + + *Rich Salz* + + * The demo files in crypto/threads were moved to demo/threads. + + *Rich Salz* + + * Removed obsolete engines: 4758cca, aep, atalla, cswift, nuron, gmp, + sureware and ubsec. + + *Matt Caswell, Rich Salz* + + * New ASN.1 embed macro. + + New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the + structure is not allocated: it is part of the parent. That is instead of + + FOO *x; + + it must be: + + FOO x; + + This reduces memory fragmentation and make it impossible to accidentally + set a mandatory field to NULL. + + This currently only works for some fields specifically a SEQUENCE, CHOICE, + or ASN1_STRING type which is part of a parent SEQUENCE. Since it is + equivalent to ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or + SEQUENCE OF. + + *Steve Henson* + + * Remove EVP_CHECK_DES_KEY, a compile-time option that never compiled. + + *Emilia Käsper* + + * Removed DES and RC4 ciphersuites from DEFAULT. Also removed RC2 although + in 1.0.2 EXPORT was already removed and the only RC2 ciphersuite is also + an EXPORT one. COMPLEMENTOFDEFAULT has been updated accordingly to add + DES and RC4 ciphersuites. + + *Matt Caswell* + + * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs. + This changes the decoding behaviour for some invalid messages, + though the change is mostly in the more lenient direction, and + legacy behaviour is preserved as much as possible. + + *Emilia Käsper* + + * Fix no-stdio build. + *David Woodhouse and also* + *Ivan Nestlerode * + + * New testing framework + The testing framework has been largely rewritten and is now using + perl and the perl modules Test::Harness and an extended variant of + Test::More called OpenSSL::Test to do its work. All test scripts in + test/ have been rewritten into test recipes, and all direct calls to + executables in test/Makefile have become individual recipes using the + simplified testing OpenSSL::Test::Simple. + + For documentation on our testing modules, do: + + perldoc test/testlib/OpenSSL/Test/Simple.pm + perldoc test/testlib/OpenSSL/Test.pm + + *Richard Levitte* + + * Revamped memory debug; only -DCRYPTO_MDEBUG and -DCRYPTO_MDEBUG_ABORT + are used; the latter aborts on memory leaks (usually checked on exit). + Some undocumented "set malloc, etc., hooks" functions were removed + and others were changed. All are now documented. + + *Rich Salz* + + * In DSA_generate_parameters_ex, if the provided seed is too short, + return an error + + *Rich Salz and Ismo Puustinen * + + * Rewrite PSK to support ECDHE_PSK, DHE_PSK and RSA_PSK. Add ciphersuites + from RFC4279, RFC4785, RFC5487, RFC5489. + + Thanks to Christian J. Dietrich and Giuseppe D'Angelo for the + original RSA_PSK patch. + + *Steve Henson* + + * Dropped support for the SSL3_FLAGS_DELAY_CLIENT_FINISHED flag. This SSLeay + era flag was never set throughout the codebase (only read). Also removed + SSL3_FLAGS_POP_BUFFER which was only used if + SSL3_FLAGS_DELAY_CLIENT_FINISHED was also set. + + *Matt Caswell* + + * Changed the default name options in the "ca", "crl", "req" and "x509" + to be "oneline" instead of "compat". + + *Richard Levitte* + + * Remove SSL_OP_TLS_BLOCK_PADDING_BUG. This is SSLeay legacy, we're + not aware of clients that still exhibit this bug, and the workaround + hasn't been working properly for a while. + + *Emilia Käsper* + + * The return type of BIO_number_read() and BIO_number_written() as well as + the corresponding num_read and num_write members in the BIO structure has + changed from unsigned long to uint64_t. On platforms where an unsigned + long is 32 bits (e.g. Windows) these counters could overflow if >4Gb is + transferred. + + *Matt Caswell* + + * Given the pervasive nature of TLS extensions it is inadvisable to run + OpenSSL without support for them. It also means that maintaining + the OPENSSL_NO_TLSEXT option within the code is very invasive (and probably + not well tested). Therefore the OPENSSL_NO_TLSEXT option has been removed. + + *Matt Caswell* + + * Removed support for the two export grade static DH ciphersuites + EXP-DH-RSA-DES-CBC-SHA and EXP-DH-DSS-DES-CBC-SHA. These two ciphersuites + were newly added (along with a number of other static DH ciphersuites) to + 1.0.2. However the two export ones have *never* worked since they were + introduced. It seems strange in any case to be adding new export + ciphersuites, and given "logjam" it also does not seem correct to fix them. + + *Matt Caswell* + + * Version negotiation has been rewritten. In particular SSLv23_method(), + SSLv23_client_method() and SSLv23_server_method() have been deprecated, + and turned into macros which simply call the new preferred function names + TLS_method(), TLS_client_method() and TLS_server_method(). All new code + should use the new names instead. Also as part of this change the ssl23.h + header file has been removed. + + *Matt Caswell* + + * Support for Kerberos ciphersuites in TLS (RFC2712) has been removed. This + code and the associated standard is no longer considered fit-for-purpose. + + *Matt Caswell* + + * RT2547 was closed. When generating a private key, try to make the + output file readable only by the owner. This behavior change might + be noticeable when interacting with other software. + + * Documented all exdata functions. Added CRYPTO_free_ex_index. + Added a test. + + *Rich Salz* + + * Added HTTP GET support to the ocsp command. + + *Rich Salz* + + * Changed default digest for the dgst and enc commands from MD5 to + sha256 + + *Rich Salz* + + * RAND_pseudo_bytes has been deprecated. Users should use RAND_bytes instead. + + *Matt Caswell* + + * Added support for TLS extended master secret from + draft-ietf-tls-session-hash-03.txt. Thanks for Alfredo Pironti for an + initial patch which was a great help during development. + + *Steve Henson* + + * All libssl internal structures have been removed from the public header + files, and the OPENSSL_NO_SSL_INTERN option has been removed (since it is + now redundant). Users should not attempt to access internal structures + directly. Instead they should use the provided API functions. + + *Matt Caswell* + + * config has been changed so that by default OPENSSL_NO_DEPRECATED is used. + Access to deprecated functions can be re-enabled by running config with + "enable-deprecated". In addition applications wishing to use deprecated + functions must define OPENSSL_USE_DEPRECATED. Note that this new behaviour + will, by default, disable some transitive includes that previously existed + in the header files (e.g. ec.h will no longer, by default, include bn.h) + + *Matt Caswell* + + * Added support for OCB mode. OpenSSL has been granted a patent license + compatible with the OpenSSL license for use of OCB. Details are available + at . Support + for OCB can be removed by calling config with no-ocb. + + *Matt Caswell* + + * SSLv2 support has been removed. It still supports receiving a SSLv2 + compatible client hello. + + *Kurt Roeckx* + + * Increased the minimal RSA keysize from 256 to 512 bits [Rich Salz], + done while fixing the error code for the key-too-small case. + + *Annie Yousar * + + * CA.sh has been removed; use CA.pl instead. + + *Rich Salz* + + * Removed old DES API. + + *Rich Salz* + + * Remove various unsupported platforms: + Sony NEWS4 + BEOS and BEOS_R5 + NeXT + SUNOS + MPE/iX + Sinix/ReliantUNIX RM400 + DGUX + NCR + Tandem + Cray + 16-bit platforms such as WIN16 + + *Rich Salz* + + * Clean up OPENSSL_NO_xxx #define's + - Use setbuf() and remove OPENSSL_NO_SETVBUF_IONBF + - Rename OPENSSL_SYSNAME_xxx to OPENSSL_SYS_xxx + - OPENSSL_NO_EC{DH,DSA} merged into OPENSSL_NO_EC + - OPENSSL_NO_RIPEMD160, OPENSSL_NO_RIPEMD merged into OPENSSL_NO_RMD160 + - OPENSSL_NO_FP_API merged into OPENSSL_NO_STDIO + - Remove OPENSSL_NO_BIO OPENSSL_NO_BUFFER OPENSSL_NO_CHAIN_VERIFY + OPENSSL_NO_EVP OPENSSL_NO_FIPS_ERR OPENSSL_NO_HASH_COMP + OPENSSL_NO_LHASH OPENSSL_NO_OBJECT OPENSSL_NO_SPEED OPENSSL_NO_STACK + OPENSSL_NO_X509 OPENSSL_NO_X509_VERIFY + - Remove MS_STATIC; it's a relic from platforms <32 bits. + + *Rich Salz* + + * Cleaned up dead code + Remove all but one '#ifdef undef' which is to be looked at. + + *Rich Salz* + + * Clean up calling of xxx_free routines. + Just like free(), fix most of the xxx_free routines to accept + NULL. Remove the non-null checks from callers. Save much code. + + *Rich Salz* + + * Add secure heap for storage of private keys (when possible). + Add BIO_s_secmem(), CBIGNUM, etc. + Contributed by Akamai Technologies under our Corporate CLA. + + *Rich Salz* + + * Experimental support for a new, fast, unbiased prime candidate generator, + bn_probable_prime_dh_coprime(). Not currently used by any prime generator. + + *Felix Laurie von Massenbach * + + * New output format NSS in the sess_id command line tool. This allows + exporting the session id and the master key in NSS keylog format. + + *Martin Kaiser * + + * Harmonize version and its documentation. -f flag is used to display + compilation flags. + + *mancha * + + * Fix eckey_priv_encode so it immediately returns an error upon a failure + in i2d_ECPrivateKey. Thanks to Ted Unangst for feedback on this issue. + + *mancha * + + * Fix some double frees. These are not thought to be exploitable. + + *mancha * + + * A missing bounds check in the handling of the TLS heartbeat extension + can be used to reveal up to 64k of memory to a connected client or + server. + + Thanks for Neel Mehta of Google Security for discovering this bug and to + Adam Langley and Bodo Moeller for + preparing the fix ([CVE-2014-0160]) + + *Adam Langley, Bodo Moeller* + + * Fix for the attack described in the paper "Recovering OpenSSL + ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack" + by Yuval Yarom and Naomi Benger. Details can be obtained from: + + + Thanks to Yuval Yarom and Naomi Benger for discovering this + flaw and to Yuval Yarom for supplying a fix ([CVE-2014-0076]) + + *Yuval Yarom and Naomi Benger* + + * Use algorithm specific chains in SSL_CTX_use_certificate_chain_file(): + this fixes a limitation in previous versions of OpenSSL. + + *Steve Henson* + + * Experimental encrypt-then-mac support. + + Experimental support for encrypt then mac from + draft-gutmann-tls-encrypt-then-mac-02.txt + + To enable it set the appropriate extension number (0x42 for the test + server) using e.g. -DTLSEXT_TYPE_encrypt_then_mac=0x42 + + For non-compliant peers (i.e. just about everything) this should have no + effect. + + WARNING: EXPERIMENTAL, SUBJECT TO CHANGE. + + *Steve Henson* + + * Add EVP support for key wrapping algorithms, to avoid problems with + existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in + the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap + algorithms and include tests cases. + + *Steve Henson* + + * Extend CMS code to support RSA-PSS signatures and RSA-OAEP for + enveloped data. + + *Steve Henson* + + * Extended RSA OAEP support via EVP_PKEY API. Options to specify digest, + MGF1 digest and OAEP label. + + *Steve Henson* + + * Make openssl verify return errors. + + *Chris Palmer and Ben Laurie* + + * New function ASN1_TIME_diff to calculate the difference between two + ASN1_TIME structures or one structure and the current time. + + *Steve Henson* + + * Update fips_test_suite to support multiple command line options. New + test to induce all self test errors in sequence and check expected + failures. + + *Steve Henson* + + * Add FIPS_{rsa,dsa,ecdsa}_{sign,verify} functions which digest and + sign or verify all in one operation. + + *Steve Henson* + + * Add fips_algvs: a multicall fips utility incorporating all the algorithm + test programs and fips_test_suite. Includes functionality to parse + the minimal script output of fipsalgest.pl directly. + + *Steve Henson* + + * Add authorisation parameter to FIPS_module_mode_set(). + + *Steve Henson* + + * Add FIPS selftest for ECDH algorithm using P-224 and B-233 curves. + + *Steve Henson* + + * Use separate DRBG fields for internal and external flags. New function + FIPS_drbg_health_check() to perform on demand health checking. Add + generation tests to fips_test_suite with reduced health check interval to + demonstrate periodic health checking. Add "nodh" option to + fips_test_suite to skip very slow DH test. + + *Steve Henson* + + * New function FIPS_get_cipherbynid() to lookup FIPS supported ciphers + based on NID. + + *Steve Henson* + + * More extensive health check for DRBG checking many more failure modes. + New function FIPS_selftest_drbg_all() to handle every possible DRBG + combination: call this in fips_test_suite. + + *Steve Henson* + + * Add support for canonical generation of DSA parameter 'g'. See + FIPS 186-3 A.2.3. + + * Add support for HMAC DRBG from SP800-90. Update DRBG algorithm test and + POST to handle HMAC cases. + + *Steve Henson* + + * Add functions FIPS_module_version() and FIPS_module_version_text() + to return numerical and string versions of the FIPS module number. + + *Steve Henson* + + * Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and + FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implemented + outside the validated module in the FIPS capable OpenSSL. + + *Steve Henson* + + * Minor change to DRBG entropy callback semantics. In some cases + there is no multiple of the block length between min_len and + max_len. Allow the callback to return more than max_len bytes + of entropy but discard any extra: it is the callback's responsibility + to ensure that the extra data discarded does not impact the + requested amount of entropy. + + *Steve Henson* + + * Add PRNG security strength checks to RSA, DSA and ECDSA using + information in FIPS186-3, SP800-57 and SP800-131A. + + *Steve Henson* + + * CCM support via EVP. Interface is very similar to GCM case except we + must supply all data in one chunk (i.e. no update, final) and the + message length must be supplied if AAD is used. Add algorithm test + support. + + *Steve Henson* + + * Initial version of POST overhaul. Add POST callback to allow the status + of POST to be monitored and/or failures induced. Modify fips_test_suite + to use callback. Always run all selftests even if one fails. + + *Steve Henson* + + * XTS support including algorithm test driver in the fips_gcmtest program. + Note: this does increase the maximum key length from 32 to 64 bytes but + there should be no binary compatibility issues as existing applications + will never use XTS mode. + + *Steve Henson* + + * Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies + to OpenSSL RAND code and replace with a tiny FIPS RAND API which also + performs algorithm blocking for unapproved PRNG types. Also do not + set PRNG type in FIPS_mode_set(): leave this to the application. + Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with + the standard OpenSSL PRNG: set additional data to a date time vector. + + *Steve Henson* + + * Rename old X9.31 PRNG functions of the form `FIPS_rand*` to `FIPS_x931*`. + This shouldn't present any incompatibility problems because applications + shouldn't be using these directly and any that are will need to rethink + anyway as the X9.31 PRNG is now deprecated by FIPS 140-2 + + *Steve Henson* + + * Extensive self tests and health checking required by SP800-90 DRBG. + Remove strength parameter from FIPS_drbg_instantiate and always + instantiate at maximum supported strength. + + *Steve Henson* + + * Add ECDH code to fips module and fips_ecdhvs for primitives only testing. + + *Steve Henson* + + * New algorithm test program fips_dhvs to handle DH primitives only testing. + + *Steve Henson* + + * New function DH_compute_key_padded() to compute a DH key and pad with + leading zeroes if needed: this complies with SP800-56A et al. + + *Steve Henson* + + * Initial implementation of SP800-90 DRBGs for Hash and CTR. Not used by + anything, incomplete, subject to change and largely untested at present. + + *Steve Henson* + + * Modify fipscanisteronly build option to only build the necessary object + files by filtering FIPS_EX_OBJ through a perl script in crypto/Makefile. + + *Steve Henson* + + * Add experimental option FIPSSYMS to give all symbols in + fipscanister.o and FIPS or fips prefix. This will avoid + conflicts with future versions of OpenSSL. Add perl script + util/fipsas.pl to preprocess assembly language source files + and rename any affected symbols. + + *Steve Henson* + + * Add selftest checks and algorithm block of non-fips algorithms in + FIPS mode. Remove DES2 from selftests. + + *Steve Henson* + + * Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just + return internal method without any ENGINE dependencies. Add new + tiny fips sign and verify functions. + + *Steve Henson* + + * New build option no-ec2m to disable characteristic 2 code. + + *Steve Henson* + + * New build option "fipscanisteronly". This only builds fipscanister.o + and (currently) associated fips utilities. Uses the file Makefile.fips + instead of Makefile.org as the prototype. + + *Steve Henson* + + * Add some FIPS mode restrictions to GCM. Add internal IV generator. + Update fips_gcmtest to use IV generator. + + *Steve Henson* + + * Initial, experimental EVP support for AES-GCM. AAD can be input by + setting output buffer to NULL. The `*Final` function must be + called although it will not retrieve any additional data. The tag + can be set or retrieved with a ctrl. The IV length is by default 12 + bytes (96 bits) but can be set to an alternative value. If the IV + length exceeds the maximum IV length (currently 16 bytes) it cannot be + set before the key. + + *Steve Henson* + + * New flag in ciphers: EVP_CIPH_FLAG_CUSTOM_CIPHER. This means the + underlying do_cipher function handles all cipher semantics itself + including padding and finalisation. This is useful if (for example) + an ENGINE cipher handles block padding itself. The behaviour of + do_cipher is subtly changed if this flag is set: the return value + is the number of characters written to the output buffer (zero is + no longer an error code) or a negative error code. Also if the + input buffer is NULL and length 0 finalisation should be performed. + + *Steve Henson* + + * If a candidate issuer certificate is already part of the constructed + path ignore it: new debug notification X509_V_ERR_PATH_LOOP for this case. + + *Steve Henson* + + * Improve forward-security support: add functions + + void SSL_CTX_set_not_resumable_session_callback( + SSL_CTX *ctx, int (*cb)(SSL *ssl, int is_forward_secure)) + void SSL_set_not_resumable_session_callback( + SSL *ssl, int (*cb)(SSL *ssl, int is_forward_secure)) + + for use by SSL/TLS servers; the callback function will be called whenever a + new session is created, and gets to decide whether the session may be + cached to make it resumable (return 0) or not (return 1). (As by the + SSL/TLS protocol specifications, the session_id sent by the server will be + empty to indicate that the session is not resumable; also, the server will + not generate RFC 4507 (RFC 5077) session tickets.) + + A simple reasonable callback implementation is to return is_forward_secure. + This parameter will be set to 1 or 0 depending on the ciphersuite selected + by the SSL/TLS server library, indicating whether it can provide forward + security. + + *Emilia Käsper (Google)* + + * New -verify_name option in command line utilities to set verification + parameters by name. + + *Steve Henson* + + * Initial CMAC implementation. WARNING: EXPERIMENTAL, API MAY CHANGE. + Add CMAC pkey methods. + + *Steve Henson* + + * Experimental renegotiation in s_server -www mode. If the client + browses /reneg connection is renegotiated. If /renegcert it is + renegotiated requesting a certificate. + + *Steve Henson* + + * Add an "external" session cache for debugging purposes to s_server. This + should help trace issues which normally are only apparent in deployed + multi-process servers. + + *Steve Henson* + + * Extensive audit of libcrypto with DEBUG_UNUSED. Fix many cases where + return value is ignored. NB. The functions RAND_add(), RAND_seed(), + BIO_set_cipher() and some obscure PEM functions were changed so they + can now return an error. The RAND changes required a change to the + RAND_METHOD structure. + + *Steve Henson* + + * New macro `__owur` for "OpenSSL Warn Unused Result". This makes use of + a gcc attribute to warn if the result of a function is ignored. This + is enable if DEBUG_UNUSED is set. Add to several functions in evp.h + whose return value is often ignored. + + *Steve Henson* + + * New -noct, -requestct, -requirect and -ctlogfile options for s_client. + These allow SCTs (signed certificate timestamps) to be requested and + validated when establishing a connection. + + *Rob Percival * + +OpenSSL 1.0.2 +------------- + +### Changes between 1.0.2s and 1.0.2t [10 Sep 2019] + + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters, when loading a encoded key + or calling `EC_GROUP_new_from_ecpkparameters()`/ + `EC_GROUP_new_from_ecparameters()`. + This prevents bypass of security hardening and performance gains, + especially for curves with specialized EC_METHODs. + By default, if a key encoded with explicit parameters is loaded and later + encoded, the output is still encoded with explicit parameters, even if + internally a "named" EC_GROUP is used for computation. + + *Nicola Tuveri* + + * Compute ECC cofactors if not provided during EC_GROUP construction. Before + this change, EC_GROUP_set_generator would accept order and/or cofactor as + NULL. After this change, only the cofactor parameter can be NULL. It also + does some minimal sanity checks on the passed order. + ([CVE-2019-1547]) + + *Billy Bob Brumley* + + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey. + An attack is simple, if the first CMS_recipientInfo is valid but the + second CMS_recipientInfo is chosen ciphertext. If the second + recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct + encryption key will be replaced by garbage, and the message cannot be + decoded, but if the RSA decryption fails, the correct encryption key is + used and the recipient will not notice the attack. + As a work around for this potential attack the length of the decrypted + key must be equal to the cipher default key length, in case the + certifiate is not given and all recipientInfo are tried out. + The old behaviour can be re-enabled in the CMS code by setting the + CMS_DEBUG_DECRYPT flag. + ([CVE-2019-1563]) + + *Bernd Edlinger* + + * Document issue with installation paths in diverse Windows builds + + '/usr/local/ssl' is an unsafe prefix for location to install OpenSSL + binaries and run-time config file. + ([CVE-2019-1552]) + + *Richard Levitte* + +### Changes between 1.0.2r and 1.0.2s [28 May 2019] + + * Change the default RSA, DSA and DH size to 2048 bit instead of 1024. + This changes the size when using the `genpkey` command when no size is given. + It fixes an omission in earlier changes that changed all RSA, DSA and DH + generation commands to use 2048 bits by default. + + *Kurt Roeckx* + + * Add FIPS support for Android Arm 64-bit + + Support for Android Arm 64-bit was added to the OpenSSL FIPS Object + Module in Version 2.0.10. For some reason, the corresponding target + 'android64-aarch64' was missing OpenSSL 1.0.2, whence it could not be + built with FIPS support on Android Arm 64-bit. This omission has been + fixed. + + *Matthias St. Pierre* + +### Changes between 1.0.2q and 1.0.2r [26 Feb 2019] + + * 0-byte record padding oracle + + If an application encounters a fatal protocol error and then calls + SSL_shutdown() twice (once to send a close_notify, and once to receive one) + then OpenSSL can respond differently to the calling application if a 0 byte + record is received with invalid padding compared to if a 0 byte record is + received with an invalid MAC. If the application then behaves differently + based on that in a way that is detectable to the remote peer, then this + amounts to a padding oracle that could be used to decrypt data. + + In order for this to be exploitable "non-stitched" ciphersuites must be in + use. Stitched ciphersuites are optimised implementations of certain + commonly used ciphersuites. Also the application must call SSL_shutdown() + twice even if a protocol error has occurred (applications should not do + this but some do anyway). + + This issue was discovered by Juraj Somorovsky, Robert Merget and Nimrod + Aviram, with additional investigation by Steven Collison and Andrew + Hourselt. It was reported to OpenSSL on 10th December 2018. + ([CVE-2019-1559]) + + *Matt Caswell* + + * Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0(). + + *Richard Levitte* + +### Changes between 1.0.2p and 1.0.2q [20 Nov 2018] + + * Microarchitecture timing vulnerability in ECC scalar multiplication + + OpenSSL ECC scalar multiplication, used in e.g. ECDSA and ECDH, has been + shown to be vulnerable to a microarchitecture timing side channel attack. + An attacker with sufficient access to mount local timing attacks during + ECDSA signature generation could recover the private key. + + This issue was reported to OpenSSL on 26th October 2018 by Alejandro + Cabrera Aldaya, Billy Brumley, Sohaib ul Hassan, Cesar Pereida Garcia and + Nicola Tuveri. + ([CVE-2018-5407]) + + *Billy Brumley* + + * Timing vulnerability in DSA signature generation + + The OpenSSL DSA signature algorithm has been shown to be vulnerable to a + timing side channel attack. An attacker could use variations in the signing + algorithm to recover the private key. + + This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser. + ([CVE-2018-0734]) + + *Paul Dale* + + * Resolve a compatibility issue in EC_GROUP handling with the FIPS Object + Module, accidentally introduced while backporting security fixes from the + development branch and hindering the use of ECC in FIPS mode. + + *Nicola Tuveri* + +### Changes between 1.0.2o and 1.0.2p [14 Aug 2018] + + * Client DoS due to large DH parameter + + During key agreement in a TLS handshake using a DH(E) based ciphersuite a + malicious server can send a very large prime value to the client. This will + cause the client to spend an unreasonably long period of time generating a + key for this prime resulting in a hang until the client has finished. This + could be exploited in a Denial Of Service attack. + + This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken + ([CVE-2018-0732]) + + *Guido Vranken* + + * Cache timing vulnerability in RSA Key Generation + + The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to + a cache timing side channel attack. An attacker with sufficient access to + mount cache timing attacks during the RSA key generation process could + recover the private key. + + This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera + Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia. + ([CVE-2018-0737]) + + *Billy Brumley* + + * Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str + parameter is no longer accepted, as it leads to a corrupt table. NULL + pem_str is reserved for alias entries only. + + *Richard Levitte* + + * Revert blinding in ECDSA sign and instead make problematic addition + length-invariant. Switch even to fixed-length Montgomery multiplication. + + *Andy Polyakov* + + * Change generating and checking of primes so that the error rate of not + being prime depends on the intended use based on the size of the input. + For larger primes this will result in more rounds of Miller-Rabin. + The maximal error rate for primes with more than 1080 bits is lowered + to 2^-128. + + *Kurt Roeckx, Annie Yousar* + + * Increase the number of Miller-Rabin rounds for DSA key generating to 64. + + *Kurt Roeckx* + + * Add blinding to ECDSA and DSA signatures to protect against side channel + attacks discovered by Keegan Ryan (NCC Group). + + *Matt Caswell* + + * When unlocking a pass phrase protected PEM file or PKCS#8 container, we + now allow empty (zero character) pass phrases. + + *Richard Levitte* + + * Certificate time validation (X509_cmp_time) enforces stricter + compliance with RFC 5280. Fractional seconds and timezone offsets + are no longer allowed. + + *Emilia Käsper* + +### Changes between 1.0.2n and 1.0.2o [27 Mar 2018] + + * Constructed ASN.1 types with a recursive definition could exceed the stack + + Constructed ASN.1 types with a recursive definition (such as can be found + in PKCS7) could eventually exceed the stack given malicious input with + excessive recursion. This could result in a Denial Of Service attack. There + are no such structures used within SSL/TLS that come from untrusted sources + so this is considered safe. + + This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz + project. + ([CVE-2018-0739]) + + *Matt Caswell* + +### Changes between 1.0.2m and 1.0.2n [7 Dec 2017] + + * Read/write after SSL object in error state + + OpenSSL 1.0.2 (starting from version 1.0.2b) introduced an "error state" + mechanism. The intent was that if a fatal error occurred during a handshake + then OpenSSL would move into the error state and would immediately fail if + you attempted to continue the handshake. This works as designed for the + explicit handshake functions (SSL_do_handshake(), SSL_accept() and + SSL_connect()), however due to a bug it does not work correctly if + SSL_read() or SSL_write() is called directly. In that scenario, if the + handshake fails then a fatal error will be returned in the initial function + call. If SSL_read()/SSL_write() is subsequently called by the application + for the same SSL object then it will succeed and the data is passed without + being decrypted/encrypted directly from the SSL/TLS record layer. + + In order to exploit this issue an application bug would have to be present + that resulted in a call to SSL_read()/SSL_write() being issued after having + already received a fatal error. + + This issue was reported to OpenSSL by David Benjamin (Google). + ([CVE-2017-3737]) + + *Matt Caswell* + + * rsaz_1024_mul_avx2 overflow bug on x86_64 + + There is an overflow bug in the AVX2 Montgomery multiplication procedure + used in exponentiation with 1024-bit moduli. No EC algorithms are affected. + Analysis suggests that attacks against RSA and DSA as a result of this + defect would be very difficult to perform and are not believed likely. + Attacks against DH1024 are considered just feasible, because most of the + work necessary to deduce information about a private key may be performed + offline. The amount of resources required for such an attack would be + significant. However, for an attack on TLS to be meaningful, the server + would have to share the DH1024 private key among multiple clients, which is + no longer an option since CVE-2016-0701. + + This only affects processors that support the AVX2 but not ADX extensions + like Intel Haswell (4th generation). + + This issue was reported to OpenSSL by David Benjamin (Google). The issue + was originally found via the OSS-Fuzz project. + ([CVE-2017-3738]) + + *Andy Polyakov* + +### Changes between 1.0.2l and 1.0.2m [2 Nov 2017] + + * bn_sqrx8x_internal carry bug on x86_64 + + There is a carry propagating bug in the x86_64 Montgomery squaring + procedure. No EC algorithms are affected. Analysis suggests that attacks + against RSA and DSA as a result of this defect would be very difficult to + perform and are not believed likely. Attacks against DH are considered just + feasible (although very difficult) because most of the work necessary to + deduce information about a private key may be performed offline. The amount + of resources required for such an attack would be very significant and + likely only accessible to a limited number of attackers. An attacker would + additionally need online access to an unpatched system using the target + private key in a scenario with persistent DH parameters and a private + key that is shared between multiple clients. + + This only affects processors that support the BMI1, BMI2 and ADX extensions + like Intel Broadwell (5th generation) and later or AMD Ryzen. + + This issue was reported to OpenSSL by the OSS-Fuzz project. + ([CVE-2017-3736]) + + *Andy Polyakov* + + * Malformed X.509 IPAddressFamily could cause OOB read + + If an X.509 certificate has a malformed IPAddressFamily extension, + OpenSSL could do a one-byte buffer overread. The most likely result + would be an erroneous display of the certificate in text format. + + This issue was reported to OpenSSL by the OSS-Fuzz project. + + *Rich Salz* + +### Changes between 1.0.2k and 1.0.2l [25 May 2017] + + * Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target + platform rather than 'mingw'. + + *Richard Levitte* + +### Changes between 1.0.2j and 1.0.2k [26 Jan 2017] + + * Truncated packet could crash via OOB read + + If one side of an SSL/TLS path is running on a 32-bit host and a specific + cipher is being used, then a truncated packet can cause that host to + perform an out-of-bounds read, usually resulting in a crash. + + This issue was reported to OpenSSL by Robert Święcki of Google. + ([CVE-2017-3731]) + + *Andy Polyakov* + + * BN_mod_exp may produce incorrect results on x86_64 + + There is a carry propagating bug in the x86_64 Montgomery squaring + procedure. No EC algorithms are affected. Analysis suggests that attacks + against RSA and DSA as a result of this defect would be very difficult to + perform and are not believed likely. Attacks against DH are considered just + feasible (although very difficult) because most of the work necessary to + deduce information about a private key may be performed offline. The amount + of resources required for such an attack would be very significant and + likely only accessible to a limited number of attackers. An attacker would + additionally need online access to an unpatched system using the target + private key in a scenario with persistent DH parameters and a private + key that is shared between multiple clients. For example this can occur by + default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very + similar to CVE-2015-3193 but must be treated as a separate problem. + + This issue was reported to OpenSSL by the OSS-Fuzz project. + ([CVE-2017-3732]) + + *Andy Polyakov* + + * Montgomery multiplication may produce incorrect results + + There is a carry propagating bug in the Broadwell-specific Montgomery + multiplication procedure that handles input lengths divisible by, but + longer than 256 bits. Analysis suggests that attacks against RSA, DSA + and DH private keys are impossible. This is because the subroutine in + question is not used in operations with the private key itself and an input + of the attacker's direct choice. Otherwise the bug can manifest itself as + transient authentication and key negotiation failures or reproducible + erroneous outcome of public-key operations with specially crafted input. + Among EC algorithms only Brainpool P-512 curves are affected and one + presumably can attack ECDH key negotiation. Impact was not analyzed in + detail, because pre-requisites for attack are considered unlikely. Namely + multiple clients have to choose the curve in question and the server has to + share the private key among them, neither of which is default behaviour. + Even then only clients that chose the curve will be affected. + + This issue was publicly reported as transient failures and was not + initially recognized as a security issue. Thanks to Richard Morgan for + providing reproducible case. + ([CVE-2016-7055]) + + *Andy Polyakov* + + * OpenSSL now fails if it receives an unrecognised record type in TLS1.0 + or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to + prevent issues where no progress is being made and the peer continually + sends unrecognised record types, using up resources processing them. + + *Matt Caswell* + +### Changes between 1.0.2i and 1.0.2j [26 Sep 2016] + + * Missing CRL sanity check + + A bug fix which included a CRL sanity check was added to OpenSSL 1.1.0 + but was omitted from OpenSSL 1.0.2i. As a result any attempt to use + CRLs in OpenSSL 1.0.2i will crash with a null pointer exception. + + This issue only affects the OpenSSL 1.0.2i + ([CVE-2016-7052]) + + *Matt Caswell* + +### Changes between 1.0.2h and 1.0.2i [22 Sep 2016] + + * OCSP Status Request extension unbounded memory growth + + A malicious client can send an excessively large OCSP Status Request + extension. If that client continually requests renegotiation, sending a + large OCSP Status Request extension each time, then there will be unbounded + memory growth on the server. This will eventually lead to a Denial Of + Service attack through memory exhaustion. Servers with a default + configuration are vulnerable even if they do not support OCSP. Builds using + the "no-ocsp" build time option are not affected. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6304]) + + *Matt Caswell* + + * In order to mitigate the SWEET32 attack, the DES ciphers were moved from + HIGH to MEDIUM. + + This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan + Leurent (INRIA) + ([CVE-2016-2183]) + + *Rich Salz* + + * OOB write in MDC2_Update() + + An overflow can occur in MDC2_Update() either if called directly or + through the EVP_DigestUpdate() function using MDC2. If an attacker + is able to supply very large amounts of input data after a previous + call to EVP_EncryptUpdate() with a partial block then a length check + can overflow resulting in a heap corruption. + + The amount of data needed is comparable to SIZE_MAX which is impractical + on most platforms. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6303]) + + *Stephen Henson* + + * Malformed SHA512 ticket DoS + + If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a + DoS attack where a malformed ticket will result in an OOB read which will + ultimately crash. + + The use of SHA512 in TLS session tickets is comparatively rare as it requires + a custom server callback and ticket lookup mechanism. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6302]) + + *Stephen Henson* + + * OOB write in BN_bn2dec() + + The function BN_bn2dec() does not check the return value of BN_div_word(). + This can cause an OOB write if an application uses this function with an + overly large BIGNUM. This could be a problem if an overly large certificate + or CRL is printed out from an untrusted source. TLS is not affected because + record limits will reject an oversized certificate before it is parsed. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-2182]) + + *Stephen Henson* + + * OOB read in TS_OBJ_print_bio() + + The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is + the total length the OID text representation would use and not the amount + of data written. This will result in OOB reads when large OIDs are + presented. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-2180]) + + *Stephen Henson* + + * Pointer arithmetic undefined behaviour + + Avoid some undefined pointer arithmetic + + A common idiom in the codebase is to check limits in the following manner: + "p + len > limit" + + Where "p" points to some malloc'd data of SIZE bytes and + limit == p + SIZE + + "len" here could be from some externally supplied data (e.g. from a TLS + message). + + The rules of C pointer arithmetic are such that "p + len" is only well + defined where len <= SIZE. Therefore the above idiom is actually + undefined behaviour. + + For example this could cause problems if some malloc implementation + provides an address for "p" such that "p + len" actually overflows for + values of len that are too big and therefore p + len < limit. + + This issue was reported to OpenSSL by Guido Vranken + ([CVE-2016-2177]) + + *Matt Caswell* + + * Constant time flag not preserved in DSA signing + + Operations in the DSA signing algorithm should run in constant time in + order to avoid side channel attacks. A flaw in the OpenSSL DSA + implementation means that a non-constant time codepath is followed for + certain operations. This has been demonstrated through a cache-timing + attack to be sufficient for an attacker to recover the private DSA key. + + This issue was reported by César Pereida (Aalto University), Billy Brumley + (Tampere University of Technology), and Yuval Yarom (The University of + Adelaide and NICTA). + ([CVE-2016-2178]) + + *César Pereida* + + * DTLS buffered message DoS + + In a DTLS connection where handshake messages are delivered out-of-order + those messages that OpenSSL is not yet ready to process will be buffered + for later use. Under certain circumstances, a flaw in the logic means that + those messages do not get removed from the buffer even though the handshake + has been completed. An attacker could force up to approx. 15 messages to + remain in the buffer when they are no longer required. These messages will + be cleared when the DTLS connection is closed. The default maximum size for + a message is 100k. Therefore the attacker could force an additional 1500k + to be consumed per connection. By opening many simulataneous connections an + attacker could cause a DoS attack through memory exhaustion. + + This issue was reported to OpenSSL by Quan Luo. + ([CVE-2016-2179]) + + *Matt Caswell* + + * DTLS replay protection DoS + + A flaw in the DTLS replay attack protection mechanism means that records + that arrive for future epochs update the replay protection "window" before + the MAC for the record has been validated. This could be exploited by an + attacker by sending a record for the next epoch (which does not have to + decrypt or have a valid MAC), with a very large sequence number. This means + that all subsequent legitimate packets are dropped causing a denial of + service for a specific DTLS connection. + + This issue was reported to OpenSSL by the OCAP audit team. + ([CVE-2016-2181]) + + *Matt Caswell* + + * Certificate message OOB reads + + In OpenSSL 1.0.2 and earlier some missing message length checks can result + in OOB reads of up to 2 bytes beyond an allocated buffer. There is a + theoretical DoS risk but this has not been observed in practice on common + platforms. + + The messages affected are client certificate, client certificate request + and server certificate. As a result the attack can only be performed + against a client or a server which enables client authentication. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6306]) + + *Stephen Henson* + +### Changes between 1.0.2g and 1.0.2h [3 May 2016] + + * Prevent padding oracle in AES-NI CBC MAC check + + A MITM attacker can use a padding oracle attack to decrypt traffic + when the connection uses an AES CBC cipher and the server support + AES-NI. + + This issue was introduced as part of the fix for Lucky 13 padding + attack ([CVE-2013-0169]). The padding check was rewritten to be in + constant time by making sure that always the same bytes are read and + compared against either the MAC or padding bytes. But it no longer + checked that there was enough data to have both the MAC and padding + bytes. + + This issue was reported by Juraj Somorovsky using TLS-Attacker. + + *Kurt Roeckx* + + * Fix EVP_EncodeUpdate overflow + + An overflow can occur in the EVP_EncodeUpdate() function which is used for + Base64 encoding of binary data. If an attacker is able to supply very large + amounts of input data then a length check can overflow resulting in a heap + corruption. + + Internally to OpenSSL the EVP_EncodeUpdate() function is primarily used by + the `PEM_write_bio*` family of functions. These are mainly used within the + OpenSSL command line applications, so any application which processes data + from an untrusted source and outputs it as a PEM file should be considered + vulnerable to this issue. User applications that call these APIs directly + with large amounts of untrusted data may also be vulnerable. + + This issue was reported by Guido Vranken. + ([CVE-2016-2105]) + + *Matt Caswell* + + * Fix EVP_EncryptUpdate overflow + + An overflow can occur in the EVP_EncryptUpdate() function. If an attacker + is able to supply very large amounts of input data after a previous call to + EVP_EncryptUpdate() with a partial block then a length check can overflow + resulting in a heap corruption. Following an analysis of all OpenSSL + internal usage of the EVP_EncryptUpdate() function all usage is one of two + forms. The first form is where the EVP_EncryptUpdate() call is known to be + the first called function after an EVP_EncryptInit(), and therefore that + specific call must be safe. The second form is where the length passed to + EVP_EncryptUpdate() can be seen from the code to be some small value and + therefore there is no possibility of an overflow. Since all instances are + one of these two forms, it is believed that there can be no overflows in + internal code due to this problem. It should be noted that + EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths. + Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances + of these calls have also been analysed too and it is believed there are no + instances in internal usage where an overflow could occur. + + This issue was reported by Guido Vranken. + ([CVE-2016-2106]) + + *Matt Caswell* + + * Prevent ASN.1 BIO excessive memory allocation + + When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio() + a short invalid encoding can cause allocation of large amounts of memory + potentially consuming excessive resources or exhausting memory. + + Any application parsing untrusted data through d2i BIO functions is + affected. The memory based functions such as d2i_X509() are *not* affected. + Since the memory based functions are used by the TLS library, TLS + applications are not affected. + + This issue was reported by Brian Carpenter. + ([CVE-2016-2109]) + + *Stephen Henson* + + * EBCDIC overread + + ASN1 Strings that are over 1024 bytes can cause an overread in applications + using the X509_NAME_oneline() function on EBCDIC systems. This could result + in arbitrary stack data being returned in the buffer. + + This issue was reported by Guido Vranken. + ([CVE-2016-2176]) + + *Matt Caswell* + + * Modify behavior of ALPN to invoke callback after SNI/servername + callback, such that updates to the SSL_CTX affect ALPN. + + *Todd Short* + + * Remove LOW from the DEFAULT cipher list. This removes singles DES from the + default. + + *Kurt Roeckx* + + * Only remove the SSLv2 methods with the no-ssl2-method option. When the + methods are enabled and ssl2 is disabled the methods return NULL. + + *Kurt Roeckx* + +### Changes between 1.0.2f and 1.0.2g [1 Mar 2016] + +* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL. + Builds that are not configured with "enable-weak-ssl-ciphers" will not + provide any "EXPORT" or "LOW" strength ciphers. + + *Viktor Dukhovni* + +* Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2 + is by default disabled at build-time. Builds that are not configured with + "enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used, + users who want to negotiate SSLv2 via the version-flexible SSLv23_method() + will need to explicitly call either of: + + SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2); + or + SSL_clear_options(ssl, SSL_OP_NO_SSLv2); + + as appropriate. Even if either of those is used, or the application + explicitly uses the version-specific SSLv2_method() or its client and + server variants, SSLv2 ciphers vulnerable to exhaustive search key + recovery have been removed. Specifically, the SSLv2 40-bit EXPORT + ciphers, and SSLv2 56-bit DES are no longer available. + ([CVE-2016-0800]) + + *Viktor Dukhovni* + + * Fix a double-free in DSA code + + A double free bug was discovered when OpenSSL parses malformed DSA private + keys and could lead to a DoS attack or memory corruption for applications + that receive DSA private keys from untrusted sources. This scenario is + considered rare. + + This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using + libFuzzer. + ([CVE-2016-0705]) + + *Stephen Henson* + + * Disable SRP fake user seed to address a server memory leak. + + Add a new method SRP_VBASE_get1_by_user that handles the seed properly. + + SRP_VBASE_get_by_user had inconsistent memory management behaviour. + In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user + was changed to ignore the "fake user" SRP seed, even if the seed + is configured. + + Users should use SRP_VBASE_get1_by_user instead. Note that in + SRP_VBASE_get1_by_user, caller must free the returned value. Note + also that even though configuring the SRP seed attempts to hide + invalid usernames by continuing the handshake with fake + credentials, this behaviour is not constant time and no strong + guarantees are made that the handshake is indistinguishable from + that of a valid user. + ([CVE-2016-0798]) + + *Emilia Käsper* + + * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption + + In the BN_hex2bn function the number of hex digits is calculated using an + int value `i`. Later `bn_expand` is called with a value of `i * 4`. For + large values of `i` this can result in `bn_expand` not allocating any + memory because `i * 4` is negative. This can leave the internal BIGNUM data + field as NULL leading to a subsequent NULL ptr deref. For very large values + of `i`, the calculation `i * 4` could be a positive value smaller than `i`. + In this case memory is allocated to the internal BIGNUM data field, but it + is insufficiently sized leading to heap corruption. A similar issue exists + in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn + is ever called by user applications with very large untrusted hex/dec data. + This is anticipated to be a rare occurrence. + + All OpenSSL internal usage of these functions use data that is not expected + to be untrusted, e.g. config file data or application command line + arguments. If user developed applications generate config file data based + on untrusted data then it is possible that this could also lead to security + consequences. This is also anticipated to be rare. + + This issue was reported to OpenSSL by Guido Vranken. + ([CVE-2016-0797]) + + *Matt Caswell* + + * Fix memory issues in `BIO_*printf` functions + + The internal `fmtstr` function used in processing a "%s" format string in + the `BIO_*printf` functions could overflow while calculating the length of a + string and cause an OOB read when printing very long strings. + + Additionally the internal `doapr_outch` function can attempt to write to an + OOB memory location (at an offset from the NULL pointer) in the event of a + memory allocation failure. In 1.0.2 and below this could be caused where + the size of a buffer to be allocated is greater than INT_MAX. E.g. this + could be in processing a very long "%s" format string. Memory leaks can + also occur. + + The first issue may mask the second issue dependent on compiler behaviour. + These problems could enable attacks where large amounts of untrusted data + is passed to the `BIO_*printf` functions. If applications use these functions + in this way then they could be vulnerable. OpenSSL itself uses these + functions when printing out human-readable dumps of ASN.1 data. Therefore + applications that print this data could be vulnerable if the data is from + untrusted sources. OpenSSL command line applications could also be + vulnerable where they print out ASN.1 data, or if untrusted data is passed + as command line arguments. + + Libssl is not considered directly vulnerable. Additionally certificates etc + received via remote connections via libssl are also unlikely to be able to + trigger these issues because of message size limits enforced within libssl. + + This issue was reported to OpenSSL Guido Vranken. + ([CVE-2016-0799]) + + *Matt Caswell* + + * Side channel attack on modular exponentiation + + A side-channel attack was found which makes use of cache-bank conflicts on + the Intel Sandy-Bridge microarchitecture which could lead to the recovery + of RSA keys. The ability to exploit this issue is limited as it relies on + an attacker who has control of code in a thread running on the same + hyper-threaded core as the victim thread which is performing decryptions. + + This issue was reported to OpenSSL by Yuval Yarom, The University of + Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and + Nadia Heninger, University of Pennsylvania with more information at + . + ([CVE-2016-0702]) + + *Andy Polyakov* + + * Change the `req` command to generate a 2048-bit RSA/DSA key by default, + if no keysize is specified with default_bits. This fixes an + omission in an earlier change that changed all RSA/DSA key generation + commands to use 2048 bits by default. + + *Emilia Käsper* + +### Changes between 1.0.2e and 1.0.2f [28 Jan 2016] + + * DH small subgroups + + Historically OpenSSL only ever generated DH parameters based on "safe" + primes. More recently (in version 1.0.2) support was provided for + generating X9.42 style parameter files such as those required for RFC 5114 + support. The primes used in such files may not be "safe". Where an + application is using DH configured with parameters based on primes that are + not "safe" then an attacker could use this fact to find a peer's private + DH exponent. This attack requires that the attacker complete multiple + handshakes in which the peer uses the same private DH exponent. For example + this could be used to discover a TLS server's private DH exponent if it's + reusing the private DH exponent or it's using a static DH ciphersuite. + + OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in + TLS. It is not on by default. If the option is not set then the server + reuses the same private DH exponent for the life of the server process and + would be vulnerable to this attack. It is believed that many popular + applications do set this option and would therefore not be at risk. + + The fix for this issue adds an additional check where a "q" parameter is + available (as is the case in X9.42 based parameters). This detects the + only known attack, and is the only possible defense for static DH + ciphersuites. This could have some performance impact. + + Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by + default and cannot be disabled. This could have some performance impact. + + This issue was reported to OpenSSL by Antonio Sanso (Adobe). + ([CVE-2016-0701]) + + *Matt Caswell* + + * SSLv2 doesn't block disabled ciphers + + A malicious client can negotiate SSLv2 ciphers that have been disabled on + the server and complete SSLv2 handshakes even if all SSLv2 ciphers have + been disabled, provided that the SSLv2 protocol was not also disabled via + SSL_OP_NO_SSLv2. + + This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram + and Sebastian Schinzel. + ([CVE-2015-3197]) + + *Viktor Dukhovni* + +### Changes between 1.0.2d and 1.0.2e [3 Dec 2015] + + * BN_mod_exp may produce incorrect results on x86_64 + + There is a carry propagating bug in the x86_64 Montgomery squaring + procedure. No EC algorithms are affected. Analysis suggests that attacks + against RSA and DSA as a result of this defect would be very difficult to + perform and are not believed likely. Attacks against DH are considered just + feasible (although very difficult) because most of the work necessary to + deduce information about a private key may be performed offline. The amount + of resources required for such an attack would be very significant and + likely only accessible to a limited number of attackers. An attacker would + additionally need online access to an unpatched system using the target + private key in a scenario with persistent DH parameters and a private + key that is shared between multiple clients. For example this can occur by + default in OpenSSL DHE based SSL/TLS ciphersuites. + + This issue was reported to OpenSSL by Hanno Böck. + ([CVE-2015-3193]) + + *Andy Polyakov* + + * Certificate verify crash with missing PSS parameter + + The signature verification routines will crash with a NULL pointer + dereference if presented with an ASN.1 signature using the RSA PSS + algorithm and absent mask generation function parameter. Since these + routines are used to verify certificate signature algorithms this can be + used to crash any certificate verification operation and exploited in a + DoS attack. Any application which performs certificate verification is + vulnerable including OpenSSL clients and servers which enable client + authentication. + + This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG). + ([CVE-2015-3194]) + + *Stephen Henson* + + * X509_ATTRIBUTE memory leak + + When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak + memory. This structure is used by the PKCS#7 and CMS routines so any + application which reads PKCS#7 or CMS data from untrusted sources is + affected. SSL/TLS is not affected. + + This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using + libFuzzer. + ([CVE-2015-3195]) + + *Stephen Henson* + + * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs. + This changes the decoding behaviour for some invalid messages, + though the change is mostly in the more lenient direction, and + legacy behaviour is preserved as much as possible. + + *Emilia Käsper* + + * In DSA_generate_parameters_ex, if the provided seed is too short, + return an error + + *Rich Salz and Ismo Puustinen * + +### Changes between 1.0.2c and 1.0.2d [9 Jul 2015] + + * Alternate chains certificate forgery + + During certificate verification, OpenSSL will attempt to find an + alternative certificate chain if the first attempt to build such a chain + fails. An error in the implementation of this logic can mean that an + attacker could cause certain checks on untrusted certificates to be + bypassed, such as the CA flag, enabling them to use a valid leaf + certificate to act as a CA and "issue" an invalid certificate. + + This issue was reported to OpenSSL by Adam Langley/David Benjamin + (Google/BoringSSL). + + *Matt Caswell* + +### Changes between 1.0.2b and 1.0.2c [12 Jun 2015] + + * Fix HMAC ABI incompatibility. The previous version introduced an ABI + incompatibility in the handling of HMAC. The previous ABI has now been + restored. + + *Matt Caswell* + +### Changes between 1.0.2a and 1.0.2b [11 Jun 2015] + + * Malformed ECParameters causes infinite loop + + When processing an ECParameters structure OpenSSL enters an infinite loop + if the curve specified is over a specially malformed binary polynomial + field. + + This can be used to perform denial of service against any + system which processes public keys, certificate requests or + certificates. This includes TLS clients and TLS servers with + client authentication enabled. + + This issue was reported to OpenSSL by Joseph Barr-Pixton. + ([CVE-2015-1788]) + + *Andy Polyakov* + + * Exploitable out-of-bounds read in X509_cmp_time + + X509_cmp_time does not properly check the length of the ASN1_TIME + string and can read a few bytes out of bounds. In addition, + X509_cmp_time accepts an arbitrary number of fractional seconds in the + time string. + + An attacker can use this to craft malformed certificates and CRLs of + various sizes and potentially cause a segmentation fault, resulting in + a DoS on applications that verify certificates or CRLs. TLS clients + that verify CRLs are affected. TLS clients and servers with client + authentication enabled may be affected if they use custom verification + callbacks. + + This issue was reported to OpenSSL by Robert Swiecki (Google), and + independently by Hanno Böck. + ([CVE-2015-1789]) + + *Emilia Käsper* + + * PKCS7 crash with missing EnvelopedContent + + The PKCS#7 parsing code does not handle missing inner EncryptedContent + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs + with missing content and trigger a NULL pointer dereference on parsing. + + Applications that decrypt PKCS#7 data or otherwise parse PKCS#7 + structures from untrusted sources are affected. OpenSSL clients and + servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + ([CVE-2015-1790]) + + *Emilia Käsper* + + * CMS verify infinite loop with unknown hash function + + When verifying a signedData message the CMS code can enter an infinite loop + if presented with an unknown hash function OID. This can be used to perform + denial of service against any system which verifies signedData messages using + the CMS code. + This issue was reported to OpenSSL by Johannes Bauer. + ([CVE-2015-1792]) + + *Stephen Henson* + + * Race condition handling NewSessionTicket + + If a NewSessionTicket is received by a multi-threaded client when attempting to + reuse a previous ticket then a race condition can occur potentially leading to + a double free of the ticket data. + ([CVE-2015-1791]) + + *Matt Caswell* + + * Only support 256-bit or stronger elliptic curves with the + 'ecdh_auto' setting (server) or by default (client). Of supported + curves, prefer P-256 (both). + + *Emilia Kasper* + +### Changes between 1.0.2 and 1.0.2a [19 Mar 2015] + + * ClientHello sigalgs DoS fix + + If a client connects to an OpenSSL 1.0.2 server and renegotiates with an + invalid signature algorithms extension a NULL pointer dereference will + occur. This can be exploited in a DoS attack against the server. + + This issue was was reported to OpenSSL by David Ramos of Stanford + University. + ([CVE-2015-0291]) + + *Stephen Henson and Matt Caswell* + + * Multiblock corrupted pointer fix + + OpenSSL 1.0.2 introduced the "multiblock" performance improvement. This + feature only applies on 64 bit x86 architecture platforms that support AES + NI instructions. A defect in the implementation of "multiblock" can cause + OpenSSL's internal write buffer to become incorrectly set to NULL when + using non-blocking IO. Typically, when the user application is using a + socket BIO for writing, this will only result in a failed connection. + However if some other BIO is used then it is likely that a segmentation + fault will be triggered, thus enabling a potential DoS attack. + + This issue was reported to OpenSSL by Daniel Danner and Rainer Mueller. + ([CVE-2015-0290]) + + *Matt Caswell* + + * Segmentation fault in DTLSv1_listen fix + + The DTLSv1_listen function is intended to be stateless and processes the + initial ClientHello from many peers. It is common for user code to loop + over the call to DTLSv1_listen until a valid ClientHello is received with + an associated cookie. A defect in the implementation of DTLSv1_listen means + that state is preserved in the SSL object from one invocation to the next + that can lead to a segmentation fault. Errors processing the initial + ClientHello can trigger this scenario. An example of such an error could be + that a DTLS1.0 only client is attempting to connect to a DTLS1.2 only + server. + + This issue was reported to OpenSSL by Per Allansson. + ([CVE-2015-0207]) + + *Matt Caswell* + + * Segmentation fault in ASN1_TYPE_cmp fix + + The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is + made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check + certificate signature algorithm consistency this can be used to crash any + certificate verification operation and exploited in a DoS attack. Any + application which performs certificate verification is vulnerable including + OpenSSL clients and servers which enable client authentication. + ([CVE-2015-0286]) + + *Stephen Henson* + + * Segmentation fault for invalid PSS parameters fix + + The signature verification routines will crash with a NULL pointer + dereference if presented with an ASN.1 signature using the RSA PSS + algorithm and invalid parameters. Since these routines are used to verify + certificate signature algorithms this can be used to crash any + certificate verification operation and exploited in a DoS attack. Any + application which performs certificate verification is vulnerable including + OpenSSL clients and servers which enable client authentication. + + This issue was was reported to OpenSSL by Brian Carpenter. + ([CVE-2015-0208]) + + *Stephen Henson* + + * ASN.1 structure reuse memory corruption fix + + Reusing a structure in ASN.1 parsing may allow an attacker to cause + memory corruption via an invalid write. Such reuse is and has been + strongly discouraged and is believed to be rare. + + Applications that parse structures containing CHOICE or ANY DEFINED BY + components may be affected. Certificate parsing (d2i_X509 and related + functions) are however not affected. OpenSSL clients and servers are + not affected. + ([CVE-2015-0287]) + + *Stephen Henson* + + * PKCS7 NULL pointer dereferences fix + + The PKCS#7 parsing code does not handle missing outer ContentInfo + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with + missing content and trigger a NULL pointer dereference on parsing. + + Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or + otherwise parse PKCS#7 structures from untrusted sources are + affected. OpenSSL clients and servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + ([CVE-2015-0289]) + + *Emilia Käsper* + + * DoS via reachable assert in SSLv2 servers fix + + A malicious client can trigger an OPENSSL_assert (i.e., an abort) in + servers that both support SSLv2 and enable export cipher suites by sending + a specially crafted SSLv2 CLIENT-MASTER-KEY message. + + This issue was discovered by Sean Burford (Google) and Emilia Käsper + (OpenSSL development team). + ([CVE-2015-0293]) + + *Emilia Käsper* + + * Empty CKE with client auth and DHE fix + + If client auth is used then a server can seg fault in the event of a DHE + ciphersuite being selected and a zero length ClientKeyExchange message + being sent by the client. This could be exploited in a DoS attack. + ([CVE-2015-1787]) + + *Matt Caswell* + + * Handshake with unseeded PRNG fix + + Under certain conditions an OpenSSL 1.0.2 client can complete a handshake + with an unseeded PRNG. The conditions are: + - The client is on a platform where the PRNG has not been seeded + automatically, and the user has not seeded manually + - A protocol specific client method version has been used (i.e. not + SSL_client_methodv23) + - A ciphersuite is used that does not require additional random data from + the PRNG beyond the initial ClientHello client random (e.g. PSK-RC4-SHA). + + If the handshake succeeds then the client random that has been used will + have been generated from a PRNG with insufficient entropy and therefore the + output may be predictable. + + For example using the following command with an unseeded openssl will + succeed on an unpatched platform: + + openssl s_client -psk 1a2b3c4d -tls1_2 -cipher PSK-RC4-SHA + ([CVE-2015-0285]) + + *Matt Caswell* + + * Use After Free following d2i_ECPrivatekey error fix + + A malformed EC private key file consumed via the d2i_ECPrivateKey function + could cause a use after free condition. This, in turn, could cause a double + free in several private key parsing functions (such as d2i_PrivateKey + or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption + for applications that receive EC private keys from untrusted + sources. This scenario is considered rare. + + This issue was discovered by the BoringSSL project and fixed in their + commit 517073cd4b. + ([CVE-2015-0209]) + + *Matt Caswell* + + * X509_to_X509_REQ NULL pointer deref fix + + The function X509_to_X509_REQ will crash with a NULL pointer dereference if + the certificate key is invalid. This function is rarely used in practice. + + This issue was discovered by Brian Carpenter. + ([CVE-2015-0288]) + + *Stephen Henson* + + * Removed the export ciphers from the DEFAULT ciphers + + *Kurt Roeckx* + +### Changes between 1.0.1l and 1.0.2 [22 Jan 2015] + + * Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g. + ARMv5 through ARMv8, as opposite to "locking" it to single one. + So far those who have to target multiple platforms would compromise + and argue that binary targeting say ARMv5 would still execute on + ARMv8. "Universal" build resolves this compromise by providing + near-optimal performance even on newer platforms. + + *Andy Polyakov* + + * Accelerated NIST P-256 elliptic curve implementation for x86_64 + (other platforms pending). + + *Shay Gueron & Vlad Krasnov (Intel Corp), Andy Polyakov* + + * Add support for the SignedCertificateTimestampList certificate and + OCSP response extensions from RFC6962. + + *Rob Stradling* + + * Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.) + for corner cases. (Certain input points at infinity could lead to + bogus results, with non-infinity inputs mapped to infinity too.) + + *Bodo Moeller* + + * Initial support for PowerISA 2.0.7, first implemented in POWER8. + This covers AES, SHA256/512 and GHASH. "Initial" means that most + common cases are optimized and there still is room for further + improvements. Vector Permutation AES for Altivec is also added. + + *Andy Polyakov* + + * Add support for little-endian ppc64 Linux target. + + *Marcelo Cerri (IBM)* + + * Initial support for AMRv8 ISA crypto extensions. This covers AES, + SHA1, SHA256 and GHASH. "Initial" means that most common cases + are optimized and there still is room for further improvements. + Both 32- and 64-bit modes are supported. + + *Andy Polyakov, Ard Biesheuvel (Linaro)* + + * Improved ARMv7 NEON support. + + *Andy Polyakov* + + * Support for SPARC Architecture 2011 crypto extensions, first + implemented in SPARC T4. This covers AES, DES, Camellia, SHA1, + SHA256/512, MD5, GHASH and modular exponentiation. + + *Andy Polyakov, David Miller* + + * Accelerated modular exponentiation for Intel processors, a.k.a. + RSAZ. + + *Shay Gueron & Vlad Krasnov (Intel Corp)* + + * Support for new and upcoming Intel processors, including AVX2, + BMI and SHA ISA extensions. This includes additional "stitched" + implementations, AESNI-SHA256 and GCM, and multi-buffer support + for TLS encrypt. + + This work was sponsored by Intel Corp. + + *Andy Polyakov* + + * Support for DTLS 1.2. This adds two sets of DTLS methods: DTLS_*_method() + supports both DTLS 1.2 and 1.0 and should use whatever version the peer + supports and DTLSv1_2_*_method() which supports DTLS 1.2 only. + + *Steve Henson* + + * Use algorithm specific chains in SSL_CTX_use_certificate_chain_file(): + this fixes a limitation in previous versions of OpenSSL. + + *Steve Henson* + + * Extended RSA OAEP support via EVP_PKEY API. Options to specify digest, + MGF1 digest and OAEP label. + + *Steve Henson* + + * Add EVP support for key wrapping algorithms, to avoid problems with + existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in + the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap + algorithms and include tests cases. + + *Steve Henson* + + * Add functions to allocate and set the fields of an ECDSA_METHOD + structure. + + *Douglas E. Engert, Steve Henson* + + * New functions OPENSSL_gmtime_diff and ASN1_TIME_diff to find the + difference in days and seconds between two tm or ASN1_TIME structures. + + *Steve Henson* + + * Add -rev test option to s_server to just reverse order of characters + received by client and send back to server. Also prints an abbreviated + summary of the connection parameters. + + *Steve Henson* + + * New option -brief for s_client and s_server to print out a brief summary + of connection parameters. + + *Steve Henson* + + * Add callbacks for arbitrary TLS extensions. + + *Trevor Perrin and Ben Laurie* + + * New option -crl_download in several openssl utilities to download CRLs + from CRLDP extension in certificates. + + *Steve Henson* + + * New options -CRL and -CRLform for s_client and s_server for CRLs. + + *Steve Henson* + + * New function X509_CRL_diff to generate a delta CRL from the difference + of two full CRLs. Add support to "crl" utility. + + *Steve Henson* + + * New functions to set lookup_crls function and to retrieve + X509_STORE from X509_STORE_CTX. + + *Steve Henson* + + * Print out deprecated issuer and subject unique ID fields in + certificates. + + *Steve Henson* + + * Extend OCSP I/O functions so they can be used for simple general purpose + HTTP as well as OCSP. New wrapper function which can be used to download + CRLs using the OCSP API. + + *Steve Henson* + + * Delegate command line handling in s_client/s_server to SSL_CONF APIs. + + *Steve Henson* + + * `SSL_CONF*` functions. These provide a common framework for application + configuration using configuration files or command lines. + + *Steve Henson* + + * SSL/TLS tracing code. This parses out SSL/TLS records using the + message callback and prints the results. Needs compile time option + "enable-ssl-trace". New options to s_client and s_server to enable + tracing. + + *Steve Henson* + + * New ctrl and macro to retrieve supported points extensions. + Print out extension in s_server and s_client. + + *Steve Henson* + + * New functions to retrieve certificate signature and signature + OID NID. + + *Steve Henson* + + * Add functions to retrieve and manipulate the raw cipherlist sent by a + client to OpenSSL. + + *Steve Henson* + + * New Suite B modes for TLS code. These use and enforce the requirements + of RFC6460: restrict ciphersuites, only permit Suite B algorithms and + only use Suite B curves. The Suite B modes can be set by using the + strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring. + + *Steve Henson* + + * New chain verification flags for Suite B levels of security. Check + algorithms are acceptable when flags are set in X509_verify_cert. + + *Steve Henson* + + * Make tls1_check_chain return a set of flags indicating checks passed + by a certificate chain. Add additional tests to handle client + certificates: checks for matching certificate type and issuer name + comparison. + + *Steve Henson* + + * If an attempt is made to use a signature algorithm not in the peer + preference list abort the handshake. If client has no suitable + signature algorithms in response to a certificate request do not + use the certificate. + + *Steve Henson* + + * If server EC tmp key is not in client preference list abort handshake. + + *Steve Henson* + + * Add support for certificate stores in CERT structure. This makes it + possible to have different stores per SSL structure or one store in + the parent SSL_CTX. Include distinct stores for certificate chain + verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN + to build and store a certificate chain in CERT structure: returning + an error if the chain cannot be built: this will allow applications + to test if a chain is correctly configured. + + Note: if the CERT based stores are not set then the parent SSL_CTX + store is used to retain compatibility with existing behaviour. + + *Steve Henson* + + * New function ssl_set_client_disabled to set a ciphersuite disabled + mask based on the current session, check mask when sending client + hello and checking the requested ciphersuite. + + *Steve Henson* + + * New ctrls to retrieve and set certificate types in a certificate + request message. Print out received values in s_client. If certificate + types is not set with custom values set sensible values based on + supported signature algorithms. + + *Steve Henson* + + * Support for distinct client and server supported signature algorithms. + + *Steve Henson* + + * Add certificate callback. If set this is called whenever a certificate + is required by client or server. An application can decide which + certificate chain to present based on arbitrary criteria: for example + supported signature algorithms. Add very simple example to s_server. + This fixes many of the problems and restrictions of the existing client + certificate callback: for example you can now clear an existing + certificate and specify the whole chain. + + *Steve Henson* + + * Add new "valid_flags" field to CERT_PKEY structure which determines what + the certificate can be used for (if anything). Set valid_flags field + in new tls1_check_chain function. Simplify ssl_set_cert_masks which used + to have similar checks in it. + + Add new "cert_flags" field to CERT structure and include a "strict mode". + This enforces some TLS certificate requirements (such as only permitting + certificate signature algorithms contained in the supported algorithms + extension) which some implementations ignore: this option should be used + with caution as it could cause interoperability issues. + + *Steve Henson* + + * Update and tidy signature algorithm extension processing. Work out + shared signature algorithms based on preferences and peer algorithms + and print them out in s_client and s_server. Abort handshake if no + shared signature algorithms. + + *Steve Henson* + + * Add new functions to allow customised supported signature algorithms + for SSL and SSL_CTX structures. Add options to s_client and s_server + to support them. + + *Steve Henson* + + * New function SSL_certs_clear() to delete all references to certificates + from an SSL structure. Before this once a certificate had been added + it couldn't be removed. + + *Steve Henson* + + * Integrate hostname, email address and IP address checking with certificate + verification. New verify options supporting checking in openssl utility. + + *Steve Henson* + + * Fixes and wildcard matching support to hostname and email checking + functions. Add manual page. + + *Florian Weimer (Red Hat Product Security Team)* + + * New functions to check a hostname email or IP address against a + certificate. Add options x509 utility to print results of checks against + a certificate. + + *Steve Henson* + + * Fix OCSP checking. + + *Rob Stradling and Ben Laurie* + + * Initial experimental support for explicitly trusted non-root CAs. + OpenSSL still tries to build a complete chain to a root but if an + intermediate CA has a trust setting included that is used. The first + setting is used: whether to trust (e.g., -addtrust option to the x509 + utility) or reject. + + *Steve Henson* + + * Add -trusted_first option which attempts to find certificates in the + trusted store even if an untrusted chain is also supplied. + + *Steve Henson* + + * MIPS assembly pack updates: support for MIPS32r2 and SmartMIPS ASE, + platform support for Linux and Android. + + *Andy Polyakov* + + * Support for linux-x32, ILP32 environment in x86_64 framework. + + *Andy Polyakov* + + * Experimental multi-implementation support for FIPS capable OpenSSL. + When in FIPS mode the approved implementations are used as normal, + when not in FIPS mode the internal unapproved versions are used instead. + This means that the FIPS capable OpenSSL isn't forced to use the + (often lower performance) FIPS implementations outside FIPS mode. + + *Steve Henson* + + * Transparently support X9.42 DH parameters when calling + PEM_read_bio_DHparameters. This means existing applications can handle + the new parameter format automatically. + + *Steve Henson* + + * Initial experimental support for X9.42 DH parameter format: mainly + to support use of 'q' parameter for RFC5114 parameters. + + *Steve Henson* + + * Add DH parameters from RFC5114 including test data to dhtest. + + *Steve Henson* + + * Support for automatic EC temporary key parameter selection. If enabled + the most preferred EC parameters are automatically used instead of + hardcoded fixed parameters. Now a server just has to call: + SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically + support ECDH and use the most appropriate parameters. + + *Steve Henson* + + * Enhance and tidy EC curve and point format TLS extension code. Use + static structures instead of allocation if default values are used. + New ctrls to set curves we wish to support and to retrieve shared curves. + Print out shared curves in s_server. New options to s_server and s_client + to set list of supported curves. + + *Steve Henson* + + * New ctrls to retrieve supported signature algorithms and + supported curve values as an array of NIDs. Extend openssl utility + to print out received values. + + *Steve Henson* + + * Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert + between NIDs and the more common NIST names such as "P-256". Enhance + ecparam utility and ECC method to recognise the NIST names for curves. + + *Steve Henson* + + * Enhance SSL/TLS certificate chain handling to support different + chains for each certificate instead of one chain in the parent SSL_CTX. + + *Steve Henson* + + * Support for fixed DH ciphersuite client authentication: where both + server and client use DH certificates with common parameters. + + *Steve Henson* + + * Support for fixed DH ciphersuites: those requiring DH server + certificates. + + *Steve Henson* + + * New function i2d_re_X509_tbs for re-encoding the TBS portion of + the certificate. + Note: Related 1.0.2-beta specific macros X509_get_cert_info, + X509_CINF_set_modified, X509_CINF_get_issuer, X509_CINF_get_extensions and + X509_CINF_get_signature were reverted post internal team review. + +OpenSSL 1.0.1 +------------- + +### Changes between 1.0.1t and 1.0.1u [22 Sep 2016] + + * OCSP Status Request extension unbounded memory growth + + A malicious client can send an excessively large OCSP Status Request + extension. If that client continually requests renegotiation, sending a + large OCSP Status Request extension each time, then there will be unbounded + memory growth on the server. This will eventually lead to a Denial Of + Service attack through memory exhaustion. Servers with a default + configuration are vulnerable even if they do not support OCSP. Builds using + the "no-ocsp" build time option are not affected. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6304]) + + *Matt Caswell* + + * In order to mitigate the SWEET32 attack, the DES ciphers were moved from + HIGH to MEDIUM. + + This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan + Leurent (INRIA) + ([CVE-2016-2183]) + + *Rich Salz* + + * OOB write in MDC2_Update() + + An overflow can occur in MDC2_Update() either if called directly or + through the EVP_DigestUpdate() function using MDC2. If an attacker + is able to supply very large amounts of input data after a previous + call to EVP_EncryptUpdate() with a partial block then a length check + can overflow resulting in a heap corruption. + + The amount of data needed is comparable to SIZE_MAX which is impractical + on most platforms. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6303]) + + *Stephen Henson* + + * Malformed SHA512 ticket DoS + + If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a + DoS attack where a malformed ticket will result in an OOB read which will + ultimately crash. + + The use of SHA512 in TLS session tickets is comparatively rare as it requires + a custom server callback and ticket lookup mechanism. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6302]) + + *Stephen Henson* + + * OOB write in BN_bn2dec() + + The function BN_bn2dec() does not check the return value of BN_div_word(). + This can cause an OOB write if an application uses this function with an + overly large BIGNUM. This could be a problem if an overly large certificate + or CRL is printed out from an untrusted source. TLS is not affected because + record limits will reject an oversized certificate before it is parsed. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-2182]) + + *Stephen Henson* + + * OOB read in TS_OBJ_print_bio() + + The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is + the total length the OID text representation would use and not the amount + of data written. This will result in OOB reads when large OIDs are + presented. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-2180]) + + *Stephen Henson* + + * Pointer arithmetic undefined behaviour + + Avoid some undefined pointer arithmetic + + A common idiom in the codebase is to check limits in the following manner: + "p + len > limit" + + Where "p" points to some malloc'd data of SIZE bytes and + limit == p + SIZE + + "len" here could be from some externally supplied data (e.g. from a TLS + message). + + The rules of C pointer arithmetic are such that "p + len" is only well + defined where len <= SIZE. Therefore the above idiom is actually + undefined behaviour. + + For example this could cause problems if some malloc implementation + provides an address for "p" such that "p + len" actually overflows for + values of len that are too big and therefore p + len < limit. + + This issue was reported to OpenSSL by Guido Vranken + ([CVE-2016-2177]) + + *Matt Caswell* + + * Constant time flag not preserved in DSA signing + + Operations in the DSA signing algorithm should run in constant time in + order to avoid side channel attacks. A flaw in the OpenSSL DSA + implementation means that a non-constant time codepath is followed for + certain operations. This has been demonstrated through a cache-timing + attack to be sufficient for an attacker to recover the private DSA key. + + This issue was reported by César Pereida (Aalto University), Billy Brumley + (Tampere University of Technology), and Yuval Yarom (The University of + Adelaide and NICTA). + ([CVE-2016-2178]) + + *César Pereida* + + * DTLS buffered message DoS + + In a DTLS connection where handshake messages are delivered out-of-order + those messages that OpenSSL is not yet ready to process will be buffered + for later use. Under certain circumstances, a flaw in the logic means that + those messages do not get removed from the buffer even though the handshake + has been completed. An attacker could force up to approx. 15 messages to + remain in the buffer when they are no longer required. These messages will + be cleared when the DTLS connection is closed. The default maximum size for + a message is 100k. Therefore the attacker could force an additional 1500k + to be consumed per connection. By opening many simulataneous connections an + attacker could cause a DoS attack through memory exhaustion. + + This issue was reported to OpenSSL by Quan Luo. + ([CVE-2016-2179]) + + *Matt Caswell* + + * DTLS replay protection DoS + + A flaw in the DTLS replay attack protection mechanism means that records + that arrive for future epochs update the replay protection "window" before + the MAC for the record has been validated. This could be exploited by an + attacker by sending a record for the next epoch (which does not have to + decrypt or have a valid MAC), with a very large sequence number. This means + that all subsequent legitimate packets are dropped causing a denial of + service for a specific DTLS connection. + + This issue was reported to OpenSSL by the OCAP audit team. + ([CVE-2016-2181]) + + *Matt Caswell* + + * Certificate message OOB reads + + In OpenSSL 1.0.2 and earlier some missing message length checks can result + in OOB reads of up to 2 bytes beyond an allocated buffer. There is a + theoretical DoS risk but this has not been observed in practice on common + platforms. + + The messages affected are client certificate, client certificate request + and server certificate. As a result the attack can only be performed + against a client or a server which enables client authentication. + + This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.) + ([CVE-2016-6306]) + + *Stephen Henson* + +### Changes between 1.0.1s and 1.0.1t [3 May 2016] + + * Prevent padding oracle in AES-NI CBC MAC check + + A MITM attacker can use a padding oracle attack to decrypt traffic + when the connection uses an AES CBC cipher and the server support + AES-NI. + + This issue was introduced as part of the fix for Lucky 13 padding + attack ([CVE-2013-0169]). The padding check was rewritten to be in + constant time by making sure that always the same bytes are read and + compared against either the MAC or padding bytes. But it no longer + checked that there was enough data to have both the MAC and padding + bytes. + + This issue was reported by Juraj Somorovsky using TLS-Attacker. + ([CVE-2016-2107]) + + *Kurt Roeckx* + + * Fix EVP_EncodeUpdate overflow + + An overflow can occur in the EVP_EncodeUpdate() function which is used for + Base64 encoding of binary data. If an attacker is able to supply very large + amounts of input data then a length check can overflow resulting in a heap + corruption. + + Internally to OpenSSL the EVP_EncodeUpdate() function is primarly used by + the `PEM_write_bio*` family of functions. These are mainly used within the + OpenSSL command line applications, so any application which processes data + from an untrusted source and outputs it as a PEM file should be considered + vulnerable to this issue. User applications that call these APIs directly + with large amounts of untrusted data may also be vulnerable. + + This issue was reported by Guido Vranken. + ([CVE-2016-2105]) + + *Matt Caswell* + + * Fix EVP_EncryptUpdate overflow + + An overflow can occur in the EVP_EncryptUpdate() function. If an attacker + is able to supply very large amounts of input data after a previous call to + EVP_EncryptUpdate() with a partial block then a length check can overflow + resulting in a heap corruption. Following an analysis of all OpenSSL + internal usage of the EVP_EncryptUpdate() function all usage is one of two + forms. The first form is where the EVP_EncryptUpdate() call is known to be + the first called function after an EVP_EncryptInit(), and therefore that + specific call must be safe. The second form is where the length passed to + EVP_EncryptUpdate() can be seen from the code to be some small value and + therefore there is no possibility of an overflow. Since all instances are + one of these two forms, it is believed that there can be no overflows in + internal code due to this problem. It should be noted that + EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths. + Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances + of these calls have also been analysed too and it is believed there are no + instances in internal usage where an overflow could occur. + + This issue was reported by Guido Vranken. + ([CVE-2016-2106]) + + *Matt Caswell* + + * Prevent ASN.1 BIO excessive memory allocation + + When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio() + a short invalid encoding can casuse allocation of large amounts of memory + potentially consuming excessive resources or exhausting memory. + + Any application parsing untrusted data through d2i BIO functions is + affected. The memory based functions such as d2i_X509() are *not* affected. + Since the memory based functions are used by the TLS library, TLS + applications are not affected. + + This issue was reported by Brian Carpenter. + ([CVE-2016-2109]) + + *Stephen Henson* + + * EBCDIC overread + + ASN1 Strings that are over 1024 bytes can cause an overread in applications + using the X509_NAME_oneline() function on EBCDIC systems. This could result + in arbitrary stack data being returned in the buffer. + + This issue was reported by Guido Vranken. + ([CVE-2016-2176]) + + *Matt Caswell* + + * Modify behavior of ALPN to invoke callback after SNI/servername + callback, such that updates to the SSL_CTX affect ALPN. + + *Todd Short* + + * Remove LOW from the DEFAULT cipher list. This removes singles DES from the + default. + + *Kurt Roeckx* + + * Only remove the SSLv2 methods with the no-ssl2-method option. When the + methods are enabled and ssl2 is disabled the methods return NULL. + + *Kurt Roeckx* + +### Changes between 1.0.1r and 1.0.1s [1 Mar 2016] + +* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL. + Builds that are not configured with "enable-weak-ssl-ciphers" will not + provide any "EXPORT" or "LOW" strength ciphers. + + *Viktor Dukhovni* + +* Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2 + is by default disabled at build-time. Builds that are not configured with + "enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used, + users who want to negotiate SSLv2 via the version-flexible SSLv23_method() + will need to explicitly call either of: + + SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2); + or + SSL_clear_options(ssl, SSL_OP_NO_SSLv2); + + as appropriate. Even if either of those is used, or the application + explicitly uses the version-specific SSLv2_method() or its client and + server variants, SSLv2 ciphers vulnerable to exhaustive search key + recovery have been removed. Specifically, the SSLv2 40-bit EXPORT + ciphers, and SSLv2 56-bit DES are no longer available. + ([CVE-2016-0800]) + + *Viktor Dukhovni* + + * Fix a double-free in DSA code + + A double free bug was discovered when OpenSSL parses malformed DSA private + keys and could lead to a DoS attack or memory corruption for applications + that receive DSA private keys from untrusted sources. This scenario is + considered rare. + + This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using + libFuzzer. + ([CVE-2016-0705]) + + *Stephen Henson* + + * Disable SRP fake user seed to address a server memory leak. + + Add a new method SRP_VBASE_get1_by_user that handles the seed properly. + + SRP_VBASE_get_by_user had inconsistent memory management behaviour. + In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user + was changed to ignore the "fake user" SRP seed, even if the seed + is configured. + + Users should use SRP_VBASE_get1_by_user instead. Note that in + SRP_VBASE_get1_by_user, caller must free the returned value. Note + also that even though configuring the SRP seed attempts to hide + invalid usernames by continuing the handshake with fake + credentials, this behaviour is not constant time and no strong + guarantees are made that the handshake is indistinguishable from + that of a valid user. + ([CVE-2016-0798]) + + *Emilia Käsper* + + * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption + + In the BN_hex2bn function the number of hex digits is calculated using an + int value `i`. Later `bn_expand` is called with a value of `i * 4`. For + large values of `i` this can result in `bn_expand` not allocating any + memory because `i * 4` is negative. This can leave the internal BIGNUM data + field as NULL leading to a subsequent NULL ptr deref. For very large values + of `i`, the calculation `i * 4` could be a positive value smaller than `i`. + In this case memory is allocated to the internal BIGNUM data field, but it + is insufficiently sized leading to heap corruption. A similar issue exists + in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn + is ever called by user applications with very large untrusted hex/dec data. + This is anticipated to be a rare occurrence. + + All OpenSSL internal usage of these functions use data that is not expected + to be untrusted, e.g. config file data or application command line + arguments. If user developed applications generate config file data based + on untrusted data then it is possible that this could also lead to security + consequences. This is also anticipated to be rare. + + This issue was reported to OpenSSL by Guido Vranken. + ([CVE-2016-0797]) + + *Matt Caswell* + + * Fix memory issues in `BIO_*printf` functions + + The internal `fmtstr` function used in processing a "%s" format string in + the `BIO_*printf` functions could overflow while calculating the length of a + string and cause an OOB read when printing very long strings. + + Additionally the internal `doapr_outch` function can attempt to write to an + OOB memory location (at an offset from the NULL pointer) in the event of a + memory allocation failure. In 1.0.2 and below this could be caused where + the size of a buffer to be allocated is greater than INT_MAX. E.g. this + could be in processing a very long "%s" format string. Memory leaks can + also occur. + + The first issue may mask the second issue dependent on compiler behaviour. + These problems could enable attacks where large amounts of untrusted data + is passed to the `BIO_*printf` functions. If applications use these functions + in this way then they could be vulnerable. OpenSSL itself uses these + functions when printing out human-readable dumps of ASN.1 data. Therefore + applications that print this data could be vulnerable if the data is from + untrusted sources. OpenSSL command line applications could also be + vulnerable where they print out ASN.1 data, or if untrusted data is passed + as command line arguments. + + Libssl is not considered directly vulnerable. Additionally certificates etc + received via remote connections via libssl are also unlikely to be able to + trigger these issues because of message size limits enforced within libssl. + + This issue was reported to OpenSSL Guido Vranken. + ([CVE-2016-0799]) + + *Matt Caswell* + + * Side channel attack on modular exponentiation + + A side-channel attack was found which makes use of cache-bank conflicts on + the Intel Sandy-Bridge microarchitecture which could lead to the recovery + of RSA keys. The ability to exploit this issue is limited as it relies on + an attacker who has control of code in a thread running on the same + hyper-threaded core as the victim thread which is performing decryptions. + + This issue was reported to OpenSSL by Yuval Yarom, The University of + Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and + Nadia Heninger, University of Pennsylvania with more information at + . + ([CVE-2016-0702]) + + *Andy Polyakov* + + * Change the req command to generate a 2048-bit RSA/DSA key by default, + if no keysize is specified with default_bits. This fixes an + omission in an earlier change that changed all RSA/DSA key generation + commands to use 2048 bits by default. + + *Emilia Käsper* + +### Changes between 1.0.1q and 1.0.1r [28 Jan 2016] + + * Protection for DH small subgroup attacks + + As a precautionary measure the SSL_OP_SINGLE_DH_USE option has been + switched on by default and cannot be disabled. This could have some + performance impact. + + *Matt Caswell* + + * SSLv2 doesn't block disabled ciphers + + A malicious client can negotiate SSLv2 ciphers that have been disabled on + the server and complete SSLv2 handshakes even if all SSLv2 ciphers have + been disabled, provided that the SSLv2 protocol was not also disabled via + SSL_OP_NO_SSLv2. + + This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram + and Sebastian Schinzel. + ([CVE-2015-3197]) + + *Viktor Dukhovni* + + * Reject DH handshakes with parameters shorter than 1024 bits. + + *Kurt Roeckx* + +### Changes between 1.0.1p and 1.0.1q [3 Dec 2015] + + * Certificate verify crash with missing PSS parameter + + The signature verification routines will crash with a NULL pointer + dereference if presented with an ASN.1 signature using the RSA PSS + algorithm and absent mask generation function parameter. Since these + routines are used to verify certificate signature algorithms this can be + used to crash any certificate verification operation and exploited in a + DoS attack. Any application which performs certificate verification is + vulnerable including OpenSSL clients and servers which enable client + authentication. + + This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG). + ([CVE-2015-3194]) + + *Stephen Henson* + + * X509_ATTRIBUTE memory leak + + When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak + memory. This structure is used by the PKCS#7 and CMS routines so any + application which reads PKCS#7 or CMS data from untrusted sources is + affected. SSL/TLS is not affected. + + This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using + libFuzzer. + ([CVE-2015-3195]) + + *Stephen Henson* + + * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs. + This changes the decoding behaviour for some invalid messages, + though the change is mostly in the more lenient direction, and + legacy behaviour is preserved as much as possible. + + *Emilia Käsper* + + * In DSA_generate_parameters_ex, if the provided seed is too short, + use a random seed, as already documented. + + *Rich Salz and Ismo Puustinen * + +### Changes between 1.0.1o and 1.0.1p [9 Jul 2015] + + * Alternate chains certificate forgery + + During certificate verfification, OpenSSL will attempt to find an + alternative certificate chain if the first attempt to build such a chain + fails. An error in the implementation of this logic can mean that an + attacker could cause certain checks on untrusted certificates to be + bypassed, such as the CA flag, enabling them to use a valid leaf + certificate to act as a CA and "issue" an invalid certificate. + + This issue was reported to OpenSSL by Adam Langley/David Benjamin + (Google/BoringSSL). + ([CVE-2015-1793]) + + *Matt Caswell* + + * Race condition handling PSK identify hint + + If PSK identity hints are received by a multi-threaded client then + the values are wrongly updated in the parent SSL_CTX structure. This can + result in a race condition potentially leading to a double free of the + identify hint data. + ([CVE-2015-3196]) + + *Stephen Henson* + +### Changes between 1.0.1n and 1.0.1o [12 Jun 2015] + + * Fix HMAC ABI incompatibility. The previous version introduced an ABI + incompatibility in the handling of HMAC. The previous ABI has now been + restored. + +### Changes between 1.0.1m and 1.0.1n [11 Jun 2015] + + * Malformed ECParameters causes infinite loop + + When processing an ECParameters structure OpenSSL enters an infinite loop + if the curve specified is over a specially malformed binary polynomial + field. + + This can be used to perform denial of service against any + system which processes public keys, certificate requests or + certificates. This includes TLS clients and TLS servers with + client authentication enabled. + + This issue was reported to OpenSSL by Joseph Barr-Pixton. + ([CVE-2015-1788]) + + *Andy Polyakov* + + * Exploitable out-of-bounds read in X509_cmp_time + + X509_cmp_time does not properly check the length of the ASN1_TIME + string and can read a few bytes out of bounds. In addition, + X509_cmp_time accepts an arbitrary number of fractional seconds in the + time string. + + An attacker can use this to craft malformed certificates and CRLs of + various sizes and potentially cause a segmentation fault, resulting in + a DoS on applications that verify certificates or CRLs. TLS clients + that verify CRLs are affected. TLS clients and servers with client + authentication enabled may be affected if they use custom verification + callbacks. + + This issue was reported to OpenSSL by Robert Swiecki (Google), and + independently by Hanno Böck. + ([CVE-2015-1789]) + + *Emilia Käsper* + + * PKCS7 crash with missing EnvelopedContent + + The PKCS#7 parsing code does not handle missing inner EncryptedContent + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs + with missing content and trigger a NULL pointer dereference on parsing. + + Applications that decrypt PKCS#7 data or otherwise parse PKCS#7 + structures from untrusted sources are affected. OpenSSL clients and + servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + ([CVE-2015-1790]) + + *Emilia Käsper* + + * CMS verify infinite loop with unknown hash function + + When verifying a signedData message the CMS code can enter an infinite loop + if presented with an unknown hash function OID. This can be used to perform + denial of service against any system which verifies signedData messages using + the CMS code. + This issue was reported to OpenSSL by Johannes Bauer. + ([CVE-2015-1792]) + + *Stephen Henson* + + * Race condition handling NewSessionTicket + + If a NewSessionTicket is received by a multi-threaded client when attempting to + reuse a previous ticket then a race condition can occur potentially leading to + a double free of the ticket data. + ([CVE-2015-1791]) + + *Matt Caswell* + + * Reject DH handshakes with parameters shorter than 768 bits. + + *Kurt Roeckx and Emilia Kasper* + + * dhparam: generate 2048-bit parameters by default. + + *Kurt Roeckx and Emilia Kasper* + +### Changes between 1.0.1l and 1.0.1m [19 Mar 2015] + + * Segmentation fault in ASN1_TYPE_cmp fix + + The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is + made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check + certificate signature algorithm consistency this can be used to crash any + certificate verification operation and exploited in a DoS attack. Any + application which performs certificate verification is vulnerable including + OpenSSL clients and servers which enable client authentication. + ([CVE-2015-0286]) + + *Stephen Henson* + + * ASN.1 structure reuse memory corruption fix + + Reusing a structure in ASN.1 parsing may allow an attacker to cause + memory corruption via an invalid write. Such reuse is and has been + strongly discouraged and is believed to be rare. + + Applications that parse structures containing CHOICE or ANY DEFINED BY + components may be affected. Certificate parsing (d2i_X509 and related + functions) are however not affected. OpenSSL clients and servers are + not affected. + ([CVE-2015-0287]) + + *Stephen Henson* + + * PKCS7 NULL pointer dereferences fix + + The PKCS#7 parsing code does not handle missing outer ContentInfo + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with + missing content and trigger a NULL pointer dereference on parsing. + + Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or + otherwise parse PKCS#7 structures from untrusted sources are + affected. OpenSSL clients and servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + ([CVE-2015-0289]) + + *Emilia Käsper* + + * DoS via reachable assert in SSLv2 servers fix + + A malicious client can trigger an OPENSSL_assert (i.e., an abort) in + servers that both support SSLv2 and enable export cipher suites by sending + a specially crafted SSLv2 CLIENT-MASTER-KEY message. + + This issue was discovered by Sean Burford (Google) and Emilia Käsper + (OpenSSL development team). + ([CVE-2015-0293]) + + *Emilia Käsper* + + * Use After Free following d2i_ECPrivatekey error fix + + A malformed EC private key file consumed via the d2i_ECPrivateKey function + could cause a use after free condition. This, in turn, could cause a double + free in several private key parsing functions (such as d2i_PrivateKey + or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption + for applications that receive EC private keys from untrusted + sources. This scenario is considered rare. + + This issue was discovered by the BoringSSL project and fixed in their + commit 517073cd4b. + ([CVE-2015-0209]) + + *Matt Caswell* + + * X509_to_X509_REQ NULL pointer deref fix + + The function X509_to_X509_REQ will crash with a NULL pointer dereference if + the certificate key is invalid. This function is rarely used in practice. + + This issue was discovered by Brian Carpenter. + ([CVE-2015-0288]) + + *Stephen Henson* + + * Removed the export ciphers from the DEFAULT ciphers + + *Kurt Roeckx* + +### Changes between 1.0.1k and 1.0.1l [15 Jan 2015] + + * Build fixes for the Windows and OpenVMS platforms + + *Matt Caswell and Richard Levitte* + +### Changes between 1.0.1j and 1.0.1k [8 Jan 2015] + + * Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS + message can cause a segmentation fault in OpenSSL due to a NULL pointer + dereference. This could lead to a Denial Of Service attack. Thanks to + Markus Stenberg of Cisco Systems, Inc. for reporting this issue. + ([CVE-2014-3571]) + + *Steve Henson* + + * Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the + dtls1_buffer_record function under certain conditions. In particular this + could occur if an attacker sent repeated DTLS records with the same + sequence number but for the next epoch. The memory leak could be exploited + by an attacker in a Denial of Service attack through memory exhaustion. + Thanks to Chris Mueller for reporting this issue. + ([CVE-2015-0206]) + + *Matt Caswell* + + * Fix issue where no-ssl3 configuration sets method to NULL. When openssl is + built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl + method would be set to NULL which could later result in a NULL pointer + dereference. Thanks to Frank Schmirler for reporting this issue. + ([CVE-2014-3569]) + + *Kurt Roeckx* + + * Abort handshake if server key exchange message is omitted for ephemeral + ECDH ciphersuites. + + Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for + reporting this issue. + ([CVE-2014-3572]) + + *Steve Henson* + + * Remove non-export ephemeral RSA code on client and server. This code + violated the TLS standard by allowing the use of temporary RSA keys in + non-export ciphersuites and could be used by a server to effectively + downgrade the RSA key length used to a value smaller than the server + certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at + INRIA or reporting this issue. + ([CVE-2015-0204]) + + *Steve Henson* + + * Fixed issue where DH client certificates are accepted without verification. + An OpenSSL server will accept a DH certificate for client authentication + without the certificate verify message. This effectively allows a client to + authenticate without the use of a private key. This only affects servers + which trust a client certificate authority which issues certificates + containing DH keys: these are extremely rare and hardly ever encountered. + Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting + this issue. + ([CVE-2015-0205]) + + *Steve Henson* + + * Ensure that the session ID context of an SSL is updated when its + SSL_CTX is updated via SSL_set_SSL_CTX. + + The session ID context is typically set from the parent SSL_CTX, + and can vary with the CTX. + + *Adam Langley* + + * Fix various certificate fingerprint issues. + + By using non-DER or invalid encodings outside the signed portion of a + certificate the fingerprint can be changed without breaking the signature. + Although no details of the signed portion of the certificate can be changed + this can cause problems with some applications: e.g. those using the + certificate fingerprint for blacklists. + + 1. Reject signatures with non zero unused bits. + + If the BIT STRING containing the signature has non zero unused bits reject + the signature. All current signature algorithms require zero unused bits. + + 2. Check certificate algorithm consistency. + + Check the AlgorithmIdentifier inside TBS matches the one in the + certificate signature. NB: this will result in signature failure + errors for some broken certificates. + + Thanks to Konrad Kraszewski from Google for reporting this issue. + + 3. Check DSA/ECDSA signatures use DER. + + Re-encode DSA/ECDSA signatures and compare with the original received + signature. Return an error if there is a mismatch. + + This will reject various cases including garbage after signature + (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS + program for discovering this case) and use of BER or invalid ASN.1 INTEGERs + (negative or with leading zeroes). + + Further analysis was conducted and fixes were developed by Stephen Henson + of the OpenSSL core team. + + ([CVE-2014-8275]) + + *Steve Henson* + + * Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect + results on some platforms, including x86_64. This bug occurs at random + with a very low probability, and is not known to be exploitable in any + way, though its exact impact is difficult to determine. Thanks to Pieter + Wuille (Blockstream) who reported this issue and also suggested an initial + fix. Further analysis was conducted by the OpenSSL development team and + Adam Langley of Google. The final fix was developed by Andy Polyakov of + the OpenSSL core team. + ([CVE-2014-3570]) + + *Andy Polyakov* + + * Do not resume sessions on the server if the negotiated protocol + version does not match the session's version. Resuming with a different + version, while not strictly forbidden by the RFC, is of questionable + sanity and breaks all known clients. + + *David Benjamin, Emilia Käsper* + + * Tighten handling of the ChangeCipherSpec (CCS) message: reject + early CCS messages during renegotiation. (Note that because + renegotiation is encrypted, this early CCS was not exploitable.) + + *Emilia Käsper* + + * Tighten client-side session ticket handling during renegotiation: + ensure that the client only accepts a session ticket if the server sends + the extension anew in the ServerHello. Previously, a TLS client would + reuse the old extension state and thus accept a session ticket if one was + announced in the initial ServerHello. + + Similarly, ensure that the client requires a session ticket if one + was advertised in the ServerHello. Previously, a TLS client would + ignore a missing NewSessionTicket message. + + *Emilia Käsper* + +### Changes between 1.0.1i and 1.0.1j [15 Oct 2014] + + * SRTP Memory Leak. + + A flaw in the DTLS SRTP extension parsing code allows an attacker, who + sends a carefully crafted handshake message, to cause OpenSSL to fail + to free up to 64k of memory causing a memory leak. This could be + exploited in a Denial Of Service attack. This issue affects OpenSSL + 1.0.1 server implementations for both SSL/TLS and DTLS regardless of + whether SRTP is used or configured. Implementations of OpenSSL that + have been compiled with OPENSSL_NO_SRTP defined are not affected. + + The fix was developed by the OpenSSL team. + ([CVE-2014-3513]) + + *OpenSSL team* + + * Session Ticket Memory Leak. + + When an OpenSSL SSL/TLS/DTLS server receives a session ticket the + integrity of that ticket is first verified. In the event of a session + ticket integrity check failing, OpenSSL will fail to free memory + causing a memory leak. By sending a large number of invalid session + tickets an attacker could exploit this issue in a Denial Of Service + attack. + ([CVE-2014-3567]) + + *Steve Henson* + + * Build option no-ssl3 is incomplete. + + When OpenSSL is configured with "no-ssl3" as a build option, servers + could accept and complete a SSL 3.0 handshake, and clients could be + configured to send them. + ([CVE-2014-3568]) + + *Akamai and the OpenSSL team* + + * Add support for TLS_FALLBACK_SCSV. + Client applications doing fallback retries should call + SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV). + ([CVE-2014-3566]) + + *Adam Langley, Bodo Moeller* + + * Add additional DigestInfo checks. + + Re-encode DigestInto in DER and check against the original when + verifying RSA signature: this will reject any improperly encoded + DigestInfo structures. + + Note: this is a precautionary measure and no attacks are currently known. + + *Steve Henson* + +### Changes between 1.0.1h and 1.0.1i [6 Aug 2014] + + * Fix SRP buffer overrun vulnerability. Invalid parameters passed to the + SRP code can be overrun an internal buffer. Add sanity check that + g, A, B < N to SRP code. + + Thanks to Sean Devlin and Watson Ladd of Cryptography Services, NCC + Group for discovering this issue. + ([CVE-2014-3512]) + + *Steve Henson* + + * A flaw in the OpenSSL SSL/TLS server code causes the server to negotiate + TLS 1.0 instead of higher protocol versions when the ClientHello message + is badly fragmented. This allows a man-in-the-middle attacker to force a + downgrade to TLS 1.0 even if both the server and the client support a + higher protocol version, by modifying the client's TLS records. + + Thanks to David Benjamin and Adam Langley (Google) for discovering and + researching this issue. + ([CVE-2014-3511]) + + *David Benjamin* + + * OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject + to a denial of service attack. A malicious server can crash the client + with a null pointer dereference (read) by specifying an anonymous (EC)DH + ciphersuite and sending carefully crafted handshake messages. + + Thanks to Felix Gröbert (Google) for discovering and researching this + issue. + ([CVE-2014-3510]) + + *Emilia Käsper* + + * By sending carefully crafted DTLS packets an attacker could cause openssl + to leak memory. This can be exploited through a Denial of Service attack. + Thanks to Adam Langley for discovering and researching this issue. + ([CVE-2014-3507]) + + *Adam Langley* + + * An attacker can force openssl to consume large amounts of memory whilst + processing DTLS handshake messages. This can be exploited through a + Denial of Service attack. + Thanks to Adam Langley for discovering and researching this issue. + ([CVE-2014-3506]) + + *Adam Langley* + + * An attacker can force an error condition which causes openssl to crash + whilst processing DTLS packets due to memory being freed twice. This + can be exploited through a Denial of Service attack. + Thanks to Adam Langley and Wan-Teh Chang for discovering and researching + this issue. + ([CVE-2014-3505]) + + *Adam Langley* + + * If a multithreaded client connects to a malicious server using a resumed + session and the server sends an ec point format extension it could write + up to 255 bytes to freed memory. + + Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this + issue. + ([CVE-2014-3509]) + + *Gabor Tyukasz* + + * A malicious server can crash an OpenSSL client with a null pointer + dereference (read) by specifying an SRP ciphersuite even though it was not + properly negotiated with the client. This can be exploited through a + Denial of Service attack. + + Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for + discovering and researching this issue. + ([CVE-2014-5139]) + + *Steve Henson* + + * A flaw in OBJ_obj2txt may cause pretty printing functions such as + X509_name_oneline, X509_name_print_ex et al. to leak some information + from the stack. Applications may be affected if they echo pretty printing + output to the attacker. + + Thanks to Ivan Fratric (Google) for discovering this issue. + ([CVE-2014-3508]) + + *Emilia Käsper, and Steve Henson* + + * Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.) + for corner cases. (Certain input points at infinity could lead to + bogus results, with non-infinity inputs mapped to infinity too.) + + *Bodo Moeller* + +### Changes between 1.0.1g and 1.0.1h [5 Jun 2014] + + * Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted + handshake can force the use of weak keying material in OpenSSL + SSL/TLS clients and servers. + + Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and + researching this issue. ([CVE-2014-0224]) + + *KIKUCHI Masashi, Steve Henson* + + * Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an + OpenSSL DTLS client the code can be made to recurse eventually crashing + in a DoS attack. + + Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue. + ([CVE-2014-0221]) + + *Imre Rad, Steve Henson* + + * Fix DTLS invalid fragment vulnerability. A buffer overrun attack can + be triggered by sending invalid DTLS fragments to an OpenSSL DTLS + client or server. This is potentially exploitable to run arbitrary + code on a vulnerable client or server. + + Thanks to Jüri Aedla for reporting this issue. ([CVE-2014-0195]) + + *Jüri Aedla, Steve Henson* + + * Fix bug in TLS code where clients enable anonymous ECDH ciphersuites + are subject to a denial of service attack. + + Thanks to Felix Gröbert and Ivan Fratric at Google for discovering + this issue. ([CVE-2014-3470]) + + *Felix Gröbert, Ivan Fratric, Steve Henson* + + * Harmonize version and its documentation. -f flag is used to display + compilation flags. + + *mancha * + + * Fix eckey_priv_encode so it immediately returns an error upon a failure + in i2d_ECPrivateKey. + + *mancha * + + * Fix some double frees. These are not thought to be exploitable. + + *mancha * + +### Changes between 1.0.1f and 1.0.1g [7 Apr 2014] + + * A missing bounds check in the handling of the TLS heartbeat extension + can be used to reveal up to 64k of memory to a connected client or + server. + + Thanks for Neel Mehta of Google Security for discovering this bug and to + Adam Langley and Bodo Moeller for + preparing the fix ([CVE-2014-0160]) + + *Adam Langley, Bodo Moeller* + + * Fix for the attack described in the paper "Recovering OpenSSL + ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack" + by Yuval Yarom and Naomi Benger. Details can be obtained from: + + + Thanks to Yuval Yarom and Naomi Benger for discovering this + flaw and to Yuval Yarom for supplying a fix ([CVE-2014-0076]) + + *Yuval Yarom and Naomi Benger* + + * TLS pad extension: draft-agl-tls-padding-03 + + Workaround for the "TLS hang bug" (see FAQ and PR#2771): if the + TLS client Hello record length value would otherwise be > 255 and + less that 512 pad with a dummy extension containing zeroes so it + is at least 512 bytes long. + + *Adam Langley, Steve Henson* + +### Changes between 1.0.1e and 1.0.1f [6 Jan 2014] + + * Fix for TLS record tampering bug. A carefully crafted invalid + handshake could crash OpenSSL with a NULL pointer exception. + Thanks to Anton Johansson for reporting this issues. + ([CVE-2013-4353]) + + * Keep original DTLS digest and encryption contexts in retransmission + structures so we can use the previous session parameters if they need + to be resent. ([CVE-2013-6450]) + + *Steve Henson* + + * Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which + avoids preferring ECDHE-ECDSA ciphers when the client appears to be + Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for + several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug + is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing + 10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer. + + *Rob Stradling, Adam Langley* + +### Changes between 1.0.1d and 1.0.1e [11 Feb 2013] + + * Correct fix for CVE-2013-0169. The original didn't work on AES-NI + supporting platforms or when small records were transferred. + + *Andy Polyakov, Steve Henson* + +### Changes between 1.0.1c and 1.0.1d [5 Feb 2013] + + * Make the decoding of SSLv3, TLS and DTLS CBC records constant time. + + This addresses the flaw in CBC record processing discovered by + Nadhem Alfardan and Kenny Paterson. Details of this attack can be found + at: + + Thanks go to Nadhem Alfardan and Kenny Paterson of the Information + Security Group at Royal Holloway, University of London + (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and + Emilia Käsper for the initial patch. + ([CVE-2013-0169]) + + *Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson* + + * Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode + ciphersuites which can be exploited in a denial of service attack. + Thanks go to and to Adam Langley for discovering + and detecting this bug and to Wolfgang Ettlinger + for independently discovering this issue. + ([CVE-2012-2686]) + + *Adam Langley* + + * Return an error when checking OCSP signatures when key is NULL. + This fixes a DoS attack. ([CVE-2013-0166]) + + *Steve Henson* + + * Make openssl verify return errors. + + *Chris Palmer and Ben Laurie* + + * Call OCSP Stapling callback after ciphersuite has been chosen, so + the right response is stapled. Also change SSL_get_certificate() + so it returns the certificate actually sent. + See . + + *Rob Stradling * + + * Fix possible deadlock when decoding public keys. + + *Steve Henson* + + * Don't use TLS 1.0 record version number in initial client hello + if renegotiating. + + *Steve Henson* + +### Changes between 1.0.1b and 1.0.1c [10 May 2012] + + * Sanity check record length before skipping explicit IV in TLS + 1.2, 1.1 and DTLS to fix DoS attack. + + Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic + fuzzing as a service testing platform. + ([CVE-2012-2333]) + + *Steve Henson* + + * Initialise tkeylen properly when encrypting CMS messages. + Thanks to Solar Designer of Openwall for reporting this issue. + + *Steve Henson* + + * In FIPS mode don't try to use composite ciphers as they are not + approved. + + *Steve Henson* + +### Changes between 1.0.1a and 1.0.1b [26 Apr 2012] + + * OpenSSL 1.0.0 sets SSL_OP_ALL to 0x80000FFFL and OpenSSL 1.0.1 and + 1.0.1a set SSL_OP_NO_TLSv1_1 to 0x00000400L which would unfortunately + mean any application compiled against OpenSSL 1.0.0 headers setting + SSL_OP_ALL would also set SSL_OP_NO_TLSv1_1, unintentionally disabling + TLS 1.1 also. Fix this by changing the value of SSL_OP_NO_TLSv1_1 to + 0x10000000L Any application which was previously compiled against + OpenSSL 1.0.1 or 1.0.1a headers and which cares about SSL_OP_NO_TLSv1_1 + will need to be recompiled as a result. Letting be results in + inability to disable specifically TLS 1.1 and in client context, + in unlike event, limit maximum offered version to TLS 1.0 [see below]. + + *Steve Henson* + + * In order to ensure interoperability SSL_OP_NO_protocolX does not + disable just protocol X, but all protocols above X *if* there are + protocols *below* X still enabled. In more practical terms it means + that if application wants to disable TLS1.0 in favor of TLS1.1 and + above, it's not sufficient to pass `SSL_OP_NO_TLSv1`, one has to pass + `SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2`. This applies to + client side. + + *Andy Polyakov* + +### Changes between 1.0.1 and 1.0.1a [19 Apr 2012] + + * Check for potentially exploitable overflows in asn1_d2i_read_bio + BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer + in CRYPTO_realloc_clean. + + Thanks to Tavis Ormandy, Google Security Team, for discovering this + issue and to Adam Langley for fixing it. + ([CVE-2012-2110]) + + *Adam Langley (Google), Tavis Ormandy, Google Security Team* + + * Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections. + + *Adam Langley* + + * Workarounds for some broken servers that "hang" if a client hello + record length exceeds 255 bytes. + + 1. Do not use record version number > TLS 1.0 in initial client + hello: some (but not all) hanging servers will now work. + 2. If we set OPENSSL_MAX_TLS1_2_CIPHER_LENGTH this will truncate + the number of ciphers sent in the client hello. This should be + set to an even number, such as 50, for example by passing: + -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 to config or Configure. + Most broken servers should now work. + 3. If all else fails setting OPENSSL_NO_TLS1_2_CLIENT will disable + TLS 1.2 client support entirely. + + *Steve Henson* + + * Fix SEGV in Vector Permutation AES module observed in OpenSSH. + + *Andy Polyakov* + +### Changes between 1.0.0h and 1.0.1 [14 Mar 2012] + + * Add compatibility with old MDC2 signatures which use an ASN1 OCTET + STRING form instead of a DigestInfo. + + *Steve Henson* + + * The format used for MDC2 RSA signatures is inconsistent between EVP + and the RSA_sign/RSA_verify functions. This was made more apparent when + OpenSSL used RSA_sign/RSA_verify for some RSA signatures in particular + those which went through EVP_PKEY_METHOD in 1.0.0 and later. Detect + the correct format in RSA_verify so both forms transparently work. + + *Steve Henson* + + * Some servers which support TLS 1.0 can choke if we initially indicate + support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA + encrypted premaster secret. As a workaround use the maximum permitted + client version in client hello, this should keep such servers happy + and still work with previous versions of OpenSSL. + + *Steve Henson* + + * Add support for TLS/DTLS heartbeats. + + *Robin Seggelmann * + + * Add support for SCTP. + + *Robin Seggelmann * + + * Improved PRNG seeding for VOS. + + *Paul Green * + + * Extensive assembler packs updates, most notably: + + - x86[_64]: AES-NI, PCLMULQDQ, RDRAND support; + - x86[_64]: SSSE3 support (SHA1, vector-permutation AES); + - x86_64: bit-sliced AES implementation; + - ARM: NEON support, contemporary platforms optimizations; + - s390x: z196 support; + - `*`: GHASH and GF(2^m) multiplication implementations; + + *Andy Polyakov* + + * Make TLS-SRP code conformant with RFC 5054 API cleanup + (removal of unnecessary code) + + *Peter Sylvester * + + * Add TLS key material exporter from RFC 5705. + + *Eric Rescorla* + + * Add DTLS-SRTP negotiation from RFC 5764. + + *Eric Rescorla* + + * Add Next Protocol Negotiation, + . Can be + disabled with a no-npn flag to config or Configure. Code donated + by Google. + + *Adam Langley and Ben Laurie* + + * Add optional 64-bit optimized implementations of elliptic curves NIST-P224, + NIST-P256, NIST-P521, with constant-time single point multiplication on + typical inputs. Compiler support for the nonstandard type `__uint128_t` is + required to use this (present in gcc 4.4 and later, for 64-bit builds). + Code made available under Apache License version 2.0. + + Specify "enable-ec_nistp_64_gcc_128" on the Configure (or config) command + line to include this in your build of OpenSSL, and run "make depend" (or + "make update"). This enables the following EC_METHODs: + + EC_GFp_nistp224_method() + EC_GFp_nistp256_method() + EC_GFp_nistp521_method() + + EC_GROUP_new_by_curve_name() will automatically use these (while + EC_GROUP_new_curve_GFp() currently prefers the more flexible + implementations). + + *Emilia Käsper, Adam Langley, Bodo Moeller (Google)* + + * Use type ossl_ssize_t instead of ssize_t which isn't available on + all platforms. Move ssize_t definition from e_os.h to the public + header file e_os2.h as it now appears in public header file cms.h + + *Steve Henson* + + * New -sigopt option to the ca, req and x509 utilities. Additional + signature parameters can be passed using this option and in + particular PSS. + + *Steve Henson* + + * Add RSA PSS signing function. This will generate and set the + appropriate AlgorithmIdentifiers for PSS based on those in the + corresponding EVP_MD_CTX structure. No application support yet. + + *Steve Henson* + + * Support for companion algorithm specific ASN1 signing routines. + New function ASN1_item_sign_ctx() signs a pre-initialised + EVP_MD_CTX structure and sets AlgorithmIdentifiers based on + the appropriate parameters. + + *Steve Henson* + + * Add new algorithm specific ASN1 verification initialisation function + to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1 + handling will be the same no matter what EVP_PKEY_METHOD is used. + Add a PSS handler to support verification of PSS signatures: checked + against a number of sample certificates. + + *Steve Henson* + + * Add signature printing for PSS. Add PSS OIDs. + + *Steve Henson, Martin Kaiser * + + * Add algorithm specific signature printing. An individual ASN1 method + can now print out signatures instead of the standard hex dump. + + More complex signatures (e.g. PSS) can print out more meaningful + information. Include DSA version that prints out the signature + parameters r, s. + + *Steve Henson* + + * Password based recipient info support for CMS library: implementing + RFC3211. + + *Steve Henson* + + * Split password based encryption into PBES2 and PBKDF2 functions. This + neatly separates the code into cipher and PBE sections and is required + for some algorithms that split PBES2 into separate pieces (such as + password based CMS). + + *Steve Henson* + + * Session-handling fixes: + - Fix handling of connections that are resuming with a session ID, + but also support Session Tickets. + - Fix a bug that suppressed issuing of a new ticket if the client + presented a ticket with an expired session. + - Try to set the ticket lifetime hint to something reasonable. + - Make tickets shorter by excluding irrelevant information. + - On the client side, don't ignore renewed tickets. + + *Adam Langley, Bodo Moeller (Google)* + + * Fix PSK session representation. + + *Bodo Moeller* + + * Add RC4-MD5 and AESNI-SHA1 "stitched" implementations. + + This work was sponsored by Intel. + + *Andy Polyakov* + + * Add GCM support to TLS library. Some custom code is needed to split + the IV between the fixed (from PRF) and explicit (from TLS record) + portions. This adds all GCM ciphersuites supported by RFC5288 and + RFC5289. Generalise some `AES*` cipherstrings to include GCM and + add a special AESGCM string for GCM only. + + *Steve Henson* + + * Expand range of ctrls for AES GCM. Permit setting invocation + field on decrypt and retrieval of invocation field only on encrypt. + + *Steve Henson* + + * Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support. + As required by RFC5289 these ciphersuites cannot be used if for + versions of TLS earlier than 1.2. + + *Steve Henson* + + * For FIPS capable OpenSSL interpret a NULL default public key method + as unset and return the appropriate default but do *not* set the default. + This means we can return the appropriate method in applications that + switch between FIPS and non-FIPS modes. + + *Steve Henson* + + * Redirect HMAC and CMAC operations to FIPS module in FIPS mode. If an + ENGINE is used then we cannot handle that in the FIPS module so we + keep original code iff non-FIPS operations are allowed. + + *Steve Henson* + + * Add -attime option to openssl utilities. + + *Peter Eckersley , Ben Laurie and Steve Henson* + + * Redirect DSA and DH operations to FIPS module in FIPS mode. + + *Steve Henson* + + * Redirect ECDSA and ECDH operations to FIPS module in FIPS mode. Also use + FIPS EC methods unconditionally for now. + + *Steve Henson* + + * New build option no-ec2m to disable characteristic 2 code. + + *Steve Henson* + + * Backport libcrypto audit of return value checking from 1.1.0-dev; not + all cases can be covered as some introduce binary incompatibilities. + + *Steve Henson* + + * Redirect RSA operations to FIPS module including keygen, + encrypt, decrypt, sign and verify. Block use of non FIPS RSA methods. + + *Steve Henson* + + * Add similar low-level API blocking to ciphers. + + *Steve Henson* + + * low-level digest APIs are not approved in FIPS mode: any attempt + to use these will cause a fatal error. Applications that *really* want + to use them can use the `private_*` version instead. + + *Steve Henson* + + * Redirect cipher operations to FIPS module for FIPS builds. + + *Steve Henson* + + * Redirect digest operations to FIPS module for FIPS builds. + + *Steve Henson* + + * Update build system to add "fips" flag which will link in fipscanister.o + for static and shared library builds embedding a signature if needed. + + *Steve Henson* + + * Output TLS supported curves in preference order instead of numerical + order. This is currently hardcoded for the highest order curves first. + This should be configurable so applications can judge speed vs strength. + + *Steve Henson* + + * Add TLS v1.2 server support for client authentication. + + *Steve Henson* + + * Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers + and enable MD5. + + *Steve Henson* + + * Functions FIPS_mode_set() and FIPS_mode() which call the underlying + FIPS modules versions. + + *Steve Henson* + + * Add TLS v1.2 client side support for client authentication. Keep cache + of handshake records longer as we don't know the hash algorithm to use + until after the certificate request message is received. + + *Steve Henson* + + * Initial TLS v1.2 client support. Add a default signature algorithms + extension including all the algorithms we support. Parse new signature + format in client key exchange. Relax some ECC signing restrictions for + TLS v1.2 as indicated in RFC5246. + + *Steve Henson* + + * Add server support for TLS v1.2 signature algorithms extension. Switch + to new signature format when needed using client digest preference. + All server ciphersuites should now work correctly in TLS v1.2. No client + support yet and no support for client certificates. + + *Steve Henson* + + * Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch + to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based + ciphersuites. At present only RSA key exchange ciphersuites work with + TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete + SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods + and version checking. + + *Steve Henson* + + * New option OPENSSL_NO_SSL_INTERN. If an application can be compiled + with this defined it will not be affected by any changes to ssl internal + structures. Add several utility functions to allow openssl application + to work with OPENSSL_NO_SSL_INTERN defined. + + *Steve Henson* + + * A long standing patch to add support for SRP from EdelWeb (Peter + Sylvester and Christophe Renou) was integrated. + *Christophe Renou , Peter Sylvester + , Tom Wu , and + Ben Laurie* + + * Add functions to copy EVP_PKEY_METHOD and retrieve flags and id. + + *Steve Henson* + + * Permit abbreviated handshakes when renegotiating using the function + SSL_renegotiate_abbreviated(). + + *Robin Seggelmann * + + * Add call to ENGINE_register_all_complete() to + ENGINE_load_builtin_engines(), so some implementations get used + automatically instead of needing explicit application support. + + *Steve Henson* + + * Add support for TLS key exporter as described in RFC5705. + + *Robin Seggelmann , Steve Henson* + + * Initial TLSv1.1 support. Since TLSv1.1 is very similar to TLS v1.0 only + a few changes are required: + + Add SSL_OP_NO_TLSv1_1 flag. + Add TLSv1_1 methods. + Update version checking logic to handle version 1.1. + Add explicit IV handling (ported from DTLS code). + Add command line options to s_client/s_server. + + *Steve Henson* + +OpenSSL 1.0.0 +------------- + +### Changes between 1.0.0s and 1.0.0t [3 Dec 2015] + + * X509_ATTRIBUTE memory leak + + When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak + memory. This structure is used by the PKCS#7 and CMS routines so any + application which reads PKCS#7 or CMS data from untrusted sources is + affected. SSL/TLS is not affected. + + This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using + libFuzzer. + ([CVE-2015-3195]) + + *Stephen Henson* + + * Race condition handling PSK identify hint + + If PSK identity hints are received by a multi-threaded client then + the values are wrongly updated in the parent SSL_CTX structure. This can + result in a race condition potentially leading to a double free of the + identify hint data. + ([CVE-2015-3196]) + + *Stephen Henson* + +### Changes between 1.0.0r and 1.0.0s [11 Jun 2015] + + * Malformed ECParameters causes infinite loop + + When processing an ECParameters structure OpenSSL enters an infinite loop + if the curve specified is over a specially malformed binary polynomial + field. + + This can be used to perform denial of service against any + system which processes public keys, certificate requests or + certificates. This includes TLS clients and TLS servers with + client authentication enabled. + + This issue was reported to OpenSSL by Joseph Barr-Pixton. + ([CVE-2015-1788]) + + *Andy Polyakov* + + * Exploitable out-of-bounds read in X509_cmp_time + + X509_cmp_time does not properly check the length of the ASN1_TIME + string and can read a few bytes out of bounds. In addition, + X509_cmp_time accepts an arbitrary number of fractional seconds in the + time string. + + An attacker can use this to craft malformed certificates and CRLs of + various sizes and potentially cause a segmentation fault, resulting in + a DoS on applications that verify certificates or CRLs. TLS clients + that verify CRLs are affected. TLS clients and servers with client + authentication enabled may be affected if they use custom verification + callbacks. + + This issue was reported to OpenSSL by Robert Swiecki (Google), and + independently by Hanno Böck. + ([CVE-2015-1789]) + + *Emilia Käsper* + + * PKCS7 crash with missing EnvelopedContent + + The PKCS#7 parsing code does not handle missing inner EncryptedContent + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs + with missing content and trigger a NULL pointer dereference on parsing. + + Applications that decrypt PKCS#7 data or otherwise parse PKCS#7 + structures from untrusted sources are affected. OpenSSL clients and + servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + ([CVE-2015-1790]) + + *Emilia Käsper* + + * CMS verify infinite loop with unknown hash function + + When verifying a signedData message the CMS code can enter an infinite loop + if presented with an unknown hash function OID. This can be used to perform + denial of service against any system which verifies signedData messages using + the CMS code. + This issue was reported to OpenSSL by Johannes Bauer. + ([CVE-2015-1792]) + + *Stephen Henson* + + * Race condition handling NewSessionTicket + + If a NewSessionTicket is received by a multi-threaded client when attempting to + reuse a previous ticket then a race condition can occur potentially leading to + a double free of the ticket data. + ([CVE-2015-1791]) + + *Matt Caswell* + +### Changes between 1.0.0q and 1.0.0r [19 Mar 2015] + + * Segmentation fault in ASN1_TYPE_cmp fix + + The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is + made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check + certificate signature algorithm consistency this can be used to crash any + certificate verification operation and exploited in a DoS attack. Any + application which performs certificate verification is vulnerable including + OpenSSL clients and servers which enable client authentication. + ([CVE-2015-0286]) + + *Stephen Henson* + + * ASN.1 structure reuse memory corruption fix + + Reusing a structure in ASN.1 parsing may allow an attacker to cause + memory corruption via an invalid write. Such reuse is and has been + strongly discouraged and is believed to be rare. + + Applications that parse structures containing CHOICE or ANY DEFINED BY + components may be affected. Certificate parsing (d2i_X509 and related + functions) are however not affected. OpenSSL clients and servers are + not affected. + ([CVE-2015-0287]) + + *Stephen Henson* + + * PKCS7 NULL pointer dereferences fix + + The PKCS#7 parsing code does not handle missing outer ContentInfo + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with + missing content and trigger a NULL pointer dereference on parsing. + + Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or + otherwise parse PKCS#7 structures from untrusted sources are + affected. OpenSSL clients and servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + ([CVE-2015-0289]) + + *Emilia Käsper* + + * DoS via reachable assert in SSLv2 servers fix + + A malicious client can trigger an OPENSSL_assert (i.e., an abort) in + servers that both support SSLv2 and enable export cipher suites by sending + a specially crafted SSLv2 CLIENT-MASTER-KEY message. + + This issue was discovered by Sean Burford (Google) and Emilia Käsper + (OpenSSL development team). + ([CVE-2015-0293]) + + *Emilia Käsper* + + * Use After Free following d2i_ECPrivatekey error fix + + A malformed EC private key file consumed via the d2i_ECPrivateKey function + could cause a use after free condition. This, in turn, could cause a double + free in several private key parsing functions (such as d2i_PrivateKey + or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption + for applications that receive EC private keys from untrusted + sources. This scenario is considered rare. + + This issue was discovered by the BoringSSL project and fixed in their + commit 517073cd4b. + ([CVE-2015-0209]) + + *Matt Caswell* + + * X509_to_X509_REQ NULL pointer deref fix + + The function X509_to_X509_REQ will crash with a NULL pointer dereference if + the certificate key is invalid. This function is rarely used in practice. + + This issue was discovered by Brian Carpenter. + ([CVE-2015-0288]) + + *Stephen Henson* + + * Removed the export ciphers from the DEFAULT ciphers + + *Kurt Roeckx* + +### Changes between 1.0.0p and 1.0.0q [15 Jan 2015] + + * Build fixes for the Windows and OpenVMS platforms + + *Matt Caswell and Richard Levitte* + +### Changes between 1.0.0o and 1.0.0p [8 Jan 2015] + + * Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS + message can cause a segmentation fault in OpenSSL due to a NULL pointer + dereference. This could lead to a Denial Of Service attack. Thanks to + Markus Stenberg of Cisco Systems, Inc. for reporting this issue. + ([CVE-2014-3571]) + + *Steve Henson* + + * Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the + dtls1_buffer_record function under certain conditions. In particular this + could occur if an attacker sent repeated DTLS records with the same + sequence number but for the next epoch. The memory leak could be exploited + by an attacker in a Denial of Service attack through memory exhaustion. + Thanks to Chris Mueller for reporting this issue. + ([CVE-2015-0206]) + + *Matt Caswell* + + * Fix issue where no-ssl3 configuration sets method to NULL. When openssl is + built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl + method would be set to NULL which could later result in a NULL pointer + dereference. Thanks to Frank Schmirler for reporting this issue. + ([CVE-2014-3569]) + + *Kurt Roeckx* + + * Abort handshake if server key exchange message is omitted for ephemeral + ECDH ciphersuites. + + Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for + reporting this issue. + ([CVE-2014-3572]) + + *Steve Henson* + + * Remove non-export ephemeral RSA code on client and server. This code + violated the TLS standard by allowing the use of temporary RSA keys in + non-export ciphersuites and could be used by a server to effectively + downgrade the RSA key length used to a value smaller than the server + certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at + INRIA or reporting this issue. + ([CVE-2015-0204]) + + *Steve Henson* + + * Fixed issue where DH client certificates are accepted without verification. + An OpenSSL server will accept a DH certificate for client authentication + without the certificate verify message. This effectively allows a client to + authenticate without the use of a private key. This only affects servers + which trust a client certificate authority which issues certificates + containing DH keys: these are extremely rare and hardly ever encountered. + Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting + this issue. + ([CVE-2015-0205]) + + *Steve Henson* + + * Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect + results on some platforms, including x86_64. This bug occurs at random + with a very low probability, and is not known to be exploitable in any + way, though its exact impact is difficult to determine. Thanks to Pieter + Wuille (Blockstream) who reported this issue and also suggested an initial + fix. Further analysis was conducted by the OpenSSL development team and + Adam Langley of Google. The final fix was developed by Andy Polyakov of + the OpenSSL core team. + ([CVE-2014-3570]) + + *Andy Polyakov* + + * Fix various certificate fingerprint issues. + + By using non-DER or invalid encodings outside the signed portion of a + certificate the fingerprint can be changed without breaking the signature. + Although no details of the signed portion of the certificate can be changed + this can cause problems with some applications: e.g. those using the + certificate fingerprint for blacklists. + + 1. Reject signatures with non zero unused bits. + + If the BIT STRING containing the signature has non zero unused bits reject + the signature. All current signature algorithms require zero unused bits. + + 2. Check certificate algorithm consistency. + + Check the AlgorithmIdentifier inside TBS matches the one in the + certificate signature. NB: this will result in signature failure + errors for some broken certificates. + + Thanks to Konrad Kraszewski from Google for reporting this issue. + + 3. Check DSA/ECDSA signatures use DER. + + Reencode DSA/ECDSA signatures and compare with the original received + signature. Return an error if there is a mismatch. + + This will reject various cases including garbage after signature + (thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS + program for discovering this case) and use of BER or invalid ASN.1 INTEGERs + (negative or with leading zeroes). + + Further analysis was conducted and fixes were developed by Stephen Henson + of the OpenSSL core team. + + ([CVE-2014-8275]) + + *Steve Henson* + +### Changes between 1.0.0n and 1.0.0o [15 Oct 2014] + + * Session Ticket Memory Leak. + + When an OpenSSL SSL/TLS/DTLS server receives a session ticket the + integrity of that ticket is first verified. In the event of a session + ticket integrity check failing, OpenSSL will fail to free memory + causing a memory leak. By sending a large number of invalid session + tickets an attacker could exploit this issue in a Denial Of Service + attack. + ([CVE-2014-3567]) + + *Steve Henson* + + * Build option no-ssl3 is incomplete. + + When OpenSSL is configured with "no-ssl3" as a build option, servers + could accept and complete a SSL 3.0 handshake, and clients could be + configured to send them. + ([CVE-2014-3568]) + + *Akamai and the OpenSSL team* + + * Add support for TLS_FALLBACK_SCSV. + Client applications doing fallback retries should call + SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV). + ([CVE-2014-3566]) + + *Adam Langley, Bodo Moeller* + + * Add additional DigestInfo checks. + + Reencode DigestInto in DER and check against the original when + verifying RSA signature: this will reject any improperly encoded + DigestInfo structures. + + Note: this is a precautionary measure and no attacks are currently known. + + *Steve Henson* + +### Changes between 1.0.0m and 1.0.0n [6 Aug 2014] + + * OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject + to a denial of service attack. A malicious server can crash the client + with a null pointer dereference (read) by specifying an anonymous (EC)DH + ciphersuite and sending carefully crafted handshake messages. + + Thanks to Felix Gröbert (Google) for discovering and researching this + issue. + ([CVE-2014-3510]) + + *Emilia Käsper* + + * By sending carefully crafted DTLS packets an attacker could cause openssl + to leak memory. This can be exploited through a Denial of Service attack. + Thanks to Adam Langley for discovering and researching this issue. + ([CVE-2014-3507]) + + *Adam Langley* + + * An attacker can force openssl to consume large amounts of memory whilst + processing DTLS handshake messages. This can be exploited through a + Denial of Service attack. + Thanks to Adam Langley for discovering and researching this issue. + ([CVE-2014-3506]) + + *Adam Langley* + + * An attacker can force an error condition which causes openssl to crash + whilst processing DTLS packets due to memory being freed twice. This + can be exploited through a Denial of Service attack. + Thanks to Adam Langley and Wan-Teh Chang for discovering and researching + this issue. + ([CVE-2014-3505]) + + *Adam Langley* + + * If a multithreaded client connects to a malicious server using a resumed + session and the server sends an ec point format extension it could write + up to 255 bytes to freed memory. + + Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this + issue. + ([CVE-2014-3509]) + + *Gabor Tyukasz* + + * A flaw in OBJ_obj2txt may cause pretty printing functions such as + X509_name_oneline, X509_name_print_ex et al. to leak some information + from the stack. Applications may be affected if they echo pretty printing + output to the attacker. + + Thanks to Ivan Fratric (Google) for discovering this issue. + ([CVE-2014-3508]) + + *Emilia Käsper, and Steve Henson* + + * Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.) + for corner cases. (Certain input points at infinity could lead to + bogus results, with non-infinity inputs mapped to infinity too.) + + *Bodo Moeller* + +### Changes between 1.0.0l and 1.0.0m [5 Jun 2014] + + * Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted + handshake can force the use of weak keying material in OpenSSL + SSL/TLS clients and servers. + + Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and + researching this issue. ([CVE-2014-0224]) + + *KIKUCHI Masashi, Steve Henson* + + * Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an + OpenSSL DTLS client the code can be made to recurse eventually crashing + in a DoS attack. + + Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue. + ([CVE-2014-0221]) + + *Imre Rad, Steve Henson* + + * Fix DTLS invalid fragment vulnerability. A buffer overrun attack can + be triggered by sending invalid DTLS fragments to an OpenSSL DTLS + client or server. This is potentially exploitable to run arbitrary + code on a vulnerable client or server. + + Thanks to Jüri Aedla for reporting this issue. ([CVE-2014-0195]) + + *Jüri Aedla, Steve Henson* + + * Fix bug in TLS code where clients enable anonymous ECDH ciphersuites + are subject to a denial of service attack. + + Thanks to Felix Gröbert and Ivan Fratric at Google for discovering + this issue. ([CVE-2014-3470]) + + *Felix Gröbert, Ivan Fratric, Steve Henson* + + * Harmonize version and its documentation. -f flag is used to display + compilation flags. + + *mancha * + + * Fix eckey_priv_encode so it immediately returns an error upon a failure + in i2d_ECPrivateKey. + + *mancha * + + * Fix some double frees. These are not thought to be exploitable. + + *mancha * + + * Fix for the attack described in the paper "Recovering OpenSSL + ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack" + by Yuval Yarom and Naomi Benger. Details can be obtained from: + + + Thanks to Yuval Yarom and Naomi Benger for discovering this + flaw and to Yuval Yarom for supplying a fix ([CVE-2014-0076]) + + *Yuval Yarom and Naomi Benger* + +### Changes between 1.0.0k and 1.0.0l [6 Jan 2014] + + * Keep original DTLS digest and encryption contexts in retransmission + structures so we can use the previous session parameters if they need + to be resent. ([CVE-2013-6450]) + + *Steve Henson* + + * Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which + avoids preferring ECDHE-ECDSA ciphers when the client appears to be + Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for + several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug + is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing + 10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer. + + *Rob Stradling, Adam Langley* + +### Changes between 1.0.0j and 1.0.0k [5 Feb 2013] + + * Make the decoding of SSLv3, TLS and DTLS CBC records constant time. + + This addresses the flaw in CBC record processing discovered by + Nadhem Alfardan and Kenny Paterson. Details of this attack can be found + at: + + Thanks go to Nadhem Alfardan and Kenny Paterson of the Information + Security Group at Royal Holloway, University of London + (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and + Emilia Käsper for the initial patch. + ([CVE-2013-0169]) + + *Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson* + + * Return an error when checking OCSP signatures when key is NULL. + This fixes a DoS attack. ([CVE-2013-0166]) + + *Steve Henson* + + * Call OCSP Stapling callback after ciphersuite has been chosen, so + the right response is stapled. Also change SSL_get_certificate() + so it returns the certificate actually sent. + See . + (This is a backport) + + *Rob Stradling * + + * Fix possible deadlock when decoding public keys. + + *Steve Henson* + +### Changes between 1.0.0i and 1.0.0j [10 May 2012] + +[NB: OpenSSL 1.0.0i and later 1.0.0 patch levels were released after +OpenSSL 1.0.1.] + + * Sanity check record length before skipping explicit IV in DTLS + to fix DoS attack. + + Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic + fuzzing as a service testing platform. + ([CVE-2012-2333]) + + *Steve Henson* + + * Initialise tkeylen properly when encrypting CMS messages. + Thanks to Solar Designer of Openwall for reporting this issue. + + *Steve Henson* + +### Changes between 1.0.0h and 1.0.0i [19 Apr 2012] + + * Check for potentially exploitable overflows in asn1_d2i_read_bio + BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer + in CRYPTO_realloc_clean. + + Thanks to Tavis Ormandy, Google Security Team, for discovering this + issue and to Adam Langley for fixing it. + ([CVE-2012-2110]) + + *Adam Langley (Google), Tavis Ormandy, Google Security Team* + +### Changes between 1.0.0g and 1.0.0h [12 Mar 2012] + + * Fix MMA (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) weakness + in CMS and PKCS7 code. When RSA decryption fails use a random key for + content decryption and always return the same error. Note: this attack + needs on average 2^20 messages so it only affects automated senders. The + old behaviour can be re-enabled in the CMS code by setting the + CMS_DEBUG_DECRYPT flag: this is useful for debugging and testing where + an MMA defence is not necessary. + Thanks to Ivan Nestlerode for discovering + this issue. ([CVE-2012-0884]) + + *Steve Henson* + + * Fix CVE-2011-4619: make sure we really are receiving a + client hello before rejecting multiple SGC restarts. Thanks to + Ivan Nestlerode for discovering this bug. + + *Steve Henson* + +### Changes between 1.0.0f and 1.0.0g [18 Jan 2012] + + * Fix for DTLS DoS issue introduced by fix for CVE-2011-4109. + Thanks to Antonio Martin, Enterprise Secure Access Research and + Development, Cisco Systems, Inc. for discovering this bug and + preparing a fix. ([CVE-2012-0050]) + + *Antonio Martin* + +### Changes between 1.0.0e and 1.0.0f [4 Jan 2012] + + * Nadhem Alfardan and Kenny Paterson have discovered an extension + of the Vaudenay padding oracle attack on CBC mode encryption + which enables an efficient plaintext recovery attack against + the OpenSSL implementation of DTLS. Their attack exploits timing + differences arising during decryption processing. A research + paper describing this attack can be found at: + + Thanks go to Nadhem Alfardan and Kenny Paterson of the Information + Security Group at Royal Holloway, University of London + (www.isg.rhul.ac.uk) for discovering this flaw and to Robin Seggelmann + and Michael Tuexen + for preparing the fix. ([CVE-2011-4108]) + + *Robin Seggelmann, Michael Tuexen* + + * Clear bytes used for block padding of SSL 3.0 records. + ([CVE-2011-4576]) + + *Adam Langley (Google)* + + * Only allow one SGC handshake restart for SSL/TLS. Thanks to George + Kadianakis for discovering this issue and + Adam Langley for preparing the fix. ([CVE-2011-4619]) + + *Adam Langley (Google)* + + * Check parameters are not NULL in GOST ENGINE. ([CVE-2012-0027]) + + *Andrey Kulikov * + + * Prevent malformed RFC3779 data triggering an assertion failure. + Thanks to Andrew Chi, BBN Technologies, for discovering the flaw + and Rob Austein for fixing it. ([CVE-2011-4577]) + + *Rob Austein * + + * Improved PRNG seeding for VOS. + + *Paul Green * + + * Fix ssl_ciph.c set-up race. + + *Adam Langley (Google)* + + * Fix spurious failures in ecdsatest.c. + + *Emilia Käsper (Google)* + + * Fix the BIO_f_buffer() implementation (which was mixing different + interpretations of the `..._len` fields). + + *Adam Langley (Google)* + + * Fix handling of BN_BLINDING: now BN_BLINDING_invert_ex (rather than + BN_BLINDING_invert_ex) calls BN_BLINDING_update, ensuring that concurrent + threads won't reuse the same blinding coefficients. + + This also avoids the need to obtain the CRYPTO_LOCK_RSA_BLINDING + lock to call BN_BLINDING_invert_ex, and avoids one use of + BN_BLINDING_update for each BN_BLINDING structure (previously, + the last update always remained unused). + + *Emilia Käsper (Google)* + + * In ssl3_clear, preserve s3->init_extra along with s3->rbuf. + + *Bob Buckholz (Google)* + +### Changes between 1.0.0d and 1.0.0e [6 Sep 2011] + + * Fix bug where CRLs with nextUpdate in the past are sometimes accepted + by initialising X509_STORE_CTX properly. ([CVE-2011-3207]) + + *Kaspar Brand * + + * Fix SSL memory handling for (EC)DH ciphersuites, in particular + for multi-threaded use of ECDH. ([CVE-2011-3210]) + + *Adam Langley (Google)* + + * Fix x509_name_ex_d2i memory leak on bad inputs. + + *Bodo Moeller* + + * Remove hard coded ecdsaWithSHA1 signature tests in ssl code and check + signature public key algorithm by using OID xref utilities instead. + Before this you could only use some ECC ciphersuites with SHA1 only. + + *Steve Henson* + + * Add protection against ECDSA timing attacks as mentioned in the paper + by Billy Bob Brumley and Nicola Tuveri, see: + + + *Billy Bob Brumley and Nicola Tuveri* + +### Changes between 1.0.0c and 1.0.0d [8 Feb 2011] + + * Fix parsing of OCSP stapling ClientHello extension. CVE-2011-0014 + + *Neel Mehta, Adam Langley, Bodo Moeller (Google)* + + * Fix bug in string printing code: if *any* escaping is enabled we must + escape the escape character (backslash) or the resulting string is + ambiguous. + + *Steve Henson* + +### Changes between 1.0.0b and 1.0.0c [2 Dec 2010] + + * Disable code workaround for ancient and obsolete Netscape browsers + and servers: an attacker can use it in a ciphersuite downgrade attack. + Thanks to Martin Rex for discovering this bug. CVE-2010-4180 + + *Steve Henson* + + * Fixed J-PAKE implementation error, originally discovered by + Sebastien Martini, further info and confirmation from Stefan + Arentz and Feng Hao. Note that this fix is a security fix. CVE-2010-4252 + + *Ben Laurie* + +### Changes between 1.0.0a and 1.0.0b [16 Nov 2010] + + * Fix extension code to avoid race conditions which can result in a buffer + overrun vulnerability: resumed sessions must not be modified as they can + be shared by multiple threads. CVE-2010-3864 + + *Steve Henson* + + * Fix WIN32 build system to correctly link an ENGINE directory into + a DLL. + + *Steve Henson* + +### Changes between 1.0.0 and 1.0.0a [01 Jun 2010] + + * Check return value of int_rsa_verify in pkey_rsa_verifyrecover + ([CVE-2010-1633]) + + *Steve Henson, Peter-Michael Hager * + +### Changes between 0.9.8n and 1.0.0 [29 Mar 2010] + + * Add "missing" function EVP_CIPHER_CTX_copy(). This copies a cipher + context. The operation can be customised via the ctrl mechanism in + case ENGINEs want to include additional functionality. + + *Steve Henson* + + * Tolerate yet another broken PKCS#8 key format: private key value negative. + + *Steve Henson* + + * Add new -subject_hash_old and -issuer_hash_old options to x509 utility to + output hashes compatible with older versions of OpenSSL. + + *Willy Weisz * + + * Fix compression algorithm handling: if resuming a session use the + compression algorithm of the resumed session instead of determining + it from client hello again. Don't allow server to change algorithm. + + *Steve Henson* + + * Add load_crls() function to commands tidying load_certs() too. Add option + to verify utility to allow additional CRLs to be included. + + *Steve Henson* + + * Update OCSP request code to permit adding custom headers to the request: + some responders need this. + + *Steve Henson* + + * The function EVP_PKEY_sign() returns <=0 on error: check return code + correctly. + + *Julia Lawall * + + * Update verify callback code in `apps/s_cb.c` and `apps/verify.c`, it + needlessly dereferenced structures, used obsolete functions and + didn't handle all updated verify codes correctly. + + *Steve Henson* + + * Disable MD2 in the default configuration. + + *Steve Henson* + + * In BIO_pop() and BIO_push() use the ctrl argument (which was NULL) to + indicate the initial BIO being pushed or popped. This makes it possible + to determine whether the BIO is the one explicitly called or as a result + of the ctrl being passed down the chain. Fix BIO_pop() and SSL BIOs so + it handles reference counts correctly and doesn't zero out the I/O bio + when it is not being explicitly popped. WARNING: applications which + included workarounds for the old buggy behaviour will need to be modified + or they could free up already freed BIOs. + + *Steve Henson* + + * Extend the uni2asc/asc2uni => OPENSSL_uni2asc/OPENSSL_asc2uni + renaming to all platforms (within the 0.9.8 branch, this was + done conditionally on Netware platforms to avoid a name clash). + + *Guenter * + + * Add ECDHE and PSK support to DTLS. + + *Michael Tuexen * + + * Add CHECKED_STACK_OF macro to safestack.h, otherwise safestack can't + be used on C++. + + *Steve Henson* + + * Add "missing" function EVP_MD_flags() (without this the only way to + retrieve a digest flags is by accessing the structure directly. Update + `EVP_MD_do_all*()` and `EVP_CIPHER_do_all*()` to include the name a digest + or cipher is registered as in the "from" argument. Print out all + registered digests in the dgst usage message instead of manually + attempting to work them out. + + *Steve Henson* + + * If no SSLv2 ciphers are used don't use an SSLv2 compatible client hello: + this allows the use of compression and extensions. Change default cipher + string to remove SSLv2 ciphersuites. This effectively avoids ancient SSLv2 + by default unless an application cipher string requests it. + + *Steve Henson* + + * Alter match criteria in PKCS12_parse(). It used to try to use local + key ids to find matching certificates and keys but some PKCS#12 files + don't follow the (somewhat unwritten) rules and this strategy fails. + Now just gather all certificates together and the first private key + then look for the first certificate that matches the key. + + *Steve Henson* + + * Support use of registered digest and cipher names for dgst and cipher + commands instead of having to add each one as a special case. So now + you can do: + + openssl sha256 foo + + as well as: + + openssl dgst -sha256 foo + + and this works for ENGINE based algorithms too. + + *Steve Henson* + + * Update Gost ENGINE to support parameter files. + + *Victor B. Wagner * + + * Support GeneralizedTime in ca utility. + + *Oliver Martin , Steve Henson* + + * Enhance the hash format used for certificate directory links. The new + form uses the canonical encoding (meaning equivalent names will work + even if they aren't identical) and uses SHA1 instead of MD5. This form + is incompatible with the older format and as a result c_rehash should + be used to rebuild symbolic links. + + *Steve Henson* + + * Make PKCS#8 the default write format for private keys, replacing the + traditional format. This form is standardised, more secure and doesn't + include an implicit MD5 dependency. + + *Steve Henson* + + * Add a $gcc_devteam_warn option to Configure. The idea is that any code + committed to OpenSSL should pass this lot as a minimum. + + *Steve Henson* + + * Add session ticket override functionality for use by EAP-FAST. + + *Jouni Malinen * + + * Modify HMAC functions to return a value. Since these can be implemented + in an ENGINE errors can occur. + + *Steve Henson* + + * Type-checked OBJ_bsearch_ex. + + *Ben Laurie* + + * Type-checked OBJ_bsearch. Also some constification necessitated + by type-checking. Still to come: TXT_DB, bsearch(?), + OBJ_bsearch_ex, qsort, CRYPTO_EX_DATA, ASN1_VALUE, ASN1_STRING, + CONF_VALUE. + + *Ben Laurie* + + * New function OPENSSL_gmtime_adj() to add a specific number of days and + seconds to a tm structure directly, instead of going through OS + specific date routines. This avoids any issues with OS routines such + as the year 2038 bug. New `*_adj()` functions for ASN1 time structures + and X509_time_adj_ex() to cover the extended range. The existing + X509_time_adj() is still usable and will no longer have any date issues. + + *Steve Henson* + + * Delta CRL support. New use deltas option which will attempt to locate + and search any appropriate delta CRLs available. + + This work was sponsored by Google. + + *Steve Henson* + + * Support for CRLs partitioned by reason code. Reorganise CRL processing + code and add additional score elements. Validate alternate CRL paths + as part of the CRL checking and indicate a new error "CRL path validation + error" in this case. Applications wanting additional details can use + the verify callback and check the new "parent" field. If this is not + NULL CRL path validation is taking place. Existing applications won't + see this because it requires extended CRL support which is off by + default. + + This work was sponsored by Google. + + *Steve Henson* + + * Support for freshest CRL extension. + + This work was sponsored by Google. + + *Steve Henson* + + * Initial indirect CRL support. Currently only supported in the CRLs + passed directly and not via lookup. Process certificate issuer + CRL entry extension and lookup CRL entries by bother issuer name + and serial number. Check and process CRL issuer entry in IDP extension. + + This work was sponsored by Google. + + *Steve Henson* + + * Add support for distinct certificate and CRL paths. The CRL issuer + certificate is validated separately in this case. Only enabled if + an extended CRL support flag is set: this flag will enable additional + CRL functionality in future. + + This work was sponsored by Google. + + *Steve Henson* + + * Add support for policy mappings extension. + + This work was sponsored by Google. + + *Steve Henson* + + * Fixes to pathlength constraint, self issued certificate handling, + policy processing to align with RFC3280 and PKITS tests. + + This work was sponsored by Google. + + *Steve Henson* + + * Support for name constraints certificate extension. DN, email, DNS + and URI types are currently supported. + + This work was sponsored by Google. + + *Steve Henson* + + * To cater for systems that provide a pointer-based thread ID rather + than numeric, deprecate the current numeric thread ID mechanism and + replace it with a structure and associated callback type. This + mechanism allows a numeric "hash" to be extracted from a thread ID in + either case, and on platforms where pointers are larger than 'long', + mixing is done to help ensure the numeric 'hash' is usable even if it + can't be guaranteed unique. The default mechanism is to use "&errno" + as a pointer-based thread ID to distinguish between threads. + + Applications that want to provide their own thread IDs should now use + CRYPTO_THREADID_set_callback() to register a callback that will call + either CRYPTO_THREADID_set_numeric() or CRYPTO_THREADID_set_pointer(). + + Note that ERR_remove_state() is now deprecated, because it is tied + to the assumption that thread IDs are numeric. ERR_remove_state(0) + to free the current thread's error state should be replaced by + ERR_remove_thread_state(NULL). + + (This new approach replaces the functions CRYPTO_set_idptr_callback(), + CRYPTO_get_idptr_callback(), and CRYPTO_thread_idptr() that existed in + OpenSSL 0.9.9-dev between June 2006 and August 2008. Also, if an + application was previously providing a numeric thread callback that + was inappropriate for distinguishing threads, then uniqueness might + have been obtained with &errno that happened immediately in the + intermediate development versions of OpenSSL; this is no longer the + case, the numeric thread callback will now override the automatic use + of &errno.) + + *Geoff Thorpe, with help from Bodo Moeller* + + * Initial support for different CRL issuing certificates. This covers a + simple case where the self issued certificates in the chain exist and + the real CRL issuer is higher in the existing chain. + + This work was sponsored by Google. + + *Steve Henson* + + * Removed effectively defunct crypto/store from the build. + + *Ben Laurie* + + * Revamp of STACK to provide stronger type-checking. Still to come: + TXT_DB, bsearch(?), OBJ_bsearch, qsort, CRYPTO_EX_DATA, ASN1_VALUE, + ASN1_STRING, CONF_VALUE. + + *Ben Laurie* + + * Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer + RAM on SSL connections. This option can save about 34k per idle SSL. + + *Nick Mathewson* + + * Revamp of LHASH to provide stronger type-checking. Still to come: + STACK, TXT_DB, bsearch, qsort. + + *Ben Laurie* + + * Initial support for Cryptographic Message Syntax (aka CMS) based + on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility, + support for data, signedData, compressedData, digestedData and + encryptedData, envelopedData types included. Scripts to check against + RFC4134 examples draft and interop and consistency checks of many + content types and variants. + + *Steve Henson* + + * Add options to enc utility to support use of zlib compression BIO. + + *Steve Henson* + + * Extend mk1mf to support importing of options and assembly language + files from Configure script, currently only included in VC-WIN32. + The assembly language rules can now optionally generate the source + files from the associated perl scripts. + + *Steve Henson* + + * Implement remaining functionality needed to support GOST ciphersuites. + Interop testing has been performed using CryptoPro implementations. + + *Victor B. Wagner * + + * s390x assembler pack. + + *Andy Polyakov* + + * ARMv4 assembler pack. ARMv4 refers to v4 and later ISA, not CPU + "family." + + *Andy Polyakov* + + * Implement Opaque PRF Input TLS extension as specified in + draft-rescorla-tls-opaque-prf-input-00.txt. Since this is not an + official specification yet and no extension type assignment by + IANA exists, this extension (for now) will have to be explicitly + enabled when building OpenSSL by providing the extension number + to use. For example, specify an option + + -DTLSEXT_TYPE_opaque_prf_input=0x9527 + + to the "config" or "Configure" script to enable the extension, + assuming extension number 0x9527 (which is a completely arbitrary + and unofficial assignment based on the MD5 hash of the Internet + Draft). Note that by doing so, you potentially lose + interoperability with other TLS implementations since these might + be using the same extension number for other purposes. + + SSL_set_tlsext_opaque_prf_input(ssl, src, len) is used to set the + opaque PRF input value to use in the handshake. This will create + an internal copy of the length-'len' string at 'src', and will + return non-zero for success. + + To get more control and flexibility, provide a callback function + by using + + SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb) + SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg) + + where + + int (*cb)(SSL *, void *peerinput, size_t len, void *arg); + void *arg; + + Callback function 'cb' will be called in handshakes, and is + expected to use SSL_set_tlsext_opaque_prf_input() as appropriate. + Argument 'arg' is for application purposes (the value as given to + SSL_CTX_set_tlsext_opaque_prf_input_callback_arg() will directly + be provided to the callback function). The callback function + has to return non-zero to report success: usually 1 to use opaque + PRF input just if possible, or 2 to enforce use of the opaque PRF + input. In the latter case, the library will abort the handshake + if opaque PRF input is not successfully negotiated. + + Arguments 'peerinput' and 'len' given to the callback function + will always be NULL and 0 in the case of a client. A server will + see the client's opaque PRF input through these variables if + available (NULL and 0 otherwise). Note that if the server + provides an opaque PRF input, the length must be the same as the + length of the client's opaque PRF input. + + Note that the callback function will only be called when creating + a new session (session resumption can resume whatever was + previously negotiated), and will not be called in SSL 2.0 + handshakes; thus, SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) or + SSL_set_options(ssl, SSL_OP_NO_SSLv2) is especially recommended + for applications that need to enforce opaque PRF input. + + *Bodo Moeller* + + * Update ssl code to support digests other than SHA1+MD5 for handshake + MAC. + + *Victor B. Wagner * + + * Add RFC4507 support to OpenSSL. This includes the corrections in + RFC4507bis. The encrypted ticket format is an encrypted encoded + SSL_SESSION structure, that way new session features are automatically + supported. + + If a client application caches session in an SSL_SESSION structure + support is transparent because tickets are now stored in the encoded + SSL_SESSION. + + The SSL_CTX structure automatically generates keys for ticket + protection in servers so again support should be possible + with no application modification. + + If a client or server wishes to disable RFC4507 support then the option + SSL_OP_NO_TICKET can be set. + + Add a TLS extension debugging callback to allow the contents of any client + or server extensions to be examined. + + This work was sponsored by Google. + + *Steve Henson* + + * Final changes to avoid use of pointer pointer casts in OpenSSL. + OpenSSL should now compile cleanly on gcc 4.2 + + *Peter Hartley , Steve Henson* + + * Update SSL library to use new EVP_PKEY MAC API. Include generic MAC + support including streaming MAC support: this is required for GOST + ciphersuite support. + + *Victor B. Wagner , Steve Henson* + + * Add option -stream to use PKCS#7 streaming in smime utility. New + function i2d_PKCS7_bio_stream() and PEM_write_PKCS7_bio_stream() + to output in BER and PEM format. + + *Steve Henson* + + * Experimental support for use of HMAC via EVP_PKEY interface. This + allows HMAC to be handled via the `EVP_DigestSign*()` interface. The + EVP_PKEY "key" in this case is the HMAC key, potentially allowing + ENGINE support for HMAC keys which are unextractable. New -mac and + -macopt options to dgst utility. + + *Steve Henson* + + * New option -sigopt to dgst utility. Update dgst to use + `EVP_Digest{Sign,Verify}*`. These two changes make it possible to use + alternative signing parameters such as X9.31 or PSS in the dgst + utility. + + *Steve Henson* + + * Change ssl_cipher_apply_rule(), the internal function that does + the work each time a ciphersuite string requests enabling + ("foo+bar"), moving ("+foo+bar"), disabling ("-foo+bar", or + removing ("!foo+bar") a class of ciphersuites: Now it maintains + the order of disabled ciphersuites such that those ciphersuites + that most recently went from enabled to disabled not only stay + in order with respect to each other, but also have higher priority + than other disabled ciphersuites the next time ciphersuites are + enabled again. + + This means that you can now say, e.g., "PSK:-PSK:HIGH" to enable + the same ciphersuites as with "HIGH" alone, but in a specific + order where the PSK ciphersuites come first (since they are the + most recently disabled ciphersuites when "HIGH" is parsed). + + Also, change ssl_create_cipher_list() (using this new + functionality) such that between otherwise identical + ciphersuites, ephemeral ECDH is preferred over ephemeral DH in + the default order. + + *Bodo Moeller* + + * Change ssl_create_cipher_list() so that it automatically + arranges the ciphersuites in reasonable order before starting + to process the rule string. Thus, the definition for "DEFAULT" + (SSL_DEFAULT_CIPHER_LIST) now is just "ALL:!aNULL:!eNULL", but + remains equivalent to `"AES:ALL:!aNULL:!eNULL:+aECDH:+kRSA:+RC4:@STRENGTH"`. + This makes it much easier to arrive at a reasonable default order + in applications for which anonymous ciphers are OK (meaning + that you can't actually use DEFAULT). + + *Bodo Moeller; suggested by Victor Duchovni* + + * Split the SSL/TLS algorithm mask (as used for ciphersuite string + processing) into multiple integers instead of setting + "SSL_MKEY_MASK" bits, "SSL_AUTH_MASK" bits, "SSL_ENC_MASK", + "SSL_MAC_MASK", and "SSL_SSL_MASK" bits all in a single integer. + (These masks as well as the individual bit definitions are hidden + away into the non-exported interface ssl/ssl_locl.h, so this + change to the definition of the SSL_CIPHER structure shouldn't + affect applications.) This give us more bits for each of these + categories, so there is no longer a need to coagulate AES128 and + AES256 into a single algorithm bit, and to coagulate Camellia128 + and Camellia256 into a single algorithm bit, which has led to all + kinds of kludges. + + Thus, among other things, the kludge introduced in 0.9.7m and + 0.9.8e for masking out AES256 independently of AES128 or masking + out Camellia256 independently of AES256 is not needed here in 0.9.9. + + With the change, we also introduce new ciphersuite aliases that + so far were missing: "AES128", "AES256", "CAMELLIA128", and + "CAMELLIA256". + + *Bodo Moeller* + + * Add support for dsa-with-SHA224 and dsa-with-SHA256. + Use the leftmost N bytes of the signature input if the input is + larger than the prime q (with N being the size in bytes of q). + + *Nils Larsch* + + * Very *very* experimental PKCS#7 streaming encoder support. Nothing uses + it yet and it is largely untested. + + *Steve Henson* + + * Add support for the ecdsa-with-SHA224/256/384/512 signature types. + + *Nils Larsch* + + * Initial incomplete changes to avoid need for function casts in OpenSSL + some compilers (gcc 4.2 and later) reject their use. Safestack is + reimplemented. Update ASN1 to avoid use of legacy functions. + + *Steve Henson* + + * Win32/64 targets are linked with Winsock2. + + *Andy Polyakov* + + * Add an X509_CRL_METHOD structure to allow CRL processing to be redirected + to external functions. This can be used to increase CRL handling + efficiency especially when CRLs are very large by (for example) storing + the CRL revoked certificates in a database. + + *Steve Henson* + + * Overhaul of by_dir code. Add support for dynamic loading of CRLs so + new CRLs added to a directory can be used. New command line option + -verify_return_error to s_client and s_server. This causes real errors + to be returned by the verify callback instead of carrying on no matter + what. This reflects the way a "real world" verify callback would behave. + + *Steve Henson* + + * GOST engine, supporting several GOST algorithms and public key formats. + Kindly donated by Cryptocom. + + *Cryptocom* + + * Partial support for Issuing Distribution Point CRL extension. CRLs + partitioned by DP are handled but no indirect CRL or reason partitioning + (yet). Complete overhaul of CRL handling: now the most suitable CRL is + selected via a scoring technique which handles IDP and AKID in CRLs. + + *Steve Henson* + + * New X509_STORE_CTX callbacks lookup_crls() and lookup_certs() which + will ultimately be used for all verify operations: this will remove the + X509_STORE dependency on certificate verification and allow alternative + lookup methods. X509_STORE based implementations of these two callbacks. + + *Steve Henson* + + * Allow multiple CRLs to exist in an X509_STORE with matching issuer names. + Modify get_crl() to find a valid (unexpired) CRL if possible. + + *Steve Henson* + + * New function X509_CRL_match() to check if two CRLs are identical. Normally + this would be called X509_CRL_cmp() but that name is already used by + a function that just compares CRL issuer names. Cache several CRL + extensions in X509_CRL structure and cache CRLDP in X509. + + *Steve Henson* + + * Store a "canonical" representation of X509_NAME structure (ASN1 Name) + this maps equivalent X509_NAME structures into a consistent structure. + Name comparison can then be performed rapidly using memcmp(). + + *Steve Henson* + + * Non-blocking OCSP request processing. Add -timeout option to ocsp + utility. + + *Steve Henson* + + * Allow digests to supply their own micalg string for S/MIME type using + the ctrl EVP_MD_CTRL_MICALG. + + *Steve Henson* + + * During PKCS7 signing pass the PKCS7 SignerInfo structure to the + EVP_PKEY_METHOD before and after signing via the EVP_PKEY_CTRL_PKCS7_SIGN + ctrl. It can then customise the structure before and/or after signing + if necessary. + + *Steve Henson* + + * New function OBJ_add_sigid() to allow application defined signature OIDs + to be added to OpenSSLs internal tables. New function OBJ_sigid_free() + to free up any added signature OIDs. + + *Steve Henson* + + * New functions EVP_CIPHER_do_all(), EVP_CIPHER_do_all_sorted(), + EVP_MD_do_all() and EVP_MD_do_all_sorted() to enumerate internal + digest and cipher tables. New options added to openssl utility: + list-message-digest-algorithms and list-cipher-algorithms. + + *Steve Henson* + + * Change the array representation of binary polynomials: the list + of degrees of non-zero coefficients is now terminated with -1. + Previously it was terminated with 0, which was also part of the + value; thus, the array representation was not applicable to + polynomials where t^0 has coefficient zero. This change makes + the array representation useful in a more general context. + + *Douglas Stebila* + + * Various modifications and fixes to SSL/TLS cipher string + handling. For ECC, the code now distinguishes between fixed ECDH + with RSA certificates on the one hand and with ECDSA certificates + on the other hand, since these are separate ciphersuites. The + unused code for Fortezza ciphersuites has been removed. + + For consistency with EDH, ephemeral ECDH is now called "EECDH" + (not "ECDHE"). For consistency with the code for DH + certificates, use of ECDH certificates is now considered ECDH + authentication, not RSA or ECDSA authentication (the latter is + merely the CA's signing algorithm and not actively used in the + protocol). + + The temporary ciphersuite alias "ECCdraft" is no longer + available, and ECC ciphersuites are no longer excluded from "ALL" + and "DEFAULT". The following aliases now exist for RFC 4492 + ciphersuites, most of these by analogy with the DH case: + + kECDHr - ECDH cert, signed with RSA + kECDHe - ECDH cert, signed with ECDSA + kECDH - ECDH cert (signed with either RSA or ECDSA) + kEECDH - ephemeral ECDH + ECDH - ECDH cert or ephemeral ECDH + + aECDH - ECDH cert + aECDSA - ECDSA cert + ECDSA - ECDSA cert + + AECDH - anonymous ECDH + EECDH - non-anonymous ephemeral ECDH (equivalent to "kEECDH:-AECDH") + + *Bodo Moeller* + + * Add additional S/MIME capabilities for AES and GOST ciphers if supported. + Use correct micalg parameters depending on digest(s) in signed message. + + *Steve Henson* + + * Add engine support for EVP_PKEY_ASN1_METHOD. Add functions to process + an ENGINE asn1 method. Support ENGINE lookups in the ASN1 code. + + *Steve Henson* + + * Initial engine support for EVP_PKEY_METHOD. New functions to permit + an engine to register a method. Add ENGINE lookups for methods and + functional reference processing. + + *Steve Henson* + + * New functions `EVP_Digest{Sign,Verify)*`. These are enhanced versions of + `EVP_{Sign,Verify}*` which allow an application to customise the signature + process. + + *Steve Henson* + + * New -resign option to smime utility. This adds one or more signers + to an existing PKCS#7 signedData structure. Also -md option to use an + alternative message digest algorithm for signing. + + *Steve Henson* + + * Tidy up PKCS#7 routines and add new functions to make it easier to + create PKCS7 structures containing multiple signers. Update smime + application to support multiple signers. + + *Steve Henson* + + * New -macalg option to pkcs12 utility to allow setting of an alternative + digest MAC. + + *Steve Henson* + + * Initial support for PKCS#5 v2.0 PRFs other than default SHA1 HMAC. + Reorganize PBE internals to lookup from a static table using NIDs, + add support for HMAC PBE OID translation. Add a EVP_CIPHER ctrl: + EVP_CTRL_PBE_PRF_NID this allows a cipher to specify an alternative + PRF which will be automatically used with PBES2. + + *Steve Henson* + + * Replace the algorithm specific calls to generate keys in "req" with the + new API. + + *Steve Henson* + + * Update PKCS#7 enveloped data routines to use new API. This is now + supported by any public key method supporting the encrypt operation. A + ctrl is added to allow the public key algorithm to examine or modify + the PKCS#7 RecipientInfo structure if it needs to: for RSA this is + a no op. + + *Steve Henson* + + * Add a ctrl to asn1 method to allow a public key algorithm to express + a default digest type to use. In most cases this will be SHA1 but some + algorithms (such as GOST) need to specify an alternative digest. The + return value indicates how strong the preference is 1 means optional and + 2 is mandatory (that is it is the only supported type). Modify + ASN1_item_sign() to accept a NULL digest argument to indicate it should + use the default md. Update openssl utilities to use the default digest + type for signing if it is not explicitly indicated. + + *Steve Henson* + + * Use OID cross reference table in ASN1_sign() and ASN1_verify(). New + EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant + signing method from the key type. This effectively removes the link + between digests and public key types. + + *Steve Henson* + + * Add an OID cross reference table and utility functions. Its purpose is to + translate between signature OIDs such as SHA1WithrsaEncryption and SHA1, + rsaEncryption. This will allow some of the algorithm specific hackery + needed to use the correct OID to be removed. + + *Steve Henson* + + * Remove algorithm specific dependencies when setting PKCS7_SIGNER_INFO + structures for PKCS7_sign(). They are now set up by the relevant public + key ASN1 method. + + *Steve Henson* + + * Add provisional EC pkey method with support for ECDSA and ECDH. + + *Steve Henson* + + * Add support for key derivation (agreement) in the API, DH method and + pkeyutl. + + *Steve Henson* + + * Add DSA pkey method and DH pkey methods, extend DH ASN1 method to support + public and private key formats. As a side effect these add additional + command line functionality not previously available: DSA signatures can be + generated and verified using pkeyutl and DH key support and generation in + pkey, genpkey. + + *Steve Henson* + + * BeOS support. + + *Oliver Tappe * + + * New make target "install_html_docs" installs HTML renditions of the + manual pages. + + *Oliver Tappe * + + * New utility "genpkey" this is analogous to "genrsa" etc except it can + generate keys for any algorithm. Extend and update EVP_PKEY_METHOD to + support key and parameter generation and add initial key generation + functionality for RSA. + + *Steve Henson* + + * Add functions for main EVP_PKEY_method operations. The undocumented + functions `EVP_PKEY_{encrypt,decrypt}` have been renamed to + `EVP_PKEY_{encrypt,decrypt}_old`. + + *Steve Henson* + + * Initial definitions for EVP_PKEY_METHOD. This will be a high level public + key API, doesn't do much yet. + + *Steve Henson* + + * New function EVP_PKEY_asn1_get0_info() to retrieve information about + public key algorithms. New option to openssl utility: + "list-public-key-algorithms" to print out info. + + *Steve Henson* + + * Implement the Supported Elliptic Curves Extension for + ECC ciphersuites from draft-ietf-tls-ecc-12.txt. + + *Douglas Stebila* + + * Don't free up OIDs in OBJ_cleanup() if they are in use by EVP_MD or + EVP_CIPHER structures to avoid later problems in EVP_cleanup(). + + *Steve Henson* + + * New utilities pkey and pkeyparam. These are similar to algorithm specific + utilities such as rsa, dsa, dsaparam etc except they process any key + type. + + *Steve Henson* + + * Transfer public key printing routines to EVP_PKEY_ASN1_METHOD. New + functions EVP_PKEY_print_public(), EVP_PKEY_print_private(), + EVP_PKEY_print_param() to print public key data from an EVP_PKEY + structure. + + *Steve Henson* + + * Initial support for pluggable public key ASN1. + De-spaghettify the public key ASN1 handling. Move public and private + key ASN1 handling to a new EVP_PKEY_ASN1_METHOD structure. Relocate + algorithm specific handling to a single module within the relevant + algorithm directory. Add functions to allow (near) opaque processing + of public and private key structures. + + *Steve Henson* + + * Implement the Supported Point Formats Extension for + ECC ciphersuites from draft-ietf-tls-ecc-12.txt. + + *Douglas Stebila* + + * Add initial support for RFC 4279 PSK TLS ciphersuites. Add members + for the psk identity [hint] and the psk callback functions to the + SSL_SESSION, SSL and SSL_CTX structure. + + New ciphersuites: + PSK-RC4-SHA, PSK-3DES-EDE-CBC-SHA, PSK-AES128-CBC-SHA, + PSK-AES256-CBC-SHA + + New functions: + SSL_CTX_use_psk_identity_hint + SSL_get_psk_identity_hint + SSL_get_psk_identity + SSL_use_psk_identity_hint + + *Mika Kousa and Pasi Eronen of Nokia Corporation* + + * Add RFC 3161 compliant time stamp request creation, response generation + and response verification functionality. + + *Zoltán Glózik , The OpenTSA Project* + + * Add initial support for TLS extensions, specifically for the server_name + extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now + have new members for a host name. The SSL data structure has an + additional member `SSL_CTX *initial_ctx` so that new sessions can be + stored in that context to allow for session resumption, even after the + SSL has been switched to a new SSL_CTX in reaction to a client's + server_name extension. + + New functions (subject to change): + + SSL_get_servername() + SSL_get_servername_type() + SSL_set_SSL_CTX() + + New CTRL codes and macros (subject to change): + + SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + - SSL_CTX_set_tlsext_servername_callback() + SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG + - SSL_CTX_set_tlsext_servername_arg() + SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name() + + openssl s_client has a new '-servername ...' option. + + openssl s_server has new options '-servername_host ...', '-cert2 ...', + '-key2 ...', '-servername_fatal' (subject to change). This allows + testing the HostName extension for a specific single host name ('-cert' + and '-key' remain fallbacks for handshakes without HostName + negotiation). If the unrecognized_name alert has to be sent, this by + default is a warning; it becomes fatal with the '-servername_fatal' + option. + + *Peter Sylvester, Remy Allais, Christophe Renou* + + * Whirlpool hash implementation is added. + + *Andy Polyakov* + + * BIGNUM code on 64-bit SPARCv9 targets is switched from bn(64,64) to + bn(64,32). Because of instruction set limitations it doesn't have + any negative impact on performance. This was done mostly in order + to make it possible to share assembler modules, such as bn_mul_mont + implementations, between 32- and 64-bit builds without hassle. + + *Andy Polyakov* + + * Move code previously exiled into file crypto/ec/ec2_smpt.c + to ec2_smpl.c, and no longer require the OPENSSL_EC_BIN_PT_COMP + macro. + + *Bodo Moeller* + + * New candidate for BIGNUM assembler implementation, bn_mul_mont, + dedicated Montgomery multiplication procedure, is introduced. + BN_MONT_CTX is modified to allow bn_mul_mont to reach for higher + "64-bit" performance on certain 32-bit targets. + + *Andy Polyakov* + + * New option SSL_OP_NO_COMP to disable use of compression selectively + in SSL structures. New SSL ctrl to set maximum send fragment size. + Save memory by setting the I/O buffer sizes dynamically instead of + using the maximum available value. + + *Steve Henson* + + * New option -V for 'openssl ciphers'. This prints the ciphersuite code + in addition to the text details. + + *Bodo Moeller* + + * Very, very preliminary EXPERIMENTAL support for printing of general + ASN1 structures. This currently produces rather ugly output and doesn't + handle several customised structures at all. + + *Steve Henson* + + * Integrated support for PVK file format and some related formats such + as MS PUBLICKEYBLOB and PRIVATEKEYBLOB. Command line switches to support + these in the 'rsa' and 'dsa' utilities. + + *Steve Henson* + + * Support for PKCS#1 RSAPublicKey format on rsa utility command line. + + *Steve Henson* + + * Remove the ancient ASN1_METHOD code. This was only ever used in one + place for the (very old) "NETSCAPE" format certificates which are now + handled using new ASN1 code equivalents. + + *Steve Henson* + + * Let the TLSv1_method() etc. functions return a 'const' SSL_METHOD + pointer and make the SSL_METHOD parameter in SSL_CTX_new, + SSL_CTX_set_ssl_version and SSL_set_ssl_method 'const'. + + *Nils Larsch* + + * Modify CRL distribution points extension code to print out previously + unsupported fields. Enhance extension setting code to allow setting of + all fields. + + *Steve Henson* + + * Add print and set support for Issuing Distribution Point CRL extension. + + *Steve Henson* + + * Change 'Configure' script to enable Camellia by default. + + *NTT* + +OpenSSL 0.9.x +------------- + +### Changes between 0.9.8m and 0.9.8n [24 Mar 2010] + + * When rejecting SSL/TLS records due to an incorrect version number, never + update s->server with a new major version number. As of + - OpenSSL 0.9.8m if 'short' is a 16-bit type, + - OpenSSL 0.9.8f if 'short' is longer than 16 bits, + the previous behavior could result in a read attempt at NULL when + receiving specific incorrect SSL/TLS records once record payload + protection is active. ([CVE-2010-0740]) + + *Bodo Moeller, Adam Langley * + + * Fix for CVE-2010-0433 where some kerberos enabled versions of OpenSSL + could be crashed if the relevant tables were not present (e.g. chrooted). + + *Tomas Hoger * + +### Changes between 0.9.8l and 0.9.8m [25 Feb 2010] + + * Always check bn_wexpand() return values for failure. ([CVE-2009-3245]) + + *Martin Olsson, Neel Mehta* + + * Fix X509_STORE locking: Every 'objs' access requires a lock (to + accommodate for stack sorting, always a write lock!). + + *Bodo Moeller* + + * On some versions of WIN32 Heap32Next is very slow. This can cause + excessive delays in the RAND_poll(): over a minute. As a workaround + include a time check in the inner Heap32Next loop too. + + *Steve Henson* + + * The code that handled flushing of data in SSL/TLS originally used the + BIO_CTRL_INFO ctrl to see if any data was pending first. This caused + the problem outlined in PR#1949. The fix suggested there however can + trigger problems with buggy BIO_CTRL_WPENDING (e.g. some versions + of Apache). So instead simplify the code to flush unconditionally. + This should be fine since flushing with no data to flush is a no op. + + *Steve Henson* + + * Handle TLS versions 2.0 and later properly and correctly use the + highest version of TLS/SSL supported. Although TLS >= 2.0 is some way + off ancient servers have a habit of sticking around for a while... + + *Steve Henson* + + * Modify compression code so it frees up structures without using the + ex_data callbacks. This works around a problem where some applications + call CRYPTO_cleanup_all_ex_data() before application exit (e.g. when + restarting) then use compression (e.g. SSL with compression) later. + This results in significant per-connection memory leaks and + has caused some security issues including CVE-2008-1678 and + CVE-2009-4355. + + *Steve Henson* + + * Constify crypto/cast (i.e., ): a CAST_KEY doesn't + change when encrypting or decrypting. + + *Bodo Moeller* + + * Add option SSL_OP_LEGACY_SERVER_CONNECT which will allow clients to + connect and renegotiate with servers which do not support RI. + Until RI is more widely deployed this option is enabled by default. + + *Steve Henson* + + * Add "missing" ssl ctrls to clear options and mode. + + *Steve Henson* + + * If client attempts to renegotiate and doesn't support RI respond with + a no_renegotiation alert as required by RFC5746. Some renegotiating + TLS clients will continue a connection gracefully when they receive + the alert. Unfortunately OpenSSL mishandled this alert and would hang + waiting for a server hello which it will never receive. Now we treat a + received no_renegotiation alert as a fatal error. This is because + applications requesting a renegotiation might well expect it to succeed + and would have no code in place to handle the server denying it so the + only safe thing to do is to terminate the connection. + + *Steve Henson* + + * Add ctrl macro SSL_get_secure_renegotiation_support() which returns 1 if + peer supports secure renegotiation and 0 otherwise. Print out peer + renegotiation support in s_client/s_server. + + *Steve Henson* + + * Replace the highly broken and deprecated SPKAC certification method with + the updated NID creation version. This should correctly handle UTF8. + + *Steve Henson* + + * Implement RFC5746. Re-enable renegotiation but require the extension + as needed. Unfortunately, SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + turns out to be a bad idea. It has been replaced by + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION which can be set with + SSL_CTX_set_options(). This is really not recommended unless you + know what you are doing. + + *Eric Rescorla , Ben Laurie, Steve Henson* + + * Fixes to stateless session resumption handling. Use initial_ctx when + issuing and attempting to decrypt tickets in case it has changed during + servername handling. Use a non-zero length session ID when attempting + stateless session resumption: this makes it possible to determine if + a resumption has occurred immediately after receiving server hello + (several places in OpenSSL subtly assume this) instead of later in + the handshake. + + *Steve Henson* + + * The functions ENGINE_ctrl(), OPENSSL_isservice(), + CMS_get1_RecipientRequest() and RAND_bytes() can return <=0 on error + fixes for a few places where the return code is not checked + correctly. + + *Julia Lawall * + + * Add --strict-warnings option to Configure script to include devteam + warnings in other configurations. + + *Steve Henson* + + * Add support for --libdir option and LIBDIR variable in makefiles. This + makes it possible to install openssl libraries in locations which + have names other than "lib", for example "/usr/lib64" which some + systems need. + + *Steve Henson, based on patch from Jeremy Utley* + + * Don't allow the use of leading 0x80 in OIDs. This is a violation of + X690 8.9.12 and can produce some misleading textual output of OIDs. + + *Steve Henson, reported by Dan Kaminsky* + + * Delete MD2 from algorithm tables. This follows the recommendation in + several standards that it is not used in new applications due to + several cryptographic weaknesses. For binary compatibility reasons + the MD2 API is still compiled in by default. + + *Steve Henson* + + * Add compression id to {d2i,i2d}_SSL_SESSION so it is correctly saved + and restored. + + *Steve Henson* + + * Rename uni2asc and asc2uni functions to OPENSSL_uni2asc and + OPENSSL_asc2uni conditionally on Netware platforms to avoid a name + clash. + + *Guenter * + + * Fix the server certificate chain building code to use X509_verify_cert(), + it used to have an ad-hoc builder which was unable to cope with anything + other than a simple chain. + + *David Woodhouse , Steve Henson* + + * Don't check self signed certificate signatures in X509_verify_cert() + by default (a flag can override this): it just wastes time without + adding any security. As a useful side effect self signed root CAs + with non-FIPS digests are now usable in FIPS mode. + + *Steve Henson* + + * In dtls1_process_out_of_seq_message() the check if the current message + is already buffered was missing. For every new message was memory + allocated, allowing an attacker to perform an denial of service attack + with sending out of seq handshake messages until there is no memory + left. Additionally every future message was buffered, even if the + sequence number made no sense and would be part of another handshake. + So only messages with sequence numbers less than 10 in advance will be + buffered. ([CVE-2009-1378]) + + *Robin Seggelmann, discovered by Daniel Mentz* + + * Records are buffered if they arrive with a future epoch to be + processed after finishing the corresponding handshake. There is + currently no limitation to this buffer allowing an attacker to perform + a DOS attack with sending records with future epochs until there is no + memory left. This patch adds the pqueue_size() function to determine + the size of a buffer and limits the record buffer to 100 entries. + ([CVE-2009-1377]) + + *Robin Seggelmann, discovered by Daniel Mentz* + + * Keep a copy of frag->msg_header.frag_len so it can be used after the + parent structure is freed. ([CVE-2009-1379]) + + *Daniel Mentz* + + * Handle non-blocking I/O properly in SSL_shutdown() call. + + *Darryl Miles * + + * Add `2.5.4.*` OIDs + + *Ilya O. * + +### Changes between 0.9.8k and 0.9.8l [5 Nov 2009] + + * Disable renegotiation completely - this fixes a severe security + problem ([CVE-2009-3555]) at the cost of breaking all + renegotiation. Renegotiation can be re-enabled by setting + SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION in s3->flags at + run-time. This is really not recommended unless you know what + you're doing. + + *Ben Laurie* + +### Changes between 0.9.8j and 0.9.8k [25 Mar 2009] + + * Don't set val to NULL when freeing up structures, it is freed up by + underlying code. If `sizeof(void *) > sizeof(long)` this can result in + zeroing past the valid field. ([CVE-2009-0789]) + + *Paolo Ganci * + + * Fix bug where return value of CMS_SignerInfo_verify_content() was not + checked correctly. This would allow some invalid signed attributes to + appear to verify correctly. ([CVE-2009-0591]) + + *Ivan Nestlerode * + + * Reject UniversalString and BMPString types with invalid lengths. This + prevents a crash in ASN1_STRING_print_ex() which assumes the strings have + a legal length. ([CVE-2009-0590]) + + *Steve Henson* + + * Set S/MIME signing as the default purpose rather than setting it + unconditionally. This allows applications to override it at the store + level. + + *Steve Henson* + + * Permit restricted recursion of ASN1 strings. This is needed in practice + to handle some structures. + + *Steve Henson* + + * Improve efficiency of mem_gets: don't search whole buffer each time + for a '\n' + + *Jeremy Shapiro * + + * New -hex option for openssl rand. + + *Matthieu Herrb* + + * Print out UTF8String and NumericString when parsing ASN1. + + *Steve Henson* + + * Support NumericString type for name components. + + *Steve Henson* + + * Allow CC in the environment to override the automatically chosen + compiler. Note that nothing is done to ensure flags work with the + chosen compiler. + + *Ben Laurie* + +### Changes between 0.9.8i and 0.9.8j [07 Jan 2009] + + * Properly check EVP_VerifyFinal() and similar return values + ([CVE-2008-5077]). + + *Ben Laurie, Bodo Moeller, Google Security Team* + + * Enable TLS extensions by default. + + *Ben Laurie* + + * Allow the CHIL engine to be loaded, whether the application is + multithreaded or not. (This does not release the developer from the + obligation to set up the dynamic locking callbacks.) + + *Sander Temme * + + * Use correct exit code if there is an error in dgst command. + + *Steve Henson; problem pointed out by Roland Dirlewanger* + + * Tweak Configure so that you need to say "experimental-jpake" to enable + JPAKE, and need to use -DOPENSSL_EXPERIMENTAL_JPAKE in applications. + + *Bodo Moeller* + + * Add experimental JPAKE support, including demo authentication in + s_client and s_server. + + *Ben Laurie* + + * Set the comparison function in v3_addr_canonize(). + + *Rob Austein * + + * Add support for XMPP STARTTLS in s_client. + + *Philip Paeps * + + * Change the server-side SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG behavior + to ensure that even with this option, only ciphersuites in the + server's preference list will be accepted. (Note that the option + applies only when resuming a session, so the earlier behavior was + just about the algorithm choice for symmetric cryptography.) + + *Bodo Moeller* + +### Changes between 0.9.8h and 0.9.8i [15 Sep 2008] + + * Fix NULL pointer dereference if a DTLS server received + ChangeCipherSpec as first record ([CVE-2009-1386]). + + *PR #1679* + + * Fix a state transition in s3_srvr.c and d1_srvr.c + (was using SSL3_ST_CW_CLNT_HELLO_B, should be `..._ST_SW_SRVR_...`). + + *Nagendra Modadugu* + + * The fix in 0.9.8c that supposedly got rid of unsafe + double-checked locking was incomplete for RSA blinding, + addressing just one layer of what turns out to have been + doubly unsafe triple-checked locking. + + So now fix this for real by retiring the MONT_HELPER macro + in crypto/rsa/rsa_eay.c. + + *Bodo Moeller; problem pointed out by Marius Schilder* + + * Various precautionary measures: + + - Avoid size_t integer overflow in HASH_UPDATE (md32_common.h). + + - Avoid a buffer overflow in d2i_SSL_SESSION() (ssl_asn1.c). + (NB: This would require knowledge of the secret session ticket key + to exploit, in which case you'd be SOL either way.) + + - Change bn_nist.c so that it will properly handle input BIGNUMs + outside the expected range. + + - Enforce the 'num' check in BN_div() (bn_div.c) for non-BN_DEBUG + builds. + + *Neel Mehta, Bodo Moeller* + + * Allow engines to be "soft loaded" - i.e. optionally don't die if + the load fails. Useful for distros. + + *Ben Laurie and the FreeBSD team* + + * Add support for Local Machine Keyset attribute in PKCS#12 files. + + *Steve Henson* + + * Fix BN_GF2m_mod_arr() top-bit cleanup code. + + *Huang Ying* + + * Expand ENGINE to support engine supplied SSL client certificate functions. + + This work was sponsored by Logica. + + *Steve Henson* + + * Add CryptoAPI ENGINE to support use of RSA and DSA keys held in Windows + keystores. Support for SSL/TLS client authentication too. + Not compiled unless enable-capieng specified to Configure. + + This work was sponsored by Logica. + + *Steve Henson* + + * Fix bug in X509_ATTRIBUTE creation: don't set attribute using + ASN1_TYPE_set1 if MBSTRING flag set. This bug would crash certain + attribute creation routines such as certificate requests and PKCS#12 + files. + + *Steve Henson* + +### Changes between 0.9.8g and 0.9.8h [28 May 2008] + + * Fix flaw if 'Server Key exchange message' is omitted from a TLS + handshake which could lead to a client crash as found using the + Codenomicon TLS test suite ([CVE-2008-1672]) + + *Steve Henson, Mark Cox* + + * Fix double free in TLS server name extensions which could lead to + a remote crash found by Codenomicon TLS test suite ([CVE-2008-0891]) + + *Joe Orton* + + * Clear error queue in SSL_CTX_use_certificate_chain_file() + + Clear the error queue to ensure that error entries left from + older function calls do not interfere with the correct operation. + + *Lutz Jaenicke, Erik de Castro Lopo* + + * Remove root CA certificates of commercial CAs: + + The OpenSSL project does not recommend any specific CA and does not + have any policy with respect to including or excluding any CA. + Therefore it does not make any sense to ship an arbitrary selection + of root CA certificates with the OpenSSL software. + + *Lutz Jaenicke* + + * RSA OAEP patches to fix two separate invalid memory reads. + The first one involves inputs when 'lzero' is greater than + 'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes + before the beginning of from). The second one involves inputs where + the 'db' section contains nothing but zeroes (there is a one-byte + invalid read after the end of 'db'). + + *Ivan Nestlerode * + + * Partial backport from 0.9.9-dev: + + Introduce bn_mul_mont (dedicated Montgomery multiplication + procedure) as a candidate for BIGNUM assembler implementation. + While 0.9.9-dev uses assembler for various architectures, only + x86_64 is available by default here in the 0.9.8 branch, and + 32-bit x86 is available through a compile-time setting. + + To try the 32-bit x86 assembler implementation, use Configure + option "enable-montasm" (which exists only for this backport). + + As "enable-montasm" for 32-bit x86 disclaims code stability + anyway, in this constellation we activate additional code + backported from 0.9.9-dev for further performance improvements, + namely BN_from_montgomery_word. (To enable this otherwise, + e.g. x86_64, try `-DMONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD`.) + + *Andy Polyakov (backport partially by Bodo Moeller)* + + * Add TLS session ticket callback. This allows an application to set + TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed + values. This is useful for key rollover for example where several key + sets may exist with different names. + + *Steve Henson* + + * Reverse ENGINE-internal logic for caching default ENGINE handles. + This was broken until now in 0.9.8 releases, such that the only way + a registered ENGINE could be used (assuming it initialises + successfully on the host) was to explicitly set it as the default + for the relevant algorithms. This is in contradiction with 0.9.7 + behaviour and the documentation. With this fix, when an ENGINE is + registered into a given algorithm's table of implementations, the + 'uptodate' flag is reset so that auto-discovery will be used next + time a new context for that algorithm attempts to select an + implementation. + + *Ian Lister (tweaked by Geoff Thorpe)* + + * Backport of CMS code to OpenSSL 0.9.8. This differs from the 0.9.9 + implementation in the following ways: + + Lack of EVP_PKEY_ASN1_METHOD means algorithm parameters have to be + hard coded. + + Lack of BER streaming support means one pass streaming processing is + only supported if data is detached: setting the streaming flag is + ignored for embedded content. + + CMS support is disabled by default and must be explicitly enabled + with the enable-cms configuration option. + + *Steve Henson* + + * Update the GMP engine glue to do direct copies between BIGNUM and + mpz_t when openssl and GMP use the same limb size. Otherwise the + existing "conversion via a text string export" trick is still used. + + *Paul Sheer * + + * Zlib compression BIO. This is a filter BIO which compressed and + uncompresses any data passed through it. + + *Steve Henson* + + * Add AES_wrap_key() and AES_unwrap_key() functions to implement + RFC3394 compatible AES key wrapping. + + *Steve Henson* + + * Add utility functions to handle ASN1 structures. ASN1_STRING_set0(): + sets string data without copying. X509_ALGOR_set0() and + X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier) + data. Attribute function X509at_get0_data_by_OBJ(): retrieves data + from an X509_ATTRIBUTE structure optionally checking it occurs only + once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied + data. + + *Steve Henson* + + * Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set() + to get the expected BN_FLG_CONSTTIME behavior. + + *Bodo Moeller (Google)* + + * Netware support: + + - fixed wrong usage of ioctlsocket() when build for LIBC BSD sockets + - fixed do_tests.pl to run the test suite with CLIB builds too (CLIB_OPT) + - added some more tests to do_tests.pl + - fixed RunningProcess usage so that it works with newer LIBC NDKs too + - removed usage of BN_LLONG for CLIB builds to avoid runtime dependency + - added new Configure targets netware-clib-bsdsock, netware-clib-gcc, + netware-clib-bsdsock-gcc, netware-libc-bsdsock-gcc + - various changes to netware.pl to enable gcc-cross builds on Win32 + platform + - changed crypto/bio/b_sock.c to work with macro functions (CLIB BSD) + - various changes to fix missing prototype warnings + - fixed x86nasm.pl to create correct asm files for NASM COFF output + - added AES, WHIRLPOOL and CPUID assembler code to build files + - added missing AES assembler make rules to mk1mf.pl + - fixed order of includes in `apps/ocsp.c` so that `e_os.h` settings apply + + *Guenter Knauf * + + * Implement certificate status request TLS extension defined in RFC3546. + A client can set the appropriate parameters and receive the encoded + OCSP response via a callback. A server can query the supplied parameters + and set the encoded OCSP response in the callback. Add simplified examples + to s_client and s_server. + + *Steve Henson* + +### Changes between 0.9.8f and 0.9.8g [19 Oct 2007] + + * Fix various bugs: + + Binary incompatibility of ssl_ctx_st structure + + DTLS interoperation with non-compliant servers + + Don't call get_session_cb() without proposed session + + Fix ia64 assembler code + + *Andy Polyakov, Steve Henson* + +### Changes between 0.9.8e and 0.9.8f [11 Oct 2007] + + * DTLS Handshake overhaul. There were longstanding issues with + OpenSSL DTLS implementation, which were making it impossible for + RFC 4347 compliant client to communicate with OpenSSL server. + Unfortunately just fixing these incompatibilities would "cut off" + pre-0.9.8f clients. To allow for hassle free upgrade post-0.9.8e + server keeps tolerating non RFC compliant syntax. The opposite is + not true, 0.9.8f client can not communicate with earlier server. + This update even addresses CVE-2007-4995. + + *Andy Polyakov* + + * Changes to avoid need for function casts in OpenSSL: some compilers + (gcc 4.2 and later) reject their use. + *Kurt Roeckx , Peter Hartley , + Steve Henson* + + * Add RFC4507 support to OpenSSL. This includes the corrections in + RFC4507bis. The encrypted ticket format is an encrypted encoded + SSL_SESSION structure, that way new session features are automatically + supported. + + If a client application caches session in an SSL_SESSION structure + support is transparent because tickets are now stored in the encoded + SSL_SESSION. + + The SSL_CTX structure automatically generates keys for ticket + protection in servers so again support should be possible + with no application modification. + + If a client or server wishes to disable RFC4507 support then the option + SSL_OP_NO_TICKET can be set. + + Add a TLS extension debugging callback to allow the contents of any client + or server extensions to be examined. + + This work was sponsored by Google. + + *Steve Henson* + + * Add initial support for TLS extensions, specifically for the server_name + extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now + have new members for a host name. The SSL data structure has an + additional member `SSL_CTX *initial_ctx` so that new sessions can be + stored in that context to allow for session resumption, even after the + SSL has been switched to a new SSL_CTX in reaction to a client's + server_name extension. + + New functions (subject to change): + + SSL_get_servername() + SSL_get_servername_type() + SSL_set_SSL_CTX() + + New CTRL codes and macros (subject to change): + + SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + - SSL_CTX_set_tlsext_servername_callback() + SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG + - SSL_CTX_set_tlsext_servername_arg() + SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name() + + openssl s_client has a new '-servername ...' option. + + openssl s_server has new options '-servername_host ...', '-cert2 ...', + '-key2 ...', '-servername_fatal' (subject to change). This allows + testing the HostName extension for a specific single host name ('-cert' + and '-key' remain fallbacks for handshakes without HostName + negotiation). If the unrecognized_name alert has to be sent, this by + default is a warning; it becomes fatal with the '-servername_fatal' + option. + + *Peter Sylvester, Remy Allais, Christophe Renou, Steve Henson* + + * Add AES and SSE2 assembly language support to VC++ build. + + *Steve Henson* + + * Mitigate attack on final subtraction in Montgomery reduction. + + *Andy Polyakov* + + * Fix crypto/ec/ec_mult.c to work properly with scalars of value 0 + (which previously caused an internal error). + + *Bodo Moeller* + + * Squeeze another 10% out of IGE mode when in != out. + + *Ben Laurie* + + * AES IGE mode speedup. + + *Dean Gaudet (Google)* + + * Add the Korean symmetric 128-bit cipher SEED (see + ) and + add SEED ciphersuites from RFC 4162: + + TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA" + TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA" + TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA" + TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA" + + To minimize changes between patchlevels in the OpenSSL 0.9.8 + series, SEED remains excluded from compilation unless OpenSSL + is configured with 'enable-seed'. + + *KISA, Bodo Moeller* + + * Mitigate branch prediction attacks, which can be practical if a + single processor is shared, allowing a spy process to extract + information. For detailed background information, see + (O. Aciicmez, S. Gueron, + J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL + and Necessary Software Countermeasures"). The core of the change + are new versions BN_div_no_branch() and + BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(), + respectively, which are slower, but avoid the security-relevant + conditional branches. These are automatically called by BN_div() + and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one + of the input BIGNUMs. Also, BN_is_bit_set() has been changed to + remove a conditional branch. + + BN_FLG_CONSTTIME is the new name for the previous + BN_FLG_EXP_CONSTTIME flag, since it now affects more than just + modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag + in the exponent causes BN_mod_exp_mont() to use the alternative + implementation in BN_mod_exp_mont_consttime().) The old name + remains as a deprecated alias. + + Similarly, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general + RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses + constant-time implementations for more than just exponentiation. + Here too the old name is kept as a deprecated alias. + + BN_BLINDING_new() will now use BN_dup() for the modulus so that + the BN_BLINDING structure gets an independent copy of the + modulus. This means that the previous `BIGNUM *m` argument to + BN_BLINDING_new() and to BN_BLINDING_create_param() now + essentially becomes `const BIGNUM *m`, although we can't actually + change this in the header file before 0.9.9. It allows + RSA_setup_blinding() to use BN_with_flags() on the modulus to + enable BN_FLG_CONSTTIME. + + *Matthew D Wood (Intel Corp)* + + * In the SSL/TLS server implementation, be strict about session ID + context matching (which matters if an application uses a single + external cache for different purposes). Previously, + out-of-context reuse was forbidden only if SSL_VERIFY_PEER was + set. This did ensure strict client verification, but meant that, + with applications using a single external cache for quite + different requirements, clients could circumvent ciphersuite + restrictions for a given session ID context by starting a session + in a different context. + + *Bodo Moeller* + + * Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that + a ciphersuite string such as "DEFAULT:RSA" cannot enable + authentication-only ciphersuites. + + *Bodo Moeller* + + * Update the SSL_get_shared_ciphers() fix CVE-2006-3738 which was + not complete and could lead to a possible single byte overflow + ([CVE-2007-5135]) [Ben Laurie] + +### Changes between 0.9.8d and 0.9.8e [23 Feb 2007] + + * Since AES128 and AES256 (and similarly Camellia128 and + Camellia256) share a single mask bit in the logic of + ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a + kludge to work properly if AES128 is available and AES256 isn't + (or if Camellia128 is available and Camellia256 isn't). + + *Victor Duchovni* + + * Fix the BIT STRING encoding generated by crypto/ec/ec_asn1.c + (within i2d_ECPrivateKey, i2d_ECPKParameters, i2d_ECParameters): + When a point or a seed is encoded in a BIT STRING, we need to + prevent the removal of trailing zero bits to get the proper DER + encoding. (By default, crypto/asn1/a_bitstr.c assumes the case + of a NamedBitList, for which trailing 0 bits need to be removed.) + + *Bodo Moeller* + + * Have SSL/TLS server implementation tolerate "mismatched" record + protocol version while receiving ClientHello even if the + ClientHello is fragmented. (The server can't insist on the + particular protocol version it has chosen before the ServerHello + message has informed the client about his choice.) + + *Bodo Moeller* + + * Add RFC 3779 support. + + *Rob Austein for ARIN, Ben Laurie* + + * Load error codes if they are not already present instead of using a + static variable. This allows them to be cleanly unloaded and reloaded. + Improve header file function name parsing. + + *Steve Henson* + + * extend SMTP and IMAP protocol emulation in s_client to use EHLO + or CAPABILITY handshake as required by RFCs. + + *Goetz Babin-Ebell* + +### Changes between 0.9.8c and 0.9.8d [28 Sep 2006] + + * Introduce limits to prevent malicious keys being able to + cause a denial of service. ([CVE-2006-2940]) + + *Steve Henson, Bodo Moeller* + + * Fix ASN.1 parsing of certain invalid structures that can result + in a denial of service. ([CVE-2006-2937]) [Steve Henson] + + * Fix buffer overflow in SSL_get_shared_ciphers() function. + ([CVE-2006-3738]) [Tavis Ormandy and Will Drewry, Google Security Team] + + * Fix SSL client code which could crash if connecting to a + malicious SSLv2 server. ([CVE-2006-4343]) + + *Tavis Ormandy and Will Drewry, Google Security Team* + + * Since 0.9.8b, ciphersuite strings naming explicit ciphersuites + match only those. Before that, "AES256-SHA" would be interpreted + as a pattern and match "AES128-SHA" too (since AES128-SHA got + the same strength classification in 0.9.7h) as we currently only + have a single AES bit in the ciphersuite description bitmap. + That change, however, also applied to ciphersuite strings such as + "RC4-MD5" that intentionally matched multiple ciphersuites -- + namely, SSL 2.0 ciphersuites in addition to the more common ones + from SSL 3.0/TLS 1.0. + + So we change the selection algorithm again: Naming an explicit + ciphersuite selects this one ciphersuite, and any other similar + ciphersuite (same bitmap) from *other* protocol versions. + Thus, "RC4-MD5" again will properly select both the SSL 2.0 + ciphersuite and the SSL 3.0/TLS 1.0 ciphersuite. + + Since SSL 2.0 does not have any ciphersuites for which the + 128/256 bit distinction would be relevant, this works for now. + The proper fix will be to use different bits for AES128 and + AES256, which would have avoided the problems from the beginning; + however, bits are scarce, so we can only do this in a new release + (not just a patchlevel) when we can change the SSL_CIPHER + definition to split the single 'unsigned long mask' bitmap into + multiple values to extend the available space. + + *Bodo Moeller* + +### Changes between 0.9.8b and 0.9.8c [05 Sep 2006] + + * Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher + ([CVE-2006-4339]) [Ben Laurie and Google Security Team] + + * Add AES IGE and biIGE modes. + + *Ben Laurie* + + * Change the Unix randomness entropy gathering to use poll() when + possible instead of select(), since the latter has some + undesirable limitations. + + *Darryl Miles via Richard Levitte and Bodo Moeller* + + * Disable "ECCdraft" ciphersuites more thoroughly. Now special + treatment in ssl/ssl_ciph.s makes sure that these ciphersuites + cannot be implicitly activated as part of, e.g., the "AES" alias. + However, please upgrade to OpenSSL 0.9.9[-dev] for + non-experimental use of the ECC ciphersuites to get TLS extension + support, which is required for curve and point format negotiation + to avoid potential handshake problems. + + *Bodo Moeller* + + * Disable rogue ciphersuites: + + - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5") + - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5") + - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5") + + The latter two were purportedly from + draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really + appear there. + + Also deactivate the remaining ciphersuites from + draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as + unofficial, and the ID has long expired. + + *Bodo Moeller* + + * Fix RSA blinding Heisenbug (problems sometimes occurred on + dual-core machines) and other potential thread-safety issues. + + *Bodo Moeller* + + * Add the symmetric cipher Camellia (128-bit, 192-bit, 256-bit key + versions), which is now available for royalty-free use + (see ). + Also, add Camellia TLS ciphersuites from RFC 4132. + + To minimize changes between patchlevels in the OpenSSL 0.9.8 + series, Camellia remains excluded from compilation unless OpenSSL + is configured with 'enable-camellia'. + + *NTT* + + * Disable the padding bug check when compression is in use. The padding + bug check assumes the first packet is of even length, this is not + necessarily true if compression is enabled and can result in false + positives causing handshake failure. The actual bug test is ancient + code so it is hoped that implementations will either have fixed it by + now or any which still have the bug do not support compression. + + *Steve Henson* + +### Changes between 0.9.8a and 0.9.8b [04 May 2006] + + * When applying a cipher rule check to see if string match is an explicit + cipher suite and only match that one cipher suite if it is. + + *Steve Henson* + + * Link in manifests for VC++ if needed. + + *Austin Ziegler * + + * Update support for ECC-based TLS ciphersuites according to + draft-ietf-tls-ecc-12.txt with proposed changes (but without + TLS extensions, which are supported starting with the 0.9.9 + branch, not in the OpenSSL 0.9.8 branch). + + *Douglas Stebila* + + * New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() to support + opaque EVP_CIPHER_CTX handling. + + *Steve Henson* + + * Fixes and enhancements to zlib compression code. We now only use + "zlib1.dll" and use the default `__cdecl` calling convention on Win32 + to conform with the standards mentioned here: + + Static zlib linking now works on Windows and the new --with-zlib-include + --with-zlib-lib options to Configure can be used to supply the location + of the headers and library. Gracefully handle case where zlib library + can't be loaded. + + *Steve Henson* + + * Several fixes and enhancements to the OID generation code. The old code + sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't + handle numbers larger than ULONG_MAX, truncated printing and had a + non standard OBJ_obj2txt() behaviour. + + *Steve Henson* + + * Add support for building of engines under engine/ as shared libraries + under VC++ build system. + + *Steve Henson* + + * Corrected the numerous bugs in the Win32 path splitter in DSO. + Hopefully, we will not see any false combination of paths any more. + + *Richard Levitte* + +### Changes between 0.9.8 and 0.9.8a [11 Oct 2005] + + * Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING + (part of SSL_OP_ALL). This option used to disable the + countermeasure against man-in-the-middle protocol-version + rollback in the SSL 2.0 server implementation, which is a bad + idea. ([CVE-2005-2969]) + + *Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center + for Information Security, National Institute of Advanced Industrial + Science and Technology [AIST], Japan)* + + * Add two function to clear and return the verify parameter flags. + + *Steve Henson* + + * Keep cipherlists sorted in the source instead of sorting them at + runtime, thus removing the need for a lock. + + *Nils Larsch* + + * Avoid some small subgroup attacks in Diffie-Hellman. + + *Nick Mathewson and Ben Laurie* + + * Add functions for well-known primes. + + *Nick Mathewson* + + * Extended Windows CE support. + + *Satoshi Nakamura and Andy Polyakov* + + * Initialize SSL_METHOD structures at compile time instead of during + runtime, thus removing the need for a lock. + + *Steve Henson* + + * Make PKCS7_decrypt() work even if no certificate is supplied by + attempting to decrypt each encrypted key in turn. Add support to + smime utility. + + *Steve Henson* + +### Changes between 0.9.7h and 0.9.8 [05 Jul 2005] + +[NB: OpenSSL 0.9.7i and later 0.9.7 patch levels were released after +OpenSSL 0.9.8.] + + * Add libcrypto.pc and libssl.pc for those who feel they need them. + + *Richard Levitte* + + * Change CA.sh and CA.pl so they don't bundle the CSR and the private + key into the same file any more. + + *Richard Levitte* + + * Add initial support for Win64, both IA64 and AMD64/x64 flavors. + + *Andy Polyakov* + + * Add -utf8 command line and config file option to 'ca'. + + *Stefan and Geoff Thorpe* + + * Add attribute functions to EVP_PKEY structure. Modify + PKCS12_create() to recognize a CSP name attribute and + use it. Make -CSP option work again in pkcs12 utility. + + *Steve Henson* + + * Add new functionality to the bn blinding code: + - automatic re-creation of the BN_BLINDING parameters after + a fixed number of uses (currently 32) + - add new function for parameter creation + - introduce flags to control the update behaviour of the + BN_BLINDING parameters + - hide BN_BLINDING structure + Add a second BN_BLINDING slot to the RSA structure to improve + performance when a single RSA object is shared among several + threads. + + *Nils Larsch* + + * Add support for DTLS. + + *Nagendra Modadugu and Ben Laurie* + + * Add support for DER encoded private keys (SSL_FILETYPE_ASN1) + to SSL_CTX_use_PrivateKey_file() and SSL_use_PrivateKey_file() + + *Walter Goulet* + + * Remove buggy and incomplete DH cert support from + ssl/ssl_rsa.c and ssl/s3_both.c + + *Nils Larsch* + + * Use SHA-1 instead of MD5 as the default digest algorithm for + the `apps/openssl` commands. + + *Nils Larsch* + + * Compile clean with "-Wall -Wmissing-prototypes + -Wstrict-prototypes -Wmissing-declarations -Werror". Currently + DEBUG_SAFESTACK must also be set. + + *Ben Laurie* + + * Change ./Configure so that certain algorithms can be disabled by default. + The new counterpiece to "no-xxx" is "enable-xxx". + + The patented RC5 and MDC2 algorithms will now be disabled unless + "enable-rc5" and "enable-mdc2", respectively, are specified. + + (IDEA remains enabled despite being patented. This is because IDEA + is frequently required for interoperability, and there is no license + fee for non-commercial use. As before, "no-idea" can be used to + avoid this algorithm.) + + *Bodo Moeller* + + * Add processing of proxy certificates (see RFC 3820). This work was + sponsored by KTH (The Royal Institute of Technology in Stockholm) and + EGEE (Enabling Grids for E-science in Europe). + + *Richard Levitte* + + * RC4 performance overhaul on modern architectures/implementations, such + as Intel P4, IA-64 and AMD64. + + *Andy Polyakov* + + * New utility extract-section.pl. This can be used specify an alternative + section number in a pod file instead of having to treat each file as + a separate case in Makefile. This can be done by adding two lines to the + pod file: + + =for comment openssl_section:XXX + + The blank line is mandatory. + + *Steve Henson* + + * New arguments -certform, -keyform and -pass for s_client and s_server + to allow alternative format key and certificate files and passphrase + sources. + + *Steve Henson* + + * New structure X509_VERIFY_PARAM which combines current verify parameters, + update associated structures and add various utility functions. + + Add new policy related verify parameters, include policy checking in + standard verify code. Enhance 'smime' application with extra parameters + to support policy checking and print out. + + *Steve Henson* + + * Add a new engine to support VIA PadLock ACE extensions in the VIA C3 + Nehemiah processors. These extensions support AES encryption in hardware + as well as RNG (though RNG support is currently disabled). + + *Michal Ludvig , with help from Andy Polyakov* + + * Deprecate `BN_[get|set]_params()` functions (they were ignored internally). + + *Geoff Thorpe* + + * New FIPS 180-2 algorithms, SHA-224/-256/-384/-512 are implemented. + + *Andy Polyakov and a number of other people* + + * Improved PowerPC platform support. Most notably BIGNUM assembler + implementation contributed by IBM. + + *Suresh Chari, Peter Waltenberg, Andy Polyakov* + + * The new 'RSA_generate_key_ex' function now takes a BIGNUM for the public + exponent rather than 'unsigned long'. There is a corresponding change to + the new 'rsa_keygen' element of the RSA_METHOD structure. + + *Jelte Jansen, Geoff Thorpe* + + * Functionality for creating the initial serial number file is now + moved from CA.pl to the 'ca' utility with a new option -create_serial. + + (Before OpenSSL 0.9.7e, CA.pl used to initialize the serial + number file to 1, which is bound to cause problems. To avoid + the problems while respecting compatibility between different 0.9.7 + patchlevels, 0.9.7e employed 'openssl x509 -next_serial' in + CA.pl for serial number initialization. With the new release 0.9.8, + we can fix the problem directly in the 'ca' utility.) + + *Steve Henson* + + * Reduced header interdependencies by declaring more opaque objects in + ossl_typ.h. As a consequence, including some headers (eg. engine.h) will + give fewer recursive includes, which could break lazy source code - so + this change is covered by the OPENSSL_NO_DEPRECATED symbol. As always, + developers should define this symbol when building and using openssl to + ensure they track the recommended behaviour, interfaces, [etc], but + backwards-compatible behaviour prevails when this isn't defined. + + *Geoff Thorpe* + + * New function X509_POLICY_NODE_print() which prints out policy nodes. + + *Steve Henson* + + * Add new EVP function EVP_CIPHER_CTX_rand_key and associated functionality. + This will generate a random key of the appropriate length based on the + cipher context. The EVP_CIPHER can provide its own random key generation + routine to support keys of a specific form. This is used in the des and + 3des routines to generate a key of the correct parity. Update S/MIME + code to use new functions and hence generate correct parity DES keys. + Add EVP_CHECK_DES_KEY #define to return an error if the key is not + valid (weak or incorrect parity). + + *Steve Henson* + + * Add a local set of CRLs that can be used by X509_verify_cert() as well + as looking them up. This is useful when the verified structure may contain + CRLs, for example PKCS#7 signedData. Modify PKCS7_verify() to use any CRLs + present unless the new PKCS7_NO_CRL flag is asserted. + + *Steve Henson* + + * Extend ASN1 oid configuration module. It now additionally accepts the + syntax: + + shortName = some long name, 1.2.3.4 + + *Steve Henson* + + * Reimplemented the BN_CTX implementation. There is now no more static + limitation on the number of variables it can handle nor the depth of the + "stack" handling for BN_CTX_start()/BN_CTX_end() pairs. The stack + information can now expand as required, and rather than having a single + static array of bignums, BN_CTX now uses a linked-list of such arrays + allowing it to expand on demand whilst maintaining the usefulness of + BN_CTX's "bundling". + + *Geoff Thorpe* + + * Add a missing BN_CTX parameter to the 'rsa_mod_exp' callback in RSA_METHOD + to allow all RSA operations to function using a single BN_CTX. + + *Geoff Thorpe* + + * Preliminary support for certificate policy evaluation and checking. This + is initially intended to pass the tests outlined in "Conformance Testing + of Relying Party Client Certificate Path Processing Logic" v1.07. + + *Steve Henson* + + * bn_dup_expand() has been deprecated, it was introduced in 0.9.7 and + remained unused and not that useful. A variety of other little bignum + tweaks and fixes have also been made continuing on from the audit (see + below). + + *Geoff Thorpe* + + * Constify all or almost all d2i, c2i, s2i and r2i functions, along with + associated ASN1, EVP and SSL functions and old ASN1 macros. + + *Richard Levitte* + + * BN_zero() only needs to set 'top' and 'neg' to zero for correct results, + and this should never fail. So the return value from the use of + BN_set_word() (which can fail due to needless expansion) is now deprecated; + if OPENSSL_NO_DEPRECATED is defined, BN_zero() is a void macro. + + *Geoff Thorpe* + + * BN_CTX_get() should return zero-valued bignums, providing the same + initialised value as BN_new(). + + *Geoff Thorpe, suggested by Ulf Möller* + + * Support for inhibitAnyPolicy certificate extension. + + *Steve Henson* + + * An audit of the BIGNUM code is underway, for which debugging code is + enabled when BN_DEBUG is defined. This makes stricter enforcements on what + is considered valid when processing BIGNUMs, and causes execution to + assert() when a problem is discovered. If BN_DEBUG_RAND is defined, + further steps are taken to deliberately pollute unused data in BIGNUM + structures to try and expose faulty code further on. For now, openssl will + (in its default mode of operation) continue to tolerate the inconsistent + forms that it has tolerated in the past, but authors and packagers should + consider trying openssl and their own applications when compiled with + these debugging symbols defined. It will help highlight potential bugs in + their own code, and will improve the test coverage for OpenSSL itself. At + some point, these tighter rules will become openssl's default to improve + maintainability, though the assert()s and other overheads will remain only + in debugging configurations. See bn.h for more details. + + *Geoff Thorpe, Nils Larsch, Ulf Möller* + + * BN_CTX_init() has been deprecated, as BN_CTX is an opaque structure + that can only be obtained through BN_CTX_new() (which implicitly + initialises it). The presence of this function only made it possible + to overwrite an existing structure (and cause memory leaks). + + *Geoff Thorpe* + + * Because of the callback-based approach for implementing LHASH as a + template type, lh_insert() adds opaque objects to hash-tables and + lh_doall() or lh_doall_arg() are typically used with a destructor callback + to clean up those corresponding objects before destroying the hash table + (and losing the object pointers). So some over-zealous constifications in + LHASH have been relaxed so that lh_insert() does not take (nor store) the + objects as "const" and the `lh_doall[_arg]` callback wrappers are not + prototyped to have "const" restrictions on the object pointers they are + given (and so aren't required to cast them away any more). + + *Geoff Thorpe* + + * The tmdiff.h API was so ugly and minimal that our own timing utility + (speed) prefers to use its own implementation. The two implementations + haven't been consolidated as yet (volunteers?) but the tmdiff API has had + its object type properly exposed (MS_TM) instead of casting to/from + `char *`. This may still change yet if someone realises MS_TM and + `ms_time_***` + aren't necessarily the greatest nomenclatures - but this is what was used + internally to the implementation so I've used that for now. + + *Geoff Thorpe* + + * Ensure that deprecated functions do not get compiled when + OPENSSL_NO_DEPRECATED is defined. Some "openssl" subcommands and a few of + the self-tests were still using deprecated key-generation functions so + these have been updated also. + + *Geoff Thorpe* + + * Reorganise PKCS#7 code to separate the digest location functionality + into PKCS7_find_digest(), digest addition into PKCS7_bio_add_digest(). + New function PKCS7_set_digest() to set the digest type for PKCS#7 + digestedData type. Add additional code to correctly generate the + digestedData type and add support for this type in PKCS7 initialization + functions. + + *Steve Henson* + + * New function PKCS7_set0_type_other() this initializes a PKCS7 + structure of type "other". + + *Steve Henson* + + * Fix prime generation loop in crypto/bn/bn_prime.pl by making + sure the loop does correctly stop and breaking ("division by zero") + modulus operations are not performed. The (pre-generated) prime + table crypto/bn/bn_prime.h was already correct, but it could not be + re-generated on some platforms because of the "division by zero" + situation in the script. + + *Ralf S. Engelschall* + + * Update support for ECC-based TLS ciphersuites according to + draft-ietf-tls-ecc-03.txt: the KDF1 key derivation function with + SHA-1 now is only used for "small" curves (where the + representation of a field element takes up to 24 bytes); for + larger curves, the field element resulting from ECDH is directly + used as premaster secret. + + *Douglas Stebila (Sun Microsystems Laboratories)* + + * Add code for kP+lQ timings to crypto/ec/ectest.c, and add SEC2 + curve secp160r1 to the tests. + + *Douglas Stebila (Sun Microsystems Laboratories)* + + * Add the possibility to load symbols globally with DSO. + + *Götz Babin-Ebell via Richard Levitte* + + * Add the functions ERR_set_mark() and ERR_pop_to_mark() for better + control of the error stack. + + *Richard Levitte* + + * Add support for STORE in ENGINE. + + *Richard Levitte* + + * Add the STORE type. The intention is to provide a common interface + to certificate and key stores, be they simple file-based stores, or + HSM-type store, or LDAP stores, or... + NOTE: The code is currently UNTESTED and isn't really used anywhere. + + *Richard Levitte* + + * Add a generic structure called OPENSSL_ITEM. This can be used to + pass a list of arguments to any function as well as provide a way + for a function to pass data back to the caller. + + *Richard Levitte* + + * Add the functions BUF_strndup() and BUF_memdup(). BUF_strndup() + works like BUF_strdup() but can be used to duplicate a portion of + a string. The copy gets NUL-terminated. BUF_memdup() duplicates + a memory area. + + *Richard Levitte* + + * Add the function sk_find_ex() which works like sk_find(), but will + return an index to an element even if an exact match couldn't be + found. The index is guaranteed to point at the element where the + searched-for key would be inserted to preserve sorting order. + + *Richard Levitte* + + * Add the function OBJ_bsearch_ex() which works like OBJ_bsearch() but + takes an extra flags argument for optional functionality. Currently, + the following flags are defined: + + OBJ_BSEARCH_VALUE_ON_NOMATCH + This one gets OBJ_bsearch_ex() to return a pointer to the first + element where the comparing function returns a negative or zero + number. + + OBJ_BSEARCH_FIRST_VALUE_ON_MATCH + This one gets OBJ_bsearch_ex() to return a pointer to the first + element where the comparing function returns zero. This is useful + if there are more than one element where the comparing function + returns zero. + + *Richard Levitte* + + * Make it possible to create self-signed certificates with 'openssl ca' + in such a way that the self-signed certificate becomes part of the + CA database and uses the same mechanisms for serial number generation + as all other certificate signing. The new flag '-selfsign' enables + this functionality. Adapt CA.sh and CA.pl.in. + + *Richard Levitte* + + * Add functionality to check the public key of a certificate request + against a given private. This is useful to check that a certificate + request can be signed by that key (self-signing). + + *Richard Levitte* + + * Make it possible to have multiple active certificates with the same + subject in the CA index file. This is done only if the keyword + 'unique_subject' is set to 'no' in the main CA section (default + if 'CA_default') of the configuration file. The value is saved + with the database itself in a separate index attribute file, + named like the index file with '.attr' appended to the name. + + *Richard Levitte* + + * Generate multi-valued AVAs using '+' notation in config files for + req and dirName. + + *Steve Henson* + + * Support for nameConstraints certificate extension. + + *Steve Henson* + + * Support for policyConstraints certificate extension. + + *Steve Henson* + + * Support for policyMappings certificate extension. + + *Steve Henson* + + * Make sure the default DSA_METHOD implementation only uses its + dsa_mod_exp() and/or bn_mod_exp() handlers if they are non-NULL, + and change its own handlers to be NULL so as to remove unnecessary + indirection. This lets alternative implementations fallback to the + default implementation more easily. + + *Geoff Thorpe* + + * Support for directoryName in GeneralName related extensions + in config files. + + *Steve Henson* + + * Make it possible to link applications using Makefile.shared. + Make that possible even when linking against static libraries! + + *Richard Levitte* + + * Support for single pass processing for S/MIME signing. This now + means that S/MIME signing can be done from a pipe, in addition + cleartext signing (multipart/signed type) is effectively streaming + and the signed data does not need to be all held in memory. + + This is done with a new flag PKCS7_STREAM. When this flag is set + PKCS7_sign() only initializes the PKCS7 structure and the actual signing + is done after the data is output (and digests calculated) in + SMIME_write_PKCS7(). + + *Steve Henson* + + * Add full support for -rpath/-R, both in shared libraries and + applications, at least on the platforms where it's known how + to do it. + + *Richard Levitte* + + * In crypto/ec/ec_mult.c, implement fast point multiplication with + precomputation, based on wNAF splitting: EC_GROUP_precompute_mult() + will now compute a table of multiples of the generator that + makes subsequent invocations of EC_POINTs_mul() or EC_POINT_mul() + faster (notably in the case of a single point multiplication, + scalar * generator). + + *Nils Larsch, Bodo Moeller* + + * IPv6 support for certificate extensions. The various extensions + which use the IP:a.b.c.d can now take IPv6 addresses using the + formats of RFC1884 2.2 . IPv6 addresses are now also displayed + correctly. + + *Steve Henson* + + * Added an ENGINE that implements RSA by performing private key + exponentiations with the GMP library. The conversions to and from + GMP's mpz_t format aren't optimised nor are any montgomery forms + cached, and on x86 it appears OpenSSL's own performance has caught up. + However there are likely to be other architectures where GMP could + provide a boost. This ENGINE is not built in by default, but it can be + specified at Configure time and should be accompanied by the necessary + linker additions, eg; + ./config -DOPENSSL_USE_GMP -lgmp + + *Geoff Thorpe* + + * "openssl engine" will not display ENGINE/DSO load failure errors when + testing availability of engines with "-t" - the old behaviour is + produced by increasing the feature's verbosity with "-tt". + + *Geoff Thorpe* + + * ECDSA routines: under certain error conditions uninitialized BN objects + could be freed. Solution: make sure initialization is performed early + enough. (Reported and fix supplied by Nils Larsch + via PR#459) + + *Lutz Jaenicke* + + * Key-generation can now be implemented in RSA_METHOD, DSA_METHOD + and DH_METHOD (eg. by ENGINE implementations) to override the normal + software implementations. For DSA and DH, parameter generation can + also be overridden by providing the appropriate method callbacks. + + *Geoff Thorpe* + + * Change the "progress" mechanism used in key-generation and + primality testing to functions that take a new BN_GENCB pointer in + place of callback/argument pairs. The new API functions have `_ex` + postfixes and the older functions are reimplemented as wrappers for + the new ones. The OPENSSL_NO_DEPRECATED symbol can be used to hide + declarations of the old functions to help (graceful) attempts to + migrate to the new functions. Also, the new key-generation API + functions operate on a caller-supplied key-structure and return + success/failure rather than returning a key or NULL - this is to + help make "keygen" another member function of RSA_METHOD etc. + + Example for using the new callback interface: + + int (*my_callback)(int a, int b, BN_GENCB *cb) = ...; + void *my_arg = ...; + BN_GENCB my_cb; + + BN_GENCB_set(&my_cb, my_callback, my_arg); + + return BN_is_prime_ex(some_bignum, BN_prime_checks, NULL, &cb); + /* For the meaning of a, b in calls to my_callback(), see the + * documentation of the function that calls the callback. + * cb will point to my_cb; my_arg can be retrieved as cb->arg. + * my_callback should return 1 if it wants BN_is_prime_ex() + * to continue, or 0 to stop. + */ + + *Geoff Thorpe* + + * Change the ZLIB compression method to be stateful, and make it + available to TLS with the number defined in + draft-ietf-tls-compression-04.txt. + + *Richard Levitte* + + * Add the ASN.1 structures and functions for CertificatePair, which + is defined as follows (according to X.509_4thEditionDraftV6.pdf): + + CertificatePair ::= SEQUENCE { + forward [0] Certificate OPTIONAL, + reverse [1] Certificate OPTIONAL, + -- at least one of the pair shall be present -- } + + Also implement the PEM functions to read and write certificate + pairs, and defined the PEM tag as "CERTIFICATE PAIR". + + This needed to be defined, mostly for the sake of the LDAP + attribute crossCertificatePair, but may prove useful elsewhere as + well. + + *Richard Levitte* + + * Make it possible to inhibit symlinking of shared libraries in + Makefile.shared, for Cygwin's sake. + + *Richard Levitte* + + * Extend the BIGNUM API by creating a function + void BN_set_negative(BIGNUM *a, int neg); + and a macro that behave like + int BN_is_negative(const BIGNUM *a); + + to avoid the need to access 'a->neg' directly in applications. + + *Nils Larsch* + + * Implement fast modular reduction for pseudo-Mersenne primes + used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c). + EC_GROUP_new_curve_GFp() will now automatically use this + if applicable. + + *Nils Larsch * + + * Add new lock type (CRYPTO_LOCK_BN). + + *Bodo Moeller* + + * Change the ENGINE framework to automatically load engines + dynamically from specific directories unless they could be + found to already be built in or loaded. Move all the + current engines except for the cryptodev one to a new + directory engines/. + The engines in engines/ are built as shared libraries if + the "shared" options was given to ./Configure or ./config. + Otherwise, they are inserted in libcrypto.a. + /usr/local/ssl/engines is the default directory for dynamic + engines, but that can be overridden at configure time through + the usual use of --prefix and/or --openssldir, and at run + time with the environment variable OPENSSL_ENGINES. + + *Geoff Thorpe and Richard Levitte* + + * Add Makefile.shared, a helper makefile to build shared + libraries. Adapt Makefile.org. + + *Richard Levitte* + + * Add version info to Win32 DLLs. + + *Peter 'Luna' Runestig" * + + * Add new 'medium level' PKCS#12 API. Certificates and keys + can be added using this API to created arbitrary PKCS#12 + files while avoiding the low-level API. + + New options to PKCS12_create(), key or cert can be NULL and + will then be omitted from the output file. The encryption + algorithm NIDs can be set to -1 for no encryption, the mac + iteration count can be set to 0 to omit the mac. + + Enhance pkcs12 utility by making the -nokeys and -nocerts + options work when creating a PKCS#12 file. New option -nomac + to omit the mac, NONE can be set for an encryption algorithm. + New code is modified to use the enhanced PKCS12_create() + instead of the low-level API. + + *Steve Henson* + + * Extend ASN1 encoder to support indefinite length constructed + encoding. This can output sequences tags and octet strings in + this form. Modify pk7_asn1.c to support indefinite length + encoding. This is experimental and needs additional code to + be useful, such as an ASN1 bio and some enhanced streaming + PKCS#7 code. + + Extend template encode functionality so that tagging is passed + down to the template encoder. + + *Steve Henson* + + * Let 'openssl req' fail if an argument to '-newkey' is not + recognized instead of using RSA as a default. + + *Bodo Moeller* + + * Add support for ECC-based ciphersuites from draft-ietf-tls-ecc-01.txt. + As these are not official, they are not included in "ALL"; + the "ECCdraft" ciphersuite group alias can be used to select them. + + *Vipul Gupta and Sumit Gupta (Sun Microsystems Laboratories)* + + * Add ECDH engine support. + + *Nils Gura and Douglas Stebila (Sun Microsystems Laboratories)* + + * Add ECDH in new directory crypto/ecdh/. + + *Douglas Stebila (Sun Microsystems Laboratories)* + + * Let BN_rand_range() abort with an error after 100 iterations + without success (which indicates a broken PRNG). + + *Bodo Moeller* + + * Change BN_mod_sqrt() so that it verifies that the input value + is really the square of the return value. (Previously, + BN_mod_sqrt would show GIGO behaviour.) + + *Bodo Moeller* + + * Add named elliptic curves over binary fields from X9.62, SECG, + and WAP/WTLS; add OIDs that were still missing. + + *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)* + + * Extend the EC library for elliptic curves over binary fields + (new files ec2_smpl.c, ec2_smpt.c, ec2_mult.c in crypto/ec/). + New EC_METHOD: + + EC_GF2m_simple_method + + New API functions: + + EC_GROUP_new_curve_GF2m + EC_GROUP_set_curve_GF2m + EC_GROUP_get_curve_GF2m + EC_POINT_set_affine_coordinates_GF2m + EC_POINT_get_affine_coordinates_GF2m + EC_POINT_set_compressed_coordinates_GF2m + + Point compression for binary fields is disabled by default for + patent reasons (compile with OPENSSL_EC_BIN_PT_COMP defined to + enable it). + + As binary polynomials are represented as BIGNUMs, various members + of the EC_GROUP and EC_POINT data structures can be shared + between the implementations for prime fields and binary fields; + the above `..._GF2m functions` (except for EX_GROUP_new_curve_GF2m) + are essentially identical to their `..._GFp` counterparts. + (For simplicity, the `..._GFp` prefix has been dropped from + various internal method names.) + + An internal 'field_div' method (similar to 'field_mul' and + 'field_sqr') has been added; this is used only for binary fields. + + *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)* + + * Optionally dispatch EC_POINT_mul(), EC_POINT_precompute_mult() + through methods ('mul', 'precompute_mult'). + + The generic implementations (now internally called 'ec_wNAF_mul' + and 'ec_wNAF_precomputed_mult') remain the default if these + methods are undefined. + + *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)* + + * New function EC_GROUP_get_degree, which is defined through + EC_METHOD. For curves over prime fields, this returns the bit + length of the modulus. + + *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)* + + * New functions EC_GROUP_dup, EC_POINT_dup. + (These simply call ..._new and ..._copy). + + *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)* + + * Add binary polynomial arithmetic software in crypto/bn/bn_gf2m.c. + Polynomials are represented as BIGNUMs (where the sign bit is not + used) in the following functions [macros]: + + BN_GF2m_add + BN_GF2m_sub [= BN_GF2m_add] + BN_GF2m_mod [wrapper for BN_GF2m_mod_arr] + BN_GF2m_mod_mul [wrapper for BN_GF2m_mod_mul_arr] + BN_GF2m_mod_sqr [wrapper for BN_GF2m_mod_sqr_arr] + BN_GF2m_mod_inv + BN_GF2m_mod_exp [wrapper for BN_GF2m_mod_exp_arr] + BN_GF2m_mod_sqrt [wrapper for BN_GF2m_mod_sqrt_arr] + BN_GF2m_mod_solve_quad [wrapper for BN_GF2m_mod_solve_quad_arr] + BN_GF2m_cmp [= BN_ucmp] + + (Note that only the 'mod' functions are actually for fields GF(2^m). + BN_GF2m_add() is misnomer, but this is for the sake of consistency.) + + For some functions, an the irreducible polynomial defining a + field can be given as an 'unsigned int[]' with strictly + decreasing elements giving the indices of those bits that are set; + i.e., p[] represents the polynomial + f(t) = t^p[0] + t^p[1] + ... + t^p[k] + where + p[0] > p[1] > ... > p[k] = 0. + This applies to the following functions: + + BN_GF2m_mod_arr + BN_GF2m_mod_mul_arr + BN_GF2m_mod_sqr_arr + BN_GF2m_mod_inv_arr [wrapper for BN_GF2m_mod_inv] + BN_GF2m_mod_div_arr [wrapper for BN_GF2m_mod_div] + BN_GF2m_mod_exp_arr + BN_GF2m_mod_sqrt_arr + BN_GF2m_mod_solve_quad_arr + BN_GF2m_poly2arr + BN_GF2m_arr2poly + + Conversion can be performed by the following functions: + + BN_GF2m_poly2arr + BN_GF2m_arr2poly + + bntest.c has additional tests for binary polynomial arithmetic. + + Two implementations for BN_GF2m_mod_div() are available. + The default algorithm simply uses BN_GF2m_mod_inv() and + BN_GF2m_mod_mul(). The alternative algorithm is compiled in only + if OPENSSL_SUN_GF2M_DIV is defined (patent pending; read the + copyright notice in crypto/bn/bn_gf2m.c before enabling it). + + *Sheueling Chang Shantz and Douglas Stebila (Sun Microsystems Laboratories)* + + * Add new error code 'ERR_R_DISABLED' that can be used when some + functionality is disabled at compile-time. + + *Douglas Stebila * + + * Change default behaviour of 'openssl asn1parse' so that more + information is visible when viewing, e.g., a certificate: + + Modify asn1_parse2 (crypto/asn1/asn1_par.c) so that in non-'dump' + mode the content of non-printable OCTET STRINGs is output in a + style similar to INTEGERs, but with '[HEX DUMP]' prepended to + avoid the appearance of a printable string. + + *Nils Larsch * + + * Add 'asn1_flag' and 'asn1_form' member to EC_GROUP with access + functions + EC_GROUP_set_asn1_flag() + EC_GROUP_get_asn1_flag() + EC_GROUP_set_point_conversion_form() + EC_GROUP_get_point_conversion_form() + These control ASN1 encoding details: + - Curves (i.e., groups) are encoded explicitly unless asn1_flag + has been set to OPENSSL_EC_NAMED_CURVE. + - Points are encoded in uncompressed form by default; options for + asn1_for are as for point2oct, namely + POINT_CONVERSION_COMPRESSED + POINT_CONVERSION_UNCOMPRESSED + POINT_CONVERSION_HYBRID + + Also add 'seed' and 'seed_len' members to EC_GROUP with access + functions + EC_GROUP_set_seed() + EC_GROUP_get0_seed() + EC_GROUP_get_seed_len() + This is used only for ASN1 purposes (so far). + + *Nils Larsch * + + * Add 'field_type' member to EC_METHOD, which holds the NID + of the appropriate field type OID. The new function + EC_METHOD_get_field_type() returns this value. + + *Nils Larsch * + + * Add functions + EC_POINT_point2bn() + EC_POINT_bn2point() + EC_POINT_point2hex() + EC_POINT_hex2point() + providing useful interfaces to EC_POINT_point2oct() and + EC_POINT_oct2point(). + + *Nils Larsch * + + * Change internals of the EC library so that the functions + EC_GROUP_set_generator() + EC_GROUP_get_generator() + EC_GROUP_get_order() + EC_GROUP_get_cofactor() + are implemented directly in crypto/ec/ec_lib.c and not dispatched + to methods, which would lead to unnecessary code duplication when + adding different types of curves. + + *Nils Larsch with input by Bodo Moeller* + + * Implement compute_wNAF (crypto/ec/ec_mult.c) without BIGNUM + arithmetic, and such that modified wNAFs are generated + (which avoid length expansion in many cases). + + *Bodo Moeller* + + * Add a function EC_GROUP_check_discriminant() (defined via + EC_METHOD) that verifies that the curve discriminant is non-zero. + + Add a function EC_GROUP_check() that makes some sanity tests + on a EC_GROUP, its generator and order. This includes + EC_GROUP_check_discriminant(). + + *Nils Larsch * + + * Add ECDSA in new directory crypto/ecdsa/. + + Add applications 'openssl ecparam' and 'openssl ecdsa' + (these are based on 'openssl dsaparam' and 'openssl dsa'). + + ECDSA support is also included in various other files across the + library. Most notably, + - 'openssl req' now has a '-newkey ecdsa:file' option; + - EVP_PKCS82PKEY (crypto/evp/evp_pkey.c) now can handle ECDSA; + - X509_PUBKEY_get (crypto/asn1/x_pubkey.c) and + d2i_PublicKey (crypto/asn1/d2i_pu.c) have been modified to make + them suitable for ECDSA where domain parameters must be + extracted before the specific public key; + - ECDSA engine support has been added. + + *Nils Larsch * + + * Include some named elliptic curves, and add OIDs from X9.62, + SECG, and WAP/WTLS. Each curve can be obtained from the new + function + EC_GROUP_new_by_curve_name(), + and the list of available named curves can be obtained with + EC_get_builtin_curves(). + Also add a 'curve_name' member to EC_GROUP objects, which can be + accessed via + EC_GROUP_set_curve_name() + EC_GROUP_get_curve_name() + + *Nils Larsch * + + * Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that + a ciphersuite string such as "DEFAULT:RSA" cannot enable + authentication-only ciphersuites. + + *Bodo Moeller* + + * Since AES128 and AES256 share a single mask bit in the logic of + ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a + kludge to work properly if AES128 is available and AES256 isn't. + + *Victor Duchovni* + + * Expand security boundary to match 1.1.1 module. + + *Steve Henson* + + * Remove redundant features: hash file source, editing of test vectors + modify fipsld to use external fips_premain.c signature. + + *Steve Henson* + + * New perl script mkfipsscr.pl to create shell scripts or batch files to + run algorithm test programs. + + *Steve Henson* + + * Make algorithm test programs more tolerant of whitespace. + + *Steve Henson* + + * Have SSL/TLS server implementation tolerate "mismatched" record + protocol version while receiving ClientHello even if the + ClientHello is fragmented. (The server can't insist on the + particular protocol version it has chosen before the ServerHello + message has informed the client about his choice.) + + *Bodo Moeller* + + * Load error codes if they are not already present instead of using a + static variable. This allows them to be cleanly unloaded and reloaded. + + *Steve Henson* + +### Changes between 0.9.7k and 0.9.7l [28 Sep 2006] + + * Introduce limits to prevent malicious keys being able to + cause a denial of service. ([CVE-2006-2940]) + + *Steve Henson, Bodo Moeller* + + * Fix ASN.1 parsing of certain invalid structures that can result + in a denial of service. ([CVE-2006-2937]) [Steve Henson] + + * Fix buffer overflow in SSL_get_shared_ciphers() function. + ([CVE-2006-3738]) [Tavis Ormandy and Will Drewry, Google Security Team] + + * Fix SSL client code which could crash if connecting to a + malicious SSLv2 server. ([CVE-2006-4343]) + + *Tavis Ormandy and Will Drewry, Google Security Team* + + * Change ciphersuite string processing so that an explicit + ciphersuite selects this one ciphersuite (so that "AES256-SHA" + will no longer include "AES128-SHA"), and any other similar + ciphersuite (same bitmap) from *other* protocol versions (so that + "RC4-MD5" will still include both the SSL 2.0 ciphersuite and the + SSL 3.0/TLS 1.0 ciphersuite). This is a backport combining + changes from 0.9.8b and 0.9.8d. + + *Bodo Moeller* + +### Changes between 0.9.7j and 0.9.7k [05 Sep 2006] + + * Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher + ([CVE-2006-4339]) [Ben Laurie and Google Security Team] + + * Change the Unix randomness entropy gathering to use poll() when + possible instead of select(), since the latter has some + undesirable limitations. + + *Darryl Miles via Richard Levitte and Bodo Moeller* + + * Disable rogue ciphersuites: + + - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5") + - SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5") + - SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5") + + The latter two were purportedly from + draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really + appear there. + + Also deactivate the remaining ciphersuites from + draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as + unofficial, and the ID has long expired. + + *Bodo Moeller* + + * Fix RSA blinding Heisenbug (problems sometimes occurred on + dual-core machines) and other potential thread-safety issues. + + *Bodo Moeller* + +### Changes between 0.9.7i and 0.9.7j [04 May 2006] + + * Adapt fipsld and the build system to link against the validated FIPS + module in FIPS mode. + + *Steve Henson* + + * Fixes for VC++ 2005 build under Windows. + + *Steve Henson* + + * Add new Windows build target VC-32-GMAKE for VC++. This uses GNU make + from a Windows bash shell such as MSYS. It is autodetected from the + "config" script when run from a VC++ environment. Modify standard VC++ + build to use fipscanister.o from the GNU make build. + + *Steve Henson* + +### Changes between 0.9.7h and 0.9.7i [14 Oct 2005] + + * Wrapped the definition of EVP_MAX_MD_SIZE in a #ifdef OPENSSL_FIPS. + The value now differs depending on if you build for FIPS or not. + BEWARE! A program linked with a shared FIPSed libcrypto can't be + safely run with a non-FIPSed libcrypto, as it may crash because of + the difference induced by this change. + + *Andy Polyakov* + +### Changes between 0.9.7g and 0.9.7h [11 Oct 2005] + + * Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING + (part of SSL_OP_ALL). This option used to disable the + countermeasure against man-in-the-middle protocol-version + rollback in the SSL 2.0 server implementation, which is a bad + idea. ([CVE-2005-2969]) + + *Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center + for Information Security, National Institute of Advanced Industrial + Science and Technology [AIST, Japan)]* + + * Minimal support for X9.31 signatures and PSS padding modes. This is + mainly for FIPS compliance and not fully integrated at this stage. + + *Steve Henson* + + * For DSA signing, unless DSA_FLAG_NO_EXP_CONSTTIME is set, perform + the exponentiation using a fixed-length exponent. (Otherwise, + the information leaked through timing could expose the secret key + after many signatures; cf. Bleichenbacher's attack on DSA with + biased k.) + + *Bodo Moeller* + + * Make a new fixed-window mod_exp implementation the default for + RSA, DSA, and DH private-key operations so that the sequence of + squares and multiplies and the memory access pattern are + independent of the particular secret key. This will mitigate + cache-timing and potential related attacks. + + BN_mod_exp_mont_consttime() is the new exponentiation implementation, + and this is automatically used by BN_mod_exp_mont() if the new flag + BN_FLG_EXP_CONSTTIME is set for the exponent. RSA, DSA, and DH + will use this BN flag for private exponents unless the flag + RSA_FLAG_NO_EXP_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME, or + DH_FLAG_NO_EXP_CONSTTIME, respectively, is set. + + *Matthew D Wood (Intel Corp), with some changes by Bodo Moeller* + + * Change the client implementation for SSLv23_method() and + SSLv23_client_method() so that is uses the SSL 3.0/TLS 1.0 + Client Hello message format if the SSL_OP_NO_SSLv2 option is set. + (Previously, the SSL 2.0 backwards compatible Client Hello + message format would be used even with SSL_OP_NO_SSLv2.) + + *Bodo Moeller* + + * Add support for smime-type MIME parameter in S/MIME messages which some + clients need. + + *Steve Henson* + + * New function BN_MONT_CTX_set_locked() to set montgomery parameters in + a threadsafe manner. Modify rsa code to use new function and add calls + to dsa and dh code (which had race conditions before). + + *Steve Henson* + + * Include the fixed error library code in the C error file definitions + instead of fixing them up at runtime. This keeps the error code + structures constant. + + *Steve Henson* + +### Changes between 0.9.7f and 0.9.7g [11 Apr 2005] + +[NB: OpenSSL 0.9.7h and later 0.9.7 patch levels were released after +OpenSSL 0.9.8.] + + * Fixes for newer kerberos headers. NB: the casts are needed because + the 'length' field is signed on one version and unsigned on another + with no (?) obvious way to tell the difference, without these VC++ + complains. Also the "definition" of FAR (blank) is no longer included + nor is the error ENOMEM. KRB5_PRIVATE has to be set to 1 to pick up + some needed definitions. + + *Steve Henson* + + * Undo Cygwin change. + + *Ulf Möller* + + * Added support for proxy certificates according to RFC 3820. + Because they may be a security thread to unaware applications, + they must be explicitly allowed in run-time. See + docs/HOWTO/proxy_certificates.txt for further information. + + *Richard Levitte* + +### Changes between 0.9.7e and 0.9.7f [22 Mar 2005] + + * Use (SSL_RANDOM_VALUE - 4) bytes of pseudo random data when generating + server and client random values. Previously + (SSL_RANDOM_VALUE - sizeof(time_t)) would be used which would result in + less random data when sizeof(time_t) > 4 (some 64 bit platforms). + + This change has negligible security impact because: + + 1. Server and client random values still have 24 bytes of pseudo random + data. + + 2. Server and client random values are sent in the clear in the initial + handshake. + + 3. The master secret is derived using the premaster secret (48 bytes in + size for static RSA ciphersuites) as well as client server and random + values. + + The OpenSSL team would like to thank the UK NISCC for bringing this issue + to our attention. + + *Stephen Henson, reported by UK NISCC* + + * Use Windows randomness collection on Cygwin. + + *Ulf Möller* + + * Fix hang in EGD/PRNGD query when communication socket is closed + prematurely by EGD/PRNGD. + + *Darren Tucker via Lutz Jänicke, resolves #1014* + + * Prompt for pass phrases when appropriate for PKCS12 input format. + + *Steve Henson* + + * Back-port of selected performance improvements from development + branch, as well as improved support for PowerPC platforms. + + *Andy Polyakov* + + * Add lots of checks for memory allocation failure, error codes to indicate + failure and freeing up memory if a failure occurs. + + *Nauticus Networks SSL Team , Steve Henson* + + * Add new -passin argument to dgst. + + *Steve Henson* + + * Perform some character comparisons of different types in X509_NAME_cmp: + this is needed for some certificates that re-encode DNs into UTF8Strings + (in violation of RFC3280) and can't or won't issue name rollover + certificates. + + *Steve Henson* + + * Make an explicit check during certificate validation to see that + the CA setting in each certificate on the chain is correct. As a + side effect always do the following basic checks on extensions, + not just when there's an associated purpose to the check: + + - if there is an unhandled critical extension (unless the user + has chosen to ignore this fault) + - if the path length has been exceeded (if one is set at all) + - that certain extensions fit the associated purpose (if one has + been given) + + *Richard Levitte* + +### Changes between 0.9.7d and 0.9.7e [25 Oct 2004] + + * Avoid a race condition when CRLs are checked in a multi threaded + environment. This would happen due to the reordering of the revoked + entries during signature checking and serial number lookup. Now the + encoding is cached and the serial number sort performed under a lock. + Add new STACK function sk_is_sorted(). + + *Steve Henson* + + * Add Delta CRL to the extension code. + + *Steve Henson* + + * Various fixes to s3_pkt.c so alerts are sent properly. + + *David Holmes * + + * Reduce the chances of duplicate issuer name and serial numbers (in + violation of RFC3280) using the OpenSSL certificate creation utilities. + This is done by creating a random 64 bit value for the initial serial + number when a serial number file is created or when a self signed + certificate is created using 'openssl req -x509'. The initial serial + number file is created using 'openssl x509 -next_serial' in CA.pl + rather than being initialized to 1. + + *Steve Henson* + +### Changes between 0.9.7c and 0.9.7d [17 Mar 2004] + + * Fix null-pointer assignment in do_change_cipher_spec() revealed + by using the Codenomicon TLS Test Tool ([CVE-2004-0079]) + + *Joe Orton, Steve Henson* + + * Fix flaw in SSL/TLS handshaking when using Kerberos ciphersuites + ([CVE-2004-0112]) + + *Joe Orton, Steve Henson* + + * Make it possible to have multiple active certificates with the same + subject in the CA index file. This is done only if the keyword + 'unique_subject' is set to 'no' in the main CA section (default + if 'CA_default') of the configuration file. The value is saved + with the database itself in a separate index attribute file, + named like the index file with '.attr' appended to the name. + + *Richard Levitte* + + * X509 verify fixes. Disable broken certificate workarounds when + X509_V_FLAGS_X509_STRICT is set. Check CRL issuer has cRLSign set if + keyUsage extension present. Don't accept CRLs with unhandled critical + extensions: since verify currently doesn't process CRL extensions this + rejects a CRL with *any* critical extensions. Add new verify error codes + for these cases. + + *Steve Henson* + + * When creating an OCSP nonce use an OCTET STRING inside the extnValue. + A clarification of RFC2560 will require the use of OCTET STRINGs and + some implementations cannot handle the current raw format. Since OpenSSL + copies and compares OCSP nonces as opaque blobs without any attempt at + parsing them this should not create any compatibility issues. + + *Steve Henson* + + * New md flag EVP_MD_CTX_FLAG_REUSE this allows md_data to be reused when + calling EVP_MD_CTX_copy_ex() to avoid calling OPENSSL_malloc(). Without + this HMAC (and other) operations are several times slower than OpenSSL + < 0.9.7. + + *Steve Henson* + + * Print out GeneralizedTime and UTCTime in ASN1_STRING_print_ex(). + + *Peter Sylvester * + + * Use the correct content when signing type "other". + + *Steve Henson* + +### Changes between 0.9.7b and 0.9.7c [30 Sep 2003] + + * Fix various bugs revealed by running the NISCC test suite: + + Stop out of bounds reads in the ASN1 code when presented with + invalid tags (CVE-2003-0543 and CVE-2003-0544). + + Free up ASN1_TYPE correctly if ANY type is invalid ([CVE-2003-0545]). + + If verify callback ignores invalid public key errors don't try to check + certificate signature with the NULL public key. + + *Steve Henson* + + * New -ignore_err option in ocsp application to stop the server + exiting on the first error in a request. + + *Steve Henson* + + * In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate + if the server requested one: as stated in TLS 1.0 and SSL 3.0 + specifications. + + *Steve Henson* + + * In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional + extra data after the compression methods not only for TLS 1.0 + but also for SSL 3.0 (as required by the specification). + + *Bodo Moeller; problem pointed out by Matthias Loepfe* + + * Change X509_certificate_type() to mark the key as exported/exportable + when it's 512 *bits* long, not 512 bytes. + + *Richard Levitte* + + * Change AES_cbc_encrypt() so it outputs exact multiple of + blocks during encryption. + + *Richard Levitte* + + * Various fixes to base64 BIO and non blocking I/O. On write + flushes were not handled properly if the BIO retried. On read + data was not being buffered properly and had various logic bugs. + This also affects blocking I/O when the data being decoded is a + certain size. + + *Steve Henson* + + * Various S/MIME bugfixes and compatibility changes: + output correct application/pkcs7 MIME type if + PKCS7_NOOLDMIMETYPE is set. Tolerate some broken signatures. + Output CR+LF for EOL if PKCS7_CRLFEOL is set (this makes opening + of files as .eml work). Correctly handle very long lines in MIME + parser. + + *Steve Henson* + +### Changes between 0.9.7a and 0.9.7b [10 Apr 2003] + + * Countermeasure against the Klima-Pokorny-Rosa extension of + Bleichbacher's attack on PKCS #1 v1.5 padding: treat + a protocol version number mismatch like a decryption error + in ssl3_get_client_key_exchange (ssl/s3_srvr.c). + + *Bodo Moeller* + + * Turn on RSA blinding by default in the default implementation + to avoid a timing attack. Applications that don't want it can call + RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING. + They would be ill-advised to do so in most cases. + + *Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller* + + * Change RSA blinding code so that it works when the PRNG is not + seeded (in this case, the secret RSA exponent is abused as + an unpredictable seed -- if it is not unpredictable, there + is no point in blinding anyway). Make RSA blinding thread-safe + by remembering the creator's thread ID in rsa->blinding and + having all other threads use local one-time blinding factors + (this requires more computation than sharing rsa->blinding, but + avoids excessive locking; and if an RSA object is not shared + between threads, blinding will still be very fast). + + *Bodo Moeller* + + * Fixed a typo bug that would cause ENGINE_set_default() to set an + ENGINE as defaults for all supported algorithms irrespective of + the 'flags' parameter. 'flags' is now honoured, so applications + should make sure they are passing it correctly. + + *Geoff Thorpe* + + * Target "mingw" now allows native Windows code to be generated in + the Cygwin environment as well as with the MinGW compiler. + + *Ulf Moeller* + +### Changes between 0.9.7 and 0.9.7a [19 Feb 2003] + + * In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked + via timing by performing a MAC computation even if incorrect + block cipher padding has been found. This is a countermeasure + against active attacks where the attacker has to distinguish + between bad padding and a MAC verification error. ([CVE-2003-0078]) + + *Bodo Moeller; problem pointed out by Brice Canvel (EPFL), + Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and + Martin Vuagnoux (EPFL, Ilion)* + + * Make the no-err option work as intended. The intention with no-err + is not to have the whole error stack handling routines removed from + libcrypto, it's only intended to remove all the function name and + reason texts, thereby removing some of the footprint that may not + be interesting if those errors aren't displayed anyway. + + NOTE: it's still possible for any application or module to have its + own set of error texts inserted. The routines are there, just not + used by default when no-err is given. + + *Richard Levitte* + + * Add support for FreeBSD on IA64. + + *dirk.meyer@dinoex.sub.org via Richard Levitte, resolves #454* + + * Adjust DES_cbc_cksum() so it returns the same value as the MIT + Kerberos function mit_des_cbc_cksum(). Before this change, + the value returned by DES_cbc_cksum() was like the one from + mit_des_cbc_cksum(), except the bytes were swapped. + + *Kevin Greaney and Richard Levitte* + + * Allow an application to disable the automatic SSL chain building. + Before this a rather primitive chain build was always performed in + ssl3_output_cert_chain(): an application had no way to send the + correct chain if the automatic operation produced an incorrect result. + + Now the chain builder is disabled if either: + + 1. Extra certificates are added via SSL_CTX_add_extra_chain_cert(). + + 2. The mode flag SSL_MODE_NO_AUTO_CHAIN is set. + + The reasoning behind this is that an application would not want the + auto chain building to take place if extra chain certificates are + present and it might also want a means of sending no additional + certificates (for example the chain has two certificates and the + root is omitted). + + *Steve Henson* + + * Add the possibility to build without the ENGINE framework. + + *Steven Reddie via Richard Levitte* + + * Under Win32 gmtime() can return NULL: check return value in + OPENSSL_gmtime(). Add error code for case where gmtime() fails. + + *Steve Henson* + + * DSA routines: under certain error conditions uninitialized BN objects + could be freed. Solution: make sure initialization is performed early + enough. (Reported and fix supplied by Ivan D Nestlerode , + Nils Larsch via PR#459) + + *Lutz Jaenicke* + + * Another fix for SSLv2 session ID handling: the session ID was incorrectly + checked on reconnect on the client side, therefore session resumption + could still fail with a "ssl session id is different" error. This + behaviour is masked when SSL_OP_ALL is used due to + SSL_OP_MICROSOFT_SESS_ID_BUG being set. + Behaviour observed by Crispin Flowerday as + followup to PR #377. + + *Lutz Jaenicke* + + * IA-32 assembler support enhancements: unified ELF targets, support + for SCO/Caldera platforms, fix for Cygwin shared build. + + *Andy Polyakov* + + * Add support for FreeBSD on sparc64. As a consequence, support for + FreeBSD on non-x86 processors is separate from x86 processors on + the config script, much like the NetBSD support. + + *Richard Levitte & Kris Kennaway * + +### Changes between 0.9.6h and 0.9.7 [31 Dec 2002] + +[NB: OpenSSL 0.9.6i and later 0.9.6 patch levels were released after +OpenSSL 0.9.7.] + + * Fix session ID handling in SSLv2 client code: the SERVER FINISHED + code (06) was taken as the first octet of the session ID and the last + octet was ignored consequently. As a result SSLv2 client side session + caching could not have worked due to the session ID mismatch between + client and server. + Behaviour observed by Crispin Flowerday as + PR #377. + + *Lutz Jaenicke* + + * Change the declaration of needed Kerberos libraries to use EX_LIBS + instead of the special (and badly supported) LIBKRB5. LIBKRB5 is + removed entirely. + + *Richard Levitte* + + * The hw_ncipher.c engine requires dynamic locks. Unfortunately, it + seems that in spite of existing for more than a year, many application + author have done nothing to provide the necessary callbacks, which + means that this particular engine will not work properly anywhere. + This is a very unfortunate situation which forces us, in the name + of usability, to give the hw_ncipher.c a static lock, which is part + of libcrypto. + NOTE: This is for the 0.9.7 series ONLY. This hack will never + appear in 0.9.8 or later. We EXPECT application authors to have + dealt properly with this when 0.9.8 is released (unless we actually + make such changes in the libcrypto locking code that changes will + have to be made anyway). + + *Richard Levitte* + + * In asn1_d2i_read_bio() repeatedly call BIO_read() until all content + octets have been read, EOF or an error occurs. Without this change + some truncated ASN1 structures will not produce an error. + + *Steve Henson* + + * Disable Heimdal support, since it hasn't been fully implemented. + Still give the possibility to force the use of Heimdal, but with + warnings and a request that patches get sent to openssl-dev. + + *Richard Levitte* + + * Add the VC-CE target, introduce the WINCE sysname, and add + INSTALL.WCE and appropriate conditionals to make it build. + + *Steven Reddie via Richard Levitte* + + * Change the DLL names for Cygwin to cygcrypto-x.y.z.dll and + cygssl-x.y.z.dll, where x, y and z are the major, minor and + edit numbers of the version. + + *Corinna Vinschen and Richard Levitte* + + * Introduce safe string copy and catenation functions + (BUF_strlcpy() and BUF_strlcat()). + + *Ben Laurie (CHATS) and Richard Levitte* + + * Avoid using fixed-size buffers for one-line DNs. + + *Ben Laurie (CHATS)* + + * Add BUF_MEM_grow_clean() to avoid information leakage when + resizing buffers containing secrets, and use where appropriate. + + *Ben Laurie (CHATS)* + + * Avoid using fixed size buffers for configuration file location. + + *Ben Laurie (CHATS)* + + * Avoid filename truncation for various CA files. + + *Ben Laurie (CHATS)* + + * Use sizeof in preference to magic numbers. + + *Ben Laurie (CHATS)* + + * Avoid filename truncation in cert requests. + + *Ben Laurie (CHATS)* + + * Add assertions to check for (supposedly impossible) buffer + overflows. + + *Ben Laurie (CHATS)* + + * Don't cache truncated DNS entries in the local cache (this could + potentially lead to a spoofing attack). + + *Ben Laurie (CHATS)* + + * Fix various buffers to be large enough for hex/decimal + representations in a platform independent manner. + + *Ben Laurie (CHATS)* + + * Add CRYPTO_realloc_clean() to avoid information leakage when + resizing buffers containing secrets, and use where appropriate. + + *Ben Laurie (CHATS)* + + * Add BIO_indent() to avoid much slightly worrying code to do + indents. + + *Ben Laurie (CHATS)* + + * Convert sprintf()/BIO_puts() to BIO_printf(). + + *Ben Laurie (CHATS)* + + * buffer_gets() could terminate with the buffer only half + full. Fixed. + + *Ben Laurie (CHATS)* + + * Add assertions to prevent user-supplied crypto functions from + overflowing internal buffers by having large block sizes, etc. + + *Ben Laurie (CHATS)* + + * New OPENSSL_assert() macro (similar to assert(), but enabled + unconditionally). + + *Ben Laurie (CHATS)* + + * Eliminate unused copy of key in RC4. + + *Ben Laurie (CHATS)* + + * Eliminate unused and incorrectly sized buffers for IV in pem.h. + + *Ben Laurie (CHATS)* + + * Fix off-by-one error in EGD path. + + *Ben Laurie (CHATS)* + + * If RANDFILE path is too long, ignore instead of truncating. + + *Ben Laurie (CHATS)* + + * Eliminate unused and incorrectly sized X.509 structure + CBCParameter. + + *Ben Laurie (CHATS)* + + * Eliminate unused and dangerous function knumber(). + + *Ben Laurie (CHATS)* + + * Eliminate unused and dangerous structure, KSSL_ERR. + + *Ben Laurie (CHATS)* + + * Protect against overlong session ID context length in an encoded + session object. Since these are local, this does not appear to be + exploitable. + + *Ben Laurie (CHATS)* + + * Change from security patch (see 0.9.6e below) that did not affect + the 0.9.6 release series: + + Remote buffer overflow in SSL3 protocol - an attacker could + supply an oversized master key in Kerberos-enabled versions. + ([CVE-2002-0657]) + + *Ben Laurie (CHATS)* + + * Change the SSL kerb5 codes to match RFC 2712. + + *Richard Levitte* + + * Make -nameopt work fully for req and add -reqopt switch. + + *Michael Bell , Steve Henson* + + * The "block size" for block ciphers in CFB and OFB mode should be 1. + + *Steve Henson, reported by Yngve Nysaeter Pettersen * + + * Make sure tests can be performed even if the corresponding algorithms + have been removed entirely. This was also the last step to make + OpenSSL compilable with DJGPP under all reasonable conditions. + + *Richard Levitte, Doug Kaufman * + + * Add cipher selection rules COMPLEMENTOFALL and COMPLEMENTOFDEFAULT + to allow version independent disabling of normally unselected ciphers, + which may be activated as a side-effect of selecting a single cipher. + + (E.g., cipher list string "RSA" enables ciphersuites that are left + out of "ALL" because they do not provide symmetric encryption. + "RSA:!COMPLEMEMENTOFALL" avoids these unsafe ciphersuites.) + + *Lutz Jaenicke, Bodo Moeller* + + * Add appropriate support for separate platform-dependent build + directories. The recommended way to make a platform-dependent + build directory is the following (tested on Linux), maybe with + some local tweaks: + + # Place yourself outside of the OpenSSL source tree. In + # this example, the environment variable OPENSSL_SOURCE + # is assumed to contain the absolute OpenSSL source directory. + mkdir -p objtree/"`uname -s`-`uname -r`-`uname -m`" + cd objtree/"`uname -s`-`uname -r`-`uname -m`" + (cd $OPENSSL_SOURCE; find . -type f) | while read F; do + mkdir -p `dirname $F` + ln -s $OPENSSL_SOURCE/$F $F + done + + To be absolutely sure not to disturb the source tree, a "make clean" + is a good thing. If it isn't successful, don't worry about it, + it probably means the source directory is very clean. + + *Richard Levitte* + + * Make sure any ENGINE control commands make local copies of string + pointers passed to them whenever necessary. Otherwise it is possible + the caller may have overwritten (or deallocated) the original string + data when a later ENGINE operation tries to use the stored values. + + *Götz Babin-Ebell * + + * Improve diagnostics in file reading and command-line digests. + + *Ben Laurie aided and abetted by Solar Designer * + + * Add AES modes CFB and OFB to the object database. Correct an + error in AES-CFB decryption. + + *Richard Levitte* + + * Remove most calls to EVP_CIPHER_CTX_cleanup() in evp_enc.c, this + allows existing EVP_CIPHER_CTX structures to be reused after + calling `EVP_*Final()`. This behaviour is used by encryption + BIOs and some applications. This has the side effect that + applications must explicitly clean up cipher contexts with + EVP_CIPHER_CTX_cleanup() or they will leak memory. + + *Steve Henson* + + * Check the values of dna and dnb in bn_mul_recursive before calling + bn_mul_comba (a non zero value means the a or b arrays do not contain + n2 elements) and fallback to bn_mul_normal if either is not zero. + + *Steve Henson* + + * Fix escaping of non-ASCII characters when using the -subj option + of the "openssl req" command line tool. (Robert Joop ) + + *Lutz Jaenicke* + + * Make object definitions compliant to LDAP (RFC2256): SN is the short + form for "surname", serialNumber has no short form. + Use "mail" as the short name for "rfc822Mailbox" according to RFC2798; + therefore remove "mail" short name for "internet 7". + The OID for unique identifiers in X509 certificates is + x500UniqueIdentifier, not uniqueIdentifier. + Some more OID additions. (Michael Bell ) + + *Lutz Jaenicke* + + * Add an "init" command to the ENGINE config module and auto initialize + ENGINEs. Without any "init" command the ENGINE will be initialized + after all ctrl commands have been executed on it. If init=1 the + ENGINE is initialized at that point (ctrls before that point are run + on the uninitialized ENGINE and after on the initialized one). If + init=0 then the ENGINE will not be initialized at all. + + *Steve Henson* + + * Fix the 'app_verify_callback' interface so that the user-defined + argument is actually passed to the callback: In the + SSL_CTX_set_cert_verify_callback() prototype, the callback + declaration has been changed from + int (*cb)() + into + int (*cb)(X509_STORE_CTX *,void *); + in ssl_verify_cert_chain (ssl/ssl_cert.c), the call + i=s->ctx->app_verify_callback(&ctx) + has been changed into + i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg). + + To update applications using SSL_CTX_set_cert_verify_callback(), + a dummy argument can be added to their callback functions. + + *D. K. Smetters * + + * Added the '4758cca' ENGINE to support IBM 4758 cards. + + *Maurice Gittens , touchups by Geoff Thorpe* + + * Add and OPENSSL_LOAD_CONF define which will cause + OpenSSL_add_all_algorithms() to load the openssl.cnf config file. + This allows older applications to transparently support certain + OpenSSL features: such as crypto acceleration and dynamic ENGINE loading. + Two new functions OPENSSL_add_all_algorithms_noconf() which will never + load the config file and OPENSSL_add_all_algorithms_conf() which will + always load it have also been added. + + *Steve Henson* + + * Add the OFB, CFB and CTR (all with 128 bit feedback) to AES. + Adjust NIDs and EVP layer. + + *Stephen Sprunk and Richard Levitte* + + * Config modules support in openssl utility. + + Most commands now load modules from the config file, + though in a few (such as version) this isn't done + because it couldn't be used for anything. + + In the case of ca and req the config file used is + the same as the utility itself: that is the -config + command line option can be used to specify an + alternative file. + + *Steve Henson* + + * Move default behaviour from OPENSSL_config(). If appname is NULL + use "openssl_conf" if filename is NULL use default openssl config file. + + *Steve Henson* + + * Add an argument to OPENSSL_config() to allow the use of an alternative + config section name. Add a new flag to tolerate a missing config file + and move code to CONF_modules_load_file(). + + *Steve Henson* + + * Support for crypto accelerator cards from Accelerated Encryption + Processing, www.aep.ie. (Use engine 'aep') + The support was copied from 0.9.6c [engine] and adapted/corrected + to work with the new engine framework. + + *AEP Inc. and Richard Levitte* + + * Support for SureWare crypto accelerator cards from Baltimore + Technologies. (Use engine 'sureware') + The support was copied from 0.9.6c [engine] and adapted + to work with the new engine framework. + + *Richard Levitte* + + * Have the CHIL engine fork-safe (as defined by nCipher) and actually + make the newer ENGINE framework commands for the CHIL engine work. + + *Toomas Kiisk and Richard Levitte* + + * Make it possible to produce shared libraries on ReliantUNIX. + + *Robert Dahlem via Richard Levitte* + + * Add the configuration target debug-linux-ppro. + Make 'openssl rsa' use the general key loading routines + implemented in `apps.c`, and make those routines able to + handle the key format FORMAT_NETSCAPE and the variant + FORMAT_IISSGC. + + *Toomas Kiisk via Richard Levitte* + + * Fix a crashbug and a logic bug in hwcrhk_load_pubkey(). + + *Toomas Kiisk via Richard Levitte* + + * Add -keyform to rsautl, and document -engine. + + *Richard Levitte, inspired by Toomas Kiisk * + + * Change BIO_new_file (crypto/bio/bss_file.c) to use new + BIO_R_NO_SUCH_FILE error code rather than the generic + ERR_R_SYS_LIB error code if fopen() fails with ENOENT. + + *Ben Laurie* + + * Add new functions + ERR_peek_last_error + ERR_peek_last_error_line + ERR_peek_last_error_line_data. + These are similar to + ERR_peek_error + ERR_peek_error_line + ERR_peek_error_line_data, + but report on the latest error recorded rather than the first one + still in the error queue. + + *Ben Laurie, Bodo Moeller* + + * default_algorithms option in ENGINE config module. This allows things + like: + default_algorithms = ALL + default_algorithms = RSA, DSA, RAND, CIPHERS, DIGESTS + + *Steve Henson* + + * Preliminary ENGINE config module. + + *Steve Henson* + + * New experimental application configuration code. + + *Steve Henson* + + * Change the AES code to follow the same name structure as all other + symmetric ciphers, and behave the same way. Move everything to + the directory crypto/aes, thereby obsoleting crypto/rijndael. + + *Stephen Sprunk and Richard Levitte* + + * SECURITY: remove unsafe setjmp/signal interaction from ui_openssl.c. + + *Ben Laurie and Theo de Raadt* + + * Add option to output public keys in req command. + + *Massimiliano Pala madwolf@openca.org* + + * Use wNAFs in EC_POINTs_mul() for improved efficiency + (up to about 10% better than before for P-192 and P-224). + + *Bodo Moeller* + + * New functions/macros + + SSL_CTX_set_msg_callback(ctx, cb) + SSL_CTX_set_msg_callback_arg(ctx, arg) + SSL_set_msg_callback(ssl, cb) + SSL_set_msg_callback_arg(ssl, arg) + + to request calling a callback function + + void cb(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg) + + whenever a protocol message has been completely received + (write_p == 0) or sent (write_p == 1). Here 'version' is the + protocol version according to which the SSL library interprets + the current protocol message (SSL2_VERSION, SSL3_VERSION, or + TLS1_VERSION). 'content_type' is 0 in the case of SSL 2.0, or + the content type as defined in the SSL 3.0/TLS 1.0 protocol + specification (change_cipher_spec(20), alert(21), handshake(22)). + 'buf' and 'len' point to the actual message, 'ssl' to the + SSL object, and 'arg' is the application-defined value set by + SSL[_CTX]_set_msg_callback_arg(). + + 'openssl s_client' and 'openssl s_server' have new '-msg' options + to enable a callback that displays all protocol messages. + + *Bodo Moeller* + + * Change the shared library support so shared libraries are built as + soon as the corresponding static library is finished, and thereby get + openssl and the test programs linked against the shared library. + This still only happens when the keyword "shard" has been given to + the configuration scripts. + + NOTE: shared library support is still an experimental thing, and + backward binary compatibility is still not guaranteed. + + *"Maciej W. Rozycki" and Richard Levitte* + + * Add support for Subject Information Access extension. + + *Peter Sylvester * + + * Make BUF_MEM_grow() behaviour more consistent: Initialise to zero + additional bytes when new memory had to be allocated, not just + when reusing an existing buffer. + + *Bodo Moeller* + + * New command line and configuration option 'utf8' for the req command. + This allows field values to be specified as UTF8 strings. + + *Steve Henson* + + * Add -multi and -mr options to "openssl speed" - giving multiple parallel + runs for the former and machine-readable output for the latter. + + *Ben Laurie* + + * Add '-noemailDN' option to 'openssl ca'. This prevents inclusion + of the e-mail address in the DN (i.e., it will go into a certificate + extension only). The new configuration file option 'email_in_dn = no' + has the same effect. + + *Massimiliano Pala madwolf@openca.org* + + * Change all functions with names starting with `des_` to be starting + with `DES_` instead. Add wrappers that are compatible with libdes, + but are named `_ossl_old_des_*`. Finally, add macros that map the + `des_*` symbols to the corresponding `_ossl_old_des_*` if libdes + compatibility is desired. If OpenSSL 0.9.6c compatibility is + desired, the `des_*` symbols will be mapped to `DES_*`, with one + exception. + + Since we provide two compatibility mappings, the user needs to + define the macro OPENSSL_DES_LIBDES_COMPATIBILITY if libdes + compatibility is desired. The default (i.e., when that macro + isn't defined) is OpenSSL 0.9.6c compatibility. + + There are also macros that enable and disable the support of old + des functions altogether. Those are OPENSSL_ENABLE_OLD_DES_SUPPORT + and OPENSSL_DISABLE_OLD_DES_SUPPORT. If none or both of those + are defined, the default will apply: to support the old des routines. + + In either case, one must include openssl/des.h to get the correct + definitions. Do not try to just include openssl/des_old.h, that + won't work. + + NOTE: This is a major break of an old API into a new one. Software + authors are encouraged to switch to the `DES_` style functions. Some + time in the future, des_old.h and the libdes compatibility functions + will be disable (i.e. OPENSSL_DISABLE_OLD_DES_SUPPORT will be the + default), and then completely removed. + + *Richard Levitte* + + * Test for certificates which contain unsupported critical extensions. + If such a certificate is found during a verify operation it is + rejected by default: this behaviour can be overridden by either + handling the new error X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION or + by setting the verify flag X509_V_FLAG_IGNORE_CRITICAL. A new function + X509_supported_extension() has also been added which returns 1 if a + particular extension is supported. + + *Steve Henson* + + * Modify the behaviour of EVP cipher functions in similar way to digests + to retain compatibility with existing code. + + *Steve Henson* + + * Modify the behaviour of EVP_DigestInit() and EVP_DigestFinal() to retain + compatibility with existing code. In particular the 'ctx' parameter does + not have to be to be initialized before the call to EVP_DigestInit() and + it is tidied up after a call to EVP_DigestFinal(). New function + EVP_DigestFinal_ex() which does not tidy up the ctx. Similarly function + EVP_MD_CTX_copy() changed to not require the destination to be + initialized valid and new function EVP_MD_CTX_copy_ex() added which + requires the destination to be valid. + + Modify all the OpenSSL digest calls to use EVP_DigestInit_ex(), + EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex(). + + *Steve Henson* + + * Change ssl3_get_message (ssl/s3_both.c) and the functions using it + so that complete 'Handshake' protocol structures are kept in memory + instead of overwriting 'msg_type' and 'length' with 'body' data. + + *Bodo Moeller* + + * Add an implementation of SSL_add_dir_cert_subjects_to_stack for Win32. + + *Massimo Santin via Richard Levitte* + + * Major restructuring to the underlying ENGINE code. This includes + reduction of linker bloat, separation of pure "ENGINE" manipulation + (initialisation, etc) from functionality dealing with implementations + of specific crypto interfaces. This change also introduces integrated + support for symmetric ciphers and digest implementations - so ENGINEs + can now accelerate these by providing EVP_CIPHER and EVP_MD + implementations of their own. This is detailed in + [crypto/engine/README.md](crypto/engine/README.md) + as it couldn't be adequately described here. However, there are a few + API changes worth noting - some RSA, DSA, DH, and RAND functions that + were changed in the original introduction of ENGINE code have now + reverted back - the hooking from this code to ENGINE is now a good + deal more passive and at run-time, operations deal directly with + RSA_METHODs, DSA_METHODs (etc) as they did before, rather than + dereferencing through an ENGINE pointer any more. Also, the ENGINE + functions dealing with `BN_MOD_EXP[_CRT]` handlers have been removed - + they were not being used by the framework as there is no concept of a + BIGNUM_METHOD and they could not be generalised to the new + 'ENGINE_TABLE' mechanism that underlies the new code. Similarly, + ENGINE_cpy() has been removed as it cannot be consistently defined in + the new code. + + *Geoff Thorpe* + + * Change ASN1_GENERALIZEDTIME_check() to allow fractional seconds. + + *Steve Henson* + + * Change mkdef.pl to sort symbols that get the same entry number, + and make sure the automatically generated functions `ERR_load_*` + become part of libeay.num as well. + + *Richard Levitte* + + * New function SSL_renegotiate_pending(). This returns true once + renegotiation has been requested (either SSL_renegotiate() call + or HelloRequest/ClientHello received from the peer) and becomes + false once a handshake has been completed. + (For servers, SSL_renegotiate() followed by SSL_do_handshake() + sends a HelloRequest, but does not ensure that a handshake takes + place. SSL_renegotiate_pending() is useful for checking if the + client has followed the request.) + + *Bodo Moeller* + + * New SSL option SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION. + By default, clients may request session resumption even during + renegotiation (if session ID contexts permit); with this option, + session resumption is possible only in the first handshake. + + SSL_OP_ALL is now 0x00000FFFL instead of 0x000FFFFFL. This makes + more bits available for options that should not be part of + SSL_OP_ALL (such as SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION). + + *Bodo Moeller* + + * Add some demos for certificate and certificate request creation. + + *Steve Henson* + + * Make maximum certificate chain size accepted from the peer application + settable (`SSL*_get/set_max_cert_list()`), as proposed by + "Douglas E. Engert" . + + *Lutz Jaenicke* + + * Add support for shared libraries for Unixware-7 + (Boyd Lynn Gerber ). + + *Lutz Jaenicke* + + * Add a "destroy" handler to ENGINEs that allows structural cleanup to + be done prior to destruction. Use this to unload error strings from + ENGINEs that load their own error strings. NB: This adds two new API + functions to "get" and "set" this destroy handler in an ENGINE. + + *Geoff Thorpe* + + * Alter all existing ENGINE implementations (except "openssl" and + "openbsd") to dynamically instantiate their own error strings. This + makes them more flexible to be built both as statically-linked ENGINEs + and self-contained shared-libraries loadable via the "dynamic" ENGINE. + Also, add stub code to each that makes building them as self-contained + shared-libraries easier (see [README-Engine.md](README-Engine.md)). + + *Geoff Thorpe* + + * Add a "dynamic" ENGINE that provides a mechanism for binding ENGINE + implementations into applications that are completely implemented in + self-contained shared-libraries. The "dynamic" ENGINE exposes control + commands that can be used to configure what shared-library to load and + to control aspects of the way it is handled. Also, made an update to + the [README-Engine.md](README-Engine.md) file + that brings its information up-to-date and + provides some information and instructions on the "dynamic" ENGINE + (ie. how to use it, how to build "dynamic"-loadable ENGINEs, etc). + + *Geoff Thorpe* + + * Make it possible to unload ranges of ERR strings with a new + "ERR_unload_strings" function. + + *Geoff Thorpe* + + * Add a copy() function to EVP_MD. + + *Ben Laurie* + + * Make EVP_MD routines take a context pointer instead of just the + md_data void pointer. + + *Ben Laurie* + + * Add flags to EVP_MD and EVP_MD_CTX. EVP_MD_FLAG_ONESHOT indicates + that the digest can only process a single chunk of data + (typically because it is provided by a piece of + hardware). EVP_MD_CTX_FLAG_ONESHOT indicates that the application + is only going to provide a single chunk of data, and hence the + framework needn't accumulate the data for oneshot drivers. + + *Ben Laurie* + + * As with "ERR", make it possible to replace the underlying "ex_data" + functions. This change also alters the storage and management of global + ex_data state - it's now all inside ex_data.c and all "class" code (eg. + RSA, BIO, SSL_CTX, etc) no longer stores its own STACKS and per-class + index counters. The API functions that use this state have been changed + to take a "class_index" rather than pointers to the class's local STACK + and counter, and there is now an API function to dynamically create new + classes. This centralisation allows us to (a) plug a lot of the + thread-safety problems that existed, and (b) makes it possible to clean + up all allocated state using "CRYPTO_cleanup_all_ex_data()". W.r.t. (b) + such data would previously have always leaked in application code and + workarounds were in place to make the memory debugging turn a blind eye + to it. Application code that doesn't use this new function will still + leak as before, but their memory debugging output will announce it now + rather than letting it slide. + + Besides the addition of CRYPTO_cleanup_all_ex_data(), another API change + induced by the "ex_data" overhaul is that X509_STORE_CTX_init() now + has a return value to indicate success or failure. + + *Geoff Thorpe* + + * Make it possible to replace the underlying "ERR" functions such that the + global state (2 LHASH tables and 2 locks) is only used by the "default" + implementation. This change also adds two functions to "get" and "set" + the implementation prior to it being automatically set the first time + any other ERR function takes place. Ie. an application can call "get", + pass the return value to a module it has just loaded, and that module + can call its own "set" function using that value. This means the + module's "ERR" operations will use (and modify) the error state in the + application and not in its own statically linked copy of OpenSSL code. + + *Geoff Thorpe* + + * Give DH, DSA, and RSA types their own `*_up_ref()` function to increment + reference counts. This performs normal REF_PRINT/REF_CHECK macros on + the operation, and provides a more encapsulated way for external code + (crypto/evp/ and ssl/) to do this. Also changed the evp and ssl code + to use these functions rather than manually incrementing the counts. + + Also rename "DSO_up()" function to more descriptive "DSO_up_ref()". + + *Geoff Thorpe* + + * Add EVP test program. + + *Ben Laurie* + + * Add symmetric cipher support to ENGINE. Expect the API to change! + + *Ben Laurie* + + * New CRL functions: X509_CRL_set_version(), X509_CRL_set_issuer_name() + X509_CRL_set_lastUpdate(), X509_CRL_set_nextUpdate(), X509_CRL_sort(), + X509_REVOKED_set_serialNumber(), and X509_REVOKED_set_revocationDate(). + These allow a CRL to be built without having to access X509_CRL fields + directly. Modify 'ca' application to use new functions. + + *Steve Henson* + + * Move SSL_OP_TLS_ROLLBACK_BUG out of the SSL_OP_ALL list of recommended + bug workarounds. Rollback attack detection is a security feature. + The problem will only arise on OpenSSL servers when TLSv1 is not + available (sslv3_server_method() or SSL_OP_NO_TLSv1). + Software authors not wanting to support TLSv1 will have special reasons + for their choice and can explicitly enable this option. + + *Bodo Moeller, Lutz Jaenicke* + + * Rationalise EVP so it can be extended: don't include a union of + cipher/digest structures, add init/cleanup functions for EVP_MD_CTX + (similar to those existing for EVP_CIPHER_CTX). + Usage example: + + EVP_MD_CTX md; + + EVP_MD_CTX_init(&md); /* new function call */ + EVP_DigestInit(&md, EVP_sha1()); + EVP_DigestUpdate(&md, in, len); + EVP_DigestFinal(&md, out, NULL); + EVP_MD_CTX_cleanup(&md); /* new function call */ + + *Ben Laurie* + + * Make DES key schedule conform to the usual scheme, as well as + correcting its structure. This means that calls to DES functions + now have to pass a pointer to a des_key_schedule instead of a + plain des_key_schedule (which was actually always a pointer + anyway): E.g., + + des_key_schedule ks; + + des_set_key_checked(..., &ks); + des_ncbc_encrypt(..., &ks, ...); + + (Note that a later change renames 'des_...' into 'DES_...'.) + + *Ben Laurie* + + * Initial reduction of linker bloat: the use of some functions, such as + PEM causes large amounts of unused functions to be linked in due to + poor organisation. For example pem_all.c contains every PEM function + which has a knock on effect of linking in large amounts of (unused) + ASN1 code. Grouping together similar functions and splitting unrelated + functions prevents this. + + *Steve Henson* + + * Cleanup of EVP macros. + + *Ben Laurie* + + * Change historical references to `{NID,SN,LN}_des_ede` and ede3 to add the + correct `_ecb suffix`. + + *Ben Laurie* + + * Add initial OCSP responder support to ocsp application. The + revocation information is handled using the text based index + use by the ca application. The responder can either handle + requests generated internally, supplied in files (for example + via a CGI script) or using an internal minimal server. + + *Steve Henson* + + * Add configuration choices to get zlib compression for TLS. + + *Richard Levitte* + + * Changes to Kerberos SSL for RFC 2712 compliance: + 1. Implemented real KerberosWrapper, instead of just using + KRB5 AP_REQ message. [Thanks to Simon Wilkinson ] + 2. Implemented optional authenticator field of KerberosWrapper. + + Added openssl-style ASN.1 macros for Kerberos ticket, ap_req, + and authenticator structs; see crypto/krb5/. + + Generalized Kerberos calls to support multiple Kerberos libraries. + *Vern Staats , Jeffrey Altman + via Richard Levitte* + + * Cause 'openssl speed' to use fully hard-coded DSA keys as it + already does with RSA. testdsa.h now has 'priv_key/pub_key' + values for each of the key sizes rather than having just + parameters (and 'speed' generating keys each time). + + *Geoff Thorpe* + + * Speed up EVP routines. + Before: +crypt +pe 8 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes +s-cbc 4408.85k 5560.51k 5778.46k 5862.20k 5825.16k +s-cbc 4389.55k 5571.17k 5792.23k 5846.91k 5832.11k +s-cbc 4394.32k 5575.92k 5807.44k 5848.37k 5841.30k +crypt +s-cbc 3482.66k 5069.49k 5496.39k 5614.16k 5639.28k +s-cbc 3480.74k 5068.76k 5510.34k 5609.87k 5635.52k +s-cbc 3483.72k 5067.62k 5504.60k 5708.01k 5724.80k + After: +crypt +s-cbc 4660.16k 5650.19k 5807.19k 5827.13k 5783.32k +crypt +s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k + + *Ben Laurie* + + * Added the OS2-EMX target. + + *"Brian Havard" and Richard Levitte* + + * Rewrite commands to use `NCONF` routines instead of the old `CONF`. + New functions to support `NCONF` routines in extension code. + New function `CONF_set_nconf()` + to allow functions which take an `NCONF` to also handle the old `LHASH` + structure: this means that the old `CONF` compatible routines can be + retained (in particular w.rt. extensions) without having to duplicate the + code. New function `X509V3_add_ext_nconf_sk()` to add extensions to a stack. + + *Steve Henson* + + * Enhance the general user interface with mechanisms for inner control + and with possibilities to have yes/no kind of prompts. + + *Richard Levitte* + + * Change all calls to low-level digest routines in the library and + applications to use EVP. Add missing calls to HMAC_cleanup() and + don't assume HMAC_CTX can be copied using memcpy(). + + *Verdon Walker , Steve Henson* + + * Add the possibility to control engines through control names but with + arbitrary arguments instead of just a string. + Change the key loaders to take a UI_METHOD instead of a callback + function pointer. NOTE: this breaks binary compatibility with earlier + versions of OpenSSL [engine]. + Adapt the nCipher code for these new conditions and add a card insertion + callback. + + *Richard Levitte* + + * Enhance the general user interface with mechanisms to better support + dialog box interfaces, application-defined prompts, the possibility + to use defaults (for example default passwords from somewhere else) + and interrupts/cancellations. + + *Richard Levitte* + + * Tidy up PKCS#12 attribute handling. Add support for the CSP name + attribute in PKCS#12 files, add new -CSP option to pkcs12 utility. + + *Steve Henson* + + * Fix a memory leak in 'sk_dup()' in the case reallocation fails. (Also + tidy up some unnecessarily weird code in 'sk_new()'). + + *Geoff, reported by Diego Tartara * + + * Change the key loading routines for ENGINEs to use the same kind + callback (pem_password_cb) as all other routines that need this + kind of callback. + + *Richard Levitte* + + * Increase ENTROPY_NEEDED to 32 bytes, as Rijndael can operate with + 256 bit (=32 byte) keys. Of course seeding with more entropy bytes + than this minimum value is recommended. + + *Lutz Jaenicke* + + * New random seeder for OpenVMS, using the system process statistics + that are easily reachable. + + *Richard Levitte* + + * Windows apparently can't transparently handle global + variables defined in DLLs. Initialisations such as: + + const ASN1_ITEM *it = &ASN1_INTEGER_it; + + won't compile. This is used by the any applications that need to + declare their own ASN1 modules. This was fixed by adding the option + EXPORT_VAR_AS_FN to all Win32 platforms, although this isn't strictly + needed for static libraries under Win32. + + *Steve Henson* + + * New functions X509_PURPOSE_set() and X509_TRUST_set() to handle + setting of purpose and trust fields. New X509_STORE trust and + purpose functions and tidy up setting in other SSL functions. + + *Steve Henson* + + * Add copies of X509_STORE_CTX fields and callbacks to X509_STORE + structure. These are inherited by X509_STORE_CTX when it is + initialised. This allows various defaults to be set in the + X509_STORE structure (such as flags for CRL checking and custom + purpose or trust settings) for functions which only use X509_STORE_CTX + internally such as S/MIME. + + Modify X509_STORE_CTX_purpose_inherit() so it only sets purposes and + trust settings if they are not set in X509_STORE. This allows X509_STORE + purposes and trust (in S/MIME for example) to override any set by default. + + Add command line options for CRL checking to smime, s_client and s_server + applications. + + *Steve Henson* + + * Initial CRL based revocation checking. If the CRL checking flag(s) + are set then the CRL is looked up in the X509_STORE structure and + its validity and signature checked, then if the certificate is found + in the CRL the verify fails with a revoked error. + + Various new CRL related callbacks added to X509_STORE_CTX structure. + + Command line options added to 'verify' application to support this. + + This needs some additional work, such as being able to handle multiple + CRLs with different times, extension based lookup (rather than just + by subject name) and ultimately more complete V2 CRL extension + handling. + + *Steve Henson* + + * Add a general user interface API (crypto/ui/). This is designed + to replace things like des_read_password and friends (backward + compatibility functions using this new API are provided). + The purpose is to remove prompting functions from the DES code + section as well as provide for prompting through dialog boxes in + a window system and the like. + + *Richard Levitte* + + * Add "ex_data" support to ENGINE so implementations can add state at a + per-structure level rather than having to store it globally. + + *Geoff* + + * Make it possible for ENGINE structures to be copied when retrieved by + ENGINE_by_id() if the ENGINE specifies a new flag: ENGINE_FLAGS_BY_ID_COPY. + This causes the "original" ENGINE structure to act like a template, + analogous to the RSA vs. RSA_METHOD type of separation. Because of this + operational state can be localised to each ENGINE structure, despite the + fact they all share the same "methods". New ENGINE structures returned in + this case have no functional references and the return value is the single + structural reference. This matches the single structural reference returned + by ENGINE_by_id() normally, when it is incremented on the pre-existing + ENGINE structure. + + *Geoff* + + * Fix ASN1 decoder when decoding type ANY and V_ASN1_OTHER: since this + needs to match any other type at all we need to manually clear the + tag cache. + + *Steve Henson* + + * Changes to the "openssl engine" utility to include; + - verbosity levels ('-v', '-vv', and '-vvv') that provide information + about an ENGINE's available control commands. + - executing control commands from command line arguments using the + '-pre' and '-post' switches. '-post' is only used if '-t' is + specified and the ENGINE is successfully initialised. The syntax for + the individual commands are colon-separated, for example; + openssl engine chil -pre FORK_CHECK:0 -pre SO_PATH:/lib/test.so + + *Geoff* + + * New dynamic control command support for ENGINEs. ENGINEs can now + declare their own commands (numbers), names (strings), descriptions, + and input types for run-time discovery by calling applications. A + subset of these commands are implicitly classed as "executable" + depending on their input type, and only these can be invoked through + the new string-based API function ENGINE_ctrl_cmd_string(). (Eg. this + can be based on user input, config files, etc). The distinction is + that "executable" commands cannot return anything other than a boolean + result and can only support numeric or string input, whereas some + discoverable commands may only be for direct use through + ENGINE_ctrl(), eg. supporting the exchange of binary data, function + pointers, or other custom uses. The "executable" commands are to + support parameterisations of ENGINE behaviour that can be + unambiguously defined by ENGINEs and used consistently across any + OpenSSL-based application. Commands have been added to all the + existing hardware-supporting ENGINEs, noticeably "SO_PATH" to allow + control over shared-library paths without source code alterations. + + *Geoff* + + * Changed all ENGINE implementations to dynamically allocate their + ENGINEs rather than declaring them statically. Apart from this being + necessary with the removal of the ENGINE_FLAGS_MALLOCED distinction, + this also allows the implementations to compile without using the + internal engine_int.h header. + + *Geoff* + + * Minor adjustment to "rand" code. RAND_get_rand_method() now returns a + 'const' value. Any code that should be able to modify a RAND_METHOD + should already have non-const pointers to it (ie. they should only + modify their own ones). + + *Geoff* + + * Made a variety of little tweaks to the ENGINE code. + - "atalla" and "ubsec" string definitions were moved from header files + to C code. "nuron" string definitions were placed in variables + rather than hard-coded - allowing parameterisation of these values + later on via ctrl() commands. + - Removed unused "#if 0"'d code. + - Fixed engine list iteration code so it uses ENGINE_free() to release + structural references. + - Constified the RAND_METHOD element of ENGINE structures. + - Constified various get/set functions as appropriate and added + missing functions (including a catch-all ENGINE_cpy that duplicates + all ENGINE values onto a new ENGINE except reference counts/state). + - Removed NULL parameter checks in get/set functions. Setting a method + or function to NULL is a way of cancelling out a previously set + value. Passing a NULL ENGINE parameter is just plain stupid anyway + and doesn't justify the extra error symbols and code. + - Deprecate the ENGINE_FLAGS_MALLOCED define and move the area for + flags from engine_int.h to engine.h. + - Changed prototypes for ENGINE handler functions (init(), finish(), + ctrl(), key-load functions, etc) to take an (ENGINE*) parameter. + + *Geoff* + + * Implement binary inversion algorithm for BN_mod_inverse in addition + to the algorithm using long division. The binary algorithm can be + used only if the modulus is odd. On 32-bit systems, it is faster + only for relatively small moduli (roughly 20-30% for 128-bit moduli, + roughly 5-15% for 256-bit moduli), so we use it only for moduli + up to 450 bits. In 64-bit environments, the binary algorithm + appears to be advantageous for much longer moduli; here we use it + for moduli up to 2048 bits. + + *Bodo Moeller* + + * Rewrite CHOICE field setting in ASN1_item_ex_d2i(). The old code + could not support the combine flag in choice fields. + + *Steve Henson* + + * Add a 'copy_extensions' option to the 'ca' utility. This copies + extensions from a certificate request to the certificate. + + *Steve Henson* + + * Allow multiple 'certopt' and 'nameopt' options to be separated + by commas. Add 'namopt' and 'certopt' options to the 'ca' config + file: this allows the display of the certificate about to be + signed to be customised, to allow certain fields to be included + or excluded and extension details. The old system didn't display + multicharacter strings properly, omitted fields not in the policy + and couldn't display additional details such as extensions. + + *Steve Henson* + + * Function EC_POINTs_mul for multiple scalar multiplication + of an arbitrary number of elliptic curve points + \sum scalars[i]*points[i], + optionally including the generator defined for the EC_GROUP: + scalar*generator + \sum scalars[i]*points[i]. + + EC_POINT_mul is a simple wrapper function for the typical case + that the point list has just one item (besides the optional + generator). + + *Bodo Moeller* + + * First EC_METHODs for curves over GF(p): + + EC_GFp_simple_method() uses the basic BN_mod_mul and BN_mod_sqr + operations and provides various method functions that can also + operate with faster implementations of modular arithmetic. + + EC_GFp_mont_method() reuses most functions that are part of + EC_GFp_simple_method, but uses Montgomery arithmetic. + + *Bodo Moeller; point addition and point doubling + implementation directly derived from source code provided by + Lenka Fibikova * + + * Framework for elliptic curves (crypto/ec/ec.h, crypto/ec/ec_lcl.h, + crypto/ec/ec_lib.c): + + Curves are EC_GROUP objects (with an optional group generator) + based on EC_METHODs that are built into the library. + + Points are EC_POINT objects based on EC_GROUP objects. + + Most of the framework would be able to handle curves over arbitrary + finite fields, but as there are no obvious types for fields other + than GF(p), some functions are limited to that for now. + + *Bodo Moeller* + + * Add the -HTTP option to s_server. It is similar to -WWW, but requires + that the file contains a complete HTTP response. + + *Richard Levitte* + + * Add the ec directory to mkdef.pl and mkfiles.pl. In mkdef.pl + change the def and num file printf format specifier from "%-40sXXX" + to "%-39s XXX". The latter will always guarantee a space after the + field while the former will cause them to run together if the field + is 40 of more characters long. + + *Steve Henson* + + * Constify the cipher and digest 'method' functions and structures + and modify related functions to take constant EVP_MD and EVP_CIPHER + pointers. + + *Steve Henson* + + * Hide BN_CTX structure details in bn_lcl.h instead of publishing them + in . Also further increase BN_CTX_NUM to 32. + + *Bodo Moeller* + + * Modify `EVP_Digest*()` routines so they now return values. Although the + internal software routines can never fail additional hardware versions + might. + + *Steve Henson* + + * Clean up crypto/err/err.h and change some error codes to avoid conflicts: + + Previously ERR_R_FATAL was too small and coincided with ERR_LIB_PKCS7 + (= ERR_R_PKCS7_LIB); it is now 64 instead of 32. + + ASN1 error codes + ERR_R_NESTED_ASN1_ERROR + ... + ERR_R_MISSING_ASN1_EOS + were 4 .. 9, conflicting with + ERR_LIB_RSA (= ERR_R_RSA_LIB) + ... + ERR_LIB_PEM (= ERR_R_PEM_LIB). + They are now 58 .. 63 (i.e., just below ERR_R_FATAL). + + Add new error code 'ERR_R_INTERNAL_ERROR'. + + *Bodo Moeller* + + * Don't overuse locks in crypto/err/err.c: For data retrieval, CRYPTO_r_lock + suffices. + + *Bodo Moeller* + + * New option '-subj arg' for 'openssl req' and 'openssl ca'. This + sets the subject name for a new request or supersedes the + subject name in a given request. Formats that can be parsed are + 'CN=Some Name, OU=myOU, C=IT' + and + 'CN=Some Name/OU=myOU/C=IT'. + + Add options '-batch' and '-verbose' to 'openssl req'. + + *Massimiliano Pala * + + * Introduce the possibility to access global variables through + functions on platform were that's the best way to handle exporting + global variables in shared libraries. To enable this functionality, + one must configure with "EXPORT_VAR_AS_FN" or defined the C macro + "OPENSSL_EXPORT_VAR_AS_FUNCTION" in crypto/opensslconf.h (the latter + is normally done by Configure or something similar). + + To implement a global variable, use the macro OPENSSL_IMPLEMENT_GLOBAL + in the source file (foo.c) like this: + + OPENSSL_IMPLEMENT_GLOBAL(int,foo)=1; + OPENSSL_IMPLEMENT_GLOBAL(double,bar); + + To declare a global variable, use the macros OPENSSL_DECLARE_GLOBAL + and OPENSSL_GLOBAL_REF in the header file (foo.h) like this: + + OPENSSL_DECLARE_GLOBAL(int,foo); + #define foo OPENSSL_GLOBAL_REF(foo) + OPENSSL_DECLARE_GLOBAL(double,bar); + #define bar OPENSSL_GLOBAL_REF(bar) + + The #defines are very important, and therefore so is including the + header file everywhere where the defined globals are used. + + The macro OPENSSL_EXPORT_VAR_AS_FUNCTION also affects the definition + of ASN.1 items, but that structure is a bit different. + + The largest change is in util/mkdef.pl which has been enhanced with + better and easier to understand logic to choose which symbols should + go into the Windows .def files as well as a number of fixes and code + cleanup (among others, algorithm keywords are now sorted + lexicographically to avoid constant rewrites). + + *Richard Levitte* + + * In BN_div() keep a copy of the sign of 'num' before writing the + result to 'rm' because if rm==num the value will be overwritten + and produce the wrong result if 'num' is negative: this caused + problems with BN_mod() and BN_nnmod(). + + *Steve Henson* + + * Function OCSP_request_verify(). This checks the signature on an + OCSP request and verifies the signer certificate. The signer + certificate is just checked for a generic purpose and OCSP request + trust settings. + + *Steve Henson* + + * Add OCSP_check_validity() function to check the validity of OCSP + responses. OCSP responses are prepared in real time and may only + be a few seconds old. Simply checking that the current time lies + between thisUpdate and nextUpdate max reject otherwise valid responses + caused by either OCSP responder or client clock inaccuracy. Instead + we allow thisUpdate and nextUpdate to fall within a certain period of + the current time. The age of the response can also optionally be + checked. Two new options -validity_period and -status_age added to + ocsp utility. + + *Steve Henson* + + * If signature or public key algorithm is unrecognized print out its + OID rather that just UNKNOWN. + + *Steve Henson* + + * Change OCSP_cert_to_id() to tolerate a NULL subject certificate and + OCSP_cert_id_new() a NULL serialNumber. This allows a partial certificate + ID to be generated from the issuer certificate alone which can then be + passed to OCSP_id_issuer_cmp(). + + *Steve Henson* + + * New compilation option ASN1_ITEM_FUNCTIONS. This causes the new + ASN1 modules to export functions returning ASN1_ITEM pointers + instead of the ASN1_ITEM structures themselves. This adds several + new macros which allow the underlying ASN1 function/structure to + be accessed transparently. As a result code should not use ASN1_ITEM + references directly (such as &X509_it) but instead use the relevant + macros (such as ASN1_ITEM_rptr(X509)). This option is to allow + use of the new ASN1 code on platforms where exporting structures + is problematical (for example in shared libraries) but exporting + functions returning pointers to structures is not. + + *Steve Henson* + + * Add support for overriding the generation of SSL/TLS session IDs. + These callbacks can be registered either in an SSL_CTX or per SSL. + The purpose of this is to allow applications to control, if they wish, + the arbitrary values chosen for use as session IDs, particularly as it + can be useful for session caching in multiple-server environments. A + command-line switch for testing this (and any client code that wishes + to use such a feature) has been added to "s_server". + + *Geoff Thorpe, Lutz Jaenicke* + + * Modify mkdef.pl to recognise and parse preprocessor conditionals + of the form `#if defined(...) || defined(...) || ...` and + `#if !defined(...) && !defined(...) && ...`. This also avoids + the growing number of special cases it was previously handling. + + *Richard Levitte* + + * Make all configuration macros available for application by making + sure they are available in opensslconf.h, by giving them names starting + with `OPENSSL_` to avoid conflicts with other packages and by making + sure e_os2.h will cover all platform-specific cases together with + opensslconf.h. + Additionally, it is now possible to define configuration/platform- + specific names (called "system identities"). In the C code, these + are prefixed with `OPENSSL_SYSNAME_`. e_os2.h will create another + macro with the name beginning with `OPENSSL_SYS_`, which is determined + from `OPENSSL_SYSNAME_*` or compiler-specific macros depending on + what is available. + + *Richard Levitte* + + * New option -set_serial to 'req' and 'x509' this allows the serial + number to use to be specified on the command line. Previously self + signed certificates were hard coded with serial number 0 and the + CA options of 'x509' had to use a serial number in a file which was + auto incremented. + + *Steve Henson* + + * New options to 'ca' utility to support V2 CRL entry extensions. + Currently CRL reason, invalidity date and hold instruction are + supported. Add new CRL extensions to V3 code and some new objects. + + *Steve Henson* + + * New function EVP_CIPHER_CTX_set_padding() this is used to + disable standard block padding (aka PKCS#5 padding) in the EVP + API, which was previously mandatory. This means that the data is + not padded in any way and so the total length much be a multiple + of the block size, otherwise an error occurs. + + *Steve Henson* + + * Initial (incomplete) OCSP SSL support. + + *Steve Henson* + + * New function OCSP_parse_url(). This splits up a URL into its host, + port and path components: primarily to parse OCSP URLs. New -url + option to ocsp utility. + + *Steve Henson* + + * New nonce behavior. The return value of OCSP_check_nonce() now + reflects the various checks performed. Applications can decide + whether to tolerate certain situations such as an absent nonce + in a response when one was present in a request: the ocsp application + just prints out a warning. New function OCSP_add1_basic_nonce() + this is to allow responders to include a nonce in a response even if + the request is nonce-less. + + *Steve Henson* + + * Disable stdin buffering in `load_cert()` (`apps/apps.c`) so that no certs are + skipped when using openssl x509 multiple times on a single input file, + e.g. `(openssl x509 -out cert1; openssl x509 -out cert2) * + + * New OCSP verify flag OCSP_TRUSTOTHER. When set the "other" certificates + passed by the function are trusted implicitly. If any of them signed the + response then it is assumed to be valid and is not verified. + + *Steve Henson* + + * In PKCS7_set_type() initialise content_type in PKCS7_ENC_CONTENT + to data. This was previously part of the PKCS7 ASN1 code. This + was causing problems with OpenSSL created PKCS#12 and PKCS#7 structures. + *Steve Henson, reported by Kenneth R. Robinette + * + + * Add CRYPTO_push_info() and CRYPTO_pop_info() calls to new ASN1 + routines: without these tracing memory leaks is very painful. + Fix leaks in PKCS12 and PKCS7 routines. + + *Steve Henson* + + * Make X509_time_adj() cope with the new behaviour of ASN1_TIME_new(). + Previously it initialised the 'type' argument to V_ASN1_UTCTIME which + effectively meant GeneralizedTime would never be used. Now it + is initialised to -1 but X509_time_adj() now has to check the value + and use ASN1_TIME_set() if the value is not V_ASN1_UTCTIME or + V_ASN1_GENERALIZEDTIME, without this it always uses GeneralizedTime. + *Steve Henson, reported by Kenneth R. Robinette + * + + * Fixes to BN_to_ASN1_INTEGER when bn is zero. This would previously + result in a zero length in the ASN1_INTEGER structure which was + not consistent with the structure when d2i_ASN1_INTEGER() was used + and would cause ASN1_INTEGER_cmp() to fail. Enhance s2i_ASN1_INTEGER() + to cope with hex and negative integers. Fix bug in i2a_ASN1_INTEGER() + where it did not print out a minus for negative ASN1_INTEGER. + + *Steve Henson* + + * Add summary printout to ocsp utility. The various functions which + convert status values to strings have been renamed to: + OCSP_response_status_str(), OCSP_cert_status_str() and + OCSP_crl_reason_str() and are no longer static. New options + to verify nonce values and to disable verification. OCSP response + printout format cleaned up. + + *Steve Henson* + + * Add additional OCSP certificate checks. These are those specified + in RFC2560. This consists of two separate checks: the CA of the + certificate being checked must either be the OCSP signer certificate + or the issuer of the OCSP signer certificate. In the latter case the + OCSP signer certificate must contain the OCSP signing extended key + usage. This check is performed by attempting to match the OCSP + signer or the OCSP signer CA to the issuerNameHash and issuerKeyHash + in the OCSP_CERTID structures of the response. + + *Steve Henson* + + * Initial OCSP certificate verification added to OCSP_basic_verify() + and related routines. This uses the standard OpenSSL certificate + verify routines to perform initial checks (just CA validity) and + to obtain the certificate chain. Then additional checks will be + performed on the chain. Currently the root CA is checked to see + if it is explicitly trusted for OCSP signing. This is used to set + a root CA as a global signing root: that is any certificate that + chains to that CA is an acceptable OCSP signing certificate. + + *Steve Henson* + + * New '-extfile ...' option to 'openssl ca' for reading X.509v3 + extensions from a separate configuration file. + As when reading extensions from the main configuration file, + the '-extensions ...' option may be used for specifying the + section to use. + + *Massimiliano Pala * + + * New OCSP utility. Allows OCSP requests to be generated or + read. The request can be sent to a responder and the output + parsed, outputted or printed in text form. Not complete yet: + still needs to check the OCSP response validity. + + *Steve Henson* + + * New subcommands for 'openssl ca': + `openssl ca -status ` prints the status of the cert with + the given serial number (according to the index file). + `openssl ca -updatedb` updates the expiry status of certificates + in the index file. + + *Massimiliano Pala * + + * New '-newreq-nodes' command option to CA.pl. This is like + '-newreq', but calls 'openssl req' with the '-nodes' option + so that the resulting key is not encrypted. + + *Damien Miller * + + * New configuration for the GNU Hurd. + + *Jonathan Bartlett via Richard Levitte* + + * Initial code to implement OCSP basic response verify. This + is currently incomplete. Currently just finds the signer's + certificate and verifies the signature on the response. + + *Steve Henson* + + * New SSLeay_version code SSLEAY_DIR to determine the compiled-in + value of OPENSSLDIR. This is available via the new '-d' option + to 'openssl version', and is also included in 'openssl version -a'. + + *Bodo Moeller* + + * Allowing defining memory allocation callbacks that will be given + file name and line number information in additional arguments + (a `const char*` and an int). The basic functionality remains, as + well as the original possibility to just replace malloc(), + realloc() and free() by functions that do not know about these + additional arguments. To register and find out the current + settings for extended allocation functions, the following + functions are provided: + + CRYPTO_set_mem_ex_functions + CRYPTO_set_locked_mem_ex_functions + CRYPTO_get_mem_ex_functions + CRYPTO_get_locked_mem_ex_functions + + These work the same way as CRYPTO_set_mem_functions and friends. + `CRYPTO_get_[locked_]mem_functions` now writes 0 where such an + extended allocation function is enabled. + Similarly, `CRYPTO_get_[locked_]mem_ex_functions` writes 0 where + a conventional allocation function is enabled. + + *Richard Levitte, Bodo Moeller* + + * Finish off removing the remaining LHASH function pointer casts. + There should no longer be any prototype-casting required when using + the LHASH abstraction, and any casts that remain are "bugs". See + the callback types and macros at the head of lhash.h for details + (and "OBJ_cleanup" in crypto/objects/obj_dat.c as an example). + + *Geoff Thorpe* + + * Add automatic query of EGD sockets in RAND_poll() for the unix variant. + If /dev/[u]random devices are not available or do not return enough + entropy, EGD style sockets (served by EGD or PRNGD) will automatically + be queried. + The locations /var/run/egd-pool, /dev/egd-pool, /etc/egd-pool, and + /etc/entropy will be queried once each in this sequence, querying stops + when enough entropy was collected without querying more sockets. + + *Lutz Jaenicke* + + * Change the Unix RAND_poll() variant to be able to poll several + random devices, as specified by DEVRANDOM, until a sufficient amount + of data has been collected. We spend at most 10 ms on each file + (select timeout) and read in non-blocking mode. DEVRANDOM now + defaults to the list "/dev/urandom", "/dev/random", "/dev/srandom" + (previously it was just the string "/dev/urandom"), so on typical + platforms the 10 ms delay will never occur. + Also separate out the Unix variant to its own file, rand_unix.c. + For VMS, there's a currently-empty rand_vms.c. + + *Richard Levitte* + + * Move OCSP client related routines to ocsp_cl.c. These + provide utility functions which an application needing + to issue a request to an OCSP responder and analyse the + response will typically need: as opposed to those which an + OCSP responder itself would need which will be added later. + + OCSP_request_sign() signs an OCSP request with an API similar + to PKCS7_sign(). OCSP_response_status() returns status of OCSP + response. OCSP_response_get1_basic() extracts basic response + from response. OCSP_resp_find_status(): finds and extracts status + information from an OCSP_CERTID structure (which will be created + when the request structure is built). These are built from lower + level functions which work on OCSP_SINGLERESP structures but + won't normally be used unless the application wishes to examine + extensions in the OCSP response for example. + + Replace nonce routines with a pair of functions. + OCSP_request_add1_nonce() adds a nonce value and optionally + generates a random value. OCSP_check_nonce() checks the + validity of the nonce in an OCSP response. + + *Steve Henson* + + * Change function OCSP_request_add() to OCSP_request_add0_id(). + This doesn't copy the supplied OCSP_CERTID and avoids the + need to free up the newly created id. Change return type + to OCSP_ONEREQ to return the internal OCSP_ONEREQ structure. + This can then be used to add extensions to the request. + Deleted OCSP_request_new(), since most of its functionality + is now in OCSP_REQUEST_new() (and the case insensitive name + clash) apart from the ability to set the request name which + will be added elsewhere. + + *Steve Henson* + + * Update OCSP API. Remove obsolete extensions argument from + various functions. Extensions are now handled using the new + OCSP extension code. New simple OCSP HTTP function which + can be used to send requests and parse the response. + + *Steve Henson* + + * Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new + ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN + uses the special reorder version of SET OF to sort the attributes + and reorder them to match the encoded order. This resolves a long + standing problem: a verify on a PKCS7 structure just after signing + it used to fail because the attribute order did not match the + encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes: + it uses the received order. This is necessary to tolerate some broken + software that does not order SET OF. This is handled by encoding + as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class) + to produce the required SET OF. + + *Steve Henson* + + * Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and + OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header + files to get correct declarations of the ASN.1 item variables. + + *Richard Levitte* + + * Rewrite of PKCS#12 code to use new ASN1 functionality. Replace many + PKCS#12 macros with real functions. Fix two unrelated ASN1 bugs: + asn1_check_tlen() would sometimes attempt to use 'ctx' when it was + NULL and ASN1_TYPE was not dereferenced properly in asn1_ex_c2i(). + New ASN1 macro: DECLARE_ASN1_ITEM() which just declares the relevant + ASN1_ITEM and no wrapper functions. + + *Steve Henson* + + * New functions or ASN1_item_d2i_fp() and ASN1_item_d2i_bio(). These + replace the old function pointer based I/O routines. Change most of + the `*_d2i_bio()` and `*_d2i_fp()` functions to use these. + + *Steve Henson* + + * Enhance mkdef.pl to be more accepting about spacing in C preprocessor + lines, recognize more "algorithms" that can be deselected, and make + it complain about algorithm deselection that isn't recognised. + + *Richard Levitte* + + * New ASN1 functions to handle dup, sign, verify, digest, pack and + unpack operations in terms of ASN1_ITEM. Modify existing wrappers + to use new functions. Add NO_ASN1_OLD which can be set to remove + some old style ASN1 functions: this can be used to determine if old + code will still work when these eventually go away. + + *Steve Henson* + + * New extension functions for OCSP structures, these follow the + same conventions as certificates and CRLs. + + *Steve Henson* + + * New function X509V3_add1_i2d(). This automatically encodes and + adds an extension. Its behaviour can be customised with various + flags to append, replace or delete. Various wrappers added for + certificates and CRLs. + + *Steve Henson* + + * Fix to avoid calling the underlying ASN1 print routine when + an extension cannot be parsed. Correct a typo in the + OCSP_SERVICELOC extension. Tidy up print OCSP format. + + *Steve Henson* + + * Make mkdef.pl parse some of the ASN1 macros and add appropriate + entries for variables. + + *Steve Henson* + + * Add functionality to `apps/openssl.c` for detecting locking + problems: As the program is single-threaded, all we have + to do is register a locking callback using an array for + storing which locks are currently held by the program. + + *Bodo Moeller* + + * Use a lock around the call to CRYPTO_get_ex_new_index() in + SSL_get_ex_data_X509_STORE_idx(), which is used in + ssl_verify_cert_chain() and thus can be called at any time + during TLS/SSL handshakes so that thread-safety is essential. + Unfortunately, the ex_data design is not at all suited + for multi-threaded use, so it probably should be abolished. + + *Bodo Moeller* + + * Added Broadcom "ubsec" ENGINE to OpenSSL. + + *Broadcom, tweaked and integrated by Geoff Thorpe* + + * Move common extension printing code to new function + X509V3_print_extensions(). Reorganise OCSP print routines and + implement some needed OCSP ASN1 functions. Add OCSP extensions. + + *Steve Henson* + + * New function X509_signature_print() to remove duplication in some + print routines. + + *Steve Henson* + + * Add a special meaning when SET OF and SEQUENCE OF flags are both + set (this was treated exactly the same as SET OF previously). This + is used to reorder the STACK representing the structure to match the + encoding. This will be used to get round a problem where a PKCS7 + structure which was signed could not be verified because the STACK + order did not reflect the encoded order. + + *Steve Henson* + + * Reimplement the OCSP ASN1 module using the new code. + + *Steve Henson* + + * Update the X509V3 code to permit the use of an ASN1_ITEM structure + for its ASN1 operations. The old style function pointers still exist + for now but they will eventually go away. + + *Steve Henson* + + * Merge in replacement ASN1 code from the ASN1 branch. This almost + completely replaces the old ASN1 functionality with a table driven + encoder and decoder which interprets an ASN1_ITEM structure describing + the ASN1 module. Compatibility with the existing ASN1 API (i2d,d2i) is + largely maintained. Almost all of the old asn1_mac.h macro based ASN1 + has also been converted to the new form. + + *Steve Henson* + + * Change BN_mod_exp_recp so that negative moduli are tolerated + (the sign is ignored). Similarly, ignore the sign in BN_MONT_CTX_set + so that BN_mod_exp_mont and BN_mod_exp_mont_word work + for negative moduli. + + *Bodo Moeller* + + * Fix BN_uadd and BN_usub: Always return non-negative results instead + of not touching the result's sign bit. + + *Bodo Moeller* + + * BN_div bugfix: If the result is 0, the sign (res->neg) must not be + set. + + *Bodo Moeller* + + * Changed the LHASH code to use prototypes for callbacks, and created + macros to declare and implement thin (optionally static) functions + that provide type-safety and avoid function pointer casting for the + type-specific callbacks. + + *Geoff Thorpe* + + * Added Kerberos Cipher Suites to be used with TLS, as written in + RFC 2712. + *Veers Staats , + Jeffrey Altman , via Richard Levitte* + + * Reformat the FAQ so the different questions and answers can be divided + in sections depending on the subject. + + *Richard Levitte* + + * Have the zlib compression code load ZLIB.DLL dynamically under + Windows. + + *Richard Levitte* + + * New function BN_mod_sqrt for computing square roots modulo a prime + (using the probabilistic Tonelli-Shanks algorithm unless + p == 3 (mod 4) or p == 5 (mod 8), which are cases that can + be handled deterministically). + + *Lenka Fibikova , Bodo Moeller* + + * Make BN_mod_inverse faster by explicitly handling small quotients + in the Euclid loop. (Speed gain about 20% for small moduli [256 or + 512 bits], about 30% for larger ones [1024 or 2048 bits].) + + *Bodo Moeller* + + * New function BN_kronecker. + + *Bodo Moeller* + + * Fix BN_gcd so that it works on negative inputs; the result is + positive unless both parameters are zero. + Previously something reasonably close to an infinite loop was + possible because numbers could be growing instead of shrinking + in the implementation of Euclid's algorithm. + + *Bodo Moeller* + + * Fix BN_is_word() and BN_is_one() macros to take into account the + sign of the number in question. + + Fix BN_is_word(a,w) to work correctly for w == 0. + + The old BN_is_word(a,w) macro is now called BN_abs_is_word(a,w) + because its test if the absolute value of 'a' equals 'w'. + Note that BN_abs_is_word does *not* handle w == 0 reliably; + it exists mostly for use in the implementations of BN_is_zero(), + BN_is_one(), and BN_is_word(). + + *Bodo Moeller* + + * New function BN_swap. + + *Bodo Moeller* + + * Use BN_nnmod instead of BN_mod in crypto/bn/bn_exp.c so that + the exponentiation functions are more likely to produce reasonable + results on negative inputs. + + *Bodo Moeller* + + * Change BN_mod_mul so that the result is always non-negative. + Previously, it could be negative if one of the factors was negative; + I don't think anyone really wanted that behaviour. + + *Bodo Moeller* + + * Move `BN_mod_...` functions into new file `crypto/bn/bn_mod.c` + (except for exponentiation, which stays in `crypto/bn/bn_exp.c`, + and `BN_mod_mul_reciprocal`, which stays in `crypto/bn/bn_recp.c`) + and add new functions: + + BN_nnmod + BN_mod_sqr + BN_mod_add + BN_mod_add_quick + BN_mod_sub + BN_mod_sub_quick + BN_mod_lshift1 + BN_mod_lshift1_quick + BN_mod_lshift + BN_mod_lshift_quick + + These functions always generate non-negative results. + + `BN_nnmod` otherwise is `like BN_mod` (if `BN_mod` computes a remainder `r` + such that `|m| < r < 0`, `BN_nnmod` will output `rem + |m|` instead). + + `BN_mod_XXX_quick(r, a, [b,] m)` generates the same result as + `BN_mod_XXX(r, a, [b,] m, ctx)`, but requires that `a` [and `b`] + be reduced modulo `m`. + + *Lenka Fibikova , Bodo Moeller* + + + + * In 'openssl passwd', verify passwords read from the terminal + unless the '-salt' option is used (which usually means that + verification would just waste user's time since the resulting + hash is going to be compared with some given password hash) + or the new '-noverify' option is used. + + This is an incompatible change, but it does not affect + non-interactive use of 'openssl passwd' (passwords on the command + line, '-stdin' option, '-in ...' option) and thus should not + cause any problems. + + *Bodo Moeller* + + * Remove all references to RSAref, since there's no more need for it. + + *Richard Levitte* + + * Make DSO load along a path given through an environment variable + (SHLIB_PATH) with shl_load(). + + *Richard Levitte* + + * Constify the ENGINE code as a result of BIGNUM constification. + Also constify the RSA code and most things related to it. In a + few places, most notable in the depth of the ASN.1 code, ugly + casts back to non-const were required (to be solved at a later + time) + + *Richard Levitte* + + * Make it so the openssl application has all engines loaded by default. + + *Richard Levitte* + + * Constify the BIGNUM routines a little more. + + *Richard Levitte* + + * Add the following functions: + + ENGINE_load_cswift() + ENGINE_load_chil() + ENGINE_load_atalla() + ENGINE_load_nuron() + ENGINE_load_builtin_engines() + + That way, an application can itself choose if external engines that + are built-in in OpenSSL shall ever be used or not. The benefit is + that applications won't have to be linked with libdl or other dso + libraries unless it's really needed. + + Changed 'openssl engine' to load all engines on demand. + Changed the engine header files to avoid the duplication of some + declarations (they differed!). + + *Richard Levitte* + + * 'openssl engine' can now list capabilities. + + *Richard Levitte* + + * Better error reporting in 'openssl engine'. + + *Richard Levitte* + + * Never call load_dh_param(NULL) in s_server. + + *Bodo Moeller* + + * Add engine application. It can currently list engines by name and + identity, and test if they are actually available. + + *Richard Levitte* + + * Improve RPM specification file by forcing symbolic linking and making + sure the installed documentation is also owned by root.root. + + *Damien Miller * + + * Give the OpenSSL applications more possibilities to make use of + keys (public as well as private) handled by engines. + + *Richard Levitte* + + * Add OCSP code that comes from CertCo. + + *Richard Levitte* + + * Add VMS support for the Rijndael code. + + *Richard Levitte* + + * Added untested support for Nuron crypto accelerator. + + *Ben Laurie* + + * Add support for external cryptographic devices. This code was + previously distributed separately as the "engine" branch. + + *Geoff Thorpe, Richard Levitte* + + * Rework the filename-translation in the DSO code. It is now possible to + have far greater control over how a "name" is turned into a filename + depending on the operating environment and any oddities about the + different shared library filenames on each system. + + *Geoff Thorpe* + + * Support threads on FreeBSD-elf in Configure. + + *Richard Levitte* + + * Fix for SHA1 assembly problem with MASM: it produces + warnings about corrupt line number information when assembling + with debugging information. This is caused by the overlapping + of two sections. + + *Bernd Matthes , Steve Henson* + + * NCONF changes. + NCONF_get_number() has no error checking at all. As a replacement, + NCONF_get_number_e() is defined (`_e` for "error checking") and is + promoted strongly. The old NCONF_get_number is kept around for + binary backward compatibility. + Make it possible for methods to load from something other than a BIO, + by providing a function pointer that is given a name instead of a BIO. + For example, this could be used to load configuration data from an + LDAP server. + + *Richard Levitte* + + * Fix for non blocking accept BIOs. Added new I/O special reason + BIO_RR_ACCEPT to cover this case. Previously use of accept BIOs + with non blocking I/O was not possible because no retry code was + implemented. Also added new SSL code SSL_WANT_ACCEPT to cover + this case. + + *Steve Henson* + + * Added the beginnings of Rijndael support. + + *Ben Laurie* + + * Fix for bug in DirectoryString mask setting. Add support for + X509_NAME_print_ex() in 'req' and X509_print_ex() function + to allow certificate printing to more controllable, additional + 'certopt' option to 'x509' to allow new printing options to be + set. + + *Steve Henson* + + * Clean old EAY MD5 hack from e_os.h. + + *Richard Levitte* + +### Changes between 0.9.6l and 0.9.6m [17 Mar 2004] + + * Fix null-pointer assignment in do_change_cipher_spec() revealed + by using the Codenomicon TLS Test Tool ([CVE-2004-0079]) + + *Joe Orton, Steve Henson* + +### Changes between 0.9.6k and 0.9.6l [04 Nov 2003] + + * Fix additional bug revealed by the NISCC test suite: + + Stop bug triggering large recursion when presented with + certain ASN.1 tags ([CVE-2003-0851]) + + *Steve Henson* + +### Changes between 0.9.6j and 0.9.6k [30 Sep 2003] + + * Fix various bugs revealed by running the NISCC test suite: + + Stop out of bounds reads in the ASN1 code when presented with + invalid tags (CVE-2003-0543 and CVE-2003-0544). + + If verify callback ignores invalid public key errors don't try to check + certificate signature with the NULL public key. + + *Steve Henson* + + * In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate + if the server requested one: as stated in TLS 1.0 and SSL 3.0 + specifications. + + *Steve Henson* + + * In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional + extra data after the compression methods not only for TLS 1.0 + but also for SSL 3.0 (as required by the specification). + + *Bodo Moeller; problem pointed out by Matthias Loepfe* + + * Change X509_certificate_type() to mark the key as exported/exportable + when it's 512 *bits* long, not 512 bytes. + + *Richard Levitte* + +### Changes between 0.9.6i and 0.9.6j [10 Apr 2003] + + * Countermeasure against the Klima-Pokorny-Rosa extension of + Bleichbacher's attack on PKCS #1 v1.5 padding: treat + a protocol version number mismatch like a decryption error + in ssl3_get_client_key_exchange (ssl/s3_srvr.c). + + *Bodo Moeller* + + * Turn on RSA blinding by default in the default implementation + to avoid a timing attack. Applications that don't want it can call + RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING. + They would be ill-advised to do so in most cases. + + *Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller* + + * Change RSA blinding code so that it works when the PRNG is not + seeded (in this case, the secret RSA exponent is abused as + an unpredictable seed -- if it is not unpredictable, there + is no point in blinding anyway). Make RSA blinding thread-safe + by remembering the creator's thread ID in rsa->blinding and + having all other threads use local one-time blinding factors + (this requires more computation than sharing rsa->blinding, but + avoids excessive locking; and if an RSA object is not shared + between threads, blinding will still be very fast). + + *Bodo Moeller* + +### Changes between 0.9.6h and 0.9.6i [19 Feb 2003] + + * In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked + via timing by performing a MAC computation even if incorrect + block cipher padding has been found. This is a countermeasure + against active attacks where the attacker has to distinguish + between bad padding and a MAC verification error. ([CVE-2003-0078]) + + *Bodo Moeller; problem pointed out by Brice Canvel (EPFL), + Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and + Martin Vuagnoux (EPFL, Ilion)* + +### Changes between 0.9.6g and 0.9.6h [5 Dec 2002] + + * New function OPENSSL_cleanse(), which is used to cleanse a section of + memory from its contents. This is done with a counter that will + place alternating values in each byte. This can be used to solve + two issues: 1) the removal of calls to memset() by highly optimizing + compilers, and 2) cleansing with other values than 0, since those can + be read through on certain media, for example a swap space on disk. + + *Geoff Thorpe* + + * Bugfix: client side session caching did not work with external caching, + because the session->cipher setting was not restored when reloading + from the external cache. This problem was masked, when + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG (part of SSL_OP_ALL) was set. + (Found by Steve Haslam .) + + *Lutz Jaenicke* + + * Fix client_certificate (ssl/s2_clnt.c): The permissible total + length of the REQUEST-CERTIFICATE message is 18 .. 34, not 17 .. 33. + + *Zeev Lieber * + + * Undo an undocumented change introduced in 0.9.6e which caused + repeated calls to OpenSSL_add_all_ciphers() and + OpenSSL_add_all_digests() to be ignored, even after calling + EVP_cleanup(). + + *Richard Levitte* + + * Change the default configuration reader to deal with last line not + being properly terminated. + + *Richard Levitte* + + * Change X509_NAME_cmp() so it applies the special rules on handling + DN values that are of type PrintableString, as well as RDNs of type + emailAddress where the value has the type ia5String. + + *stefank@valicert.com via Richard Levitte* + + * Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half + the job SSL_SESS_CACHE_NO_INTERNAL_LOOKUP was inconsistently + doing, define a new flag (SSL_SESS_CACHE_NO_INTERNAL) to be + the bitwise-OR of the two for use by the majority of applications + wanting this behaviour, and update the docs. The documented + behaviour and actual behaviour were inconsistent and had been + changing anyway, so this is more a bug-fix than a behavioural + change. + + *Geoff Thorpe, diagnosed by Nadav Har'El* + + * Don't impose a 16-byte length minimum on session IDs in ssl/s3_clnt.c + (the SSL 3.0 and TLS 1.0 specifications allow any length up to 32 bytes). + + *Bodo Moeller* + + * Fix initialization code race conditions in + SSLv23_method(), SSLv23_client_method(), SSLv23_server_method(), + SSLv2_method(), SSLv2_client_method(), SSLv2_server_method(), + SSLv3_method(), SSLv3_client_method(), SSLv3_server_method(), + TLSv1_method(), TLSv1_client_method(), TLSv1_server_method(), + ssl2_get_cipher_by_char(), + ssl3_get_cipher_by_char(). + + *Patrick McCormick , Bodo Moeller* + + * Reorder cleanup sequence in SSL_CTX_free(): only remove the ex_data after + the cached sessions are flushed, as the remove_cb() might use ex_data + contents. Bug found by Sam Varshavchik + (see [openssl.org #212]). + + *Geoff Thorpe, Lutz Jaenicke* + + * Fix typo in OBJ_txt2obj which incorrectly passed the content + length, instead of the encoding length to d2i_ASN1_OBJECT. + + *Steve Henson* + +### Changes between 0.9.6f and 0.9.6g [9 Aug 2002] + + * [In 0.9.6g-engine release:] + Fix crypto/engine/vendor_defns/cswift.h for WIN32 (use `_stdcall`). + + *Lynn Gazis * + +### Changes between 0.9.6e and 0.9.6f [8 Aug 2002] + + * Fix ASN1 checks. Check for overflow by comparing with LONG_MAX + and get fix the header length calculation. + *Florian Weimer , + Alon Kantor (and others), Steve Henson* + + * Use proper error handling instead of 'assertions' in buffer + overflow checks added in 0.9.6e. This prevents DoS (the + assertions could call abort()). + + *Arne Ansper , Bodo Moeller* + +### Changes between 0.9.6d and 0.9.6e [30 Jul 2002] + + * Add various sanity checks to asn1_get_length() to reject + the ASN1 length bytes if they exceed sizeof(long), will appear + negative or the content length exceeds the length of the + supplied buffer. + + *Steve Henson, Adi Stav , James Yonan * + + * Fix cipher selection routines: ciphers without encryption had no flags + for the cipher strength set and where therefore not handled correctly + by the selection routines (PR #130). + + *Lutz Jaenicke* + + * Fix EVP_dsa_sha macro. + + *Nils Larsch* + + * New option + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + for disabling the SSL 3.0/TLS 1.0 CBC vulnerability countermeasure + that was added in OpenSSL 0.9.6d. + + As the countermeasure turned out to be incompatible with some + broken SSL implementations, the new option is part of SSL_OP_ALL. + SSL_OP_ALL is usually employed when compatibility with weird SSL + implementations is desired (e.g. '-bugs' option to 's_client' and + 's_server'), so the new option is automatically set in many + applications. + + *Bodo Moeller* + + * Changes in security patch: + + Changes marked "(CHATS)" were sponsored by the Defense Advanced + Research Projects Agency (DARPA) and Air Force Research Laboratory, + Air Force Materiel Command, USAF, under agreement number + F30602-01-2-0537. + + * Add various sanity checks to asn1_get_length() to reject + the ASN1 length bytes if they exceed sizeof(long), will appear + negative or the content length exceeds the length of the + supplied buffer. ([CVE-2002-0659]) + + *Steve Henson, Adi Stav , James Yonan * + + * Assertions for various potential buffer overflows, not known to + happen in practice. + + *Ben Laurie (CHATS)* + + * Various temporary buffers to hold ASCII versions of integers were + too small for 64 bit platforms. ([CVE-2002-0655]) + *Matthew Byng-Maddick and Ben Laurie (CHATS)>* + + * Remote buffer overflow in SSL3 protocol - an attacker could + supply an oversized session ID to a client. ([CVE-2002-0656]) + + *Ben Laurie (CHATS)* + + * Remote buffer overflow in SSL2 protocol - an attacker could + supply an oversized client master key. ([CVE-2002-0656]) + + *Ben Laurie (CHATS)* + +### Changes between 0.9.6c and 0.9.6d [9 May 2002] + + * Fix crypto/asn1/a_sign.c so that 'parameters' is omitted (not + encoded as NULL) with id-dsa-with-sha1. + + *Nils Larsch ; problem pointed out by Bodo Moeller* + + * Check various `X509_...()` return values in `apps/req.c`. + + *Nils Larsch * + + * Fix BASE64 decode (EVP_DecodeUpdate) for data with CR/LF ended lines: + an end-of-file condition would erroneously be flagged, when the CRLF + was just at the end of a processed block. The bug was discovered when + processing data through a buffering memory BIO handing the data to a + BASE64-decoding BIO. Bug fund and patch submitted by Pavel Tsekov + and Nedelcho Stanev. + + *Lutz Jaenicke* + + * Implement a countermeasure against a vulnerability recently found + in CBC ciphersuites in SSL 3.0/TLS 1.0: Send an empty fragment + before application data chunks to avoid the use of known IVs + with data potentially chosen by the attacker. + + *Bodo Moeller* + + * Fix length checks in ssl3_get_client_hello(). + + *Bodo Moeller* + + * TLS/SSL library bugfix: use s->s3->in_read_app_data differently + to prevent ssl3_read_internal() from incorrectly assuming that + ssl3_read_bytes() found application data while handshake + processing was enabled when in fact s->s3->in_read_app_data was + merely automatically cleared during the initial handshake. + + *Bodo Moeller; problem pointed out by Arne Ansper * + + * Fix object definitions for Private and Enterprise: they were not + recognized in their shortname (=lowercase) representation. Extend + obj_dat.pl to issue an error when using undefined keywords instead + of silently ignoring the problem (Svenning Sorensen + ). + + *Lutz Jaenicke* + + * Fix DH_generate_parameters() so that it works for 'non-standard' + generators, i.e. generators other than 2 and 5. (Previously, the + code did not properly initialise the 'add' and 'rem' values to + BN_generate_prime().) + + In the new general case, we do not insist that 'generator' is + actually a primitive root: This requirement is rather pointless; + a generator of the order-q subgroup is just as good, if not + better. + + *Bodo Moeller* + + * Map new X509 verification errors to alerts. Discovered and submitted by + Tom Wu . + + *Lutz Jaenicke* + + * Fix ssl3_pending() (ssl/s3_lib.c) to prevent SSL_pending() from + returning non-zero before the data has been completely received + when using non-blocking I/O. + + *Bodo Moeller; problem pointed out by John Hughes* + + * Some of the ciphers missed the strength entry (SSL_LOW etc). + + *Ben Laurie, Lutz Jaenicke* + + * Fix bug in SSL_clear(): bad sessions were not removed (found by + Yoram Zahavi ). + + *Lutz Jaenicke* + + * Add information about CygWin 1.3 and on, and preserve proper + configuration for the versions before that. + + *Corinna Vinschen and Richard Levitte* + + * Make removal from session cache (SSL_CTX_remove_session()) more robust: + check whether we deal with a copy of a session and do not delete from + the cache in this case. Problem reported by "Izhar Shoshani Levi" + . + + *Lutz Jaenicke* + + * Do not store session data into the internal session cache, if it + is never intended to be looked up (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP + flag is set). Proposed by Aslam . + + *Lutz Jaenicke* + + * Have ASN1_BIT_STRING_set_bit() really clear a bit when the requested + value is 0. + + *Richard Levitte* + + * [In 0.9.6d-engine release:] + Fix a crashbug and a logic bug in hwcrhk_load_pubkey(). + + *Toomas Kiisk via Richard Levitte* + + * Add the configuration target linux-s390x. + + *Neale Ferguson via Richard Levitte* + + * The earlier bugfix for the SSL3_ST_SW_HELLO_REQ_C case of + ssl3_accept (ssl/s3_srvr.c) incorrectly used a local flag + variable as an indication that a ClientHello message has been + received. As the flag value will be lost between multiple + invocations of ssl3_accept when using non-blocking I/O, the + function may not be aware that a handshake has actually taken + place, thus preventing a new session from being added to the + session cache. + + To avoid this problem, we now set s->new_session to 2 instead of + using a local variable. + + *Lutz Jaenicke, Bodo Moeller* + + * Bugfix: Return -1 from ssl3_get_server_done (ssl3/s3_clnt.c) + if the SSL_R_LENGTH_MISMATCH error is detected. + + *Geoff Thorpe, Bodo Moeller* + + * New 'shared_ldflag' column in Configure platform table. + + *Richard Levitte* + + * Fix EVP_CIPHER_mode macro. + + *"Dan S. Camper" * + + * Fix ssl3_read_bytes (ssl/s3_pkt.c): To ignore messages of unknown + type, we must throw them away by setting rr->length to 0. + + *D P Chang * + +### Changes between 0.9.6b and 0.9.6c [21 dec 2001] + + * Fix BN_rand_range bug pointed out by Dominikus Scherkl + . (The previous implementation + worked incorrectly for those cases where range = `10..._2` and + `3*range` is two bits longer than range.) + + *Bodo Moeller* + + * Only add signing time to PKCS7 structures if it is not already + present. + + *Steve Henson* + + * Fix crypto/objects/objects.h: "ld-ce" should be "id-ce", + OBJ_ld_ce should be OBJ_id_ce. + Also some ip-pda OIDs in crypto/objects/objects.txt were + incorrect (cf. RFC 3039). + + *Matt Cooper, Frederic Giudicelli, Bodo Moeller* + + * Release CRYPTO_LOCK_DYNLOCK when CRYPTO_destroy_dynlockid() + returns early because it has nothing to do. + + *Andy Schneider * + + * [In 0.9.6c-engine release:] + Fix mutex callback return values in crypto/engine/hw_ncipher.c. + + *Andy Schneider * + + * [In 0.9.6c-engine release:] + Add support for Cryptographic Appliance's keyserver technology. + (Use engine 'keyclient') + + *Cryptographic Appliances and Geoff Thorpe* + + * Add a configuration entry for OS/390 Unix. The C compiler 'c89' + is called via tools/c89.sh because arguments have to be + rearranged (all '-L' options must appear before the first object + modules). + + *Richard Shapiro * + + * [In 0.9.6c-engine release:] + Add support for Broadcom crypto accelerator cards, backported + from 0.9.7. + + *Broadcom, Nalin Dahyabhai , Mark Cox* + + * [In 0.9.6c-engine release:] + Add support for SureWare crypto accelerator cards from + Baltimore Technologies. (Use engine 'sureware') + + *Baltimore Technologies and Mark Cox* + + * [In 0.9.6c-engine release:] + Add support for crypto accelerator cards from Accelerated + Encryption Processing, www.aep.ie. (Use engine 'aep') + + *AEP Inc. and Mark Cox* + + * Add a configuration entry for gcc on UnixWare. + + *Gary Benson * + + * Change ssl/s2_clnt.c and ssl/s2_srvr.c so that received handshake + messages are stored in a single piece (fixed-length part and + variable-length part combined) and fix various bugs found on the way. + + *Bodo Moeller* + + * Disable caching in BIO_gethostbyname(), directly use gethostbyname() + instead. BIO_gethostbyname() does not know what timeouts are + appropriate, so entries would stay in cache even when they have + become invalid. + *Bodo Moeller; problem pointed out by Rich Salz * + + * Change ssl23_get_client_hello (ssl/s23_srvr.c) behaviour when + faced with a pathologically small ClientHello fragment that does + not contain client_version: Instead of aborting with an error, + simply choose the highest available protocol version (i.e., + TLS 1.0 unless it is disabled). In practice, ClientHello + messages are never sent like this, but this change gives us + strictly correct behaviour at least for TLS. + + *Bodo Moeller* + + * Fix SSL handshake functions and SSL_clear() such that SSL_clear() + never resets s->method to s->ctx->method when called from within + one of the SSL handshake functions. + + *Bodo Moeller; problem pointed out by Niko Baric* + + * In ssl3_get_client_hello (ssl/s3_srvr.c), generate a fatal alert + (sent using the client's version number) if client_version is + smaller than the protocol version in use. Also change + ssl23_get_client_hello (ssl/s23_srvr.c) to select TLS 1.0 if + the client demanded SSL 3.0 but only TLS 1.0 is enabled; then + the client will at least see that alert. + + *Bodo Moeller* + + * Fix ssl3_get_message (ssl/s3_both.c) to handle message fragmentation + correctly. + + *Bodo Moeller* + + * Avoid infinite loop in ssl3_get_message (ssl/s3_both.c) if a + client receives HelloRequest while in a handshake. + + *Bodo Moeller; bug noticed by Andy Schneider * + + * Bugfix in ssl3_accept (ssl/s3_srvr.c): Case SSL3_ST_SW_HELLO_REQ_C + should end in 'break', not 'goto end' which circumvents various + cleanups done in state SSL_ST_OK. But session related stuff + must be disabled for SSL_ST_OK in the case that we just sent a + HelloRequest. + + Also avoid some overhead by not calling ssl_init_wbio_buffer() + before just sending a HelloRequest. + + *Bodo Moeller, Eric Rescorla * + + * Fix ssl/s3_enc.c, ssl/t1_enc.c and ssl/s3_pkt.c so that we don't + reveal whether illegal block cipher padding was found or a MAC + verification error occurred. (Neither SSLerr() codes nor alerts + are directly visible to potential attackers, but the information + may leak via logfiles.) + + Similar changes are not required for the SSL 2.0 implementation + because the number of padding bytes is sent in clear for SSL 2.0, + and the extra bytes are just ignored. However ssl/s2_pkt.c + failed to verify that the purported number of padding bytes is in + the legal range. + + *Bodo Moeller* + + * Add OpenUNIX-8 support including shared libraries + (Boyd Lynn Gerber ). + + *Lutz Jaenicke* + + * Improve RSA_padding_check_PKCS1_OAEP() check again to avoid + 'wristwatch attack' using huge encoding parameters (cf. + James H. Manger's CRYPTO 2001 paper). Note that the + RSA_PKCS1_OAEP_PADDING case of RSA_private_decrypt() does not use + encoding parameters and hence was not vulnerable. + + *Bodo Moeller* + + * BN_sqr() bug fix. + + *Ulf Möller, reported by Jim Ellis * + + * Rabin-Miller test analyses assume uniformly distributed witnesses, + so use BN_pseudo_rand_range() instead of using BN_pseudo_rand() + followed by modular reduction. + + *Bodo Moeller; pointed out by Adam Young * + + * Add BN_pseudo_rand_range() with obvious functionality: BN_rand_range() + equivalent based on BN_pseudo_rand() instead of BN_rand(). + + *Bodo Moeller* + + * s3_srvr.c: allow sending of large client certificate lists (> 16 kB). + This function was broken, as the check for a new client hello message + to handle SGC did not allow these large messages. + (Tracked down by "Douglas E. Engert" .) + + *Lutz Jaenicke* + + * Add alert descriptions for TLSv1 to `SSL_alert_desc_string[_long]()`. + + *Lutz Jaenicke* + + * Fix buggy behaviour of BIO_get_num_renegotiates() and BIO_ctrl() + for BIO_C_GET_WRITE_BUF_SIZE ("Stephen Hinton" ). + + *Lutz Jaenicke* + + * Rework the configuration and shared library support for Tru64 Unix. + The configuration part makes use of modern compiler features and + still retains old compiler behavior for those that run older versions + of the OS. The shared library support part includes a variant that + uses the RPATH feature, and is available through the special + configuration target "alpha-cc-rpath", which will never be selected + automatically. + + *Tim Mooney via Richard Levitte* + + * In ssl3_get_key_exchange (ssl/s3_clnt.c), call ssl3_get_message() + with the same message size as in ssl3_get_certificate_request(). + Otherwise, if no ServerKeyExchange message occurs, CertificateRequest + messages might inadvertently be reject as too long. + + *Petr Lampa * + + * Enhanced support for IA-64 Unix platforms (well, Linux and HP-UX). + + *Andy Polyakov* + + * Modified SSL library such that the verify_callback that has been set + specifically for an SSL object with SSL_set_verify() is actually being + used. Before the change, a verify_callback set with this function was + ignored and the verify_callback() set in the SSL_CTX at the time of + the call was used. New function X509_STORE_CTX_set_verify_cb() introduced + to allow the necessary settings. + + *Lutz Jaenicke* + + * Initialize static variable in crypto/dsa/dsa_lib.c and crypto/dh/dh_lib.c + explicitly to NULL, as at least on Solaris 8 this seems not always to be + done automatically (in contradiction to the requirements of the C + standard). This made problems when used from OpenSSH. + + *Lutz Jaenicke* + + * In OpenSSL 0.9.6a and 0.9.6b, crypto/dh/dh_key.c ignored + dh->length and always used + + BN_rand_range(priv_key, dh->p). + + BN_rand_range() is not necessary for Diffie-Hellman, and this + specific range makes Diffie-Hellman unnecessarily inefficient if + dh->length (recommended exponent length) is much smaller than the + length of dh->p. We could use BN_rand_range() if the order of + the subgroup was stored in the DH structure, but we only have + dh->length. + + So switch back to + + BN_rand(priv_key, l, ...) + + where 'l' is dh->length if this is defined, or BN_num_bits(dh->p)-1 + otherwise. + + *Bodo Moeller* + + * In + + RSA_eay_public_encrypt + RSA_eay_private_decrypt + RSA_eay_private_encrypt (signing) + RSA_eay_public_decrypt (signature verification) + + (default implementations for RSA_public_encrypt, + RSA_private_decrypt, RSA_private_encrypt, RSA_public_decrypt), + always reject numbers >= n. + + *Bodo Moeller* + + * In crypto/rand/md_rand.c, use a new short-time lock CRYPTO_LOCK_RAND2 + to synchronize access to 'locking_thread'. This is necessary on + systems where access to 'locking_thread' (an 'unsigned long' + variable) is not atomic. + + *Bodo Moeller* + + * In crypto/rand/md_rand.c, set 'locking_thread' to current thread's ID + *before* setting the 'crypto_lock_rand' flag. The previous code had + a race condition if 0 is a valid thread ID. + + *Travis Vitek * + + * Add support for shared libraries under Irix. + + *Albert Chin-A-Young * + + * Add configuration option to build on Linux on both big-endian and + little-endian MIPS. + + *Ralf Baechle * + + * Add the possibility to create shared libraries on HP-UX. + + *Richard Levitte* + +### Changes between 0.9.6a and 0.9.6b [9 Jul 2001] + + * Change ssleay_rand_bytes (crypto/rand/md_rand.c) + to avoid a SSLeay/OpenSSL PRNG weakness pointed out by + Markku-Juhani O. Saarinen : + PRNG state recovery was possible based on the output of + one PRNG request appropriately sized to gain knowledge on + 'md' followed by enough consecutive 1-byte PRNG requests + to traverse all of 'state'. + + 1. When updating 'md_local' (the current thread's copy of 'md') + during PRNG output generation, hash all of the previous + 'md_local' value, not just the half used for PRNG output. + + 2. Make the number of bytes from 'state' included into the hash + independent from the number of PRNG bytes requested. + + The first measure alone would be sufficient to avoid + Markku-Juhani's attack. (Actually it had never occurred + to me that the half of 'md_local' used for chaining was the + half from which PRNG output bytes were taken -- I had always + assumed that the secret half would be used.) The second + measure makes sure that additional data from 'state' is never + mixed into 'md_local' in small portions; this heuristically + further strengthens the PRNG. + + *Bodo Moeller* + + * Fix crypto/bn/asm/mips3.s. + + *Andy Polyakov* + + * When only the key is given to "enc", the IV is undefined. Print out + an error message in this case. + + *Lutz Jaenicke* + + * Handle special case when X509_NAME is empty in X509 printing routines. + + *Steve Henson* + + * In dsa_do_verify (crypto/dsa/dsa_ossl.c), verify that r and s are + positive and less than q. + + *Bodo Moeller* + + * Don't change `*pointer` in CRYPTO_add_lock() is add_lock_callback is + used: it isn't thread safe and the add_lock_callback should handle + that itself. + + *Paul Rose * + + * Verify that incoming data obeys the block size in + ssl3_enc (ssl/s3_enc.c) and tls1_enc (ssl/t1_enc.c). + + *Bodo Moeller* + + * Fix OAEP check. + + *Ulf Möller, Bodo Möller* + + * The countermeasure against Bleichbacher's attack on PKCS #1 v1.5 + RSA encryption was accidentally removed in s3_srvr.c in OpenSSL 0.9.5 + when fixing the server behaviour for backwards-compatible 'client + hello' messages. (Note that the attack is impractical against + SSL 3.0 and TLS 1.0 anyway because length and version checking + means that the probability of guessing a valid ciphertext is + around 2^-40; see section 5 in Bleichenbacher's CRYPTO '98 + paper.) + + Before 0.9.5, the countermeasure (hide the error by generating a + random 'decryption result') did not work properly because + ERR_clear_error() was missing, meaning that SSL_get_error() would + detect the supposedly ignored error. + + Both problems are now fixed. + + *Bodo Moeller* + + * In crypto/bio/bf_buff.c, increase DEFAULT_BUFFER_SIZE to 4096 + (previously it was 1024). + + *Bodo Moeller* + + * Fix for compatibility mode trust settings: ignore trust settings + unless some valid trust or reject settings are present. + + *Steve Henson* + + * Fix for blowfish EVP: its a variable length cipher. + + *Steve Henson* + + * Fix various bugs related to DSA S/MIME verification. Handle missing + parameters in DSA public key structures and return an error in the + DSA routines if parameters are absent. + + *Steve Henson* + + * In versions up to 0.9.6, RAND_file_name() resorted to file ".rnd" + in the current directory if neither $RANDFILE nor $HOME was set. + RAND_file_name() in 0.9.6a returned NULL in this case. This has + caused some confusion to Windows users who haven't defined $HOME. + Thus RAND_file_name() is changed again: e_os.h can define a + DEFAULT_HOME, which will be used if $HOME is not set. + For Windows, we use "C:"; on other platforms, we still require + environment variables. + + * Move 'if (!initialized) RAND_poll()' into regions protected by + CRYPTO_LOCK_RAND. This is not strictly necessary, but avoids + having multiple threads call RAND_poll() concurrently. + + *Bodo Moeller* + + * In crypto/rand/md_rand.c, replace 'add_do_not_lock' flag by a + combination of a flag and a thread ID variable. + Otherwise while one thread is in ssleay_rand_bytes (which sets the + flag), *other* threads can enter ssleay_add_bytes without obeying + the CRYPTO_LOCK_RAND lock (and may even illegally release the lock + that they do not hold after the first thread unsets add_do_not_lock). + + *Bodo Moeller* + + * Change bctest again: '-x' expressions are not available in all + versions of 'test'. + + *Bodo Moeller* + +### Changes between 0.9.6 and 0.9.6a [5 Apr 2001] + + * Fix a couple of memory leaks in PKCS7_dataDecode() + + *Steve Henson, reported by Heyun Zheng * + + * Change Configure and Makefiles to provide EXE_EXT, which will contain + the default extension for executables, if any. Also, make the perl + scripts that use symlink() to test if it really exists and use "cp" + if it doesn't. All this made OpenSSL compilable and installable in + CygWin. + + *Richard Levitte* + + * Fix for asn1_GetSequence() for indefinite length constructed data. + If SEQUENCE is length is indefinite just set c->slen to the total + amount of data available. + + *Steve Henson, reported by shige@FreeBSD.org* + + *This change does not apply to 0.9.7.* + + * Change bctest to avoid here-documents inside command substitution + (workaround for FreeBSD /bin/sh bug). + For compatibility with Ultrix, avoid shell functions (introduced + in the bctest version that searches along $PATH). + + *Bodo Moeller* + + * Rename 'des_encrypt' to 'des_encrypt1'. This avoids the clashes + with des_encrypt() defined on some operating systems, like Solaris + and UnixWare. + + *Richard Levitte* + + * Check the result of RSA-CRT (see D. Boneh, R. DeMillo, R. Lipton: + On the Importance of Eliminating Errors in Cryptographic + Computations, J. Cryptology 14 (2001) 2, 101-119, + ). + + *Ulf Moeller* + + * MIPS assembler BIGNUM division bug fix. + + *Andy Polyakov* + + * Disabled incorrect Alpha assembler code. + + *Richard Levitte* + + * Fix PKCS#7 decode routines so they correctly update the length + after reading an EOC for the EXPLICIT tag. + + *Steve Henson* + + *This change does not apply to 0.9.7.* + + * Fix bug in PKCS#12 key generation routines. This was triggered + if a 3DES key was generated with a 0 initial byte. Include + PKCS12_BROKEN_KEYGEN compilation option to retain the old + (but broken) behaviour. + + *Steve Henson* + + * Enhance bctest to search for a working bc along $PATH and print + it when found. + + *Tim Rice via Richard Levitte* + + * Fix memory leaks in err.c: free err_data string if necessary; + don't write to the wrong index in ERR_set_error_data. + + *Bodo Moeller* + + * Implement ssl23_peek (analogous to ssl23_read), which previously + did not exist. + + *Bodo Moeller* + + * Replace rdtsc with `_emit` statements for VC++ version 5. + + *Jeremy Cooper * + + * Make it possible to reuse SSLv2 sessions. + + *Richard Levitte* + + * In copy_email() check for >= 0 as a return value for + X509_NAME_get_index_by_NID() since 0 is a valid index. + + *Steve Henson reported by Massimiliano Pala * + + * Avoid coredump with unsupported or invalid public keys by checking if + X509_get_pubkey() fails in PKCS7_verify(). Fix memory leak when + PKCS7_verify() fails with non detached data. + + *Steve Henson* + + * Don't use getenv in library functions when run as setuid/setgid. + New function OPENSSL_issetugid(). + + *Ulf Moeller* + + * Avoid false positives in memory leak detection code (crypto/mem_dbg.c) + due to incorrect handling of multi-threading: + + 1. Fix timing glitch in the MemCheck_off() portion of CRYPTO_mem_ctrl(). + + 2. Fix logical glitch in is_MemCheck_on() aka CRYPTO_is_mem_check_on(). + + 3. Count how many times MemCheck_off() has been called so that + nested use can be treated correctly. This also avoids + inband-signalling in the previous code (which relied on the + assumption that thread ID 0 is impossible). + + *Bodo Moeller* + + * Add "-rand" option also to s_client and s_server. + + *Lutz Jaenicke* + + * Fix CPU detection on Irix 6.x. + *Kurt Hockenbury and + "Bruce W. Forsberg" * + + * Fix X509_NAME bug which produced incorrect encoding if X509_NAME + was empty. + + *Steve Henson* + + *This change does not apply to 0.9.7.* + + * Use the cached encoding of an X509_NAME structure rather than + copying it. This is apparently the reason for the libsafe "errors" + but the code is actually correct. + + *Steve Henson* + + * Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent + Bleichenbacher's DSA attack. + Extend BN_[pseudo_]rand: As before, top=1 forces the highest two bits + to be set and top=0 forces the highest bit to be set; top=-1 is new + and leaves the highest bit random. + + *Ulf Moeller, Bodo Moeller* + + * In the `NCONF_...`-based implementations for `CONF_...` queries + (crypto/conf/conf_lib.c), if the input LHASH is NULL, avoid using + a temporary CONF structure with the data component set to NULL + (which gives segmentation faults in lh_retrieve). + Instead, use NULL for the CONF pointer in CONF_get_string and + CONF_get_number (which may use environment variables) and directly + return NULL from CONF_get_section. + + *Bodo Moeller* + + * Fix potential buffer overrun for EBCDIC. + + *Ulf Moeller* + + * Tolerate nonRepudiation as being valid for S/MIME signing and certSign + keyUsage if basicConstraints absent for a CA. + + *Steve Henson* + + * Make SMIME_write_PKCS7() write mail header values with a format that + is more generally accepted (no spaces before the semicolon), since + some programs can't parse those values properly otherwise. Also make + sure BIO's that break lines after each write do not create invalid + headers. + + *Richard Levitte* + + * Make the CRL encoding routines work with empty SEQUENCE OF. The + macros previously used would not encode an empty SEQUENCE OF + and break the signature. + + *Steve Henson* + + *This change does not apply to 0.9.7.* + + * Zero the premaster secret after deriving the master secret in + DH ciphersuites. + + *Steve Henson* + + * Add some EVP_add_digest_alias registrations (as found in + OpenSSL_add_all_digests()) to SSL_library_init() + aka OpenSSL_add_ssl_algorithms(). This provides improved + compatibility with peers using X.509 certificates + with unconventional AlgorithmIdentifier OIDs. + + *Bodo Moeller* + + * Fix for Irix with NO_ASM. + + *"Bruce W. Forsberg" * + + * ./config script fixes. + + *Ulf Moeller, Richard Levitte* + + * Fix 'openssl passwd -1'. + + *Bodo Moeller* + + * Change PKCS12_key_gen_asc() so it can cope with non null + terminated strings whose length is passed in the passlen + parameter, for example from PEM callbacks. This was done + by adding an extra length parameter to asc2uni(). + + *Steve Henson, reported by * + + * Fix C code generated by 'openssl dsaparam -C': If a BN_bin2bn + call failed, free the DSA structure. + + *Bodo Moeller* + + * Fix to uni2asc() to cope with zero length Unicode strings. + These are present in some PKCS#12 files. + + *Steve Henson* + + * Increase s2->wbuf allocation by one byte in ssl2_new (ssl/s2_lib.c). + Otherwise do_ssl_write (ssl/s2_pkt.c) will write beyond buffer limits + when writing a 32767 byte record. + + *Bodo Moeller; problem reported by Eric Day * + + * In `RSA_eay_public_{en,ed}crypt` and RSA_eay_mod_exp (rsa_eay.c), + obtain lock CRYPTO_LOCK_RSA before setting `rsa->_method_mod_{n,p,q}`. + + (RSA objects have a reference count access to which is protected + by CRYPTO_LOCK_RSA [see rsa_lib.c, s3_srvr.c, ssl_cert.c, ssl_rsa.c], + so they are meant to be shared between threads.) + *Bodo Moeller, Geoff Thorpe; original patch submitted by + "Reddie, Steven" * + + * Fix a deadlock in CRYPTO_mem_leaks(). + + *Bodo Moeller* + + * Use better test patterns in bntest. + + *Ulf Möller* + + * rand_win.c fix for Borland C. + + *Ulf Möller* + + * BN_rshift bugfix for n == 0. + + *Bodo Moeller* + + * Add a 'bctest' script that checks for some known 'bc' bugs + so that 'make test' does not abort just because 'bc' is broken. + + *Bodo Moeller* + + * Store verify_result within SSL_SESSION also for client side to + avoid potential security hole. (Re-used sessions on the client side + always resulted in verify_result==X509_V_OK, not using the original + result of the server certificate verification.) + + *Lutz Jaenicke* + + * Fix ssl3_pending: If the record in s->s3->rrec is not of type + SSL3_RT_APPLICATION_DATA, return 0. + Similarly, change ssl2_pending to return 0 if SSL_in_init(s) is true. + + *Bodo Moeller* + + * Fix SSL_peek: + Both ssl2_peek and ssl3_peek, which were totally broken in earlier + releases, have been re-implemented by renaming the previous + implementations of ssl2_read and ssl3_read to ssl2_read_internal + and ssl3_read_internal, respectively, and adding 'peek' parameters + to them. The new ssl[23]_{read,peek} functions are calls to + ssl[23]_read_internal with the 'peek' flag set appropriately. + A 'peek' parameter has also been added to ssl3_read_bytes, which + does the actual work for ssl3_read_internal. + + *Bodo Moeller* + + * Initialise "ex_data" member of RSA/DSA/DH structures prior to calling + the method-specific "init()" handler. Also clean up ex_data after + calling the method-specific "finish()" handler. Previously, this was + happening the other way round. + + *Geoff Thorpe* + + * Increase BN_CTX_NUM (the number of BIGNUMs in a BN_CTX) to 16. + The previous value, 12, was not always sufficient for BN_mod_exp(). + + *Bodo Moeller* + + * Make sure that shared libraries get the internal name engine with + the full version number and not just 0. This should mark the + shared libraries as not backward compatible. Of course, this should + be changed again when we can guarantee backward binary compatibility. + + *Richard Levitte* + + * Fix typo in get_cert_by_subject() in by_dir.c + + *Jean-Marc Desperrier * + + * Rework the system to generate shared libraries: + + - Make note of the expected extension for the shared libraries and + if there is a need for symbolic links from for example libcrypto.so.0 + to libcrypto.so.0.9.7. There is extended info in Configure for + that. + + - Make as few rebuilds of the shared libraries as possible. + + - Still avoid linking the OpenSSL programs with the shared libraries. + + - When installing, install the shared libraries separately from the + static ones. + + *Richard Levitte* + + * Fix SSL_CTX_set_read_ahead macro to actually use its argument. + + Copy SSL_CTX's read_ahead flag to SSL object directly in SSL_new + and not in SSL_clear because the latter is also used by the + accept/connect functions; previously, the settings made by + SSL_set_read_ahead would be lost during the handshake. + + *Bodo Moeller; problems reported by Anders Gertz * + + * Correct util/mkdef.pl to be selective about disabled algorithms. + Previously, it would create entries for disabled algorithms no + matter what. + + *Richard Levitte* + + * Added several new manual pages for SSL_* function. + + *Lutz Jaenicke* + +### Changes between 0.9.5a and 0.9.6 [24 Sep 2000] + + * In ssl23_get_client_hello, generate an error message when faced + with an initial SSL 3.0/TLS record that is too small to contain the + first two bytes of the ClientHello message, i.e. client_version. + (Note that this is a pathologic case that probably has never happened + in real life.) The previous approach was to use the version number + from the record header as a substitute; but our protocol choice + should not depend on that one because it is not authenticated + by the Finished messages. + + *Bodo Moeller* + + * More robust randomness gathering functions for Windows. + + *Jeffrey Altman * + + * For compatibility reasons if the flag X509_V_FLAG_ISSUER_CHECK is + not set then we don't setup the error code for issuer check errors + to avoid possibly overwriting other errors which the callback does + handle. If an application does set the flag then we assume it knows + what it is doing and can handle the new informational codes + appropriately. + + *Steve Henson* + + * Fix for a nasty bug in ASN1_TYPE handling. ASN1_TYPE is used for + a general "ANY" type, as such it should be able to decode anything + including tagged types. However it didn't check the class so it would + wrongly interpret tagged types in the same way as their universal + counterpart and unknown types were just rejected. Changed so that the + tagged and unknown types are handled in the same way as a SEQUENCE: + that is the encoding is stored intact. There is also a new type + "V_ASN1_OTHER" which is used when the class is not universal, in this + case we have no idea what the actual type is so we just lump them all + together. + + *Steve Henson* + + * On VMS, stdout may very well lead to a file that is written to + in a record-oriented fashion. That means that every write() will + write a separate record, which will be read separately by the + programs trying to read from it. This can be very confusing. + + The solution is to put a BIO filter in the way that will buffer + text until a linefeed is reached, and then write everything a + line at a time, so every record written will be an actual line, + not chunks of lines and not (usually doesn't happen, but I've + seen it once) several lines in one record. BIO_f_linebuffer() is + the answer. + + Currently, it's a VMS-only method, because that's where it has + been tested well enough. + + *Richard Levitte* + + * Remove 'optimized' squaring variant in BN_mod_mul_montgomery, + it can return incorrect results. + (Note: The buggy variant was not enabled in OpenSSL 0.9.5a, + but it was in 0.9.6-beta[12].) + + *Bodo Moeller* + + * Disable the check for content being present when verifying detached + signatures in pk7_smime.c. Some versions of Netscape (wrongly) + include zero length content when signing messages. + + *Steve Henson* + + * New BIO_shutdown_wr macro, which invokes the BIO_C_SHUTDOWN_WR + BIO_ctrl (for BIO pairs). + + *Bodo Möller* + + * Add DSO method for VMS. + + *Richard Levitte* + + * Bug fix: Montgomery multiplication could produce results with the + wrong sign. + + *Ulf Möller* + + * Add RPM specification openssl.spec and modify it to build three + packages. The default package contains applications, application + documentation and run-time libraries. The devel package contains + include files, static libraries and function documentation. The + doc package contains the contents of the doc directory. The original + openssl.spec was provided by Damien Miller . + + *Richard Levitte* + + * Add a large number of documentation files for many SSL routines. + + *Lutz Jaenicke * + + * Add a configuration entry for Sony News 4. + + *NAKAJI Hiroyuki * + + * Don't set the two most significant bits to one when generating a + random number < q in the DSA library. + + *Ulf Möller* + + * New SSL API mode 'SSL_MODE_AUTO_RETRY'. This disables the default + behaviour that SSL_read may result in SSL_ERROR_WANT_READ (even if + the underlying transport is blocking) if a handshake took place. + (The default behaviour is needed by applications such as s_client + and s_server that use select() to determine when to use SSL_read; + but for applications that know in advance when to expect data, it + just makes things more complicated.) + + *Bodo Moeller* + + * Add RAND_egd_bytes(), which gives control over the number of bytes read + from EGD. + + *Ben Laurie* + + * Add a few more EBCDIC conditionals that make `req` and `x509` + work better on such systems. + + *Martin Kraemer * + + * Add two demo programs for PKCS12_parse() and PKCS12_create(). + Update PKCS12_parse() so it copies the friendlyName and the + keyid to the certificates aux info. + + *Steve Henson* + + * Fix bug in PKCS7_verify() which caused an infinite loop + if there was more than one signature. + + *Sven Uszpelkat * + + * Major change in util/mkdef.pl to include extra information + about each symbol, as well as presenting variables as well + as functions. This change means that there's n more need + to rebuild the .num files when some algorithms are excluded. + + *Richard Levitte* + + * Allow the verify time to be set by an application, + rather than always using the current time. + + *Steve Henson* + + * Phase 2 verify code reorganisation. The certificate + verify code now looks up an issuer certificate by a + number of criteria: subject name, authority key id + and key usage. It also verifies self signed certificates + by the same criteria. The main comparison function is + X509_check_issued() which performs these checks. + + Lot of changes were necessary in order to support this + without completely rewriting the lookup code. + + Authority and subject key identifier are now cached. + + The LHASH 'certs' is X509_STORE has now been replaced + by a STACK_OF(X509_OBJECT). This is mainly because an + LHASH can't store or retrieve multiple objects with + the same hash value. + + As a result various functions (which were all internal + use only) have changed to handle the new X509_STORE + structure. This will break anything that messed round + with X509_STORE internally. + + The functions X509_STORE_add_cert() now checks for an + exact match, rather than just subject name. + + The X509_STORE API doesn't directly support the retrieval + of multiple certificates matching a given criteria, however + this can be worked round by performing a lookup first + (which will fill the cache with candidate certificates) + and then examining the cache for matches. This is probably + the best we can do without throwing out X509_LOOKUP + entirely (maybe later...). + + The X509_VERIFY_CTX structure has been enhanced considerably. + + All certificate lookup operations now go via a get_issuer() + callback. Although this currently uses an X509_STORE it + can be replaced by custom lookups. This is a simple way + to bypass the X509_STORE hackery necessary to make this + work and makes it possible to use more efficient techniques + in future. A very simple version which uses a simple + STACK for its trusted certificate store is also provided + using X509_STORE_CTX_trusted_stack(). + + The verify_cb() and verify() callbacks now have equivalents + in the X509_STORE_CTX structure. + + X509_STORE_CTX also has a 'flags' field which can be used + to customise the verify behaviour. + + *Steve Henson* + + * Add new PKCS#7 signing option PKCS7_NOSMIMECAP which + excludes S/MIME capabilities. + + *Steve Henson* + + * When a certificate request is read in keep a copy of the + original encoding of the signed data and use it when outputting + again. Signatures then use the original encoding rather than + a decoded, encoded version which may cause problems if the + request is improperly encoded. + + *Steve Henson* + + * For consistency with other BIO_puts implementations, call + buffer_write(b, ...) directly in buffer_puts instead of calling + BIO_write(b, ...). + + In BIO_puts, increment b->num_write as in BIO_write. + + *Peter.Sylvester@EdelWeb.fr* + + * Fix BN_mul_word for the case where the word is 0. (We have to use + BN_zero, we may not return a BIGNUM with an array consisting of + words set to zero.) + + *Bodo Moeller* + + * Avoid calling abort() from within the library when problems are + detected, except if preprocessor symbols have been defined + (such as REF_CHECK, BN_DEBUG etc.). + + *Bodo Moeller* + + * New openssl application 'rsautl'. This utility can be + used for low-level RSA operations. DER public key + BIO/fp routines also added. + + *Steve Henson* + + * New Configure entry and patches for compiling on QNX 4. + + *Andreas Schneider * + + * A demo state-machine implementation was sponsored by + Nuron () and is now available in + demos/state_machine. + + *Ben Laurie* + + * New options added to the 'dgst' utility for signature + generation and verification. + + *Steve Henson* + + * Unrecognized PKCS#7 content types are now handled via a + catch all ASN1_TYPE structure. This allows unsupported + types to be stored as a "blob" and an application can + encode and decode it manually. + + *Steve Henson* + + * Fix various signed/unsigned issues to make a_strex.c + compile under VC++. + + *Oscar Jacobsson * + + * ASN1 fixes. i2d_ASN1_OBJECT was not returning the correct + length if passed a buffer. ASN1_INTEGER_to_BN failed + if passed a NULL BN and its argument was negative. + + *Steve Henson, pointed out by Sven Heiberg * + + * Modification to PKCS#7 encoding routines to output definite + length encoding. Since currently the whole structures are in + memory there's not real point in using indefinite length + constructed encoding. However if OpenSSL is compiled with + the flag PKCS7_INDEFINITE_ENCODING the old form is used. + + *Steve Henson* + + * Added BIO_vprintf() and BIO_vsnprintf(). + + *Richard Levitte* + + * Added more prefixes to parse for in the strings written + through a logging bio, to cover all the levels that are available + through syslog. The prefixes are now: + + PANIC, EMERG, EMR => LOG_EMERG + ALERT, ALR => LOG_ALERT + CRIT, CRI => LOG_CRIT + ERROR, ERR => LOG_ERR + WARNING, WARN, WAR => LOG_WARNING + NOTICE, NOTE, NOT => LOG_NOTICE + INFO, INF => LOG_INFO + DEBUG, DBG => LOG_DEBUG + + and as before, if none of those prefixes are present at the + beginning of the string, LOG_ERR is chosen. + + On Win32, the `LOG_*` levels are mapped according to this: + + LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR => EVENTLOG_ERROR_TYPE + LOG_WARNING => EVENTLOG_WARNING_TYPE + LOG_NOTICE, LOG_INFO, LOG_DEBUG => EVENTLOG_INFORMATION_TYPE + + *Richard Levitte* + + * Made it possible to reconfigure with just the configuration + argument "reconf" or "reconfigure". The command line arguments + are stored in Makefile.ssl in the variable CONFIGURE_ARGS, + and are retrieved from there when reconfiguring. + + *Richard Levitte* + + * MD4 implemented. + + *Assar Westerlund , Richard Levitte* + + * Add the arguments -CAfile and -CApath to the pkcs12 utility. + + *Richard Levitte* + + * The obj_dat.pl script was messing up the sorting of object + names. The reason was that it compared the quoted version + of strings as a result "OCSP" > "OCSP Signing" because + " > SPACE. Changed script to store unquoted versions of + names and add quotes on output. It was also omitting some + names from the lookup table if they were given a default + value (that is if SN is missing it is given the same + value as LN and vice versa), these are now added on the + grounds that if an object has a name we should be able to + look it up. Finally added warning output when duplicate + short or long names are found. + + *Steve Henson* + + * Changes needed for Tandem NSK. + + *Scott Uroff * + + * Fix SSL 2.0 rollback checking: Due to an off-by-one error in + RSA_padding_check_SSLv23(), special padding was never detected + and thus the SSL 3.0/TLS 1.0 countermeasure against protocol + version rollback attacks was not effective. + + In s23_clnt.c, don't use special rollback-attack detection padding + (RSA_SSLV23_PADDING) if SSL 2.0 is the only protocol enabled in the + client; similarly, in s23_srvr.c, don't do the rollback check if + SSL 2.0 is the only protocol enabled in the server. + + *Bodo Moeller* + + * Make it possible to get hexdumps of unprintable data with 'openssl + asn1parse'. By implication, the functions ASN1_parse_dump() and + BIO_dump_indent() are added. + + *Richard Levitte* + + * New functions ASN1_STRING_print_ex() and X509_NAME_print_ex() + these print out strings and name structures based on various + flags including RFC2253 support and proper handling of + multibyte characters. Added options to the 'x509' utility + to allow the various flags to be set. + + *Steve Henson* + + * Various fixes to use ASN1_TIME instead of ASN1_UTCTIME. + Also change the functions X509_cmp_current_time() and + X509_gmtime_adj() work with an ASN1_TIME structure, + this will enable certificates using GeneralizedTime in validity + dates to be checked. + + *Steve Henson* + + * Make the NEG_PUBKEY_BUG code (which tolerates invalid + negative public key encodings) on by default, + NO_NEG_PUBKEY_BUG can be set to disable it. + + *Steve Henson* + + * New function c2i_ASN1_OBJECT() which acts on ASN1_OBJECT + content octets. An i2c_ASN1_OBJECT is unnecessary because + the encoding can be trivially obtained from the structure. + + *Steve Henson* + + * crypto/err.c locking bugfix: Use write locks (`CRYPTO_w_[un]lock`), + not read locks (`CRYPTO_r_[un]lock`). + + *Bodo Moeller* + + * A first attempt at creating official support for shared + libraries through configuration. I've kept it so the + default is static libraries only, and the OpenSSL programs + are always statically linked for now, but there are + preparations for dynamic linking in place. + This has been tested on Linux and Tru64. + + *Richard Levitte* + + * Randomness polling function for Win9x, as described in: + Peter Gutmann, Software Generation of Practically Strong + Random Numbers. + + *Ulf Möller* + + * Fix so PRNG is seeded in req if using an already existing + DSA key. + + *Steve Henson* + + * New options to smime application. -inform and -outform + allow alternative formats for the S/MIME message including + PEM and DER. The -content option allows the content to be + specified separately. This should allow things like Netscape + form signing output easier to verify. + + *Steve Henson* + + * Fix the ASN1 encoding of tags using the 'long form'. + + *Steve Henson* + + * New ASN1 functions, `i2c_*` and `c2i_*` for INTEGER and BIT + STRING types. These convert content octets to and from the + underlying type. The actual tag and length octets are + already assumed to have been read in and checked. These + are needed because all other string types have virtually + identical handling apart from the tag. By having versions + of the ASN1 functions that just operate on content octets + IMPLICIT tagging can be handled properly. It also allows + the ASN1_ENUMERATED code to be cut down because ASN1_ENUMERATED + and ASN1_INTEGER are identical apart from the tag. + + *Steve Henson* + + * Change the handling of OID objects as follows: + + - New object identifiers are inserted in objects.txt, following + the syntax given in [crypto/objects/README.md](crypto/objects/README.md). + - objects.pl is used to process obj_mac.num and create a new + obj_mac.h. + - obj_dat.pl is used to create a new obj_dat.h, using the data in + obj_mac.h. + + This is currently kind of a hack, and the perl code in objects.pl + isn't very elegant, but it works as I intended. The simplest way + to check that it worked correctly is to look in obj_dat.h and + check the array nid_objs and make sure the objects haven't moved + around (this is important!). Additions are OK, as well as + consistent name changes. + + *Richard Levitte* + + * Add BSD-style MD5-based passwords to 'openssl passwd' (option '-1'). + + *Bodo Moeller* + + * Addition of the command line parameter '-rand file' to 'openssl req'. + The given file adds to whatever has already been seeded into the + random pool through the RANDFILE configuration file option or + environment variable, or the default random state file. + + *Richard Levitte* + + * mkstack.pl now sorts each macro group into lexical order. + Previously the output order depended on the order the files + appeared in the directory, resulting in needless rewriting + of safestack.h . + + *Steve Henson* + + * Patches to make OpenSSL compile under Win32 again. Mostly + work arounds for the VC++ problem that it treats func() as + func(void). Also stripped out the parts of mkdef.pl that + added extra typesafe functions: these no longer exist. + + *Steve Henson* + + * Reorganisation of the stack code. The macros are now all + collected in safestack.h . Each macro is defined in terms of + a "stack macro" of the form `SKM_(type, a, b)`. The + DEBUG_SAFESTACK is now handled in terms of function casts, + this has the advantage of retaining type safety without the + use of additional functions. If DEBUG_SAFESTACK is not defined + then the non typesafe macros are used instead. Also modified the + mkstack.pl script to handle the new form. Needs testing to see + if which (if any) compilers it chokes and maybe make DEBUG_SAFESTACK + the default if no major problems. Similar behaviour for ASN1_SET_OF + and PKCS12_STACK_OF. + + *Steve Henson* + + * When some versions of IIS use the 'NET' form of private key the + key derivation algorithm is different. Normally MD5(password) is + used as a 128 bit RC4 key. In the modified case + MD5(MD5(password) + "SGCKEYSALT") is used instead. Added some + new functions i2d_RSA_NET(), d2i_RSA_NET() etc which are the same + as the old Netscape_RSA functions except they have an additional + 'sgckey' parameter which uses the modified algorithm. Also added + an -sgckey command line option to the rsa utility. Thanks to + Adrian Peck for posting details of the modified + algorithm to openssl-dev. + + *Steve Henson* + + * The evp_local.h macros were using 'c.##kname' which resulted in + invalid expansion on some systems (SCO 5.0.5 for example). + Corrected to 'c.kname'. + + *Phillip Porch * + + * New X509_get1_email() and X509_REQ_get1_email() functions that return + a STACK of email addresses from a certificate or request, these look + in the subject name and the subject alternative name extensions and + omit any duplicate addresses. + + *Steve Henson* + + * Re-implement BN_mod_exp2_mont using independent (and larger) windows. + This makes DSA verification about 2 % faster. + + *Bodo Moeller* + + * Increase maximum window size in `BN_mod_exp_...` to 6 bits instead of 5 + (meaning that now 2^5 values will be precomputed, which is only 4 KB + plus overhead for 1024 bit moduli). + This makes exponentiations about 0.5 % faster for 1024 bit + exponents (as measured by "openssl speed rsa2048"). + + *Bodo Moeller* + + * Rename memory handling macros to avoid conflicts with other + software: + Malloc => OPENSSL_malloc + Malloc_locked => OPENSSL_malloc_locked + Realloc => OPENSSL_realloc + Free => OPENSSL_free + + *Richard Levitte* + + * New function BN_mod_exp_mont_word for small bases (roughly 15% + faster than BN_mod_exp_mont, i.e. 7% for a full DH exchange). + + *Bodo Moeller* + + * CygWin32 support. + + *John Jarvie * + + * The type-safe stack code has been rejigged. It is now only compiled + in when OpenSSL is configured with the DEBUG_SAFESTACK option and + by default all type-specific stack functions are "#define"d back to + standard stack functions. This results in more streamlined output + but retains the type-safety checking possibilities of the original + approach. + + *Geoff Thorpe* + + * The STACK code has been cleaned up, and certain type declarations + that didn't make a lot of sense have been brought in line. This has + also involved a cleanup of sorts in safestack.h to more correctly + map type-safe stack functions onto their plain stack counterparts. + This work has also resulted in a variety of "const"ifications of + lots of the code, especially `_cmp` operations which should normally + be prototyped with "const" parameters anyway. + + *Geoff Thorpe* + + * When generating bytes for the first time in md_rand.c, 'stir the pool' + by seeding with STATE_SIZE dummy bytes (with zero entropy count). + (The PRNG state consists of two parts, the large pool 'state' and 'md', + where all of 'md' is used each time the PRNG is used, but 'state' + is used only indexed by a cyclic counter. As entropy may not be + well distributed from the beginning, 'md' is important as a + chaining variable. However, the output function chains only half + of 'md', i.e. 80 bits. ssleay_rand_add, on the other hand, chains + all of 'md', and seeding with STATE_SIZE dummy bytes will result + in all of 'state' being rewritten, with the new values depending + on virtually all of 'md'. This overcomes the 80 bit limitation.) + + *Bodo Moeller* + + * In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when + the handshake is continued after ssl_verify_cert_chain(); + otherwise, if SSL_VERIFY_NONE is set, remaining error codes + can lead to 'unexplainable' connection aborts later. + + *Bodo Moeller; problem tracked down by Lutz Jaenicke* + + * Major EVP API cipher revision. + Add hooks for extra EVP features. This allows various cipher + parameters to be set in the EVP interface. Support added for variable + key length ciphers via the EVP_CIPHER_CTX_set_key_length() function and + setting of RC2 and RC5 parameters. + + Modify EVP_OpenInit() and EVP_SealInit() to cope with variable key length + ciphers. + + Remove lots of duplicated code from the EVP library. For example *every* + cipher init() function handles the 'iv' in the same way according to the + cipher mode. They also all do nothing if the 'key' parameter is NULL and + for CFB and OFB modes they zero ctx->num. + + New functionality allows removal of S/MIME code RC2 hack. + + Most of the routines have the same form and so can be declared in terms + of macros. + + By shifting this to the top level EVP_CipherInit() it can be removed from + all individual ciphers. If the cipher wants to handle IVs or keys + differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT + flags. + + Change lots of functions like EVP_EncryptUpdate() to now return a + value: although software versions of the algorithms cannot fail + any installed hardware versions can. + + *Steve Henson* + + * Implement SSL_OP_TLS_ROLLBACK_BUG: In ssl3_get_client_key_exchange, if + this option is set, tolerate broken clients that send the negotiated + protocol version number instead of the requested protocol version + number. + + *Bodo Moeller* + + * Call dh_tmp_cb (set by `..._TMP_DH_CB`) with correct 'is_export' flag; + i.e. non-zero for export ciphersuites, zero otherwise. + Previous versions had this flag inverted, inconsistent with + rsa_tmp_cb (..._TMP_RSA_CB). + + *Bodo Moeller; problem reported by Amit Chopra* + + * Add missing DSA library text string. Work around for some IIS + key files with invalid SEQUENCE encoding. + + *Steve Henson* + + * Add a document (doc/standards.txt) that list all kinds of standards + and so on that are implemented in OpenSSL. + + *Richard Levitte* + + * Enhance c_rehash script. Old version would mishandle certificates + with the same subject name hash and wouldn't handle CRLs at all. + Added -fingerprint option to crl utility, to support new c_rehash + features. + + *Steve Henson* + + * Eliminate non-ANSI declarations in crypto.h and stack.h. + + *Ulf Möller* + + * Fix for SSL server purpose checking. Server checking was + rejecting certificates which had extended key usage present + but no ssl client purpose. + + *Steve Henson, reported by Rene Grosser * + + * Make PKCS#12 code work with no password. The PKCS#12 spec + is a little unclear about how a blank password is handled. + Since the password in encoded as a BMPString with terminating + double NULL a zero length password would end up as just the + double NULL. However no password at all is different and is + handled differently in the PKCS#12 key generation code. NS + treats a blank password as zero length. MSIE treats it as no + password on export: but it will try both on import. We now do + the same: PKCS12_parse() tries zero length and no password if + the password is set to "" or NULL (NULL is now a valid password: + it wasn't before) as does the pkcs12 application. + + *Steve Henson* + + * Bugfixes in `apps/x509.c`: Avoid a memory leak; and don't use + perror when PEM_read_bio_X509_REQ fails, the error message must + be obtained from the error queue. + + *Bodo Moeller* + + * Avoid 'thread_hash' memory leak in crypto/err/err.c by freeing + it in ERR_remove_state if appropriate, and change ERR_get_state + accordingly to avoid race conditions (this is necessary because + thread_hash is no longer constant once set). + + *Bodo Moeller* + + * Bugfix for linux-elf makefile.one. + + *Ulf Möller* + + * RSA_get_default_method() will now cause a default + RSA_METHOD to be chosen if one doesn't exist already. + Previously this was only set during a call to RSA_new() + or RSA_new_method(NULL) meaning it was possible for + RSA_get_default_method() to return NULL. + + *Geoff Thorpe* + + * Added native name translation to the existing DSO code + that will convert (if the flag to do so is set) filenames + that are sufficiently small and have no path information + into a canonical native form. Eg. "blah" converted to + "libblah.so" or "blah.dll" etc. + + *Geoff Thorpe* + + * New function ERR_error_string_n(e, buf, len) which is like + ERR_error_string(e, buf), but writes at most 'len' bytes + including the 0 terminator. For ERR_error_string_n, 'buf' + may not be NULL. + + *Damien Miller , Bodo Moeller* + + * CONF library reworked to become more general. A new CONF + configuration file reader "class" is implemented as well as a + new functions (`NCONF_*`, for "New CONF") to handle it. The now + old `CONF_*` functions are still there, but are reimplemented to + work in terms of the new functions. Also, a set of functions + to handle the internal storage of the configuration data is + provided to make it easier to write new configuration file + reader "classes" (I can definitely see something reading a + configuration file in XML format, for example), called `_CONF_*`, + or "the configuration storage API"... + + The new configuration file reading functions are: + + NCONF_new, NCONF_free, NCONF_load, NCONF_load_fp, NCONF_load_bio, + NCONF_get_section, NCONF_get_string, NCONF_get_numbre + + NCONF_default, NCONF_WIN32 + + NCONF_dump_fp, NCONF_dump_bio + + NCONF_default and NCONF_WIN32 are method (or "class") choosers, + NCONF_new creates a new CONF object. This works in the same way + as other interfaces in OpenSSL, like the BIO interface. + `NCONF_dump_*` dump the internal storage of the configuration file, + which is useful for debugging. All other functions take the same + arguments as the old `CONF_*` functions with the exception of the + first that must be a `CONF *` instead of a `LHASH *`. + + To make it easier to use the new classes with the old `CONF_*` functions, + the function CONF_set_default_method is provided. + + *Richard Levitte* + + * Add '-tls1' option to 'openssl ciphers', which was already + mentioned in the documentation but had not been implemented. + (This option is not yet really useful because even the additional + experimental TLS 1.0 ciphers are currently treated as SSL 3.0 ciphers.) + + *Bodo Moeller* + + * Initial DSO code added into libcrypto for letting OpenSSL (and + OpenSSL-based applications) load shared libraries and bind to + them in a portable way. + + *Geoff Thorpe, with contributions from Richard Levitte* + +### Changes between 0.9.5 and 0.9.5a [1 Apr 2000] + + * Make sure _lrotl and _lrotr are only used with MSVC. + + * Use lock CRYPTO_LOCK_RAND correctly in ssleay_rand_status + (the default implementation of RAND_status). + + * Rename openssl x509 option '-crlext', which was added in 0.9.5, + to '-clrext' (= clear extensions), as intended and documented. + *Bodo Moeller; inconsistency pointed out by Michael Attili + * + + * Fix for HMAC. It wasn't zeroing the rest of the block if the key length + was larger than the MD block size. + + *Steve Henson, pointed out by Yost William * + + * Modernise PKCS12_parse() so it uses STACK_OF(X509) for its ca argument + fix a leak when the ca argument was passed as NULL. Stop X509_PUBKEY_set() + using the passed key: if the passed key was a private key the result + of X509_print(), for example, would be to print out all the private key + components. + + *Steve Henson* + + * des_quad_cksum() byte order bug fix. + *Ulf Möller, using the problem description in krb4-0.9.7, where + the solution is attributed to Derrick J Brashear * + + * Fix so V_ASN1_APP_CHOOSE works again: however its use is strongly + discouraged. + + *Steve Henson, pointed out by Brian Korver * + + * For easily testing in shell scripts whether some command + 'openssl XXX' exists, the new pseudo-command 'openssl no-XXX' + returns with exit code 0 iff no command of the given name is available. + 'no-XXX' is printed in this case, 'XXX' otherwise. In both cases, + the output goes to stdout and nothing is printed to stderr. + Additional arguments are always ignored. + + Since for each cipher there is a command of the same name, + the 'no-cipher' compilation switches can be tested this way. + + ('openssl no-XXX' is not able to detect pseudo-commands such + as 'quit', 'list-XXX-commands', or 'no-XXX' itself.) + + *Bodo Moeller* + + * Update test suite so that 'make test' succeeds in 'no-rsa' configuration. + + *Bodo Moeller* + + * For SSL_[CTX_]set_tmp_dh, don't create a DH key if SSL_OP_SINGLE_DH_USE + is set; it will be thrown away anyway because each handshake creates + its own key. + ssl_cert_dup, which is used by SSL_new, now copies DH keys in addition + to parameters -- in previous versions (since OpenSSL 0.9.3) the + 'default key' from SSL_CTX_set_tmp_dh would always be lost, meaning + you effectively got SSL_OP_SINGLE_DH_USE when using this macro. + + *Bodo Moeller* + + * New s_client option -ign_eof: EOF at stdin is ignored, and + 'Q' and 'R' lose their special meanings (quit/renegotiate). + This is part of what -quiet does; unlike -quiet, -ign_eof + does not suppress any output. + + *Richard Levitte* + + * Add compatibility options to the purpose and trust code. The + purpose X509_PURPOSE_ANY is "any purpose" which automatically + accepts a certificate or CA, this was the previous behaviour, + with all the associated security issues. + + X509_TRUST_COMPAT is the old trust behaviour: only and + automatically trust self signed roots in certificate store. A + new trust setting X509_TRUST_DEFAULT is used to specify that + a purpose has no associated trust setting and it should instead + use the value in the default purpose. + + *Steve Henson* + + * Fix the PKCS#8 DSA private key code so it decodes keys again + and fix a memory leak. + + *Steve Henson* + + * In util/mkerr.pl (which implements 'make errors'), preserve + reason strings from the previous version of the .c file, as + the default to have only downcase letters (and digits) in + automatically generated reasons codes is not always appropriate. + + *Bodo Moeller* + + * In ERR_load_ERR_strings(), build an ERR_LIB_SYS error reason table + using strerror. Previously, ERR_reason_error_string() returned + library names as reason strings for SYSerr; but SYSerr is a special + case where small numbers are errno values, not library numbers. + + *Bodo Moeller* + + * Add '-dsaparam' option to 'openssl dhparam' application. This + converts DSA parameters into DH parameters. (When creating parameters, + DSA_generate_parameters is used.) + + *Bodo Moeller* + + * Include 'length' (recommended exponent length) in C code generated + by 'openssl dhparam -C'. + + *Bodo Moeller* + + * The second argument to set_label in perlasm was already being used + so couldn't be used as a "file scope" flag. Moved to third argument + which was free. + + *Steve Henson* + + * In PEM_ASN1_write_bio and some other functions, use RAND_pseudo_bytes + instead of RAND_bytes for encryption IVs and salts. + + *Bodo Moeller* + + * Include RAND_status() into RAND_METHOD instead of implementing + it only for md_rand.c Otherwise replacing the PRNG by calling + RAND_set_rand_method would be impossible. + + *Bodo Moeller* + + * Don't let DSA_generate_key() enter an infinite loop if the random + number generation fails. + + *Bodo Moeller* + + * New 'rand' application for creating pseudo-random output. + + *Bodo Moeller* + + * Added configuration support for Linux/IA64 + + *Rolf Haberrecker * + + * Assembler module support for Mingw32. + + *Ulf Möller* + + * Shared library support for HPUX (in shlib/). + + *Lutz Jaenicke and Anonymous* + + * Shared library support for Solaris gcc. + + *Lutz Behnke * + +### Changes between 0.9.4 and 0.9.5 [28 Feb 2000] + + * PKCS7_encrypt() was adding text MIME headers twice because they + were added manually and by SMIME_crlf_copy(). + + *Steve Henson* + + * In bntest.c don't call BN_rand with zero bits argument. + + *Steve Henson, pointed out by Andrew W. Gray * + + * BN_mul bugfix: In bn_mul_part_recursion() only the a>a[n] && b>b[n] + case was implemented. This caused BN_div_recp() to fail occasionally. + + *Ulf Möller* + + * Add an optional second argument to the set_label() in the perl + assembly language builder. If this argument exists and is set + to 1 it signals that the assembler should use a symbol whose + scope is the entire file, not just the current function. This + is needed with MASM which uses the format label:: for this scope. + + *Steve Henson, pointed out by Peter Runestig * + + * Change the ASN1 types so they are typedefs by default. Before + almost all types were #define'd to ASN1_STRING which was causing + STACK_OF() problems: you couldn't declare STACK_OF(ASN1_UTF8STRING) + for example. + + *Steve Henson* + + * Change names of new functions to the new get1/get0 naming + convention: After 'get1', the caller owns a reference count + and has to call `..._free`; 'get0' returns a pointer to some + data structure without incrementing reference counters. + (Some of the existing 'get' functions increment a reference + counter, some don't.) + Similarly, 'set1' and 'add1' functions increase reference + counters or duplicate objects. + + *Steve Henson* + + * Allow for the possibility of temp RSA key generation failure: + the code used to assume it always worked and crashed on failure. + + *Steve Henson* + + * Fix potential buffer overrun problem in BIO_printf(). + *Ulf Möller, using public domain code by Patrick Powell; problem + pointed out by David Sacerdote * + + * Support EGD . New functions + RAND_egd() and RAND_status(). In the command line application, + the EGD socket can be specified like a seed file using RANDFILE + or -rand. + + *Ulf Möller* + + * Allow the string CERTIFICATE to be tolerated in PKCS#7 structures. + Some CAs (e.g. Verisign) distribute certificates in this form. + + *Steve Henson* + + * Remove the SSL_ALLOW_ADH compile option and set the default cipher + list to exclude them. This means that no special compilation option + is needed to use anonymous DH: it just needs to be included in the + cipher list. + + *Steve Henson* + + * Change the EVP_MD_CTX_type macro so its meaning consistent with + EVP_MD_type. The old functionality is available in a new macro called + EVP_MD_md(). Change code that uses it and update docs. + + *Steve Henson* + + * `..._ctrl` functions now have corresponding `..._callback_ctrl` functions + where the `void *` argument is replaced by a function pointer argument. + Previously `void *` was abused to point to functions, which works on + many platforms, but is not correct. As these functions are usually + called by macros defined in OpenSSL header files, most source code + should work without changes. + + *Richard Levitte* + + * `` (which is created by Configure) now contains + sections with information on -D... compiler switches used for + compiling the library so that applications can see them. To enable + one of these sections, a pre-processor symbol `OPENSSL_..._DEFINES` + must be defined. E.g., + #define OPENSSL_ALGORITHM_DEFINES + #include + defines all pertinent `NO_` symbols, such as NO_IDEA, NO_RSA, etc. + + *Richard Levitte, Ulf and Bodo Möller* + + * Bugfix: Tolerate fragmentation and interleaving in the SSL 3/TLS + record layer. + + *Bodo Moeller* + + * Change the 'other' type in certificate aux info to a STACK_OF + X509_ALGOR. Although not an AlgorithmIdentifier as such it has + the required ASN1 format: arbitrary types determined by an OID. + + *Steve Henson* + + * Add some PEM_write_X509_REQ_NEW() functions and a command line + argument to 'req'. This is not because the function is newer or + better than others it just uses the work 'NEW' in the certificate + request header lines. Some software needs this. + + *Steve Henson* + + * Reorganise password command line arguments: now passwords can be + obtained from various sources. Delete the PEM_cb function and make + it the default behaviour: i.e. if the callback is NULL and the + usrdata argument is not NULL interpret it as a null terminated pass + phrase. If usrdata and the callback are NULL then the pass phrase + is prompted for as usual. + + *Steve Henson* + + * Add support for the Compaq Atalla crypto accelerator. If it is installed, + the support is automatically enabled. The resulting binaries will + autodetect the card and use it if present. + + *Ben Laurie and Compaq Inc.* + + * Work around for Netscape hang bug. This sends certificate request + and server done in one record. Since this is perfectly legal in the + SSL/TLS protocol it isn't a "bug" option and is on by default. See + the bugs/SSLv3 entry for more info. + + *Steve Henson* + + * HP-UX tune-up: new unified configs, HP C compiler bug workaround. + + *Andy Polyakov* + + * Add -rand argument to smime and pkcs12 applications and read/write + of seed file. + + *Steve Henson* + + * New 'passwd' tool for crypt(3) and apr1 password hashes. + + *Bodo Moeller* + + * Add command line password options to the remaining applications. + + *Steve Henson* + + * Bug fix for BN_div_recp() for numerators with an even number of + bits. + + *Ulf Möller* + + * More tests in bntest.c, and changed test_bn output. + + *Ulf Möller* + + * ./config recognizes MacOS X now. + + *Andy Polyakov* + + * Bug fix for BN_div() when the first words of num and divisor are + equal (it gave wrong results if `(rem=(n1-q*d0)&BN_MASK2) < d0)`. + + *Ulf Möller* + + * Add support for various broken PKCS#8 formats, and command line + options to produce them. + + *Steve Henson* + + * New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to + get temporary BIGNUMs from a BN_CTX. + + *Ulf Möller* + + * Correct return values in BN_mod_exp_mont() and BN_mod_exp2_mont() + for p == 0. + + *Ulf Möller* + + * Change the `SSLeay_add_all_*()` functions to `OpenSSL_add_all_*()` and + include a #define from the old name to the new. The original intent + was that statically linked binaries could for example just call + SSLeay_add_all_ciphers() to just add ciphers to the table and not + link with digests. This never worked because SSLeay_add_all_digests() + and SSLeay_add_all_ciphers() were in the same source file so calling + one would link with the other. They are now in separate source files. + + *Steve Henson* + + * Add a new -notext option to 'ca' and a -pubkey option to 'spkac'. + + *Steve Henson* + + * Use a less unusual form of the Miller-Rabin primality test (it used + a binary algorithm for exponentiation integrated into the Miller-Rabin + loop, our standard modexp algorithms are faster). + + *Bodo Moeller* + + * Support for the EBCDIC character set completed. + + *Martin Kraemer * + + * Source code cleanups: use const where appropriate, eliminate casts, + use `void *` instead of `char *` in lhash. + + *Ulf Möller* + + * Bugfix: ssl3_send_server_key_exchange was not restartable + (the state was not changed to SSL3_ST_SW_KEY_EXCH_B, and because of + this the server could overwrite ephemeral keys that the client + has already seen). + + *Bodo Moeller* + + * Turn DSA_is_prime into a macro that calls BN_is_prime, + using 50 iterations of the Rabin-Miller test. + + DSA_generate_parameters now uses BN_is_prime_fasttest (with 50 + iterations of the Rabin-Miller test as required by the appendix + to FIPS PUB 186[-1]) instead of DSA_is_prime. + As BN_is_prime_fasttest includes trial division, DSA parameter + generation becomes much faster. + + This implies a change for the callback functions in DSA_is_prime + and DSA_generate_parameters: The callback function is called once + for each positive witness in the Rabin-Miller test, not just + occasionally in the inner loop; and the parameters to the + callback function now provide an iteration count for the outer + loop rather than for the current invocation of the inner loop. + DSA_generate_parameters additionally can call the callback + function with an 'iteration count' of -1, meaning that a + candidate has passed the trial division test (when q is generated + from an application-provided seed, trial division is skipped). + + *Bodo Moeller* + + * New function BN_is_prime_fasttest that optionally does trial + division before starting the Rabin-Miller test and has + an additional BN_CTX * argument (whereas BN_is_prime always + has to allocate at least one BN_CTX). + 'callback(1, -1, cb_arg)' is called when a number has passed the + trial division stage. + + *Bodo Moeller* + + * Fix for bug in CRL encoding. The validity dates weren't being handled + as ASN1_TIME. + + *Steve Henson* + + * New -pkcs12 option to CA.pl script to write out a PKCS#12 file. + + *Steve Henson* + + * New function BN_pseudo_rand(). + + *Ulf Möller* + + * Clean up BN_mod_mul_montgomery(): replace the broken (and unreadable) + bignum version of BN_from_montgomery() with the working code from + SSLeay 0.9.0 (the word based version is faster anyway), and clean up + the comments. + + *Ulf Möller* + + * Avoid a race condition in s2_clnt.c (function get_server_hello) that + made it impossible to use the same SSL_SESSION data structure in + SSL2 clients in multiple threads. + + *Bodo Moeller* + + * The return value of RAND_load_file() no longer counts bytes obtained + by stat(). RAND_load_file(..., -1) is new and uses the complete file + to seed the PRNG (previously an explicit byte count was required). + + *Ulf Möller, Bodo Möller* + + * Clean up CRYPTO_EX_DATA functions, some of these didn't have prototypes + used `char *` instead of `void *` and had casts all over the place. + + *Steve Henson* + + * Make BN_generate_prime() return NULL on error if ret!=NULL. + + *Ulf Möller* + + * Retain source code compatibility for BN_prime_checks macro: + BN_is_prime(..., BN_prime_checks, ...) now uses + BN_prime_checks_for_size to determine the appropriate number of + Rabin-Miller iterations. + + *Ulf Möller* + + * Diffie-Hellman uses "safe" primes: DH_check() return code renamed to + DH_CHECK_P_NOT_SAFE_PRIME. + (Check if this is true? OpenPGP calls them "strong".) + + *Ulf Möller* + + * Merge the functionality of "dh" and "gendh" programs into a new program + "dhparam". The old programs are retained for now but will handle DH keys + (instead of parameters) in future. + + *Steve Henson* + + * Make the ciphers, s_server and s_client programs check the return values + when a new cipher list is set. + + *Steve Henson* + + * Enhance the SSL/TLS cipher mechanism to correctly handle the TLS 56bit + ciphers. Before when the 56bit ciphers were enabled the sorting was + wrong. + + The syntax for the cipher sorting has been extended to support sorting by + cipher-strength (using the strength_bits hard coded in the tables). + The new command is `@STRENGTH` (see also `doc/apps/ciphers.pod`). + + Fix a bug in the cipher-command parser: when supplying a cipher command + string with an "undefined" symbol (neither command nor alphanumeric + *A-Za-z0-9*, ssl_set_cipher_list used to hang in an endless loop. Now + an error is flagged. + + Due to the strength-sorting extension, the code of the + ssl_create_cipher_list() function was completely rearranged. I hope that + the readability was also increased :-) + + *Lutz Jaenicke * + + * Minor change to 'x509' utility. The -CAcreateserial option now uses 1 + for the first serial number and places 2 in the serial number file. This + avoids problems when the root CA is created with serial number zero and + the first user certificate has the same issuer name and serial number + as the root CA. + + *Steve Henson* + + * Fixes to X509_ATTRIBUTE utilities, change the 'req' program so it uses + the new code. Add documentation for this stuff. + + *Steve Henson* + + * Changes to X509_ATTRIBUTE utilities. These have been renamed from + `X509_*()` to `X509at_*()` on the grounds that they don't handle X509 + structures and behave in an analogous way to the X509v3 functions: + they shouldn't be called directly but wrapper functions should be used + instead. + + So we also now have some wrapper functions that call the X509at functions + when passed certificate requests. (TO DO: similar things can be done with + PKCS#7 signed and unsigned attributes, PKCS#12 attributes and a few other + things. Some of these need some d2i or i2d and print functionality + because they handle more complex structures.) + + *Steve Henson* + + * Add missing #ifndefs that caused missing symbols when building libssl + as a shared library without RSA. Use #ifndef NO_SSL2 instead of + NO_RSA in `ssl/s2*.c`. + + *Kris Kennaway , modified by Ulf Möller* + + * Precautions against using the PRNG uninitialized: RAND_bytes() now + has a return value which indicates the quality of the random data + (1 = ok, 0 = not seeded). Also an error is recorded on the thread's + error queue. New function RAND_pseudo_bytes() generates output that is + guaranteed to be unique but not unpredictable. RAND_add is like + RAND_seed, but takes an extra argument for an entropy estimate + (RAND_seed always assumes full entropy). + + *Ulf Möller* + + * Do more iterations of Rabin-Miller probable prime test (specifically, + 3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes + instead of only 2 for all lengths; see BN_prime_checks_for_size definition + in crypto/bn/bn_prime.c for the complete table). This guarantees a + false-positive rate of at most 2^-80 for random input. + + *Bodo Moeller* + + * Rewrite ssl3_read_n (ssl/s3_pkt.c) avoiding a couple of bugs. + + *Bodo Moeller* + + * New function X509_CTX_rget_chain() (renamed to X509_CTX_get1_chain + in the 0.9.5 release), this returns the chain + from an X509_CTX structure with a dup of the stack and all + the X509 reference counts upped: so the stack will exist + after X509_CTX_cleanup() has been called. Modify pkcs12.c + to use this. + + Also make SSL_SESSION_print() print out the verify return + code. + + *Steve Henson* + + * Add manpage for the pkcs12 command. Also change the default + behaviour so MAC iteration counts are used unless the new + -nomaciter option is used. This improves file security and + only older versions of MSIE (4.0 for example) need it. + + *Steve Henson* + + * Honor the no-xxx Configure options when creating .DEF files. + + *Ulf Möller* + + * Add PKCS#10 attributes to field table: challengePassword, + unstructuredName and unstructuredAddress. These are taken from + draft PKCS#9 v2.0 but are compatible with v1.2 provided no + international characters are used. + + More changes to X509_ATTRIBUTE code: allow the setting of types + based on strings. Remove the 'loc' parameter when adding + attributes because these will be a SET OF encoding which is sorted + in ASN1 order. + + *Steve Henson* + + * Initial changes to the 'req' utility to allow request generation + automation. This will allow an application to just generate a template + file containing all the field values and have req construct the + request. + + Initial support for X509_ATTRIBUTE handling. Stacks of these are + used all over the place including certificate requests and PKCS#7 + structures. They are currently handled manually where necessary with + some primitive wrappers for PKCS#7. The new functions behave in a + manner analogous to the X509 extension functions: they allow + attributes to be looked up by NID and added. + + Later something similar to the X509V3 code would be desirable to + automatically handle the encoding, decoding and printing of the + more complex types. The string types like challengePassword can + be handled by the string table functions. + + Also modified the multi byte string table handling. Now there is + a 'global mask' which masks out certain types. The table itself + can use the flag STABLE_NO_MASK to ignore the mask setting: this + is useful when for example there is only one permissible type + (as in countryName) and using the mask might result in no valid + types at all. + + *Steve Henson* + + * Clean up 'Finished' handling, and add functions SSL_get_finished and + SSL_get_peer_finished to allow applications to obtain the latest + Finished messages sent to the peer or expected from the peer, + respectively. (SSL_get_peer_finished is usually the Finished message + actually received from the peer, otherwise the protocol will be aborted.) + + As the Finished message are message digests of the complete handshake + (with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can + be used for external authentication procedures when the authentication + provided by SSL/TLS is not desired or is not enough. + + *Bodo Moeller* + + * Enhanced support for Alpha Linux is added. Now ./config checks if + the host supports BWX extension and if Compaq C is present on the + $PATH. Just exploiting of the BWX extension results in 20-30% + performance kick for some algorithms, e.g. DES and RC4 to mention + a couple. Compaq C in turn generates ~20% faster code for MD5 and + SHA1. + + *Andy Polyakov* + + * Add support for MS "fast SGC". This is arguably a violation of the + SSL3/TLS protocol. Netscape SGC does two handshakes: the first with + weak crypto and after checking the certificate is SGC a second one + with strong crypto. MS SGC stops the first handshake after receiving + the server certificate message and sends a second client hello. Since + a server will typically do all the time consuming operations before + expecting any further messages from the client (server key exchange + is the most expensive) there is little difference between the two. + + To get OpenSSL to support MS SGC we have to permit a second client + hello message after we have sent server done. In addition we have to + reset the MAC if we do get this second client hello. + + *Steve Henson* + + * Add a function 'd2i_AutoPrivateKey()' this will automatically decide + if a DER encoded private key is RSA or DSA traditional format. Changed + d2i_PrivateKey_bio() to use it. This is only needed for the "traditional" + format DER encoded private key. Newer code should use PKCS#8 format which + has the key type encoded in the ASN1 structure. Added DER private key + support to pkcs8 application. + + *Steve Henson* + + * SSL 3/TLS 1 servers now don't request certificates when an anonymous + ciphersuites has been selected (as required by the SSL 3/TLS 1 + specifications). Exception: When SSL_VERIFY_FAIL_IF_NO_PEER_CERT + is set, we interpret this as a request to violate the specification + (the worst that can happen is a handshake failure, and 'correct' + behaviour would result in a handshake failure anyway). + + *Bodo Moeller* + + * In SSL_CTX_add_session, take into account that there might be multiple + SSL_SESSION structures with the same session ID (e.g. when two threads + concurrently obtain them from an external cache). + The internal cache can handle only one SSL_SESSION with a given ID, + so if there's a conflict, we now throw out the old one to achieve + consistency. + + *Bodo Moeller* + + * Add OIDs for idea and blowfish in CBC mode. This will allow both + to be used in PKCS#5 v2.0 and S/MIME. Also add checking to + some routines that use cipher OIDs: some ciphers do not have OIDs + defined and so they cannot be used for S/MIME and PKCS#5 v2.0 for + example. + + *Steve Henson* + + * Simplify the trust setting structure and code. Now we just have + two sequences of OIDs for trusted and rejected settings. These will + typically have values the same as the extended key usage extension + and any application specific purposes. + + The trust checking code now has a default behaviour: it will just + check for an object with the same NID as the passed id. Functions can + be provided to override either the default behaviour or the behaviour + for a given id. SSL client, server and email already have functions + in place for compatibility: they check the NID and also return "trusted" + if the certificate is self signed. + + *Steve Henson* + + * Add d2i,i2d bio/fp functions for PrivateKey: these convert the + traditional format into an EVP_PKEY structure. + + *Steve Henson* + + * Add a password callback function PEM_cb() which either prompts for + a password if usr_data is NULL or otherwise assumes it is a null + terminated password. Allow passwords to be passed on command line + environment or config files in a few more utilities. + + *Steve Henson* + + * Add a bunch of DER and PEM functions to handle PKCS#8 format private + keys. Add some short names for PKCS#8 PBE algorithms and allow them + to be specified on the command line for the pkcs8 and pkcs12 utilities. + Update documentation. + + *Steve Henson* + + * Support for ASN1 "NULL" type. This could be handled before by using + ASN1_TYPE but there wasn't any function that would try to read a NULL + and produce an error if it couldn't. For compatibility we also have + ASN1_NULL_new() and ASN1_NULL_free() functions but these are faked and + don't allocate anything because they don't need to. + + *Steve Henson* + + * Initial support for MacOS is now provided. Examine INSTALL.MacOS + for details. + + *Andy Polyakov, Roy Woods * + + * Rebuild of the memory allocation routines used by OpenSSL code and + possibly others as well. The purpose is to make an interface that + provide hooks so anyone can build a separate set of allocation and + deallocation routines to be used by OpenSSL, for example memory + pool implementations, or something else, which was previously hard + since Malloc(), Realloc() and Free() were defined as macros having + the values malloc, realloc and free, respectively (except for Win32 + compilations). The same is provided for memory debugging code. + OpenSSL already comes with functionality to find memory leaks, but + this gives people a chance to debug other memory problems. + + With these changes, a new set of functions and macros have appeared: + + CRYPTO_set_mem_debug_functions() [F] + CRYPTO_get_mem_debug_functions() [F] + CRYPTO_dbg_set_options() [F] + CRYPTO_dbg_get_options() [F] + CRYPTO_malloc_debug_init() [M] + + The memory debug functions are NULL by default, unless the library + is compiled with CRYPTO_MDEBUG or friends is defined. If someone + wants to debug memory anyway, CRYPTO_malloc_debug_init() (which + gives the standard debugging functions that come with OpenSSL) or + CRYPTO_set_mem_debug_functions() (tells OpenSSL to use functions + provided by the library user) must be used. When the standard + debugging functions are used, CRYPTO_dbg_set_options can be used to + request additional information: + CRYPTO_dbg_set_options(V_CYRPTO_MDEBUG_xxx) corresponds to setting + the CRYPTO_MDEBUG_xxx macro when compiling the library. + + Also, things like CRYPTO_set_mem_functions will always give the + expected result (the new set of functions is used for allocation + and deallocation) at all times, regardless of platform and compiler + options. + + To finish it up, some functions that were never use in any other + way than through macros have a new API and new semantic: + + CRYPTO_dbg_malloc() + CRYPTO_dbg_realloc() + CRYPTO_dbg_free() + + All macros of value have retained their old syntax. + + *Richard Levitte and Bodo Moeller* + + * Some S/MIME fixes. The OID for SMIMECapabilities was wrong, the + ordering of SMIMECapabilities wasn't in "strength order" and there + was a missing NULL in the AlgorithmIdentifier for the SHA1 signature + algorithm. + + *Steve Henson* + + * Some ASN1 types with illegal zero length encoding (INTEGER, + ENUMERATED and OBJECT IDENTIFIER) choked the ASN1 routines. + + *Frans Heymans , modified by Steve Henson* + + * Merge in my S/MIME library for OpenSSL. This provides a simple + S/MIME API on top of the PKCS#7 code, a MIME parser (with enough + functionality to handle multipart/signed properly) and a utility + called 'smime' to call all this stuff. This is based on code I + originally wrote for Celo who have kindly allowed it to be + included in OpenSSL. + + *Steve Henson* + + * Add variants des_set_key_checked and des_set_key_unchecked of + des_set_key (aka des_key_sched). Global variable des_check_key + decides which of these is called by des_set_key; this way + des_check_key behaves as it always did, but applications and + the library itself, which was buggy for des_check_key == 1, + have a cleaner way to pick the version they need. + + *Bodo Moeller* + + * New function PKCS12_newpass() which changes the password of a + PKCS12 structure. + + *Steve Henson* + + * Modify X509_TRUST and X509_PURPOSE so it also uses a static and + dynamic mix. In both cases the ids can be used as an index into the + table. Also modified the X509_TRUST_add() and X509_PURPOSE_add() + functions so they accept a list of the field values and the + application doesn't need to directly manipulate the X509_TRUST + structure. + + *Steve Henson* + + * Modify the ASN1_STRING_TABLE stuff so it also uses bsearch and doesn't + need initialising. + + *Steve Henson* + + * Modify the way the V3 extension code looks up extensions. This now + works in a similar way to the object code: we have some "standard" + extensions in a static table which is searched with OBJ_bsearch() + and the application can add dynamic ones if needed. The file + crypto/x509v3/ext_dat.h now has the info: this file needs to be + updated whenever a new extension is added to the core code and kept + in ext_nid order. There is a simple program 'tabtest.c' which checks + this. New extensions are not added too often so this file can readily + be maintained manually. + + There are two big advantages in doing things this way. The extensions + can be looked up immediately and no longer need to be "added" using + X509V3_add_standard_extensions(): this function now does nothing. + Side note: I get *lots* of email saying the extension code doesn't + work because people forget to call this function. + Also no dynamic allocation is done unless new extensions are added: + so if we don't add custom extensions there is no need to call + X509V3_EXT_cleanup(). + + *Steve Henson* + + * Modify enc utility's salting as follows: make salting the default. Add a + magic header, so unsalted files fail gracefully instead of just decrypting + to garbage. This is because not salting is a big security hole, so people + should be discouraged from doing it. + + *Ben Laurie* + + * Fixes and enhancements to the 'x509' utility. It allowed a message + digest to be passed on the command line but it only used this + parameter when signing a certificate. Modified so all relevant + operations are affected by the digest parameter including the + -fingerprint and -x509toreq options. Also -x509toreq choked if a + DSA key was used because it didn't fix the digest. + + *Steve Henson* + + * Initial certificate chain verify code. Currently tests the untrusted + certificates for consistency with the verify purpose (which is set + when the X509_STORE_CTX structure is set up) and checks the pathlength. + + There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour: + this is because it will reject chains with invalid extensions whereas + every previous version of OpenSSL and SSLeay made no checks at all. + + Trust code: checks the root CA for the relevant trust settings. Trust + settings have an initial value consistent with the verify purpose: e.g. + if the verify purpose is for SSL client use it expects the CA to be + trusted for SSL client use. However the default value can be changed to + permit custom trust settings: one example of this would be to only trust + certificates from a specific "secure" set of CAs. + + Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions + which should be used for version portability: especially since the + verify structure is likely to change more often now. + + SSL integration. Add purpose and trust to SSL_CTX and SSL and functions + to set them. If not set then assume SSL clients will verify SSL servers + and vice versa. + + Two new options to the verify program: -untrusted allows a set of + untrusted certificates to be passed in and -purpose which sets the + intended purpose of the certificate. If a purpose is set then the + new chain verify code is used to check extension consistency. + + *Steve Henson* + + * Support for the authority information access extension. + + *Steve Henson* + + * Modify RSA and DSA PEM read routines to transparently handle + PKCS#8 format private keys. New *_PUBKEY_* functions that handle + public keys in a format compatible with certificate + SubjectPublicKeyInfo structures. Unfortunately there were already + functions called *_PublicKey_* which used various odd formats so + these are retained for compatibility: however the DSA variants were + never in a public release so they have been deleted. Changed dsa/rsa + utilities to handle the new format: note no releases ever handled public + keys so we should be OK. + + The primary motivation for this change is to avoid the same fiasco + that dogs private keys: there are several incompatible private key + formats some of which are standard and some OpenSSL specific and + require various evil hacks to allow partial transparent handling and + even then it doesn't work with DER formats. Given the option anything + other than PKCS#8 should be dumped: but the other formats have to + stay in the name of compatibility. + + With public keys and the benefit of hindsight one standard format + is used which works with EVP_PKEY, RSA or DSA structures: though + it clearly returns an error if you try to read the wrong kind of key. + + Added a -pubkey option to the 'x509' utility to output the public key. + Also rename the `EVP_PKEY_get_*()` to `EVP_PKEY_rget_*()` + (renamed to `EVP_PKEY_get1_*()` in the OpenSSL 0.9.5 release) and add + `EVP_PKEY_rset_*()` functions (renamed to `EVP_PKEY_set1_*()`) + that do the same as the `EVP_PKEY_assign_*()` except they up the + reference count of the added key (they don't "swallow" the + supplied key). + + *Steve Henson* + + * Fixes to crypto/x509/by_file.c the code to read in certificates and + CRLs would fail if the file contained no certificates or no CRLs: + added a new function to read in both types and return the number + read: this means that if none are read it will be an error. The + DER versions of the certificate and CRL reader would always fail + because it isn't possible to mix certificates and CRLs in DER format + without choking one or the other routine. Changed this to just read + a certificate: this is the best we can do. Also modified the code + in `apps/verify.c` to take notice of return codes: it was previously + attempting to read in certificates from NULL pointers and ignoring + any errors: this is one reason why the cert and CRL reader seemed + to work. It doesn't check return codes from the default certificate + routines: these may well fail if the certificates aren't installed. + + *Steve Henson* + + * Code to support otherName option in GeneralName. + + *Steve Henson* + + * First update to verify code. Change the verify utility + so it warns if it is passed a self signed certificate: + for consistency with the normal behaviour. X509_verify + has been modified to it will now verify a self signed + certificate if *exactly* the same certificate appears + in the store: it was previously impossible to trust a + single self signed certificate. This means that: + openssl verify ss.pem + now gives a warning about a self signed certificate but + openssl verify -CAfile ss.pem ss.pem + is OK. + + *Steve Henson* + + * For servers, store verify_result in SSL_SESSION data structure + (and add it to external session representation). + This is needed when client certificate verifications fails, + but an application-provided verification callback (set by + SSL_CTX_set_cert_verify_callback) allows accepting the session + anyway (i.e. leaves x509_store_ctx->error != X509_V_OK + but returns 1): When the session is reused, we have to set + ssl->verify_result to the appropriate error code to avoid + security holes. + + *Bodo Moeller, problem pointed out by Lutz Jaenicke* + + * Fix a bug in the new PKCS#7 code: it didn't consider the + case in PKCS7_dataInit() where the signed PKCS7 structure + didn't contain any existing data because it was being created. + + *Po-Cheng Chen , slightly modified by Steve Henson* + + * Add a salt to the key derivation routines in enc.c. This + forms the first 8 bytes of the encrypted file. Also add a + -S option to allow a salt to be input on the command line. + + *Steve Henson* + + * New function X509_cmp(). Oddly enough there wasn't a function + to compare two certificates. We do this by working out the SHA1 + hash and comparing that. X509_cmp() will be needed by the trust + code. + + *Steve Henson* + + * SSL_get1_session() is like SSL_get_session(), but increments + the reference count in the SSL_SESSION returned. + + *Geoff Thorpe * + + * Fix for 'req': it was adding a null to request attributes. + Also change the X509_LOOKUP and X509_INFO code to handle + certificate auxiliary information. + + *Steve Henson* + + * Add support for 40 and 64 bit RC2 and RC4 algorithms: document + the 'enc' command. + + *Steve Henson* + + * Add the possibility to add extra information to the memory leak + detecting output, to form tracebacks, showing from where each + allocation was originated: CRYPTO_push_info("constant string") adds + the string plus current file name and line number to a per-thread + stack, CRYPTO_pop_info() does the obvious, CRYPTO_remove_all_info() + is like calling CYRPTO_pop_info() until the stack is empty. + Also updated memory leak detection code to be multi-thread-safe. + + *Richard Levitte* + + * Add options -text and -noout to pkcs7 utility and delete the + encryption options which never did anything. Update docs. + + *Steve Henson* + + * Add options to some of the utilities to allow the pass phrase + to be included on either the command line (not recommended on + OSes like Unix) or read from the environment. Update the + manpages and fix a few bugs. + + *Steve Henson* + + * Add a few manpages for some of the openssl commands. + + *Steve Henson* + + * Fix the -revoke option in ca. It was freeing up memory twice, + leaking and not finding already revoked certificates. + + *Steve Henson* + + * Extensive changes to support certificate auxiliary information. + This involves the use of X509_CERT_AUX structure and X509_AUX + functions. An X509_AUX function such as PEM_read_X509_AUX() + can still read in a certificate file in the usual way but it + will also read in any additional "auxiliary information". By + doing things this way a fair degree of compatibility can be + retained: existing certificates can have this information added + using the new 'x509' options. + + Current auxiliary information includes an "alias" and some trust + settings. The trust settings will ultimately be used in enhanced + certificate chain verification routines: currently a certificate + can only be trusted if it is self signed and then it is trusted + for all purposes. + + *Steve Henson* + + * Fix assembler for Alpha (tested only on DEC OSF not Linux or `*BSD`). + The problem was that one of the replacement routines had not been working + since SSLeay releases. For now the offending routine has been replaced + with non-optimised assembler. Even so, this now gives around 95% + performance improvement for 1024 bit RSA signs. + + *Mark Cox* + + * Hack to fix PKCS#7 decryption when used with some unorthodox RC2 + handling. Most clients have the effective key size in bits equal to + the key length in bits: so a 40 bit RC2 key uses a 40 bit (5 byte) key. + A few however don't do this and instead use the size of the decrypted key + to determine the RC2 key length and the AlgorithmIdentifier to determine + the effective key length. In this case the effective key length can still + be 40 bits but the key length can be 168 bits for example. This is fixed + by manually forcing an RC2 key into the EVP_PKEY structure because the + EVP code can't currently handle unusual RC2 key sizes: it always assumes + the key length and effective key length are equal. + + *Steve Henson* + + * Add a bunch of functions that should simplify the creation of + X509_NAME structures. Now you should be able to do: + X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0); + and have it automatically work out the correct field type and fill in + the structures. The more adventurous can try: + X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0); + and it will (hopefully) work out the correct multibyte encoding. + + *Steve Henson* + + * Change the 'req' utility to use the new field handling and multibyte + copy routines. Before the DN field creation was handled in an ad hoc + way in req, ca, and x509 which was rather broken and didn't support + BMPStrings or UTF8Strings. Since some software doesn't implement + BMPStrings or UTF8Strings yet, they can be enabled using the config file + using the dirstring_type option. See the new comment in the default + openssl.cnf for more info. + + *Steve Henson* + + * Make crypto/rand/md_rand.c more robust: + - Assure unique random numbers after fork(). + - Make sure that concurrent threads access the global counter and + md serializably so that we never lose entropy in them + or use exactly the same state in multiple threads. + Access to the large state is not always serializable because + the additional locking could be a performance killer, and + md should be large enough anyway. + + *Bodo Moeller* + + * New file `apps/app_rand.c` with commonly needed functionality + for handling the random seed file. + + Use the random seed file in some applications that previously did not: + ca, + dsaparam -genkey (which also ignored its '-rand' option), + s_client, + s_server, + x509 (when signing). + Except on systems with /dev/urandom, it is crucial to have a random + seed file at least for key creation, DSA signing, and for DH exchanges; + for RSA signatures we could do without one. + + gendh and gendsa (unlike genrsa) used to read only the first byte + of each file listed in the '-rand' option. The function as previously + found in genrsa is now in app_rand.c and is used by all programs + that support '-rand'. + + *Bodo Moeller* + + * In RAND_write_file, use mode 0600 for creating files; + don't just chmod when it may be too late. + + *Bodo Moeller* + + * Report an error from X509_STORE_load_locations + when X509_LOOKUP_load_file or X509_LOOKUP_add_dir failed. + + *Bill Perry* + + * New function ASN1_mbstring_copy() this copies a string in either + ASCII, Unicode, Universal (4 bytes per character) or UTF8 format + into an ASN1_STRING type. A mask of permissible types is passed + and it chooses the "minimal" type to use or an error if not type + is suitable. + + *Steve Henson* + + * Add function equivalents to the various macros in asn1.h. The old + macros are retained with an `M_` prefix. Code inside the library can + use the `M_` macros. External code (including the openssl utility) + should *NOT* in order to be "shared library friendly". + + *Steve Henson* + + * Add various functions that can check a certificate's extensions + to see if it usable for various purposes such as SSL client, + server or S/MIME and CAs of these types. This is currently + VERY EXPERIMENTAL but will ultimately be used for certificate chain + verification. Also added a -purpose flag to x509 utility to + print out all the purposes. + + *Steve Henson* + + * Add a CRYPTO_EX_DATA to X509 certificate structure and associated + functions. + + *Steve Henson* + + * New `X509V3_{X509,CRL,REVOKED}_get_d2i()` functions. These will search + for, obtain and decode and extension and obtain its critical flag. + This allows all the necessary extension code to be handled in a + single function call. + + *Steve Henson* + + * RC4 tune-up featuring 30-40% performance improvement on most RISC + platforms. See crypto/rc4/rc4_enc.c for further details. + + *Andy Polyakov* + + * New -noout option to asn1parse. This causes no output to be produced + its main use is when combined with -strparse and -out to extract data + from a file (which may not be in ASN.1 format). + + *Steve Henson* + + * Fix for pkcs12 program. It was hashing an invalid certificate pointer + when producing the local key id. + + *Richard Levitte * + + * New option -dhparam in s_server. This allows a DH parameter file to be + stated explicitly. If it is not stated then it tries the first server + certificate file. The previous behaviour hard coded the filename + "server.pem". + + *Steve Henson* + + * Add -pubin and -pubout options to the rsa and dsa commands. These allow + a public key to be input or output. For example: + openssl rsa -in key.pem -pubout -out pubkey.pem + Also added necessary DSA public key functions to handle this. + + *Steve Henson* + + * Fix so PKCS7_dataVerify() doesn't crash if no certificates are contained + in the message. This was handled by allowing + X509_find_by_issuer_and_serial() to tolerate a NULL passed to it. + + *Steve Henson, reported by Sampo Kellomaki * + + * Fix for bug in d2i_ASN1_bytes(): other ASN1 functions add an extra null + to the end of the strings whereas this didn't. This would cause problems + if strings read with d2i_ASN1_bytes() were later modified. + + *Steve Henson, reported by Arne Ansper * + + * Fix for base64 decode bug. When a base64 bio reads only one line of + data and it contains EOF it will end up returning an error. This is + caused by input 46 bytes long. The cause is due to the way base64 + BIOs find the start of base64 encoded data. They do this by trying a + trial decode on each line until they find one that works. When they + do a flag is set and it starts again knowing it can pass all the + data directly through the decoder. Unfortunately it doesn't reset + the context it uses. This means that if EOF is reached an attempt + is made to pass two EOFs through the context and this causes the + resulting error. This can also cause other problems as well. As is + usual with these problems it takes *ages* to find and the fix is + trivial: move one line. + + *Steve Henson, reported by ian@uns.ns.ac.yu (Ivan Nejgebauer)* + + * Ugly workaround to get s_client and s_server working under Windows. The + old code wouldn't work because it needed to select() on sockets and the + tty (for keypresses and to see if data could be written). Win32 only + supports select() on sockets so we select() with a 1s timeout on the + sockets and then see if any characters are waiting to be read, if none + are present then we retry, we also assume we can always write data to + the tty. This isn't nice because the code then blocks until we've + received a complete line of data and it is effectively polling the + keyboard at 1s intervals: however it's quite a bit better than not + working at all :-) A dedicated Windows application might handle this + with an event loop for example. + + *Steve Henson* + + * Enhance RSA_METHOD structure. Now there are two extra methods, rsa_sign + and rsa_verify. When the RSA_FLAGS_SIGN_VER option is set these functions + will be called when RSA_sign() and RSA_verify() are used. This is useful + if rsa_pub_dec() and rsa_priv_enc() equivalents are not available. + For this to work properly RSA_public_decrypt() and RSA_private_encrypt() + should *not* be used: RSA_sign() and RSA_verify() must be used instead. + This necessitated the support of an extra signature type NID_md5_sha1 + for SSL signatures and modifications to the SSL library to use it instead + of calling RSA_public_decrypt() and RSA_private_encrypt(). + + *Steve Henson* + + * Add new -verify -CAfile and -CApath options to the crl program, these + will lookup a CRL issuers certificate and verify the signature in a + similar way to the verify program. Tidy up the crl program so it + no longer accesses structures directly. Make the ASN1 CRL parsing a bit + less strict. It will now permit CRL extensions even if it is not + a V2 CRL: this will allow it to tolerate some broken CRLs. + + *Steve Henson* + + * Initialize all non-automatic variables each time one of the openssl + sub-programs is started (this is necessary as they may be started + multiple times from the "OpenSSL>" prompt). + + *Lennart Bang, Bodo Moeller* + + * Preliminary compilation option RSA_NULL which disables RSA crypto without + removing all other RSA functionality (this is what NO_RSA does). This + is so (for example) those in the US can disable those operations covered + by the RSA patent while allowing storage and parsing of RSA keys and RSA + key generation. + + *Steve Henson* + + * Non-copying interface to BIO pairs. + (still largely untested) + + *Bodo Moeller* + + * New function ASN1_tag2str() to convert an ASN1 tag to a descriptive + ASCII string. This was handled independently in various places before. + + *Steve Henson* + + * New functions UTF8_getc() and UTF8_putc() that parse and generate + UTF8 strings a character at a time. + + *Steve Henson* + + * Use client_version from client hello to select the protocol + (s23_srvr.c) and for RSA client key exchange verification + (s3_srvr.c), as required by the SSL 3.0/TLS 1.0 specifications. + + *Bodo Moeller* + + * Add various utility functions to handle SPKACs, these were previously + handled by poking round in the structure internals. Added new function + NETSCAPE_SPKI_print() to print out SPKAC and a new utility 'spkac' to + print, verify and generate SPKACs. Based on an original idea from + Massimiliano Pala but extensively modified. + + *Steve Henson* + + * RIPEMD160 is operational on all platforms and is back in 'make test'. + + *Andy Polyakov* + + * Allow the config file extension section to be overwritten on the + command line. Based on an original idea from Massimiliano Pala + . The new option is called -extensions + and can be applied to ca, req and x509. Also -reqexts to override + the request extensions in req and -crlexts to override the crl extensions + in ca. + + *Steve Henson* + + * Add new feature to the SPKAC handling in ca. Now you can include + the same field multiple times by preceding it by "XXXX." for example: + 1.OU="Unit name 1" + 2.OU="Unit name 2" + this is the same syntax as used in the req config file. + + *Steve Henson* + + * Allow certificate extensions to be added to certificate requests. These + are specified in a 'req_extensions' option of the req section of the + config file. They can be printed out with the -text option to req but + are otherwise ignored at present. + + *Steve Henson* + + * Fix a horrible bug in enc_read() in crypto/evp/bio_enc.c: if the first + data read consists of only the final block it would not decrypted because + EVP_CipherUpdate() would correctly report zero bytes had been decrypted. + A misplaced 'break' also meant the decrypted final block might not be + copied until the next read. + + *Steve Henson* + + * Initial support for DH_METHOD. Again based on RSA_METHOD. Also added + a few extra parameters to the DH structure: these will be useful if + for example we want the value of 'q' or implement X9.42 DH. + + *Steve Henson* + + * Initial support for DSA_METHOD. This is based on the RSA_METHOD and + provides hooks that allow the default DSA functions or functions on a + "per key" basis to be replaced. This allows hardware acceleration and + hardware key storage to be handled without major modification to the + library. Also added low-level modexp hooks and CRYPTO_EX structure and + associated functions. + + *Steve Henson* + + * Add a new flag to memory BIOs, BIO_FLAG_MEM_RDONLY. This marks the BIO + as "read only": it can't be written to and the buffer it points to will + not be freed. Reading from a read only BIO is much more efficient than + a normal memory BIO. This was added because there are several times when + an area of memory needs to be read from a BIO. The previous method was + to create a memory BIO and write the data to it, this results in two + copies of the data and an O(n^2) reading algorithm. There is a new + function BIO_new_mem_buf() which creates a read only memory BIO from + an area of memory. Also modified the PKCS#7 routines to use read only + memory BIOs. + + *Steve Henson* + + * Bugfix: ssl23_get_client_hello did not work properly when called in + state SSL23_ST_SR_CLNT_HELLO_B, i.e. when the first 7 bytes of + a SSLv2-compatible client hello for SSLv3 or TLSv1 could be read, + but a retry condition occurred while trying to read the rest. + + *Bodo Moeller* + + * The PKCS7_ENC_CONTENT_new() function was setting the content type as + NID_pkcs7_encrypted by default: this was wrong since this should almost + always be NID_pkcs7_data. Also modified the PKCS7_set_type() to handle + the encrypted data type: this is a more sensible place to put it and it + allows the PKCS#12 code to be tidied up that duplicated this + functionality. + + *Steve Henson* + + * Changed obj_dat.pl script so it takes its input and output files on + the command line. This should avoid shell escape redirection problems + under Win32. + + *Steve Henson* + + * Initial support for certificate extension requests, these are included + in things like Xenroll certificate requests. Included functions to allow + extensions to be obtained and added. + + *Steve Henson* + + * -crlf option to s_client and s_server for sending newlines as + CRLF (as required by many protocols). + + *Bodo Moeller* + +### Changes between 0.9.3a and 0.9.4 [09 Aug 1999] + + * Install libRSAglue.a when OpenSSL is built with RSAref. + + *Ralf S. Engelschall* + + * A few more `#ifndef NO_FP_API / #endif` pairs for consistency. + + *Andrija Antonijevic * + + * Fix -startdate and -enddate (which was missing) arguments to 'ca' + program. + + *Steve Henson* + + * New function DSA_dup_DH, which duplicates DSA parameters/keys as + DH parameters/keys (q is lost during that conversion, but the resulting + DH parameters contain its length). + + For 1024-bit p, DSA_generate_parameters followed by DSA_dup_DH is + much faster than DH_generate_parameters (which creates parameters + where `p = 2*q + 1`), and also the smaller q makes DH computations + much more efficient (160-bit exponentiation instead of 1024-bit + exponentiation); so this provides a convenient way to support DHE + ciphersuites in SSL/TLS servers (see ssl/ssltest.c). It is of + utter importance to use + SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); + or + SSL_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); + when such DH parameters are used, because otherwise small subgroup + attacks may become possible! + + *Bodo Moeller* + + * Avoid memory leak in i2d_DHparams. + + *Bodo Moeller* + + * Allow the -k option to be used more than once in the enc program: + this allows the same encrypted message to be read by multiple recipients. + + *Steve Henson* + + * New function OBJ_obj2txt(buf, buf_len, a, no_name), this converts + an ASN1_OBJECT to a text string. If the "no_name" parameter is set then + it will always use the numerical form of the OID, even if it has a short + or long name. + + *Steve Henson* + + * Added an extra RSA flag: RSA_FLAG_EXT_PKEY. Previously the rsa_mod_exp + method only got called if p,q,dmp1,dmq1,iqmp components were present, + otherwise bn_mod_exp was called. In the case of hardware keys for example + no private key components need be present and it might store extra data + in the RSA structure, which cannot be accessed from bn_mod_exp. + By setting RSA_FLAG_EXT_PKEY rsa_mod_exp will always be called for + private key operations. + + *Steve Henson* + + * Added support for SPARC Linux. + + *Andy Polyakov* + + * pem_password_cb function type incompatibly changed from + typedef int pem_password_cb(char *buf, int size, int rwflag); + to + ....(char *buf, int size, int rwflag, void *userdata); + so that applications can pass data to their callbacks: + The `PEM[_ASN1]_{read,write}...` functions and macros now take an + additional void * argument, which is just handed through whenever + the password callback is called. + + *Damien Miller ; tiny changes by Bodo Moeller* + + New function SSL_CTX_set_default_passwd_cb_userdata. + + Compatibility note: As many C implementations push function arguments + onto the stack in reverse order, the new library version is likely to + interoperate with programs that have been compiled with the old + pem_password_cb definition (PEM_whatever takes some data that + happens to be on the stack as its last argument, and the callback + just ignores this garbage); but there is no guarantee whatsoever that + this will work. + + * The -DPLATFORM="\"$(PLATFORM)\"" definition and the similar -DCFLAGS=... + (both in crypto/Makefile.ssl for use by crypto/cversion.c) caused + problems not only on Windows, but also on some Unix platforms. + To avoid problematic command lines, these definitions are now in an + auto-generated file crypto/buildinf.h (created by crypto/Makefile.ssl + for standard "make" builds, by util/mk1mf.pl for "mk1mf" builds). + + *Bodo Moeller* + + * MIPS III/IV assembler module is reimplemented. + + *Andy Polyakov* + + * More DES library cleanups: remove references to srand/rand and + delete an unused file. + + *Ulf Möller* + + * Add support for the free Netwide assembler (NASM) under Win32, + since not many people have MASM (ml) and it can be hard to obtain. + This is currently experimental but it seems to work OK and pass all + the tests. Check out INSTALL.W32 for info. + + *Steve Henson* + + * Fix memory leaks in s3_clnt.c: All non-anonymous SSL3/TLS1 connections + without temporary keys kept an extra copy of the server key, + and connections with temporary keys did not free everything in case + of an error. + + *Bodo Moeller* + + * New function RSA_check_key and new openssl rsa option -check + for verifying the consistency of RSA keys. + + *Ulf Moeller, Bodo Moeller* + + * Various changes to make Win32 compile work: + 1. Casts to avoid "loss of data" warnings in p5_crpt2.c + 2. Change unsigned int to int in b_dump.c to avoid "signed/unsigned + comparison" warnings. + 3. Add `sk__sort` to DEF file generator and do make update. + + *Steve Henson* + + * Add a debugging option to PKCS#5 v2 key generation function: when + you #define DEBUG_PKCS5V2 passwords, salts, iteration counts and + derived keys are printed to stderr. + + *Steve Henson* + + * Copy the flags in ASN1_STRING_dup(). + + *Roman E. Pavlov * + + * The x509 application mishandled signing requests containing DSA + keys when the signing key was also DSA and the parameters didn't match. + + It was supposed to omit the parameters when they matched the signing key: + the verifying software was then supposed to automatically use the CA's + parameters if they were absent from the end user certificate. + + Omitting parameters is no longer recommended. The test was also + the wrong way round! This was probably due to unusual behaviour in + EVP_cmp_parameters() which returns 1 if the parameters match. + This meant that parameters were omitted when they *didn't* match and + the certificate was useless. Certificates signed with 'ca' didn't have + this bug. + + *Steve Henson, reported by Doug Erickson * + + * Memory leak checking (-DCRYPTO_MDEBUG) had some problems. + The interface is as follows: + Applications can use + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) aka MemCheck_start(), + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) aka MemCheck_stop(); + "off" is now the default. + The library internally uses + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) aka MemCheck_off(), + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) aka MemCheck_on() + to disable memory-checking temporarily. + + Some inconsistent states that previously were possible (and were + even the default) are now avoided. + + -DCRYPTO_MDEBUG_TIME is new and additionally stores the current time + with each memory chunk allocated; this is occasionally more helpful + than just having a counter. + + -DCRYPTO_MDEBUG_THREAD is also new and adds the thread ID. + + -DCRYPTO_MDEBUG_ALL enables all of the above, plus any future + extensions. + + *Bodo Moeller* + + * Introduce "mode" for SSL structures (with defaults in SSL_CTX), + which largely parallels "options", but is for changing API behaviour, + whereas "options" are about protocol behaviour. + Initial "mode" flags are: + + SSL_MODE_ENABLE_PARTIAL_WRITE Allow SSL_write to report success when + a single record has been written. + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Don't insist that SSL_write + retries use the same buffer location. + (But all of the contents must be + copied!) + + *Bodo Moeller* + + * Bugfix: SSL_set_options ignored its parameter, only SSL_CTX_set_options + worked. + + * Fix problems with no-hmac etc. + + *Ulf Möller, pointed out by Brian Wellington * + + * New functions RSA_get_default_method(), RSA_set_method() and + RSA_get_method(). These allows replacement of RSA_METHODs without having + to mess around with the internals of an RSA structure. + + *Steve Henson* + + * Fix memory leaks in DSA_do_sign and DSA_is_prime. + Also really enable memory leak checks in openssl.c and in some + test programs. + + *Chad C. Mulligan, Bodo Moeller* + + * Fix a bug in d2i_ASN1_INTEGER() and i2d_ASN1_INTEGER() which can mess + up the length of negative integers. This has now been simplified to just + store the length when it is first determined and use it later, rather + than trying to keep track of where data is copied and updating it to + point to the end. + *Steve Henson, reported by Brien Wheeler * + + * Add a new function PKCS7_signatureVerify. This allows the verification + of a PKCS#7 signature but with the signing certificate passed to the + function itself. This contrasts with PKCS7_dataVerify which assumes the + certificate is present in the PKCS#7 structure. This isn't always the + case: certificates can be omitted from a PKCS#7 structure and be + distributed by "out of band" means (such as a certificate database). + + *Steve Henson* + + * Complete the `PEM_*` macros with DECLARE_PEM versions to replace the + function prototypes in pem.h, also change util/mkdef.pl to add the + necessary function names. + + *Steve Henson* + + * mk1mf.pl (used by Windows builds) did not properly read the + options set by Configure in the top level Makefile, and Configure + was not even able to write more than one option correctly. + Fixed, now "no-idea no-rc5 -DCRYPTO_MDEBUG" etc. works as intended. + + *Bodo Moeller* + + * New functions CONF_load_bio() and CONF_load_fp() to allow a config + file to be loaded from a BIO or FILE pointer. The BIO version will + for example allow memory BIOs to contain config info. + + *Steve Henson* + + * New function "CRYPTO_num_locks" that returns CRYPTO_NUM_LOCKS. + Whoever hopes to achieve shared-library compatibility across versions + must use this, not the compile-time macro. + (Exercise 0.9.4: Which is the minimum library version required by + such programs?) + Note: All this applies only to multi-threaded programs, others don't + need locks. + + *Bodo Moeller* + + * Add missing case to s3_clnt.c state machine -- one of the new SSL tests + through a BIO pair triggered the default case, i.e. + SSLerr(...,SSL_R_UNKNOWN_STATE). + + *Bodo Moeller* + + * New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications + can use the SSL library even if none of the specific BIOs is + appropriate. + + *Bodo Moeller* + + * Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value + for the encoded length. + + *Jeon KyoungHo * + + * Add initial documentation of the X509V3 functions. + + *Steve Henson* + + * Add a new pair of functions PEM_write_PKCS8PrivateKey() and + PEM_write_bio_PKCS8PrivateKey() that are equivalent to + PEM_write_PrivateKey() and PEM_write_bio_PrivateKey() but use the more + secure PKCS#8 private key format with a high iteration count. + + *Steve Henson* + + * Fix determination of Perl interpreter: A perl or perl5 + *directory* in $PATH was also accepted as the interpreter. + + *Ralf S. Engelschall* + + * Fix demos/sign/sign.c: well there wasn't anything strictly speaking + wrong with it but it was very old and did things like calling + PEM_ASN1_read() directly and used MD5 for the hash not to mention some + unusual formatting. + + *Steve Henson* + + * Fix demos/selfsign.c: it used obsolete and deleted functions, changed + to use the new extension code. + + *Steve Henson* + + * Implement the PEM_read/PEM_write functions in crypto/pem/pem_all.c + with macros. This should make it easier to change their form, add extra + arguments etc. Fix a few PEM prototypes which didn't have cipher as a + constant. + + *Steve Henson* + + * Add to configuration table a new entry that can specify an alternative + name for unistd.h (for pre-POSIX systems); we need this for NeXTstep, + according to Mark Crispin . + + *Bodo Moeller* + + * DES CBC did not update the IV. Weird. + + *Ben Laurie* +lse + des_cbc_encrypt does not update the IV, but des_ncbc_encrypt does. + Changing the behaviour of the former might break existing programs -- + where IV updating is needed, des_ncbc_encrypt can be used. +ndif + + * When bntest is run from "make test" it drives bc to check its + calculations, as well as internally checking them. If an internal check + fails, it needs to cause bc to give a non-zero result or make test carries + on without noticing the failure. Fixed. + + *Ben Laurie* + + * DES library cleanups. + + *Ulf Möller* + + * Add support for PKCS#5 v2.0 PBE algorithms. This will permit PKCS#8 to be + used with any cipher unlike PKCS#5 v1.5 which can at most handle 64 bit + ciphers. NOTE: although the key derivation function has been verified + against some published test vectors it has not been extensively tested + yet. Added a -v2 "cipher" option to pkcs8 application to allow the use + of v2.0. + + *Steve Henson* + + * Instead of "mkdir -p", which is not fully portable, use new + Perl script "util/mkdir-p.pl". + + *Bodo Moeller* + + * Rewrite the way password based encryption (PBE) is handled. It used to + assume that the ASN1 AlgorithmIdentifier parameter was a PBEParameter + structure. This was true for the PKCS#5 v1.5 and PKCS#12 PBE algorithms + but doesn't apply to PKCS#5 v2.0 where it can be something else. Now + the 'parameter' field of the AlgorithmIdentifier is passed to the + underlying key generation function so it must do its own ASN1 parsing. + This has also changed the EVP_PBE_CipherInit() function which now has a + 'parameter' argument instead of literal salt and iteration count values + and the function EVP_PBE_ALGOR_CipherInit() has been deleted. + + *Steve Henson* + + * Support for PKCS#5 v1.5 compatible password based encryption algorithms + and PKCS#8 functionality. New 'pkcs8' application linked to openssl. + Needed to change the PEM_STRING_EVP_PKEY value which was just "PRIVATE + KEY" because this clashed with PKCS#8 unencrypted string. Since this + value was just used as a "magic string" and not used directly its + value doesn't matter. + + *Steve Henson* + + * Introduce some semblance of const correctness to BN. Shame C doesn't + support mutable. + + *Ben Laurie* + + * "linux-sparc64" configuration (ultrapenguin). + + *Ray Miller * + "linux-sparc" configuration. + + *Christian Forster * + + * config now generates no-xxx options for missing ciphers. + + *Ulf Möller* + + * Support the EBCDIC character set (work in progress). + File ebcdic.c not yet included because it has a different license. + + *Martin Kraemer * + + * Support BS2000/OSD-POSIX. + + *Martin Kraemer * + + * Make callbacks for key generation use `void *` instead of `char *`. + + *Ben Laurie* + + * Make S/MIME samples compile (not yet tested). + + *Ben Laurie* + + * Additional typesafe stacks. + + *Ben Laurie* + + * New configuration variants "bsdi-elf-gcc" (BSD/OS 4.x). + + *Bodo Moeller* + +### Changes between 0.9.3 and 0.9.3a [29 May 1999] + + * New configuration variant "sco5-gcc". + + * Updated some demos. + + *Sean O Riordain, Wade Scholine* + + * Add missing BIO_free at exit of pkcs12 application. + + *Wu Zhigang* + + * Fix memory leak in conf.c. + + *Steve Henson* + + * Updates for Win32 to assembler version of MD5. + + *Steve Henson* + + * Set #! path to perl in `apps/der_chop` to where we found it + instead of using a fixed path. + + *Bodo Moeller* + + * SHA library changes for irix64-mips4-cc. + + *Andy Polyakov* + + * Improvements for VMS support. + + *Richard Levitte* + +### Changes between 0.9.2b and 0.9.3 [24 May 1999] + + * Bignum library bug fix. IRIX 6 passes "make test" now! + This also avoids the problems with SC4.2 and unpatched SC5. + + *Andy Polyakov * + + * New functions sk_num, sk_value and sk_set to replace the previous macros. + These are required because of the typesafe stack would otherwise break + existing code. If old code used a structure member which used to be STACK + and is now STACK_OF (for example cert in a PKCS7_SIGNED structure) with + sk_num or sk_value it would produce an error because the num, data members + are not present in STACK_OF. Now it just produces a warning. sk_set + replaces the old method of assigning a value to sk_value + (e.g. sk_value(x, i) = y) which the library used in a few cases. Any code + that does this will no longer work (and should use sk_set instead) but + this could be regarded as a "questionable" behaviour anyway. + + *Steve Henson* + + * Fix most of the other PKCS#7 bugs. The "experimental" code can now + correctly handle encrypted S/MIME data. + + *Steve Henson* + + * Change type of various DES function arguments from des_cblock + (which means, in function argument declarations, pointer to char) + to des_cblock * (meaning pointer to array with 8 char elements), + which allows the compiler to do more typechecking; it was like + that back in SSLeay, but with lots of ugly casts. + + Introduce new type const_des_cblock. + + *Bodo Moeller* + + * Reorganise the PKCS#7 library and get rid of some of the more obvious + problems: find RecipientInfo structure that matches recipient certificate + and initialise the ASN1 structures properly based on passed cipher. + + *Steve Henson* + + * Belatedly make the BN tests actually check the results. + + *Ben Laurie* + + * Fix the encoding and decoding of negative ASN1 INTEGERS and conversion + to and from BNs: it was completely broken. New compilation option + NEG_PUBKEY_BUG to allow for some broken certificates that encode public + key elements as negative integers. + + *Steve Henson* + + * Reorganize and speed up MD5. + + *Andy Polyakov * + + * VMS support. + + *Richard Levitte * + + * New option -out to asn1parse to allow the parsed structure to be + output to a file. This is most useful when combined with the -strparse + option to examine the output of things like OCTET STRINGS. + + *Steve Henson* + + * Make SSL library a little more fool-proof by not requiring any longer + that `SSL_set_{accept,connect}_state` be called before + `SSL_{accept,connect}` may be used (`SSL_set_..._state` is omitted + in many applications because usually everything *appeared* to work as + intended anyway -- now it really works as intended). + + *Bodo Moeller* + + * Move openssl.cnf out of lib/. + + *Ulf Möller* + + * Fix various things to let OpenSSL even pass "egcc -pipe -O2 -Wall + -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes + -Wmissing-declarations -Wnested-externs -Winline" with EGCS 1.1.2+ + + *Ralf S. Engelschall* + + * Various fixes to the EVP and PKCS#7 code. It may now be able to + handle PKCS#7 enveloped data properly. + + *Sebastian Akerman , modified by Steve* + + * Create a duplicate of the SSL_CTX's CERT in SSL_new instead of + copying pointers. The cert_st handling is changed by this in + various ways (and thus what used to be known as ctx->default_cert + is now called ctx->cert, since we don't resort to `s->ctx->[default_]cert` + any longer when s->cert does not give us what we need). + ssl_cert_instantiate becomes obsolete by this change. + As soon as we've got the new code right (possibly it already is?), + we have solved a couple of bugs of the earlier code where s->cert + was used as if it could not have been shared with other SSL structures. + + Note that using the SSL API in certain dirty ways now will result + in different behaviour than observed with earlier library versions: + Changing settings for an `SSL_CTX *ctx` after having done s = SSL_new(ctx) + does not influence s as it used to. + + In order to clean up things more thoroughly, inside SSL_SESSION + we don't use CERT any longer, but a new structure SESS_CERT + that holds per-session data (if available); currently, this is + the peer's certificate chain and, for clients, the server's certificate + and temporary key. CERT holds only those values that can have + meaningful defaults in an SSL_CTX. + + *Bodo Moeller* + + * New function X509V3_EXT_i2d() to create an X509_EXTENSION structure + from the internal representation. Various PKCS#7 fixes: remove some + evil casts and set the enc_dig_alg field properly based on the signing + key type. + + *Steve Henson* + + * Allow PKCS#12 password to be set from the command line or the + environment. Let 'ca' get its config file name from the environment + variables "OPENSSL_CONF" or "SSLEAY_CONF" (for consistency with 'req' + and 'x509'). + + *Steve Henson* + + * Allow certificate policies extension to use an IA5STRING for the + organization field. This is contrary to the PKIX definition but + VeriSign uses it and IE5 only recognises this form. Document 'x509' + extension option. + + *Steve Henson* + + * Add PEDANTIC compiler flag to allow compilation with gcc -pedantic, + without disallowing inline assembler and the like for non-pedantic builds. + + *Ben Laurie* + + * Support Borland C++ builder. + + *Janez Jere , modified by Ulf Möller* + + * Support Mingw32. + + *Ulf Möller* + + * SHA-1 cleanups and performance enhancements. + + *Andy Polyakov * + + * Sparc v8plus assembler for the bignum library. + + *Andy Polyakov * + + * Accept any -xxx and +xxx compiler options in Configure. + + *Ulf Möller* + + * Update HPUX configuration. + + *Anonymous* + + * Add missing `sk__unshift()` function to safestack.h + + *Ralf S. Engelschall* + + * New function SSL_CTX_use_certificate_chain_file that sets the + "extra_cert"s in addition to the certificate. (This makes sense + only for "PEM" format files, as chains as a whole are not + DER-encoded.) + + *Bodo Moeller* + + * Support verify_depth from the SSL API. + x509_vfy.c had what can be considered an off-by-one-error: + Its depth (which was not part of the external interface) + was actually counting the number of certificates in a chain; + now it really counts the depth. + + *Bodo Moeller* + + * Bugfix in crypto/x509/x509_cmp.c: The SSLerr macro was used + instead of X509err, which often resulted in confusing error + messages since the error codes are not globally unique + (e.g. an alleged error in ssl3_accept when a certificate + didn't match the private key). + + * New function SSL_CTX_set_session_id_context that allows to set a default + value (so that you don't need SSL_set_session_id_context for each + connection using the SSL_CTX). + + *Bodo Moeller* + + * OAEP decoding bug fix. + + *Ulf Möller* + + * Support INSTALL_PREFIX for package builders, as proposed by + David Harris. + + *Bodo Moeller* + + * New Configure options "threads" and "no-threads". For systems + where the proper compiler options are known (currently Solaris + and Linux), "threads" is the default. + + *Bodo Moeller* + + * New script util/mklink.pl as a faster substitute for util/mklink.sh. + + *Bodo Moeller* + + * Install various scripts to $(OPENSSLDIR)/misc, not to + $(INSTALLTOP)/bin -- they shouldn't clutter directories + such as /usr/local/bin. + + *Bodo Moeller* + + * "make linux-shared" to build shared libraries. + + *Niels Poppe * + + * New Configure option `no-` (rsa, idea, rc5, ...). + + *Ulf Möller* + + * Add the PKCS#12 API documentation to openssl.txt. Preliminary support for + extension adding in x509 utility. + + *Steve Henson* + + * Remove NOPROTO sections and error code comments. + + *Ulf Möller* + + * Partial rewrite of the DEF file generator to now parse the ANSI + prototypes. + + *Steve Henson* + + * New Configure options --prefix=DIR and --openssldir=DIR. + + *Ulf Möller* + + * Complete rewrite of the error code script(s). It is all now handled + by one script at the top level which handles error code gathering, + header rewriting and C source file generation. It should be much better + than the old method: it now uses a modified version of Ulf's parser to + read the ANSI prototypes in all header files (thus the old K&R definitions + aren't needed for error creation any more) and do a better job of + translating function codes into names. The old 'ASN1 error code embedded + in a comment' is no longer necessary and it doesn't use .err files which + have now been deleted. Also the error code call doesn't have to appear all + on one line (which resulted in some large lines...). + + *Steve Henson* + + * Change #include filenames from `` to ``. + + *Bodo Moeller* + + * Change behaviour of ssl2_read when facing length-0 packets: Don't return + 0 (which usually indicates a closed connection), but continue reading. + + *Bodo Moeller* + + * Fix some race conditions. + + *Bodo Moeller* + + * Add support for CRL distribution points extension. Add Certificate + Policies and CRL distribution points documentation. + + *Steve Henson* + + * Move the autogenerated header file parts to crypto/opensslconf.h. + + *Ulf Möller* + + * Fix new 56-bit DES export ciphersuites: they were using 7 bytes instead of + 8 of keying material. Merlin has also confirmed interop with this fix + between OpenSSL and Baltimore C/SSL 2.0 and J/SSL 2.0. + + *Merlin Hughes * + + * Fix lots of warnings. + + *Richard Levitte * + + * In add_cert_dir() in crypto/x509/by_dir.c, break out of the loop if + the directory spec didn't end with a LIST_SEPARATOR_CHAR. + + *Richard Levitte * + + * Fix problems with sizeof(long) == 8. + + *Andy Polyakov * + + * Change functions to ANSI C. + + *Ulf Möller* + + * Fix typos in error codes. + + *Martin Kraemer , Ulf Möller* + + * Remove defunct assembler files from Configure. + + *Ulf Möller* + + * SPARC v8 assembler BIGNUM implementation. + + *Andy Polyakov * + + * Support for Certificate Policies extension: both print and set. + Various additions to support the r2i method this uses. + + *Steve Henson* + + * A lot of constification, and fix a bug in X509_NAME_oneline() that could + return a const string when you are expecting an allocated buffer. + + *Ben Laurie* + + * Add support for ASN1 types UTF8String and VISIBLESTRING, also the CHOICE + types DirectoryString and DisplayText. + + *Steve Henson* + + * Add code to allow r2i extensions to access the configuration database, + add an LHASH database driver and add several ctx helper functions. + + *Steve Henson* + + * Fix an evil bug in bn_expand2() which caused various BN functions to + fail when they extended the size of a BIGNUM. + + *Steve Henson* + + * Various utility functions to handle SXNet extension. Modify mkdef.pl to + support typesafe stack. + + *Steve Henson* + + * Fix typo in SSL_[gs]et_options(). + + *Nils Frostberg * + + * Delete various functions and files that belonged to the (now obsolete) + old X509V3 handling code. + + *Steve Henson* + + * New Configure option "rsaref". + + *Ulf Möller* + + * Don't auto-generate pem.h. + + *Bodo Moeller* + + * Introduce type-safe ASN.1 SETs. + + *Ben Laurie* + + * Convert various additional casted stacks to type-safe STACK_OF() variants. + + *Ben Laurie, Ralf S. Engelschall, Steve Henson* + + * Introduce type-safe STACKs. This will almost certainly break lots of code + that links with OpenSSL (well at least cause lots of warnings), but fear + not: the conversion is trivial, and it eliminates loads of evil casts. A + few STACKed things have been converted already. Feel free to convert more. + In the fullness of time, I'll do away with the STACK type altogether. + + *Ben Laurie* + + * Add `openssl ca -revoke ` facility which revokes a certificate + specified in `` by updating the entry in the index.txt file. + This way one no longer has to edit the index.txt file manually for + revoking a certificate. The -revoke option does the gory details now. + + *Massimiliano Pala , Ralf S. Engelschall* + + * Fix `openssl crl -noout -text` combination where `-noout` killed the + `-text` option at all and this way the `-noout -text` combination was + inconsistent in `openssl crl` with the friends in `openssl x509|rsa|dsa`. + + *Ralf S. Engelschall* + + * Make sure a corresponding plain text error message exists for the + X509_V_ERR_CERT_REVOKED/23 error number which can occur when a + verify callback function determined that a certificate was revoked. + + *Ralf S. Engelschall* + + * Bugfix: In test/testenc, don't test `openssl ` for + ciphers that were excluded, e.g. by -DNO_IDEA. Also, test + all available ciphers including rc5, which was forgotten until now. + In order to let the testing shell script know which algorithms + are available, a new (up to now undocumented) command + `openssl list-cipher-commands` is used. + + *Bodo Moeller* + + * Bugfix: s_client occasionally would sleep in select() when + it should have checked SSL_pending() first. + + *Bodo Moeller* + + * New functions DSA_do_sign and DSA_do_verify to provide access to + the raw DSA values prior to ASN.1 encoding. + + *Ulf Möller* + + * Tweaks to Configure + + *Niels Poppe * + + * Add support for PKCS#5 v2.0 ASN1 PBES2 structures. No other support, + yet... + + *Steve Henson* + + * New variables $(RANLIB) and $(PERL) in the Makefiles. + + *Ulf Möller* + + * New config option to avoid instructions that are illegal on the 80386. + The default code is faster, but requires at least a 486. + + *Ulf Möller* + + * Got rid of old SSL2_CLIENT_VERSION (inconsistently used) and + SSL2_SERVER_VERSION (not used at all) macros, which are now the + same as SSL2_VERSION anyway. + + *Bodo Moeller* + + * New "-showcerts" option for s_client. + + *Bodo Moeller* + + * Still more PKCS#12 integration. Add pkcs12 application to openssl + application. Various cleanups and fixes. + + *Steve Henson* + + * More PKCS#12 integration. Add new pkcs12 directory with Makefile.ssl and + modify error routines to work internally. Add error codes and PBE init + to library startup routines. + + *Steve Henson* + + * Further PKCS#12 integration. Added password based encryption, PKCS#8 and + packing functions to asn1 and evp. Changed function names and error + codes along the way. + + *Steve Henson* + + * PKCS12 integration: and so it begins... First of several patches to + slowly integrate PKCS#12 functionality into OpenSSL. Add PKCS#12 + objects to objects.h + + *Steve Henson* + + * Add a new 'indent' option to some X509V3 extension code. Initial ASN1 + and display support for Thawte strong extranet extension. + + *Steve Henson* + + * Add LinuxPPC support. + + *Jeff Dubrule * + + * Get rid of redundant BN file bn_mulw.c, and rename bn_div64 to + bn_div_words in alpha.s. + + *Hannes Reinecke and Ben Laurie* + + * Make sure the RSA OAEP test is skipped under -DRSAref because + OAEP isn't supported when OpenSSL is built with RSAref. + + *Ulf Moeller * + + * Move definitions of IS_SET/IS_SEQUENCE inside crypto/asn1/asn1.h + so they no longer are missing under -DNOPROTO. + + *Soren S. Jorvang * + +### Changes between 0.9.1c and 0.9.2b [22 Mar 1999] + + * Make SSL_get_peer_cert_chain() work in servers. Unfortunately, it still + doesn't work when the session is reused. Coming soon! + + *Ben Laurie* + + * Fix a security hole, that allows sessions to be reused in the wrong + context thus bypassing client cert protection! All software that uses + client certs and session caches in multiple contexts NEEDS PATCHING to + allow session reuse! A fuller solution is in the works. + + *Ben Laurie, problem pointed out by Holger Reif, Bodo Moeller (and ???)* + + * Some more source tree cleanups (removed obsolete files + crypto/bf/asm/bf586.pl, test/test.txt and crypto/sha/asm/f.s; changed + permission on "config" script to be executable) and a fix for the INSTALL + document. + + *Ulf Moeller * + + * Remove some legacy and erroneous uses of malloc, free instead of + Malloc, Free. + + *Lennart Bang , with minor changes by Steve* + + * Make rsa_oaep_test return non-zero on error. + + *Ulf Moeller * + + * Add support for native Solaris shared libraries. Configure + solaris-sparc-sc4-pic, make, then run shlib/solaris-sc4.sh. It'd be nice + if someone would make that last step automatic. + + *Matthias Loepfe * + + * ctx_size was not built with the right compiler during "make links". Fixed. + + *Ben Laurie* + + * Change the meaning of 'ALL' in the cipher list. It now means "everything + except NULL ciphers". This means the default cipher list will no longer + enable NULL ciphers. They need to be specifically enabled e.g. with + the string "DEFAULT:eNULL". + + *Steve Henson* + + * Fix to RSA private encryption routines: if p < q then it would + occasionally produce an invalid result. This will only happen with + externally generated keys because OpenSSL (and SSLeay) ensure p > q. + + *Steve Henson* + + * Be less restrictive and allow also `perl util/perlpath.pl + /path/to/bin/perl` in addition to `perl util/perlpath.pl /path/to/bin`, + because this way one can also use an interpreter named `perl5` (which is + usually the name of Perl 5.xxx on platforms where an Perl 4.x is still + installed as `perl`). + + *Matthias Loepfe * + + * Let util/clean-depend.pl work also with older Perl 5.00x versions. + + *Matthias Loepfe * + + * Fix Makefile.org so CC,CFLAG etc are passed to 'make links' add + advapi32.lib to Win32 build and change the pem test comparison + to fc.exe (thanks to Ulrich Kroener for the + suggestion). Fix misplaced ASNI prototypes and declarations in evp.h + and crypto/des/ede_cbcm_enc.c. + + *Steve Henson* + + * DES quad checksum was broken on big-endian architectures. Fixed. + + *Ben Laurie* + + * Comment out two functions in bio.h that aren't implemented. Fix up the + Win32 test batch file so it (might) work again. The Win32 test batch file + is horrible: I feel ill.... + + *Steve Henson* + + * Move various #ifdefs around so NO_SYSLOG, NO_DIRENT etc are now selected + in e_os.h. Audit of header files to check ANSI and non ANSI + sections: 10 functions were absent from non ANSI section and not exported + from Windows DLLs. Fixed up libeay.num for new functions. + + *Steve Henson* + + * Make `openssl version` output lines consistent. + + *Ralf S. Engelschall* + + * Fix Win32 symbol export lists for BIO functions: Added + BIO_get_ex_new_index, BIO_get_ex_num, BIO_get_ex_data and BIO_set_ex_data + to ms/libeay{16,32}.def. + + *Ralf S. Engelschall* + + * Second round of fixing the OpenSSL perl/ stuff. It now at least compiled + fine under Unix and passes some trivial tests I've now added. But the + whole stuff is horribly incomplete, so a README.1ST with a disclaimer was + added to make sure no one expects that this stuff really works in the + OpenSSL 0.9.2 release. Additionally I've started to clean the XS sources + up and fixed a few little bugs and inconsistencies in OpenSSL.{pm,xs} and + openssl_bio.xs. + + *Ralf S. Engelschall* + + * Fix the generation of two part addresses in perl. + + *Kenji Miyake , integrated by Ben Laurie* + + * Add config entry for Linux on MIPS. + + *John Tobey * + + * Make links whenever Configure is run, unless we are on Windoze. + + *Ben Laurie* + + * Permit extensions to be added to CRLs using crl_section in openssl.cnf. + Currently only issuerAltName and AuthorityKeyIdentifier make any sense + in CRLs. + + *Steve Henson* + + * Add a useful kludge to allow package maintainers to specify compiler and + other platforms details on the command line without having to patch the + Configure script every time: One now can use + `perl Configure :
`, + i.e. platform ids are allowed to have details appended + to them (separated by colons). This is treated as there would be a static + pre-configured entry in Configure's %table under key `` with value + `
` and `perl Configure ` is called. So, when you want to + perform a quick test-compile under FreeBSD 3.1 with pgcc and without + assembler stuff you can use `perl Configure "FreeBSD-elf:pgcc:-O6:::"` + now, which overrides the FreeBSD-elf entry on-the-fly. + + *Ralf S. Engelschall* + + * Disable new TLS1 ciphersuites by default: they aren't official yet. + + *Ben Laurie* + + * Allow DSO flags like -fpic, -fPIC, -KPIC etc. to be specified + on the `perl Configure ...` command line. This way one can compile + OpenSSL libraries with Position Independent Code (PIC) which is needed + for linking it into DSOs. + + *Ralf S. Engelschall* + + * Remarkably, export ciphers were totally broken and no-one had noticed! + Fixed. + + *Ben Laurie* + + * Cleaned up the LICENSE document: The official contact for any license + questions now is the OpenSSL core team under openssl-core@openssl.org. + And add a paragraph about the dual-license situation to make sure people + recognize that _BOTH_ the OpenSSL license _AND_ the SSLeay license apply + to the OpenSSL toolkit. + + *Ralf S. Engelschall* + + * General source tree makefile cleanups: Made `making xxx in yyy...` + display consistent in the source tree and replaced `/bin/rm` by `rm`. + Additionally cleaned up the `make links` target: Remove unnecessary + semicolons, subsequent redundant removes, inline point.sh into mklink.sh + to speed processing and no longer clutter the display with confusing + stuff. Instead only the actually done links are displayed. + + *Ralf S. Engelschall* + + * Permit null encryption ciphersuites, used for authentication only. It used + to be necessary to set the preprocessor define SSL_ALLOW_ENULL to do this. + It is now necessary to set SSL_FORBID_ENULL to prevent the use of null + encryption. + + *Ben Laurie* + + * Add a bunch of fixes to the PKCS#7 stuff. It used to sometimes reorder + signed attributes when verifying signatures (this would break them), + the detached data encoding was wrong and public keys obtained using + X509_get_pubkey() weren't freed. + + *Steve Henson* + + * Add text documentation for the BUFFER functions. Also added a work around + to a Win95 console bug. This was triggered by the password read stuff: the + last character typed gets carried over to the next fread(). If you were + generating a new cert request using 'req' for example then the last + character of the passphrase would be CR which would then enter the first + field as blank. + + *Steve Henson* + + * Added the new 'Includes OpenSSL Cryptography Software' button as + doc/openssl_button.{gif,html} which is similar in style to the old SSLeay + button and can be used by applications based on OpenSSL to show the + relationship to the OpenSSL project. + + *Ralf S. Engelschall* + + * Remove confusing variables in function signatures in files + ssl/ssl_lib.c and ssl/ssl.h. + + *Lennart Bong * + + * Don't install bss_file.c under PREFIX/include/ + + *Lennart Bong * + + * Get the Win32 compile working again. Modify mkdef.pl so it can handle + functions that return function pointers and has support for NT specific + stuff. Fix mk1mf.pl and VC-32.pl to support NT differences also. Various + #ifdef WIN32 and WINNTs sprinkled about the place and some changes from + unsigned to signed types: this was killing the Win32 compile. + + *Steve Henson* + + * Add new certificate file to stack functions, + SSL_add_dir_cert_subjects_to_stack() and + SSL_add_file_cert_subjects_to_stack(). These largely supplant + SSL_load_client_CA_file(), and can be used to add multiple certs easily + to a stack (usually this is then handed to SSL_CTX_set_client_CA_list()). + This means that Apache-SSL and similar packages don't have to mess around + to add as many CAs as they want to the preferred list. + + *Ben Laurie* + + * Experiment with doxygen documentation. Currently only partially applied to + ssl/ssl_lib.c. + See , and run doxygen with + openssl.doxy as the configuration file. + + *Ben Laurie* + + * Get rid of remaining C++-style comments which strict C compilers hate. + + *Ralf S. Engelschall, pointed out by Carlos Amengual* + + * Changed BN_RECURSION in bn_mont.c to BN_RECURSION_MONT so it is not + compiled in by default: it has problems with large keys. + + *Steve Henson* + + * Add a bunch of SSL_xxx() functions for configuring the temporary RSA and + DH private keys and/or callback functions which directly correspond to + their SSL_CTX_xxx() counterparts but work on a per-connection basis. This + is needed for applications which have to configure certificates on a + per-connection basis (e.g. Apache+mod_ssl) instead of a per-context basis + (e.g. s_server). + For the RSA certificate situation is makes no difference, but + for the DSA certificate situation this fixes the "no shared cipher" + problem where the OpenSSL cipher selection procedure failed because the + temporary keys were not overtaken from the context and the API provided + no way to reconfigure them. + The new functions now let applications reconfigure the stuff and they + are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh, + SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback. Additionally a new + non-public-API function ssl_cert_instantiate() is used as a helper + function and also to reduce code redundancy inside ssl_rsa.c. + + *Ralf S. Engelschall* + + * Move s_server -dcert and -dkey options out of the undocumented feature + area because they are useful for the DSA situation and should be + recognized by the users. + + *Ralf S. Engelschall* + + * Fix the cipher decision scheme for export ciphers: the export bits are + *not* within SSL_MKEY_MASK or SSL_AUTH_MASK, they are within + SSL_EXP_MASK. So, the original variable has to be used instead of the + already masked variable. + + *Richard Levitte * + + * Fix `port` variable from `int` to `unsigned int` in crypto/bio/b_sock.c + + *Richard Levitte * + + * Change type of another md_len variable in pk7_doit.c:PKCS7_dataFinal() + from `int` to `unsigned int` because it is a length and initialized by + EVP_DigestFinal() which expects an `unsigned int *`. + + *Richard Levitte * + + * Don't hard-code path to Perl interpreter on shebang line of Configure + script. Instead use the usual Shell->Perl transition trick. + + *Ralf S. Engelschall* + + * Make `openssl x509 -noout -modulus`' functional also for DSA certificates + (in addition to RSA certificates) to match the behaviour of `openssl dsa + -noout -modulus` as it's already the case for `openssl rsa -noout + -modulus`. For RSA the -modulus is the real "modulus" while for DSA + currently the public key is printed (a decision which was already done by + `openssl dsa -modulus` in the past) which serves a similar purpose. + Additionally the NO_RSA no longer completely removes the whole -modulus + option; it now only avoids using the RSA stuff. Same applies to NO_DSA + now, too. + + *Ralf S. Engelschall* + + * Add Arne Ansper's reliable BIO - this is an encrypted, block-digested + BIO. See the source (crypto/evp/bio_ok.c) for more info. + + *Arne Ansper * + + * Dump the old yucky req code that tried (and failed) to allow raw OIDs + to be added. Now both 'req' and 'ca' can use new objects defined in the + config file. + + *Steve Henson* + + * Add cool BIO that does syslog (or event log on NT). + + *Arne Ansper , integrated by Ben Laurie* + + * Add support for new TLS ciphersuites, TLS_RSA_EXPORT56_WITH_RC4_56_MD5, + TLS_RSA_EXPORT56_WITH_RC2_CBC_56_MD5 and + TLS_RSA_EXPORT56_WITH_DES_CBC_SHA, as specified in "56-bit Export Cipher + Suites For TLS", draft-ietf-tls-56-bit-ciphersuites-00.txt. + + *Ben Laurie* + + * Add preliminary config info for new extension code. + + *Steve Henson* + + * Make RSA_NO_PADDING really use no padding. + + *Ulf Moeller * + + * Generate errors when private/public key check is done. + + *Ben Laurie* + + * Overhaul for 'crl' utility. New function X509_CRL_print. Partial support + for some CRL extensions and new objects added. + + *Steve Henson* + + * Really fix the ASN1 IMPLICIT bug this time... Partial support for private + key usage extension and fuller support for authority key id. + + *Steve Henson* + + * Add OAEP encryption for the OpenSSL crypto library. OAEP is the improved + padding method for RSA, which is recommended for new applications in PKCS + #1 v2.0 (RFC 2437, October 1998). + OAEP (Optimal Asymmetric Encryption Padding) has better theoretical + foundations than the ad-hoc padding used in PKCS #1 v1.5. It is secure + against Bleichbacher's attack on RSA. + *Ulf Moeller , reformatted, corrected and integrated by + Ben Laurie* + + * Updates to the new SSL compression code + + *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)* + + * Fix so that the version number in the master secret, when passed + via RSA, checks that if TLS was proposed, but we roll back to SSLv3 + (because the server will not accept higher), that the version number + is 0x03,0x01, not 0x03,0x00 + + *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)* + + * Run extensive memory leak checks on SSL commands. Fixed *lots* of memory + leaks in `ssl/` relating to new `X509_get_pubkey()` behaviour. Also fixes + in `apps/` and an unrelated leak in `crypto/dsa/dsa_vrf.c`. + + *Steve Henson* + + * Support for RAW extensions where an arbitrary extension can be + created by including its DER encoding. See `apps/openssl.cnf` for + an example. + + *Steve Henson* + + * Make sure latest Perl versions don't interpret some generated C array + code as Perl array code in the crypto/err/err_genc.pl script. + + *Lars Weber <3weber@informatik.uni-hamburg.de>* + + * Modify ms/do_ms.bat to not generate assembly language makefiles since + not many people have the assembler. Various Win32 compilation fixes and + update to the INSTALL.W32 file with (hopefully) more accurate Win32 + build instructions. + + *Steve Henson* + + * Modify configure script 'Configure' to automatically create crypto/date.h + file under Win32 and also build pem.h from pem.org. New script + util/mkfiles.pl to create the MINFO file on environments that can't do a + 'make files': perl util/mkfiles.pl >MINFO should work. + + *Steve Henson* + + * Major rework of DES function declarations, in the pursuit of correctness + and purity. As a result, many evil casts evaporated, and some weirdness, + too. You may find this causes warnings in your code. Zapping your evil + casts will probably fix them. Mostly. + + *Ben Laurie* + + * Fix for a typo in asn1.h. Bug fix to object creation script + obj_dat.pl. It considered a zero in an object definition to mean + "end of object": none of the objects in objects.h have any zeros + so it wasn't spotted. + + *Steve Henson, reported by Erwann ABALEA * + + * Add support for Triple DES Cipher Block Chaining with Output Feedback + Masking (CBCM). In the absence of test vectors, the best I have been able + to do is check that the decrypt undoes the encrypt, so far. Send me test + vectors if you have them. + + *Ben Laurie* + + * Correct calculation of key length for export ciphers (too much space was + allocated for null ciphers). This has not been tested! + + *Ben Laurie* + + * Modifications to the mkdef.pl for Win32 DEF file creation. The usage + message is now correct (it understands "crypto" and "ssl" on its + command line). There is also now an "update" option. This will update + the util/ssleay.num and util/libeay.num files with any new functions. + If you do a: + perl util/mkdef.pl crypto ssl update + it will update them. + + *Steve Henson* + + * Overhauled the Perl interface: + - ported BN stuff to OpenSSL's different BN library + - made the perl/ source tree CVS-aware + - renamed the package from SSLeay to OpenSSL (the files still contain + their history because I've copied them in the repository) + - removed obsolete files (the test scripts will be replaced + by better Test::Harness variants in the future) + + *Ralf S. Engelschall* + + * First cut for a very conservative source tree cleanup: + 1. merge various obsolete readme texts into doc/ssleay.txt + where we collect the old documents and readme texts. + 2. remove the first part of files where I'm already sure that we no + longer need them because of three reasons: either they are just temporary + files which were left by Eric or they are preserved original files where + I've verified that the diff is also available in the CVS via "cvs diff + -rSSLeay_0_8_1b" or they were renamed (as it was definitely the case for + the crypto/md/ stuff). + + *Ralf S. Engelschall* + + * More extension code. Incomplete support for subject and issuer alt + name, issuer and authority key id. Change the i2v function parameters + and add an extra 'crl' parameter in the X509V3_CTX structure: guess + what that's for :-) Fix to ASN1 macro which messed up + IMPLICIT tag and add f_enum.c which adds a2i, i2a for ENUMERATED. + + *Steve Henson* + + * Preliminary support for ENUMERATED type. This is largely copied from the + INTEGER code. + + *Steve Henson* + + * Add new function, EVP_MD_CTX_copy() to replace frequent use of memcpy. + + *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)* + + * Make sure `make rehash` target really finds the `openssl` program. + + *Ralf S. Engelschall, Matthias Loepfe * + + * Squeeze another 7% of speed out of MD5 assembler, at least on a P2. I'd + like to hear about it if this slows down other processors. + + *Ben Laurie* + + * Add CygWin32 platform information to Configure script. + + *Alan Batie * + + * Fixed ms/32all.bat script: `no_asm` -> `no-asm` + + *Rainer W. Gerling * + + * New program nseq to manipulate netscape certificate sequences + + *Steve Henson* + + * Modify crl2pkcs7 so it supports multiple -certfile arguments. Fix a + few typos. + + *Steve Henson* + + * Fixes to BN code. Previously the default was to define BN_RECURSION + but the BN code had some problems that would cause failures when + doing certificate verification and some other functions. + + *Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)* + + * Add ASN1 and PEM code to support netscape certificate sequences. + + *Steve Henson* + + * Add ASN1 and PEM code to support netscape certificate sequences. + + *Steve Henson* + + * Add several PKIX and private extended key usage OIDs. + + *Steve Henson* + + * Modify the 'ca' program to handle the new extension code. Modify + openssl.cnf for new extension format, add comments. + + *Steve Henson* + + * More X509 V3 changes. Fix typo in v3_bitstr.c. Add support to 'req' + and add a sample to openssl.cnf so req -x509 now adds appropriate + CA extensions. + + *Steve Henson* + + * Continued X509 V3 changes. Add to other makefiles, integrate with the + error code, add initial support to X509_print() and x509 application. + + *Steve Henson* + + * Takes a deep breath and start adding X509 V3 extension support code. Add + files in crypto/x509v3. Move original stuff to crypto/x509v3/old. All this + stuff is currently isolated and isn't even compiled yet. + + *Steve Henson* + + * Continuing patches for GeneralizedTime. Fix up certificate and CRL + ASN1 to use ASN1_TIME and modify print routines to use ASN1_TIME_print. + Removed the versions check from X509 routines when loading extensions: + this allows certain broken certificates that don't set the version + properly to be processed. + + *Steve Henson* + + * Deal with irritating shit to do with dependencies, in YAAHW (Yet Another + Ad Hoc Way) - Makefile.ssls now all contain local dependencies, which + can still be regenerated with "make depend". + + *Ben Laurie* + + * Spelling mistake in C version of CAST-128. + + *Ben Laurie, reported by Jeremy Hylton * + + * Changes to the error generation code. The perl script err-code.pl + now reads in the old error codes and retains the old numbers, only + adding new ones if necessary. It also only changes the .err files if new + codes are added. The makefiles have been modified to only insert errors + when needed (to avoid needlessly modifying header files). This is done + by only inserting errors if the .err file is newer than the auto generated + C file. To rebuild all the error codes from scratch (the old behaviour) + either modify crypto/Makefile.ssl to pass the -regen flag to err_code.pl + or delete all the .err files. + + *Steve Henson* + + * CAST-128 was incorrectly implemented for short keys. The C version has + been fixed, but is untested. The assembler versions are also fixed, but + new assembler HAS NOT BEEN GENERATED FOR WIN32 - the Makefile needs fixing + to regenerate it if needed. + *Ben Laurie, reported (with fix for C version) by Jun-ichiro itojun + Hagino * + + * File was opened incorrectly in randfile.c. + + *Ulf Möller * + + * Beginning of support for GeneralizedTime. d2i, i2d, check and print + functions. Also ASN1_TIME suite which is a CHOICE of UTCTime or + GeneralizedTime. ASN1_TIME is the proper type used in certificates et + al: it's just almost always a UTCTime. Note this patch adds new error + codes so do a "make errors" if there are problems. + + *Steve Henson* + + * Correct Linux 1 recognition in config. + + *Ulf Möller * + + * Remove pointless MD5 hash when using DSA keys in ca. + + *Anonymous * + + * Generate an error if given an empty string as a cert directory. Also + generate an error if handed NULL (previously returned 0 to indicate an + error, but didn't set one). + + *Ben Laurie, reported by Anonymous * + + * Add prototypes to SSL methods. Make SSL_write's buffer const, at last. + + *Ben Laurie* + + * Fix the dummy function BN_ref_mod_exp() in rsaref.c to have the correct + parameters. This was causing a warning which killed off the Win32 compile. + + *Steve Henson* + + * Remove C++ style comments from crypto/bn/bn_local.h. + + *Neil Costigan * + + * The function OBJ_txt2nid was broken. It was supposed to return a nid + based on a text string, looking up short and long names and finally + "dot" format. The "dot" format stuff didn't work. Added new function + OBJ_txt2obj to do the same but return an ASN1_OBJECT and rewrote + OBJ_txt2nid to use it. OBJ_txt2obj can also return objects even if the + OID is not part of the table. + + *Steve Henson* + + * Add prototypes to X509 lookup/verify methods, fixing a bug in + X509_LOOKUP_by_alias(). + + *Ben Laurie* + + * Sort openssl functions by name. + + *Ben Laurie* + + * Get the `gendsa` command working and add it to the `list` command. Remove + encryption from sample DSA keys (in case anyone is interested the password + was "1234"). + + *Steve Henson* + + * Make *all* `*_free` functions accept a NULL pointer. + + *Frans Heymans * + + * If a DH key is generated in s3_srvr.c, don't blow it by trying to use + NULL pointers. + + *Anonymous * + + * s_server should send the CAfile as acceptable CAs, not its own cert. + + *Bodo Moeller <3moeller@informatik.uni-hamburg.de>* + + * Don't blow it for numeric `-newkey` arguments to `apps/req`. + + *Bodo Moeller <3moeller@informatik.uni-hamburg.de>* + + * Temp key "for export" tests were wrong in s3_srvr.c. + + *Anonymous * + + * Add prototype for temp key callback functions + SSL_CTX_set_tmp_{rsa,dh}_callback(). + + *Ben Laurie* + + * Make DH_free() tolerate being passed a NULL pointer (like RSA_free() and + DSA_free()). Make X509_PUBKEY_set() check for errors in d2i_PublicKey(). + + *Steve Henson* + + * X509_name_add_entry() freed the wrong thing after an error. + + *Arne Ansper * + + * rsa_eay.c would attempt to free a NULL context. + + *Arne Ansper * + + * BIO_s_socket() had a broken should_retry() on Windoze. + + *Arne Ansper * + + * BIO_f_buffer() didn't pass on BIO_CTRL_FLUSH. + + *Arne Ansper * + + * Make sure the already existing X509_STORE->depth variable is initialized + in X509_STORE_new(), but document the fact that this variable is still + unused in the certificate verification process. + + *Ralf S. Engelschall* + + * Fix the various library and `apps/` files to free up pkeys obtained from + X509_PUBKEY_get() et al. Also allow x509.c to handle netscape extensions. + + *Steve Henson* + + * Fix reference counting in X509_PUBKEY_get(). This makes + demos/maurice/example2.c work, amongst others, probably. + + *Steve Henson and Ben Laurie* + + * First cut of a cleanup for `apps/`. First the `ssleay` program is now named + `openssl` and second, the shortcut symlinks for the `openssl ` + are no longer created. This way we have a single and consistent command + line interface `openssl `, similar to `cvs `. + + *Ralf S. Engelschall, Paul Sutton and Ben Laurie* + + * ca.c: move test for DSA keys inside #ifndef NO_DSA. Make pubkey + BIT STRING wrapper always have zero unused bits. + + *Steve Henson* + + * Add CA.pl, perl version of CA.sh, add extended key usage OID. + + *Steve Henson* + + * Make the top-level INSTALL documentation easier to understand. + + *Paul Sutton* + + * Makefiles updated to exit if an error occurs in a sub-directory + make (including if user presses ^C) [Paul Sutton] + + * Make Montgomery context stuff explicit in RSA data structure. + + *Ben Laurie* + + * Fix build order of pem and err to allow for generated pem.h. + + *Ben Laurie* + + * Fix renumbering bug in X509_NAME_delete_entry(). + + *Ben Laurie* + + * Enhanced the err-ins.pl script so it makes the error library number + global and can add a library name. This is needed for external ASN1 and + other error libraries. + + *Steve Henson* + + * Fixed sk_insert which never worked properly. + + *Steve Henson* + + * Fix ASN1 macros so they can handle indefinite length constructed + EXPLICIT tags. Some non standard certificates use these: they can now + be read in. + + *Steve Henson* + + * Merged the various old/obsolete SSLeay documentation files (doc/xxx.doc) + into a single doc/ssleay.txt bundle. This way the information is still + preserved but no longer messes up this directory. Now it's new room for + the new set of documentation files. + + *Ralf S. Engelschall* + + * SETs were incorrectly DER encoded. This was a major pain, because they + shared code with SEQUENCEs, which aren't coded the same. This means that + almost everything to do with SETs or SEQUENCEs has either changed name or + number of arguments. + + *Ben Laurie, based on a partial fix by GP Jayan * + + * Fix test data to work with the above. + + *Ben Laurie* + + * Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but + was already fixed by Eric for 0.9.1 it seems. + + *Ben Laurie - pointed out by Ulf Möller * + + * Autodetect FreeBSD3. + + *Ben Laurie* + + * Fix various bugs in Configure. This affects the following platforms: + nextstep + ncr-scde + unixware-2.0 + unixware-2.0-pentium + sco5-cc. + + *Ben Laurie* + + * Eliminate generated files from CVS. Reorder tests to regenerate files + before they are needed. + + *Ben Laurie* + + * Generate Makefile.ssl from Makefile.org (to keep CVS happy). + + *Ben Laurie* + +### Changes between 0.9.1b and 0.9.1c [23-Dec-1998] + + * Added OPENSSL_VERSION_NUMBER to crypto/crypto.h and + changed SSLeay to OpenSSL in version strings. + + *Ralf S. Engelschall* + + * Some fixups to the top-level documents. + + *Paul Sutton* + + * Fixed the nasty bug where rsaref.h was not found under compile-time + because the symlink to include/ was missing. + + *Ralf S. Engelschall* + + * Incorporated the popular no-RSA/DSA-only patches + which allow to compile an RSA-free SSLeay. + + *Andrew Cooke / Interrader Ldt., Ralf S. Engelschall* + + * Fixed nasty rehash problem under `make -f Makefile.ssl links` + when "ssleay" is still not found. + + *Ralf S. Engelschall* + + * Added more platforms to Configure: Cray T3E, HPUX 11, + + *Ralf S. Engelschall, Beckmann * + + * Updated the README file. + + *Ralf S. Engelschall* + + * Added various .cvsignore files in the CVS repository subdirs + to make a "cvs update" really silent. + + *Ralf S. Engelschall* + + * Recompiled the error-definition header files and added + missing symbols to the Win32 linker tables. + + *Ralf S. Engelschall* + + * Cleaned up the top-level documents; + o new files: CHANGES and LICENSE + o merged VERSION, HISTORY* and README* files a CHANGES.SSLeay + o merged COPYRIGHT into LICENSE + o removed obsolete TODO file + o renamed MICROSOFT to INSTALL.W32 + + *Ralf S. Engelschall* + + * Removed dummy files from the 0.9.1b source tree: + crypto/asn1/x crypto/bio/cd crypto/bio/fg crypto/bio/grep crypto/bio/vi + crypto/bn/asm/......add.c crypto/bn/asm/a.out crypto/dsa/f crypto/md5/f + crypto/pem/gmon.out crypto/perlasm/f crypto/pkcs7/build crypto/rsa/f + crypto/sha/asm/f crypto/threads/f ms/zzz ssl/f ssl/f.mak test/f + util/f.mak util/pl/f util/pl/f.mak crypto/bf/bf_locl.old apps/f + + *Ralf S. Engelschall* + + * Added various platform portability fixes. + + *Mark J. Cox* + + * The Genesis of the OpenSSL rpject: + We start with the latest (unreleased) SSLeay version 0.9.1b which Eric A. + Young and Tim J. Hudson created while they were working for C2Net until + summer 1998. + + *The OpenSSL Project* + +### Changes between 0.9.0b and 0.9.1b [not released] + + * Updated a few CA certificates under certs/ + + *Eric A. Young* + + * Changed some BIGNUM api stuff. + + *Eric A. Young* + + * Various platform ports: OpenBSD, Ultrix, IRIX 64bit, NetBSD, + DGUX x86, Linux Alpha, etc. + + *Eric A. Young* + + * New COMP library [crypto/comp/] for SSL Record Layer Compression: + RLE (dummy implemented) and ZLIB (really implemented when ZLIB is + available). + + *Eric A. Young* + + * Add -strparse option to asn1pars program which parses nested + binary structures + + *Dr Stephen Henson * + + * Added "oid_file" to ssleay.cnf for "ca" and "req" programs. + + *Eric A. Young* + + * DSA fix for "ca" program. + + *Eric A. Young* + + * Added "-genkey" option to "dsaparam" program. + + *Eric A. Young* + + * Added RIPE MD160 (rmd160) message digest. + + *Eric A. Young* + + * Added -a (all) option to "ssleay version" command. + + *Eric A. Young* + + * Added PLATFORM define which is the id given to Configure. + + *Eric A. Young* + + * Added MemCheck_XXXX functions to crypto/mem.c for memory checking. + + *Eric A. Young* + + * Extended the ASN.1 parser routines. + + *Eric A. Young* + + * Extended BIO routines to support REUSEADDR, seek, tell, etc. + + *Eric A. Young* + + * Added a BN_CTX to the BN library. + + *Eric A. Young* + + * Fixed the weak key values in DES library + + *Eric A. Young* + + * Changed API in EVP library for cipher aliases. + + *Eric A. Young* + + * Added support for RC2/64bit cipher. + + *Eric A. Young* + + * Converted the lhash library to the crypto/mem.c functions. + + *Eric A. Young* + + * Added more recognized ASN.1 object ids. + + *Eric A. Young* + + * Added more RSA padding checks for SSL/TLS. + + *Eric A. Young* + + * Added BIO proxy/filter functionality. + + *Eric A. Young* + + * Added extra_certs to SSL_CTX which can be used + send extra CA certificates to the client in the CA cert chain sending + process. It can be configured with SSL_CTX_add_extra_chain_cert(). + + *Eric A. Young* + + * Now Fortezza is denied in the authentication phase because + this is key exchange mechanism is not supported by SSLeay at all. + + *Eric A. Young* + + * Additional PKCS1 checks. + + *Eric A. Young* + + * Support the string "TLSv1" for all TLS v1 ciphers. + + *Eric A. Young* + + * Added function SSL_get_ex_data_X509_STORE_CTX_idx() which gives the + ex_data index of the SSL context in the X509_STORE_CTX ex_data. + + *Eric A. Young* + + * Fixed a few memory leaks. + + *Eric A. Young* + + * Fixed various code and comment typos. + + *Eric A. Young* + + * A minor bug in ssl/s3_clnt.c where there would always be 4 0 + bytes sent in the client random. + + *Edward Bishop * + + + +[CVE-2023-0401]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0401 +[CVE-2023-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0286 +[CVE-2023-0217]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0217 +[CVE-2023-0216]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0216 +[CVE-2023-0215]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0215 +[CVE-2022-4450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4450 +[CVE-2022-4304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4304 +[CVE-2022-4203]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4203 +[CVE-2022-3996]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-3996 +[CVE-2022-2274]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274 +[CVE-2022-2097]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274 +[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971 +[CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967 +[CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563 +[CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559 +[CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552 +[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551 +[CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549 +[CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547 +[CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543 +[CVE-2018-5407]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-5407 +[CVE-2018-0739]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0739 +[CVE-2018-0737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0737 +[CVE-2018-0735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0735 +[CVE-2018-0734]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0734 +[CVE-2018-0733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0733 +[CVE-2018-0732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0732 +[CVE-2017-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3738 +[CVE-2017-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3737 +[CVE-2017-3736]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3736 +[CVE-2017-3735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3735 +[CVE-2017-3733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3733 +[CVE-2017-3732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3732 +[CVE-2017-3731]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3731 +[CVE-2017-3730]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3730 +[CVE-2016-7055]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7055 +[CVE-2016-7054]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7054 +[CVE-2016-7053]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7053 +[CVE-2016-7052]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7052 +[CVE-2016-6309]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6309 +[CVE-2016-6308]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6308 +[CVE-2016-6307]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6307 +[CVE-2016-6306]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6306 +[CVE-2016-6305]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6305 +[CVE-2016-6304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6304 +[CVE-2016-6303]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6303 +[CVE-2016-6302]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6302 +[CVE-2016-2183]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2183 +[CVE-2016-2182]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2182 +[CVE-2016-2181]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2181 +[CVE-2016-2180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2180 +[CVE-2016-2179]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2179 +[CVE-2016-2178]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2178 +[CVE-2016-2177]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2177 +[CVE-2016-2176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2176 +[CVE-2016-2109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2109 +[CVE-2016-2107]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2107 +[CVE-2016-2106]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2106 +[CVE-2016-2105]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2105 +[CVE-2016-0800]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0800 +[CVE-2016-0799]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0799 +[CVE-2016-0798]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0798 +[CVE-2016-0797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0797 +[CVE-2016-0705]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0705 +[CVE-2016-0702]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0702 +[CVE-2016-0701]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0701 +[CVE-2015-3197]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3197 +[CVE-2015-3196]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3196 +[CVE-2015-3195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3195 +[CVE-2015-3194]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3194 +[CVE-2015-3193]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3193 +[CVE-2015-1793]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1793 +[CVE-2015-1792]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1792 +[CVE-2015-1791]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1791 +[CVE-2015-1790]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1790 +[CVE-2015-1789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1789 +[CVE-2015-1788]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1788 +[CVE-2015-1787]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1787 +[CVE-2015-0293]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0293 +[CVE-2015-0291]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0291 +[CVE-2015-0290]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0290 +[CVE-2015-0289]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0289 +[CVE-2015-0288]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0288 +[CVE-2015-0287]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0287 +[CVE-2015-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0286 +[CVE-2015-0285]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0285 +[CVE-2015-0209]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0209 +[CVE-2015-0208]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0208 +[CVE-2015-0207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0207 +[CVE-2015-0206]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0206 +[CVE-2015-0205]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0205 +[CVE-2015-0204]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0204 +[CVE-2014-8275]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-8275 +[CVE-2014-5139]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-5139 +[CVE-2014-3572]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3572 +[CVE-2014-3571]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3571 +[CVE-2014-3570]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3570 +[CVE-2014-3569]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3569 +[CVE-2014-3568]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3568 +[CVE-2014-3567]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3567 +[CVE-2014-3566]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3566 +[CVE-2014-3513]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3513 +[CVE-2014-3512]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3512 +[CVE-2014-3511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3511 +[CVE-2014-3510]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3510 +[CVE-2014-3509]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3509 +[CVE-2014-3508]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3508 +[CVE-2014-3507]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3507 +[CVE-2014-3506]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3506 +[CVE-2014-3505]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3505 +[CVE-2014-3470]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3470 +[CVE-2014-0224]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0224 +[CVE-2014-0221]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0221 +[CVE-2014-0195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0195 +[CVE-2014-0160]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0160 +[CVE-2014-0076]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0076 +[CVE-2013-6450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6450 +[CVE-2013-4353]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-4353 +[CVE-2013-0169]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0169 +[CVE-2013-0166]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0166 +[CVE-2012-2686]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2686 +[CVE-2012-2333]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2333 +[CVE-2012-2110]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2110 +[CVE-2012-0884]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0884 +[CVE-2012-0050]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0050 +[CVE-2012-0027]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0027 +[CVE-2011-4619]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4619 +[CVE-2011-4577]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4577 +[CVE-2011-4576]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4576 +[CVE-2011-4109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4109 +[CVE-2011-4108]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4108 +[CVE-2011-3210]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3210 +[CVE-2011-3207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3207 +[CVE-2011-0014]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-0014 +[CVE-2010-4252]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4252 +[CVE-2010-4180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4180 +[CVE-2010-3864]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-3864 +[CVE-2010-1633]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-1633 +[CVE-2010-0740]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0740 +[CVE-2010-0433]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0433 +[CVE-2009-4355]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-4355 +[CVE-2009-3555]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3555 +[CVE-2009-3245]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3245 +[CVE-2009-1386]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1386 +[CVE-2009-1379]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1379 +[CVE-2009-1378]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1378 +[CVE-2009-1377]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-1377 +[CVE-2009-0789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0789 +[CVE-2009-0591]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0591 +[CVE-2009-0590]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0590 +[CVE-2008-5077]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-5077 +[CVE-2008-1678]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-1678 +[CVE-2008-1672]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-1672 +[CVE-2008-0891]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-0891 +[CVE-2007-5135]: https://www.openssl.org/news/vulnerabilities.html#CVE-2007-5135 +[CVE-2007-4995]: https://www.openssl.org/news/vulnerabilities.html#CVE-2007-4995 +[CVE-2006-4343]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4343 +[CVE-2006-4339]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4339 +[CVE-2006-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-3738 +[CVE-2006-2940]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2940 +[CVE-2006-2937]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2937 +[CVE-2005-2969]: https://www.openssl.org/news/vulnerabilities.html#CVE-2005-2969 +[CVE-2004-0112]: https://www.openssl.org/news/vulnerabilities.html#CVE-2004-0112 +[CVE-2004-0079]: https://www.openssl.org/news/vulnerabilities.html#CVE-2004-0079 +[CVE-2003-0851]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0851 +[CVE-2003-0545]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0545 +[CVE-2003-0544]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0544 +[CVE-2003-0543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0543 +[CVE-2003-0078]: https://www.openssl.org/news/vulnerabilities.html#CVE-2003-0078 +[CVE-2002-0659]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0659 +[CVE-2002-0657]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0657 +[CVE-2002-0656]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0656 +[CVE-2002-0655]: https://www.openssl.org/news/vulnerabilities.html#CVE-2002-0655 diff --git a/CONTRIBUTING b/CONTRIBUTING deleted file mode 100644 --- a/CONTRIBUTING +++ /dev/null @@ -1,72 +0,0 @@ -HOW TO CONTRIBUTE TO OpenSSL ----------------------------- - -(Please visit https://www.openssl.org/community/getting-started.html for -other ideas about how to contribute.) - -Development is done on GitHub, https://github.com/openssl/openssl. - -To request new features or report bugs, please open an issue on GitHub - -To submit a patch, please open a pull request on GitHub. If you are thinking -of making a large contribution, open an issue for it before starting work, -to get comments from the community. Someone may be already working on -the same thing or there may be reasons why that feature isn't implemented. - -To make it easier to review and accept your pull request, please follow these -guidelines: - - 1. Anything other than a trivial contribution requires a Contributor - License Agreement (CLA), giving us permission to use your code. See - https://www.openssl.org/policies/cla.html for details. If your - contribution is too small to require a CLA, put "CLA: trivial" on a - line by itself in your commit message body. - - 2. All source files should start with the following text (with - appropriate comment characters at the start of each line and the - year(s) updated): - - Copyright 20xx-20yy 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 - - 3. Patches should be as current as possible; expect to have to rebase - often. We do not accept merge commits, you will have to remove them - (usually by rebasing) before it will be acceptable. - - 4. Patches should follow our coding style (see - https://www.openssl.org/policies/codingstyle.html) and compile - without warnings. Where gcc or clang is available you should use the - --strict-warnings Configure option. OpenSSL compiles on many varied - platforms: try to ensure you only use portable features. Clean builds via - GitHub Actions and AppVeyor are required, and they are started automatically - whenever a PR is created or updated. - - 5. When at all possible, patches should include tests. These can - either be added to an existing test, or completely new. Please see - test/README for information on the test framework. - - 6. New features or changed functionality must include - documentation. Please look at the "pod" files in doc/man[1357] for - examples of our style. Run "make doc-nits" to make sure that your - documentation changes are clean. - - 7. For user visible changes (API changes, behaviour changes, ...), - consider adding a note in CHANGES. This could be a summarising - description of the change, and could explain the grander details. - Have a look through existing entries for inspiration. - Please note that this is NOT simply a copy of git-log one-liners. - Also note that security fixes get an entry in CHANGES. - This file helps users get more in depth information of what comes - with a specific release without having to sift through the higher - noise ratio in git-log. - - 8. For larger or more important user visible changes, as well as - security fixes, please add a line in NEWS. On exception, it might be - worth adding a multi-line entry (such as the entry that announces all - the types that became opaque with OpenSSL 1.1.0). - This file helps users get a very quick summary of what comes with a - specific release, to see if an upgrade is worth the effort. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,94 @@ +HOW TO CONTRIBUTE TO OpenSSL +============================ + +Please visit our [Getting Started] page for other ideas about how to contribute. + + [Getting Started]: + +Development is done on GitHub in the [openssl/openssl] repository. + + [openssl/openssl]: + +To request new features or report bugs, please open an issue on GitHub + +To submit a patch, please open a pull request on GitHub. If you are thinking +of making a large contribution, open an issue for it before starting work, +to get comments from the community. Someone may be already working on +the same thing or there may be reasons why that feature isn't implemented. + +To make it easier to review and accept your pull request, please follow these +guidelines: + + 1. Anything other than a trivial contribution requires a [Contributor + License Agreement] (CLA), giving us permission to use your code. + If your contribution is too small to require a CLA (e.g. fixing a spelling + mistake), place the text "`CLA: trivial`" on a line by itself separated by + an empty line from the rest of the commit message. It is not sufficient to + only place the text in the GitHub pull request description. + + [Contributor License Agreement]: + + To amend a missing "`CLA: trivial`" line after submission, do the following: + + ``` + git commit --amend + [add the line, save and quit the editor] + git push -f + ``` + + 2. All source files should start with the following text (with + appropriate comment characters at the start of each line and the + year(s) updated): + + ``` + Copyright 20xx-20yy 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 + https://www.openssl.org/source/license.html + ``` + + 3. Patches should be as current as possible; expect to have to rebase + often. We do not accept merge commits, you will have to remove them + (usually by rebasing) before it will be acceptable. + + 4. Patches should follow our [coding style] and compile without warnings. + Where `gcc` or `clang` is available you should use the + `--strict-warnings` `Configure` option. OpenSSL compiles on many varied + platforms: try to ensure you only use portable features. Clean builds via + GitHub Actions and AppVeyor are required, and they are started automatically + whenever a PR is created or updated. + + [coding style]: https://www.openssl.org/policies/technical/coding-style.html + + 5. When at all possible, patches should include tests. These can + either be added to an existing test, or completely new. Please see + [test/README.md](test/README.md) for information on the test framework. + + 6. New features or changed functionality must include + documentation. Please look at the "pod" files in doc/man[1357] for + examples of our style. Run "make doc-nits" to make sure that your + documentation changes are clean. + + 7. For user visible changes (API changes, behaviour changes, ...), + consider adding a note in [CHANGES.md](CHANGES.md). + This could be a summarising description of the change, and could + explain the grander details. + Have a look through existing entries for inspiration. + Please note that this is NOT simply a copy of git-log one-liners. + Also note that security fixes get an entry in [CHANGES.md](CHANGES.md). + This file helps users get more in depth information of what comes + with a specific release without having to sift through the higher + noise ratio in git-log. + + 8. For larger or more important user visible changes, as well as + security fixes, please add a line in [NEWS.md](NEWS.md). + On exception, it might be worth adding a multi-line entry (such as + the entry that announces all the types that became opaque with + OpenSSL 1.1.0). + This file helps users get a very quick summary of what comes with a + specific release, to see if an upgrade is worth the effort. + + 9. Guidelines how to integrate error output of new crypto library modules + can be found in [crypto/err/README.md](crypto/err/README.md). diff --git a/Configure b/Configure --- a/Configure +++ b/Configure @@ -2,7 +2,7 @@ # -*- mode: perl; -*- # Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -15,17 +15,38 @@ use FindBin; use lib "$FindBin::Bin/util/perl"; use File::Basename; -use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; +use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs splitdir/; use File::Path qw/mkpath/; +use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt"; use OpenSSL::Glob; +use OpenSSL::Template; +use OpenSSL::config; -# see INSTALL for instructions. +# see INSTALL.md for instructions. my $orig_death_handler = $SIG{__DIE__}; $SIG{__DIE__} = \&death_handler; my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n"; +my $banner = <<"EOF"; + +********************************************************************** +*** *** +*** OpenSSL has been successfully configured *** +*** *** +*** If you encounter a problem while building, please open an *** +*** issue on GitHub *** +*** and include the output from the following command: *** +*** *** +*** perl configdata.pm --dump *** +*** *** +*** (If you are new to OpenSSL, you might want to consult the *** +*** 'Troubleshooting' section in the INSTALL.md file first) *** +*** *** +********************************************************************** +EOF + # Options: # # --config add the given configuration file, which will be read after @@ -40,11 +61,17 @@ # given with --prefix. # This becomes the value of OPENSSLDIR in Makefile and in C. # (Default: PREFIX/ssl) +# --banner=".." Output specified text instead of default completion banner +# +# -w Don't wait after showing a Configure warning # # --cross-compile-prefix Add specified prefix to binutils components. # -# --api One of 0.9.8, 1.0.0 or 1.1.0. Do not compile support for -# interfaces deprecated as of the specified OpenSSL version. +# --api One of 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, or 3.0 +# Define the public APIs as they were for that version +# including patch releases. If 'no-deprecated' is also +# given, do not compile support for interfaces deprecated +# up to and including the specified OpenSSL version. # # no-hw-xxx do not compile support for specific crypto hardware. # Generic OpenSSL-style methods relating to this support @@ -63,12 +90,13 @@ # zlib-dynamic Like "zlib", but the zlib library is expected to be a shared # library and will be loaded in run-time by the OpenSSL library. # sctp include SCTP support +# no-uplink Don't build support for UPLINK interface. # enable-weak-ssl-ciphers # Enable weak ciphers that are disabled by default. # 386 generate 80386 code in assembly modules # no-sse2 disables IA-32 SSE2 code in assembly modules, the above # mentioned '386' option implies this one -# no- build without specified algorithm (rsa, idea, rc5, ...) +# no- build without specified algorithm (dsa, idea, rc5, ...) # - + All options which are unknown to the 'Configure' script are # / passed through to the compiler. Unix-style options beginning # with a '-' or '+' are recognized, as well as Windows-style @@ -110,7 +138,6 @@ # get past these. Note that we only use these with C compilers, not with # C++ compilers. -# DEBUG_UNUSED enables __owur (warn unused result) checks. # -DPEDANTIC complements -pedantic and is meant to mask code that # is not strictly standard-compliant and/or implementation-specific, # e.g. inline assembly, disregards to alignment requirements, such @@ -124,9 +151,9 @@ # but 'long long' type. my @gcc_devteam_warn = qw( - -DDEBUG_UNUSED - -DPEDANTIC -pedantic -Wno-long-long + -DPEDANTIC -pedantic -Wno-long-long -DUNUSEDRESULT_DEBUG -Wall + -Wmissing-declarations -Wextra -Wno-unused-parameter -Wno-missing-field-initializers @@ -164,10 +191,6 @@ /WX ); -# This adds backtrace information to the memory leak info. Is only used -# when crypto-mdebug-backtrace is enabled. -my $memleak_devteam_backtrace = "-rdynamic"; - my $strict_warnings = 0; # As for $BSDthreads. Idea is to maintain "collective" set of flags, @@ -182,13 +205,31 @@ # # API compatibility name to version number mapping. # -my $maxapi = "1.1.0"; # API for "no-deprecated" builds my $apitable = { - "1.1.0" => "0x10100000L", - "1.0.0" => "0x10000000L", - "0.9.8" => "0x00908000L", + # This table expresses when API additions or changes can occur. + # The numbering used changes from 3.0 and on because we updated + # (solidified) our version numbering scheme at that point. + + # From 3.0 and on, we internalise the given version number in decimal + # as MAJOR * 10000 + MINOR * 100 + 0 + "3.0.0" => 30000, + "3.0" => 30000, + + # Note that before 3.0, we didn't have the same version number scheme. + # Still, the numbering we use here covers what we need. + "1.1.1" => 10101, + "1.1.0" => 10100, + "1.0.2" => 10002, + "1.0.1" => 10001, + "1.0.0" => 10000, + "0.9.8" => 908, }; +# For OpenSSL::config::get_platform +my %guess_opts = (); + +my $dryrun = 0; + our %table = (); our %config = (); our %withargs = (); @@ -233,6 +274,9 @@ $config{sourcedir} = abs2rel($srcdir, $blddir); $config{builddir} = abs2rel($blddir, $blddir); +# echo -n 'holy hand grenade of antioch' | openssl sha256 +$config{FIPSKEY} = + 'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813'; # Collect reconfiguration information if needed my @argvcopy=@ARGV; @@ -260,29 +304,58 @@ $config{perlargv} = [ @argvcopy ]; +# Historical: if known directories in crypto/ have been removed, it means +# that those sub-systems are disabled. +# (the other option would be to removed them from the SUBDIRS statement in +# crypto/build.info) +# We reverse the input list for cosmetic purely reasons, to compensate that +# 'unshift' adds at the front of the list (i.e. in reverse input order). +foreach ( reverse sort( 'aes', 'aria', 'bf', 'camellia', 'cast', 'des', 'dh', + 'dsa', 'ec', 'hmac', 'idea', 'md2', 'md5', 'mdc2', + 'rc2', 'rc4', 'rc5', 'ripemd', 'seed', 'sha', + 'sm2', 'sm3', 'sm4') ) { + unshift @argvcopy, "no-$_" if ! -d catdir($srcdir, 'crypto', $_); +} + # Collect version numbers -$config{version} = "unknown"; -$config{version_num} = "unknown"; -$config{shlib_version_number} = "unknown"; -$config{shlib_version_history} = "unknown"; +my %version = (); collect_information( - collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')), - qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; }, - qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 }, - qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 }, - qr/SHLIB_VERSION_HISTORY *"([^"]*)"/ => sub { $config{shlib_version_history}=$1 } + collect_from_file(catfile($srcdir,'VERSION.dat')), + qr/\s*(\w+)\s*=\s*(.*?)\s*$/ => + sub { + # Only define it if there is a value at all + if ($2 ne '') { + my $k = $1; + my $v = $2; + # Some values are quoted. Trim the quotes + $v = $1 if $v =~ /^"(.*)"$/; + $version{uc $k} = $v; + } + }, + "OTHERWISE" => + sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION.dat" }, ); -if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; } -($config{major}, $config{minor}) - = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/); -($config{shlib_major}, $config{shlib_minor}) - = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/); -die "erroneous version information in opensslv.h: ", - "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n" - if ($config{major} eq "" || $config{minor} eq "" - || $config{shlib_major} eq "" || $config{shlib_minor} eq ""); +$config{major} = $version{MAJOR} // 'unknown'; +$config{minor} = $version{MINOR} // 'unknown'; +$config{patch} = $version{PATCH} // 'unknown'; +$config{prerelease} = + defined $version{PRE_RELEASE_TAG} ? "-$version{PRE_RELEASE_TAG}" : ''; +$config{build_metadata} = + defined $version{BUILD_METADATA} ? "+$version{BUILD_METADATA}" : ''; +$config{shlib_version} = $version{SHLIB_VERSION} // 'unknown'; +$config{release_date} = $version{RELEASE_DATE} // 'xx XXX xxxx'; + +$config{version} = "$config{major}.$config{minor}.$config{patch}"; +$config{full_version} = "$config{version}$config{prerelease}$config{build_metadata}"; + +die "erroneous version information in VERSION.dat: ", + "$config{version}, $config{shlib_version}\n" + unless (defined $version{MAJOR} + && defined $version{MINOR} + && defined $version{PATCH} + && defined $version{SHLIB_VERSION}); # Collect target configurations @@ -317,21 +390,6 @@ my $auto_threads=1; # enable threads automatically? true by default my $default_ranlib; -# Top level directories to build -$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ]; -# crypto/ subdirectories to build -$config{sdirs} = [ - "objects", - "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3", - "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes", - "bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine", - "buffer", "bio", "stack", "lhash", "rand", "err", - "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", - "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store" - ]; -# test/ subdirectories to build -$config{tdirs} = [ "ossl_shim" ]; - # Known TLS and DTLS protocols my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3); my @dtls = qw(dtls1 dtls1_2); @@ -341,6 +399,7 @@ # For developers: keep it sorted alphabetically my @disablables = ( + "acvp-tests", "afalgeng", "aria", "asan", @@ -351,16 +410,18 @@ "autoload-config", "bf", "blake2", - "buildtest-c\\+\\+", + "buildtest-c++", + "bulk", + "cached-fetch", "camellia", "capieng", "cast", "chacha", "cmac", + "cmp", "cms", "comp", "crypto-mdebug", - "crypto-mdebug-backtrace", "ct", "deprecated", "des", @@ -373,31 +434,36 @@ "dynamic-engine", "ec", "ec2m", + "ec_nistp_64_gcc_128", "ecdh", "ecdsa", - "ec_nistp_64_gcc_128", "egd", "engine", "err", "external-tests", "filenames", - "fuzz-libfuzzer", + "fips", + "fips-securitychecks", "fuzz-afl", + "fuzz-libfuzzer", "gost", - "heartbeats", - "hw(-.+)?", "idea", + "ktls", + "legacy", + "loadereng", "makedepend", "md2", "md4", "mdc2", + "module", "msan", "multiblock", "nextprotoneg", - "pinshared", "ocb", "ocsp", + "padlockeng", "pic", + "pinshared", "poly1305", "posix-io", "psk", @@ -409,9 +475,11 @@ "rmd160", "scrypt", "sctp", + "secure-memory", "seed", "shared", "siphash", + "siv", "sm2", "sm3", "sm4", @@ -426,12 +494,14 @@ "tests", "threads", "tls", + "trace", "ts", "ubsan", "ui-console", "unit-test", - "whirlpool", + "uplink", "weak-ssl-ciphers", + "whirlpool", "zlib", "zlib-dynamic", ); @@ -441,16 +511,29 @@ push(@disablables, "$proto-method") unless $proto eq "tls1_3"; } +# Internal disablables, for aliasing purposes. They serve no special +# purpose here, but allow scripts to get to know them through configdata.pm, +# where these are merged with @disablables. +# The actual aliasing mechanism is done via %disable_cascades +my @disablables_int = qw( + crmf + ); + my %deprecated_disablables = ( "ssl2" => undef, "buf-freelists" => undef, + "crypto-mdebug-backtrace" => undef, + "hw" => "hw", # causes cascade, but no macro + "hw-padlock" => "padlockeng", "ripemd" => "rmd160", "ui" => "ui-console", + "heartbeats" => undef, ); # All of the following are disabled by default: our %disabled = ( # "what" => "comment" + "fips" => "default", "asan" => "default", "buildtest-c++" => "default", "crypto-mdebug" => "default", @@ -459,16 +542,16 @@ "ec_nistp_64_gcc_128" => "default", "egd" => "default", "external-tests" => "default", - "fuzz-libfuzzer" => "default", "fuzz-afl" => "default", - "heartbeats" => "default", + "fuzz-libfuzzer" => "default", + "ktls" => "default", "md2" => "default", "msan" => "default", "rc5" => "default", "sctp" => "default", - "ssl-trace" => "default", "ssl3" => "default", "ssl3-method" => "default", + "trace" => "default", "ubsan" => "default", "unit-test" => "default", "weak-ssl-ciphers" => "default", @@ -479,14 +562,29 @@ # Note: => pair form used for aesthetics, not to truly make a hash table my @disable_cascades = ( # "what" => [ "cascade", ... ] + "bulk" => [ "shared", "dso", + "aria", "async", "autoload-config", + "blake2", "bf", "camellia", "cast", "chacha", + "cmac", "cms", "cmp", "comp", "ct", + "des", "dgram", "dh", "dsa", + "ec", "engine", + "filenames", + "idea", "ktls", + "md4", "multiblock", "nextprotoneg", + "ocsp", "ocb", "poly1305", "psk", + "rc2", "rc4", "rmd160", + "seed", "siphash", "siv", + "sm3", "sm4", "srp", + "srtp", "ssl3-method", "ssl-trace", + "ts", "ui-console", "whirlpool", + "fips-securitychecks" ], sub { $config{processor} eq "386" } => [ "sse2" ], "ssl" => [ "ssl3" ], "ssl3-method" => [ "ssl3" ], "zlib" => [ "zlib-dynamic" ], "des" => [ "mdc2" ], - "ec" => [ "ecdsa", "ecdh" ], - + "ec" => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ], "dgram" => [ "dtls", "sctp" ], "sock" => [ "dgram" ], "dtls" => [ @dtls ], @@ -499,24 +597,51 @@ "crypto-mdebug" => [ "crypto-mdebug-backtrace" ], - # Without position independent code, there can be no shared libraries or DSOs - "pic" => [ "shared" ], - "shared" => [ "dynamic-engine" ], - "dso" => [ "dynamic-engine" ], - "engine" => [ "afalgeng", "devcryptoeng" ], + # If no modules, then no dynamic engines either + "module" => [ "dynamic-engine" ], + + # Without shared libraries, dynamic engines aren't possible. + # This is due to them having to link with libcrypto and register features + # using the ENGINE functionality, and since that relies on global tables, + # those *have* to be exacty the same as the ones accessed from the app, + # which cannot be guaranteed if shared libraries aren't present. + # (note that even with shared libraries, both the app and dynamic engines + # must be linked with the same library) + "shared" => [ "dynamic-engine", "uplink" ], + "dso" => [ "dynamic-engine", "module" ], + # Other modules don't necessarily have to link with libcrypto, so shared + # libraries do not have to be a condition to produce those. + + # Without position independent code, there can be no shared libraries + # or modules. + "pic" => [ "shared", "module" ], + + "module" => [ "fips", "dso" ], + + "engine" => [ "dynamic-engine", grep(/eng$/, @disablables) ], + "dynamic-engine" => [ "loadereng" ], + "hw" => [ "padlockeng" ], # no-autoalginit is only useful when building non-shared - "autoalginit" => [ "shared", "apps" ], + "autoalginit" => [ "shared", "apps", "fips" ], "stdio" => [ "apps", "capieng", "egd" ], "apps" => [ "tests" ], "tests" => [ "external-tests" ], "comp" => [ "zlib" ], - "ec" => [ "tls1_3", "sm2" ], "sm3" => [ "sm2" ], sub { !$disabled{"unit-test"} } => [ "heartbeats" ], sub { !$disabled{"msan"} } => [ "asm" ], + + "cmac" => [ "siv" ], + "legacy" => [ "md2" ], + + "cmp" => [ "crmf" ], + + "fips" => [ "fips-securitychecks", "acvp-tests" ], + + "deprecated-3.0" => [ "engine", "srp" ] ); # Avoid protocol support holes. Also disable all versions below N, if version @@ -541,8 +666,6 @@ # To remove something from %disabled, use "enable-foo". # For symmetry, "disable-foo" is a synonym for "no-foo". -&usage if ($#ARGV < 0); - # For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with # platform specific list separators. Users from those platforms should # recognise those separators from how you set up the PATH to find executables. @@ -627,10 +750,8 @@ $config{ex_libs} = [ env('__CNF_LDLIBS') || () ]; $config{openssl_api_defines}=[]; -$config{openssl_algorithm_defines}=[]; -$config{openssl_thread_defines}=[]; $config{openssl_sys_defines}=[]; -$config{openssl_other_defines}=[]; +$config{openssl_feature_defines}=[]; $config{options}=""; $config{build_type} = "release"; my $target=""; @@ -679,12 +800,14 @@ s /^threads$/enable-threads/; s /^zlib$/enable-zlib/; s /^zlib-dynamic$/enable-zlib-dynamic/; + s /^fips$/enable-fips/; if (/^(no|disable|enable)-(.+)$/) { my $word = $2; - if (!exists $deprecated_disablables{$word} - && !grep { $word =~ /^${_}$/ } @disablables) + if ($word !~ m|hw(?:-.+)| # special treatment for hw regexp opt + && !exists $deprecated_disablables{$word} + && !grep { $word eq $_ } @disablables) { $unsupported_options{$_} = 1; next; @@ -732,15 +855,16 @@ } elsif (exists $deprecated_disablables{$1}) { - if ($deprecated_disablables{$1} ne "") + $deprecated_options{$_} = 1; + if (defined $deprecated_disablables{$1}) { - $deprecated_options{$_} = 1; - if (defined $deprecated_disablables{$1}) - { - $disabled{$deprecated_disablables{$1}} = "option"; - } + $disabled{$deprecated_disablables{$1}} = "option"; } } + elsif ($1 =~ m|hw(?:-.+)|) # deprecate hw options in regexp form + { + $deprecated_options{$_} = 1; + } else { $disabled{$1} = "option"; @@ -768,6 +892,22 @@ # No longer an automatic choice $auto_threads = 0 if ($1 eq "threads"); } + elsif (/^-d$/) # From older 'config' + { + $config{build_type} = "debug"; + } + elsif (/^-v$/) # From older 'config' + { + $guess_opts{verbose} = 1; + } + elsif (/^-w$/) + { + $guess_opts{nowait} = 1; + } + elsif (/^-t$/) # From older 'config' + { + $dryrun = 1; + } elsif (/^--strict-warnings$/) { # Pretend that our strict flags is a C flag, and replace it @@ -785,20 +925,12 @@ } elsif (/^386$/) { $config{processor}=386; } - elsif (/^fips$/) - { - die "FIPS mode not supported\n"; - } elsif (/^rsaref$/) { # No RSAref support any more since it's not needed. # The check for the option is there so scripts aren't # broken } - elsif (/^nofipscanistercheck$/) - { - die "FIPS mode not supported\n"; - } elsif (m|^[-+/]|) { if (/^--prefix=(.*)$/) @@ -809,7 +941,10 @@ } elsif (/^--api=(.*)$/) { - $config{api}=$1; + my $api = $1; + die "Unknown API compatibility level $api" + unless defined $apitable->{$api}; + $config{api}=$apitable->{$api}; } elsif (/^--libdir=(.*)$/) { @@ -844,6 +979,20 @@ push @seed_sources, $x; } } + elsif (/^--fips-key=(.*)$/) + { + $user{FIPSKEY}=lc($1); + die "Non-hex character in FIPS key\n" + if $user{FIPSKEY} =~ /[^a-f0-9]/; + die "FIPS key must have even number of characters\n" + if length $1 & 1; + die "FIPS key too long (64 bytes max)\n" + if length $1 > 64; + } + elsif (/^--banner=(.*)$/) + { + $banner = $1 . "\n"; + } elsif (/^--cross-compile-prefix=(.*)$/) { $user{CROSS_COMPILE}=$1; @@ -926,10 +1075,6 @@ } } -if (defined($config{api}) && !exists $apitable->{$config{api}}) { - die "***** Unsupported api compatibility level: $config{api}\n", -} - if (keys %deprecated_options) { warn "***** Deprecated options: ", @@ -1002,6 +1147,23 @@ "***** any of asan, msan or ubsan\n"; } +# If no target was given, try guessing. +unless ($target) { + my %system_config = OpenSSL::config::get_platform(%guess_opts, %user); + + # The $system_config{disable} is used to populate %disabled with + # entries that aren't already there. + foreach ( @{$system_config{disable} // []} ) { + $disabled{$_} = 'system' unless defined $disabled{$_}; + } + delete $system_config{disable}; + + # Override config entries with stuff from the guesser. + # It's assumed that this really is nothing new. + %config = ( %config, %system_config ); + $target = $system_config{target}; +} + sub disable { my $disable_type = shift; @@ -1052,8 +1214,8 @@ exit 0; } -print "Configuring OpenSSL version $config{version} ($config{version_num}) "; -print "for $target\n"; +print "Configuring OpenSSL version $config{full_version} "; +print "for target $target\n"; if (scalar(@seed_sources) == 0) { print "Using os-specific seed configuration\n"; @@ -1074,12 +1236,13 @@ application. Please read the 'Note on random number generation' section in the -INSTALL instructions and the RAND_DRBG(7) manual page for more details. +INSTALL.md instructions and the RAND_DRBG(7) manual page for more +details. ============================== WARNING =============================== _____ } -push @{$config{openssl_other_defines}}, +push @{$config{openssl_feature_defines}}, map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" } @seed_sources; @@ -1099,7 +1262,26 @@ } } -&usage if !$table{$target} || $table{$target}->{template}; +if ($target) { + # It's possible that we have different config targets for specific + # toolchains, so we try to detect them, and go for the plain config + # target if not. + my $found; + foreach ( ( "$target-$user{CC}", "$target", undef ) ) { + $found=$_ if $table{$_} && !$table{$_}->{template}; + last if $found; + } + $target = $found; +} else { + # If we don't have a config target now, we try the C compiler as we + # fallback + my $cc = $user{CC} // 'cc'; + $target = $cc if $table{$cc} && !$table{$cc}->{template}; +} + +&usage unless $target; + +exit 0 if $dryrun; # From older 'config' $config{target} = $target; my %target = resolve_config($target); @@ -1135,22 +1317,19 @@ delete $disabled{$feature}; } } + +# If uplink_arch isn't defined, disable uplink +$disabled{uplink} = 'no uplink_arch' unless (defined $target{uplink_arch}); +# If asm_arch isn't defined, disable asm +$disabled{asm} = 'no asm_arch' unless (defined $target{asm_arch}); + disable(); # Run a cascade now $target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX}; $target{cxxflags}//=$target{cflags} if $target{CXX}; -$target{exe_extension}=""; -$target{exe_extension}=".exe" if ($config{target} eq "DJGPP" - || $config{target} =~ /^(?:Cygwin|mingw)/); +$target{exe_extension}=".exe" if ($config{target} eq "DJGPP"); $target{exe_extension}=".pm" if ($config{target} =~ /vos/); -($target{shared_extension_simple}=$target{shared_extension}) - =~ s|\.\$\(SHLIB_VERSION_NUMBER\)|| - unless defined($target{shared_extension_simple}); -$target{dso_extension}//=$target{shared_extension_simple}; -($target{shared_import_extension}=$target{shared_extension_simple}.".a") - if ($config{target} =~ /^(?:Cygwin|mingw)/); - # Fill %config with values from %user, and in case those are undefined or # empty, use values from %target (acting as a default). foreach (keys %user) { @@ -1201,7 +1380,7 @@ # At this point, we can forget everything about %user and %useradd, # because it's now all been merged into the corresponding $config entry -if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) { +if (grep { $_ =~ /(?:^|\s)-static(?:\s|$)/ } @{$config{LDFLAGS}}) { disable('static', 'pic', 'threads'); } @@ -1277,19 +1456,35 @@ } } +# Find out if clang's sanitizers have been enabled with -fsanitize +# flags and ensure that the corresponding %disabled elements area +# removed to reflect that the sanitizers are indeed enabled. +my %detected_sanitizers = (); +foreach (grep /^-fsanitize=/, @{$config{CFLAGS} || []}) { + (my $checks = $_) =~ s/^-fsanitize=//; + foreach (split /,/, $checks) { + my $d = { address => 'asan', + undefined => 'ubsan', + memory => 'msan' } -> {$_}; + next unless defined $d; + + $detected_sanitizers{$d} = 1; + if (defined $disabled{$d}) { + die "***** Conflict between disabling $d and enabling $_ sanitizer" + if $disabled{$d} ne "default"; + delete $disabled{$d}; + } + } +} + # If threads still aren't disabled, add a C macro to ensure the source # code knows about it. Any other flag is taken care of by the configs. unless($disabled{threads}) { - push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS"; -} - -# With "deprecated" disable all deprecated features. -if (defined($disabled{"deprecated"})) { - $config{api} = $maxapi; + push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS"; } my $no_shared_warn=0; -if ($target{shared_target} eq "") +if (($target{shared_target} // '') eq "") { $no_shared_warn = 1 if (!$disabled{shared} || !$disabled{"dynamic-engine"}); @@ -1302,21 +1497,16 @@ $config{dynamic_engines} = 1; } -unless ($disabled{asan}) { +unless ($disabled{asan} || defined $detected_sanitizers{asan}) { push @{$config{cflags}}, "-fsanitize=address"; - push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX}; } -unless ($disabled{ubsan}) { - # -DPEDANTIC or -fnosanitize=alignment may also be required on some - # platforms. - push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"; - push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all" if $config{CXX}; +unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) { + push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC"; } -unless ($disabled{msan}) { +unless ($disabled{msan} || defined $detected_sanitizers{msan}) { push @{$config{cflags}}, "-fsanitize=memory"; - push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX}; } unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"} @@ -1350,98 +1540,46 @@ push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}"; } -unless ($disabled{asm}) { - $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386"); - push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c"); - - $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m})); - - # bn-586 is the only one implementing bn_*_part_words - push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/); - push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/); - - push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/); - push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/); - push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/); - push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/); - - if ($target{sha1_asm_src}) { - push @{$config{lib_defines}}, "SHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/); - push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/); - push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/); - } - if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) { - push @{$config{lib_defines}}, "KECCAK1600_ASM"; - } - if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) { - push @{$config{lib_defines}}, "RC4_ASM"; - } - if ($target{md5_asm_src}) { - push @{$config{lib_defines}}, "MD5_ASM"; - } - $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC - if ($target{rmd160_asm_src}) { - push @{$config{lib_defines}}, "RMD160_ASM"; - } - if ($target{aes_asm_src}) { - push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);; - push @{$config{lib_defines}}, "AESNI_ASM" if ($target{aes_asm_src} =~ m/\baesni-/);; - # aes-ctr.fake is not a real file, only indication that assembler - # module implements AES_ctr32_encrypt... - push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//); - # aes-xts.fake indicates presence of AES_xts_[en|de]crypt... - push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//); - $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2}); - push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/); - push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/); - } - if ($target{wp_asm_src} =~ /mmx/) { - if ($config{processor} eq "386") { - $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src}; - } elsif (!$disabled{"whirlpool"}) { - push @{$config{lib_defines}}, "WHIRLPOOL_ASM"; - } - } - if ($target{modes_asm_src} =~ /ghash-/) { - push @{$config{lib_defines}}, "GHASH_ASM"; - } - if ($target{ec_asm_src} =~ /ecp_nistz256/) { - push @{$config{lib_defines}}, "ECP_NISTZ256_ASM"; - } - if ($target{ec_asm_src} =~ /x25519/) { - push @{$config{lib_defines}}, "X25519_ASM"; - } - if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) { - push @{$config{dso_defines}}, "PADLOCK_ASM"; - } - if ($target{poly1305_asm_src} ne "") { - push @{$config{lib_defines}}, "POLY1305_ASM"; - } -} - my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); my %predefined_CXX = $config{CXX} ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX}) : (); +unless ($disabled{asm}) { + # big endian systems can use ELFv2 ABI + if ($target eq "linux-ppc64") { + $target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2); + } +} + # Check for makedepend capabilities. if (!$disabled{makedepend}) { - if ($config{target} =~ /^(VC|vms)-/) { - # For VC- and vms- targets, there's nothing more to do here. The - # functionality is hard coded in the corresponding build files for - # cl (Windows) and CC/DECC (VMS). + # If the attribute makedep_scheme is defined, then we assume that the + # config target and its associated build file are programmed to deal + # with it. + # If makedep_scheme is undefined, we go looking for GCC compatible + # dependency making, and if that's not available, we try to fall back + # on 'makedepend'. + if ($target{makedep_scheme}) { + $config{makedep_scheme} = $target{makedep_scheme}; + # If the makedepcmd attribute is defined, copy it. If not, the + # build files will have to fend for themselves. + $config{makedepcmd} = $target{makedepcmd} if $target{makedepcmd}; } elsif (($predefined_C{__GNUC__} // -1) >= 3 && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) { # We know that GNU C version 3 and up as well as all clang # versions support dependency generation, but Xcode did not # handle $cc -M before clang support (but claims __GNUC__ = 3) - $config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}"; + $config{makedep_scheme} = 'gcc'; } else { - # In all other cases, we look for 'makedepend', and disable the - # capability if not found. - $config{makedepprog} = which('makedepend'); - disable('unavailable', 'makedepend') unless $config{makedepprog}; + # In all other cases, we look for 'makedepend', and set the + # makedep_scheme value if we found it. + $config{makedepcmd} = which('makedepend'); + $config{makedep_scheme} = 'makedepend' if $config{makedepcmd}; } + + # If no depend scheme is set, we disable makedepend + disable('unavailable', 'makedepend') unless $config{makedep_scheme}; } if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') { @@ -1469,7 +1607,6 @@ # Deal with bn_ops ################################################### $config{bn_ll} =0; -$config{export_var_as_fn} =0; my $def_int="unsigned int"; $config{rc4_int} =$def_int; ($config{b64l},$config{b64},$config{b32})=(0,0,1); @@ -1477,7 +1614,6 @@ my $count = 0; foreach (sort split(/\s+/,$target{bn_ops})) { $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/; - $config{export_var_as_fn}=1 if $_ eq 'EXPORT_VAR_AS_FN'; $config{bn_ll}=1 if $_ eq 'BN_LLONG'; $config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR'; ($config{b64l},$config{b64},$config{b32}) @@ -1490,6 +1626,14 @@ die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n" if $count > 1; +$config{api} = $config{major} * 10000 + $config{minor} * 100 + unless $config{api}; +foreach (keys %$apitable) { + $disabled{"deprecated-$_"} = "deprecation" + if $disabled{deprecated} && $config{api} >= $apitable->{$_}; +} + +disable(); # Run a cascade now # Hack cflags for better warnings (dev option) ####################### @@ -1500,11 +1644,9 @@ $config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } @{$config{cxxflags}} ] if $config{CXX}; -if (defined($config{api})) { - $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ]; - my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}}); - push @{$config{defines}}, $apiflag; -} +$config{openssl_api_defines} = [ + "OPENSSL_CONFIGURED_API=".$config{api}, +]; my @strict_warnings_collection=(); if ($strict_warnings) @@ -1533,19 +1675,6 @@ : ( $_ ) } @{$config{CFLAGS}} ]; -unless ($disabled{"crypto-mdebug-backtrace"}) - { - foreach my $wopt (split /\s+/, $memleak_devteam_backtrace) - { - push @{$config{cflags}}, $wopt - unless grep { $_ eq $wopt } @{$config{cflags}}; - } - if ($target =~ /^BSD-/) - { - push @{$config{ex_libs}}, "-lexecinfo"; - } - } - unless ($disabled{afalgeng}) { $config{afalgeng}=""; if (grep { $_ eq 'afalgeng' } @{$target{enable}}) { @@ -1583,6 +1712,26 @@ } } +unless ($disabled{ktls}) { + $config{ktls}=""; + my $cc = $config{CROSS_COMPILE}.$config{CC}; + if ($target =~ m/^linux/) { + system("printf '#include \n#include ' | $cc -E - >/dev/null 2>&1"); + if ($? != 0) { + disable('too-old-kernel', 'ktls'); + } + } elsif ($target =~ m/^BSD/) { + system("printf '#include \n#include ' | $cc -E - >/dev/null 2>&1"); + if ($? != 0) { + disable('too-old-freebsd', 'ktls'); + } + } else { + disable('not-linux-or-freebsd', 'ktls'); + } +} + +push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls}); + # Get the extra flags used when building shared libraries and modules. We # do this late because some of them depend on %disabled. @@ -1626,47 +1775,53 @@ # ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON +###################################################################### +# Build up information for skipping certain directories depending on disabled +# features, as well as setting up macros for disabled features. + +# This is a tentative database of directories to skip. Some entries may not +# correspond to anything real, but that's ok, they will simply be ignored. +# The actual processing of these entries is done in the build.info lookup +# loop further down. +# +# The key is a Unix formatted path in the source tree, the value is an index +# into %disabled_info, so any existing path gets added to a corresponding +# 'skipped' entry in there with the list of skipped directories. +my %skipdir = (); my %disabled_info = (); # For configdata.pm foreach my $what (sort keys %disabled) { + # There are deprecated disablables that translate to themselves. + # They cause disabling cascades, but should otherwise not regiter. + next if $deprecated_disablables{$what}; + # The generated $disabled{"deprecated-x.y"} entries are special + # and treated properly elsewhere + next if $what =~ m|^deprecated-|; + $config{options} .= " no-$what"; - if (!grep { $what eq $_ } ( 'buildtest-c++', 'threads', 'shared', 'pic', - 'dynamic-engine', 'makedepend', - 'zlib-dynamic', 'zlib', 'sse2' )) { + if (!grep { $what eq $_ } ( 'buildtest-c++', 'fips', 'threads', 'shared', + 'module', 'pic', 'dynamic-engine', 'makedepend', + 'zlib-dynamic', 'zlib', 'sse2', 'legacy' )) { (my $WHAT = uc $what) =~ s|-|_|g; - - # Fix up C macro end names - $WHAT = "RMD160" if $what eq "ripemd"; + my $skipdir = $what; # fix-up crypto/directory name(s) - $what = "ripemd" if $what eq "rmd160"; - $what = "whrlpool" if $what eq "whirlpool"; + $skipdir = "ripemd" if $what eq "rmd160"; + $skipdir = "whrlpool" if $what eq "whirlpool"; my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT"; + push @{$config{openssl_feature_defines}}, $macro; - if ((grep { $what eq $_ } @{$config{sdirs}}) - && $what ne 'async' && $what ne 'err' && $what ne 'dso') { - @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}}; - $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ]; - - if ($what ne 'engine') { - push @{$config{openssl_algorithm_defines}}, $macro; - } else { - @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}}; - push @{$disabled_info{engine}->{skipped}}, catdir('engines'); - push @{$config{openssl_other_defines}}, $macro; - } - } else { - push @{$config{openssl_other_defines}}, $macro; - } - + $skipdir{engines} = $what if $what eq 'engine'; + $skipdir{"crypto/$skipdir"} = $what + unless $what eq 'async' || $what eq 'err' || $what eq 'dso'; } } if ($disabled{"dynamic-engine"}) { - push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE"; + push @{$config{openssl_feature_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE"; } else { - push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE"; + push @{$config{openssl_feature_defines}}, "OPENSSL_NO_STATIC_ENGINE"; } # If we use the unified build, collect information from build.info files @@ -1674,7 +1829,7 @@ my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO}); if ($builder eq "unified") { - use with_fallback qw(Text::Template); + use Text::Template 1.46; sub cleandir { my $base = shift; @@ -1748,64 +1903,174 @@ $config{build_file_templates} = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"), $blddir), - $build_file_template, - cleanfile($srcdir, catfile("Configurations", "common.tmpl"), - $blddir) ]; + $build_file_template ]; - my @build_infos = ( [ ".", "build.info" ] ); - foreach (@{$config{dirs}}) { - push @build_infos, [ $_, "build.info" ] - if (-f catfile($srcdir, $_, "build.info")); - } - foreach (@{$config{sdirs}}) { - push @build_infos, [ catdir("crypto", $_), "build.info" ] - if (-f catfile($srcdir, "crypto", $_, "build.info")); - } - foreach (@{$config{engdirs}}) { - push @build_infos, [ catdir("engines", $_), "build.info" ] - if (-f catfile($srcdir, "engines", $_, "build.info")); - } - foreach (@{$config{tdirs}}) { - push @build_infos, [ catdir("test", $_), "build.info" ] - if (-f catfile($srcdir, "test", $_, "build.info")); - } + my @build_dirs = ( [ ] ); # current directory $config{build_infos} = [ ]; + # We want to detect configdata.pm in the source tree, so we + # don't use it if the build tree is different. + my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir); + + # Any source file that we recognise is placed in this hash table, with + # the list of its intended destinations as value. When everything has + # been collected, there's a routine that checks that these source files + # exist, or if they are generated, that the generator exists. + my %check_exist = (); + my %check_generate = (); + my %ordinals = (); - foreach (@build_infos) { - my $sourced = catdir($srcdir, $_->[0]); - my $buildd = catdir($blddir, $_->[0]); + while (@build_dirs) { + my @curd = @{shift @build_dirs}; + my $sourced = catdir($srcdir, @curd); + my $buildd = catdir($blddir, @curd); + + my $unixdir = join('/', @curd); + if (exists $skipdir{$unixdir}) { + my $what = $skipdir{$unixdir}; + push @{$disabled_info{$what}->{skipped}}, catdir(@curd); + next; + } mkpath($buildd); - my $f = $_->[1]; + my $f = 'build.info'; # The basic things we're trying to build my @programs = (); - my @programs_install = (); my @libraries = (); - my @libraries_install = (); - my @engines = (); - my @engines_install = (); + my @modules = (); my @scripts = (); - my @scripts_install = (); - my @extra = (); - my @overrides = (); - my @intermediates = (); - my @rawlines = (); my %sources = (); my %shared_sources = (); my %includes = (); + my %defines = (); my %depends = (); - my %renames = (); - my %sharednames = (); my %generate = (); + my %imagedocs = (); + my %htmldocs = (); + my %mandocs = (); + + # Support for $variablename in build.info files. + # Embedded perl code is the ultimate master, still. If its output + # contains a dollar sign, it had better be escaped, or it will be + # taken for a variable name prefix. + my %variables = (); + # Variable name syntax + my $variable_name_re = qr/(?P[[:alpha:]][[:alnum:]_]*)/; + # Value modifier syntaxes + my $variable_subst_re = qr/\/(?P(?:\\\/|.)*?)\/(?P.*?)/; + # Variable reference + my $variable_simple_re = qr/(?(?:\\\/|.)*?)\}/; + # Tie it all together + my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/; + + my $expand_variables = sub { + my $value = ''; + my $value_rest = shift; + + if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) { + print STDERR + "DEBUG[\$expand_variables] Parsed '$value_rest' ...\n" + } + + while ($value_rest =~ /${variable_re}/) { + # We must save important regexp values, because the next + # regexp clears them + my $mod = $+{MOD}; + my $variable_value = $variables{$+{VARIABLE}}; + + $value_rest = $'; + $value .= $`; + + # Process modifier expressions, if present + if (defined $mod) { + if ($mod =~ /^${variable_subst_re}$/) { + my $re = $+{RE}; + my $subst = $+{SUBST}; - # We want to detect configdata.pm in the source tree, so we - # don't use it if the build tree is different. - my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir); + $variable_value =~ s/\Q$re\E/$subst/g; + + if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) { + print STDERR + "DEBUG[\$expand_variables] ... and substituted ", + "'$re' with '$subst'\n"; + } + } + } + + $value .= $variable_value; + } + if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) { + print STDERR + "DEBUG[\$expand_variables] ... into: '$value$value_rest'\n"; + } + return $value . $value_rest; + }; + + # Support for attributes in build.info files + my %attributes = (); + my $handle_attributes = sub { + my $attr_str = shift; + my $ref = shift; + my @goals = @_; + + return unless defined $attr_str; + + my @a = tokenize($attr_str, qr|\s*,\s*|); + foreach my $a (@a) { + my $ac = 1; + my $ak = $a; + my $av = 1; + if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|x) { + $ac = ! $1; + $ak = $2; + $av = $3; + } + foreach my $g (@goals) { + if ($ac) { + $$ref->{$g}->{$ak} = $av; + } else { + delete $$ref->{$g}->{$ak}; + } + } + } + }; + + # Support for pushing values on multiple indexes of a given hash + # array. + my $push_to = sub { + my $valueref = shift; + my $index_str = shift; # May be undef or empty + my $attrref = shift; # May be undef + my $attr_str = shift; + my @values = @_; + + if (defined $index_str) { + my @indexes = ( '' ); + if ($index_str !~ m|^\s*$|) { + @indexes = tokenize($index_str); + } + foreach (@indexes) { + push @{$valueref->{$_}}, @values; + if (defined $attrref) { + $handle_attributes->($attr_str, \$$attrref->{$_}, + @values); + } + } + } else { + push @$valueref, @values; + $handle_attributes->($attr_str, $attrref, @values) + if defined $attrref; + } + }; + if ($buildinfo_debug) { + print STDERR "DEBUG: Reading ",catfile($sourced, $f),"\n"; + } push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f); my $template = Text::Template->new(TYPE => 'FILE', @@ -1831,117 +2096,118 @@ # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF) # 2 positive ELSE (following ELSIF should fail) my @skip = (); + + # A few useful generic regexps + my $index_re = qr/\[\s*(?P(?:\\.|.)*?)\s*\]/; + my $cond_re = qr/\[\s*(?P(?:\\.|.)*?)\s*\]/; + my $attribs_re = qr/(?:\{\s*(?P(?:\\.|.)*?)\s*\})?/; + my $value_re = qr/(?P.*?)/; collect_information( collect_from_array([ @text ], qr/\\$/ => sub { my $l1 = shift; my $l2 = shift; $l1 =~ s/\\$//; $l1.$l2 }), # Info we're looking for - qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/ + qr/^\s* IF ${cond_re} \s*$/x => sub { if (! @skip || $skip[$#skip] > 0) { - push @skip, !! $1; + push @skip, !! $expand_variables->($+{COND}); } else { push @skip, -1; } }, - qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/ + qr/^\s* ELSIF ${cond_re} \s*$/x => sub { die "ELSIF out of scope" if ! @skip; die "ELSIF following ELSE" if abs($skip[$#skip]) == 2; $skip[$#skip] = -1 if $skip[$#skip] != 0; - $skip[$#skip] = !! $1 + $skip[$#skip] = !! $expand_variables->($+{COND}) if $skip[$#skip] == 0; }, - qr/^\s*ELSE\s*$/ + qr/^\s* ELSE \s*$/x => sub { die "ELSE out of scope" if ! @skip; $skip[$#skip] = -2 if $skip[$#skip] != 0; $skip[$#skip] = 2 if $skip[$#skip] == 0; }, - qr/^\s*ENDIF\s*$/ + qr/^\s* ENDIF \s*$/x => sub { die "ENDIF out of scope" if ! @skip; pop @skip; }, - qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/ - => sub { - if (!@skip || $skip[$#skip] > 0) { - my $install = $1; - my @x = tokenize($2); - push @programs, @x; - push @programs_install, @x unless $install; - } - }, - qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/ + qr/^\s* ${variable_re} \s* = \s* ${value_re} \s* $/x => sub { if (!@skip || $skip[$#skip] > 0) { - my $install = $1; - my @x = tokenize($2); - push @libraries, @x; - push @libraries_install, @x unless $install; + $variables{$+{VARIABLE}} = $expand_variables->($+{VALUE}); } }, - qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/ + qr/^\s* SUBDIRS \s* = \s* ${value_re} \s* $/x => sub { if (!@skip || $skip[$#skip] > 0) { - my $install = $1; - my @x = tokenize($2); - push @engines, @x; - push @engines_install, @x unless $install; - } - }, - qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/ - => sub { - if (!@skip || $skip[$#skip] > 0) { - my $install = $1; - my @x = tokenize($2); - push @scripts, @x; - push @scripts_install, @x unless $install; - } - }, - qr/^\s*EXTRA\s*=\s*(.*)\s*$/ - => sub { push @extra, tokenize($1) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/ - => sub { push @overrides, tokenize($1) - if !@skip || $skip[$#skip] > 0 }, - - qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/, - => sub { push @{$ordinals{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$sources{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$shared_sources{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$includes{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/ - => sub { push @{$depends{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$generate{$1}}, $2 - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$renames{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$sharednames{$1}}, tokenize($2) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/ - => sub { - my $lineiterator = shift; - my $target_kind = $1; - while (defined $lineiterator->()) { - s|\R$||; - if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) { - die "ENDRAW doesn't match BEGINRAW" - if $1 ne $target_kind; - last; + foreach (tokenize($expand_variables->($+{VALUE}))) { + push @build_dirs, [ @curd, splitdir($_, 1) ]; } - next if @skip && $skip[$#skip] <= 0; - push @rawlines, $_ - if ($target_kind eq $config{build_file} - || $target_kind eq $config{build_file}."(".$builder_platform.")"); } }, - qr/^\s*(?:#.*)?$/ => sub { }, + qr/^\s* PROGRAMS ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\@programs, undef, + \$attributes{programs}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* LIBS ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\@libraries, undef, + \$attributes{libraries}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* MODULES ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\@modules, undef, + \$attributes{modules}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* SCRIPTS ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\@scripts, undef, + \$attributes{scripts}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* IMAGEDOCS ${index_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%imagedocs, $expand_variables->($+{INDEX}), + undef, undef, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* HTMLDOCS ${index_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%htmldocs, $expand_variables->($+{INDEX}), + undef, undef, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* MANDOCS ${index_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%mandocs, $expand_variables->($+{INDEX}), + undef, undef, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%sources, $expand_variables->($+{INDEX}), + \$attributes{sources}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* SHARED_SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%shared_sources, $expand_variables->($+{INDEX}), + \$attributes{sources}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* INCLUDE ${index_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%includes, $expand_variables->($+{INDEX}), + undef, undef, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* DEFINE ${index_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%defines, $expand_variables->($+{INDEX}), + undef, undef, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* DEPEND ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%depends, $expand_variables->($+{INDEX}), + \$attributes{depends}, $+{ATTRIBS}, + tokenize($expand_variables->($+{VALUE}))) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* GENERATE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x + => sub { $push_to->(\%generate, $expand_variables->($+{INDEX}), + \$attributes{generate}, $+{ATTRIBS}, + $expand_variables->($+{VALUE})) + if !@skip || $skip[$#skip] > 0; }, + qr/^\s* (?:\#.*)? $/x => sub { }, "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }, "BEFORE" => sub { if ($buildinfo_debug) { @@ -1957,269 +2223,200 @@ ); die "runaway IF?" if (@skip); - foreach (keys %renames) { - die "$_ renamed to more than one thing: " - ,join(" ", @{$renames{$_}}),"\n" - if scalar @{$renames{$_}} > 1; - my $dest = cleanfile($buildd, $_, $blddir); - my $to = cleanfile($buildd, $renames{$_}->[0], $blddir); - die "$dest renamed to more than one thing: " - ,$unified_info{rename}->{$dest}, $to - unless !defined($unified_info{rename}->{$dest}) - or $unified_info{rename}->{$dest} eq $to; - $unified_info{rename}->{$dest} = $to; - } - - foreach (@programs) { - my $program = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$program}) { - $program = $unified_info{rename}->{$program}; - } - $unified_info{programs}->{$program} = 1; - } - - foreach (@programs_install) { - my $program = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$program}) { - $program = $unified_info{rename}->{$program}; - } - $unified_info{install}->{programs}->{$program} = 1; - } - - foreach (@libraries) { - my $library = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$library}) { - $library = $unified_info{rename}->{$library}; - } - $unified_info{libraries}->{$library} = 1; - } - - foreach (@libraries_install) { - my $library = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$library}) { - $library = $unified_info{rename}->{$library}; - } - $unified_info{install}->{libraries}->{$library} = 1; - } - - die <<"EOF" if scalar @engines and !$config{dynamic_engines}; + if (grep { defined $attributes{modules}->{$_}->{engine} } keys %attributes + and !$config{dynamic_engines}) { + die <<"EOF" ENGINES can only be used if configured with 'dynamic-engine'. This is usually a fault in a build.info file. EOF - foreach (@engines) { - my $library = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$library}) { - $library = $unified_info{rename}->{$library}; - } - $unified_info{engines}->{$library} = 1; } - foreach (@engines_install) { - my $library = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$library}) { - $library = $unified_info{rename}->{$library}; - } - $unified_info{install}->{engines}->{$library} = 1; - } - - foreach (@scripts) { - my $script = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$script}) { - $script = $unified_info{rename}->{$script}; - } - $unified_info{scripts}->{$script} = 1; - } - - foreach (@scripts_install) { - my $script = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$script}) { - $script = $unified_info{rename}->{$script}; - } - $unified_info{install}->{scripts}->{$script} = 1; - } - - foreach (@extra) { - my $extra = cleanfile($buildd, $_, $blddir); - $unified_info{extra}->{$extra} = 1; - } - - foreach (@overrides) { - my $override = cleanfile($buildd, $_, $blddir); - $unified_info{overrides}->{$override} = 1; - } - - push @{$unified_info{rawlines}}, @rawlines; - - unless ($disabled{shared}) { - # Check sharednames. - foreach (keys %sharednames) { - my $dest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$dest}) { - $dest = $unified_info{rename}->{$dest}; - } - die "shared_name for $dest with multiple values: " - ,join(" ", @{$sharednames{$_}}),"\n" - if scalar @{$sharednames{$_}} > 1; - my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir); - die "shared_name found for a library $dest that isn't defined\n" - unless $unified_info{libraries}->{$dest}; - die "shared_name for $dest with multiple values: " - ,$unified_info{sharednames}->{$dest}, ", ", $to - unless !defined($unified_info{sharednames}->{$dest}) - or $unified_info{sharednames}->{$dest} eq $to; - $unified_info{sharednames}->{$dest} = $to; - } - - # Additionally, we set up sharednames for libraries that don't - # have any, as themselves. Only for libraries that aren't - # explicitly static. - foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) { - if (!defined $unified_info{sharednames}->{$_}) { - $unified_info{sharednames}->{$_} = $_ + { + my %infos = ( programs => [ @programs ], + libraries => [ @libraries ], + modules => [ @modules ], + scripts => [ @scripts ] ); + foreach my $k (keys %infos) { + foreach (@{$infos{$k}}) { + my $item = cleanfile($buildd, $_, $blddir); + $unified_info{$k}->{$item} = 1; + + # Fix up associated attributes + $unified_info{attributes}->{$k}->{$item} = + $attributes{$k}->{$_} + if defined $attributes{$k}->{$_}; } } + } - # Check that we haven't defined any library as both shared and - # explicitly static. That is forbidden. - my @doubles = (); - foreach (grep /\.a$/, keys %{$unified_info{libraries}}) { - (my $l = $_) =~ s/\.a$//; - push @doubles, $l if defined $unified_info{sharednames}->{$l}; - } - die "these libraries are both explicitly static and shared:\n ", - join(" ", @doubles), "\n" - if @doubles; + # Check that we haven't defined any library as both shared and + # explicitly static. That is forbidden. + my @doubles = (); + foreach (grep /\.a$/, keys %{$unified_info{libraries}}) { + (my $l = $_) =~ s/\.a$//; + push @doubles, $l if defined $unified_info{libraries}->{$l}; } + die "these libraries are both explicitly static and shared:\n ", + join(" ", @doubles), "\n" + if @doubles; foreach (keys %sources) { my $dest = $_; my $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; - } foreach (@{$sources{$dest}}) { my $s = cleanfile($sourced, $_, $blddir); - # If it isn't in the source tree, we assume it's generated - # in the build tree - if ($s eq $src_configdata || ! -f $s || $generate{$_}) { + # If it's generated or we simply don't find it in the source + # tree, we assume it's in the build tree. + if ($s eq $src_configdata || $generate{$_} || ! -f $s) { $s = cleanfile($buildd, $_, $blddir); } + my $o = $_; # We recognise C++, C and asm files if ($s =~ /\.(cc|cpp|c|s|S)$/) { - my $o = $_; + push @{$check_exist{$s}}, $ddest; $o =~ s/\.[csS]$/.o/; # C and assembler $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ $o = cleanfile($buildd, $o, $blddir); - $unified_info{sources}->{$ddest}->{$o} = 1; - $unified_info{sources}->{$o}->{$s} = 1; + $unified_info{sources}->{$ddest}->{$o} = -1; + $unified_info{sources}->{$o}->{$s} = -1; } elsif ($s =~ /\.rc$/) { # We also recognise resource files - my $o = $_; + push @{$check_exist{$s}}, $ddest; $o =~ s/\.rc$/.res/; # Resource configuration - my $o = cleanfile($buildd, $o, $blddir); - $unified_info{sources}->{$ddest}->{$o} = 1; - $unified_info{sources}->{$o}->{$s} = 1; + $o = cleanfile($buildd, $o, $blddir); + $unified_info{sources}->{$ddest}->{$o} = -1; + $unified_info{sources}->{$o}->{$s} = -1; } else { + push @{$check_exist{$s}}, $ddest; $unified_info{sources}->{$ddest}->{$s} = 1; } + # Fix up associated attributes + if ($o ne $_) { + $unified_info{attributes}->{sources}->{$ddest}->{$o} = + $unified_info{attributes}->{sources}->{$o}->{$s} = + $attributes{sources}->{$dest}->{$_} + if defined $attributes{sources}->{$dest}->{$_}; + } else { + $unified_info{attributes}->{sources}->{$ddest}->{$s} = + $attributes{sources}->{$dest}->{$_} + if defined $attributes{sources}->{$dest}->{$_}; + } } } foreach (keys %shared_sources) { my $dest = $_; my $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; - } foreach (@{$shared_sources{$dest}}) { my $s = cleanfile($sourced, $_, $blddir); - # If it isn't in the source tree, we assume it's generated - # in the build tree - if ($s eq $src_configdata || ! -f $s || $generate{$_}) { + # If it's generated or we simply don't find it in the source + # tree, we assume it's in the build tree. + if ($s eq $src_configdata || $generate{$_} || ! -f $s) { $s = cleanfile($buildd, $_, $blddir); } + my $o = $_; if ($s =~ /\.(cc|cpp|c|s|S)$/) { # We recognise C++, C and asm files - my $o = $_; + push @{$check_exist{$s}}, $ddest; $o =~ s/\.[csS]$/.o/; # C and assembler $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ $o = cleanfile($buildd, $o, $blddir); - $unified_info{shared_sources}->{$ddest}->{$o} = 1; - $unified_info{sources}->{$o}->{$s} = 1; + $unified_info{shared_sources}->{$ddest}->{$o} = -1; + $unified_info{sources}->{$o}->{$s} = -1; } elsif ($s =~ /\.rc$/) { # We also recognise resource files - my $o = $_; + push @{$check_exist{$s}}, $ddest; $o =~ s/\.rc$/.res/; # Resource configuration - my $o = cleanfile($buildd, $o, $blddir); - $unified_info{shared_sources}->{$ddest}->{$o} = 1; - $unified_info{sources}->{$o}->{$s} = 1; - } elsif ($s =~ /\.(def|map|opt)$/) { - # We also recognise .def / .map / .opt files + $o = cleanfile($buildd, $o, $blddir); + $unified_info{shared_sources}->{$ddest}->{$o} = -1; + $unified_info{sources}->{$o}->{$s} = -1; + } elsif ($s =~ /\.ld$/) { + # We also recognise linker scripts (or corresponding) # We know they are generated files - my $def = cleanfile($buildd, $s, $blddir); - $unified_info{shared_sources}->{$ddest}->{$def} = 1; + push @{$check_exist{$s}}, $ddest; + $o = cleanfile($buildd, $_, $blddir); + $unified_info{shared_sources}->{$ddest}->{$o} = 1; } else { die "unrecognised source file type for shared library: $s\n"; } + # Fix up associated attributes + if ($o ne $_) { + $unified_info{attributes}->{shared_sources}->{$ddest}->{$o} = + $unified_info{attributes}->{sources}->{$o}->{$s} = + $attributes{sources}->{$dest}->{$_} + if defined $attributes{sources}->{$dest}->{$_}; + } else { + $unified_info{attributes}->{shared_sources}->{$ddest}->{$o} = + $attributes{sources}->{$dest}->{$_} + if defined $attributes{sources}->{$dest}->{$_}; + } } } foreach (keys %generate) { my $dest = $_; my $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; - } die "more than one generator for $dest: " - ,join(" ", @{$generate{$_}}),"\n" - if scalar @{$generate{$_}} > 1; + ,join(" ", @{$generate{$_}}),"\n" + if scalar @{$generate{$_}} > 1; my @generator = split /\s+/, $generate{$dest}->[0]; - $generator[0] = cleanfile($sourced, $generator[0], $blddir), + my $gen = $generator[0]; + $generator[0] = cleanfile($sourced, $gen, $blddir); + + # If the generator is itself generated, it's in the build tree + if ($generate{$gen} || ! -f $generator[0]) { + $generator[0] = cleanfile($buildd, $gen, $blddir); + } + $check_generate{$ddest}->{$generator[0]}++; + $unified_info{generate}->{$ddest} = [ @generator ]; + # Fix up associated attributes + $unified_info{attributes}->{generate}->{$ddest} = + $attributes{generate}->{$dest}->{$gen} + if defined $attributes{generate}->{$dest}->{$gen}; } foreach (keys %depends) { my $dest = $_; - my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir); + my $ddest = $dest; + + if ($dest =~ /^\|(.*)\|$/) { + # Collect the raw target + $unified_info{targets}->{$1} = 1; + $ddest = $1; + } elsif ($dest eq '') { + $ddest = ''; + } else { + $ddest = cleanfile($sourced, $_, $blddir); - # If the destination doesn't exist in source, it can only be - # a generated file in the build tree. - if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) { - $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; + # If the destination doesn't exist in source, it can only be + # a generated file in the build tree. + if ($ddest eq $src_configdata || ! -f $ddest) { + $ddest = cleanfile($buildd, $_, $blddir); } } foreach (@{$depends{$dest}}) { my $d = cleanfile($sourced, $_, $blddir); + my $d2 = cleanfile($buildd, $_, $blddir); # If we know it's generated, or assume it is because we can't # find it in the source tree, we set file we depend on to be - # in the build tree rather than the source tree, and assume - # and that there are lines to build it in a BEGINRAW..ENDRAW - # section or in the Makefile template. + # in the build tree rather than the source tree. if ($d eq $src_configdata - || ! -f $d - || (grep { $d eq $_ } - map { cleanfile($srcdir, $_, $blddir) } - grep { /\.h$/ } keys %{$unified_info{generate}})) { - $d = cleanfile($buildd, $_, $blddir); - } - # Take note if the file to depend on is being renamed - # Take extra care with files ending with .a, they should - # be treated without that extension, and the extension - # should be added back after treatment. - $d =~ /(\.a)?$/; - my $e = $1 // ""; - $d = $`; - if ($unified_info{rename}->{$d}) { - $d = $unified_info{rename}->{$d}; + || (grep { $d2 eq $_ } + keys %{$unified_info{generate}}) + || ! -f $d) { + $d = $d2; } - $d .= $e; $unified_info{depends}->{$ddest}->{$d} = 1; + + # Fix up associated attributes + $unified_info{attributes}->{depends}->{$ddest}->{$d} = + $attributes{depends}->{$dest}->{$_} + if defined $attributes{depends}->{$dest}->{$_}; } } @@ -2231,9 +2428,6 @@ # a generated file in the build tree. if ($ddest eq $src_configdata || ! -f $ddest) { $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; - } } foreach (@{$includes{$dest}}) { my $is = cleandir($sourced, $_, $blddir); @@ -2244,6 +2438,54 @@ unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}}; } } + + foreach my $dest (keys %defines) { + my $ddest; + + if ($dest ne "") { + $ddest = cleanfile($sourced, $dest, $blddir); + + # If the destination doesn't exist in source, it can only + # be a generated file in the build tree. + if (! -f $ddest) { + $ddest = cleanfile($buildd, $dest, $blddir); + } + } + foreach my $v (@{$defines{$dest}}) { + $v =~ m|^([^=]*)(=.*)?$|; + die "0 length macro name not permitted\n" if $1 eq ""; + if ($dest ne "") { + die "$1 defined more than once\n" + if defined $unified_info{defines}->{$ddest}->{$1}; + $unified_info{defines}->{$ddest}->{$1} = $2; + } else { + die "$1 defined more than once\n" + if grep { $v eq $_ } @{$config{defines}}; + push @{$config{defines}}, $v; + } + } + } + + foreach my $section (keys %imagedocs) { + foreach (@{$imagedocs{$section}}) { + my $imagedocs = cleanfile($buildd, $_, $blddir); + $unified_info{imagedocs}->{$section}->{$imagedocs} = 1; + } + } + + foreach my $section (keys %htmldocs) { + foreach (@{$htmldocs{$section}}) { + my $htmldocs = cleanfile($buildd, $_, $blddir); + $unified_info{htmldocs}->{$section}->{$htmldocs} = 1; + } + } + + foreach my $section (keys %mandocs) { + foreach (@{$mandocs{$section}}) { + my $mandocs = cleanfile($buildd, $_, $blddir); + $unified_info{mandocs}->{$section}->{$mandocs} = 1; + } + } } my $ordinals_text = join(', ', sort keys %ordinals); @@ -2254,18 +2496,90 @@ DEPEND and SHARED_SOURCE. EOF - # Massage the result + # Check that each generated file is only generated once + my $ambiguous_generation = 0; + foreach (sort keys %check_generate) { + my @generators = sort keys %{$check_generate{$_}}; + my $generators_txt = join(', ', @generators); + if (scalar @generators > 1) { + warn "$_ is GENERATEd by more than one generator ($generators_txt)\n"; + $ambiguous_generation++; + } + if ($check_generate{$_}->{$generators[0]} > 1) { + warn "INFO: $_ has more than one GENERATE declaration (same generator)\n" + } + } + die "There are ambiguous source file generations\n" + if $ambiguous_generation > 0; + + # All given source files should exist, or if generated, their + # generator should exist. This loop ensures this is true. + my $missing = 0; + foreach my $orig (sort keys %check_exist) { + foreach my $dest (@{$check_exist{$orig}}) { + if ($orig ne $src_configdata) { + if ($orig =~ /\.a$/) { + # Static library names may be used as sources, so we + # need to detect those and give them special treatment. + unless (grep { $_ eq $orig } + keys %{$unified_info{libraries}}) { + warn "$orig is given as source for $dest, but no such library is built\n"; + $missing++; + } + } else { + # A source may be generated, and its generator may be + # generated as well. We therefore loop to dig out the + # first generator. + my $gen = $orig; + + while (my @next = keys %{$check_generate{$gen}}) { + $gen = $next[0]; + } + + if (! -f $gen) { + if ($gen ne $orig) { + $missing++; + warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n"; + } else { + $missing++; + warn "$orig is given as source for $dest, but is missing\n"; + } + } + } + } + } + } + die "There are files missing\n" if $missing > 0; + + # Go through the sources of all libraries and check that the same basename + # doesn't appear more than once. Some static library archivers depend on + # them being unique. + { + my $err = 0; + foreach my $prod (keys %{$unified_info{libraries}}) { + my @prod_sources = + map { keys %{$unified_info{sources}->{$_}} } + keys %{$unified_info{sources}->{$prod}}; + my %srccnt = (); + + # Count how many times a given each source basename + # appears for each product. + foreach my $src (@prod_sources) { + $srccnt{basename $src}++; + } - # If the user configured no-shared, we allow no shared sources - if ($disabled{shared}) { - foreach (keys %{$unified_info{shared_sources}}) { - foreach (keys %{$unified_info{shared_sources}->{$_}}) { - delete $unified_info{sources}->{$_}; + foreach my $src (keys %srccnt) { + if ((my $cnt = $srccnt{$src}) > 1) { + print STDERR "$src appears $cnt times for the product $prod\n"; + $err++ + } } } - $unified_info{shared_sources} = {}; + die if $err > 0; } + # Massage the result + # If we depend on a header file or a perl module, add an inclusion of # its directory to allow smoothe inclusion foreach my $dest (keys %{$unified_info{depends}}) { @@ -2281,38 +2595,144 @@ } } - # Trickle down includes placed on libraries, engines and programs to - # their sources (i.e. object files) - foreach my $dest (keys %{$unified_info{engines}}, - keys %{$unified_info{libraries}}, - keys %{$unified_info{programs}}) { - foreach my $k (("source", "build")) { - next unless defined($unified_info{includes}->{$dest}->{$k}); - my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}}; - foreach my $obj (grep /\.o$/, - (keys %{$unified_info{sources}->{$dest} // {}}, - keys %{$unified_info{shared_sources}->{$dest} // {}})) { - foreach my $inc (@incs) { - unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc - unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}}; + # Go through all intermediary files and change their names to something that + # reflects what they will be built for. Note that for some source files, + # this leads to duplicate object files because they are used multiple times. + # the goal is to rename all object files according to this scheme: + # {productname}-{midfix}-{origobjname}.[o|res] + # the {midfix} is a keyword indicating the type of product, which is mostly + # valuable for libraries since they come in two forms. + # + # This also reorganises the {sources} and {shared_sources} so that the + # former only contains ALL object files that are supposed to end up in + # static libraries and programs, while the latter contains ALL object files + # that are supposed to end up in shared libraries and DSOs. + # The main reason for having two different source structures is to allow + # the same name to be used for the static and the shared variants of a + # library. + { + # Take copies so we don't get interference from added stuff + my %unified_copy = (); + foreach (('sources', 'shared_sources')) { + $unified_copy{$_} = { %{$unified_info{$_}} } + if defined($unified_info{$_}); + delete $unified_info{$_}; + } + foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) { + # $intent serves multi purposes: + # - give a prefix for the new object files names + # - in the case of libraries, rearrange the object files so static + # libraries use the 'sources' structure exclusively, while shared + # libraries use the 'shared_sources' structure exclusively. + my $intent = { + programs => { bin => { src => [ 'sources' ], + dst => 'sources' } }, + libraries => { lib => { src => [ 'sources' ], + dst => 'sources' }, + shlib => { prodselect => + sub { grep !/\.a$/, @_ }, + src => [ 'sources', + 'shared_sources' ], + dst => 'shared_sources' } }, + modules => { dso => { src => [ 'sources' ], + dst => 'sources' } }, + scripts => { script => { src => [ 'sources' ], + dst => 'sources' } } + } -> {$prodtype}; + foreach my $kind (keys %$intent) { + next if ($intent->{$kind}->{dst} eq 'shared_sources' + && $disabled{shared}); + + my @src = @{$intent->{$kind}->{src}}; + my $dst = $intent->{$kind}->{dst}; + my $prodselect = $intent->{$kind}->{prodselect} // sub { @_ }; + foreach my $prod ($prodselect->(keys %{$unified_info{$prodtype}})) { + # %prod_sources has all applicable objects as keys, and + # their corresponding sources as values + my %prod_sources = + map { $_ => [ keys %{$unified_copy{sources}->{$_}} ] } + map { keys %{$unified_copy{$_}->{$prod}} } + @src; + foreach (keys %prod_sources) { + # Only affect object files and resource files, + # the others simply get a new value + # (+1 instead of -1) + if ($_ =~ /\.(o|res)$/) { + (my $prodname = $prod) =~ s|\.a$||; + my $newobj = + catfile(dirname($_), + basename($prodname) + . '-' . $kind + . '-' . basename($_)); + $unified_info{$dst}->{$prod}->{$newobj} = 1; + foreach my $src (@{$prod_sources{$_}}) { + $unified_info{sources}->{$newobj}->{$src} = 1; + # Adjust source attributes + my $attrs = $unified_info{attributes}->{sources}; + if (defined $attrs->{$prod} + && defined $attrs->{$prod}->{$_}) { + $attrs->{$prod}->{$newobj} = + $attrs->{$prod}->{$_}; + delete $attrs->{$prod}->{$_}; + } + foreach my $objsrc (keys %{$attrs->{$_} // {}}) { + $attrs->{$newobj}->{$objsrc} = + $attrs->{$_}->{$objsrc}; + delete $attrs->{$_}->{$objsrc}; + } + } + # Adjust dependencies + foreach my $deps (keys %{$unified_info{depends}->{$_}}) { + $unified_info{depends}->{$_}->{$deps} = -1; + $unified_info{depends}->{$newobj}->{$deps} = 1; + } + # Adjust includes + foreach my $k (('source', 'build')) { + next unless + defined($unified_info{includes}->{$_}->{$k}); + my @incs = @{$unified_info{includes}->{$_}->{$k}}; + $unified_info{includes}->{$newobj}->{$k} = [ @incs ]; + } + } else { + $unified_info{$dst}->{$prod}->{$_} = 1; + } + } } } } - delete $unified_info{includes}->{$dest}; } + # At this point, we have a number of sources with the value -1. They + # aren't part of the local build and are probably meant for a different + # platform, and can therefore be cleaned away. That happens when making + # %unified_info more efficient below. + ### Make unified_info a bit more efficient # One level structures - foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) { + foreach (("programs", "libraries", "modules", "scripts", "targets")) { $unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; } # Two level structures - foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) { + foreach my $l1 (("sources", "shared_sources", "ldadd", "depends", + "imagedocs", "htmldocs", "mandocs")) { foreach my $l2 (sort keys %{$unified_info{$l1}}) { - $unified_info{$l1}->{$l2} = - [ sort keys %{$unified_info{$l1}->{$l2}} ]; + my @items = + sort + grep { $unified_info{$l1}->{$l2}->{$_} > 0 } + keys %{$unified_info{$l1}->{$l2}}; + if (@items) { + $unified_info{$l1}->{$l2} = [ @items ]; + } else { + delete $unified_info{$l1}->{$l2}; + } } } + # Defines + foreach my $dest (sort keys %{$unified_info{defines}}) { + $unified_info{defines}->{$dest} + = [ map { $_.$unified_info{defines}->{$dest}->{$_} } + sort keys %{$unified_info{defines}->{$dest}} ]; + } # Includes foreach my $dest (sort keys %{$unified_info{includes}}) { if (defined($unified_info{includes}->{$dest}->{build})) { @@ -2325,9 +2745,11 @@ push @{$unified_info{includes}->{$dest}}, $inc unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}}; } - } else { + } elsif (defined($unified_info{includes}->{$dest}->{source})) { $unified_info{includes}->{$dest} = [ @{$unified_info{includes}->{$dest}->{source}} ]; + } else { + delete $unified_info{includes}->{$dest}; } } @@ -2336,10 +2758,16 @@ # they end up in where applicable. Then, add build rules for those # directories my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ], - "dso" => [ @{$unified_info{engines}} ], + "dso" => [ @{$unified_info{modules}} ], "bin" => [ @{$unified_info{programs}} ], - "script" => [ @{$unified_info{scripts}} ] ); - foreach my $type (keys %loopinfo) { + "script" => [ @{$unified_info{scripts}} ], + "docs" => [ (map { @{$unified_info{imagedocs}->{$_} // []} } + keys %{$unified_info{imagedocs} // {}}), + (map { @{$unified_info{htmldocs}->{$_} // []} } + keys %{$unified_info{htmldocs} // {}}), + (map { @{$unified_info{mandocs}->{$_} // []} } + keys %{$unified_info{mandocs} // {}}) ] ); + foreach my $type (sort keys %loopinfo) { foreach my $product (@{$loopinfo{$type}}) { my %dirs = (); my $pd = dirname($product); @@ -2360,7 +2788,7 @@ push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ if $d ne $pd; } - foreach (keys %dirs) { + foreach (sort keys %dirs) { push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, $product; } @@ -2380,446 +2808,51 @@ # Write down our configuration where it fits ######################### -print "Creating configdata.pm\n"; -open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n"; -print OUT <<"EOF"; -#! $config{HASHBANGPERL} - -package configdata; - -use strict; -use warnings; - -use Exporter; -#use vars qw(\@ISA \@EXPORT); -our \@ISA = qw(Exporter); -our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables); - -EOF -print OUT "our %config = (\n"; -foreach (sort keys %config) { - if (ref($config{$_}) eq "ARRAY") { - print OUT " ", $_, " => [ ", join(", ", - map { quotify("perl", $_) } - @{$config{$_}}), " ],\n"; - } elsif (ref($config{$_}) eq "HASH") { - print OUT " ", $_, " => {"; - if (scalar keys %{$config{$_}} > 0) { - print OUT "\n"; - foreach my $key (sort keys %{$config{$_}}) { - print OUT " ", - join(" => ", - quotify("perl", $key), - defined $config{$_}->{$key} - ? quotify("perl", $config{$_}->{$key}) - : "undef"); - print OUT ",\n"; - } - print OUT " "; - } - print OUT "},\n"; - } else { - print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n" - } -} -print OUT <<"EOF"; -); - -EOF -print OUT "our %target = (\n"; -foreach (sort keys %target) { - if (ref($target{$_}) eq "ARRAY") { - print OUT " ", $_, " => [ ", join(", ", - map { quotify("perl", $_) } - @{$target{$_}}), " ],\n"; - } else { - print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n" - } -} -print OUT <<"EOF"; -); - -EOF -print OUT "our \%available_protocols = (\n"; -print OUT " tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n"; -print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n"; -print OUT <<"EOF"; -); - -EOF -print OUT "our \@disablables = (\n"; -foreach (@disablables) { - print OUT " ", quotify("perl", $_), ",\n"; -} -print OUT <<"EOF"; -); - -EOF -print OUT "our \%disabled = (\n"; -foreach (sort keys %disabled) { - print OUT " ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n"; -} -print OUT <<"EOF"; -); - -EOF -print OUT "our %withargs = (\n"; -foreach (sort keys %withargs) { - if (ref($withargs{$_}) eq "ARRAY") { - print OUT " ", $_, " => [ ", join(", ", - map { quotify("perl", $_) } - @{$withargs{$_}}), " ],\n"; - } else { - print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n" - } -} -print OUT <<"EOF"; -); - -EOF -if ($builder eq "unified") { - my $recurse; - $recurse = sub { - my $indent = shift; - foreach (@_) { - if (ref $_ eq "ARRAY") { - print OUT " "x$indent, "[\n"; - foreach (@$_) { - $recurse->($indent + 4, $_); - } - print OUT " "x$indent, "],\n"; - } elsif (ref $_ eq "HASH") { - my %h = %$_; - print OUT " "x$indent, "{\n"; - foreach (sort keys %h) { - if (ref $h{$_} eq "") { - print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n"; - } else { - print OUT " "x($indent + 4), quotify("perl", $_), " =>\n"; - $recurse->($indent + 8, $h{$_}); - } - } - print OUT " "x$indent, "},\n"; - } else { - print OUT " "x$indent, quotify("perl", $_), ",\n"; - } - } - }; - print OUT "our %unified_info = (\n"; - foreach (sort keys %unified_info) { - if (ref $unified_info{$_} eq "") { - print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n"; - } else { - print OUT " "x4, quotify("perl", $_), " =>\n"; - $recurse->(8, $unified_info{$_}); - } - } - print OUT <<"EOF"; +my %template_vars = ( + config => \%config, + target => \%target, + disablables => \@disablables, + disablables_int => \@disablables_int, + disabled => \%disabled, + withargs => \%withargs, + unified_info => \%unified_info, + tls => \@tls, + dtls => \@dtls, + makevars => [ sort keys %user ], + disabled_info => \%disabled_info, + user_crossable => \@user_crossable, ); - -EOF -} -print OUT - "# The following data is only used when this files is use as a script\n"; -print OUT "my \@makevars = (\n"; -foreach (sort keys %user) { - print OUT " '",$_,"',\n"; -} -print OUT ");\n"; -print OUT "my \%disabled_info = (\n"; -foreach my $what (sort keys %disabled_info) { - print OUT " '$what' => {\n"; - foreach my $info (sort keys %{$disabled_info{$what}}) { - if (ref $disabled_info{$what}->{$info} eq 'ARRAY') { - print OUT " $info => [ ", - join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}), - " ],\n"; - } else { - print OUT " $info => '", $disabled_info{$what}->{$info}, - "',\n"; - } - } - print OUT " },\n"; -} -print OUT ");\n"; -print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n"; -print OUT << 'EOF'; -# If run directly, we can give some answers, and even reconfigure -unless (caller) { - use Getopt::Long; - use File::Spec::Functions; - use File::Basename; - use Pod::Usage; - - my $here = dirname($0); - - my $dump = undef; - my $cmdline = undef; - my $options = undef; - my $target = undef; - my $envvars = undef; - my $makevars = undef; - my $buildparams = undef; - my $reconf = undef; - my $verbose = undef; - my $help = undef; - my $man = undef; - GetOptions('dump|d' => \$dump, - 'command-line|c' => \$cmdline, - 'options|o' => \$options, - 'target|t' => \$target, - 'environment|e' => \$envvars, - 'make-variables|m' => \$makevars, - 'build-parameters|b' => \$buildparams, - 'reconfigure|reconf|r' => \$reconf, - 'verbose|v' => \$verbose, - 'help' => \$help, - 'man' => \$man) - or die "Errors in command line arguments\n"; - - unless ($dump || $cmdline || $options || $target || $envvars || $makevars - || $buildparams || $reconf || $verbose || $help || $man) { - print STDERR <<"_____"; -You must give at least one option. -For more information, do '$0 --help' -_____ - exit(2); - } - - if ($help) { - pod2usage(-exitval => 0, - -verbose => 1); - } - if ($man) { - pod2usage(-exitval => 0, - -verbose => 2); - } - if ($dump || $cmdline) { - print "\nCommand line (with current working directory = $here):\n\n"; - print ' ',join(' ', - $config{PERL}, - catfile($config{sourcedir}, 'Configure'), - @{$config{perlargv}}), "\n"; - print "\nPerl information:\n\n"; - print ' ',$config{perl_cmd},"\n"; - print ' ',$config{perl_version},' for ',$config{perl_archname},"\n"; - } - if ($dump || $options) { - my $longest = 0; - my $longest2 = 0; - foreach my $what (@disablables) { - $longest = length($what) if $longest < length($what); - $longest2 = length($disabled{$what}) - if $disabled{$what} && $longest2 < length($disabled{$what}); - } - print "\nEnabled features:\n\n"; - foreach my $what (@disablables) { - print " $what\n" - unless grep { $_ =~ /^${what}$/ } keys %disabled; - } - print "\nDisabled features:\n\n"; - foreach my $what (@disablables) { - my @what2 = grep { $_ =~ /^${what}$/ } keys %disabled; - my $what3 = $what2[0]; - if ($what3) { - print " $what3", ' ' x ($longest - length($what3) + 1), - "[$disabled{$what3}]", ' ' x ($longest2 - length($disabled{$what3}) + 1); - print $disabled_info{$what3}->{macro} - if $disabled_info{$what3}->{macro}; - print ' (skip ', - join(', ', @{$disabled_info{$what3}->{skipped}}), - ')' - if $disabled_info{$what3}->{skipped}; - print "\n"; - } - } - } - if ($dump || $target) { - print "\nConfig target attributes:\n\n"; - foreach (sort keys %target) { - next if $_ =~ m|^_| || $_ eq 'template'; - my $quotify = sub { - map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_; - }; - print ' ', $_, ' => '; - if (ref($target{$_}) eq "ARRAY") { - print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n"; - } else { - print $quotify->($target{$_}), ",\n" - } - } - } - if ($dump || $envvars) { - print "\nRecorded environment:\n\n"; - foreach (sort keys %{$config{perlenv}}) { - print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n"; - } - } - if ($dump || $makevars) { - print "\nMakevars:\n\n"; - foreach my $var (@makevars) { - my $prefix = ''; - $prefix = $config{CROSS_COMPILE} - if grep { $var eq $_ } @user_crossable; - $prefix //= ''; - print ' ',$var,' ' x (16 - length $var),'= ', - (ref $config{$var} eq 'ARRAY' - ? join(' ', @{$config{$var}}) - : $prefix.$config{$var}), - "\n" - if defined $config{$var}; - } - - my @buildfile = ($config{builddir}, $config{build_file}); - unshift @buildfile, $here - unless file_name_is_absolute($config{builddir}); - my $buildfile = canonpath(catdir(@buildfile)); - print <<"_____"; - -NOTE: These variables only represent the configuration view. The build file -template may have processed these variables further, please have a look at the -build file for more exact data: - $buildfile -_____ - } - if ($dump || $buildparams) { - my @buildfile = ($config{builddir}, $config{build_file}); - unshift @buildfile, $here - unless file_name_is_absolute($config{builddir}); - print "\nbuild file:\n\n"; - print " ", canonpath(catfile(@buildfile)),"\n"; - - print "\nbuild file templates:\n\n"; - foreach (@{$config{build_file_templates}}) { - my @tmpl = ($_); - unshift @tmpl, $here - unless file_name_is_absolute($config{sourcedir}); - print ' ',canonpath(catfile(@tmpl)),"\n"; - } - } - if ($reconf) { - if ($verbose) { - print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n"; - foreach (sort keys %{$config{perlenv}}) { - print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n"; - } - } - - chdir $here; - exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf'; - } -} - -1; - -__END__ - -=head1 NAME - -configdata.pm - configuration data for OpenSSL builds - -=head1 SYNOPSIS - -Interactive: - - perl configdata.pm [options] - -As data bank module: - - use configdata; - -=head1 DESCRIPTION - -This module can be used in two modes, interactively and as a module containing -all the data recorded by OpenSSL's Configure script. - -When used interactively, simply run it as any perl script, with at least one -option, and you will get the information you ask for. See L below. - -When loaded as a module, you get a few databanks with useful information to -perform build related tasks. The databanks are: - - %config Configured things. - %target The OpenSSL config target with all inheritances - resolved. - %disabled The features that are disabled. - @disablables The list of features that can be disabled. - %withargs All data given through --with-THING options. - %unified_info All information that was computed from the build.info - files. - -=head1 OPTIONS - -=over 4 - -=item B<--help> - -Print a brief help message and exit. - -=item B<--man> - -Print the manual page and exit. - -=item B<--dump> | B<-d> - -Print all relevant configuration data. This is equivalent to B<--command-line> -B<--options> B<--target> B<--environment> B<--make-variables> -B<--build-parameters>. - -=item B<--command-line> | B<-c> - -Print the current configuration command line. - -=item B<--options> | B<-o> - -Print the features, both enabled and disabled, and display defined macro and -skipped directories where applicable. - -=item B<--target> | B<-t> - -Print the config attributes for this config target. - -=item B<--environment> | B<-e> - -Print the environment variables and their values at the time of configuration. - -=item B<--make-variables> | B<-m> - -Print the main make variables generated in the current configuration - -=item B<--build-parameters> | B<-b> - -Print the build parameters, i.e. build file and build file templates. - -=item B<--reconfigure> | B<--reconf> | B<-r> - -Redo the configuration. - -=item B<--verbose> | B<-v> - -Verbose output. - -=back - -=cut - -EOF -close(OUT); +my $configdata_outname = 'configdata.pm'; +open CONFIGDATA, ">$configdata_outname.new" + or die "Trying to create $configdata_outname.new: $!"; +my $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir); +my $configdata_tmpl = + OpenSSL::Template->new(TYPE => 'FILE', SOURCE => $configdata_tmplname); +$configdata_tmpl->fill_in( + FILENAME => $configdata_tmplname, + OUTPUT => \*CONFIGDATA, + HASH => { %template_vars, + autowarntext => [ + 'WARNING: do not edit!', + "Generated by Configure from $configdata_tmplname", + ] } +) or die $Text::Template::ERROR; +close CONFIGDATA; + +rename "$configdata_outname.new", $configdata_outname; if ($builder_platform eq 'unix') { my $mode = (0755 & ~umask); chmod $mode, 'configdata.pm' or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!); } +print "Created $configdata_outname\n"; -my %builders = ( - unified => sub { - print 'Creating ',$config{build_file},"\n"; - run_dofile(catfile($blddir, $config{build_file}), - @{$config{build_file_templates}}); - }, - ); - -$builders{$builder}->($builder_platform, @builder_opts); +print "Running $configdata_outname\n"; +my $perlcmd = (quotify("maybeshell", $config{PERL}))[0]; +my $cmd = "$perlcmd $configdata_outname"; +#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; +system($cmd); +exit 1 if $? != 0; $SIG{__DIE__} = $orig_death_handler; @@ -2827,7 +2860,7 @@ The library could not be configured for supporting multi-threaded applications as the compiler options required on this system are not known. -See file INSTALL for details if you need multi-threading. +See file INSTALL.md for details if you need multi-threading. EOF print <<"EOF" if ($no_shared_warn); @@ -2839,23 +2872,7 @@ you have tried with a current version of OpenSSL). EOF -print <<"EOF"; - -********************************************************************** -*** *** -*** OpenSSL has been successfully configured *** -*** *** -*** If you encounter a problem while building, please open an *** -*** issue on GitHub *** -*** and include the output from the following command: *** -*** *** -*** perl configdata.pm --dump *** -*** *** -*** (If you are new to OpenSSL, you might want to consult the *** -*** 'Troubleshooting' section in the INSTALL file first) *** -*** *** -********************************************************************** -EOF +print $banner; exit(0); @@ -2872,8 +2889,8 @@ my @message = ( <<"_____", @_ ); Failure! $build_file wasn't produced. -Please read INSTALL and associated NOTES files. You may also have to look over -your available compiler tool chain or change your configuration. +Please read INSTALL.md and associated NOTES-* files. You may also have to +look over your available compiler tool chain or change your configuration. _____ @@ -2889,18 +2906,6 @@ # Thus, whenever there's mention of a returned value, it's about that # intended value. -# Helper function to implement conditional inheritance depending on the -# value of $disabled{asm}. Used in inherit_from values as follows: -# -# inherit_from => [ "template", asm("asm_tmpl") ] -# -sub asm { - my @x = @_; - sub { - $disabled{asm} ? () : @x; - } -} - # Helper function to implement conditional value variants, with a default # plus additional values based on the value of $config{build_type}. # Arguments are given in hash table form: @@ -3218,28 +3223,9 @@ } print STDERR $i . " "; } - print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n"; exit(1); } -sub run_dofile -{ - my $out = shift; - my @templates = @_; - - unlink $out || warn "Can't remove $out, $!" - if -f $out; - foreach (@templates) { - die "Can't open $_, $!" unless -f $_; - } - my $perlcmd = (quotify("maybeshell", $config{PERL}))[0]; - my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\""; - #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; - system($cmd); - exit 1 if $? != 0; - rename("$out.new", $out) || die "Can't rename $out.new, $!"; -} - sub compiler_predefined { state %predefined; my $cc = shift; @@ -3321,31 +3307,13 @@ "includes", "cc", "cflags", - "unistd", "ld", "lflags", "loutflag", "ex_libs", "bn_ops", - "apps_aux_src", - "cpuid_asm_src", - "uplink_aux_src", - "bn_asm_src", - "ec_asm_src", - "des_asm_src", - "aes_asm_src", - "bf_asm_src", - "md5_asm_src", - "cast_asm_src", - "sha1_asm_src", - "rc4_asm_src", - "rmd160_asm_src", - "rc5_asm_src", - "wp_asm_src", - "cmll_asm_src", - "modes_asm_src", - "padlock_asm_src", - "chacha_asm_src", + "enable", + "disable", "poly1035_asm_src", "thread_scheme", "perlasm_scheme", @@ -3577,32 +3545,43 @@ } # tokenize($line) +# tokenize($line,$separator) # $line is a line of text to split up into tokens -# returns a list of tokens +# $separator [optional] is a regular expression that separates the tokens, +# the default being spaces. Do not use quotes of any kind as separators, +# that will give undefined results. +# Returns a list of tokens. # -# Tokens are divided by spaces. If the tokens include spaces, they -# have to be quoted with single or double quotes. Double quotes -# inside a double quoted token must be escaped. Escaping is done +# Tokens are divided by separator (spaces by default). If the tokens include +# the separators, they have to be quoted with single or double quotes. +# Double quotes inside a double quoted token must be escaped. Escaping is done # with backslash. # Basically, the same quoting rules apply for " and ' as in any # Unix shell. sub tokenize { my $line = my $debug_line = shift; + my $separator = shift // qr|\s+|; my @result = (); - while ($line =~ s|^\s+||, $line ne "") { + if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) { + print STDERR "DEBUG[tokenize]: \$separator = $separator\n"; + } + + while ($line =~ s|^${separator}||, $line ne "") { my $token = ""; - while ($line ne "" && $line !~ m|^\s|) { - if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) { - $token .= $1; - $line = $'; - } elsif ($line =~ m/^'([^']*)'/) { - $token .= $1; - $line = $'; - } elsif ($line =~ m/^(\S+)/) { - $token .= $1; - $line = $'; - } + again: + $line =~ m/^(.*?)(${separator}|"|'|$)/; + $token .= $1; + $line = $2.$'; + + if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) { + $token .= $1; + $line = $'; + goto again; + } elsif ($line =~ m/^'([^']*)'/) { + $token .= $1; + $line = $'; + goto again; } push @result, $token; } diff --git a/FAQ b/FAQ deleted file mode 100644 --- a/FAQ +++ /dev/null @@ -1,2 +0,0 @@ -The FAQ is now maintained on the web: - https://www.openssl.org/docs/faq.html diff --git a/FAQ.md b/FAQ.md new file mode 100644 --- /dev/null +++ b/FAQ.md @@ -0,0 +1,6 @@ +Frequently Asked Questions (FAQ) +================================ + +The [Frequently Asked Questions][FAQ] are now maintained on the OpenSSL homepage. + + [FAQ]: https://www.openssl.org/docs/faq.html diff --git a/HACKING.md b/HACKING.md new file mode 100644 --- /dev/null +++ b/HACKING.md @@ -0,0 +1,33 @@ +MODIFYING OPENSSL SOURCE +======================== + +This document describes the way to add custom modifications to OpenSSL sources. + + If you are adding new public functions to the custom library build, you need to + either add a prototype in one of the existing OpenSSL header files; + or provide a new header file and edit + [Configurations/unix-Makefile.tmpl](Configurations/unix-Makefile.tmpl) + to pick up that file. + + After that perform the following steps: + + ./Configure -Werror --strict-warnings [your-options] + make update + make + make test + + `make update` ensures that your functions declarations are added to + `util/libcrypto.num` or `util/libssl.num`. + If you plan to submit the changes you made to OpenSSL + (see [CONTRIBUTING.md](CONTRIBUTING.md)), it's worth running: + + make doc-nits + + after running `make update` to ensure that documentation has correct format. + + `make update` also generates files related to OIDs (in the `crypto/objects/` + folder) and errors. + If a merge error occurs in one of these generated files then the + generated files need to be removed and regenerated using `make update`. + To aid in this process the generated files can be committed separately + so they can be removed easily. diff --git a/INSTALL b/INSTALL deleted file mode 100644 --- a/INSTALL +++ /dev/null @@ -1,1289 +0,0 @@ - OPENSSL INSTALLATION - -------------------- - - This document describes installation on all supported operating - systems (the Unix/Linux family (which includes Mac OS/X), OpenVMS, - and Windows). - - To install OpenSSL, you will need: - - * A make implementation - * Perl 5 with core modules (please read NOTES.PERL) - * The perl module Text::Template (please read NOTES.PERL) - * an ANSI C compiler - * a development environment in the form of development libraries and C - header files - * a supported operating system - - For additional platform specific requirements, solutions to specific - issues and other details, please read one of these: - - * NOTES.UNIX (any supported Unix like system) - * NOTES.VMS (OpenVMS) - * NOTES.WIN (any supported Windows) - * NOTES.DJGPP (DOS platform with DJGPP) - * NOTES.ANDROID (obviously Android [NDK]) - - Notational conventions in this document - --------------------------------------- - - Throughout this document, we use the following conventions in command - examples: - - $ command Any line starting with a dollar sign - ($) is a command line. - - { word1 | word2 | word3 } This denotes a mandatory choice, to be - replaced with one of the given words. - A simple example would be this: - - $ echo { FOO | BAR | COOKIE } - - which is to be understood as one of - these: - - $ echo FOO - - or - - $ echo BAR - - or - - $ echo COOKIE - - [ word1 | word2 | word3 ] Similar to { word1 | word2 | word3 } - except it's optional to give any of - those. In addition to the examples - above, this would also be valid: - - $ echo - - {{ target }} This denotes a mandatory word or - sequence of words of some sort. A - simple example would be this: - - $ type {{ filename }} - - which is to be understood to use the - command 'type' on some file name - determined by the user. - - [[ options ]] Similar to {{ target }}, but is - optional. - - Note that the notation assumes spaces around {, }, [, ], {{, }} and - [[, ]]. This is to differentiate from OpenVMS directory - specifications, which also use [ and ], but without spaces. - - Quick Start - ----------- - - If you want to just get on with it, do: - - on Unix (again, this includes Mac OS/X): - - $ ./config - $ make - $ make test - $ make install - - on OpenVMS: - - $ @config - $ mms - $ mms test - $ mms install - - on Windows (only pick one of the targets for configuration): - - $ perl Configure { VC-WIN32 | VC-WIN64A | VC-WIN64I | VC-CE } - $ nmake - $ nmake test - $ nmake install - - Note that in order to perform the install step above you need to have - appropriate permissions to write to the installation directory. - - If any of these steps fails, see section Installation in Detail below. - - This will build and install OpenSSL in the default location, which is: - - Unix: normal installation directories under /usr/local - OpenVMS: SYS$COMMON:[OPENSSL] - Windows: C:\Program Files\OpenSSL or C:\Program Files (x86)\OpenSSL - - The installation directory should be appropriately protected to ensure - unprivileged users cannot make changes to OpenSSL binaries or files, or install - engines. If you already have a pre-installed version of OpenSSL as part of - your Operating System it is recommended that you do not overwrite the system - version and instead install to somewhere else. - - If you want to install it anywhere else, run config like this (the options - --prefix and --openssldir are explained further down, and the values shown - here are mere examples): - - On Unix: - - $ ./config --prefix=/opt/openssl --openssldir=/usr/local/ssl - - On OpenVMS: - - $ @config --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL] - - (Note: if you do add options to the configuration command, please make sure - you've read more than just this Quick Start, such as relevant NOTES.* files, - the options outline below, as configuration options may change the outcome - in otherwise unexpected ways) - - - Configuration Options - --------------------- - - There are several options to ./config (or ./Configure) to customize - the build (note that for Windows, the defaults for --prefix and - --openssldir depend in what configuration is used and what Windows - implementation OpenSSL is built on. More notes on this in NOTES.WIN): - - --api=x.y.z - Don't build with support for deprecated APIs below the - specified version number. For example "--api=1.1.0" will - remove support for all APIS that were deprecated in OpenSSL - version 1.1.0 or below. This is a rather specialized option - for developers. If you just intend to remove all deprecated - APIs entirely (up to the current version), it is easier - to add the 'no-deprecated' option instead (see below). - - --cross-compile-prefix=PREFIX - The PREFIX to include in front of commands for your - toolchain. It's likely to have to end with dash, e.g. - a-b-c- would invoke GNU compiler as a-b-c-gcc, etc. - Unfortunately cross-compiling is too case-specific to - put together one-size-fits-all instructions. You might - have to pass more flags or set up environment variables - to actually make it work. Android and iOS cases are - discussed in corresponding Configurations/15-*.conf - files. But there are cases when this option alone is - sufficient. For example to build the mingw64 target on - Linux "--cross-compile-prefix=x86_64-w64-mingw32-" - works. Naturally provided that mingw packages are - installed. Today Debian and Ubuntu users have option to - install a number of prepackaged cross-compilers along - with corresponding run-time and development packages for - "alien" hardware. To give another example - "--cross-compile-prefix=mipsel-linux-gnu-" suffices - in such case. Needless to mention that you have to - invoke ./Configure, not ./config, and pass your target - name explicitly. Also, note that --openssldir refers - to target's file system, not one you are building on. - - --debug - Build OpenSSL with debugging symbols and zero optimization - level. - - --libdir=DIR - The name of the directory under the top of the installation - directory tree (see the --prefix option) where libraries will - be installed. By default this is "lib". Note that on Windows - only ".lib" files will be stored in this location. dll files - will always be installed to the "bin" directory. - - --openssldir=DIR - Directory for OpenSSL configuration files, and also the - default certificate and key store. Defaults are: - - Unix: /usr/local/ssl - Windows: C:\Program Files\Common Files\SSL - or C:\Program Files (x86)\Common Files\SSL - OpenVMS: SYS$COMMON:[OPENSSL-COMMON] - - --prefix=DIR - The top of the installation directory tree. Defaults are: - - Unix: /usr/local - Windows: C:\Program Files\OpenSSL - or C:\Program Files (x86)\OpenSSL - OpenVMS: SYS$COMMON:[OPENSSL] - - --release - Build OpenSSL without debugging symbols. This is the default. - - --strict-warnings - This is a developer flag that switches on various compiler - options recommended for OpenSSL development. It only works - when using gcc or clang as the compiler. If you are - developing a patch for OpenSSL then it is recommended that - you use this option where possible. - - --with-zlib-include=DIR - The directory for the location of the zlib include file. This - option is only necessary if enable-zlib (see below) is used - and the include file is not already on the system include - path. - - --with-zlib-lib=LIB - On Unix: this is the directory containing the zlib library. - If not provided the system library path will be used. - On Windows: this is the filename of the zlib library (with or - without a path). This flag must be provided if the - zlib-dynamic option is not also used. If zlib-dynamic is used - then this flag is optional and a default value ("ZLIB1") is - used if not provided. - On VMS: this is the filename of the zlib library (with or - without a path). This flag is optional and if not provided - then "GNV$LIBZSHR", "GNV$LIBZSHR32" or "GNV$LIBZSHR64" is - used by default depending on the pointer size chosen. - - - --with-rand-seed=seed1[,seed2,...] - A comma separated list of seeding methods which will be tried - by OpenSSL in order to obtain random input (a.k.a "entropy") - for seeding its cryptographically secure random number - generator (CSPRNG). The current seeding methods are: - - os: Use a trusted operating system entropy source. - This is the default method if such an entropy - source exists. - getrandom: Use the L or equivalent system - call. - devrandom: Use the first device from the DEVRANDOM list - which can be opened to read random bytes. The - DEVRANDOM preprocessor constant expands to - "/dev/urandom","/dev/random","/dev/srandom" on - most unix-ish operating systems. - egd: Check for an entropy generating daemon. - rdcpu: Use the RDSEED or RDRAND command if provided by - the CPU. - librandom: Use librandom (not implemented yet). - none: Disable automatic seeding. This is the default - on some operating systems where no suitable - entropy source exists, or no support for it is - implemented yet. - - For more information, see the section 'Note on random number - generation' at the end of this document. - - no-afalgeng - Don't build the AFALG engine. This option will be forced if - on a platform that does not support AFALG. - - enable-asan - Build with the Address sanitiser. This is a developer option - only. It may not work on all platforms and should never be - used in production environments. It will only work when used - with gcc or clang and should be used in conjunction with the - no-shared option. - - no-asm - Do not use assembler code. This should be viewed as - debugging/trouble-shooting option rather than production. - On some platforms a small amount of assembler code may - still be used even with this option. - - no-async - Do not build support for async operations. - - no-autoalginit - Don't automatically load all supported ciphers and digests. - Typically OpenSSL will make available all of its supported - ciphers and digests. For a statically linked application this - may be undesirable if small executable size is an objective. - This only affects libcrypto. Ciphers and digests will have to - be loaded manually using EVP_add_cipher() and - EVP_add_digest() if this option is used. This option will - force a non-shared build. - - no-autoerrinit - Don't automatically load all libcrypto/libssl error strings. - Typically OpenSSL will automatically load human readable - error strings. For a statically linked application this may - be undesirable if small executable size is an objective. - - no-autoload-config - Don't automatically load the default openssl.cnf file. - Typically OpenSSL will automatically load a system config - file which configures default ssl options. - - enable-buildtest-c++ - While testing, generate C++ buildtest files that - simply check that the public OpenSSL header files - are usable standalone with C++. - - Enabling this option demands extra care. For any - compiler flag given directly as configuration - option, you must ensure that it's valid for both - the C and the C++ compiler. If not, the C++ build - test will most likely break. As an alternative, - you can use the language specific variables, CFLAGS - and CXXFLAGS. - - no-capieng - Don't build the CAPI engine. This option will be forced if - on a platform that does not support CAPI. - - no-cms - Don't build support for CMS features - - no-comp - Don't build support for SSL/TLS compression. If this option - is left enabled (the default), then compression will only - work if the zlib or zlib-dynamic options are also chosen. - - enable-crypto-mdebug - Build support for debugging memory allocated via - OPENSSL_malloc() or OPENSSL_zalloc(). - - enable-crypto-mdebug-backtrace - As for crypto-mdebug, but additionally provide backtrace - information for allocated memory. - TO BE USED WITH CARE: this uses GNU C functionality, and - is therefore not usable for non-GNU config targets. If - your build complains about the use of '-rdynamic' or the - lack of header file execinfo.h, this option is not for you. - ALSO NOTE that even though execinfo.h is available on your - system (through Gnulib), the functions might just be stubs - that do nothing. - - no-ct - Don't build support for Certificate Transparency. - - no-deprecated - Don't build with support for any deprecated APIs. This is the - same as using "--api" and supplying the latest version - number. - - no-dgram - Don't build support for datagram based BIOs. Selecting this - option will also force the disabling of DTLS. - - no-dso - Don't build support for loading Dynamic Shared Objects. - - enable-devcryptoeng - Build the /dev/crypto engine. It is automatically selected - on BSD implementations, in which case it can be disabled with - no-devcryptoeng. - - no-dynamic-engine - Don't build the dynamically loaded engines. This only has an - effect in a "shared" build - - no-ec - Don't build support for Elliptic Curves. - - no-ec2m - Don't build support for binary Elliptic Curves - - enable-ec_nistp_64_gcc_128 - Enable support for optimised implementations of some commonly - used NIST elliptic curves. - This is only supported on platforms: - - with little-endian storage of non-byte types - - that tolerate misaligned memory references - - where the compiler: - - supports the non-standard type __uint128_t - - defines the built-in macro __SIZEOF_INT128__ - - enable-egd - Build support for gathering entropy from EGD (Entropy - Gathering Daemon). - - no-engine - Don't build support for loading engines. - - no-err - Don't compile in any error strings. - - enable-external-tests - Enable building of integration with external test suites. - This is a developer option and may not work on all platforms. - The only supported external test suite at the current time is - the BoringSSL test suite. See the file test/README.external - for further details. - - no-filenames - Don't compile in filename and line number information (e.g. - for errors and memory allocation). - - enable-fuzz-libfuzzer, enable-fuzz-afl - Build with support for fuzzing using either libfuzzer or AFL. - These are developer options only. They may not work on all - platforms and should never be used in production environments. - See the file fuzz/README.md for further details. - - no-gost - Don't build support for GOST based ciphersuites. Note that - if this feature is enabled then GOST ciphersuites are only - available if the GOST algorithms are also available through - loading an externally supplied engine. - - no-hw-padlock - Don't build the padlock engine. - - no-makedepend - Don't generate dependencies. - - no-multiblock - Don't build support for writing multiple records in one - go in libssl (Note: this is a different capability to the - pipelining functionality). - - no-nextprotoneg - Don't build support for the NPN TLS extension. - - no-ocsp - Don't build support for OCSP. - - 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. - - no-psk - Don't build support for Pre-Shared Key based ciphersuites. - - no-rdrand - Don't use hardware RDRAND capabilities. - - no-rfc3779 - Don't build support for RFC3779 ("X.509 Extensions for IP - Addresses and AS Identifiers") - - sctp - Build support for SCTP - - no-shared - Do not create shared libraries, only static ones. See "Note - on shared libraries" below. - - no-sock - Don't build support for socket BIOs - - no-srp - Don't build support for SRP or SRP based ciphersuites. - - no-srtp - Don't build SRTP support - - no-sse2 - Exclude SSE2 code paths from 32-bit x86 assembly modules. - Normally SSE2 extension is detected at run-time, but the - decision whether or not the machine code will be executed - is taken solely on CPU capability vector. This means that - if you happen to run OS kernel which does not support SSE2 - extension on Intel P4 processor, then your application - might be exposed to "illegal instruction" exception. - There might be a way to enable support in kernel, e.g. - FreeBSD kernel can be compiled with CPU_ENABLE_SSE, and - there is a way to disengage SSE2 code paths upon application - start-up, but if you aim for wider "audience" running - such kernel, consider no-sse2. Both the 386 and - no-asm options imply no-sse2. - - enable-ssl-trace - Build with the SSL Trace capabilities (adds the "-trace" - option to s_client and s_server). - - no-static-engine - Don't build the statically linked engines. This only - has an impact when not built "shared". - - no-stdio - Don't use anything from the C header file "stdio.h" that - makes use of the "FILE" type. Only libcrypto and libssl can - be built in this way. Using this option will suppress - building the command line applications. Additionally since - the OpenSSL tests also use the command line applications the - tests will also be skipped. - - no-tests - Don't build test programs or run any test. - - no-threads - Don't try to build with support for multi-threaded - applications. - - threads - Build with support for multi-threaded applications. Most - platforms will enable this by default. However if on a - platform where this is not the case then this will usually - require additional system-dependent options! See "Note on - multi-threading" below. - - no-ts - Don't build Time Stamping Authority support. - - enable-ubsan - Build with the Undefined Behaviour sanitiser. This is a - developer option only. It may not work on all platforms and - should never be used in production environments. It will only - work when used with gcc or clang and should be used in - conjunction with the "-DPEDANTIC" option (or the - --strict-warnings option). - - no-ui-console - Don't build with the "UI" console method (i.e. the "UI" - method that enables text based console prompts). - - enable-unit-test - Enable additional unit test APIs. This should not typically - be used in production deployments. - - enable-weak-ssl-ciphers - Build support for SSL/TLS ciphers that are considered "weak" - (e.g. RC4 based ciphersuites). - - zlib - Build with support for zlib compression/decompression. - - zlib-dynamic - Like "zlib", but has OpenSSL load the zlib library - dynamically when needed. This is only supported on systems - where loading of shared libraries is supported. - - 386 - In 32-bit x86 builds, when generating assembly modules, - use the 80386 instruction set only (the default x86 code - is more efficient, but requires at least a 486). Note: - This doesn't affect code generated by compiler, you're - likely to complement configuration command line with - suitable compiler-specific option. - - no- - Don't build support for negotiating the specified SSL/TLS - protocol (one of ssl, ssl3, tls, tls1, tls1_1, tls1_2, - tls1_3, dtls, dtls1 or dtls1_2). If "no-tls" is selected then - all of tls1, tls1_1, tls1_2 and tls1_3 are disabled. - Similarly "no-dtls" will disable dtls1 and dtls1_2. The - "no-ssl" option is synonymous with "no-ssl3". Note this only - affects version negotiation. OpenSSL will still provide the - methods for applications to explicitly select the individual - protocol versions. - - no--method - As for no- but in addition do not build the methods for - applications to explicitly select individual protocol - versions. Note that there is no "no-tls1_3-method" option - because there is no application method for TLSv1.3. Using - individual protocol methods directly is deprecated. - Applications should use TLS_method() instead. - - enable- - Build with support for the specified algorithm, where - is one of: md2 or rc5. - - no- - Build without support for the specified algorithm, where - is one of: aria, bf, blake2, camellia, cast, chacha, - cmac, des, dh, dsa, ecdh, ecdsa, idea, md4, mdc2, ocb, - poly1305, rc2, rc4, rmd160, scrypt, seed, siphash, sm2, sm3, - sm4 or whirlpool. The "ripemd" algorithm is deprecated and - if used is synonymous with rmd160. - - -Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static - These system specific options will be recognised and - passed through to the compiler to allow you to define - preprocessor symbols, specify additional libraries, library - directories or other compiler options. It might be worth - noting that some compilers generate code specifically for - processor the compiler currently executes on. This is not - necessarily what you might have in mind, since it might be - unsuitable for execution on other, typically older, - processor. Consult your compiler documentation. - - Take note of the VAR=value documentation below and how - these flags interact with those variables. - - -xxx, +xxx, /xxx - Additional options that are not otherwise recognised are - passed through as they are to the compiler as well. - Unix-style options beginning with a '-' or '+' and - Windows-style options beginning with a '/' are recognized. - Again, consult your compiler documentation. - - If the option contains arguments separated by spaces, - then the URL-style notation %20 can be used for the space - character in order to avoid having to quote the option. - For example, -opt%20arg gets expanded to -opt arg. - In fact, any ASCII character can be encoded as %xx using its - hexadecimal encoding. - - Take note of the VAR=value documentation below and how - these flags interact with those variables. - - VAR=value - Assignment of environment variable for Configure. These - work just like normal environment variable assignments, - but are supported on all platforms and are confined to - the configuration scripts only. These assignments override - the corresponding value in the inherited environment, if - there is one. - - The following variables are used as "make variables" and - can be used as an alternative to giving preprocessor, - compiler and linker options directly as configuration. - The following variables are supported: - - AR The static library archiver. - ARFLAGS Flags for the static library archiver. - AS The assembler compiler. - ASFLAGS Flags for the assembler compiler. - CC The C compiler. - CFLAGS Flags for the C compiler. - CXX The C++ compiler. - CXXFLAGS Flags for the C++ compiler. - CPP The C/C++ preprocessor. - CPPFLAGS Flags for the C/C++ preprocessor. - CPPDEFINES List of CPP macro definitions, separated - by a platform specific character (':' or - space for Unix, ';' for Windows, ',' for - VMS). This can be used instead of using - -D (or what corresponds to that on your - compiler) in CPPFLAGS. - CPPINCLUDES List of CPP inclusion directories, separated - the same way as for CPPDEFINES. This can - be used instead of -I (or what corresponds - to that on your compiler) in CPPFLAGS. - HASHBANGPERL Perl invocation to be inserted after '#!' - in public perl scripts (only relevant on - Unix). - LD The program linker (not used on Unix, $(CC) - is used there). - LDFLAGS Flags for the shared library, DSO and - program linker. - LDLIBS Extra libraries to use when linking. - Takes the form of a space separated list - of library specifications on Unix and - Windows, and as a comma separated list of - libraries on VMS. - RANLIB The library archive indexer. - RC The Windows resource compiler. - RCFLAGS Flags for the Windows resource compiler. - RM The command to remove files and directories. - - These cannot be mixed with compiling / linking flags given - on the command line. In other words, something like this - isn't permitted. - - ./config -DFOO CPPFLAGS=-DBAR -DCOOKIE - - Backward compatibility note: - - To be compatible with older configuration scripts, the - environment variables are ignored if compiling / linking - flags are given on the command line, except for these: - - AR, CC, CXX, CROSS_COMPILE, HASHBANGPERL, PERL, RANLIB, RC - and WINDRES - - For example, the following command will not see -DBAR: - - CPPFLAGS=-DBAR ./config -DCOOKIE - - However, the following will see both set variables: - - CC=gcc CROSS_COMPILE=x86_64-w64-mingw32- \ - ./config -DCOOKIE - - If CC is set, it is advisable to also set CXX to ensure - both C and C++ compilers are in the same "family". This - becomes relevant with 'enable-external-tests' and - 'enable-buildtest-c++'. - - reconf - reconfigure - Reconfigure from earlier data. This fetches the previous - command line options and environment from data saved in - "configdata.pm", and runs the configuration process again, - using these options and environment. - Note: NO other option is permitted together with "reconf". - This means that you also MUST use "./Configure" (or - what corresponds to that on non-Unix platforms) directly - to invoke this option. - Note: The original configuration saves away values for ALL - environment variables that were used, and if they weren't - defined, they are still saved away with information that - they weren't originally defined. This information takes - precedence over environment variables that are defined - when reconfiguring. - - Displaying configuration data - ----------------------------- - - The configuration script itself will say very little, and finishes by - creating "configdata.pm". This perl module can be loaded by other scripts - to find all the configuration data, and it can also be used as a script to - display all sorts of configuration data in a human readable form. - - For more information, please do: - - $ ./configdata.pm --help # Unix - - or - - $ perl configdata.pm --help # Windows and VMS - - Installation in Detail - ---------------------- - - 1a. Configure OpenSSL for your operation system automatically: - - NOTE: This is not available on Windows. - - $ ./config [[ options ]] # Unix - - or - - $ @config [[ options ]] ! OpenVMS - - For the remainder of this text, the Unix form will be used in all - examples, please use the appropriate form for your platform. - - This guesses at your operating system (and compiler, if necessary) and - configures OpenSSL based on this guess. Run ./config -t to see - if it guessed correctly. If you want to use a different compiler, you - are cross-compiling for another platform, or the ./config guess was - wrong for other reasons, go to step 1b. Otherwise go to step 2. - - On some systems, you can include debugging information as follows: - - $ ./config -d [[ options ]] - - 1b. Configure OpenSSL for your operating system manually - - OpenSSL knows about a range of different operating system, hardware and - compiler combinations. To see the ones it knows about, run - - $ ./Configure # Unix - - or - - $ perl Configure # All other platforms - - For the remainder of this text, the Unix form will be used in all - examples, please use the appropriate form for your platform. - - Pick a suitable name from the list that matches your system. For most - operating systems there is a choice between using "cc" or "gcc". When - you have identified your system (and if necessary compiler) use this name - as the argument to Configure. For example, a "linux-elf" user would - run: - - $ ./Configure linux-elf [[ options ]] - - If your system isn't listed, you will have to create a configuration - file named Configurations/{{ something }}.conf and add the correct - configuration for your system. See the available configs as examples - and read Configurations/README and Configurations/README.design for - more information. - - The generic configurations "cc" or "gcc" should usually work on 32 bit - Unix-like systems. - - Configure creates a build file ("Makefile" on Unix, "makefile" on Windows - and "descrip.mms" on OpenVMS) from a suitable template in Configurations, - and defines various macros in include/openssl/opensslconf.h (generated from - include/openssl/opensslconf.h.in). - - 1c. Configure OpenSSL for building outside of the source tree. - - OpenSSL can be configured to build in a build directory separate from - the directory with the source code. It's done by placing yourself in - some other directory and invoking the configuration commands from - there. - - Unix example: - - $ mkdir /var/tmp/openssl-build - $ cd /var/tmp/openssl-build - $ /PATH/TO/OPENSSL/SOURCE/config [[ options ]] - - or - - $ /PATH/TO/OPENSSL/SOURCE/Configure {{ target }} [[ options ]] - - OpenVMS example: - - $ set default sys$login: - $ create/dir [.tmp.openssl-build] - $ set default [.tmp.openssl-build] - $ @[PATH.TO.OPENSSL.SOURCE]config [[ options ]] - - or - - $ @[PATH.TO.OPENSSL.SOURCE]Configure {{ target }} [[ options ]] - - Windows example: - - $ C: - $ mkdir \temp-openssl - $ cd \temp-openssl - $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure {{ target }} [[ options ]] - - Paths can be relative just as well as absolute. Configure will - do its best to translate them to relative paths whenever possible. - - 2. Build OpenSSL by running: - - $ make # Unix - $ mms ! (or mmk) OpenVMS - $ nmake # Windows - - This will build the OpenSSL libraries (libcrypto.a and libssl.a on - Unix, corresponding on other platforms) and the OpenSSL binary - ("openssl"). The libraries will be built in the top-level directory, - and the binary will be in the "apps" subdirectory. - - Troubleshooting: - - If the build fails, look at the output. There may be reasons - for the failure that aren't problems in OpenSSL itself (like - missing standard headers). - - If the build succeeded previously, but fails after a source or - configuration change, it might be helpful to clean the build tree - before attempting another build. Use this command: - - $ make clean # Unix - $ mms clean ! (or mmk) OpenVMS - $ nmake clean # Windows - - Assembler error messages can sometimes be sidestepped by using the - "no-asm" configuration option. - - Compiling parts of OpenSSL with gcc and others with the system - compiler will result in unresolved symbols on some systems. - - If you are still having problems you can get help by sending an email - to the openssl-users email list (see - https://www.openssl.org/community/mailinglists.html for details). If - it is a bug with OpenSSL itself, please open an issue on GitHub, at - https://github.com/openssl/openssl/issues. Please review the existing - ones first; maybe the bug was already reported or has already been - fixed. - - 3. After a successful build, the libraries should be tested. Run: - - $ make test # Unix - $ mms test ! OpenVMS - $ nmake test # Windows - - NOTE: you MUST run the tests from an unprivileged account (or - disable your privileges temporarily if your platform allows it). - - If some tests fail, look at the output. There may be reasons for - the failure that isn't a problem in OpenSSL itself (like a - malfunction with Perl). You may want increased verbosity, that - can be accomplished like this: - - $ make VERBOSE=1 test # Unix - - $ mms /macro=(VERBOSE=1) test ! OpenVMS - - $ nmake VERBOSE=1 test # Windows - - If you want to run just one or a few specific tests, you can use - the make variable TESTS to specify them, like this: - - $ make TESTS='test_rsa test_dsa' test # Unix - $ mms/macro="TESTS=test_rsa test_dsa" test ! OpenVMS - $ nmake TESTS='test_rsa test_dsa' test # Windows - - And of course, you can combine (Unix example shown): - - $ make VERBOSE=1 TESTS='test_rsa test_dsa' test - - You can find the list of available tests like this: - - $ make list-tests # Unix - $ mms list-tests ! OpenVMS - $ nmake list-tests # Windows - - Have a look at the manual for the perl module Test::Harness to - see what other HARNESS_* variables there are. - - If you find a problem with OpenSSL itself, try removing any - compiler optimization flags from the CFLAGS line in Makefile and - run "make clean; make" or corresponding. - - To report a bug please open an issue on GitHub, at - https://github.com/openssl/openssl/issues. - - For more details on how the make variables TESTS can be used, - see section TESTS in Detail below. - - 4. If everything tests ok, install OpenSSL with - - $ make install # Unix - $ mms install ! OpenVMS - $ nmake install # Windows - - Note that in order to perform the install step above you need to have - appropriate permissions to write to the installation directory. - - The above commands will install all the software components in this - directory tree under PREFIX (the directory given with --prefix or its - default): - - Unix: - - bin/ Contains the openssl binary and a few other - utility scripts. - include/openssl - Contains the header files needed if you want - to build your own programs that use libcrypto - or libssl. - lib Contains the OpenSSL library files. - lib/engines Contains the OpenSSL dynamically loadable engines. - - share/man/man1 Contains the OpenSSL command line man-pages. - share/man/man3 Contains the OpenSSL library calls man-pages. - share/man/man5 Contains the OpenSSL configuration format man-pages. - share/man/man7 Contains the OpenSSL other misc man-pages. - - share/doc/openssl/html/man1 - share/doc/openssl/html/man3 - share/doc/openssl/html/man5 - share/doc/openssl/html/man7 - Contains the HTML rendition of the man-pages. - - OpenVMS ('arch' is replaced with the architecture name, "ALPHA" - or "IA64", 'sover' is replaced with the shared library version - (0101 for 1.1.x), and 'pz' is replaced with the pointer size - OpenSSL was built with): - - [.EXE.'arch'] Contains the openssl binary. - [.EXE] Contains a few utility scripts. - [.include.openssl] - Contains the header files needed if you want - to build your own programs that use libcrypto - or libssl. - [.LIB.'arch'] Contains the OpenSSL library files. - [.ENGINES'sover''pz'.'arch'] - Contains the OpenSSL dynamically loadable engines. - [.SYS$STARTUP] Contains startup, login and shutdown scripts. - These define appropriate logical names and - command symbols. - [.SYSTEST] Contains the installation verification procedure. - [.HTML] Contains the HTML rendition of the manual pages. - - - Additionally, install will add the following directories under - OPENSSLDIR (the directory given with --openssldir or its default) - for you convenience: - - certs Initially empty, this is the default location - for certificate files. - private Initially empty, this is the default location - for private key files. - misc Various scripts. - - The installation directory should be appropriately protected to ensure - unprivileged users cannot make changes to OpenSSL binaries or files, or - install engines. If you already have a pre-installed version of OpenSSL as - part of your Operating System it is recommended that you do not overwrite - the system version and instead install to somewhere else. - - Package builders who want to configure the library for standard - locations, but have the package installed somewhere else so that - it can easily be packaged, can use - - $ make DESTDIR=/tmp/package-root install # Unix - $ mms/macro="DESTDIR=TMP:[PACKAGE-ROOT]" install ! OpenVMS - - The specified destination directory will be prepended to all - installation target paths. - - Compatibility issues with previous OpenSSL versions: - - * COMPILING existing applications - - Starting with version 1.1.0, OpenSSL hides a number of structures - that were previously open. This includes all internal libssl - structures and a number of EVP types. Accessor functions have - been added to allow controlled access to the structures' data. - - This means that some software needs to be rewritten to adapt to - the new ways of doing things. This often amounts to allocating - an instance of a structure explicitly where you could previously - allocate them on the stack as automatic variables, and using the - provided accessor functions where you would previously access a - structure's field directly. - - Some APIs have changed as well. However, older APIs have been - preserved when possible. - - Environment Variables - --------------------- - - A number of environment variables can be used to provide additional control - over the build process. Typically these should be defined prior to running - config or Configure. Not all environment variables are relevant to all - platforms. - - AR - The name of the ar executable to use. - - BUILDFILE - Use a different build file name than the platform default - ("Makefile" on Unix-like platforms, "makefile" on native Windows, - "descrip.mms" on OpenVMS). This requires that there is a - corresponding build file template. See Configurations/README - for further information. - - CC - The compiler to use. Configure will attempt to pick a default - compiler for your platform but this choice can be overridden - using this variable. Set it to the compiler executable you wish - to use, e.g. "gcc" or "clang". - - CROSS_COMPILE - This environment variable has the same meaning as for the - "--cross-compile-prefix" Configure flag described above. If both - are set then the Configure flag takes precedence. - - NM - The name of the nm executable to use. - - OPENSSL_LOCAL_CONFIG_DIR - OpenSSL comes with a database of information about how it - should be built on different platforms as well as build file - templates for those platforms. The database is comprised of - ".conf" files in the Configurations directory. The build - file templates reside there as well as ".tmpl" files. See the - file Configurations/README for further information about the - format of ".conf" files as well as information on the ".tmpl" - files. - In addition to the standard ".conf" and ".tmpl" files, it is - possible to create your own ".conf" and ".tmpl" files and store - them locally, outside the OpenSSL source tree. This environment - variable can be set to the directory where these files are held - and will be considered by Configure before it looks in the - standard directories. - - PERL - The name of the Perl executable to use when building OpenSSL. - This variable is used in config script only. Configure on the - other hand imposes the interpreter by which it itself was - executed on the whole build procedure. - - HASHBANGPERL - The command string for the Perl executable to insert in the - #! line of perl scripts that will be publicly installed. - Default: /usr/bin/env perl - Note: the value of this variable is added to the same scripts - on all platforms, but it's only relevant on Unix-like platforms. - - RC - The name of the rc executable to use. The default will be as - defined for the target platform in the ".conf" file. If not - defined then "windres" will be used. The WINDRES environment - variable is synonymous to this. If both are defined then RC - takes precedence. - - RANLIB - The name of the ranlib executable to use. - - WINDRES - See RC. - - Makefile targets - ---------------- - - The Configure script generates a Makefile in a format relevant to the specific - platform. The Makefiles provide a number of targets that can be used. Not all - targets may be available on all platforms. Only the most common targets are - described here. Examine the Makefiles themselves for the full list. - - all - The default target to build all the software components. - - clean - Remove all build artefacts and return the directory to a "clean" - state. - - depend - Rebuild the dependencies in the Makefiles. This is a legacy - option that no longer needs to be used since OpenSSL 1.1.0. - - install - Install all OpenSSL components. - - install_sw - Only install the OpenSSL software components. - - install_docs - Only install the OpenSSL documentation components. - - install_man_docs - Only install the OpenSSL man pages (Unix only). - - install_html_docs - Only install the OpenSSL html documentation. - - list-tests - Prints a list of all the self test names. - - test - Build and run the OpenSSL self tests. - - uninstall - Uninstall all OpenSSL components. - - reconfigure - reconf - Re-run the configuration process, as exactly as the last time - as possible. - - update - This is a developer option. If you are developing a patch for - OpenSSL you may need to use this if you want to update - automatically generated files; add new error codes or add new - (or change the visibility of) public API functions. (Unix only). - - TESTS in Detail - --------------- - - The make variable TESTS supports a versatile set of space separated tokens - with which you can specify a set of tests to be performed. With a "current - set of tests" in mind, initially being empty, here are the possible tokens: - - alltests The current set of tests becomes the whole set of available - tests (as listed when you do 'make list-tests' or similar). - xxx Adds the test 'xxx' to the current set of tests. - -xxx Removes 'xxx' from the current set of tests. If this is the - first token in the list, the current set of tests is first - assigned the whole set of available tests, effectively making - this token equivalent to TESTS="alltests -xxx". - nn Adds the test group 'nn' (which is a number) to the current - set of tests. - -nn Removes the test group 'nn' from the current set of tests. - If this is the first token in the list, the current set of - tests is first assigned the whole set of available tests, - effectively making this token equivalent to - TESTS="alltests -xxx". - - Also, all tokens except for "alltests" may have wildcards, such as *. - (on Unix and Windows, BSD style wildcards are supported, while on VMS, - it's VMS style wildcards) - - Example: All tests except for the fuzz tests: - - $ make TESTS=-test_fuzz test - - or (if you want to be explicit) - - $ make TESTS='alltests -test_fuzz' test - - Example: All tests that have a name starting with "test_ssl" but not those - starting with "test_ssl_": - - $ make TESTS='test_ssl* -test_ssl_*' test - - Example: Only test group 10: - - $ make TESTS='10' - - Example: All tests except the slow group (group 99): - - $ make TESTS='-99' - - Example: All tests in test groups 80 to 99 except for tests in group 90: - - $ make TESTS='[89]? -90' - - Note on multi-threading - ----------------------- - - For some systems, the OpenSSL Configure script knows what compiler options - are needed to generate a library that is suitable for multi-threaded - applications. On these systems, support for multi-threading is enabled - by default; use the "no-threads" option to disable (this should never be - necessary). - - On other systems, to enable support for multi-threading, you will have - to specify at least two options: "threads", and a system-dependent option. - (The latter is "-D_REENTRANT" on various systems.) The default in this - case, obviously, is not to include support for multi-threading (but - you can still use "no-threads" to suppress an annoying warning message - from the Configure script.) - - OpenSSL provides built-in support for two threading models: pthreads (found on - most UNIX/Linux systems), and Windows threads. No other threading models are - supported. If your platform does not provide pthreads or Windows threads then - you should Configure with the "no-threads" option. - - Notes on shared libraries - ------------------------- - - For most systems the OpenSSL Configure script knows what is needed to - build shared libraries for libcrypto and libssl. On these systems - the shared libraries will be created by default. This can be suppressed and - only static libraries created by using the "no-shared" option. On systems - where OpenSSL does not know how to build shared libraries the "no-shared" - option will be forced and only static libraries will be created. - - Shared libraries are named a little differently on different platforms. - One way or another, they all have the major OpenSSL version number as - part of the file name, i.e. for OpenSSL 1.1.x, 1.1 is somehow part of - the name. - - On most POSIX platforms, shared libraries are named libcrypto.so.1.1 - and libssl.so.1.1. - - on Cygwin, shared libraries are named cygcrypto-1.1.dll and cygssl-1.1.dll - with import libraries libcrypto.dll.a and libssl.dll.a. - - On Windows build with MSVC or using MingW, shared libraries are named - libcrypto-1_1.dll and libssl-1_1.dll for 32-bit Windows, libcrypto-1_1-x64.dll - and libssl-1_1-x64.dll for 64-bit x86_64 Windows, and libcrypto-1_1-ia64.dll - and libssl-1_1-ia64.dll for IA64 Windows. With MSVC, the import libraries - are named libcrypto.lib and libssl.lib, while with MingW, they are named - libcrypto.dll.a and libssl.dll.a. - - On VMS, shareable images (VMS speak for shared libraries) are named - ossl$libcrypto0101_shr.exe and ossl$libssl0101_shr.exe. However, when - OpenSSL is specifically built for 32-bit pointers, the shareable images - are named ossl$libcrypto0101_shr32.exe and ossl$libssl0101_shr32.exe - instead, and when built for 64-bit pointers, they are named - ossl$libcrypto0101_shr64.exe and ossl$libssl0101_shr64.exe. - - Note on random number generation - -------------------------------- - - Availability of cryptographically secure random numbers is required for - secret key generation. OpenSSL provides several options to seed the - internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse - to deliver random bytes and a "PRNG not seeded error" will occur. - - The seeding method can be configured using the --with-rand-seed option, - which can be used to specify a comma separated list of seed methods. - However in most cases OpenSSL will choose a suitable default method, - so it is not necessary to explicitly provide this option. Note also - that not all methods are available on all platforms. - - I) On operating systems which provide a suitable randomness source (in - form of a system call or system device), OpenSSL will use the optimal - available method to seed the CSPRNG from the operating system's - randomness sources. This corresponds to the option --with-rand-seed=os. - - II) On systems without such a suitable randomness source, automatic seeding - and reseeding is disabled (--with-rand-seed=none) and it may be necessary - to install additional support software to obtain a random seed and reseed - the CSPRNG manually. Please check out the manual pages for RAND_add(), - RAND_bytes(), RAND_egd(), and the FAQ for more information. diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,1817 @@ +Build and Install +================= + +This document describes installation on all supported operating +systems (the Unix/Linux family, including macOS), OpenVMS, +and Windows). + +Table of Contents +================= + + - [Prerequisites](#prerequisites) + - [Notational Conventions](#notational-conventions) + - [Quick Installation Guide](#quick-installation-guide) + - [Building OpenSSL](#building-openssl) + - [Installing OpenSSL](#installing-openssl) + - [Configuration Options](#configuration-options) + - [API Level](#api-level) + - [Cross Compile Prefix](#cross-compile-prefix) + - [Build Type](#build-type) + - [Directories](#directories) + - [Compiler Warnings](#compiler-warnings) + - [ZLib Flags](#zlib-flags) + - [Seeding the Random Generator](#seeding-the-random-generator) + - [Setting the FIPS HMAC key](#setting-the-FIPS-HMAC-key) + - [Enable and Disable Features](#enable-and-disable-features) + - [Displaying configuration data](#displaying-configuration-data) + - [Installation Steps in Detail](#installation-steps-in-detail) + - [Configure](#configure-openssl) + - [Build](#build-openssl) + - [Test](#test-openssl) + - [Install](#install-openssl) + - [Advanced Build Options](#advanced-build-options) + - [Environment Variables](#environment-variables) + - [Makefile Targets](#makefile-targets) + - [Running Selected Tests](#running-selected-tests) + - [Troubleshooting](#troubleshooting) + - [Configuration Problems](#configuration-problems) + - [Build Failures](#build-failures) + - [Test Failures](#test-failures) + - [Notes](#notes) + - [Notes on multi-threading](#notes-on-multi-threading) + - [Notes on shared libraries](#notes-on-shared-libraries) + - [Notes on random number generation](#notes-on-random-number-generation) + - [Notes on assembler modules compilation](#notes-on-assembler-modules-compilation) + +Prerequisites +============= + +To install OpenSSL, you will need: + + * A "make" implementation + * Perl 5 with core modules (please read [NOTES-PERL.md](NOTES-PERL.md)) + * The Perl module `Text::Template` (please read [NOTES-PERL.md](NOTES-PERL.md)) + * an ANSI C compiler + * a development environment in the form of development libraries and C + header files + * a supported operating system + +For additional platform specific requirements, solutions to specific +issues and other details, please read one of these: + + * [Notes for UNIX-like platforms](NOTES-UNIX.md) + * [Notes for Android platforms](NOTES-ANDROID.md) + * [Notes for Windows platforms](NOTES-WINDOWS.md) + * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md) + * [Notes for the OpenVMS platform](NOTES-VMS.md) + * [Notes on Perl](NOTES-PERL.md) + * [Notes on Valgrind](NOTES-VALGRIND.md) + +Notational conventions +====================== + +Throughout this document, we use the following conventions. + +Commands +-------- + +Any line starting with a dollar sign is a command line. + + $ command + +The dollar sign indicates the shell prompt and is not to be entered as +part of the command. + +Choices +------- + +Several words in curly braces separated by pipe characters indicate a +**mandatory choice**, to be replaced with one of the given words. +For example, the line + + $ echo { WORD1 | WORD2 | WORD3 } + +represents one of the following three commands + + $ echo WORD1 + - or - + $ echo WORD2 + - or - + $ echo WORD3 + +One or several words in square brackets separated by pipe characters +denote an **optional choice**. It is similar to the mandatory choice, +but it can also be omitted entirely. + +So the line + + $ echo [ WORD1 | WORD2 | WORD3 ] + +represents one of the four commands + + $ echo WORD1 + - or - + $ echo WORD2 + - or - + $ echo WORD3 + - or - + $ echo + +Arguments +--------- + +**Mandatory arguments** are enclosed in double curly braces. +A simple example would be + + $ type {{ filename }} + +which is to be understood to use the command `type` on some file name +determined by the user. + +**Optional Arguments** are enclosed in double square brackets. + + [[ options ]] + +Note that the notation assumes spaces around `{`, `}`, `[`, `]`, `{{`, `}}` and +`[[`, `]]`. This is to differentiate from OpenVMS directory +specifications, which also use [ and ], but without spaces. + +Quick Installation Guide +======================== + +If you just want to get OpenSSL installed without bothering too much +about the details, here is the short version of how to build and install +OpenSSL. If any of the following steps fails, please consult the +[Installation in Detail](#installation-steps-in-detail) section below. + +Building OpenSSL +---------------- + +Use the following commands to configure, build and test OpenSSL. +The testing is optional, but recommended if you intend to install +OpenSSL for production use. + +### Unix / Linux / macOS + + $ ./Configure + $ make + $ make test + +### OpenVMS + +Use the following commands to build OpenSSL: + + $ perl Configure + $ mms + $ mms test + +### Windows + +If you are using Visual Studio, open a Developer Command Prompt and +issue the following commands to build OpenSSL. + + $ perl Configure + $ nmake + $ nmake test + +As mentioned in the [Choices](#choices) section, you need to pick one +of the four Configure targets in the first command. + +Most likely you will be using the `VC-WIN64A` target for 64bit Windows +binaries (AMD64) or `VC-WIN32` for 32bit Windows binaries (X86). +The other two options are `VC-WIN64I` (Intel IA64, Itanium) and +`VC-CE` (Windows CE) are rather uncommon nowadays. + +Installing OpenSSL +------------------ + +The following commands will install OpenSSL to a default system location. + +**Danger Zone:** even if you are impatient, please read the following two +paragraphs carefully before you install OpenSSL. + +For security reasons the default system location is by default not writable +for unprivileged users. So for the final installation step administrative +privileges are required. The default system location and the procedure to +obtain administrative privileges depends on the operating system. +It is recommended to compile and test OpenSSL with normal user privileges +and use administrative privileges only for the final installation step. + +On some platforms OpenSSL is preinstalled as part of the Operating System. +In this case it is highly recommended not to overwrite the system versions, +because other applications or libraries might depend on it. +To avoid breaking other applications, install your copy of OpenSSL to a +[different location](#installing-to-a-different-location) which is not in +the global search path for system libraries. + +Finally, if you plan on using the FIPS module, you need to read the +[Post-installation Notes](#post-installation-notes) further down. + +### Unix / Linux / macOS + +Depending on your distribution, you need to run the following command as +root user or prepend `sudo` to the command: + + $ make install + +By default, OpenSSL will be installed to + + /usr/local + +More precisely, the files will be installed into the subdirectories + + /usr/local/bin + /usr/local/lib + /usr/local/include + ... + +depending on the file type, as it is custom on Unix-like operating systems. + +### OpenVMS + +Use the following command to install OpenSSL. + + $ mms install + +By default, OpenSSL will be installed to + + SYS$COMMON:[OPENSSL] + +### Windows + +If you are using Visual Studio, open the Developer Command Prompt _elevated_ +and issue the following command. + + $ nmake install + +The easiest way to elevate the Command Prompt is to press and hold down both +the `` and `` keys while clicking the menu item in the task menu. + +The default installation location is + + C:\Program Files\OpenSSL + +for native binaries, or + + C:\Program Files (x86)\OpenSSL + +for 32bit binaries on 64bit Windows (WOW64). + +#### Installing to a different location + +To install OpenSSL to a different location (for example into your home +directory for testing purposes) run `Configure` as shown in the following +examples. + +The options `--prefix` and `--openssldir` are explained in further detail in +[Directories](#directories) below, and the values used here are mere examples. + +On Unix: + + $ ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl + +On OpenVMS: + + $ perl Configure --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL] + +Note: if you do add options to the configuration command, please make sure +you've read more than just this Quick Start, such as relevant `NOTES-*` files, +the options outline below, as configuration options may change the outcome +in otherwise unexpected ways. + +Configuration Options +===================== + +There are several options to `./Configure` to customize the build (note that +for Windows, the defaults for `--prefix` and `--openssldir` depend on what +configuration is used and what Windows implementation OpenSSL is built on. +For more information, see the [Notes for Windows platforms](NOTES-WINDOWS.md). + +API Level +--------- + + --api=x.y[.z] + +Build the OpenSSL libraries to support the API for the specified version. +If [no-deprecated](#no-deprecated) is also given, don't build with support +for deprecated APIs in or below the specified version number. For example, +adding + + --api=1.1.0 no-deprecated + +will remove support for all APIs that were deprecated in OpenSSL version +1.1.0 or below. This is a rather specialized option for developers. +If you just intend to remove all deprecated APIs up to the current version +entirely, just specify [no-deprecated](#no-deprecated). +If `--api` isn't given, it defaults to the current (minor) OpenSSL version. + +Cross Compile Prefix +-------------------- + + --cross-compile-prefix= + +The `` to include in front of commands for your toolchain. + +It is likely to have to end with dash, e.g. `a-b-c-` would invoke GNU compiler +as `a-b-c-gcc`, etc. Unfortunately cross-compiling is too case-specific to put +together one-size-fits-all instructions. You might have to pass more flags or +set up environment variables to actually make it work. Android and iOS cases +are discussed in corresponding `Configurations/15-*.conf` files. But there are +cases when this option alone is sufficient. For example to build the mingw64 +target on Linux `--cross-compile-prefix=x86_64-w64-mingw32-` works. Naturally +provided that mingw packages are installed. Today Debian and Ubuntu users +have option to install a number of prepackaged cross-compilers along with +corresponding run-time and development packages for "alien" hardware. To give +another example `--cross-compile-prefix=mipsel-linux-gnu-` suffices in such +case. + +For cross compilation, you must [configure manually](#manual-configuration). +Also, note that `--openssldir` refers to target's file system, not one you are +building on. + +Build Type +---------- + + --debug + +Build OpenSSL with debugging symbols and zero optimization level. + + --release + +Build OpenSSL without debugging symbols. This is the default. + +Directories +----------- + +### libdir + + --libdir=DIR + +The name of the directory under the top of the installation directory tree +(see the `--prefix` option) where libraries will be installed. By default +this is `lib`. Note that on Windows only static libraries (`*.lib`) will +be stored in this location. Shared libraries (`*.dll`) will always be +installed to the `bin` directory. + +Some build targets have a multilib postfix set in the build configuration. +For these targets the default libdir is `lib`. Please use +`--libdir=lib` to override the libdir if adding the postfix is undesirable. + +### openssldir + + --openssldir=DIR + +Directory for OpenSSL configuration files, and also the default certificate +and key store. Defaults are: + + Unix: /usr/local/ssl + Windows: C:\Program Files\Common Files\SSL + OpenVMS: SYS$COMMON:[OPENSSL-COMMON] + +For 32bit Windows applications on Windows 64bit (WOW64), always replace +`C:\Program Files` by `C:\Program Files (x86)`. + +### prefix + + --prefix=DIR + +The top of the installation directory tree. Defaults are: + + Unix: /usr/local + Windows: C:\Program Files\OpenSSL + OpenVMS: SYS$COMMON:[OPENSSL] + +Compiler Warnings +----------------- + + --strict-warnings + +This is a developer flag that switches on various compiler options recommended +for OpenSSL development. It only works when using gcc or clang as the compiler. +If you are developing a patch for OpenSSL then it is recommended that you use +this option where possible. + +ZLib Flags +---------- + +### with-zlib-include + + --with-zlib-include=DIR + +The directory for the location of the zlib include file. This option is only +necessary if [zlib](#zlib) is used and the include file is not +already on the system include path. + +### with-zlib-lib + + --with-zlib-lib=LIB + +**On Unix**: this is the directory containing the zlib library. +If not provided the system library path will be used. + +**On Windows:** this is the filename of the zlib library (with or +without a path). This flag must be provided if the +[zlib-dynamic](#zlib-dynamic) option is not also used. If `zlib-dynamic` is used +then this flag is optional and defaults to `ZLIB1` if not provided. + +**On VMS:** this is the filename of the zlib library (with or without a path). +This flag is optional and if not provided then `GNV$LIBZSHR`, `GNV$LIBZSHR32` +or `GNV$LIBZSHR64` is used by default depending on the pointer size chosen. + +Seeding the Random Generator +---------------------------- + + --with-rand-seed=seed1[,seed2,...] + +A comma separated list of seeding methods which will be tried by OpenSSL +in order to obtain random input (a.k.a "entropy") for seeding its +cryptographically secure random number generator (CSPRNG). +The current seeding methods are: + +### os + +Use a trusted operating system entropy source. +This is the default method if such an entropy source exists. + +### getrandom + +Use the [getrandom(2)][man-getrandom] or equivalent system call. + +[man-getrandom]: http://man7.org/linux/man-pages/man2/getrandom.2.html + +### devrandom + +Use the first device from the `DEVRANDOM` list which can be opened to read +random bytes. The `DEVRANDOM` preprocessor constant expands to + + "/dev/urandom","/dev/random","/dev/srandom" + +on most unix-ish operating systems. + +### egd + +Check for an entropy generating daemon. +This source is ignored by the FIPS provider. + +### rdcpu + +Use the `RDSEED` or `RDRAND` command if provided by the CPU. + +### librandom + +Use librandom (not implemented yet). +This source is ignored by the FIPS provider. + +### none + +Disable automatic seeding. This is the default on some operating systems where +no suitable entropy source exists, or no support for it is implemented yet. +This option is ignored by the FIPS provider. + +For more information, see the section [Notes on random number generation][rng] +at the end of this document. + +[rng]: #notes-on-random-number-generation + +Setting the FIPS HMAC key +------------------------- + + --fips-key=value + +As part of its self-test validation, the FIPS module must verify itself +by performing a SHA-256 HMAC computation on itself. The default key is +the SHA256 value of "the holy handgrenade of antioch" and is sufficient +for meeting the FIPS requirements. + +To change the key to a different value, use this flag. The value should +be a hex string no more than 64 characters. + +Enable and Disable Features +--------------------------- + +Feature options always come in pairs, an option to enable feature +`xxxx`, and an option to disable it: + + [ enable-xxxx | no-xxxx ] + +Whether a feature is enabled or disabled by default, depends on the feature. +In the following list, always the non-default variant is documented: if +feature `xxxx` is disabled by default then `enable-xxxx` is documented and +if feature `xxxx` is enabled by default then `no-xxxx` is documented. + +### no-afalgeng + +Don't build the AFALG engine. + +This option will be forced on a platform that does not support AFALG. + +### enable-ktls + +Build with Kernel TLS support. + +This option will enable the use of the Kernel TLS data-path, which can improve +performance and allow for the use of sendfile and splice system calls on +TLS sockets. The Kernel may use TLS accelerators if any are available on the +system. This option will be forced off on systems that do not support the +Kernel TLS data-path. + +### enable-asan + +Build with the Address sanitiser. + +This is a developer option only. It may not work on all platforms and should +never be used in production environments. It will only work when used with +gcc or clang and should be used in conjunction with the [no-shared](#no-shared) +option. + +### enable-acvp-tests + +Build support for Automated Cryptographic Validation Protocol (ACVP) +tests. + +This is required for FIPS validation purposes. Certain ACVP tests require +access to algorithm internals that are not normally accessible. +Additional information related to ACVP can be found at +. + +### no-asm + +Do not use assembler code. + +This should be viewed as debugging/troubleshooting option rather than for +production use. On some platforms a small amount of assembler code may still +be used even with this option. + +### no-async + +Do not build support for async operations. + +### no-autoalginit + +Don't automatically load all supported ciphers and digests. + +Typically OpenSSL will make available all of its supported ciphers and digests. +For a statically linked application this may be undesirable if small executable +size is an objective. This only affects libcrypto. Ciphers and digests will +have to be loaded manually using `EVP_add_cipher()` and `EVP_add_digest()` +if this option is used. This option will force a non-shared build. + +### no-autoerrinit + +Don't automatically load all libcrypto/libssl error strings. + +Typically OpenSSL will automatically load human readable error strings. For a +statically linked application this may be undesirable if small executable size +is an objective. + +### no-autoload-config + +Don't automatically load the default `openssl.cnf` file. + +Typically OpenSSL will automatically load a system config file which configures +default SSL options. + +### enable-buildtest-c++ + +While testing, generate C++ buildtest files that simply check that the public +OpenSSL header files are usable standalone with C++. + +Enabling this option demands extra care. For any compiler flag given directly +as configuration option, you must ensure that it's valid for both the C and +the C++ compiler. If not, the C++ build test will most likely break. As an +alternative, you can use the language specific variables, `CFLAGS` and `CXXFLAGS`. + +### --banner=text + +Use the specified text instead of the default banner at the end of +configuration. + +### --w + +On platforms where the choice of 32-bit or 64-bit architecture +is not explicitly specified, `Configure` will print a warning +message and wait for a few seconds to let you interrupt the +configuration. Using this flag skips the wait. + +### no-bulk + +Build only some minimal set of features. +This is a developer option used internally for CI build tests of the project. + +### no-cached-fetch + +Never cache algorithms when they are fetched from a provider. Normally, a +provider indicates if the algorithms it supplies can be cached or not. Using +this option will reduce run-time memory usage but it also introduces a +significant performance penalty. This option is primarily designed to help +with detecting incorrect reference counting. + +### no-capieng + +Don't build the CAPI engine. + +This option will be forced if on a platform that does not support CAPI. + +### no-cmp + +Don't build support for Certificate Management Protocol (CMP) +and Certificate Request Message Format (CRMF). + +### no-cms + +Don't build support for Cryptographic Message Syntax (CMS). + +### no-comp + +Don't build support for SSL/TLS compression. + +If this option is enabled (the default), then compression will only work if +the zlib or `zlib-dynamic` options are also chosen. + +### enable-crypto-mdebug + +This now only enables the `failed-malloc` feature. + +### enable-crypto-mdebug-backtrace + +This is a no-op; the project uses the compiler's address/leak sanitizer instead. + +### no-ct + +Don't build support for Certificate Transparency (CT). + +### no-deprecated + +Don't build with support for deprecated APIs up until and including the version +given with `--api` (or the current version, if `--api` wasn't specified). + +### no-dgram + +Don't build support for datagram based BIOs. + +Selecting this option will also force the disabling of DTLS. + +### no-dso + +Don't build support for loading Dynamic Shared Objects (DSO) + +### enable-devcryptoeng + +Build the `/dev/crypto` engine. + +This option is automatically selected on the BSD platform, in which case it can +be disabled with `no-devcryptoeng`. + +### no-dynamic-engine + +Don't build the dynamically loaded engines. + +This only has an effect in a shared build. + +### no-ec + +Don't build support for Elliptic Curves. + +### no-ec2m + +Don't build support for binary Elliptic Curves + +### enable-ec_nistp_64_gcc_128 + +Enable support for optimised implementations of some commonly used NIST +elliptic curves. + +This option is only supported on platforms: + + - with little-endian storage of non-byte types + - that tolerate misaligned memory references + - where the compiler: + - supports the non-standard type `__uint128_t` + - defines the built-in macro `__SIZEOF_INT128__` + +### enable-egd + +Build support for gathering entropy from the Entropy Gathering Daemon (EGD). + +### no-engine + +Don't build support for loading engines. + +### no-err + +Don't compile in any error strings. + +### enable-external-tests + +Enable building of integration with external test suites. + +This is a developer option and may not work on all platforms. The following +external test suites are currently supported: + + - GOST engine test suite + - Python PYCA/Cryptography test suite + - krb5 test suite + +See the file [test/README-external.md](test/README-external.md) +for further details. + +### no-filenames + +Don't compile in filename and line number information (e.g. for errors and +memory allocation). + +### enable-fips + +Build (and install) the FIPS provider + +### no-fips-securitychecks + +Don't perform FIPS module run-time checks related to enforcement of security +parameters such as minimum security strength of keys. + +### enable-fuzz-libfuzzer, enable-fuzz-afl + +Build with support for fuzzing using either libfuzzer or AFL. + +These are developer options only. They may not work on all platforms and +should never be used in production environments. + +See the file [fuzz/README.md](fuzz/README.md) for further details. + +### no-gost + +Don't build support for GOST based ciphersuites. + +Note that if this feature is enabled then GOST ciphersuites are only available +if the GOST algorithms are also available through loading an externally supplied +engine. + +### no-legacy + +Don't build the legacy provider. + +Disabling this also disables the legacy algorithms: MD2 (already disabled by default). + +### no-makedepend + +Don't generate dependencies. + +### no-module + +Don't build any dynamically loadable engines. + +This also implies `no-dynamic-engine`. + +### no-multiblock + +Don't build support for writing multiple records in one go in libssl + +Note: this is a different capability to the pipelining functionality. + +### no-nextprotoneg + +Don't build support for the Next Protocol Negotiation (NPN) TLS extension. + +### no-ocsp + +Don't build support for Online Certificate Status Protocol (OCSP). + +### no-padlockeng + +Don't build the padlock engine. + +### no-hw-padlock + +As synonym for `no-padlockeng`. Deprecated and should not be used. + +### no-pic + +Don't build with support for Position Independent Code. + +### no-pinshared + +Don't pin the shared libraries. + +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. + +### no-psk + +Don't build support for Pre-Shared Key based ciphersuites. + +### no-rdrand + +Don't use hardware RDRAND capabilities. + +### no-rfc3779 + +Don't build support for RFC3779, "X.509 Extensions for IP Addresses and +AS Identifiers". + +### sctp + +Build support for Stream Control Transmission Protocol (SCTP). + +### no-shared + +Do not create shared libraries, only static ones. + +See [Notes on shared libraries](#notes-on-shared-libraries) below. + +### no-sock + +Don't build support for socket BIOs. + +### no-srp + +Don't build support for Secure Remote Password (SRP) protocol or +SRP based ciphersuites. + +### no-srtp + +Don't build Secure Real-Time Transport Protocol (SRTP) support. + +### no-sse2 + +Exclude SSE2 code paths from 32-bit x86 assembly modules. + +Normally SSE2 extension is detected at run-time, but the decision whether or not +the machine code will be executed is taken solely on CPU capability vector. This +means that if you happen to run OS kernel which does not support SSE2 extension +on Intel P4 processor, then your application might be exposed to "illegal +instruction" exception. There might be a way to enable support in kernel, e.g. +FreeBSD kernel can be compiled with `CPU_ENABLE_SSE`, and there is a way to +disengage SSE2 code paths upon application start-up, but if you aim for wider +"audience" running such kernel, consider `no-sse2`. Both the `386` and `no-asm` +options imply `no-sse2`. + +### no-ssl-trace + +Don't build with SSL Trace capabilities. + +This removes the `-trace` option from `s_client` and `s_server`, and omits the +`SSL_trace()` function from libssl. + +Disabling `ssl-trace` may provide a small reduction in libssl binary size. + +### no-static-engine + +Don't build the statically linked engines. + +This only has an impact when not built "shared". + +### no-stdio + +Don't use anything from the C header file `stdio.h` that makes use of the `FILE` +type. Only libcrypto and libssl can be built in this way. Using this option will +suppress building the command line applications. Additionally, since the OpenSSL +tests also use the command line applications, the tests will also be skipped. + +### no-tests + +Don't build test programs or run any tests. + +### no-threads + +Don't build with support for multi-threaded applications. + +### threads + +Build with support for multi-threaded applications. Most platforms will enable +this by default. However, if on a platform where this is not the case then this +will usually require additional system-dependent options! + +See [Notes on multi-threading](#notes-on-multi-threading) below. + +### enable-trace + +Build with support for the integrated tracing api. + +See manual pages OSSL_trace_set_channel(3) and OSSL_trace_enabled(3) for details. + +### no-ts + +Don't build Time Stamping (TS) Authority support. + +### enable-ubsan + +Build with the Undefined Behaviour sanitiser (UBSAN). + +This is a developer option only. It may not work on all platforms and should +never be used in production environments. It will only work when used with +gcc or clang and should be used in conjunction with the `-DPEDANTIC` option +(or the `--strict-warnings` option). + +### no-ui-console + +Don't build with the User Interface (UI) console method + +The User Interface console method enables text based console prompts. + +### enable-unit-test + +Enable additional unit test APIs. + +This should not typically be used in production deployments. + +### no-uplink + +Don't build support for UPLINK interface. + +### enable-weak-ssl-ciphers + +Build support for SSL/TLS ciphers that are considered "weak" + +Enabling this includes for example the RC4 based ciphersuites. + +### zlib + +Build with support for zlib compression/decompression. + +### zlib-dynamic + +Like the zlib option, but has OpenSSL load the zlib library dynamically +when needed. + +This is only supported on systems where loading of shared libraries is supported. + +### 386 + +In 32-bit x86 builds, use the 80386 instruction set only in assembly modules + +The default x86 code is more efficient, but requires at least an 486 processor. +Note: This doesn't affect compiler generated code, so this option needs to be +accompanied by a corresponding compiler-specific option. + +### no-{protocol} + + no-{ssl|ssl3|tls|tls1|tls1_1|tls1_2|tls1_3|dtls|dtls1|dtls1_2} + +Don't build support for negotiating the specified SSL/TLS protocol. + +If `no-tls` is selected then all of `tls1`, `tls1_1`, `tls1_2` and `tls1_3` +are disabled. +Similarly `no-dtls` will disable `dtls1` and `dtls1_2`. The `no-ssl` option is +synonymous with `no-ssl3`. Note this only affects version negotiation. +OpenSSL will still provide the methods for applications to explicitly select +the individual protocol versions. + +### no-{protocol}-method + + no-{ssl3|tls1|tls1_1|tls1_2|dtls1|dtls1_2}-method + +Analogous to `no-{protocol}` but in addition do not build the methods for +applications to explicitly select individual protocol versions. Note that there +is no `no-tls1_3-method` option because there is no application method for +TLSv1.3. + +Using individual protocol methods directly is deprecated. Applications should +use `TLS_method()` instead. + +### enable-{algorithm} + + enable-{md2|rc5} + +Build with support for the specified algorithm. + +### no-{algorithm} + + no-{aria|bf|blake2|camellia|cast|chacha|cmac| + des|dh|dsa|ecdh|ecdsa|idea|md4|mdc2|ocb| + poly1305|rc2|rc4|rmd160|scrypt|seed| + siphash|siv|sm2|sm3|sm4|whirlpool} + +Build without support for the specified algorithm. + +The `ripemd` algorithm is deprecated and if used is synonymous with `rmd160`. + +### Compiler-specific options + + -Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static + +These system specific options will be recognised and passed through to the +compiler to allow you to define preprocessor symbols, specify additional +libraries, library directories or other compiler options. It might be worth +noting that some compilers generate code specifically for processor the +compiler currently executes on. This is not necessarily what you might have +in mind, since it might be unsuitable for execution on other, typically older, +processor. Consult your compiler documentation. + +Take note of the [Environment Variables](#environment-variables) documentation +below and how these flags interact with those variables. + + -xxx, +xxx, /xxx + +Additional options that are not otherwise recognised are passed through as +they are to the compiler as well. Unix-style options beginning with a +`-` or `+` and Windows-style options beginning with a `/` are recognized. +Again, consult your compiler documentation. + +If the option contains arguments separated by spaces, then the URL-style +notation `%20` can be used for the space character in order to avoid having +to quote the option. For example, `-opt%20arg` gets expanded to `-opt arg`. +In fact, any ASCII character can be encoded as %xx using its hexadecimal +encoding. + +Take note of the [Environment Variables](#environment-variables) documentation +below and how these flags interact with those variables. + +### Environment Variables + + VAR=value + +Assign the given value to the environment variable `VAR` for `Configure`. + +These work just like normal environment variable assignments, but are supported +on all platforms and are confined to the configuration scripts only. +These assignments override the corresponding value in the inherited environment, +if there is one. + +The following variables are used as "`make` variables" and can be used as an +alternative to giving preprocessor, compiler and linker options directly as +configuration. The following variables are supported: + + AR The static library archiver. + ARFLAGS Flags for the static library archiver. + AS The assembler compiler. + ASFLAGS Flags for the assembler compiler. + CC The C compiler. + CFLAGS Flags for the C compiler. + CXX The C++ compiler. + CXXFLAGS Flags for the C++ compiler. + CPP The C/C++ preprocessor. + CPPFLAGS Flags for the C/C++ preprocessor. + CPPDEFINES List of CPP macro definitions, separated + by a platform specific character (':' or + space for Unix, ';' for Windows, ',' for + VMS). This can be used instead of using + -D (or what corresponds to that on your + compiler) in CPPFLAGS. + CPPINCLUDES List of CPP inclusion directories, separated + the same way as for CPPDEFINES. This can + be used instead of -I (or what corresponds + to that on your compiler) in CPPFLAGS. + HASHBANGPERL Perl invocation to be inserted after '#!' + in public perl scripts (only relevant on + Unix). + LD The program linker (not used on Unix, $(CC) + is used there). + LDFLAGS Flags for the shared library, DSO and + program linker. + LDLIBS Extra libraries to use when linking. + Takes the form of a space separated list + of library specifications on Unix and + Windows, and as a comma separated list of + libraries on VMS. + RANLIB The library archive indexer. + RC The Windows resource compiler. + RCFLAGS Flags for the Windows resource compiler. + RM The command to remove files and directories. + +These cannot be mixed with compiling/linking flags given on the command line. +In other words, something like this isn't permitted. + + $ ./Configure -DFOO CPPFLAGS=-DBAR -DCOOKIE + +Backward compatibility note: + +To be compatible with older configuration scripts, the environment variables +are ignored if compiling/linking flags are given on the command line, except +for the following: + + AR, CC, CXX, CROSS_COMPILE, HASHBANGPERL, PERL, RANLIB, RC, and WINDRES + +For example, the following command will not see `-DBAR`: + + $ CPPFLAGS=-DBAR ./Configure -DCOOKIE + +However, the following will see both set variables: + + $ CC=gcc CROSS_COMPILE=x86_64-w64-mingw32- ./Configure -DCOOKIE + +If `CC` is set, it is advisable to also set `CXX` to ensure both the C and C++ +compiler are in the same "family". This becomes relevant with +`enable-external-tests` and `enable-buildtest-c++`. + +### Reconfigure + + reconf + reconfigure + +Reconfigure from earlier data. + +This fetches the previous command line options and environment from data +saved in `configdata.pm` and runs the configuration process again, using +these options and environment. Note: NO other option is permitted together +with `reconf`. Note: The original configuration saves away values for ALL +environment variables that were used, and if they weren't defined, they are +still saved away with information that they weren't originally defined. +This information takes precedence over environment variables that are +defined when reconfiguring. + +Displaying configuration data +----------------------------- + +The configuration script itself will say very little, and finishes by +creating `configdata.pm`. This perl module can be loaded by other scripts +to find all the configuration data, and it can also be used as a script to +display all sorts of configuration data in a human readable form. + +For more information, please do: + + $ ./configdata.pm --help # Unix + +or + + $ perl configdata.pm --help # Windows and VMS + +Installation Steps in Detail +============================ + +Configure OpenSSL +----------------- + +### Automatic Configuration + +In previous version, the `config` script determined the platform type and +compiler and then called `Configure`. Starting with this release, they are +the same. + +#### Unix / Linux / macOS + + $ ./Configure [[ options ]] + +#### OpenVMS + + $ perl Configure [[ options ]] + +#### Windows + + $ perl Configure [[ options ]] + +### Manual Configuration + +OpenSSL knows about a range of different operating system, hardware and +compiler combinations. To see the ones it knows about, run + + $ ./Configure LIST # Unix + +or + + $ perl Configure LIST # All other platforms + +For the remainder of this text, the Unix form will be used in all examples. +Please use the appropriate form for your platform. + +Pick a suitable name from the list that matches your system. For most +operating systems there is a choice between using cc or gcc. +When you have identified your system (and if necessary compiler) use this +name as the argument to `Configure`. For example, a `linux-elf` user would +run: + + $ ./Configure linux-elf [[ options ]] + +### Creating your own Configuration + +If your system isn't listed, you will have to create a configuration +file named `Configurations/{{ something }}.conf` and add the correct +configuration for your system. See the available configs as examples +and read [Configurations/README.md](Configurations/README.md) and +[Configurations/README-design.md](Configurations/README-design.md) +for more information. + +The generic configurations `cc` or `gcc` should usually work on 32 bit +Unix-like systems. + +`Configure` creates a build file (`Makefile` on Unix, `makefile` on Windows +and `descrip.mms` on OpenVMS) from a suitable template in `Configurations/`, +and defines various macros in `include/openssl/configuration.h` (generated +from `include/openssl/configuration.h.in`. + +If none of the generated build files suit your purpose, it's possible to +write your own build file template and give its name through the environment +variable `BUILDFILE`. For example, Ninja build files could be supported by +writing `Configurations/build.ninja.tmpl` and then configure with `BUILDFILE` +set like this (Unix syntax shown, you'll have to adapt for other platforms): + + $ BUILDFILE=build.ninja perl Configure [options...] + +### Out of Tree Builds + +OpenSSL can be configured to build in a build directory separate from the +source code directory. It's done by placing yourself in some other +directory and invoking the configuration commands from there. + +#### Unix example + + $ mkdir /var/tmp/openssl-build + $ cd /var/tmp/openssl-build + $ /PATH/TO/OPENSSL/SOURCE/Configure [[ options ]] + +#### OpenVMS example + + $ set default sys$login: + $ create/dir [.tmp.openssl-build] + $ set default [.tmp.openssl-build] + $ perl D:[PATH.TO.OPENSSL.SOURCE]Configure [[ options ]] + +#### Windows example + + $ C: + $ mkdir \temp-openssl + $ cd \temp-openssl + $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure [[ options ]] + +Paths can be relative just as well as absolute. `Configure` will do its best +to translate them to relative paths whenever possible. + +Build OpenSSL +------------- + +Build OpenSSL by running: + + $ make # Unix + $ mms ! (or mmk) OpenVMS + $ nmake # Windows + +This will build the OpenSSL libraries (`libcrypto.a` and `libssl.a` on +Unix, corresponding on other platforms) and the OpenSSL binary +(`openssl`). The libraries will be built in the top-level directory, +and the binary will be in the `apps/` subdirectory. + +If the build fails, take a look at the [Build Failures](#build-failures) +subsection of the [Troubleshooting](#troubleshooting) section. + +Test OpenSSL +------------ + +After a successful build, and before installing, the libraries should +be tested. Run: + + $ make test # Unix + $ mms test ! OpenVMS + $ nmake test # Windows + +**Warning:** you MUST run the tests from an unprivileged account (or disable +your privileges temporarily if your platform allows it). + +See [test/README.md](test/README.md) for further details how run tests. + +See [test/README-dev.md](test/README-dev.md) for guidelines on adding tests. + +Install OpenSSL +--------------- + +If everything tests ok, install OpenSSL with + + $ make install # Unix + $ mms install ! OpenVMS + $ nmake install # Windows + +Note that in order to perform the install step above you need to have +appropriate permissions to write to the installation directory. + +The above commands will install all the software components in this +directory tree under `` (the directory given with `--prefix` or +its default): + +### Unix / Linux / macOS + + bin/ Contains the openssl binary and a few other + utility scripts. + include/openssl + Contains the header files needed if you want + to build your own programs that use libcrypto + or libssl. + lib Contains the OpenSSL library files. + lib/engines Contains the OpenSSL dynamically loadable engines. + + share/man/man1 Contains the OpenSSL command line man-pages. + share/man/man3 Contains the OpenSSL library calls man-pages. + share/man/man5 Contains the OpenSSL configuration format man-pages. + share/man/man7 Contains the OpenSSL other misc man-pages. + + share/doc/openssl/html/man1 + share/doc/openssl/html/man3 + share/doc/openssl/html/man5 + share/doc/openssl/html/man7 + Contains the HTML rendition of the man-pages. + +### OpenVMS + +'arch' is replaced with the architecture name, `ALPHA` or `IA64`, +'sover' is replaced with the shared library version (`0101` for 1.1), and +'pz' is replaced with the pointer size OpenSSL was built with: + + [.EXE.'arch'] Contains the openssl binary. + [.EXE] Contains a few utility scripts. + [.include.openssl] + Contains the header files needed if you want + to build your own programs that use libcrypto + or libssl. + [.LIB.'arch'] Contains the OpenSSL library files. + [.ENGINES'sover''pz'.'arch'] + Contains the OpenSSL dynamically loadable engines. + [.SYS$STARTUP] Contains startup, login and shutdown scripts. + These define appropriate logical names and + command symbols. + [.SYSTEST] Contains the installation verification procedure. + [.HTML] Contains the HTML rendition of the manual pages. + +### Additional Directories + +Additionally, install will add the following directories under +OPENSSLDIR (the directory given with `--openssldir` or its default) +for you convenience: + + certs Initially empty, this is the default location + for certificate files. + private Initially empty, this is the default location + for private key files. + misc Various scripts. + +The installation directory should be appropriately protected to ensure +unprivileged users cannot make changes to OpenSSL binaries or files, or +install engines. If you already have a pre-installed version of OpenSSL as +part of your Operating System it is recommended that you do not overwrite +the system version and instead install to somewhere else. + +Package builders who want to configure the library for standard locations, +but have the package installed somewhere else so that it can easily be +packaged, can use + + $ make DESTDIR=/tmp/package-root install # Unix + $ mms/macro="DESTDIR=TMP:[PACKAGE-ROOT]" install ! OpenVMS + +The specified destination directory will be prepended to all installation +target paths. + +Compatibility issues with previous OpenSSL versions +--------------------------------------------------- + +### COMPILING existing applications + +Starting with version 1.1.0, OpenSSL hides a number of structures that were +previously open. This includes all internal libssl structures and a number +of EVP types. Accessor functions have been added to allow controlled access +to the structures' data. + +This means that some software needs to be rewritten to adapt to the new ways +of doing things. This often amounts to allocating an instance of a structure +explicitly where you could previously allocate them on the stack as automatic +variables, and using the provided accessor functions where you would previously +access a structure's field directly. + +Some APIs have changed as well. However, older APIs have been preserved when +possible. + +Post-installation Notes +----------------------- + +With the default OpenSSL installation comes a FIPS provider module, which +needs some post-installation attention, without which it will not be usable. +This involves using the following command: + + $ openssl fipsinstall + +See the openssl-fipsinstall(1) manual for details and examples. + +Advanced Build Options +====================== + +Environment Variables +--------------------- + +A number of environment variables can be used to provide additional control +over the build process. Typically these should be defined prior to running +`Configure`. Not all environment variables are relevant to all platforms. + + AR + The name of the ar executable to use. + + BUILDFILE + Use a different build file name than the platform default + ("Makefile" on Unix-like platforms, "makefile" on native Windows, + "descrip.mms" on OpenVMS). This requires that there is a + corresponding build file template. + See [Configurations/README.md](Configurations/README.md) + for further information. + + CC + The compiler to use. Configure will attempt to pick a default + compiler for your platform but this choice can be overridden + using this variable. Set it to the compiler executable you wish + to use, e.g. gcc or clang. + + CROSS_COMPILE + This environment variable has the same meaning as for the + "--cross-compile-prefix" Configure flag described above. If both + are set then the Configure flag takes precedence. + + HASHBANGPERL + The command string for the Perl executable to insert in the + #! line of perl scripts that will be publicly installed. + Default: /usr/bin/env perl + Note: the value of this variable is added to the same scripts + on all platforms, but it's only relevant on Unix-like platforms. + + KERNEL_BITS + This can be the value `32` or `64` to specify the architecture + when it is not "obvious" to the configuration. It should generally + not be necessary to specify this environment variable. + + NM + The name of the nm executable to use. + + OPENSSL_LOCAL_CONFIG_DIR + OpenSSL comes with a database of information about how it + should be built on different platforms as well as build file + templates for those platforms. The database is comprised of + ".conf" files in the Configurations directory. The build + file templates reside there as well as ".tmpl" files. See the + file [Configurations/README.md](Configurations/README.md) + for further information about the format of ".conf" files + as well as information on the ".tmpl" files. + In addition to the standard ".conf" and ".tmpl" files, it is + possible to create your own ".conf" and ".tmpl" files and + store them locally, outside the OpenSSL source tree. + This environment variable can be set to the directory where + these files are held and will be considered by Configure + before it looks in the standard directories. + + PERL + The name of the Perl executable to use when building OpenSSL. + Only needed if builing should use a different Perl executable + than what is used to run the Configure script. + + RANLIB + The name of the ranlib executable to use. + + RC + The name of the rc executable to use. The default will be as + defined for the target platform in the ".conf" file. If not + defined then "windres" will be used. The WINDRES environment + variable is synonymous to this. If both are defined then RC + takes precedence. + + WINDRES + See RC. + +Makefile Targets +---------------- + +The `Configure` script generates a Makefile in a format relevant to the specific +platform. The Makefiles provide a number of targets that can be used. Not all +targets may be available on all platforms. Only the most common targets are +described here. Examine the Makefiles themselves for the full list. + + all + The target to build all the software components and + documentation. + + build_sw + Build all the software components. + THIS IS THE DEFAULT TARGET. + + build_docs + Build all documentation components. + + clean + Remove all build artefacts and return the directory to a "clean" + state. + + depend + Rebuild the dependencies in the Makefiles. This is a legacy + option that no longer needs to be used since OpenSSL 1.1.0. + + install + Install all OpenSSL components. + + install_sw + Only install the OpenSSL software components. + + install_docs + Only install the OpenSSL documentation components. + + install_man_docs + Only install the OpenSSL man pages (Unix only). + + install_html_docs + Only install the OpenSSL HTML documentation. + + install_fips + Install the FIPS provider module configuration file. + + list-tests + Prints a list of all the self test names. + + test + Build and run the OpenSSL self tests. + + uninstall + Uninstall all OpenSSL components. + + reconfigure + reconf + Re-run the configuration process, as exactly as the last time + as possible. + + update + This is a developer option. If you are developing a patch for + OpenSSL you may need to use this if you want to update + automatically generated files; add new error codes or add new + (or change the visibility of) public API functions. (Unix only). + +Running Selected Tests +---------------------- + +You can specify a set of tests to be performed +using the `make` variable `TESTS`. + +See the section [Running Selected Tests of +test/README.md](test/README.md#running-selected-tests). + +Troubleshooting +=============== + +Configuration Problems +---------------------- + +### Selecting the correct target + +The `./Configure` script tries hard to guess your operating system, but in some +cases it does not succeed. You will see a message like the following: + + $ ./Configure + Operating system: x86-whatever-minix + This system (minix) is not supported. See file INSTALL.md for details. + +Even if the automatic target selection by the `./Configure` script fails, +chances are that you still might find a suitable target in the `Configurations` +directory, which you can supply to the `./Configure` command, +possibly after some adjustment. + +The `Configurations/` directory contains a lot of examples of such targets. +The main configuration file is [10-main.conf], which contains all targets that +are officially supported by the OpenSSL team. Other configuration files contain +targets contributed by other OpenSSL users. The list of targets can be found in +a Perl list `my %targets = ( ... )`. + + my %targets = ( + ... + "target-name" => { + inherit_from => [ "base-target" ], + CC => "...", + cflags => add("..."), + asm_arch => '...', + perlasm_scheme => "...", + }, + ... + ) + +If you call `./Configure` without arguments, it will give you a list of all +known targets. Using `grep`, you can lookup the target definition in the +`Configurations/` directory. For example the `android-x86_64` can be found in +[Configurations/15-android.conf](Configurations/15-android.conf). + +The directory contains two README files, which explain the general syntax and +design of the configuration files. + + - [Configurations/README.md](Configurations/README.md) + - [Configurations/README-design.md](Configurations/README-design.md) + +If you need further help, try to search the [openssl-users] mailing list +or the [GitHub Issues] for existing solutions. If you don't find anything, +you can [raise an issue] to ask a question yourself. + +More about our support resources can be found in the [SUPPORT] file. + +### Configuration Errors + +If the `./Configure` or `./Configure` command fails with an error message, +read the error message carefully and try to figure out whether you made +a mistake (e.g., by providing a wrong option), or whether the script is +working incorrectly. If you think you encountered a bug, please +[raise an issue] on GitHub to file a bug report. + +Along with a short description of the bug, please provide the complete +configure command line and the relevant output including the error message. + +Note: To make the output readable, pleace add a 'code fence' (three backquotes +` ``` ` on a separate line) before and after your output: + + ``` + ./Configure [your arguments...] + + [output...] + + ``` + +Build Failures +-------------- + +If the build fails, look carefully at the output. Try to locate and understand +the error message. It might be that the compiler is already telling you +exactly what you need to do to fix your problem. + +There may be reasons for the failure that aren't problems in OpenSSL itself, +for example if the compiler reports missing standard or third party headers. + +If the build succeeded previously, but fails after a source or configuration +change, it might be helpful to clean the build tree before attempting another +build. Use this command: + + $ make clean # Unix + $ mms clean ! (or mmk) OpenVMS + $ nmake clean # Windows + +Assembler error messages can sometimes be sidestepped by using the `no-asm` +configuration option. See also [notes](#notes-on-assembler-modules-compilation). + +Compiling parts of OpenSSL with gcc and others with the system compiler will +result in unresolved symbols on some systems. + +If you are still having problems, try to search the [openssl-users] mailing +list or the [GitHub Issues] for existing solutions. If you think you +encountered an OpenSSL bug, please [raise an issue] to file a bug report. +Please take the time to review the existing issues first; maybe the bug was +already reported or has already been fixed. + +Test Failures +------------- + +If some tests fail, look at the output. There may be reasons for the failure +that isn't a problem in OpenSSL itself (like an OS malfunction or a Perl issue). + +You may want increased verbosity, that can be accomplished as described in +section [Test Failures of test/README.md](test/README.md#test-failures). + +You may also want to selectively specify which test(s) to perform. This can be +done using the `make` variable `TESTS` as described in section [Running +Selected Tests of test/README.md](test/README.md#running-selected-tests). + +If you find a problem with OpenSSL itself, try removing any +compiler optimization flags from the `CFLAGS` line in the Makefile and +run `make clean; make` or corresponding. + +To report a bug please open an issue on GitHub, at +. + +Notes +===== + +Notes on multi-threading +------------------------ + +For some systems, the OpenSSL `Configure` script knows what compiler options +are needed to generate a library that is suitable for multi-threaded +applications. On these systems, support for multi-threading is enabled +by default; use the `no-threads` option to disable (this should never be +necessary). + +On other systems, to enable support for multi-threading, you will have +to specify at least two options: `threads`, and a system-dependent option. +(The latter is `-D_REENTRANT` on various systems.) The default in this +case, obviously, is not to include support for multi-threading (but +you can still use `no-threads` to suppress an annoying warning message +from the `Configure` script.) + +OpenSSL provides built-in support for two threading models: pthreads (found on +most UNIX/Linux systems), and Windows threads. No other threading models are +supported. If your platform does not provide pthreads or Windows threads then +you should use `Configure` with the `no-threads` option. + +For pthreads, all locks are non-recursive. In addition, in a debug build, +the mutex attribute `PTHREAD_MUTEX_ERRORCHECK` is used. If this is not +available on your platform, you might have to add +`-DOPENSSL_NO_MUTEX_ERRORCHECK` to your `Configure` invocation. +(On Linux `PTHREAD_MUTEX_ERRORCHECK` is an enum value, so a built-in +ifdef test cannot be used.) + +Notes on shared libraries +------------------------- + +For most systems the OpenSSL `Configure` script knows what is needed to +build shared libraries for libcrypto and libssl. On these systems +the shared libraries will be created by default. This can be suppressed and +only static libraries created by using the `no-shared` option. On systems +where OpenSSL does not know how to build shared libraries the `no-shared` +option will be forced and only static libraries will be created. + +Shared libraries are named a little differently on different platforms. +One way or another, they all have the major OpenSSL version number as +part of the file name, i.e. for OpenSSL 1.1.x, `1.1` is somehow part of +the name. + +On most POSIX platforms, shared libraries are named `libcrypto.so.1.1` +and `libssl.so.1.1`. + +on Cygwin, shared libraries are named `cygcrypto-1.1.dll` and `cygssl-1.1.dll` +with import libraries `libcrypto.dll.a` and `libssl.dll.a`. + +On Windows build with MSVC or using MingW, shared libraries are named +`libcrypto-1_1.dll` and `libssl-1_1.dll` for 32-bit Windows, +`libcrypto-1_1-x64.dll` and `libssl-1_1-x64.dll` for 64-bit x86_64 Windows, +and `libcrypto-1_1-ia64.dll` and `libssl-1_1-ia64.dll` for IA64 Windows. +With MSVC, the import libraries are named `libcrypto.lib` and `libssl.lib`, +while with MingW, they are named `libcrypto.dll.a` and `libssl.dll.a`. + +On VMS, shareable images (VMS speak for shared libraries) are named +`ossl$libcrypto0101_shr.exe` and `ossl$libssl0101_shr.exe`. However, when +OpenSSL is specifically built for 32-bit pointers, the shareable images +are named `ossl$libcrypto0101_shr32.exe` and `ossl$libssl0101_shr32.exe` +instead, and when built for 64-bit pointers, they are named +`ossl$libcrypto0101_shr64.exe` and `ossl$libssl0101_shr64.exe`. + +Notes on random number generation +--------------------------------- + +Availability of cryptographically secure random numbers is required for +secret key generation. OpenSSL provides several options to seed the +internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse +to deliver random bytes and a "PRNG not seeded error" will occur. + +The seeding method can be configured using the `--with-rand-seed` option, +which can be used to specify a comma separated list of seed methods. +However, in most cases OpenSSL will choose a suitable default method, +so it is not necessary to explicitly provide this option. Note also +that not all methods are available on all platforms. The FIPS provider will +silently ignore seed sources that were not validated. + +I) On operating systems which provide a suitable randomness source (in +form of a system call or system device), OpenSSL will use the optimal +available method to seed the CSPRNG from the operating system's +randomness sources. This corresponds to the option `--with-rand-seed=os`. + +II) On systems without such a suitable randomness source, automatic seeding +and reseeding is disabled (`--with-rand-seed=none`) and it may be necessary +to install additional support software to obtain a random seed and reseed +the CSPRNG manually. Please check out the manual pages for `RAND_add()`, +`RAND_bytes()`, `RAND_egd()`, and the FAQ for more information. + +Notes on assembler modules compilation +-------------------------------------- + +Compilation of some code paths in assembler modules might depend on whether the +current assembler version supports certain ISA extensions or not. Code paths +that use the AES-NI, PCLMULQDQ, SSSE3, and SHA extensions are always assembled. +Apart from that, the minimum requirements for the assembler versions are shown +in the table below: + +| ISA extension | GNU as | nasm | llvm | +|---------------|--------|--------|---------| +| AVX | 2.19 | 2.09 | 3.0 | +| AVX2 | 2.22 | 2.10 | 3.1 | +| ADCX/ADOX | 2.23 | 2.10 | 3.3 | +| AVX512 | 2.25 | 2.11.8 | 3.6 (*) | +| AVX512IFMA | 2.26 | 2.11.8 | 6.0 (*) | +| VAES | 2.30 | 2.13.3 | 6.0 (*) | + +--- + +(*) Even though AVX512 support was implemented in llvm 3.6, prior to version 7.0 +an explicit -march flag was apparently required to compile assembly modules. But +then the compiler generates processor-specific code, which in turn contradicts +the idea of performing dispatch at run-time, which is facilitated by the special +variable `OPENSSL_ia32cap`. For versions older than 7.0, it is possible to work +around the problem by forcing the build procedure to use the following script: + + #!/bin/sh + exec clang -no-integrated-as "$@" + +instead of the real clang. In which case it doesn't matter what clang version +is used, as it is the version of the GNU assembler that will be checked. + +--- + + + +[openssl-users]: + + +[SUPPORT]: + ./SUPPORT.md + +[GitHub Issues]: + + +[raise an issue]: + + +[10-main.conf]: + Configurations/10-main.conf diff --git a/LICENSE b/LICENSE deleted file mode 100644 --- a/LICENSE +++ /dev/null @@ -1,125 +0,0 @@ - - LICENSE ISSUES - ============== - - The OpenSSL toolkit stays under a double license, i.e. both the conditions of - the OpenSSL License and the original SSLeay license apply to the toolkit. - See below for the actual license texts. - - OpenSSL License - --------------- - -/* ==================================================================== - * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - - Original SSLeay License - ----------------------- - -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/NEWS b/NEWS deleted file mode 100644 --- a/NEWS +++ /dev/null @@ -1,1045 +0,0 @@ - - NEWS - ==== - - This file gives a brief overview of the major changes between each OpenSSL - release. For more details please read the CHANGES file. - - Major changes between OpenSSL 1.1.1s and OpenSSL 1.1.1t [7 Feb 2023] - - o Fixed X.400 address type confusion in X.509 GeneralName (CVE-2023-0286) - o Fixed Use-after-free following BIO_new_NDEF (CVE-2023-0215) - o Fixed Double free after calling PEM_read_bio_ex (CVE-2022-4450) - o Fixed Timing Oracle in RSA Decryption (CVE-2022-4304) - - Major changes between OpenSSL 1.1.1r and OpenSSL 1.1.1s [1 Nov 2022] - - o Fixed a regression introduced in OpenSSL 1.1.1r not refreshing the - certificate data to be signed before signing the certificate. - - Major changes between OpenSSL 1.1.1q and OpenSSL 1.1.1r [11 Oct 2022] - - o Added a missing header for memcmp that caused compilation failure on - some platforms - - Major changes between OpenSSL 1.1.1p and OpenSSL 1.1.1q [5 Jul 2022] - - o Fixed AES OCB failure to encrypt some bytes on 32-bit x86 platforms - (CVE-2022-2097) - - Major changes between OpenSSL 1.1.1o and OpenSSL 1.1.1p [21 Jun 2022] - - o Fixed additional bugs in the c_rehash script which was not properly - sanitising shell metacharacters to prevent command injection - (CVE-2022-2068) - - Major changes between OpenSSL 1.1.1n and OpenSSL 1.1.1o [3 May 2022] - - o Fixed a bug in the c_rehash script which was not properly sanitising - shell metacharacters to prevent command injection (CVE-2022-1292) - - Major changes between OpenSSL 1.1.1m and OpenSSL 1.1.1n [15 Mar 2022] - - o Fixed a bug in the BN_mod_sqrt() function that can cause it to loop - forever for non-prime moduli (CVE-2022-0778) - - Major changes between OpenSSL 1.1.1l and OpenSSL 1.1.1m [14 Dec 2021] - - o None - - Major changes between OpenSSL 1.1.1k and OpenSSL 1.1.1l [24 Aug 2021] - - o Fixed an SM2 Decryption Buffer Overflow (CVE-2021-3711) - o Fixed various read buffer overruns processing ASN.1 strings (CVE-2021-3712) - - Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [25 Mar 2021] - - o Fixed a problem with verifying a certificate chain when using the - X509_V_FLAG_X509_STRICT flag (CVE-2021-3450) - o Fixed an issue where an OpenSSL TLS server may crash if sent a - maliciously crafted renegotiation ClientHello message from a client - (CVE-2021-3449) - - Major changes between OpenSSL 1.1.1i and OpenSSL 1.1.1j [16 Feb 2021] - - o Fixed a NULL pointer deref in the X509_issuer_and_serial_hash() - function (CVE-2021-23841) - o Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING - padding mode to correctly check for rollback attacks - o Fixed an overflow in the EVP_CipherUpdate, EVP_EncryptUpdate and - EVP_DecryptUpdate functions (CVE-2021-23840) - o Fixed SRP_Calc_client_key so that it runs in constant time - - Major changes between OpenSSL 1.1.1h and OpenSSL 1.1.1i [8 Dec 2020] - - o Fixed NULL pointer deref in GENERAL_NAME_cmp (CVE-2020-1971) - - Major changes between OpenSSL 1.1.1g and OpenSSL 1.1.1h [22 Sep 2020] - - o Disallow explicit curve parameters in verifications chains when - X509_V_FLAG_X509_STRICT is used - o Enable 'MinProtocol' and 'MaxProtocol' to configure both TLS and DTLS - contexts - o Oracle Developer Studio will start reporting deprecation warnings - - Major changes between OpenSSL 1.1.1f and OpenSSL 1.1.1g [21 Apr 2020] - - o Fixed segmentation fault in SSL_check_chain() (CVE-2020-1967) - - Major changes between OpenSSL 1.1.1e and OpenSSL 1.1.1f [31 Mar 2020] - - o Revert the unexpected EOF reporting via SSL_ERROR_SSL - - Major changes between OpenSSL 1.1.1d and OpenSSL 1.1.1e [17 Mar 2020] - - o Fixed an overflow bug in the x64_64 Montgomery squaring procedure - used in exponentiation with 512-bit moduli (CVE-2019-1551) - o Properly detect unexpected EOF while reading in libssl and report - it via SSL_ERROR_SSL - - Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019] - - o Fixed a fork protection issue (CVE-2019-1549) - o Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey - (CVE-2019-1563) - o For built-in EC curves, ensure an EC_GROUP built from the curve name is - used even when parsing explicit parameters - o Compute ECC cofactors if not provided during EC_GROUP construction - (CVE-2019-1547) - o Early start up entropy quality from the DEVRANDOM seed source has been - improved for older Linux systems - o Correct the extended master secret constant on EBCDIC systems - o Use Windows installation paths in the mingw builds (CVE-2019-1552) - o Changed DH_check to accept parameters with order q and 2q subgroups - o Significantly reduce secure memory usage by the randomness pools - o Revert the DEVRANDOM_WAIT feature for Linux systems - - Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019] - - o Prevent over long nonces in ChaCha20-Poly1305 (CVE-2019-1543) - - Major changes between OpenSSL 1.1.1a and OpenSSL 1.1.1b [26 Feb 2019] - - o Change the info callback signals for the start and end of a post-handshake - message exchange in TLSv1.3. - o Fix a bug in DTLS over SCTP. This breaks interoperability with older versions - of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. - - Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018] - - o Timing vulnerability in DSA signature generation (CVE-2018-0734) - o Timing vulnerability in ECDSA signature generation (CVE-2018-0735) - - Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018] - - o Support for TLSv1.3 added (see https://wiki.openssl.org/index.php/TLS1.3 - for further important information). The TLSv1.3 implementation includes: - o Fully compliant implementation of RFC8446 (TLSv1.3) on by default - o Early data (0-RTT) - o Post-handshake authentication and key update - o Middlebox Compatibility Mode - o TLSv1.3 PSKs - o Support for all five RFC8446 ciphersuites - o RSA-PSS signature algorithms (backported to TLSv1.2) - o Configurable session ticket support - o Stateless server support - o Rewrite of the packet construction code for "safer" packet handling - o Rewrite of the extension handling code - o Complete rewrite of the OpenSSL random number generator to introduce the - following capabilities - o The default RAND method now utilizes an AES-CTR DRBG according to - NIST standard SP 800-90Ar1. - o Support for multiple DRBG instances with seed chaining. - o There is a public and private DRBG instance. - o The DRBG instances are fork-safe. - o Keep all global DRBG instances on the secure heap if it is enabled. - o The public and private DRBG instance are per thread for lock free - operation - o Support for various new cryptographic algorithms including: - o SHA3 - o SHA512/224 and SHA512/256 - o EdDSA (both Ed25519 and Ed448) including X509 and TLS support - o X448 (adding to the existing X25519 support in 1.1.0) - o Multi-prime RSA - o SM2 - o SM3 - o SM4 - o SipHash - o ARIA (including TLS support) - o Significant Side-Channel attack security improvements - o Add a new ClientHello callback to provide the ability to adjust the SSL - object at an early stage. - o Add 'Maximum Fragment Length' TLS extension negotiation and support - o A new STORE module, which implements a uniform and URI based reader of - stores that can contain keys, certificates, CRLs and numerous other - objects. - o Move the display of configuration data to configdata.pm. - o Allow GNU style "make variables" to be used with Configure. - o Claim the namespaces OSSL and OPENSSL, represented as symbol prefixes - o Rewrite of devcrypto engine - - Major changes between OpenSSL 1.1.0h and OpenSSL 1.1.0i [under development] - - o Client DoS due to large DH parameter (CVE-2018-0732) - o Cache timing vulnerability in RSA Key Generation (CVE-2018-0737) - - Major changes between OpenSSL 1.1.0g and OpenSSL 1.1.0h [under development] - - o Constructed ASN.1 types with a recursive definition could exceed the - stack (CVE-2018-0739) - o Incorrect CRYPTO_memcmp on HP-UX PA-RISC (CVE-2018-0733) - o rsaz_1024_mul_avx2 overflow bug on x86_64 (CVE-2017-3738) - - Major changes between OpenSSL 1.1.0f and OpenSSL 1.1.0g [2 Nov 2017] - - o bn_sqrx8x_internal carry bug on x86_64 (CVE-2017-3736) - o Malformed X.509 IPAddressFamily could cause OOB read (CVE-2017-3735) - - Major changes between OpenSSL 1.1.0e and OpenSSL 1.1.0f [25 May 2017] - - o config now recognises 64-bit mingw and chooses mingw64 instead of mingw - - Major changes between OpenSSL 1.1.0d and OpenSSL 1.1.0e [16 Feb 2017] - - o Encrypt-Then-Mac renegotiation crash (CVE-2017-3733) - - Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017] - - o Truncated packet could crash via OOB read (CVE-2017-3731) - o Bad (EC)DHE parameters cause a client crash (CVE-2017-3730) - o BN_mod_exp may produce incorrect results on x86_64 (CVE-2017-3732) - - Major changes between OpenSSL 1.1.0b and OpenSSL 1.1.0c [10 Nov 2016] - - o ChaCha20/Poly1305 heap-buffer-overflow (CVE-2016-7054) - o CMS Null dereference (CVE-2016-7053) - o Montgomery multiplication may produce incorrect results (CVE-2016-7055) - - Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016] - - o Fix Use After Free for large message sizes (CVE-2016-6309) - - Major changes between OpenSSL 1.1.0 and OpenSSL 1.1.0a [22 Sep 2016] - - o OCSP Status Request extension unbounded memory growth (CVE-2016-6304) - o SSL_peek() hang on empty record (CVE-2016-6305) - o Excessive allocation of memory in tls_get_message_header() - (CVE-2016-6307) - o Excessive allocation of memory in dtls1_preprocess_fragment() - (CVE-2016-6308) - - Major changes between OpenSSL 1.0.2h and OpenSSL 1.1.0 [25 Aug 2016] - - o Copyright text was shrunk to a boilerplate that points to the license - o "shared" builds are now the default when possible - o Added support for "pipelining" - o Added the AFALG engine - o New threading API implemented - o Support for ChaCha20 and Poly1305 added to libcrypto and libssl - o Support for extended master secret - o CCM ciphersuites - o Reworked test suite, now based on perl, Test::Harness and Test::More - o *Most* libcrypto and libssl public structures were made opaque, - including: - BIGNUM and associated types, EC_KEY and EC_KEY_METHOD, - DH and DH_METHOD, DSA and DSA_METHOD, RSA and RSA_METHOD, - BIO and BIO_METHOD, EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, - EVP_CIPHER, EVP_PKEY and associated types, HMAC_CTX, - X509, X509_CRL, X509_OBJECT, X509_STORE_CTX, X509_STORE, - X509_LOOKUP, X509_LOOKUP_METHOD - o libssl internal structures made opaque - o SSLv2 support removed - o Kerberos ciphersuite support removed - o RC4 removed from DEFAULT ciphersuites in libssl - o 40 and 56 bit cipher support removed from libssl - o All public header files moved to include/openssl, no more symlinking - o SSL/TLS state machine, version negotiation and record layer rewritten - o EC revision: now operations use new EC_KEY_METHOD. - o Support for OCB mode added to libcrypto - o Support for asynchronous crypto operations added to libcrypto and libssl - o Deprecated interfaces can now be disabled at build time either - relative to the latest release via the "no-deprecated" Configure - argument, or via the "--api=1.1.0|1.0.0|0.9.8" option. - o Application software can be compiled with -DOPENSSL_API_COMPAT=version - to ensure that features deprecated in that version are not exposed. - o Support for RFC6698/RFC7671 DANE TLSA peer authentication - o Change of Configure to use --prefix as the main installation - directory location rather than --openssldir. The latter becomes - the directory for certs, private key and openssl.cnf exclusively. - o Reworked BIO networking library, with full support for IPv6. - o New "unified" build system - o New security levels - o Support for scrypt algorithm - o Support for X25519 - o Extended SSL_CONF support using configuration files - o KDF algorithm support. Implement TLS PRF as a KDF. - o Support for Certificate Transparency - o HKDF support. - - Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016] - - o Prevent padding oracle in AES-NI CBC MAC check (CVE-2016-2107) - o Fix EVP_EncodeUpdate overflow (CVE-2016-2105) - o Fix EVP_EncryptUpdate overflow (CVE-2016-2106) - o Prevent ASN.1 BIO excessive memory allocation (CVE-2016-2109) - o EBCDIC overread (CVE-2016-2176) - o Modify behavior of ALPN to invoke callback after SNI/servername - callback, such that updates to the SSL_CTX affect ALPN. - o Remove LOW from the DEFAULT cipher list. This removes singles DES from - the default. - o Only remove the SSLv2 methods with the no-ssl2-method option. - - Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016] - - o Disable weak ciphers in SSLv3 and up in default builds of OpenSSL. - o Disable SSLv2 default build, default negotiation and weak ciphers - (CVE-2016-0800) - o Fix a double-free in DSA code (CVE-2016-0705) - o Disable SRP fake user seed to address a server memory leak - (CVE-2016-0798) - o Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption - (CVE-2016-0797) - o Fix memory issues in BIO_*printf functions (CVE-2016-0799) - o Fix side channel attack on modular exponentiation (CVE-2016-0702) - - Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016] - - o DH small subgroups (CVE-2016-0701) - o SSLv2 doesn't block disabled ciphers (CVE-2015-3197) - - Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015] - - o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193) - o Certificate verify crash with missing PSS parameter (CVE-2015-3194) - o X509_ATTRIBUTE memory leak (CVE-2015-3195) - o Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs - o In DSA_generate_parameters_ex, if the provided seed is too short, - return an error - - Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015] - - o Alternate chains certificate forgery (CVE-2015-1793) - o Race condition handling PSK identify hint (CVE-2015-3196) - - Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015] - - o Fix HMAC ABI incompatibility - - Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015] - - o Malformed ECParameters causes infinite loop (CVE-2015-1788) - o Exploitable out-of-bounds read in X509_cmp_time (CVE-2015-1789) - o PKCS7 crash with missing EnvelopedContent (CVE-2015-1790) - o CMS verify infinite loop with unknown hash function (CVE-2015-1792) - o Race condition handling NewSessionTicket (CVE-2015-1791) - - Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015] - - o OpenSSL 1.0.2 ClientHello sigalgs DoS fix (CVE-2015-0291) - o Multiblock corrupted pointer fix (CVE-2015-0290) - o Segmentation fault in DTLSv1_listen fix (CVE-2015-0207) - o Segmentation fault in ASN1_TYPE_cmp fix (CVE-2015-0286) - o Segmentation fault for invalid PSS parameters fix (CVE-2015-0208) - o ASN.1 structure reuse memory corruption fix (CVE-2015-0287) - o PKCS7 NULL pointer dereferences fix (CVE-2015-0289) - o DoS via reachable assert in SSLv2 servers fix (CVE-2015-0293) - o Empty CKE with client auth and DHE fix (CVE-2015-1787) - o Handshake with unseeded PRNG fix (CVE-2015-0285) - o Use After Free following d2i_ECPrivatekey error fix (CVE-2015-0209) - o X509_to_X509_REQ NULL pointer deref fix (CVE-2015-0288) - o Removed the export ciphers from the DEFAULT ciphers - - Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]: - - o Suite B support for TLS 1.2 and DTLS 1.2 - o Support for DTLS 1.2 - o TLS automatic EC curve selection. - o API to set TLS supported signature algorithms and curves - o SSL_CONF configuration API. - o TLS Brainpool support. - o ALPN support. - o CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH. - - Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015] - - o Build fixes for the Windows and OpenVMS platforms - - Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015] - - o Fix for CVE-2014-3571 - o Fix for CVE-2015-0206 - o Fix for CVE-2014-3569 - o Fix for CVE-2014-3572 - o Fix for CVE-2015-0204 - o Fix for CVE-2015-0205 - o Fix for CVE-2014-8275 - o Fix for CVE-2014-3570 - - Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014] - - o Fix for CVE-2014-3513 - o Fix for CVE-2014-3567 - o Mitigation for CVE-2014-3566 (SSL protocol vulnerability) - o Fix for CVE-2014-3568 - - Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014] - - o Fix for CVE-2014-3512 - o Fix for CVE-2014-3511 - o Fix for CVE-2014-3510 - o Fix for CVE-2014-3507 - o Fix for CVE-2014-3506 - o Fix for CVE-2014-3505 - o Fix for CVE-2014-3509 - o Fix for CVE-2014-5139 - o Fix for CVE-2014-3508 - - Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014] - - o Fix for CVE-2014-0224 - o Fix for CVE-2014-0221 - o Fix for CVE-2014-0198 - o Fix for CVE-2014-0195 - o Fix for CVE-2014-3470 - o Fix for CVE-2010-5298 - - Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014] - - o Fix for CVE-2014-0160 - o Add TLS padding extension workaround for broken servers. - o Fix for CVE-2014-0076 - - Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014] - - o Don't include gmt_unix_time in TLS server and client random values - o Fix for TLS record tampering bug CVE-2013-4353 - o Fix for TLS version checking bug CVE-2013-6449 - o Fix for DTLS retransmission bug CVE-2013-6450 - - Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013]: - - o Corrected fix for CVE-2013-0169 - - Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013]: - - o Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version. - o Include the fips configuration module. - o Fix OCSP bad key DoS attack CVE-2013-0166 - o Fix for SSL/TLS/DTLS CBC plaintext recovery attack CVE-2013-0169 - o Fix for TLS AESNI record handling flaw CVE-2012-2686 - - Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c [10 May 2012]: - - o Fix TLS/DTLS record length checking bug CVE-2012-2333 - o Don't attempt to use non-FIPS composite ciphers in FIPS mode. - - Major changes between OpenSSL 1.0.1a and OpenSSL 1.0.1b [26 Apr 2012]: - - o Fix compilation error on non-x86 platforms. - o Make FIPS capable OpenSSL ciphers work in non-FIPS mode. - o Fix SSL_OP_NO_TLSv1_1 clash with SSL_OP_ALL in OpenSSL 1.0.0 - - Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a [19 Apr 2012]: - - o Fix for ASN1 overflow bug CVE-2012-2110 - o Workarounds for some servers that hang on long client hellos. - o Fix SEGV in AES code. - - Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012]: - - o TLS/DTLS heartbeat support. - o SCTP support. - o RFC 5705 TLS key material exporter. - o RFC 5764 DTLS-SRTP negotiation. - o Next Protocol Negotiation. - o PSS signatures in certificates, requests and CRLs. - o Support for password based recipient info for CMS. - o Support TLS v1.2 and TLS v1.1. - o Preliminary FIPS capability for unvalidated 2.0 FIPS module. - o SRP support. - - Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012]: - - o Fix for CMS/PKCS#7 MMA CVE-2012-0884 - o Corrected fix for CVE-2011-4619 - o Various DTLS fixes. - - Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012]: - - o Fix for DTLS DoS issue CVE-2012-0050 - - Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012]: - - o Fix for DTLS plaintext recovery attack CVE-2011-4108 - o Clear block padding bytes of SSL 3.0 records CVE-2011-4576 - o Only allow one SGC handshake restart for SSL/TLS CVE-2011-4619 - o Check parameters are not NULL in GOST ENGINE CVE-2012-0027 - o Check for malformed RFC3779 data CVE-2011-4577 - - Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011]: - - o Fix for CRL vulnerability issue CVE-2011-3207 - o Fix for ECDH crashes CVE-2011-3210 - o Protection against EC timing attacks. - o Support ECDH ciphersuites for certificates using SHA2 algorithms. - o Various DTLS fixes. - - Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011]: - - o Fix for security issue CVE-2011-0014 - - Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010]: - - o Fix for security issue CVE-2010-4180 - o Fix for CVE-2010-4252 - o Fix mishandling of absent EC point format extension. - o Fix various platform compilation issues. - o Corrected fix for security issue CVE-2010-3864. - - Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010]: - - o Fix for security issue CVE-2010-3864. - o Fix for CVE-2010-2939 - o Fix WIN32 build system for GOST ENGINE. - - Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010]: - - o Fix for security issue CVE-2010-1633. - o GOST MAC and CFB fixes. - - Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010]: - - o RFC3280 path validation: sufficient to process PKITS tests. - o Integrated support for PVK files and keyblobs. - o Change default private key format to PKCS#8. - o CMS support: able to process all examples in RFC4134 - o Streaming ASN1 encode support for PKCS#7 and CMS. - o Multiple signer and signer add support for PKCS#7 and CMS. - o ASN1 printing support. - o Whirlpool hash algorithm added. - o RFC3161 time stamp support. - o New generalised public key API supporting ENGINE based algorithms. - o New generalised public key API utilities. - o New ENGINE supporting GOST algorithms. - o SSL/TLS GOST ciphersuite support. - o PKCS#7 and CMS GOST support. - o RFC4279 PSK ciphersuite support. - o Supported points format extension for ECC ciphersuites. - o ecdsa-with-SHA224/256/384/512 signature types. - o dsa-with-SHA224 and dsa-with-SHA256 signature types. - o Opaque PRF Input TLS extension support. - o Updated time routines to avoid OS limitations. - - Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010]: - - o CFB cipher definition fixes. - o Fix security issues CVE-2010-0740 and CVE-2010-0433. - - Major changes between OpenSSL 0.9.8l and OpenSSL 0.9.8m [25 Feb 2010]: - - o Cipher definition fixes. - o Workaround for slow RAND_poll() on some WIN32 versions. - o Remove MD2 from algorithm tables. - o SPKAC handling fixes. - o Support for RFC5746 TLS renegotiation extension. - o Compression memory leak fixed. - o Compression session resumption fixed. - o Ticket and SNI coexistence fixes. - o Many fixes to DTLS handling. - - Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009]: - - o Temporary work around for CVE-2009-3555: disable renegotiation. - - Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009]: - - o Fix various build issues. - o Fix security issues (CVE-2009-0590, CVE-2009-0591, CVE-2009-0789) - - Major changes between OpenSSL 0.9.8i and OpenSSL 0.9.8j [7 Jan 2009]: - - o Fix security issue (CVE-2008-5077) - o Merge FIPS 140-2 branch code. - - Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008]: - - o CryptoAPI ENGINE support. - o Various precautionary measures. - o Fix for bugs affecting certificate request creation. - o Support for local machine keyset attribute in PKCS#12 files. - - Major changes between OpenSSL 0.9.8f and OpenSSL 0.9.8g [19 Oct 2007]: - - o Backport of CMS functionality to 0.9.8. - o Fixes for bugs introduced with 0.9.8f. - - Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007]: - - o Add gcc 4.2 support. - o Add support for AES and SSE2 assembly language optimization - for VC++ build. - o Support for RFC4507bis and server name extensions if explicitly - selected at compile time. - o DTLS improvements. - o RFC4507bis support. - o TLS Extensions support. - - Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007]: - - o Various ciphersuite selection fixes. - o RFC3779 support. - - Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006]: - - o Introduce limits to prevent malicious key DoS (CVE-2006-2940) - o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343) - o Changes to ciphersuite selection algorithm - - Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006]: - - o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339 - o New cipher Camellia - - Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006]: - - o Cipher string fixes. - o Fixes for VC++ 2005. - o Updated ECC cipher suite support. - o New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free(). - o Zlib compression usage fixes. - o Built in dynamic engine compilation support on Win32. - o Fixes auto dynamic engine loading in Win32. - - Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005]: - - o Fix potential SSL 2.0 rollback, CVE-2005-2969 - o Extended Windows CE support - - Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005]: - - o Major work on the BIGNUM library for higher efficiency and to - make operations more streamlined and less contradictory. This - is the result of a major audit of the BIGNUM library. - o Addition of BIGNUM functions for fields GF(2^m) and NIST - curves, to support the Elliptic Crypto functions. - o Major work on Elliptic Crypto; ECDH and ECDSA added, including - the use through EVP, X509 and ENGINE. - o New ASN.1 mini-compiler that's usable through the OpenSSL - configuration file. - o Added support for ASN.1 indefinite length constructed encoding. - o New PKCS#12 'medium level' API to manipulate PKCS#12 files. - o Complete rework of shared library construction and linking - programs with shared or static libraries, through a separate - Makefile.shared. - o Rework of the passing of parameters from one Makefile to another. - o Changed ENGINE framework to load dynamic engine modules - automatically from specifically given directories. - o New structure and ASN.1 functions for CertificatePair. - o Changed the ZLIB compression method to be stateful. - o Changed the key-generation and primality testing "progress" - mechanism to take a structure that contains the ticker - function and an argument. - o New engine module: GMP (performs private key exponentiation). - o New engine module: VIA PadLOck ACE extension in VIA C3 - Nehemiah processors. - o Added support for IPv6 addresses in certificate extensions. - See RFC 1884, section 2.2. - o Added support for certificate policy mappings, policy - constraints and name constraints. - o Added support for multi-valued AVAs in the OpenSSL - configuration file. - o Added support for multiple certificates with the same subject - in the 'openssl ca' index file. - o Make it possible to create self-signed certificates using - 'openssl ca -selfsign'. - o Make it possible to generate a serial number file with - 'openssl ca -create_serial'. - o New binary search functions with extended functionality. - o New BUF functions. - o New STORE structure and library to provide an interface to all - sorts of data repositories. Supports storage of public and - private keys, certificates, CRLs, numbers and arbitrary blobs. - This library is unfortunately unfinished and unused within - OpenSSL. - o New control functions for the error stack. - o Changed the PKCS#7 library to support one-pass S/MIME - processing. - o Added the possibility to compile without old deprecated - functionality with the OPENSSL_NO_DEPRECATED macro or the - 'no-deprecated' argument to the config and Configure scripts. - o Constification of all ASN.1 conversion functions, and other - affected functions. - o Improved platform support for PowerPC. - o New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512). - o New X509_VERIFY_PARAM structure to support parameterisation - of X.509 path validation. - o Major overhaul of RC4 performance on Intel P4, IA-64 and - AMD64. - o Changed the Configure script to have some algorithms disabled - by default. Those can be explicitly enabled with the new - argument form 'enable-xxx'. - o Change the default digest in 'openssl' commands from MD5 to - SHA-1. - o Added support for DTLS. - o New BIGNUM blinding. - o Added support for the RSA-PSS encryption scheme - o Added support for the RSA X.931 padding. - o Added support for BSD sockets on NetWare. - o Added support for files larger than 2GB. - o Added initial support for Win64. - o Added alternate pkg-config files. - - Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007]: - - o FIPS 1.1.1 module linking. - o Various ciphersuite selection fixes. - - Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006]: - - o Introduce limits to prevent malicious key DoS (CVE-2006-2940) - o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343) - - Major changes between OpenSSL 0.9.7j and OpenSSL 0.9.7k [5 Sep 2006]: - - o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339 - - Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006]: - - o Visual C++ 2005 fixes. - o Update Windows build system for FIPS. - - Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]: - - o Give EVP_MAX_MD_SIZE its old value, except for a FIPS build. - - Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]: - - o Fix SSL 2.0 Rollback, CVE-2005-2969 - o Allow use of fixed-length exponent on DSA signing - o Default fixed-window RSA, DSA, DH private-key operations - - Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005]: - - o More compilation issues fixed. - o Adaptation to more modern Kerberos API. - o Enhanced or corrected configuration for Solaris64, Mingw and Cygwin. - o Enhanced x86_64 assembler BIGNUM module. - o More constification. - o Added processing of proxy certificates (RFC 3820). - - Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005]: - - o Several compilation issues fixed. - o Many memory allocation failure checks added. - o Improved comparison of X509 Name type. - o Mandatory basic checks on certificates. - o Performance improvements. - - Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004]: - - o Fix race condition in CRL checking code. - o Fixes to PKCS#7 (S/MIME) code. - - Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004]: - - o Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug - o Security: Fix null-pointer assignment in do_change_cipher_spec() - o Allow multiple active certificates with same subject in CA index - o Multiple X509 verification fixes - o Speed up HMAC and other operations - - Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003]: - - o Security: fix various ASN1 parsing bugs. - o New -ignore_err option to OCSP utility. - o Various interop and bug fixes in S/MIME code. - o SSL/TLS protocol fix for unrequested client certificates. - - Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003]: - - o Security: counter the Klima-Pokorny-Rosa extension of - Bleichbacher's attack - o Security: make RSA blinding default. - o Configuration: Irix fixes, AIX fixes, better mingw support. - o Support for new platforms: linux-ia64-ecc. - o Build: shared library support fixes. - o ASN.1: treat domainComponent correctly. - o Documentation: fixes and additions. - - Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003]: - - o Security: Important security related bugfixes. - o Enhanced compatibility with MIT Kerberos. - o Can be built without the ENGINE framework. - o IA32 assembler enhancements. - o Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64. - o Configuration: the no-err option now works properly. - o SSL/TLS: now handles manual certificate chain building. - o SSL/TLS: certain session ID malfunctions corrected. - - Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002]: - - o New library section OCSP. - o Complete rewrite of ASN1 code. - o CRL checking in verify code and openssl utility. - o Extension copying in 'ca' utility. - o Flexible display options in 'ca' utility. - o Provisional support for international characters with UTF8. - o Support for external crypto devices ('engine') is no longer - a separate distribution. - o New elliptic curve library section. - o New AES (Rijndael) library section. - o Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit, - Linux x86_64, Linux 64-bit on Sparc v9 - o Extended support for some platforms: VxWorks - o Enhanced support for shared libraries. - o Now only builds PIC code when shared library support is requested. - o Support for pkg-config. - o Lots of new manuals. - o Makes symbolic links to or copies of manuals to cover all described - functions. - o Change DES API to clean up the namespace (some applications link also - against libdes providing similar functions having the same name). - Provide macros for backward compatibility (will be removed in the - future). - o Unify handling of cryptographic algorithms (software and engine) - to be available via EVP routines for asymmetric and symmetric ciphers. - o NCONF: new configuration handling routines. - o Change API to use more 'const' modifiers to improve error checking - and help optimizers. - o Finally remove references to RSAref. - o Reworked parts of the BIGNUM code. - o Support for new engines: Broadcom ubsec, Accelerated Encryption - Processing, IBM 4758. - o A few new engines added in the demos area. - o Extended and corrected OID (object identifier) table. - o PRNG: query at more locations for a random device, automatic query for - EGD style random sources at several locations. - o SSL/TLS: allow optional cipher choice according to server's preference. - o SSL/TLS: allow server to explicitly set new session ids. - o SSL/TLS: support Kerberos cipher suites (RFC2712). - Only supports MIT Kerberos for now. - o SSL/TLS: allow more precise control of renegotiations and sessions. - o SSL/TLS: add callback to retrieve SSL/TLS messages. - o SSL/TLS: support AES cipher suites (RFC3268). - - Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003]: - - o Security: fix various ASN1 parsing bugs. - o SSL/TLS protocol fix for unrequested client certificates. - - Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003]: - - o Security: counter the Klima-Pokorny-Rosa extension of - Bleichbacher's attack - o Security: make RSA blinding default. - o Build: shared library support fixes. - - Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003]: - - o Important security related bugfixes. - - Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002]: - - o New configuration targets for Tandem OSS and A/UX. - o New OIDs for Microsoft attributes. - o Better handling of SSL session caching. - o Better comparison of distinguished names. - o Better handling of shared libraries in a mixed GNU/non-GNU environment. - o Support assembler code with Borland C. - o Fixes for length problems. - o Fixes for uninitialised variables. - o Fixes for memory leaks, some unusual crashes and some race conditions. - o Fixes for smaller building problems. - o Updates of manuals, FAQ and other instructive documents. - - Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002]: - - o Important building fixes on Unix. - - Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002]: - - o Various important bugfixes. - - Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002]: - - o Important security related bugfixes. - o Various SSL/TLS library bugfixes. - - Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002]: - - o Various SSL/TLS library bugfixes. - o Fix DH parameter generation for 'non-standard' generators. - - Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001]: - - o Various SSL/TLS library bugfixes. - o BIGNUM library fixes. - o RSA OAEP and random number generation fixes. - o Object identifiers corrected and added. - o Add assembler BN routines for IA64. - o Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8, - MIPS Linux; shared library support for Irix, HP-UX. - o Add crypto accelerator support for AEP, Baltimore SureWare, - Broadcom and Cryptographic Appliance's keyserver - [in 0.9.6c-engine release]. - - Major changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b [9 Jul 2001]: - - o Security fix: PRNG improvements. - o Security fix: RSA OAEP check. - o Security fix: Reinsert and fix countermeasure to Bleichbacher's - attack. - o MIPS bug fix in BIGNUM. - o Bug fix in "openssl enc". - o Bug fix in X.509 printing routine. - o Bug fix in DSA verification routine and DSA S/MIME verification. - o Bug fix to make PRNG thread-safe. - o Bug fix in RAND_file_name(). - o Bug fix in compatibility mode trust settings. - o Bug fix in blowfish EVP. - o Increase default size for BIO buffering filter. - o Compatibility fixes in some scripts. - - Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001]: - - o Security fix: change behavior of OpenSSL to avoid using - environment variables when running as root. - o Security fix: check the result of RSA-CRT to reduce the - possibility of deducing the private key from an incorrectly - calculated signature. - o Security fix: prevent Bleichenbacher's DSA attack. - o Security fix: Zero the premaster secret after deriving the - master secret in DH ciphersuites. - o Reimplement SSL_peek(), which had various problems. - o Compatibility fix: the function des_encrypt() renamed to - des_encrypt1() to avoid clashes with some Unixen libc. - o Bug fixes for Win32, HP/UX and Irix. - o Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and - memory checking routines. - o Bug fixes for RSA operations in threaded environments. - o Bug fixes in misc. openssl applications. - o Remove a few potential memory leaks. - o Add tighter checks of BIGNUM routines. - o Shared library support has been reworked for generality. - o More documentation. - o New function BN_rand_range(). - o Add "-rand" option to openssl s_client and s_server. - - Major changes between OpenSSL 0.9.5a and OpenSSL 0.9.6 [10 Oct 2000]: - - o Some documentation for BIO and SSL libraries. - o Enhanced chain verification using key identifiers. - o New sign and verify options to 'dgst' application. - o Support for DER and PEM encoded messages in 'smime' application. - o New 'rsautl' application, low level RSA utility. - o MD4 now included. - o Bugfix for SSL rollback padding check. - o Support for external crypto devices [1]. - o Enhanced EVP interface. - - [1] The support for external crypto devices is currently a separate - distribution. See the file README.ENGINE. - - Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000]: - - o Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8 - o Shared library support for HPUX and Solaris-gcc - o Support of Linux/IA64 - o Assembler support for Mingw32 - o New 'rand' application - o New way to check for existence of algorithms from scripts - - Major changes between OpenSSL 0.9.4 and OpenSSL 0.9.5 [25 May 2000]: - - o S/MIME support in new 'smime' command - o Documentation for the OpenSSL command line application - o Automation of 'req' application - o Fixes to make s_client, s_server work under Windows - o Support for multiple fieldnames in SPKACs - o New SPKAC command line utility and associated library functions - o Options to allow passwords to be obtained from various sources - o New public key PEM format and options to handle it - o Many other fixes and enhancements to command line utilities - o Usable certificate chain verification - o Certificate purpose checking - o Certificate trust settings - o Support of authority information access extension - o Extensions in certificate requests - o Simplified X509 name and attribute routines - o Initial (incomplete) support for international character sets - o New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD - o Read only memory BIOs and simplified creation function - o TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0 - record; allow fragmentation and interleaving of handshake and other - data - o TLS/SSL code now "tolerates" MS SGC - o Work around for Netscape client certificate hang bug - o RSA_NULL option that removes RSA patent code but keeps other - RSA functionality - o Memory leak detection now allows applications to add extra information - via a per-thread stack - o PRNG robustness improved - o EGD support - o BIGNUM library bug fixes - o Faster DSA parameter generation - o Enhanced support for Alpha Linux - o Experimental MacOS support - - Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999]: - - o Transparent support for PKCS#8 format private keys: these are used - by several software packages and are more secure than the standard - form - o PKCS#5 v2.0 implementation - o Password callbacks have a new void * argument for application data - o Avoid various memory leaks - o New pipe-like BIO that allows using the SSL library when actual I/O - must be handled by the application (BIO pair) - - Major changes between OpenSSL 0.9.2b and OpenSSL 0.9.3 [24 May 1999]: - o Lots of enhancements and cleanups to the Configuration mechanism - o RSA OEAP related fixes - o Added `openssl ca -revoke' option for revoking a certificate - o Source cleanups: const correctness, type-safe stacks and ASN.1 SETs - o Source tree cleanups: removed lots of obsolete files - o Thawte SXNet, certificate policies and CRL distribution points - extension support - o Preliminary (experimental) S/MIME support - o Support for ASN.1 UTF8String and VisibleString - o Full integration of PKCS#12 code - o Sparc assembler bignum implementation, optimized hash functions - o Option to disable selected ciphers - - Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999]: - o Fixed a security hole related to session resumption - o Fixed RSA encryption routines for the p < q case - o "ALL" in cipher lists now means "everything except NULL ciphers" - o Support for Triple-DES CBCM cipher - o Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA - o First support for new TLSv1 ciphers - o Added a few new BIOs (syslog BIO, reliable BIO) - o Extended support for DSA certificate/keys. - o Extended support for Certificate Signing Requests (CSR) - o Initial support for X.509v3 extensions - o Extended support for compression inside the SSL record layer - o Overhauled Win32 builds - o Cleanups and fixes to the Big Number (BN) library - o Support for ASN.1 GeneralizedTime - o Splitted ASN.1 SETs from SEQUENCEs - o ASN1 and PEM support for Netscape Certificate Sequences - o Overhauled Perl interface - o Lots of source tree cleanups. - o Lots of memory leak fixes. - o Lots of bug fixes. - - Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998]: - o Integration of the popular NO_RSA/NO_DSA patches - o Initial support for compression inside the SSL record layer - o Added BIO proxy and filtering functionality - o Extended Big Number (BN) library - o Added RIPE MD160 message digest - o Added support for RC2/64bit cipher - o Extended ASN.1 parser routines - o Adjustments of the source tree for CVS - o Support for various new platforms diff --git a/NEWS.md b/NEWS.md new file mode 100644 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,1586 @@ +NEWS +==== + +This file gives a brief overview of the major changes between each OpenSSL +release. For more details please read the CHANGES file. + +OpenSSL Releases +---------------- + + - [OpenSSL 3.0](#openssl-30) + - [OpenSSL 1.1.1](#openssl-111) + - [OpenSSL 1.1.0](#openssl-110) + - [OpenSSL 1.0.2](#openssl-102) + - [OpenSSL 1.0.1](#openssl-101) + - [OpenSSL 1.0.0](#openssl-100) + - [OpenSSL 0.9.x](#openssl-09x) + +OpenSSL 3.0 +----------- + +### Major changes between OpenSSL 3.0.7 and OpenSSL 3.0.8 [7 Feb 2023] + + * Fixed NULL dereference during PKCS7 data verification ([CVE-2023-0401]) + * Fixed X.400 address type confusion in X.509 GeneralName ([CVE-2023-0286]) + * Fixed NULL dereference validating DSA public key ([CVE-2023-0217]) + * Fixed Invalid pointer dereference in d2i_PKCS7 functions ([CVE-2023-0216]) + * Fixed Use-after-free following BIO_new_NDEF ([CVE-2023-0215]) + * Fixed Double free after calling PEM_read_bio_ex ([CVE-2022-4450]) + * Fixed Timing Oracle in RSA Decryption ([CVE-2022-4304]) + * Fixed X.509 Name Constraints Read Buffer Overflow ([CVE-2022-4203]) + * Fixed X.509 Policy Constraints Double Locking ([CVE-2022-3996]) + +### Major changes between OpenSSL 3.0.6 and OpenSSL 3.0.7 [1 Nov 2022] + + * Added RIPEMD160 to the default provider. + * Fixed regressions introduced in 3.0.6 version. + * Fixed two buffer overflows in punycode decoding functions. + ([CVE-2022-3786]) and ([CVE-2022-3602]) + +### Major changes between OpenSSL 3.0.5 and OpenSSL 3.0.6 [11 Oct 2022] + + * Fix for custom ciphers to prevent accidental use of NULL encryption + ([CVE-2022-3358]) + +### Major changes between OpenSSL 3.0.4 and OpenSSL 3.0.5 [5 Jul 2022] + + * Fixed heap memory corruption with RSA private key operation + ([CVE-2022-2274]) + * Fixed AES OCB failure to encrypt some bytes on 32-bit x86 platforms + ([CVE-2022-2097]) + +### Major changes between OpenSSL 3.0.3 and OpenSSL 3.0.4 [21 Jun 2022] + + * Fixed additional bugs in the c_rehash script which was not properly + sanitising shell metacharacters to prevent command injection + ([CVE-2022-2068]) + +### Major changes between OpenSSL 3.0.2 and OpenSSL 3.0.3 [3 May 2022] + + * Fixed a bug in the c_rehash script which was not properly sanitising shell + metacharacters to prevent command injection ([CVE-2022-1292]) + * Fixed a bug in the function `OCSP_basic_verify` that verifies the signer + certificate on an OCSP response ([CVE-2022-1343]) + * Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the + AAD data as the MAC key ([CVE-2022-1434]) + * Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory + occuppied by the removed hash table entries ([CVE-2022-1473]) + +### Major changes between OpenSSL 3.0.1 and OpenSSL 3.0.2 [15 Mar 2022] + + * Fixed a bug in the BN_mod_sqrt() function that can cause it to loop forever + for non-prime moduli ([CVE-2022-0778]) + +### Major changes between OpenSSL 3.0.0 and OpenSSL 3.0.1 [14 Dec 2021] + + * Fixed invalid handling of X509_verify_cert() internal errors in libssl + ([CVE-2021-4044]) + * Allow fetching an operation from the provider that owns an unexportable key + as a fallback if that is still allowed by the property query. + +### Major changes between OpenSSL 1.1.1 and OpenSSL 3.0.0 [7 sep 2021] + + * Enhanced 'openssl list' with many new options. + * Added migration guide to man7. + * Implemented support for fully "pluggable" TLSv1.3 groups. + * Added suport for Kernel TLS (KTLS). + * Changed the license to the Apache License v2.0. + * Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, + RC4, RC5, and DES to the legacy provider. + * Moved the EVP digests MD2, MD4, MDC2, WHIRLPOOL and RIPEMD-160 to the legacy + provider. + * Added convenience functions for generating asymmetric key pairs. + * Deprecated the `OCSP_REQ_CTX` type and functions. + * Deprecated the `EC_KEY` and `EC_KEY_METHOD` types and functions. + * Deprecated the `RSA` and `RSA_METHOD` types and functions. + * Deprecated the `DSA` and `DSA_METHOD` types and functions. + * Deprecated the `DH` and `DH_METHOD` types and functions. + * Deprecated the `ERR_load_` functions. + * Remove the `RAND_DRBG` API. + * Deprecated the `ENGINE` API. + * Added `OSSL_LIB_CTX`, a libcrypto library context. + * Added various `_ex` functions to the OpenSSL API that support using + a non-default `OSSL_LIB_CTX`. + * Interactive mode is removed from the 'openssl' program. + * The X25519, X448, Ed25519, Ed448, SHAKE128 and SHAKE256 algorithms are + included in the FIPS provider. + * X509 certificates signed using SHA1 are no longer allowed at security + level 1 or higher. The default security level for TLS is 1, so + certificates signed using SHA1 are by default no longer trusted to + authenticate servers or clients. + * enable-crypto-mdebug and enable-crypto-mdebug-backtrace were mostly + disabled; the project uses address sanitize/leak-detect instead. + * Added a Certificate Management Protocol (CMP, RFC 4210) implementation + also covering CRMF (RFC 4211) and HTTP transfer (RFC 6712). + It is part of the crypto lib and adds a 'cmp' app with a demo configuration. + All widely used CMP features are supported for both clients and servers. + * Added a proper HTTP client supporting GET with optional redirection, POST, + arbitrary request and response content types, TLS, persistent connections, + connections via HTTP(s) proxies, connections and exchange via user-defined + BIOs (allowing implicit connections), and timeout checks. + * Added util/check-format.pl for checking adherence to the coding guidelines. + * Added OSSL_ENCODER, a generic encoder API. + * Added OSSL_DECODER, a generic decoder API. + * Added OSSL_PARAM_BLD, an easier to use API to OSSL_PARAM. + * Added error raising macros, ERR_raise() and ERR_raise_data(). + * Deprecated ERR_put_error(), ERR_get_error_line(), ERR_get_error_line_data(), + ERR_peek_error_line_data(), ERR_peek_last_error_line_data() and + ERR_func_error_string(). + * Added OSSL_PROVIDER_available(), to check provider availibility. + * Added 'openssl mac' that uses the EVP_MAC API. + * Added 'openssl kdf' that uses the EVP_KDF API. + * Add OPENSSL_info() and 'openssl info' to get built-in data. + * Add support for enabling instrumentation through trace and debug + output. + * Changed our version number scheme and set the next major release to + 3.0.0 + * Added EVP_MAC, an EVP layer MAC API, and a generic EVP_PKEY to EVP_MAC + bridge. Supported MACs are: BLAKE2, CMAC, GMAC, HMAC, KMAC, POLY1305 + and SIPHASH. + * Removed the heartbeat message in DTLS feature. + * Added EVP_KDF, an EVP layer KDF and PRF API, and a generic EVP_PKEY to + EVP_KDF bridge. Supported KDFs are: HKDF, KBKDF, KRB5 KDF, PBKDF2, + PKCS12 KDF, SCRYPT, SSH KDF, SSKDF, TLS1 PRF, X9.42 KDF and X9.63 KDF. + * All of the low-level MD2, MD4, MD5, MDC2, RIPEMD160, SHA1, SHA224, + SHA256, SHA384, SHA512 and Whirlpool digest functions have been + deprecated. + * All of the low-level AES, Blowfish, Camellia, CAST, DES, IDEA, RC2, + RC4, RC5 and SEED cipher functions have been deprecated. + * All of the low-level DH, DSA, ECDH, ECDSA and RSA public key functions + have been deprecated. + * SSL 3, TLS 1.0, TLS 1.1, and DTLS 1.0 only work at security level 0, + except when RSA key exchange without SHA1 is used. + * Added providers, a new pluggability concept that will replace the + ENGINE API and ENGINE implementations. + +OpenSSL 1.1.1 +------------- + +### Major changes between OpenSSL 1.1.1k and OpenSSL 1.1.1l [24 Aug 2021] + + * Fixed an SM2 Decryption Buffer Overflow ([CVE-2021-3711]) + * Fixed various read buffer overruns processing ASN.1 strings ([CVE-2021-3712]) + +### Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [25 Mar 2021] + + * Fixed a problem with verifying a certificate chain when using the + X509_V_FLAG_X509_STRICT flag ([CVE-2021-3450]) + * Fixed an issue where an OpenSSL TLS server may crash if sent a maliciously + crafted renegotiation ClientHello message from a client ([CVE-2021-3449]) + +### Major changes between OpenSSL 1.1.1i and OpenSSL 1.1.1j [16 Feb 2021] + + * Fixed a NULL pointer deref in the X509_issuer_and_serial_hash() + function ([CVE-2021-23841]) + * Fixed the RSA_padding_check_SSLv23() function and the RSA_SSLV23_PADDING + padding mode to correctly check for rollback attacks + * Fixed an overflow in the EVP_CipherUpdate, EVP_EncryptUpdate and + EVP_DecryptUpdate functions ([CVE-2021-23840]) + * Fixed SRP_Calc_client_key so that it runs in constant time + +### Major changes between OpenSSL 1.1.1h and OpenSSL 1.1.1i [8 Dec 2020] + + * Fixed NULL pointer deref in GENERAL_NAME_cmp ([CVE-2020-1971]) + +### Major changes between OpenSSL 1.1.1g and OpenSSL 1.1.1h [22 Sep 2020] + + * Disallow explicit curve parameters in verifications chains when + X509_V_FLAG_X509_STRICT is used + * Enable 'MinProtocol' and 'MaxProtocol' to configure both TLS and DTLS + contexts + * Oracle Developer Studio will start reporting deprecation warnings + +### Major changes between OpenSSL 1.1.1f and OpenSSL 1.1.1g [21 Apr 2020] + + * Fixed segmentation fault in SSL_check_chain() ([CVE-2020-1967]) + +### Major changes between OpenSSL 1.1.1e and OpenSSL 1.1.1f [31 Mar 2020] + + * Revert the unexpected EOF reporting via SSL_ERROR_SSL + +### Major changes between OpenSSL 1.1.1d and OpenSSL 1.1.1e [17 Mar 2020] + + * Fixed an overflow bug in the x64_64 Montgomery squaring procedure + used in exponentiation with 512-bit moduli ([CVE-2019-1551]) + +### Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019] + + * Fixed a fork protection issue ([CVE-2019-1549]) + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey + ([CVE-2019-1563]) + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters + * Compute ECC cofactors if not provided during EC_GROUP construction + ([CVE-2019-1547]) + * Early start up entropy quality from the DEVRANDOM seed source has been + improved for older Linux systems + * Correct the extended master secret constant on EBCDIC systems + * Use Windows installation paths in the mingw builds ([CVE-2019-1552]) + * Changed DH_check to accept parameters with order q and 2q subgroups + * Significantly reduce secure memory usage by the randomness pools + * Revert the DEVRANDOM_WAIT feature for Linux systems + +### Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019] + + * Prevent over long nonces in ChaCha20-Poly1305 ([CVE-2019-1543]) + +### Major changes between OpenSSL 1.1.1a and OpenSSL 1.1.1b [26 Feb 2019] + + * Change the info callback signals for the start and end of a post-handshake + message exchange in TLSv1.3. + * Fix a bug in DTLS over SCTP. This breaks interoperability with older + versions of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. + +### Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018] + + * Timing vulnerability in DSA signature generation ([CVE-2018-0734]) + * Timing vulnerability in ECDSA signature generation ([CVE-2018-0735]) + +### Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018] + + * Support for TLSv1.3 added. The TLSv1.3 implementation includes: + * Fully compliant implementation of RFC8446 (TLSv1.3) on by default + * Early data (0-RTT) + * Post-handshake authentication and key update + * Middlebox Compatibility Mode + * TLSv1.3 PSKs + * Support for all five RFC8446 ciphersuites + * RSA-PSS signature algorithms (backported to TLSv1.2) + * Configurable session ticket support + * Stateless server support + * Rewrite of the packet construction code for "safer" packet handling + * Rewrite of the extension handling code + For further important information, see the [TLS1.3 page]( + https://wiki.openssl.org/index.php/TLS1.3) in the OpenSSL Wiki. + + * Complete rewrite of the OpenSSL random number generator to introduce the + following capabilities + * The default RAND method now utilizes an AES-CTR DRBG according to + NIST standard SP 800-90Ar1. + * Support for multiple DRBG instances with seed chaining. + * There is a public and private DRBG instance. + * The DRBG instances are fork-safe. + * Keep all global DRBG instances on the secure heap if it is enabled. + * The public and private DRBG instance are per thread for lock free + operation + * Support for various new cryptographic algorithms including: + * SHA3 + * SHA512/224 and SHA512/256 + * EdDSA (both Ed25519 and Ed448) including X509 and TLS support + * X448 (adding to the existing X25519 support in 1.1.0) + * Multi-prime RSA + * SM2 + * SM3 + * SM4 + * SipHash + * ARIA (including TLS support) + * Significant Side-Channel attack security improvements + * Add a new ClientHello callback to provide the ability to adjust the SSL + object at an early stage. + * Add 'Maximum Fragment Length' TLS extension negotiation and support + * A new STORE module, which implements a uniform and URI based reader of + stores that can contain keys, certificates, CRLs and numerous other + objects. + * Move the display of configuration data to configdata.pm. + * Allow GNU style "make variables" to be used with Configure. + * Claim the namespaces OSSL and OPENSSL, represented as symbol prefixes + * Rewrite of devcrypto engine + +OpenSSL 1.1.0 +------------- + +### Major changes between OpenSSL 1.1.0k and OpenSSL 1.1.0l [10 Sep 2019] + + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey + ([CVE-2019-1563]) + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters + * Compute ECC cofactors if not provided during EC_GROUP construction + ([CVE-2019-1547]) + * Use Windows installation paths in the mingw builds ([CVE-2019-1552]) + +### Major changes between OpenSSL 1.1.0j and OpenSSL 1.1.0k [28 May 2019] + + * Prevent over long nonces in ChaCha20-Poly1305 ([CVE-2019-1543]) + +### Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.0j [20 Nov 2018] + + * Timing vulnerability in DSA signature generation ([CVE-2018-0734]) + * Timing vulnerability in ECDSA signature generation ([CVE-2018-0735]) + +### Major changes between OpenSSL 1.1.0h and OpenSSL 1.1.0i [14 Aug 2018] + + * Client DoS due to large DH parameter ([CVE-2018-0732]) + * Cache timing vulnerability in RSA Key Generation ([CVE-2018-0737]) + +### Major changes between OpenSSL 1.1.0g and OpenSSL 1.1.0h [27 Mar 2018] + + * Constructed ASN.1 types with a recursive definition could exceed the + stack ([CVE-2018-0739]) + * Incorrect CRYPTO_memcmp on HP-UX PA-RISC ([CVE-2018-0733]) + * rsaz_1024_mul_avx2 overflow bug on x86_64 ([CVE-2017-3738]) + +### Major changes between OpenSSL 1.1.0f and OpenSSL 1.1.0g [2 Nov 2017] + + * bn_sqrx8x_internal carry bug on x86_64 ([CVE-2017-3736]) + * Malformed X.509 IPAddressFamily could cause OOB read ([CVE-2017-3735]) + +### Major changes between OpenSSL 1.1.0e and OpenSSL 1.1.0f [25 May 2017] + + * config now recognises 64-bit mingw and chooses mingw64 instead of mingw + +### Major changes between OpenSSL 1.1.0d and OpenSSL 1.1.0e [16 Feb 2017] + + * Encrypt-Then-Mac renegotiation crash ([CVE-2017-3733]) + +### Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017] + + * Truncated packet could crash via OOB read ([CVE-2017-3731]) + * Bad (EC)DHE parameters cause a client crash ([CVE-2017-3730]) + * BN_mod_exp may produce incorrect results on x86_64 ([CVE-2017-3732]) + +### Major changes between OpenSSL 1.1.0b and OpenSSL 1.1.0c [10 Nov 2016] + + * ChaCha20/Poly1305 heap-buffer-overflow ([CVE-2016-7054]) + * CMS Null dereference ([CVE-2016-7053]) + * Montgomery multiplication may produce incorrect results ([CVE-2016-7055]) + +### Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016] + + * Fix Use After Free for large message sizes ([CVE-2016-6309]) + +### Major changes between OpenSSL 1.1.0 and OpenSSL 1.1.0a [22 Sep 2016] + + * OCSP Status Request extension unbounded memory growth ([CVE-2016-6304]) + * SSL_peek() hang on empty record ([CVE-2016-6305]) + * Excessive allocation of memory in tls_get_message_header() + ([CVE-2016-6307]) + * Excessive allocation of memory in dtls1_preprocess_fragment() + ([CVE-2016-6308]) + +### Major changes between OpenSSL 1.0.2h and OpenSSL 1.1.0 [25 Aug 2016] + + * Copyright text was shrunk to a boilerplate that points to the license + * "shared" builds are now the default when possible + * Added support for "pipelining" + * Added the AFALG engine + * New threading API implemented + * Support for ChaCha20 and Poly1305 added to libcrypto and libssl + * Support for extended master secret + * CCM ciphersuites + * Reworked test suite, now based on perl, Test::Harness and Test::More + * *Most* libcrypto and libssl public structures were made opaque, + including: + BIGNUM and associated types, EC_KEY and EC_KEY_METHOD, + DH and DH_METHOD, DSA and DSA_METHOD, RSA and RSA_METHOD, + BIO and BIO_METHOD, EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, + EVP_CIPHER, EVP_PKEY and associated types, HMAC_CTX, + X509, X509_CRL, X509_OBJECT, X509_STORE_CTX, X509_STORE, + X509_LOOKUP, X509_LOOKUP_METHOD + * libssl internal structures made opaque + * SSLv2 support removed + * Kerberos ciphersuite support removed + * RC4 removed from DEFAULT ciphersuites in libssl + * 40 and 56 bit cipher support removed from libssl + * All public header files moved to include/openssl, no more symlinking + * SSL/TLS state machine, version negotiation and record layer rewritten + * EC revision: now operations use new EC_KEY_METHOD. + * Support for OCB mode added to libcrypto + * Support for asynchronous crypto operations added to libcrypto and libssl + * Deprecated interfaces can now be disabled at build time either + relative to the latest release via the "no-deprecated" Configure + argument, or via the "--api=1.1.0|1.0.0|0.9.8" option. + * Application software can be compiled with -DOPENSSL_API_COMPAT=version + to ensure that features deprecated in that version are not exposed. + * Support for RFC6698/RFC7671 DANE TLSA peer authentication + * Change of Configure to use --prefix as the main installation + directory location rather than --openssldir. The latter becomes + the directory for certs, private key and openssl.cnf exclusively. + * Reworked BIO networking library, with full support for IPv6. + * New "unified" build system + * New security levels + * Support for scrypt algorithm + * Support for X25519 + * Extended SSL_CONF support using configuration files + * KDF algorithm support. Implement TLS PRF as a KDF. + * Support for Certificate Transparency + * HKDF support. + +OpenSSL 1.0.2 +------------- + +### Major changes between OpenSSL 1.0.2s and OpenSSL 1.0.2t [10 Sep 2019] + + * Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey + ([CVE-2019-1563]) + * For built-in EC curves, ensure an EC_GROUP built from the curve name is + used even when parsing explicit parameters + * Compute ECC cofactors if not provided during EC_GROUP construction + ([CVE-2019-1547]) + * Document issue with installation paths in diverse Windows builds + ([CVE-2019-1552]) + +### Major changes between OpenSSL 1.0.2r and OpenSSL 1.0.2s [28 May 2019] + + * None + +### Major changes between OpenSSL 1.0.2q and OpenSSL 1.0.2r [26 Feb 2019] + + * 0-byte record padding oracle ([CVE-2019-1559]) + +### Major changes between OpenSSL 1.0.2p and OpenSSL 1.0.2q [20 Nov 2018] + + * Microarchitecture timing vulnerability in ECC scalar multiplication ([CVE-2018-5407]) + * Timing vulnerability in DSA signature generation ([CVE-2018-0734]) + +### Major changes between OpenSSL 1.0.2o and OpenSSL 1.0.2p [14 Aug 2018] + + * Client DoS due to large DH parameter ([CVE-2018-0732]) + * Cache timing vulnerability in RSA Key Generation ([CVE-2018-0737]) + +### Major changes between OpenSSL 1.0.2n and OpenSSL 1.0.2o [27 Mar 2018] + + * Constructed ASN.1 types with a recursive definition could exceed the + stack ([CVE-2018-0739]) + +### Major changes between OpenSSL 1.0.2m and OpenSSL 1.0.2n [7 Dec 2017] + + * Read/write after SSL object in error state ([CVE-2017-3737]) + * rsaz_1024_mul_avx2 overflow bug on x86_64 ([CVE-2017-3738]) + +### Major changes between OpenSSL 1.0.2l and OpenSSL 1.0.2m [2 Nov 2017] + + * bn_sqrx8x_internal carry bug on x86_64 ([CVE-2017-3736]) + * Malformed X.509 IPAddressFamily could cause OOB read ([CVE-2017-3735]) + +### Major changes between OpenSSL 1.0.2k and OpenSSL 1.0.2l [25 May 2017] + + * config now recognises 64-bit mingw and chooses mingw64 instead of mingw + +### Major changes between OpenSSL 1.0.2j and OpenSSL 1.0.2k [26 Jan 2017] + + * Truncated packet could crash via OOB read ([CVE-2017-3731]) + * BN_mod_exp may produce incorrect results on x86_64 ([CVE-2017-3732]) + * Montgomery multiplication may produce incorrect results ([CVE-2016-7055]) + +### Major changes between OpenSSL 1.0.2i and OpenSSL 1.0.2j [26 Sep 2016] + + * Missing CRL sanity check ([CVE-2016-7052]) + +### Major changes between OpenSSL 1.0.2h and OpenSSL 1.0.2i [22 Sep 2016] + + * OCSP Status Request extension unbounded memory growth ([CVE-2016-6304]) + * SWEET32 Mitigation ([CVE-2016-2183]) + * OOB write in MDC2_Update() ([CVE-2016-6303]) + * Malformed SHA512 ticket DoS ([CVE-2016-6302]) + * OOB write in BN_bn2dec() ([CVE-2016-2182]) + * OOB read in TS_OBJ_print_bio() ([CVE-2016-2180]) + * Pointer arithmetic undefined behaviour ([CVE-2016-2177]) + * Constant time flag not preserved in DSA signing ([CVE-2016-2178]) + * DTLS buffered message DoS ([CVE-2016-2179]) + * DTLS replay protection DoS ([CVE-2016-2181]) + * Certificate message OOB reads ([CVE-2016-6306]) + +### Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016] + + * Prevent padding oracle in AES-NI CBC MAC check ([CVE-2016-2107]) + * Fix EVP_EncodeUpdate overflow ([CVE-2016-2105]) + * Fix EVP_EncryptUpdate overflow ([CVE-2016-2106]) + * Prevent ASN.1 BIO excessive memory allocation ([CVE-2016-2109]) + * EBCDIC overread ([CVE-2016-2176]) + * Modify behavior of ALPN to invoke callback after SNI/servername + callback, such that updates to the SSL_CTX affect ALPN. + * Remove LOW from the DEFAULT cipher list. This removes singles DES from + the default. + * Only remove the SSLv2 methods with the no-ssl2-method option. + +### Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016] + + * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL. + * Disable SSLv2 default build, default negotiation and weak ciphers + ([CVE-2016-0800]) + * Fix a double-free in DSA code ([CVE-2016-0705]) + * Disable SRP fake user seed to address a server memory leak + ([CVE-2016-0798]) + * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption + ([CVE-2016-0797]) + * Fix memory issues in BIO_*printf functions ([CVE-2016-0799]) + * Fix side channel attack on modular exponentiation ([CVE-2016-0702]) + +### Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016] + + * DH small subgroups ([CVE-2016-0701]) + * SSLv2 doesn't block disabled ciphers ([CVE-2015-3197]) + +### Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015] + + * BN_mod_exp may produce incorrect results on x86_64 ([CVE-2015-3193]) + * Certificate verify crash with missing PSS parameter ([CVE-2015-3194]) + * X509_ATTRIBUTE memory leak ([CVE-2015-3195]) + * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs + * In DSA_generate_parameters_ex, if the provided seed is too short, + return an error + +### Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015] + + * Alternate chains certificate forgery ([CVE-2015-1793]) + * Race condition handling PSK identify hint ([CVE-2015-3196]) + +### Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015] + + * Fix HMAC ABI incompatibility + +### Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015] + + * Malformed ECParameters causes infinite loop ([CVE-2015-1788]) + * Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789]) + * PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790]) + * CMS verify infinite loop with unknown hash function ([CVE-2015-1792]) + * Race condition handling NewSessionTicket ([CVE-2015-1791]) + +### Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015] + + * OpenSSL 1.0.2 ClientHello sigalgs DoS fix ([CVE-2015-0291]) + * Multiblock corrupted pointer fix ([CVE-2015-0290]) + * Segmentation fault in DTLSv1_listen fix ([CVE-2015-0207]) + * Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286]) + * Segmentation fault for invalid PSS parameters fix ([CVE-2015-0208]) + * ASN.1 structure reuse memory corruption fix ([CVE-2015-0287]) + * PKCS7 NULL pointer dereferences fix ([CVE-2015-0289]) + * DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293]) + * Empty CKE with client auth and DHE fix ([CVE-2015-1787]) + * Handshake with unseeded PRNG fix ([CVE-2015-0285]) + * Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209]) + * X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288]) + * Removed the export ciphers from the DEFAULT ciphers + +### Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015] + + * Suite B support for TLS 1.2 and DTLS 1.2 + * Support for DTLS 1.2 + * TLS automatic EC curve selection. + * API to set TLS supported signature algorithms and curves + * SSL_CONF configuration API. + * TLS Brainpool support. + * ALPN support. + * CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH. + +OpenSSL 1.0.1 +------------- + +### Major changes between OpenSSL 1.0.1t and OpenSSL 1.0.1u [22 Sep 2016] + + * OCSP Status Request extension unbounded memory growth ([CVE-2016-6304]) + * SWEET32 Mitigation ([CVE-2016-2183]) + * OOB write in MDC2_Update() ([CVE-2016-6303]) + * Malformed SHA512 ticket DoS ([CVE-2016-6302]) + * OOB write in BN_bn2dec() ([CVE-2016-2182]) + * OOB read in TS_OBJ_print_bio() ([CVE-2016-2180]) + * Pointer arithmetic undefined behaviour ([CVE-2016-2177]) + * Constant time flag not preserved in DSA signing ([CVE-2016-2178]) + * DTLS buffered message DoS ([CVE-2016-2179]) + * DTLS replay protection DoS ([CVE-2016-2181]) + * Certificate message OOB reads ([CVE-2016-6306]) + +### Major changes between OpenSSL 1.0.1s and OpenSSL 1.0.1t [3 May 2016] + + * Prevent padding oracle in AES-NI CBC MAC check ([CVE-2016-2107]) + * Fix EVP_EncodeUpdate overflow ([CVE-2016-2105]) + * Fix EVP_EncryptUpdate overflow ([CVE-2016-2106]) + * Prevent ASN.1 BIO excessive memory allocation ([CVE-2016-2109]) + * EBCDIC overread ([CVE-2016-2176]) + * Modify behavior of ALPN to invoke callback after SNI/servername + callback, such that updates to the SSL_CTX affect ALPN. + * Remove LOW from the DEFAULT cipher list. This removes singles DES from + the default. + * Only remove the SSLv2 methods with the no-ssl2-method option. + +### Major changes between OpenSSL 1.0.1r and OpenSSL 1.0.1s [1 Mar 2016] + + * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL. + * Disable SSLv2 default build, default negotiation and weak ciphers + ([CVE-2016-0800]) + * Fix a double-free in DSA code ([CVE-2016-0705]) + * Disable SRP fake user seed to address a server memory leak + ([CVE-2016-0798]) + * Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption + ([CVE-2016-0797]) + * Fix memory issues in BIO_*printf functions ([CVE-2016-0799]) + * Fix side channel attack on modular exponentiation ([CVE-2016-0702]) + +### Major changes between OpenSSL 1.0.1q and OpenSSL 1.0.1r [28 Jan 2016] + + * Protection for DH small subgroup attacks + * SSLv2 doesn't block disabled ciphers ([CVE-2015-3197]) + +### Major changes between OpenSSL 1.0.1p and OpenSSL 1.0.1q [3 Dec 2015] + + * Certificate verify crash with missing PSS parameter ([CVE-2015-3194]) + * X509_ATTRIBUTE memory leak ([CVE-2015-3195]) + * Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs + * In DSA_generate_parameters_ex, if the provided seed is too short, + return an error + +### Major changes between OpenSSL 1.0.1o and OpenSSL 1.0.1p [9 Jul 2015] + + * Alternate chains certificate forgery ([CVE-2015-1793]) + * Race condition handling PSK identify hint ([CVE-2015-3196]) + +### Major changes between OpenSSL 1.0.1n and OpenSSL 1.0.1o [12 Jun 2015] + + * Fix HMAC ABI incompatibility + +### Major changes between OpenSSL 1.0.1m and OpenSSL 1.0.1n [11 Jun 2015] + + * Malformed ECParameters causes infinite loop ([CVE-2015-1788]) + * Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789]) + * PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790]) + * CMS verify infinite loop with unknown hash function ([CVE-2015-1792]) + * Race condition handling NewSessionTicket ([CVE-2015-1791]) + +### Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.1m [19 Mar 2015] + + * Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286]) + * ASN.1 structure reuse memory corruption fix ([CVE-2015-0287]) + * PKCS7 NULL pointer dereferences fix ([CVE-2015-0289]) + * DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293]) + * Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209]) + * X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288]) + * Removed the export ciphers from the DEFAULT ciphers + +### Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015] + + * Build fixes for the Windows and OpenVMS platforms + +### Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015] + + * Fix for [CVE-2014-3571] + * Fix for [CVE-2015-0206] + * Fix for [CVE-2014-3569] + * Fix for [CVE-2014-3572] + * Fix for [CVE-2015-0204] + * Fix for [CVE-2015-0205] + * Fix for [CVE-2014-8275] + * Fix for [CVE-2014-3570] + +### Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014] + + * Fix for [CVE-2014-3513] + * Fix for [CVE-2014-3567] + * Mitigation for [CVE-2014-3566] (SSL protocol vulnerability) + * Fix for [CVE-2014-3568] + +### Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014] + + * Fix for [CVE-2014-3512] + * Fix for [CVE-2014-3511] + * Fix for [CVE-2014-3510] + * Fix for [CVE-2014-3507] + * Fix for [CVE-2014-3506] + * Fix for [CVE-2014-3505] + * Fix for [CVE-2014-3509] + * Fix for [CVE-2014-5139] + * Fix for [CVE-2014-3508] + +### Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014] + + * Fix for [CVE-2014-0224] + * Fix for [CVE-2014-0221] + * Fix for [CVE-2014-0198] + * Fix for [CVE-2014-0195] + * Fix for [CVE-2014-3470] + * Fix for [CVE-2010-5298] + +### Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014] + + * Fix for [CVE-2014-0160] + * Add TLS padding extension workaround for broken servers. + * Fix for [CVE-2014-0076] + +### Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014] + + * Don't include gmt_unix_time in TLS server and client random values + * Fix for TLS record tampering bug ([CVE-2013-4353]) + * Fix for TLS version checking bug ([CVE-2013-6449]) + * Fix for DTLS retransmission bug ([CVE-2013-6450]) + +### Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013] + + * Corrected fix for ([CVE-2013-0169]) + +### Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013] + + * Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version. + * Include the fips configuration module. + * Fix OCSP bad key DoS attack ([CVE-2013-0166]) + * Fix for SSL/TLS/DTLS CBC plaintext recovery attack ([CVE-2013-0169]) + * Fix for TLS AESNI record handling flaw ([CVE-2012-2686]) + +### Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c [10 May 2012] + + * Fix TLS/DTLS record length checking bug ([CVE-2012-2333]) + * Don't attempt to use non-FIPS composite ciphers in FIPS mode. + +### Major changes between OpenSSL 1.0.1a and OpenSSL 1.0.1b [26 Apr 2012] + + * Fix compilation error on non-x86 platforms. + * Make FIPS capable OpenSSL ciphers work in non-FIPS mode. + * Fix SSL_OP_NO_TLSv1_1 clash with SSL_OP_ALL in OpenSSL 1.0.0 + +### Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a [19 Apr 2012] + + * Fix for ASN1 overflow bug ([CVE-2012-2110]) + * Workarounds for some servers that hang on long client hellos. + * Fix SEGV in AES code. + +### Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012] + + * TLS/DTLS heartbeat support. + * SCTP support. + * RFC 5705 TLS key material exporter. + * RFC 5764 DTLS-SRTP negotiation. + * Next Protocol Negotiation. + * PSS signatures in certificates, requests and CRLs. + * Support for password based recipient info for CMS. + * Support TLS v1.2 and TLS v1.1. + * Preliminary FIPS capability for unvalidated 2.0 FIPS module. + * SRP support. + +OpenSSL 1.0.0 +------------- + +### Major changes between OpenSSL 1.0.0s and OpenSSL 1.0.0t [3 Dec 2015] + + * X509_ATTRIBUTE memory leak (([CVE-2015-3195])) + * Race condition handling PSK identify hint ([CVE-2015-3196]) + +### Major changes between OpenSSL 1.0.0r and OpenSSL 1.0.0s [11 Jun 2015] + + * Malformed ECParameters causes infinite loop ([CVE-2015-1788]) + * Exploitable out-of-bounds read in X509_cmp_time ([CVE-2015-1789]) + * PKCS7 crash with missing EnvelopedContent ([CVE-2015-1790]) + * CMS verify infinite loop with unknown hash function ([CVE-2015-1792]) + * Race condition handling NewSessionTicket ([CVE-2015-1791]) + +### Major changes between OpenSSL 1.0.0q and OpenSSL 1.0.0r [19 Mar 2015] + + * Segmentation fault in ASN1_TYPE_cmp fix ([CVE-2015-0286]) + * ASN.1 structure reuse memory corruption fix ([CVE-2015-0287]) + * PKCS7 NULL pointer dereferences fix ([CVE-2015-0289]) + * DoS via reachable assert in SSLv2 servers fix ([CVE-2015-0293]) + * Use After Free following d2i_ECPrivatekey error fix ([CVE-2015-0209]) + * X509_to_X509_REQ NULL pointer deref fix ([CVE-2015-0288]) + * Removed the export ciphers from the DEFAULT ciphers + +### Major changes between OpenSSL 1.0.0p and OpenSSL 1.0.0q [15 Jan 2015] + + * Build fixes for the Windows and OpenVMS platforms + +### Major changes between OpenSSL 1.0.0o and OpenSSL 1.0.0p [8 Jan 2015] + + * Fix for [CVE-2014-3571] + * Fix for [CVE-2015-0206] + * Fix for [CVE-2014-3569] + * Fix for [CVE-2014-3572] + * Fix for [CVE-2015-0204] + * Fix for [CVE-2015-0205] + * Fix for [CVE-2014-8275] + * Fix for [CVE-2014-3570] + +### Major changes between OpenSSL 1.0.0n and OpenSSL 1.0.0o [15 Oct 2014] + + * Fix for [CVE-2014-3513] + * Fix for [CVE-2014-3567] + * Mitigation for [CVE-2014-3566] (SSL protocol vulnerability) + * Fix for [CVE-2014-3568] + +### Major changes between OpenSSL 1.0.0m and OpenSSL 1.0.0n [6 Aug 2014] + + * Fix for [CVE-2014-3510] + * Fix for [CVE-2014-3507] + * Fix for [CVE-2014-3506] + * Fix for [CVE-2014-3505] + * Fix for [CVE-2014-3509] + * Fix for [CVE-2014-3508] + + Known issues in OpenSSL 1.0.0m: + + * EAP-FAST and other applications using tls_session_secret_cb + won't resume sessions. Fixed in 1.0.0n-dev + * Compilation failure of s3_pkt.c on some platforms due to missing + `` include. Fixed in 1.0.0n-dev + +### Major changes between OpenSSL 1.0.0l and OpenSSL 1.0.0m [5 Jun 2014] + + * Fix for [CVE-2014-0224] + * Fix for [CVE-2014-0221] + * Fix for [CVE-2014-0198] + * Fix for [CVE-2014-0195] + * Fix for [CVE-2014-3470] + * Fix for [CVE-2014-0076] + * Fix for [CVE-2010-5298] + +### Major changes between OpenSSL 1.0.0k and OpenSSL 1.0.0l [6 Jan 2014] + + * Fix for DTLS retransmission bug ([CVE-2013-6450]) + +### Major changes between OpenSSL 1.0.0j and OpenSSL 1.0.0k [5 Feb 2013] + + * Fix for SSL/TLS/DTLS CBC plaintext recovery attack ([CVE-2013-0169]) + * Fix OCSP bad key DoS attack ([CVE-2013-0166]) + +### Major changes between OpenSSL 1.0.0i and OpenSSL 1.0.0j [10 May 2012] + + * Fix DTLS record length checking bug ([CVE-2012-2333]) + +### Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.0i [19 Apr 2012] + + * Fix for ASN1 overflow bug ([CVE-2012-2110]) + +### Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012] + + * Fix for CMS/PKCS#7 MMA ([CVE-2012-0884]) + * Corrected fix for ([CVE-2011-4619]) + * Various DTLS fixes. + +### Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012] + + * Fix for DTLS DoS issue ([CVE-2012-0050]) + +### Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012] + + * Fix for DTLS plaintext recovery attack ([CVE-2011-4108]) + * Clear block padding bytes of SSL 3.0 records ([CVE-2011-4576]) + * Only allow one SGC handshake restart for SSL/TLS ([CVE-2011-4619]) + * Check parameters are not NULL in GOST ENGINE ([CVE-2012-0027]) + * Check for malformed RFC3779 data ([CVE-2011-4577]) + +### Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011] + + * Fix for CRL vulnerability issue ([CVE-2011-3207]) + * Fix for ECDH crashes ([CVE-2011-3210]) + * Protection against EC timing attacks. + * Support ECDH ciphersuites for certificates using SHA2 algorithms. + * Various DTLS fixes. + +### Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011] + + * Fix for security issue ([CVE-2011-0014]) + +### Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010] + + * Fix for security issue ([CVE-2010-4180]) + * Fix for ([CVE-2010-4252]) + * Fix mishandling of absent EC point format extension. + * Fix various platform compilation issues. + * Corrected fix for security issue ([CVE-2010-3864]). + +### Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010] + + * Fix for security issue ([CVE-2010-3864]). + * Fix for ([CVE-2010-2939]) + * Fix WIN32 build system for GOST ENGINE. + +### Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010] + + * Fix for security issue ([CVE-2010-1633]). + * GOST MAC and CFB fixes. + +### Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010] + + * RFC3280 path validation: sufficient to process PKITS tests. + * Integrated support for PVK files and keyblobs. + * Change default private key format to PKCS#8. + * CMS support: able to process all examples in RFC4134 + * Streaming ASN1 encode support for PKCS#7 and CMS. + * Multiple signer and signer add support for PKCS#7 and CMS. + * ASN1 printing support. + * Whirlpool hash algorithm added. + * RFC3161 time stamp support. + * New generalised public key API supporting ENGINE based algorithms. + * New generalised public key API utilities. + * New ENGINE supporting GOST algorithms. + * SSL/TLS GOST ciphersuite support. + * PKCS#7 and CMS GOST support. + * RFC4279 PSK ciphersuite support. + * Supported points format extension for ECC ciphersuites. + * ecdsa-with-SHA224/256/384/512 signature types. + * dsa-with-SHA224 and dsa-with-SHA256 signature types. + * Opaque PRF Input TLS extension support. + * Updated time routines to avoid OS limitations. + +OpenSSL 0.9.x +------------- + +### Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010] + + * CFB cipher definition fixes. + * Fix security issues [CVE-2010-0740] and [CVE-2010-0433]. + +### Major changes between OpenSSL 0.9.8l and OpenSSL 0.9.8m [25 Feb 2010] + + * Cipher definition fixes. + * Workaround for slow RAND_poll() on some WIN32 versions. + * Remove MD2 from algorithm tables. + * SPKAC handling fixes. + * Support for RFC5746 TLS renegotiation extension. + * Compression memory leak fixed. + * Compression session resumption fixed. + * Ticket and SNI coexistence fixes. + * Many fixes to DTLS handling. + +### Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009] + + * Temporary work around for [CVE-2009-3555]: disable renegotiation. + +### Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009] + + * Fix various build issues. + * Fix security issues [CVE-2009-0590], [CVE-2009-0591], [CVE-2009-0789] + +### Major changes between OpenSSL 0.9.8i and OpenSSL 0.9.8j [7 Jan 2009] + + * Fix security issue ([CVE-2008-5077]) + * Merge FIPS 140-2 branch code. + +### Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008] + + * CryptoAPI ENGINE support. + * Various precautionary measures. + * Fix for bugs affecting certificate request creation. + * Support for local machine keyset attribute in PKCS#12 files. + +### Major changes between OpenSSL 0.9.8f and OpenSSL 0.9.8g [19 Oct 2007] + + * Backport of CMS functionality to 0.9.8. + * Fixes for bugs introduced with 0.9.8f. + +### Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007] + + * Add gcc 4.2 support. + * Add support for AES and SSE2 assembly language optimization + for VC++ build. + * Support for RFC4507bis and server name extensions if explicitly + selected at compile time. + * DTLS improvements. + * RFC4507bis support. + * TLS Extensions support. + +### Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007] + + * Various ciphersuite selection fixes. + * RFC3779 support. + +### Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006] + + * Introduce limits to prevent malicious key DoS ([CVE-2006-2940]) + * Fix security issues [CVE-2006-2937], [CVE-2006-3737], [CVE-2006-4343] + * Changes to ciphersuite selection algorithm + +### Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006] + + * Fix Daniel Bleichenbacher forged signature attack, [CVE-2006-4339] + * New cipher Camellia + +### Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006] + + * Cipher string fixes. + * Fixes for VC++ 2005. + * Updated ECC cipher suite support. + * New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free(). + * Zlib compression usage fixes. + * Built in dynamic engine compilation support on Win32. + * Fixes auto dynamic engine loading in Win32. + +### Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005] + + * Fix potential SSL 2.0 rollback ([CVE-2005-2969]) + * Extended Windows CE support + +### Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005] + + * Major work on the BIGNUM library for higher efficiency and to + make operations more streamlined and less contradictory. This + is the result of a major audit of the BIGNUM library. + * Addition of BIGNUM functions for fields GF(2^m) and NIST + curves, to support the Elliptic Crypto functions. + * Major work on Elliptic Crypto; ECDH and ECDSA added, including + the use through EVP, X509 and ENGINE. + * New ASN.1 mini-compiler that's usable through the OpenSSL + configuration file. + * Added support for ASN.1 indefinite length constructed encoding. + * New PKCS#12 'medium level' API to manipulate PKCS#12 files. + * Complete rework of shared library construction and linking + programs with shared or static libraries, through a separate + Makefile.shared. + * Rework of the passing of parameters from one Makefile to another. + * Changed ENGINE framework to load dynamic engine modules + automatically from specifically given directories. + * New structure and ASN.1 functions for CertificatePair. + * Changed the ZLIB compression method to be stateful. + * Changed the key-generation and primality testing "progress" + mechanism to take a structure that contains the ticker + function and an argument. + * New engine module: GMP (performs private key exponentiation). + * New engine module: VIA PadLOck ACE extension in VIA C3 + Nehemiah processors. + * Added support for IPv6 addresses in certificate extensions. + See RFC 1884, section 2.2. + * Added support for certificate policy mappings, policy + constraints and name constraints. + * Added support for multi-valued AVAs in the OpenSSL + configuration file. + * Added support for multiple certificates with the same subject + in the 'openssl ca' index file. + * Make it possible to create self-signed certificates using + 'openssl ca -selfsign'. + * Make it possible to generate a serial number file with + 'openssl ca -create_serial'. + * New binary search functions with extended functionality. + * New BUF functions. + * New STORE structure and library to provide an interface to all + sorts of data repositories. Supports storage of public and + private keys, certificates, CRLs, numbers and arbitrary blobs. + This library is unfortunately unfinished and unused within + OpenSSL. + * New control functions for the error stack. + * Changed the PKCS#7 library to support one-pass S/MIME + processing. + * Added the possibility to compile without old deprecated + functionality with the OPENSSL_NO_DEPRECATED macro or the + 'no-deprecated' argument to the config and Configure scripts. + * Constification of all ASN.1 conversion functions, and other + affected functions. + * Improved platform support for PowerPC. + * New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512). + * New X509_VERIFY_PARAM structure to support parameterisation + of X.509 path validation. + * Major overhaul of RC4 performance on Intel P4, IA-64 and + AMD64. + * Changed the Configure script to have some algorithms disabled + by default. Those can be explicitly enabled with the new + argument form 'enable-xxx'. + * Change the default digest in 'openssl' commands from MD5 to + SHA-1. + * Added support for DTLS. + * New BIGNUM blinding. + * Added support for the RSA-PSS encryption scheme + * Added support for the RSA X.931 padding. + * Added support for BSD sockets on NetWare. + * Added support for files larger than 2GB. + * Added initial support for Win64. + * Added alternate pkg-config files. + +### Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007] + + * FIPS 1.1.1 module linking. + * Various ciphersuite selection fixes. + +### Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006] + + * Introduce limits to prevent malicious key DoS ([CVE-2006-2940]) + * Fix security issues [CVE-2006-2937], [CVE-2006-3737], [CVE-2006-4343] + +### Major changes between OpenSSL 0.9.7j and OpenSSL 0.9.7k [5 Sep 2006] + + * Fix Daniel Bleichenbacher forged signature attack, [CVE-2006-4339] + +### Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006] + + * Visual C++ 2005 fixes. + * Update Windows build system for FIPS. + +### Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005] + + * Give EVP_MAX_MD_SIZE its old value, except for a FIPS build. + +### Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005] + + * Fix SSL 2.0 Rollback ([CVE-2005-2969]) + * Allow use of fixed-length exponent on DSA signing + * Default fixed-window RSA, DSA, DH private-key operations + +### Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005] + + * More compilation issues fixed. + * Adaptation to more modern Kerberos API. + * Enhanced or corrected configuration for Solaris64, Mingw and Cygwin. + * Enhanced x86_64 assembler BIGNUM module. + * More constification. + * Added processing of proxy certificates (RFC 3820). + +### Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005] + + * Several compilation issues fixed. + * Many memory allocation failure checks added. + * Improved comparison of X509 Name type. + * Mandatory basic checks on certificates. + * Performance improvements. + +### Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004] + + * Fix race condition in CRL checking code. + * Fixes to PKCS#7 (S/MIME) code. + +### Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004] + + * Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug + * Security: Fix null-pointer assignment in do_change_cipher_spec() + * Allow multiple active certificates with same subject in CA index + * Multiple X509 verification fixes + * Speed up HMAC and other operations + +### Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003] + + * Security: fix various ASN1 parsing bugs. + * New -ignore_err option to OCSP utility. + * Various interop and bug fixes in S/MIME code. + * SSL/TLS protocol fix for unrequested client certificates. + +### Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003] + + * Security: counter the Klima-Pokorny-Rosa extension of + Bleichbacher's attack + * Security: make RSA blinding default. + * Configuration: Irix fixes, AIX fixes, better mingw support. + * Support for new platforms: linux-ia64-ecc. + * Build: shared library support fixes. + * ASN.1: treat domainComponent correctly. + * Documentation: fixes and additions. + +### Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003] + + * Security: Important security related bugfixes. + * Enhanced compatibility with MIT Kerberos. + * Can be built without the ENGINE framework. + * IA32 assembler enhancements. + * Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64. + * Configuration: the no-err option now works properly. + * SSL/TLS: now handles manual certificate chain building. + * SSL/TLS: certain session ID malfunctions corrected. + +### Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002] + + * New library section OCSP. + * Complete rewrite of ASN1 code. + * CRL checking in verify code and openssl utility. + * Extension copying in 'ca' utility. + * Flexible display options in 'ca' utility. + * Provisional support for international characters with UTF8. + * Support for external crypto devices ('engine') is no longer + a separate distribution. + * New elliptic curve library section. + * New AES (Rijndael) library section. + * Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit, + Linux x86_64, Linux 64-bit on Sparc v9 + * Extended support for some platforms: VxWorks + * Enhanced support for shared libraries. + * Now only builds PIC code when shared library support is requested. + * Support for pkg-config. + * Lots of new manuals. + * Makes symbolic links to or copies of manuals to cover all described + functions. + * Change DES API to clean up the namespace (some applications link also + against libdes providing similar functions having the same name). + Provide macros for backward compatibility (will be removed in the + future). + * Unify handling of cryptographic algorithms (software and engine) + to be available via EVP routines for asymmetric and symmetric ciphers. + * NCONF: new configuration handling routines. + * Change API to use more 'const' modifiers to improve error checking + and help optimizers. + * Finally remove references to RSAref. + * Reworked parts of the BIGNUM code. + * Support for new engines: Broadcom ubsec, Accelerated Encryption + Processing, IBM 4758. + * A few new engines added in the demos area. + * Extended and corrected OID (object identifier) table. + * PRNG: query at more locations for a random device, automatic query for + EGD style random sources at several locations. + * SSL/TLS: allow optional cipher choice according to server's preference. + * SSL/TLS: allow server to explicitly set new session ids. + * SSL/TLS: support Kerberos cipher suites (RFC2712). + Only supports MIT Kerberos for now. + * SSL/TLS: allow more precise control of renegotiations and sessions. + * SSL/TLS: add callback to retrieve SSL/TLS messages. + * SSL/TLS: support AES cipher suites (RFC3268). + +### Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003] + + * Security: fix various ASN1 parsing bugs. + * SSL/TLS protocol fix for unrequested client certificates. + +### Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003] + + * Security: counter the Klima-Pokorny-Rosa extension of + Bleichbacher's attack + * Security: make RSA blinding default. + * Build: shared library support fixes. + +### Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003] + + * Important security related bugfixes. + +### Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002] + + * New configuration targets for Tandem OSS and A/UX. + * New OIDs for Microsoft attributes. + * Better handling of SSL session caching. + * Better comparison of distinguished names. + * Better handling of shared libraries in a mixed GNU/non-GNU environment. + * Support assembler code with Borland C. + * Fixes for length problems. + * Fixes for uninitialised variables. + * Fixes for memory leaks, some unusual crashes and some race conditions. + * Fixes for smaller building problems. + * Updates of manuals, FAQ and other instructive documents. + +### Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002] + + * Important building fixes on Unix. + +### Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002] + + * Various important bugfixes. + +### Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002] + + * Important security related bugfixes. + * Various SSL/TLS library bugfixes. + +### Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002] + + * Various SSL/TLS library bugfixes. + * Fix DH parameter generation for 'non-standard' generators. + +### Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001] + + * Various SSL/TLS library bugfixes. + * BIGNUM library fixes. + * RSA OAEP and random number generation fixes. + * Object identifiers corrected and added. + * Add assembler BN routines for IA64. + * Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8, + MIPS Linux; shared library support for Irix, HP-UX. + * Add crypto accelerator support for AEP, Baltimore SureWare, + Broadcom and Cryptographic Appliance's keyserver + [in 0.9.6c-engine release]. + +### Major changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b [9 Jul 2001] + + * Security fix: PRNG improvements. + * Security fix: RSA OAEP check. + * Security fix: Reinsert and fix countermeasure to Bleichbacher's + attack. + * MIPS bug fix in BIGNUM. + * Bug fix in "openssl enc". + * Bug fix in X.509 printing routine. + * Bug fix in DSA verification routine and DSA S/MIME verification. + * Bug fix to make PRNG thread-safe. + * Bug fix in RAND_file_name(). + * Bug fix in compatibility mode trust settings. + * Bug fix in blowfish EVP. + * Increase default size for BIO buffering filter. + * Compatibility fixes in some scripts. + +### Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001] + + * Security fix: change behavior of OpenSSL to avoid using + environment variables when running as root. + * Security fix: check the result of RSA-CRT to reduce the + possibility of deducing the private key from an incorrectly + calculated signature. + * Security fix: prevent Bleichenbacher's DSA attack. + * Security fix: Zero the premaster secret after deriving the + master secret in DH ciphersuites. + * Reimplement SSL_peek(), which had various problems. + * Compatibility fix: the function des_encrypt() renamed to + des_encrypt1() to avoid clashes with some Unixen libc. + * Bug fixes for Win32, HP/UX and Irix. + * Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and + memory checking routines. + * Bug fixes for RSA operations in threaded environments. + * Bug fixes in misc. openssl applications. + * Remove a few potential memory leaks. + * Add tighter checks of BIGNUM routines. + * Shared library support has been reworked for generality. + * More documentation. + * New function BN_rand_range(). + * Add "-rand" option to openssl s_client and s_server. + +### Major changes between OpenSSL 0.9.5a and OpenSSL 0.9.6 [10 Oct 2000] + + * Some documentation for BIO and SSL libraries. + * Enhanced chain verification using key identifiers. + * New sign and verify options to 'dgst' application. + * Support for DER and PEM encoded messages in 'smime' application. + * New 'rsautl' application, low-level RSA utility. + * MD4 now included. + * Bugfix for SSL rollback padding check. + * Support for external crypto devices [1]. + * Enhanced EVP interface. + + [1] The support for external crypto devices is currently a separate + distribution. See the file README-Engine.md. + +### Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000] + + * Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8 + * Shared library support for HPUX and Solaris-gcc + * Support of Linux/IA64 + * Assembler support for Mingw32 + * New 'rand' application + * New way to check for existence of algorithms from scripts + +### Major changes between OpenSSL 0.9.4 and OpenSSL 0.9.5 [25 May 2000] + + * S/MIME support in new 'smime' command + * Documentation for the OpenSSL command line application + * Automation of 'req' application + * Fixes to make s_client, s_server work under Windows + * Support for multiple fieldnames in SPKACs + * New SPKAC command line utility and associated library functions + * Options to allow passwords to be obtained from various sources + * New public key PEM format and options to handle it + * Many other fixes and enhancements to command line utilities + * Usable certificate chain verification + * Certificate purpose checking + * Certificate trust settings + * Support of authority information access extension + * Extensions in certificate requests + * Simplified X509 name and attribute routines + * Initial (incomplete) support for international character sets + * New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD + * Read only memory BIOs and simplified creation function + * TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0 + record; allow fragmentation and interleaving of handshake and other + data + * TLS/SSL code now "tolerates" MS SGC + * Work around for Netscape client certificate hang bug + * RSA_NULL option that removes RSA patent code but keeps other + RSA functionality + * Memory leak detection now allows applications to add extra information + via a per-thread stack + * PRNG robustness improved + * EGD support + * BIGNUM library bug fixes + * Faster DSA parameter generation + * Enhanced support for Alpha Linux + * Experimental macOS support + +### Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999] + + * Transparent support for PKCS#8 format private keys: these are used + by several software packages and are more secure than the standard + form + * PKCS#5 v2.0 implementation + * Password callbacks have a new void * argument for application data + * Avoid various memory leaks + * New pipe-like BIO that allows using the SSL library when actual I/O + must be handled by the application (BIO pair) + +### Major changes between OpenSSL 0.9.2b and OpenSSL 0.9.3 [24 May 1999] + + * Lots of enhancements and cleanups to the Configuration mechanism + * RSA OEAP related fixes + * Added "openssl ca -revoke" option for revoking a certificate + * Source cleanups: const correctness, type-safe stacks and ASN.1 SETs + * Source tree cleanups: removed lots of obsolete files + * Thawte SXNet, certificate policies and CRL distribution points + extension support + * Preliminary (experimental) S/MIME support + * Support for ASN.1 UTF8String and VisibleString + * Full integration of PKCS#12 code + * Sparc assembler bignum implementation, optimized hash functions + * Option to disable selected ciphers + +### Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999] + + * Fixed a security hole related to session resumption + * Fixed RSA encryption routines for the p < q case + * "ALL" in cipher lists now means "everything except NULL ciphers" + * Support for Triple-DES CBCM cipher + * Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA + * First support for new TLSv1 ciphers + * Added a few new BIOs (syslog BIO, reliable BIO) + * Extended support for DSA certificate/keys. + * Extended support for Certificate Signing Requests (CSR) + * Initial support for X.509v3 extensions + * Extended support for compression inside the SSL record layer + * Overhauled Win32 builds + * Cleanups and fixes to the Big Number (BN) library + * Support for ASN.1 GeneralizedTime + * Splitted ASN.1 SETs from SEQUENCEs + * ASN1 and PEM support for Netscape Certificate Sequences + * Overhauled Perl interface + * Lots of source tree cleanups. + * Lots of memory leak fixes. + * Lots of bug fixes. + +### Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998] + + * Integration of the popular NO_RSA/NO_DSA patches + * Initial support for compression inside the SSL record layer + * Added BIO proxy and filtering functionality + * Extended Big Number (BN) library + * Added RIPE MD160 message digest + * Added support for RC2/64bit cipher + * Extended ASN.1 parser routines + * Adjustments of the source tree for CVS + * Support for various new platforms + + +[CVE-2023-0401]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0401 +[CVE-2023-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0286 +[CVE-2023-0217]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0217 +[CVE-2023-0216]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0216 +[CVE-2023-0215]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-0215 +[CVE-2022-4450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4450 +[CVE-2022-4304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4304 +[CVE-2022-4203]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-4203 +[CVE-2022-3996]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-3996 +[CVE-2022-2274]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274 +[CVE-2022-2097]: https://www.openssl.org/news/vulnerabilities.html#CVE-2022-2274 +[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971 +[CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967 +[CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563 +[CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559 +[CVE-2019-1552]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1552 +[CVE-2019-1551]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1551 +[CVE-2019-1549]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1549 +[CVE-2019-1547]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1547 +[CVE-2019-1543]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1543 +[CVE-2018-5407]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-5407 +[CVE-2018-0739]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0739 +[CVE-2018-0737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0737 +[CVE-2018-0735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0735 +[CVE-2018-0734]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0734 +[CVE-2018-0733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0733 +[CVE-2018-0732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2018-0732 +[CVE-2017-3738]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3738 +[CVE-2017-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3737 +[CVE-2017-3736]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3736 +[CVE-2017-3735]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3735 +[CVE-2017-3733]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3733 +[CVE-2017-3732]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3732 +[CVE-2017-3731]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3731 +[CVE-2017-3730]: https://www.openssl.org/news/vulnerabilities.html#CVE-2017-3730 +[CVE-2016-7055]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7055 +[CVE-2016-7054]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7054 +[CVE-2016-7053]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7053 +[CVE-2016-7052]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-7052 +[CVE-2016-6309]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6309 +[CVE-2016-6308]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6308 +[CVE-2016-6307]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6307 +[CVE-2016-6306]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6306 +[CVE-2016-6305]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6305 +[CVE-2016-6304]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6304 +[CVE-2016-6303]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6303 +[CVE-2016-6302]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-6302 +[CVE-2016-2183]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2183 +[CVE-2016-2182]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2182 +[CVE-2016-2181]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2181 +[CVE-2016-2180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2180 +[CVE-2016-2179]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2179 +[CVE-2016-2178]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2178 +[CVE-2016-2177]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2177 +[CVE-2016-2176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2176 +[CVE-2016-2109]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2109 +[CVE-2016-2107]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2107 +[CVE-2016-2106]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2106 +[CVE-2016-2105]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-2105 +[CVE-2016-0800]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0800 +[CVE-2016-0799]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0799 +[CVE-2016-0798]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0798 +[CVE-2016-0797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0797 +[CVE-2016-0705]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0705 +[CVE-2016-0702]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0702 +[CVE-2016-0701]: https://www.openssl.org/news/vulnerabilities.html#CVE-2016-0701 +[CVE-2015-3197]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3197 +[CVE-2015-3196]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3196 +[CVE-2015-3195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3195 +[CVE-2015-3194]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3194 +[CVE-2015-3193]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-3193 +[CVE-2015-1793]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1793 +[CVE-2015-1792]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1792 +[CVE-2015-1791]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1791 +[CVE-2015-1790]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1790 +[CVE-2015-1789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1789 +[CVE-2015-1788]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1788 +[CVE-2015-1787]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-1787 +[CVE-2015-0293]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0293 +[CVE-2015-0291]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0291 +[CVE-2015-0290]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0290 +[CVE-2015-0289]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0289 +[CVE-2015-0288]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0288 +[CVE-2015-0287]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0287 +[CVE-2015-0286]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0286 +[CVE-2015-0285]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0285 +[CVE-2015-0209]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0209 +[CVE-2015-0208]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0208 +[CVE-2015-0207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0207 +[CVE-2015-0206]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0206 +[CVE-2015-0205]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0205 +[CVE-2015-0204]: https://www.openssl.org/news/vulnerabilities.html#CVE-2015-0204 +[CVE-2014-8275]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-8275 +[CVE-2014-5139]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-5139 +[CVE-2014-3572]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3572 +[CVE-2014-3571]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3571 +[CVE-2014-3570]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3570 +[CVE-2014-3569]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3569 +[CVE-2014-3568]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3568 +[CVE-2014-3567]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3567 +[CVE-2014-3566]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3566 +[CVE-2014-3513]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3513 +[CVE-2014-3512]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3512 +[CVE-2014-3511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3511 +[CVE-2014-3510]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3510 +[CVE-2014-3509]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3509 +[CVE-2014-3508]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3508 +[CVE-2014-3507]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3507 +[CVE-2014-3506]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3506 +[CVE-2014-3505]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3505 +[CVE-2014-3470]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-3470 +[CVE-2014-0224]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0224 +[CVE-2014-0221]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0221 +[CVE-2014-0198]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0198 +[CVE-2014-0195]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0195 +[CVE-2014-0160]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0160 +[CVE-2014-0076]: https://www.openssl.org/news/vulnerabilities.html#CVE-2014-0076 +[CVE-2013-6450]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6450 +[CVE-2013-6449]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-6449 +[CVE-2013-4353]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-4353 +[CVE-2013-0169]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0169 +[CVE-2013-0166]: https://www.openssl.org/news/vulnerabilities.html#CVE-2013-0166 +[CVE-2012-2686]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2686 +[CVE-2012-2333]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2333 +[CVE-2012-2110]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-2110 +[CVE-2012-0884]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0884 +[CVE-2012-0050]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0050 +[CVE-2012-0027]: https://www.openssl.org/news/vulnerabilities.html#CVE-2012-0027 +[CVE-2011-4619]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4619 +[CVE-2011-4577]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4577 +[CVE-2011-4576]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4576 +[CVE-2011-4108]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-4108 +[CVE-2011-3210]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3210 +[CVE-2011-3207]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-3207 +[CVE-2011-0014]: https://www.openssl.org/news/vulnerabilities.html#CVE-2011-0014 +[CVE-2010-5298]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-5298 +[CVE-2010-4252]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4252 +[CVE-2010-4180]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-4180 +[CVE-2010-3864]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-3864 +[CVE-2010-2939]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-2939 +[CVE-2010-1633]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-1633 +[CVE-2010-0740]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0740 +[CVE-2010-0433]: https://www.openssl.org/news/vulnerabilities.html#CVE-2010-0433 +[CVE-2009-3555]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-3555 +[CVE-2009-0789]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0789 +[CVE-2009-0591]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0591 +[CVE-2009-0590]: https://www.openssl.org/news/vulnerabilities.html#CVE-2009-0590 +[CVE-2008-5077]: https://www.openssl.org/news/vulnerabilities.html#CVE-2008-5077 +[CVE-2006-4343]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4343 +[CVE-2006-4339]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-4339 +[CVE-2006-3737]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-3737 +[CVE-2006-2940]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2940 +[CVE-2006-2937]: https://www.openssl.org/news/vulnerabilities.html#CVE-2006-2937 +[CVE-2005-2969]: https://www.openssl.org/news/vulnerabilities.html#CVE-2005-2969 diff --git a/NOTES-ANDROID.md b/NOTES-ANDROID.md new file mode 100644 --- /dev/null +++ b/NOTES-ANDROID.md @@ -0,0 +1,90 @@ +Notes for Android platforms +=========================== + + Requirement details + ------------------- + + Beside basic tools like perl and make you'll need to download the Android + NDK. It's available for Linux, macOS and Windows, but only Linux + version was actually tested. There is no reason to believe that macOS + wouldn't work. And as for Windows, it's unclear which "shell" would be + suitable, MSYS2 might have best chances. NDK version should play lesser + role, the goal is to support a range of most recent versions. + + Configuration + ------------- + + Android is a cross-compiled target and you can't rely on `./Configure` + to find out the configuration target for you. You have to name your + target explicitly; there are `android-arm`, `android-arm64`, `android-mips`, + `android-mip64`, `android-x86` and `android-x86_64` (`*MIPS` targets are no + longer supported with NDK R20+). + + Do not pass --cross-compile-prefix (as you might be tempted), as it + will be "calculated" automatically based on chosen platform. However, + you still need to know the prefix to extend your PATH, in order to + invoke `$(CROSS_COMPILE)clang` [`*gcc` on NDK 19 and lower] and company. + (`./Configure` will fail and give you a hint if you get it wrong.) + + Apart from `PATH` adjustment you need to set `ANDROID_NDK_ROOT` environment + to point at the `NDK` directory. If you're using a side-by-side NDK the path + will look something like `/some/where/android-sdk/ndk/`, and for a + standalone NDK the path will be something like `/some/where/android-ndk-`. + Both variables are significant at both configuration and compilation times. + The NDK customarily supports multiple Android API levels, e.g. `android-14`, + `android-21`, etc. By default latest API level is chosen. If you need to target + an older platform pass the argument `-D__ANDROID_API__=N` to `Configure`, + with `N` being the numerical value of the target platform version. For example, + to compile for Android 10 arm64 with a side-by-side NDK r20.0.5594570 + + export ANDROID_NDK_ROOT=/home/whoever/Android/android-sdk/ndk/20.0.5594570 + PATH=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH + ./Configure android-arm64 -D__ANDROID_API__=29 + make + + Older versions of the NDK have GCC under their common prebuilt tools + directory, so the bin path will be slightly different. EG: to compile + for ICS on ARM with NDK 10d: + + export ANDROID_NDK_ROOT=/some/where/android-ndk-10d + PATH=$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin:$PATH + ./Configure android-arm -D__ANDROID_API__=14 + make + + Caveat lector! Earlier OpenSSL versions relied on additional `CROSS_SYSROOT` + variable set to `$ANDROID_NDK_ROOT/platforms/android-/arch-` to + appoint headers-n-libraries' location. It's still recognized in order + to facilitate migration from older projects. However, since API level + appears in `CROSS_SYSROOT` value, passing `-D__ANDROID_API__=N` can be in + conflict, and mixing the two is therefore not supported. Migration to + `CROSS_SYSROOT`-less setup is recommended. + + One can engage clang by adjusting PATH to cover same NDK's clang. Just + keep in mind that if you miss it, Configure will try to use gcc... + Also, PATH would need even further adjustment to cover unprefixed, yet + target-specific, ar and ranlib. It's possible that you don't need to + bother, if binutils-multiarch is installed on your Linux system. + + Another option is to create so called "standalone toolchain" tailored + for single specific platform including Android API level, and assign its + location to `ANDROID_NDK_ROOT`. In such case you have to pass matching + target name to Configure and shouldn't use `-D__ANDROID_API__=N`. `PATH` + adjustment becomes simpler, `$ANDROID_NDK_ROOT/bin:$PATH` suffices. + + Running tests (on Linux) + ------------------------ + + This is not actually supported. Notes are meant rather as inspiration. + + Even though build output targets alien system, it's possible to execute + test suite on Linux system by employing qemu-user. The trick is static + linking. Pass -static to Configure, then edit generated Makefile and + remove occurrences of -ldl and -pie flags. You would also need to pick + API version that comes with usable static libraries, 42/2=21 used to + work. Once built, you should be able to + + env EXE_SHELL=qemu- make test + + If you need to pass additional flag to qemu, quotes are your friend, e.g. + + env EXE_SHELL="qemu-mips64el -cpu MIPS64R6-generic" make test diff --git a/NOTES-DJGPP.md b/NOTES-DJGPP.md new file mode 100644 --- /dev/null +++ b/NOTES-DJGPP.md @@ -0,0 +1,46 @@ +Notes for the DOS platform with DJGPP +===================================== + + OpenSSL has been ported to DJGPP, a Unix look-alike 32-bit run-time + environment for 16-bit DOS, but only with long filename support. + If you wish to compile on native DOS with 8+3 filenames, you will + have to tweak the installation yourself, including renaming files + with illegal or duplicate names. + + You should have a full DJGPP environment installed, including the + latest versions of DJGPP, GCC, BINUTILS, BASH, etc. This package + requires that PERL and the PERL module `Text::Template` also be + installed (see [NOTES-PERL.md](NOTES-PERL.md)). + + All of these can be obtained from the usual DJGPP mirror sites or + directly at . For help on which + files to download, see the DJGPP "ZIP PICKER" page at + . You also need to have + the WATT-32 networking package installed before you try to compile + OpenSSL. This can be obtained from . + The Makefile assumes that the WATT-32 code is in the directory + specified by the environment variable WATT_ROOT. If you have watt-32 + in directory `watt32` under your main DJGPP directory, specify + `WATT_ROOT="/dev/env/DJDIR/watt32"`. + + To compile OpenSSL, start your BASH shell, then configure for DJGPP by + running `./Configure` with appropriate arguments: + + ./Configure no-threads --prefix=/dev/env/DJDIR DJGPP + + And finally fire up `make`. You may run out of DPMI selectors when + running in a DOS box under Windows. If so, just close the BASH + shell, go back to Windows, and restart BASH. Then run `make` again. + + RUN-TIME CAVEAT LECTOR + -------------- + + Quoting FAQ: + + "Cryptographic software needs a source of unpredictable data to work + correctly. Many open source operating systems provide a "randomness + device" (`/dev/urandom` or `/dev/random`) that serves this purpose." + + As of version 0.9.7f DJGPP port checks upon `/dev/urandom$` for a 3rd + party "randomness" DOS driver. One such driver, `NOISE.SYS`, can be + obtained from . diff --git a/NOTES-NONSTOP.md b/NOTES-NONSTOP.md new file mode 100644 --- /dev/null +++ b/NOTES-NONSTOP.md @@ -0,0 +1,245 @@ +NOTES FOR THE HPE NONSTOP PLATFORM +============================== + +Requirement details +------------------- + +In addition to the requirements and instructions listed +in [INSTALL.md](INSTALL.md), the following are required as well: + + * The TNS/X platform supports hardware randomization. + Specify the `--with-rand-seed=rdcpu` option to the `./Configure` script. + This is recommended but not required. `egd` is supported at 3.0 but cannot + be used if FIPS is selected. + * The TNS/E platform does not support hardware randomization, so + specify the `--with-rand-seed=egd` option to the `./Configure` script. + +About c99 compiler +------------------ + +The c99 compiler is required for building OpenSSL from source. While c11 +may work, it has not been broadly tested. c99 is the only compiler +prerequisite needed to build OpenSSL 3.0 on this platform. You should also +have the FLOSS package installed on your system. The ITUGLIB FLOSS package +is the only FLOSS variant that has been broadly tested. + +Threading Models +---------------- + +OpenSSL can be built using unthreaded, POSIX User Threads (PUT), or Standard +POSIX Threads (SPT). Select the following build configuration for each on +the TNS/X (L-Series) platform: + + * `nonstop-nsx` or default will select an unthreaded build. + * `nonstop-nsx_put` selects the PUT build. + * `nonstop-nsx_64_put` selects the 64 bit file length PUT build. + * `nonstop-nsx_spt_floss` selects the SPT build with FLOSS. FLOSS is + required for SPT builds because of a known hang when using SPT on its own. + +### TNS/E Considerations + +The TNS/E platform is build using the same set of builds specifying `nse` +instead of `nsx` in the set above. + +You cannot build for TNS/E for FIPS, so you must specify the `no-fips` +option to `./Configure`. + +About Prefix and OpenSSLDir +--------------------------- + +Because there are many potential builds that must co-exist on any given +NonStop node, managing the location of your build distribution is crucial. +Keep each destination separate and distinct. Mixing any mode described in +this document can cause application instability. The recommended approach +is to specify the OpenSSL version and threading model in your configuration +options, and keeping your memory and float options consistent, for example: + + * For 1.1 `--prefix=/usr/local-ssl1.1 --openssldir=/usr/local-ssl1.1/ssl` + * For 1.1 PUT `--prefix=/usr/local-ssl1.1_put --openssldir=/usr/local-ssl1.1_put/ssl` + +As of 3.0, the NonStop configurations use the multilib attribute to distinguish +between different models: + + * For 3.0 `--prefix=/usr/local-ssl3.0 --openssldir=/usr/local-ssl3.0/ssl` + +The PUT model is placed in `${prefix}/lib-put` for 32-bit models and +`${prefix}/lib64-put` for 64-bit models. + +Use the `_RLD_LIB_PATH` environment variable in OSS to select the appropriate +directory containing `libcrypto.so` and `libssl.so`. In GUARDIAN, use the +`=_RLD_LIB_PATH` search define to locate the GUARDIAN subvolume where OpenSSL +is installed. + +Float Considerations +-------------------- + +OpenSSL is built using IEEE Float mode by default. If you need a different +IEEE mode, create a new configuration specifying `tfloat-x86-64` (for Tandem +Float) or `nfloat-x86-64` (for Neutral Float). + +Memory Models +------------- + +The current OpenSSL default memory model uses the default platform address +model. If you need a different address model, you must specify the appropriate +c99 options for compile (`CFLAGS`) and linkers (`LDFLAGS`). + +Cross Compiling on Windows +-------------------------- + +To configure and compile OpenSSL, you will need to set up a Cygwin environment. +The Cygwin tools should include bash, make, and any other normal tools required +for building programs. + +Your `PATH` must include the bin directory for the c99 cross-compiler, as in: + + export PATH=/cygdrive/c/Program\ Files\ \(x86\)/HPE\ NonStop/L16.05/usr/bin:$PATH + +This should be set before Configure is run. For the c99 cross-compiler to work +correctly, you also need the `COMP_ROOT` set, as in: + + export COMP_ROOT="C:\Program Files (x86)\HPE NonStop\L16.05" + +`COMP_ROOT` needs to be in Windows form. + +`Configure` must specify the `no-makedepend` option otherwise errors will +result when running the build because the c99 cross-compiler does not support +the `gcc -MT` option. An example of a `Configure` command to be run from the +OpenSSL directory is: + + ./Configure nonstop-nsx_64 no-makedepend --with-rand-seed=rdcpu + +Do not forget to include any OpenSSL cross-compiling prefix and certificate +options when creating your libraries. + +The OpenSSL test suite will not run on your workstation. In order to verify the +build, you will need to perform the build and test steps in OSS in your NonStop +server. You can also build under gcc and run the test suite for Windows but that +is not equivalent. + +**Note:** In the event that you are attempting a FIPS-compliant cross-compile, +be aware that signatures may not match between builds done under OSS and under +cross-compiles as the compilers do not necessarily generate identical objects. +Anything and everything to do with FIPS is outside the scope of this document. +Refer to the FIPS security policy for more information. + +The following build configurations have been successfully attempted at one +point or another. If you are successful in your cross-compile efforts, please +update this list: + +- nonstop-nsx_64 +- nonstop-nsx_64_put + +**Note:** Cross-compile builds for TNS/E have not been attempted, but should +follow the same considerations as for TNS/X above. SPT builds generally require +FLOSS, which is not available for workstation builds. As a result, SPT builds +of OpenSSL cannot be cross-compiled. + +Also see the NSDEE discussion below for more historical information. + +Cross Compiling with NSDEE +-------------------------- + +**Note:** None of these builds have been tested by the platform maintainer and +are supplied for historical value. Please submit a Pull Request to OpenSSL +should these need to be adjusted. + +If you are attempting to build OpenSSL with NSDEE, you will need to specify +the following variables. The following set of compiler defines are required: + + # COMP_ROOT must be a full path for the build system (e.g. windows) + COMP_ROOT=$(cygpath -w /path/to/comp_root) + # CC must be executable by your shell + CC=/path/to/c99 + +### Optional Build Variables + + DBGFLAG="--debug" + CIPHENABLES="enable-ssl3 enable-ssl3-method enable-weak-ssl-ciphers enable-rc4" + +### Internal Known TNS/X to TNS/E Cross Compile Variables + +The following definition is required if you are building on TNS/X for TNS/E +and have access to a TNS/E machine on your EXPAND network - with an example +node named `\CS3`: + + SYSTEMLIBS="-L/E/cs3/usr/local/lib" + +Version Procedure (VPROC) Considerations +---------------------------------------- + +If you require a VPROC entry for platform version identification, use the +following variables: + +### For Itanium + + OPENSSL_VPROC_PREFIX=T0085H06 + +### For x86 + + OPENSSL_VPROC_PREFIX=T0085L01 + +### Common Definition + + export OPENSSL_VPROC=${OPENSSL_VPROC_PREFIX}_$( + . VERSION.dat + if [ -n "$PRE_RELEASE_TAG" ]; then + PRE_RELEASE_TAG="-$PRE_RELEASE_TAG" + fi + if [ -n "$BUILD_METADATA" ]; then + BUILD_METADATA="+$BUILD_METADATA" + fi + echo "$MAJOR.$MINOR.$PATCH$PRE_RELEASE_TAG$BUILD_METADATA" |\ + sed -e 's/[-.+]/_/g' + ) + +Example Configure Targets +------------------------- + +For OSS targets, the main DLL names will be `libssl.so` and `libcrypto.so`. +For GUARDIAN targets, DLL names will be `ssl` and `crypto`. The following +assumes that your PWD is set according to your installation standards. + + ./Configure nonstop-nsx --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nsx_g --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nsx_put --prefix=${PWD} \ + --openssldir=${PWD}/ssl threads "-D_REENTRANT" \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nsx_spt_floss --prefix=${PWD} \ + --openssldir=${PWD}/ssl threads "-D_REENTRANT" \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nsx_64 --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nsx_64_put --prefix=${PWD} \ + --openssldir=${PWD}/ssl threads "-D_REENTRANT" \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nsx_g_tandem --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=rdcpu ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + + ./Configure nonstop-nse --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nse_g --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nse_put --prefix=${PWD} \ + --openssldir=${PWD}/ssl threads "-D_REENTRANT" \ + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nse_spt_floss --prefix=${PWD} \ + --openssldir=${PWD}/ssl threads "-D_REENTRANT" \ + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nse_64 --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nse_64_put --prefix=${PWD} \ + --openssldir=${PWD}/ssl threads "-D_REENTRANT" + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} + ./Configure nonstop-nse_g_tandem --prefix=${PWD} \ + --openssldir=${PWD}/ssl no-threads \ + --with-rand-seed=egd ${CIPHENABLES} ${DBGFLAG} ${SYSTEMLIBS} diff --git a/NOTES-PERL.md b/NOTES-PERL.md new file mode 100644 --- /dev/null +++ b/NOTES-PERL.md @@ -0,0 +1,127 @@ +Notes on Perl +============= + + - [General Notes](#general-notes) + - [Perl on Windows](#perl-on-windows) + - [Perl on VMS](#perl-on-vms) + - [Perl on NonStop](#perl-on-nonstop) + - [Required Perl modules](#required-perl-modules) + - [Notes on installing a Perl module](#notes-on-installing-a-perl-module]) + +General Notes +------------- + +For our scripts, we rely quite a bit on Perl, and increasingly on +some core Perl modules. These Perl modules are part of the Perl +source, so if you build Perl on your own, you should be set. + +However, if you install Perl as binary packages, the outcome might +differ, and you may have to check that you do get the core modules +installed properly. We do not claim to know them all, but experience +has told us the following: + + - on Linux distributions based on Debian, the package `perl` will + install the core Perl modules as well, so you will be fine. + - on Linux distributions based on RPMs, you will need to install + `perl-core` rather than just `perl`. + +You MUST have at least Perl version 5.10.0 installed. This minimum +requirement is due to our use of regexp backslash sequence \R among +other features that didn't exist in core Perl before that version. + +Perl on Windows +--------------- + +There are a number of build targets that can be viewed as "Windows". +Indeed, there are `VC-*` configs targeting VisualStudio C, as well as +MinGW and Cygwin. The key recommendation is to use a Perl installation +that matches the build environment. For example, if you will build +on Cygwin be sure to use the Cygwin package manager to install Perl. +For MSYS builds use the MSYS provided Perl. +For VC-* builds we recommend Strawberry Perl, from . +An alternative is ActiveState Perl, from +for which you may need to explicitly select the Perl module Win32/Console.pm +available via . + +Perl on VMS +----------- + +You will need to install Perl separately. One way to do so is to +download the source from , unpacking it, reading +`README-VMS.md` and follow the instructions. Another way is to download a +`.PCSI` file from and install it using the +POLYCENTER install tool. + +Perl on NonStop +--------------- + +Perl is installed on HPE NonStop platforms as part of the Scripting Languages +package T1203PAX file. The package is shipped as part of a NonStop RVU +(Release Version Updates) package. Individual SPRs (Software Product Release) +representing fixes can be obtained from the Scout website at +. Follow the appropriate set of installation +instructions for your operating system release as described in the +Script Language User Guide available from the NonStop Technical Library. + +Required Perl modules +--------------------- + +We do our best to limit ourselves to core Perl modules to keep the +requirements down. There are just a few exceptions. + + * Text::Template this is required *for building* + + To avoid unnecessary initial hurdles, we include a copy of this module + in the source. It will work as a fallback if the module isn't already + installed. + + * `Test::More` this is required *for testing* + + We require the minimum version to be 0.96, which appeared in Perl 5.13.4, + because that version was the first to have all the features we're using. + This module is required for testing only! If you don't plan on running + the tests, you don't need to bother with this one. + +Notes on installing a Perl module +--------------------------------- + +There are a number of ways to install a perl module. In all +descriptions below, `Text::Template` will serve as an example. + +1. for Linux users, the easiest is to install with the use of your + favorite package manager. Usually, all you need to do is search + for the module name and to install the package that comes up. + + On Debian based Linux distributions, it would go like this: + + $ apt-cache search Text::Template + ... + libtext-template-perl - perl module to process text templates + $ sudo apt-get install libtext-template-perl + + Perl modules in Debian based distributions use package names like + the name of the module in question, with "lib" prepended and + "-perl" appended. + +2. Install using CPAN. This is very easy, but usually requires root + access: + + $ cpan -i Text::Template + + Note that this runs all the tests that the module to be installed + comes with. This is usually a smooth operation, but there are + platforms where a failure is indicated even though the actual tests + were successful. Should that happen, you can force an + installation regardless (that should be safe since you've already + seen the tests succeed!): + + $ cpan -f -i Text::Template + + Note: on VMS, you must quote any argument that contains upper case + characters, so the lines above would be: + + $ cpan -i "Text::Template" + + and: + + $ cpan -f -i "Text::Template" diff --git a/NOTES-UNIX.md b/NOTES-UNIX.md new file mode 100644 --- /dev/null +++ b/NOTES-UNIX.md @@ -0,0 +1,115 @@ +Notes for UNIX-like platforms +============================= + + For Unix/POSIX runtime systems on Windows, + please see the [Notes for Windows platforms](NOTES-WINDOWS.md). + + OpenSSL uses the compiler to link programs and shared libraries + --------------------------------------------------------------- + + OpenSSL's generated Makefile uses the C compiler command line to + link programs, shared libraries and dynamically loadable shared + objects. Because of this, any linking option that's given to the + configuration scripts MUST be in a form that the compiler can accept. + This varies between systems, where some have compilers that accept + linker flags directly, while others take them in `-Wl,` form. You need + to read your compiler documentation to figure out what is acceptable, + and `ld(1)` to figure out what linker options are available. + + Shared libraries and installation in non-default locations + ---------------------------------------------------------- + + Every Unix system has its own set of default locations for shared + libraries, such as `/lib`, `/usr/lib` or possibly `/usr/local/lib`. If + libraries are installed in non-default locations, dynamically linked + binaries will not find them and therefore fail to run, unless they get + a bit of help from a defined runtime shared library search path. + + For OpenSSL's application (the `openssl` command), our configuration + scripts do NOT generally set the runtime shared library search path for + you. It's therefore advisable to set it explicitly when configuring, + unless the libraries are to be installed in directories that you know + to be in the default list. + + Runtime shared library search paths are specified with different + linking options depending on operating system and versions thereof, and + are talked about differently in their respective documentation; + variations of RPATH are the most usual (note: ELF systems have two such + tags, more on that below). + + Possible options to set the runtime shared library search path include + the following: + + -Wl,-rpath,/whatever/path # Linux, *BSD, etc. + -R /whatever/path # Solaris + -Wl,-R,/whatever/path # AIX (-bsvr4 is passed internally) + -Wl,+b,/whatever/path # HP-UX + -rpath /whatever/path # Tru64, IRIX + + OpenSSL's configuration scripts recognise all these options and pass + them to the Makefile that they build. (In fact, all arguments starting + with `-Wl,` are recognised as linker options.) + Please note that 'l' in '-Wl' is lowercase L and not 1. + + Please do not use verbatim directories in your runtime shared library + search path! Some OpenSSL config targets add an extra directory level + for multilib installations. To help with that, the produced Makefile + includes the variable LIBRPATH, which is a convenience variable to be + used with the runtime shared library search path options, as shown in + this example: + + $ ./Configure --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \ + '-Wl,-rpath,$(LIBRPATH)' + + On modern ELF based systems, there are two runtime search paths tags to + consider, `DT_RPATH` and `DT_RUNPATH`. Shared objects are searched for in + this order: + + 1. Using directories specified in DT_RPATH, unless DT_RUNPATH is also set. + 2. Using the environment variable LD_LIBRARY_PATH + 3. Using directories specified in DT_RUNPATH. + 4. Using system shared object caches and default directories. + + This means that the values in the environment variable `LD_LIBRARY_PATH` + won't matter if the library is found in the paths given by `DT_RPATH` + (and `DT_RUNPATH` isn't set). + + Exactly which of `DT_RPATH` or `DT_RUNPATH` is set by default appears to + depend on the system. For example, according to documentation, + `DT_RPATH` appears to be deprecated on Solaris in favor of `DT_RUNPATH`, + while on Debian GNU/Linux, either can be set, and `DT_RPATH` is the + default at the time of writing. + + How to choose which runtime search path tag is to be set depends on + your system, please refer to ld(1) for the exact information on your + system. As an example, the way to ensure the `DT_RUNPATH` is set on + Debian GNU/Linux systems rather than DT_RPATH is to tell the linker to + set new dtags, like this: + + $ ./Configure --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \ + '-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)' + + It might be worth noting that some/most ELF systems implement support + for runtime search path relative to the directory containing current + executable, by interpreting `$ORIGIN` along with some other internal + variables. Consult your system documentation. + + Linking your application + ------------------------ + + Third-party applications dynamically linked with OpenSSL (or any other) + shared library face exactly the same problem with non-default locations. + The OpenSSL config options mentioned above might or might not have bearing + on linking of the target application. "Might" means that under some + circumstances it would be sufficient to link with OpenSSL shared library + "naturally", i.e. with `-L/whatever/path -lssl -lcrypto`. But there are + also cases when you'd have to explicitly specify runtime search path + when linking your application. Consult your system documentation and use + above section as inspiration... + + Shared OpenSSL builds also install static libraries. Linking with the + latter is likely to require special care, because linkers usually look + for shared libraries first and tend to remain "blind" to static OpenSSL + libraries. Referring to system documentation would suffice, if not for + a corner case. On AIX static libraries (in shared build) are named + differently, add `_a` suffix to link with them, e.g. `-lcrypto_a`. diff --git a/NOTES-VALGRIND.md b/NOTES-VALGRIND.md new file mode 100644 --- /dev/null +++ b/NOTES-VALGRIND.md @@ -0,0 +1,72 @@ +Notes on Valgrind +================= + +Valgrind is a test harness that includes many tools such as memcheck, +which is commonly used to check for memory leaks, etc. The default tool +run by Valgrind is memcheck. There are other tools available, but this +will focus on memcheck. + +Valgrind runs programs in a virtual machine, this means OpenSSL unit +tests run under Valgrind will take longer than normal. + +Requirements +------------ + +1. Platform supported by Valgrind + See +2. Valgrind installed on the platform + See +3. OpenSSL compiled + See [INSTALL.md](INSTALL.md) + +Running Tests +------------- + +Test behavior can be modified by adjusting environment variables. + +`EXE_SHELL` + +This variable is used to specify the shell used to execute OpenSSL test +programs. The default wrapper (`util/wrap.pl`) initializes the environment +to allow programs to find shared libraries. The variable can be modified +to specify a different executable environment. + + EXE_SHELL=\ + "`/bin/pwd`/util/wrap.pl valgrind --error-exitcode=1 --leak-check=full -q" + +This will start up Valgrind with the default checker (`memcheck`). +The `--error-exitcode=1` option specifies that Valgrind should exit with an +error code of 1 when memory leaks occur. +The `--leak-check=full` option specifies extensive memory checking. +The `-q` option prints only error messages. +Additional Valgrind options may be added to the `EXE_SHELL` variable. + +`OPENSSL_ia32cap` + +This variable controls the processor-specific code on Intel processors. +By default, OpenSSL will attempt to figure out the capabilities of a +processor, and use it to its fullest capability. This variable can be +used to control what capabilities OpenSSL uses. + +As of valgrind-3.15.0 on Linux/x86_64, instructions up to AVX2 are +supported. Setting the following disables instructions beyond AVX2: + +`OPENSSL_ia32cap=":0"` + +This variable may need to be set to something different based on the +processor and Valgrind version you are running tests on. More information +may be found in [doc/man3/OPENSSL_ia32cap.pod](doc/man3/OPENSSL_ia32cap.pod). + +Additional variables (such as `VERBOSE` and `TESTS`) are described in the +file [test/README.md](test/README.md). + +Example command line: + + $ make test EXE_SHELL="`/bin/pwd`/util/wrap.pl valgrind --error-exitcode=1 \ + --leak-check=full -q" OPENSSL_ia32cap=":0" + +If an error occurs, you can then run the specific test via the `TESTS` variable +with the `VERBOSE` or `VF` or `VFP` options to gather additional information. + + $ make test VERBOSE=1 TESTS=test_test EXE_SHELL="`/bin/pwd`/util/wrap.pl \ + valgrind --error-exitcode=1 --leak-check=full -q" OPENSSL_ia32cap=":0" diff --git a/NOTES-VMS.md b/NOTES-VMS.md new file mode 100644 --- /dev/null +++ b/NOTES-VMS.md @@ -0,0 +1,115 @@ +Notes for the OpenVMS platform +============================== + + - [Requirement details](#requirement-details) + - [About ANSI C compiler](#about-ansi-c-compiler) + - [About ODS-5 directory names and Perl](#about-ods-5-directory-names-and-perl) + - [About MMS and DCL](#about-mms-and-dcl) + - [About debugging](#about-debugging) + - [Checking the distribution](#checking-the-distribution) + +Requirement details +------------------- + +In addition to the requirements and instructions listed +in [INSTALL.md](INSTALL.md), this are required as well: + + * At least ODS-5 disk organization for source and build. + Installation can be done on any existing disk organization. + +About ANSI C compiler +--------------------- + +An ANSI C compiled is needed among other things. This means that +VAX C is not and will not be supported. + +We have only tested with DEC C (aka HP VMS C / VSI C) and require +version 7.1 or later. Compiling with a different ANSI C compiler may +require some work. + +Please avoid using C RTL feature logical names `DECC$*` when building +and testing OpenSSL. Most of all, they can be disruptive when +running the tests, as they affect the Perl interpreter. + +About ODS-5 directory names and Perl +------------------------------------ + +It seems that the perl function canonpath() in the `File::Spec` module +doesn't treat file specifications where the last directory name +contains periods very well. Unfortunately, some versions of VMS tar +will keep the periods in the OpenSSL source directory instead of +converting them to underscore, thereby leaving your source in +something like `[.openssl-1^.1^.0]`. This will lead to issues when +configuring and building OpenSSL. + +We have no replacement for Perl's canonpath(), so the best workaround +for now is to rename the OpenSSL source directory, as follows (please +adjust for the actual source directory name you have): + + $ rename openssl-1^.1^.0.DIR openssl-1_1_0.DIR + +About MMS and DCL +----------------- + +MMS has certain limitations when it comes to line length, and DCL has +certain limitations when it comes to total command length. We do +what we can to mitigate, but there is the possibility that it's not +enough. Should you run into issues, a very simple solution is to set +yourself up a few logical names for the directory trees you're going +to use. + +About debugging +--------------- + +If you build for debugging, the default on VMS is that image +activation starts the debugger automatically, giving you a debug +prompt. Unfortunately, this disrupts all other uses, such as running +test programs in the test framework. + +Generally speaking, if you build for debugging, only use the programs +directly for debugging. Do not try to use them from a script, such +as running the test suite. + +### The following is not available on Alpha + +As a compromise, we're turning off the flag that makes the debugger +start automatically. If there is a program that you need to debug, +you need to turn that flag back on first, for example: + + $ set image /flag=call_debug [.test]evp_test.exe + +Then just run it and you will find yourself in a debugging session. +When done, we recommend that you turn that flag back off: + + $ set image /flag=nocall_debug [.test]evp_test.exe + +Checking the distribution +------------------------- + +There have been reports of places where the distribution didn't quite +get through, for example if you've copied the tree from a NFS-mounted +Unix mount point. + +The easiest way to check if everything got through as it should is to +check that this file exists: + + [.include.openssl]configuration^.h.in + +The best way to get a correct distribution is to download the gzipped +tar file from ftp://ftp.openssl.org/source/, use `GZIP -d` to uncompress +it and `VMSTAR` to unpack the resulting tar file. + +Gzip and VMSTAR are available here: + + + +Should you need it, you can find UnZip for VMS here: + + + + How the value of 'arch' is determined + ------------------------------------- + + 'arch' is mentioned in INSTALL. It's value is determined like this: + + arch = f$edit( f$getsyi( "arch_name"), "upcase") diff --git a/NOTES-WINDOWS.md b/NOTES-WINDOWS.md new file mode 100644 --- /dev/null +++ b/NOTES-WINDOWS.md @@ -0,0 +1,265 @@ +Notes for Windows platforms +=========================== + + - [Native builds using Visual C++](#native-builds-using-visual-c++) + - [Native builds using Embarcadero C++Builder]( + #native-builds-using-embarcadero-c++-builder) + - [Native builds using MinGW](#native-builds-using-mingw) + - [Linking native applications](#linking-native-applications) + - [Hosted builds using Cygwin](#hosted-builds-using-cygwin) + +There are various options to build and run OpenSSL on the Windows platforms. + +"Native" OpenSSL uses the Windows APIs directly at run time. +To build a native OpenSSL you can either use: + + Microsoft Visual C++ (MSVC) C compiler on the command line +or + Embarcadero C++Builder +or + MinGW cross compiler + run on the GNU-like development environment MSYS2 + or run on Linux or Cygwin + +"Hosted" OpenSSL relies on an external POSIX compatibility layer +for building (using GNU/Unix shell, compiler, and tools) and at run time. +For this option you can use Cygwin. + +Native builds using Visual C++ +============================== + +The native builds using Visual C++ have a `VC-*` prefix. + +Requirement details +------------------- + +In addition to the requirements and instructions listed in `INSTALL.md`, +these are required as well: + +### Perl + +We recommend Strawberry Perl, available from +Please read NOTES.PERL for more information, including the use of CPAN. +An alternative is ActiveState Perl, +for which you may need to explicitly build the Perl module Win32/Console.pm +via and then download it. + +### Microsoft Visual C compiler. + +Since these are proprietary and ever-changing we cannot test them all. +Older versions may not work. Use a recent version wherever possible. + +### Netwide Assembler (NASM) + +NASM is the only supported assembler. It is available from . + +Quick start +----------- + + 1. Install Perl + + 2. Install NASM + + 3. Make sure both Perl and NASM are on your %PATH% + + 4. Use Visual Studio Developer Command Prompt with administrative privileges, + choosing one of its variants depending on the intended architecture. + Or run `cmd` and execute `vcvarsall.bat` with one of the options `x86`, + `x86_amd64`, `x86_arm`, `x86_arm64`, `amd64`, `amd64_x86`, `amd64_arm`, + or `amd64_arm64`. + This sets up the environment variables needed for `nmake.exe`, `cl.exe`, + etc. + See also + + + 5. From the root of the OpenSSL source directory enter + - `perl Configure VC-WIN32` if you want 32-bit OpenSSL or + - `perl Configure VC-WIN64A` if you want 64-bit OpenSSL or + - `perl Configure VC-WIN64-ARM` if you want Windows on Arm (win-arm64) + OpenSSL or + - `perl Configure` to let Configure figure out the platform + + 6. `nmake` + + 7. `nmake test` + + 8. `nmake install` + +For the full installation instructions, or if anything goes wrong at any stage, +check the INSTALL.md file. + +Installation directories +------------------------ + +The default installation directories are derived from environment +variables. + +For VC-WIN32, the following defaults are use: + + PREFIX: %ProgramFiles(x86)%\OpenSSL + OPENSSLDIR: %CommonProgramFiles(x86)%\SSL + +For VC-WIN64, the following defaults are use: + + PREFIX: %ProgramW6432%\OpenSSL + OPENSSLDIR: %CommonProgramW6432%\SSL + +Should those environment variables not exist (on a pure Win32 +installation for examples), these fallbacks are used: + + PREFIX: %ProgramFiles%\OpenSSL + OPENSSLDIR: %CommonProgramFiles%\SSL + +ALSO NOTE that those directories are usually write protected, even if +your account is in the Administrators group. To work around that, +start the command prompt by right-clicking on it and choosing "Run as +Administrator" before running `nmake install`. The other solution +is, of course, to choose a different set of directories by using +`--prefix` and `--openssldir` when configuring. + +Special notes for Universal Windows Platform builds, aka `VC-*-UWP` +------------------------------------------------------------------- + + - UWP targets only support building the static and dynamic libraries. + + - You should define the platform type to `uwp` and the target arch via + `vcvarsall.bat` before you compile. For example, if you want to build + `arm64` builds, you should run `vcvarsall.bat x86_arm64 uwp`. + +Native builds using Embarcadero C++Builder +========================================= + +This toolchain (a descendant of Turbo/Borland C++) is an alternative to MSVC. +OpenSSL currently includes an experimental 32-bit configuration targeting the +Clang-based compiler (`bcc32c.exe`) in v10.3.3 Community Edition. + + + 1. Install Perl. + + 2. Open the RAD Studio Command Prompt. + + 3. Go to the root of the OpenSSL source directory and run: + `perl Configure BC-32 --prefix=%CD%` + + 4. `make -N` + + 5. `make -N test` + + 6. Build your program against this OpenSSL: + * Set your include search path to the "include" subdirectory of OpenSSL. + * Set your library search path to the OpenSSL source directory. + +Note that this is very experimental. Support for 64-bit and other Configure +options is still pending. + +Native builds using MinGW +========================= + +MinGW offers an alternative way to build native OpenSSL, by cross compilation. + + * Usually the build is done on Windows in a GNU-like environment called MSYS2. + + MSYS2 provides GNU tools, a Unix-like command prompt, + and a UNIX compatibility layer for applications. + However, in this context it is only used for building OpenSSL. + The resulting OpenSSL does not rely on MSYS2 to run and is fully native. + + Requirement details + + - MSYS2 shell, from + + - Perl, at least version 5.10.0, which usually comes pre-installed with MSYS2 + + - make, installed using `pacman -S make` into the MSYS2 environment + + - MinGW[64] compiler: `mingw-w64-i686-gcc` and/or `mingw-w64-x86_64-gcc`. + These compilers must be on your MSYS2 $PATH. + A common error is to not have these on your $PATH. + The MSYS2 version of gcc will not work correctly here. + + In the MSYS2 shell do the configuration depending on the target architecture: + + ./Configure mingw ... + + or + + ./Configure mingw64 ... + + or + + ./Configure ... + + for the default architecture. + + Apart from that, follow the Unix / Linux instructions in `INSTALL.md`. + + * It is also possible to build mingw[64] on Linux or Cygwin. + + In this case configure with the corresponding `--cross-compile-prefix=` + option. For example + + ./Configure mingw --cross-compile-prefix=i686-w64-mingw32- ... + + or + + ./Configure mingw64 --cross-compile-prefix=x86_64-w64-mingw32- ... + + This requires that you've installed the necessary add-on packages for + mingw[64] cross compilation. + +Linking native applications +=========================== + +This section applies to all native builds. + +If you link with static OpenSSL libraries then you're expected to +additionally link your application with `WS2_32.LIB`, `GDI32.LIB`, +`ADVAPI32.LIB`, `CRYPT32.LIB` and `USER32.LIB`. Those developing +non-interactive service applications might feel concerned about +linking with `GDI32.LIB` and `USER32.LIB`, as they are justly associated +with interactive desktop, which is not available to service +processes. The toolkit is designed to detect in which context it's +currently executed, GUI, console app or service, and act accordingly, +namely whether or not to actually make GUI calls. Additionally those +who wish to `/DELAYLOAD:GDI32.DLL` and `/DELAYLOAD:USER32.DLL` and +actually keep them off service process should consider implementing +and exporting from .exe image in question own `_OPENSSL_isservice` not +relying on `USER32.DLL`. E.g., on Windows Vista and later you could: + + __declspec(dllexport) __cdecl BOOL _OPENSSL_isservice(void) + { + DWORD sess; + + if (ProcessIdToSessionId(GetCurrentProcessId(), &sess)) + return sess == 0; + return FALSE; + } + +If you link with OpenSSL .DLLs, then you're expected to include into +your application code a small "shim" snippet, which provides +the glue between the OpenSSL BIO layer and your compiler run-time. +See also the OPENSSL_Applink manual page. + +Hosted builds using Cygwin +========================== + +Cygwin implements a POSIX/Unix runtime system (`cygwin1.dll`) on top of the +Windows subsystem and provides a Bash shell and GNU tools environment. +Consequently, a build of OpenSSL with Cygwin is virtually identical to the +Unix procedure. + +To build OpenSSL using Cygwin, you need to: + + * Install Cygwin, see + + * Install Cygwin Perl, at least version 5.10.0 + and ensure it is in the $PATH + + * Run the Cygwin Bash shell + +Apart from that, follow the Unix / Linux instructions in INSTALL.md. + +NOTE: `make test` and normal file operations may fail in directories +mounted as text (i.e. `mount -t c:\somewhere /home`) due to Cygwin +stripping of carriage returns. To avoid this ensure that a binary +mount is used, e.g. `mount -b c:\somewhere /home`. diff --git a/NOTES.PERL b/NOTES.PERL deleted file mode 100644 --- a/NOTES.PERL +++ /dev/null @@ -1,119 +0,0 @@ - TOC - === - - - Notes on Perl - - Notes on Perl on Windows - - Notes on Perl modules we use - - Notes on installing a perl module - - Notes on Perl - ------------- - - For our scripts, we rely quite a bit on Perl, and increasingly on - some core Perl modules. These Perl modules are part of the Perl - source, so if you build Perl on your own, you should be set. - - However, if you install Perl as binary packages, the outcome might - differ, and you may have to check that you do get the core modules - installed properly. We do not claim to know them all, but experience - has told us the following: - - - on Linux distributions based on Debian, the package 'perl' will - install the core Perl modules as well, so you will be fine. - - on Linux distributions based on RPMs, you will need to install - 'perl-core' rather than just 'perl'. - - You MUST have at least Perl version 5.10.0 installed. This minimum - requirement is due to our use of regexp backslash sequence \R among - other features that didn't exist in core Perl before that version. - - Notes on Perl on Windows - ------------------------ - - There are a number of build targets that can be viewed as "Windows". - Indeed, there are VC-* configs targeting VisualStudio C, as well as - MinGW and Cygwin. The key recommendation is to use "matching" Perl, - one that matches build environment. For example, if you will build - on Cygwin be sure to use the Cygwin package manager to install Perl. - For MSYS builds use the MSYS provided Perl. For VC-* builds we - recommend ActiveState Perl, available from - http://www.activestate.com/ActivePerl. - - Notes on Perl on VMS - -------------------- - - You will need to install Perl separately. One way to do so is to - download the source from http://perl.org/, unpacking it, reading - README.vms and follow the instructions. Another way is to download a - .PCSI file from http://www.vmsperl.com/ and install it using the - POLYCENTER install tool. - - Notes on Perl modules we use - ---------------------------- - - We make increasing use of Perl modules, and do our best to limit - ourselves to core Perl modules to keep the requirements down. There - are just a few exceptions: - - Test::More We require the minimum version to be 0.96, which - appeared in Perl 5.13.4, because that version was - the first to have all the features we're using. - This module is required for testing only! If you - don't plan on running the tests, you don't need to - bother with this one. - - Text::Template This module is not part of the core Perl modules. - As a matter of fact, the core Perl modules do not - include any templating module to date. - This module is absolutely needed, configuration - depends on it. - - To avoid unnecessary initial hurdles, we have bundled a copy of the - following modules in our source. They will work as fallbacks if - these modules aren't already installed on the system. - - Text::Template - - Notes on installing a perl module - --------------------------------- - - There are a number of ways to install a perl module. In all - descriptions below, Text::Template will serve as an example. - - 1. for Linux users, the easiest is to install with the use of your - favorite package manager. Usually, all you need to do is search - for the module name and to install the package that comes up. - - On Debian based Linux distributions, it would go like this: - - $ apt-cache search Text::Template - ... - libtext-template-perl - perl module to process text templates - $ sudo apt-get install libtext-template-perl - - Perl modules in Debian based distributions use package names like - the name of the module in question, with "lib" prepended and - "-perl" appended. - - 2. Install using CPAN. This is very easy, but usually requires root - access: - - $ cpan -i Text::Template - - Note that this runs all the tests that the module to be installed - comes with. This is usually a smooth operation, but there are - platforms where a failure is indicated even though the actual tests - were successful. Should that happen, you can force an - installation regardless (that should be safe since you've already - seen the tests succeed!): - - $ cpan -f -i Text::Template - - Note: on VMS, you must quote any argument that contains uppercase - characters, so the lines above would be: - - $ cpan -i "Text::Template" - - and: - - $ cpan -f -i "Text::Template" diff --git a/NOTES.UNIX b/NOTES.UNIX deleted file mode 100644 --- a/NOTES.UNIX +++ /dev/null @@ -1,117 +0,0 @@ - - NOTES FOR UNIX LIKE PLATFORMS - ============================= - - For Unix/POSIX runtime systems on Windows, please see NOTES.WIN. - - - OpenSSL uses the compiler to link programs and shared libraries - --------------------------------------------------------------- - - OpenSSL's generated Makefile uses the C compiler command line to - link programs, shared libraries and dynamically loadable shared - objects. Because of this, any linking option that's given to the - configuration scripts MUST be in a form that the compiler can accept. - This varies between systems, where some have compilers that accept - linker flags directly, while others take them in '-Wl,' form. You need - to read your compiler documentation to figure out what is acceptable, - and ld(1) to figure out what linker options are available. - - - Shared libraries and installation in non-default locations - ---------------------------------------------------------- - - Every Unix system has its own set of default locations for shared - libraries, such as /lib, /usr/lib or possibly /usr/local/lib. If - libraries are installed in non-default locations, dynamically linked - binaries will not find them and therefore fail to run, unless they get - a bit of help from a defined runtime shared library search path. - - For OpenSSL's application (the 'openssl' command), our configuration - scripts do NOT generally set the runtime shared library search path for - you. It's therefore advisable to set it explicitly when configuring, - unless the libraries are to be installed in directories that you know - to be in the default list. - - Runtime shared library search paths are specified with different - linking options depending on operating system and versions thereof, and - are talked about differently in their respective documentation; - variations of RPATH are the most usual (note: ELF systems have two such - tags, more on that below). - - Possible options to set the runtime shared library search path include - the following: - - -Wl,-rpath,/whatever/path # Linux, *BSD, etc. - -R /whatever/path # Solaris - -Wl,-R,/whatever/path # AIX (-bsvr4 is passed internally) - -Wl,+b,/whatever/path # HP-UX - -rpath /whatever/path # Tru64, IRIX - - OpenSSL's configuration scripts recognise all these options and pass - them to the Makefile that they build. (In fact, all arguments starting - with '-Wl,' are recognised as linker options.) - - Please do not use verbatim directories in your runtime shared library - search path! Some OpenSSL config targets add an extra directory level - for multilib installations. To help with that, the produced Makefile - includes the variable LIBRPATH, which is a convenience variable to be - used with the runtime shared library search path options, as shown in - this example: - - $ ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \ - '-Wl,-rpath,$(LIBRPATH)' - - On modern ELF based systems, there are two runtime search paths tags to - consider, DT_RPATH and DT_RUNPATH. Shared objects are searched for in - this order: - - 1. Using directories specified in DT_RPATH, unless DT_RUNPATH is - also set. - 2. Using the environment variable LD_LIBRARY_PATH - 3. Using directories specified in DT_RUNPATH. - 4. Using system shared object caches and default directories. - - This means that the values in the environment variable LD_LIBRARY_PATH - won't matter if the library is found in the paths given by DT_RPATH - (and DT_RUNPATH isn't set). - - Exactly which of DT_RPATH or DT_RUNPATH is set by default appears to - depend on the system. For example, according to documentation, - DT_RPATH appears to be deprecated on Solaris in favor of DT_RUNPATH, - while on Debian GNU/Linux, either can be set, and DT_RPATH is the - default at the time of writing. - - How to choose which runtime search path tag is to be set depends on - your system, please refer to ld(1) for the exact information on your - system. As an example, the way to ensure the DT_RUNPATH is set on - Debian GNU/Linux systems rather than DT_RPATH is to tell the linker to - set new dtags, like this: - - $ ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \ - '-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)' - - It might be worth noting that some/most ELF systems implement support - for runtime search path relative to the directory containing current - executable, by interpreting $ORIGIN along with some other internal - variables. Consult your system documentation. - - Linking your application - ------------------------ - - Third-party applications dynamically linked with OpenSSL (or any other) - shared library face exactly the same problem with non-default locations. - The OpenSSL config options mentioned above might or might not have bearing - on linking of the target application. "Might" means that under some - circumstances it would be sufficient to link with OpenSSL shared library - "naturally", i.e. with -L/whatever/path -lssl -lcrypto. But there are - also cases when you'd have to explicitly specify runtime search path - when linking your application. Consult your system documentation and use - above section as inspiration... - - Shared OpenSSL builds also install static libraries. Linking with the - latter is likely to require special care, because linkers usually look - for shared libraries first and tend to remain "blind" to static OpenSSL - libraries. Referring to system documentation would suffice, if not for - a corner case. On AIX static libraries (in shared build) are named - differently, add _a suffix to link with them, e.g. -lcrypto_a. diff --git a/README b/README deleted file mode 100644 --- a/README +++ /dev/null @@ -1,93 +0,0 @@ - - OpenSSL 1.1.1t 7 Feb 2023 - - Copyright (c) 1998-2022 The OpenSSL Project - Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson - All rights reserved. - - DESCRIPTION - ----------- - - The OpenSSL Project is a collaborative effort to develop a robust, - commercial-grade, fully featured, and Open Source toolkit implementing the - Transport Layer Security (TLS) protocols (including SSLv3) as well as a - full-strength general purpose cryptographic library. - - OpenSSL is descended from the SSLeay library developed by Eric A. Young - and Tim J. Hudson. The OpenSSL toolkit is licensed under a dual-license (the - OpenSSL license plus the SSLeay license), which means that you are free to - get and use it for commercial and non-commercial purposes as long as you - fulfill the conditions of both licenses. - - OVERVIEW - -------- - - The OpenSSL toolkit includes: - - libssl (with platform specific naming): - Provides the client and server-side implementations for SSLv3 and TLS. - - libcrypto (with platform specific naming): - Provides general cryptographic and X.509 support needed by SSL/TLS but - not logically part of it. - - openssl: - A command line tool that can be used for: - Creation of key parameters - Creation of X.509 certificates, CSRs and CRLs - Calculation of message digests - Encryption and decryption - SSL/TLS client and server tests - Handling of S/MIME signed or encrypted mail - And more... - - INSTALLATION - ------------ - - See the appropriate file: - INSTALL Linux, Unix, Windows, OpenVMS, ... - NOTES.* INSTALL addendums for different platforms - - SUPPORT - ------- - - See the OpenSSL website www.openssl.org for details on how to obtain - commercial technical support. Free community support is available through the - openssl-users email list (see - https://www.openssl.org/community/mailinglists.html for further details). - - If you have any problems with OpenSSL then please take the following steps - first: - - - Download the latest version from the repository - to see if the problem has already been addressed - - Configure with no-asm - - Remove compiler optimization flags - - If you wish to report a bug then please include the following information - and create an issue on GitHub: - - - OpenSSL version: output of 'openssl version -a' - - Configuration data: output of 'perl configdata.pm --dump' - - OS Name, Version, Hardware platform - - Compiler Details (name, version) - - Application Details (name, version) - - Problem Description (steps that will reproduce the problem, if known) - - Stack Traceback (if the application dumps core) - - Just because something doesn't work the way you expect does not mean it - is necessarily a bug in OpenSSL. Use the openssl-users email list for this type - of query. - - HOW TO CONTRIBUTE TO OpenSSL - ---------------------------- - - See CONTRIBUTING - - LEGALITIES - ---------- - - A number of nations restrict the use or export of cryptography. If you - are potentially subject to such restrictions you should seek competent - professional legal advice before attempting to develop or distribute - cryptographic code. diff --git a/README-ENGINES.md b/README-ENGINES.md new file mode 100644 --- /dev/null +++ b/README-ENGINES.md @@ -0,0 +1,316 @@ +Engines +======= + +Deprecation Note +---------------- + +The ENGINE API was introduced in OpenSSL version 0.9.6 as a low level +interface for adding alternative implementations of cryptographic +primitives, most notably for integrating hardware crypto devices. + +The ENGINE interface has its limitations and it has been superseeded +by the [PROVIDER API](README-PROVIDERS.md), it is deprecated in OpenSSL +version 3.0. The following documentation is retained as an aid for +users who need to maintain or support existing ENGINE implementations. +Support for new hardware devices or new algorithms should be added +via providers, and existing engines should be converted to providers +as soon as possible. + +Built-in ENGINE implementations +------------------------------- + +There are currently built-in ENGINE implementations for the following +crypto devices: + + * Microsoft CryptoAPI + * VIA Padlock + * nCipher CHIL + +In addition, dynamic binding to external ENGINE implementations is now +provided by a special ENGINE called "dynamic". See the "DYNAMIC ENGINE" +section below for details. + +At this stage, a number of things are still needed and are being worked on: + + 1. Integration of EVP support. + 2. Configuration support. + 3. Documentation! + +Integration of EVP support +-------------------------- + +With respect to EVP, this relates to support for ciphers and digests in +the ENGINE model so that alternative implementations of existing +algorithms/modes (or previously unimplemented ones) can be provided by +ENGINE implementations. + +Configuration support +--------------------- + +Configuration support currently exists in the ENGINE API itself, in the +form of "control commands". These allow an application to expose to the +user/admin the set of commands and parameter types a given ENGINE +implementation supports, and for an application to directly feed string +based input to those ENGINEs, in the form of name-value pairs. This is an +extensible way for ENGINEs to define their own "configuration" mechanisms +that are specific to a given ENGINE (eg. for a particular hardware +device) but that should be consistent across *all* OpenSSL-based +applications when they use that ENGINE. Work is in progress (or at least +in planning) for supporting these control commands from the CONF (or +NCONF) code so that applications using OpenSSL's existing configuration +file format can have ENGINE settings specified in much the same way. +Presently however, applications must use the ENGINE API itself to provide +such functionality. To see first hand the types of commands available +with the various compiled-in ENGINEs (see further down for dynamic +ENGINEs), use the "engine" openssl utility with full verbosity, i.e.: + + openssl engine -vvvv + +Documentation +------------- + +Documentation? Volunteers welcome! The source code is reasonably well +self-documenting, but some summaries and usage instructions are needed - +moreover, they are needed in the same POD format the existing OpenSSL +documentation is provided in. Any complete or incomplete contributions +would help make this happen. + +STABILITY & BUG-REPORTS +======================= + +What already exists is fairly stable as far as it has been tested, but +the test base has been a bit small most of the time. For the most part, +the vendors of the devices these ENGINEs support have contributed to the +development and/or testing of the implementations, and *usually* (with no +guarantees) have experience in using the ENGINE support to drive their +devices from common OpenSSL-based applications. Bugs and/or inexplicable +behaviour in using a specific ENGINE implementation should be sent to the +author of that implementation (if it is mentioned in the corresponding C +file), and in the case of implementations for commercial hardware +devices, also through whatever vendor support channels are available. If +none of this is possible, or the problem seems to be something about the +ENGINE API itself (ie. not necessarily specific to a particular ENGINE +implementation) then you should mail complete details to the relevant +OpenSSL mailing list. For a definition of "complete details", refer to +the OpenSSL "README" file. As for which list to send it to: + + * openssl-users: if you are *using* the ENGINE abstraction, either in an + pre-compiled application or in your own application code. + + * openssl-dev: if you are discussing problems with OpenSSL source code. + +USAGE +===== + +The default "openssl" ENGINE is always chosen when performing crypto +operations unless you specify otherwise. You must actively tell the +openssl utility commands to use anything else through a new command line +switch called "-engine". Also, if you want to use the ENGINE support in +your own code to do something similar, you must likewise explicitly +select the ENGINE implementation you want. + +Depending on the type of hardware, system, and configuration, "settings" +may need to be applied to an ENGINE for it to function as expected/hoped. +The recommended way of doing this is for the application to support +ENGINE "control commands" so that each ENGINE implementation can provide +whatever configuration primitives it might require and the application +can allow the user/admin (and thus the hardware vendor's support desk +also) to provide any such input directly to the ENGINE implementation. +This way, applications do not need to know anything specific to any +device, they only need to provide the means to carry such user/admin +input through to the ENGINE in question. Ie. this connects *you* (and +your helpdesk) to the specific ENGINE implementation (and device), and +allows application authors to not get buried in hassle supporting +arbitrary devices they know (and care) nothing about. + +A new "openssl" utility, "openssl engine", has been added in that allows +for testing and examination of ENGINE implementations. Basic usage +instructions are available by specifying the "-?" command line switch. + +DYNAMIC ENGINES +=============== + +The new "dynamic" ENGINE provides a low-overhead way to support ENGINE +implementations that aren't pre-compiled and linked into OpenSSL-based +applications. This could be because existing compiled-in implementations +have known problems and you wish to use a newer version with an existing +application. It could equally be because the application (or OpenSSL +library) you are using simply doesn't have support for the ENGINE you +wish to use, and the ENGINE provider (eg. hardware vendor) is providing +you with a self-contained implementation in the form of a shared-library. +The other use-case for "dynamic" is with applications that wish to +maintain the smallest foot-print possible and so do not link in various +ENGINE implementations from OpenSSL, but instead leaves you to provide +them, if you want them, in the form of "dynamic"-loadable +shared-libraries. It should be possible for hardware vendors to provide +their own shared-libraries to support arbitrary hardware to work with +applications based on OpenSSL 0.9.7 or later. If you're using an +application based on 0.9.7 (or later) and the support you desire is only +announced for versions later than the one you need, ask the vendor to +backport their ENGINE to the version you need. + +How does "dynamic" work? +------------------------ + +The dynamic ENGINE has a special flag in its implementation such that +every time application code asks for the 'dynamic' ENGINE, it in fact +gets its own copy of it. As such, multi-threaded code (or code that +multiplexes multiple uses of 'dynamic' in a single application in any +way at all) does not get confused by 'dynamic' being used to do many +independent things. Other ENGINEs typically don't do this so there is +only ever 1 ENGINE structure of its type (and reference counts are used +to keep order). The dynamic ENGINE itself provides absolutely no +cryptographic functionality, and any attempt to "initialise" the ENGINE +automatically fails. All it does provide are a few "control commands" +that can be used to control how it will load an external ENGINE +implementation from a shared-library. To see these control commands, +use the command-line; + + openssl engine -vvvv dynamic + +The "SO_PATH" control command should be used to identify the +shared-library that contains the ENGINE implementation, and "NO_VCHECK" +might possibly be useful if there is a minor version conflict and you +(or a vendor helpdesk) is convinced you can safely ignore it. +"ID" is probably only needed if a shared-library implements +multiple ENGINEs, but if you know the engine id you expect to be using, +it doesn't hurt to specify it (and this provides a sanity check if +nothing else). "LIST_ADD" is only required if you actually wish the +loaded ENGINE to be discoverable by application code later on using the +ENGINE's "id". For most applications, this isn't necessary - but some +application authors may have nifty reasons for using it. The "LOAD" +command is the only one that takes no parameters and is the command +that uses the settings from any previous commands to actually *load* +the shared-library ENGINE implementation. If this command succeeds, the +(copy of the) 'dynamic' ENGINE will magically morph into the ENGINE +that has been loaded from the shared-library. As such, any control +commands supported by the loaded ENGINE could then be executed as per +normal. Eg. if ENGINE "foo" is implemented in the shared-library +"libfoo.so" and it supports some special control command "CMD_FOO", the +following code would load and use it (NB: obviously this code has no +error checking); + + ENGINE *e = ENGINE_by_id("dynamic"); + ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0); + ENGINE_ctrl_cmd_string(e, "ID", "foo", 0); + ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0); + ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0); + +For testing, the "openssl engine" utility can be useful for this sort +of thing. For example the above code excerpt would achieve much the +same result as; + + openssl engine dynamic \ + -pre SO_PATH:/lib/libfoo.so \ + -pre ID:foo \ + -pre LOAD \ + -pre "CMD_FOO:some input data" + +Or to simply see the list of commands supported by the "foo" ENGINE; + + openssl engine -vvvv dynamic \ + -pre SO_PATH:/lib/libfoo.so \ + -pre ID:foo \ + -pre LOAD + +Applications that support the ENGINE API and more specifically, the +"control commands" mechanism, will provide some way for you to pass +such commands through to ENGINEs. As such, you would select "dynamic" +as the ENGINE to use, and the parameters/commands you pass would +control the *actual* ENGINE used. Each command is actually a name-value +pair and the value can sometimes be omitted (eg. the "LOAD" command). +Whilst the syntax demonstrated in "openssl engine" uses a colon to +separate the command name from the value, applications may provide +their own syntax for making that separation (eg. a win32 registry +key-value pair may be used by some applications). The reason for the +"-pre" syntax in the "openssl engine" utility is that some commands +might be issued to an ENGINE *after* it has been initialised for use. +Eg. if an ENGINE implementation requires a smart-card to be inserted +during initialisation (or a PIN to be typed, or whatever), there may be +a control command you can issue afterwards to "forget" the smart-card +so that additional initialisation is no longer possible. In +applications such as web-servers, where potentially volatile code may +run on the same host system, this may provide some arguable security +value. In such a case, the command would be passed to the ENGINE after +it has been initialised for use, and so the "-post" switch would be +used instead. Applications may provide a different syntax for +supporting this distinction, and some may simply not provide it at all +("-pre" is almost always what you're after, in reality). + +How do I build a "dynamic" ENGINE? +---------------------------------- + +This question is trickier - currently OpenSSL bundles various ENGINE +implementations that are statically built in, and any application that +calls the "ENGINE_load_builtin_engines()" function will automatically +have all such ENGINEs available (and occupying memory). Applications +that don't call that function have no ENGINEs available like that and +would have to use "dynamic" to load any such ENGINE - but on the other +hand such applications would only have the memory footprint of any +ENGINEs explicitly loaded using user/admin provided control commands. +The main advantage of not statically linking ENGINEs and only using +"dynamic" for hardware support is that any installation using no +"external" ENGINE suffers no unnecessary memory footprint from unused +ENGINEs. Likewise, installations that do require an ENGINE incur the +overheads from only *that* ENGINE once it has been loaded. + +Sounds good? Maybe, but currently building an ENGINE implementation as +a shared-library that can be loaded by "dynamic" isn't automated in +OpenSSL's build process. It can be done manually quite easily however. +Such a shared-library can either be built with any OpenSSL code it +needs statically linked in, or it can link dynamically against OpenSSL +if OpenSSL itself is built as a shared library. The instructions are +the same in each case, but in the former (statically linked any +dependencies on OpenSSL) you must ensure OpenSSL is built with +position-independent code ("PIC"). The default OpenSSL compilation may +already specify the relevant flags to do this, but you should consult +with your compiler documentation if you are in any doubt. + +This example will show building the "atalla" ENGINE in the +crypto/engine/ directory as a shared-library for use via the "dynamic" +ENGINE. + + 1. "cd" to the crypto/engine/ directory of a pre-compiled OpenSSL + source tree. + + 2. Recompile at least one source file so you can see all the compiler + flags (and syntax) being used to build normally. Eg; + + touch hw_atalla.c ; make + + will rebuild "hw_atalla.o" using all such flags. + + 3. Manually enter the same compilation line to compile the + "hw_atalla.c" file but with the following two changes; + * add "-DENGINE_DYNAMIC_SUPPORT" to the command line switches, + * change the output file from "hw_atalla.o" to something new, + eg. "tmp_atalla.o" + + 4. Link "tmp_atalla.o" into a shared-library using the top-level + OpenSSL libraries to resolve any dependencies. The syntax for doing + this depends heavily on your system/compiler and is a nightmare + known well to anyone who has worked with shared-library portability + before. 'gcc' on Linux, for example, would use the following syntax; + + gcc -shared -o dyn_atalla.so tmp_atalla.o -L../.. -lcrypto + + 5. Test your shared library using "openssl engine" as explained in the + previous section. Eg. from the top-level directory, you might try + + apps/openssl engine -vvvv dynamic \ + -pre SO_PATH:./crypto/engine/dyn_atalla.so -pre LOAD + +If the shared-library loads successfully, you will see both "-pre" +commands marked as "SUCCESS" and the list of control commands +displayed (because of "-vvvv") will be the control commands for the +*atalla* ENGINE (ie. *not* the 'dynamic' ENGINE). You can also add +the "-t" switch to the utility if you want it to try and initialise +the atalla ENGINE for use to test any possible hardware/driver issues. + +PROBLEMS +======== + +It seems like the ENGINE part doesn't work too well with CryptoSwift on Win32. +A quick test done right before the release showed that trying "openssl speed +-engine cswift" generated errors. If the DSO gets enabled, an attempt is made +to write at memory address 0x00000002. diff --git a/README-FIPS.md b/README-FIPS.md new file mode 100644 --- /dev/null +++ b/README-FIPS.md @@ -0,0 +1,86 @@ +OpenSSL FIPS support +==================== + +This release of OpenSSL includes a cryptographic module that can be +FIPS 140-2 validated. The module is implemented as an OpenSSL provider. +A provider is essentially a dynamically loadable module which implements +cryptographic algorithms, see the [README-PROVIDERS](README-PROVIDERS.md) file +for further details. + +A cryptographic module is only FIPS validated after it has gone through the complex +FIPS 140 validation process. As this process takes a very long time, it is not +possible to validate every minor release of OpenSSL. +If you need a FIPS validated module then you must ONLY generate a FIPS provider +using OpenSSL versions that have valid FIPS certificates. A FIPS certificate +contains a link to a Security Policy, and you MUST follow the instructions +in the Security Policy in order to be FIPS compliant. +See for information related to OpenSSL +FIPS certificates and Security Policies. + +Newer OpenSSL Releases that include security or bug fixes can be used to build +all other components (such as the core API's, TLS and the default, base and +legacy providers) without any restrictions, but the FIPS provider must be built +as specified in the Security Policy (normally with a different version of the +source code). + +The OpenSSL FIPS provider is a shared library called `fips.so` (on Unix), or +resp. `fips.dll` (on Windows). The FIPS provider does not get built and +installed automatically. To enable it, you need to configure OpenSSL using +the `enable-fips` option. + +Installing the FIPS module +========================== + +The following is only a guide. +Please read the Security Policy for up to date installation instructions. + +If the FIPS provider is enabled, it gets installed automatically during the +normal installation process. Simply follow the normal procedure (configure, +make, make test, make install) as described in the [INSTALL](INSTALL.md) file. + +For example, on Unix the final command + + $ make install + +effectively executes the following install targets + + $ make install_sw + $ make install_ssldirs + $ make install_docs + $ make install_fips # for `enable-fips` only + +The `install_fips` make target can also be invoked explicitly to install +the FIPS provider independently, without installing the rest of OpenSSL. + +The Installation of the FIPS provider consists of two steps. In the first step, +the shared library is copied to its installed location, which by default is + + /usr/local/lib/ossl-modules/fips.so on Unix, and + C:\Program Files\OpenSSL\lib\ossl-modules\fips.dll on Windows. + +In the second step, the `openssl fipsinstall` command is executed, which completes +the installation by doing the following two things: + +- Runs the FIPS module self tests +- Generates the so-called FIPS module configuration file containing information + about the module such as the self test status, and the module checksum. + +The FIPS module must have the self tests run, and the FIPS module config file +output generated on every machine that it is to be used on. You must not copy +the FIPS module config file output data from one machine to another. + +On Unix the `openssl fipsinstall` command will be invoked as follows by default: + + $ openssl fipsinstall -out /usr/local/ssl/fipsmodule.cnf -module /usr/local/lib/ossl-modules/fips.so + +If you configured OpenSSL to be installed to a different location, the paths will +vary accordingly. In the rare case that you need to install the fipsmodule.cnf +to non-standard location, you can execute the `openssl fipsinstall` command manually. + +Using the FIPS Module in applications +===================================== + +Documentation about using the FIPS module is available on the [fips_module(7)] +manual page. + + [fips_module(7)]: https://www.openssl.org/docs/man3.0/man7/fips_module.html diff --git a/README-PROVIDERS.md b/README-PROVIDERS.md new file mode 100644 --- /dev/null +++ b/README-PROVIDERS.md @@ -0,0 +1,145 @@ +Providers +========= + + - [Standard Providers](#standard-providers) + - [The Default Provider](#the-default-provider) + - [The Legacy Provider](#the-legacy-provider) + - [The FIPS Provider](#the-fips-provider) + - [The Base Provider](#the-base-provider) + - [The Null Provider](#the-null-provider) + - [Loading Providers](#loading-providers) + +Standard Providers +================== + +Providers are containers for algorithm implementations. Whenever a cryptographic +algorithm is used via the high level APIs a provider is selected. It is that +provider implementation that actually does the required work. There are five +providers distributed with OpenSSL. In the future we expect third parties to +distribute their own providers which can be added to OpenSSL dynamically. +Documentation about writing providers is available on the [provider(7)] +manual page. + + [provider(7)]: https://www.openssl.org/docs/man3.0/man7/provider.html + +The Default Provider +-------------------- + +The default provider collects together all of the standard built-in OpenSSL +algorithm implementations. If an application doesn't specify anything else +explicitly (e.g. in the application or via config), then this is the provider +that will be used. It is loaded automatically the first time that we try to +get an algorithm from a provider if no other provider has been loaded yet. +If another provider has already been loaded then it won't be loaded +automatically. Therefore if you want to use it in conjunction with other +providers then you must load it explicitly. + +This is a "built-in" provider which means that it is compiled and linked +into the libcrypto library and does not exist as a separate standalone module. + +The Legacy Provider +------------------- + +The legacy provider is a collection of legacy algorithms that are either no +longer in common use or considered insecure and strongly discouraged from use. +However, some applications may need to use these algorithms for backwards +compatibility reasons. This provider is **not** loaded by default. +This may mean that some applications upgrading from earlier versions of OpenSSL +may find that some algorithms are no longer available unless they load the +legacy provider explicitly. + +Algorithms in the legacy provider include MD2, MD4, MDC2, RMD160, CAST5, +BF (Blowfish), IDEA, SEED, RC2, RC4, RC5 and DES (but not 3DES). + +The FIPS Provider +----------------- + +The FIPS provider contains a sub-set of the algorithm implementations available +from the default provider, consisting of algorithms conforming to FIPS standards. +It is intended that this provider will be FIPS140-2 validated. + +In some cases there may be minor behavioural differences between algorithm +implementations in this provider compared to the equivalent algorithm in the +default provider. This is typically in order to conform to FIPS standards. + +The Base Provider +----------------- + +The base provider contains a small sub-set of non-cryptographic algorithms +available in the default provider. For example, it contains algorithms to +serialize and deserialize keys to files. If you do not load the default +provider then you should always load this one instead (in particular, if +you are using the FIPS provider). + +The Null Provider +----------------- + +The null provider is "built-in" to libcrypto and contains no algorithm +implementations. In order to guarantee that the default provider is not +automatically loaded, the null provider can be loaded instead. + +This can be useful if you are using non-default library contexts and want +to ensure that the default library context is never used unintentionally. + +Loading Providers +================= + +Providers to be loaded can be specified in the OpenSSL config file. +See the [config(5)] manual page for information about how to configure +providers via the config file, and how to automatically activate them. + + [config(5)]: https://www.openssl.org/docs/man3.0/man5/config.html + +The following is a minimal config file example to load and activate both +the legacy and the default provider in the default library context. + + openssl_conf = openssl_init + + [openssl_init] + providers = provider_sect + + [provider_sect] + default = default_sect + legacy = legacy_sect + + [default_sect] + activate = 1 + + [legacy_sect] + activate = 1 + +It is also possible to load providers programmatically. For example you can +load the legacy provider into the default library context as shown below. +Note that once you have explicitly loaded a provider into the library context +the default provider will no longer be automatically loaded. Therefore you will +often also want to explicitly load the default provider, as is done here: + + #include + #include + + #include + + int main(void) + { + OSSL_PROVIDER *legacy; + OSSL_PROVIDER *deflt; + + /* Load Multiple providers into the default (NULL) library context */ + legacy = OSSL_PROVIDER_load(NULL, "legacy"); + if (legacy == NULL) { + printf("Failed to load Legacy provider\n"); + exit(EXIT_FAILURE); + } + deflt = OSSL_PROVIDER_load(NULL, "default"); + if (deflt == NULL) { + printf("Failed to load Default provider\n"); + OSSL_PROVIDER_unload(legacy); + exit(EXIT_FAILURE); + } + + /* Rest of application */ + + OSSL_PROVIDER_unload(legacy); + OSSL_PROVIDER_unload(deflt); + exit(EXIT_SUCCESS); + } diff --git a/README.ENGINE b/README.ENGINE deleted file mode 100644 --- a/README.ENGINE +++ /dev/null @@ -1,287 +0,0 @@ - ENGINE - ====== - - With OpenSSL 0.9.6, a new component was added to support alternative - cryptography implementations, most commonly for interfacing with external - crypto devices (eg. accelerator cards). This component is called ENGINE, - and its presence in OpenSSL 0.9.6 (and subsequent bug-fix releases) - caused a little confusion as 0.9.6** releases were rolled in two - versions, a "standard" and an "engine" version. In development for 0.9.7, - the ENGINE code has been merged into the main branch and will be present - in the standard releases from 0.9.7 forwards. - - There are currently built-in ENGINE implementations for the following - crypto devices: - - o Microsoft CryptoAPI - o VIA Padlock - o nCipher CHIL - - In addition, dynamic binding to external ENGINE implementations is now - provided by a special ENGINE called "dynamic". See the "DYNAMIC ENGINE" - section below for details. - - At this stage, a number of things are still needed and are being worked on: - - 1 Integration of EVP support. - 2 Configuration support. - 3 Documentation! - -1 With respect to EVP, this relates to support for ciphers and digests in - the ENGINE model so that alternative implementations of existing - algorithms/modes (or previously unimplemented ones) can be provided by - ENGINE implementations. - -2 Configuration support currently exists in the ENGINE API itself, in the - form of "control commands". These allow an application to expose to the - user/admin the set of commands and parameter types a given ENGINE - implementation supports, and for an application to directly feed string - based input to those ENGINEs, in the form of name-value pairs. This is an - extensible way for ENGINEs to define their own "configuration" mechanisms - that are specific to a given ENGINE (eg. for a particular hardware - device) but that should be consistent across *all* OpenSSL-based - applications when they use that ENGINE. Work is in progress (or at least - in planning) for supporting these control commands from the CONF (or - NCONF) code so that applications using OpenSSL's existing configuration - file format can have ENGINE settings specified in much the same way. - Presently however, applications must use the ENGINE API itself to provide - such functionality. To see first hand the types of commands available - with the various compiled-in ENGINEs (see further down for dynamic - ENGINEs), use the "engine" openssl utility with full verbosity, ie; - openssl engine -vvvv - -3 Documentation? Volunteers welcome! The source code is reasonably well - self-documenting, but some summaries and usage instructions are needed - - moreover, they are needed in the same POD format the existing OpenSSL - documentation is provided in. Any complete or incomplete contributions - would help make this happen. - - STABILITY & BUG-REPORTS - ======================= - - What already exists is fairly stable as far as it has been tested, but - the test base has been a bit small most of the time. For the most part, - the vendors of the devices these ENGINEs support have contributed to the - development and/or testing of the implementations, and *usually* (with no - guarantees) have experience in using the ENGINE support to drive their - devices from common OpenSSL-based applications. Bugs and/or inexplicable - behaviour in using a specific ENGINE implementation should be sent to the - author of that implementation (if it is mentioned in the corresponding C - file), and in the case of implementations for commercial hardware - devices, also through whatever vendor support channels are available. If - none of this is possible, or the problem seems to be something about the - ENGINE API itself (ie. not necessarily specific to a particular ENGINE - implementation) then you should mail complete details to the relevant - OpenSSL mailing list. For a definition of "complete details", refer to - the OpenSSL "README" file. As for which list to send it to; - - openssl-users: if you are *using* the ENGINE abstraction, either in an - pre-compiled application or in your own application code. - - openssl-dev: if you are discussing problems with OpenSSL source code. - - USAGE - ===== - - The default "openssl" ENGINE is always chosen when performing crypto - operations unless you specify otherwise. You must actively tell the - openssl utility commands to use anything else through a new command line - switch called "-engine". Also, if you want to use the ENGINE support in - your own code to do something similar, you must likewise explicitly - select the ENGINE implementation you want. - - Depending on the type of hardware, system, and configuration, "settings" - may need to be applied to an ENGINE for it to function as expected/hoped. - The recommended way of doing this is for the application to support - ENGINE "control commands" so that each ENGINE implementation can provide - whatever configuration primitives it might require and the application - can allow the user/admin (and thus the hardware vendor's support desk - also) to provide any such input directly to the ENGINE implementation. - This way, applications do not need to know anything specific to any - device, they only need to provide the means to carry such user/admin - input through to the ENGINE in question. Ie. this connects *you* (and - your helpdesk) to the specific ENGINE implementation (and device), and - allows application authors to not get buried in hassle supporting - arbitrary devices they know (and care) nothing about. - - A new "openssl" utility, "openssl engine", has been added in that allows - for testing and examination of ENGINE implementations. Basic usage - instructions are available by specifying the "-?" command line switch. - - DYNAMIC ENGINES - =============== - - The new "dynamic" ENGINE provides a low-overhead way to support ENGINE - implementations that aren't pre-compiled and linked into OpenSSL-based - applications. This could be because existing compiled-in implementations - have known problems and you wish to use a newer version with an existing - application. It could equally be because the application (or OpenSSL - library) you are using simply doesn't have support for the ENGINE you - wish to use, and the ENGINE provider (eg. hardware vendor) is providing - you with a self-contained implementation in the form of a shared-library. - The other use-case for "dynamic" is with applications that wish to - maintain the smallest foot-print possible and so do not link in various - ENGINE implementations from OpenSSL, but instead leaves you to provide - them, if you want them, in the form of "dynamic"-loadable - shared-libraries. It should be possible for hardware vendors to provide - their own shared-libraries to support arbitrary hardware to work with - applications based on OpenSSL 0.9.7 or later. If you're using an - application based on 0.9.7 (or later) and the support you desire is only - announced for versions later than the one you need, ask the vendor to - backport their ENGINE to the version you need. - - How does "dynamic" work? - ------------------------ - The dynamic ENGINE has a special flag in its implementation such that - every time application code asks for the 'dynamic' ENGINE, it in fact - gets its own copy of it. As such, multi-threaded code (or code that - multiplexes multiple uses of 'dynamic' in a single application in any - way at all) does not get confused by 'dynamic' being used to do many - independent things. Other ENGINEs typically don't do this so there is - only ever 1 ENGINE structure of its type (and reference counts are used - to keep order). The dynamic ENGINE itself provides absolutely no - cryptographic functionality, and any attempt to "initialise" the ENGINE - automatically fails. All it does provide are a few "control commands" - that can be used to control how it will load an external ENGINE - implementation from a shared-library. To see these control commands, - use the command-line; - - openssl engine -vvvv dynamic - - The "SO_PATH" control command should be used to identify the - shared-library that contains the ENGINE implementation, and "NO_VCHECK" - might possibly be useful if there is a minor version conflict and you - (or a vendor helpdesk) is convinced you can safely ignore it. - "ID" is probably only needed if a shared-library implements - multiple ENGINEs, but if you know the engine id you expect to be using, - it doesn't hurt to specify it (and this provides a sanity check if - nothing else). "LIST_ADD" is only required if you actually wish the - loaded ENGINE to be discoverable by application code later on using the - ENGINE's "id". For most applications, this isn't necessary - but some - application authors may have nifty reasons for using it. The "LOAD" - command is the only one that takes no parameters and is the command - that uses the settings from any previous commands to actually *load* - the shared-library ENGINE implementation. If this command succeeds, the - (copy of the) 'dynamic' ENGINE will magically morph into the ENGINE - that has been loaded from the shared-library. As such, any control - commands supported by the loaded ENGINE could then be executed as per - normal. Eg. if ENGINE "foo" is implemented in the shared-library - "libfoo.so" and it supports some special control command "CMD_FOO", the - following code would load and use it (NB: obviously this code has no - error checking); - - ENGINE *e = ENGINE_by_id("dynamic"); - ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0); - ENGINE_ctrl_cmd_string(e, "ID", "foo", 0); - ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0); - ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0); - - For testing, the "openssl engine" utility can be useful for this sort - of thing. For example the above code excerpt would achieve much the - same result as; - - openssl engine dynamic \ - -pre SO_PATH:/lib/libfoo.so \ - -pre ID:foo \ - -pre LOAD \ - -pre "CMD_FOO:some input data" - - Or to simply see the list of commands supported by the "foo" ENGINE; - - openssl engine -vvvv dynamic \ - -pre SO_PATH:/lib/libfoo.so \ - -pre ID:foo \ - -pre LOAD - - Applications that support the ENGINE API and more specifically, the - "control commands" mechanism, will provide some way for you to pass - such commands through to ENGINEs. As such, you would select "dynamic" - as the ENGINE to use, and the parameters/commands you pass would - control the *actual* ENGINE used. Each command is actually a name-value - pair and the value can sometimes be omitted (eg. the "LOAD" command). - Whilst the syntax demonstrated in "openssl engine" uses a colon to - separate the command name from the value, applications may provide - their own syntax for making that separation (eg. a win32 registry - key-value pair may be used by some applications). The reason for the - "-pre" syntax in the "openssl engine" utility is that some commands - might be issued to an ENGINE *after* it has been initialised for use. - Eg. if an ENGINE implementation requires a smart-card to be inserted - during initialisation (or a PIN to be typed, or whatever), there may be - a control command you can issue afterwards to "forget" the smart-card - so that additional initialisation is no longer possible. In - applications such as web-servers, where potentially volatile code may - run on the same host system, this may provide some arguable security - value. In such a case, the command would be passed to the ENGINE after - it has been initialised for use, and so the "-post" switch would be - used instead. Applications may provide a different syntax for - supporting this distinction, and some may simply not provide it at all - ("-pre" is almost always what you're after, in reality). - - How do I build a "dynamic" ENGINE? - ---------------------------------- - This question is trickier - currently OpenSSL bundles various ENGINE - implementations that are statically built in, and any application that - calls the "ENGINE_load_builtin_engines()" function will automatically - have all such ENGINEs available (and occupying memory). Applications - that don't call that function have no ENGINEs available like that and - would have to use "dynamic" to load any such ENGINE - but on the other - hand such applications would only have the memory footprint of any - ENGINEs explicitly loaded using user/admin provided control commands. - The main advantage of not statically linking ENGINEs and only using - "dynamic" for hardware support is that any installation using no - "external" ENGINE suffers no unnecessary memory footprint from unused - ENGINEs. Likewise, installations that do require an ENGINE incur the - overheads from only *that* ENGINE once it has been loaded. - - Sounds good? Maybe, but currently building an ENGINE implementation as - a shared-library that can be loaded by "dynamic" isn't automated in - OpenSSL's build process. It can be done manually quite easily however. - Such a shared-library can either be built with any OpenSSL code it - needs statically linked in, or it can link dynamically against OpenSSL - if OpenSSL itself is built as a shared library. The instructions are - the same in each case, but in the former (statically linked any - dependencies on OpenSSL) you must ensure OpenSSL is built with - position-independent code ("PIC"). The default OpenSSL compilation may - already specify the relevant flags to do this, but you should consult - with your compiler documentation if you are in any doubt. - - This example will show building the "atalla" ENGINE in the - crypto/engine/ directory as a shared-library for use via the "dynamic" - ENGINE. - 1) "cd" to the crypto/engine/ directory of a pre-compiled OpenSSL - source tree. - 2) Recompile at least one source file so you can see all the compiler - flags (and syntax) being used to build normally. Eg; - touch hw_atalla.c ; make - will rebuild "hw_atalla.o" using all such flags. - 3) Manually enter the same compilation line to compile the - "hw_atalla.c" file but with the following two changes; - (a) add "-DENGINE_DYNAMIC_SUPPORT" to the command line switches, - (b) change the output file from "hw_atalla.o" to something new, - eg. "tmp_atalla.o" - 4) Link "tmp_atalla.o" into a shared-library using the top-level - OpenSSL libraries to resolve any dependencies. The syntax for doing - this depends heavily on your system/compiler and is a nightmare - known well to anyone who has worked with shared-library portability - before. 'gcc' on Linux, for example, would use the following syntax; - gcc -shared -o dyn_atalla.so tmp_atalla.o -L../.. -lcrypto - 5) Test your shared library using "openssl engine" as explained in the - previous section. Eg. from the top-level directory, you might try; - apps/openssl engine -vvvv dynamic \ - -pre SO_PATH:./crypto/engine/dyn_atalla.so -pre LOAD - If the shared-library loads successfully, you will see both "-pre" - commands marked as "SUCCESS" and the list of control commands - displayed (because of "-vvvv") will be the control commands for the - *atalla* ENGINE (ie. *not* the 'dynamic' ENGINE). You can also add - the "-t" switch to the utility if you want it to try and initialise - the atalla ENGINE for use to test any possible hardware/driver - issues. - - PROBLEMS - ======== - - It seems like the ENGINE part doesn't work too well with CryptoSwift on Win32. - A quick test done right before the release showed that trying "openssl speed - -engine cswift" generated errors. If the DSO gets enabled, an attempt is made - to write at memory address 0x00000002. - diff --git a/README.FIPS b/README.FIPS deleted file mode 100644 --- a/README.FIPS +++ /dev/null @@ -1 +0,0 @@ -This release does not support a FIPS 140-2 validated module. diff --git a/README.md b/README.md new file mode 100644 --- /dev/null +++ b/README.md @@ -0,0 +1,224 @@ +Welcome to the OpenSSL Project +============================== + +[![openssl logo]][www.openssl.org] + +[![github actions ci badge]][github actions ci] +[![appveyor badge]][appveyor jobs] + +OpenSSL is a robust, commercial-grade, full-featured Open Source Toolkit +for the Transport Layer Security (TLS) protocol formerly known as the +Secure Sockets Layer (SSL) protocol. The protocol implementation is based +on a full-strength general purpose cryptographic library, which can also +be used stand-alone. + +OpenSSL is descended from the SSLeay library developed by Eric A. Young +and Tim J. Hudson. + +The official Home Page of the OpenSSL Project is [www.openssl.org]. + +Table of Contents +================= + + - [Overview](#overview) + - [Download](#download) + - [Build and Install](#build-and-install) + - [Documentation](#documentation) + - [License](#license) + - [Support](#support) + - [Contributing](#contributing) + - [Legalities](#legalities) + +Overview +======== + +The OpenSSL toolkit includes: + +- **libssl** + an implementation of all TLS protocol versions up to TLSv1.3 ([RFC 8446]). + +- **libcrypto** + a full-strength general purpose cryptographic library. It constitutes the + basis of the TLS implementation, but can also be used independently. + +- **openssl** + the OpenSSL command line tool, a swiss army knife for cryptographic tasks, + testing and analyzing. It can be used for + - creation of key parameters + - creation of X.509 certificates, CSRs and CRLs + - calculation of message digests + - encryption and decryption + - SSL/TLS client and server tests + - handling of S/MIME signed or encrypted mail + - and more... + +Download +======== + +For Production Use +------------------ + +Source code tarballs of the official releases can be downloaded from +[www.openssl.org/source](https://www.openssl.org/source). +The OpenSSL project does not distribute the toolkit in binary form. + +However, for a large variety of operating systems precompiled versions +of the OpenSSL toolkit are available. In particular on Linux and other +Unix operating systems it is normally recommended to link against the +precompiled shared libraries provided by the distributor or vendor. + +For Testing and Development +--------------------------- + +Although testing and development could in theory also be done using +the source tarballs, having a local copy of the git repository with +the entire project history gives you much more insight into the +code base. + +The official OpenSSL Git Repository is located at [git.openssl.org]. +There is a GitHub mirror of the repository at [github.com/openssl/openssl], +which is updated automatically from the former on every commit. + +A local copy of the Git Repository can be obtained by cloning it from +the original OpenSSL repository using + + git clone git://git.openssl.org/openssl.git + +or from the GitHub mirror using + + git clone https://github.com/openssl/openssl.git + +If you intend to contribute to OpenSSL, either to fix bugs or contribute +new features, you need to fork the OpenSSL repository openssl/openssl on +GitHub and clone your public fork instead. + + git clone https://github.com/yourname/openssl.git + +This is necessary, because all development of OpenSSL nowadays is done via +GitHub pull requests. For more details, see [Contributing](#contributing). + +Build and Install +================= + +After obtaining the Source, have a look at the [INSTALL](INSTALL.md) file for +detailed instructions about building and installing OpenSSL. For some +platforms, the installation instructions are amended by a platform specific +document. + + * [Notes for UNIX-like platforms](NOTES-UNIX.md) + * [Notes for Android platforms](NOTES-ANDROID.md) + * [Notes for Windows platforms](NOTES-WINDOWS.md) + * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md) + * [Notes for the OpenVMS platform](NOTES-VMS.md) + * [Notes on Perl](NOTES-PERL.md) + * [Notes on Valgrind](NOTES-VALGRIND.md) + +Specific notes on upgrading to OpenSSL 3.0 from previous versions can be found +in the [migration_guide(7ossl)] manual page. + +Documentation +============= + +Manual Pages +------------ + +The manual pages for the master branch and all current stable releases are +available online. + +- [OpenSSL master](https://www.openssl.org/docs/manmaster) +- [OpenSSL 3.0](https://www.openssl.org/docs/man3.0) +- [OpenSSL 1.1.1](https://www.openssl.org/docs/man1.1.1) + +Wiki +---- + +There is a Wiki at [wiki.openssl.org] which is currently not very active. +It contains a lot of useful information, not all of which is up to date. + +License +======= + +OpenSSL is licensed under the Apache License 2.0, which means that +you are free to get and use it for commercial and non-commercial +purposes as long as you fulfill its conditions. + +See the [LICENSE.txt](LICENSE.txt) file for more details. + +Support +======= + +There are various ways to get in touch. The correct channel depends on +your requirement. see the [SUPPORT](SUPPORT.md) file for more details. + +Contributing +============ + +If you are interested and willing to contribute to the OpenSSL project, +please take a look at the [CONTRIBUTING](CONTRIBUTING.md) file. + +Legalities +========== + +A number of nations restrict the use or export of cryptography. If you are +potentially subject to such restrictions you should seek legal advice before +attempting to develop or distribute cryptographic code. + +Copyright +========= + +Copyright (c) 1998-2022 The OpenSSL Project + +Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson + +All rights reserved. + + + +[www.openssl.org]: + + "OpenSSL Homepage" + +[git.openssl.org]: + + "OpenSSL Git Repository" + +[git.openssl.org]: + + "OpenSSL Git Repository" + +[github.com/openssl/openssl]: + + "OpenSSL GitHub Mirror" + +[wiki.openssl.org]: + + "OpenSSL Wiki" + +[migration_guide(7ossl)]: + + "OpenSSL Migration Guide" + +[RFC 8446]: + + + + +[openssl logo]: + doc/images/openssl.svg + "OpenSSL Logo" + +[github actions ci badge]: + + "GitHub Actions CI Status" + +[github actions ci]: + + "GitHub Actions CI" + +[appveyor badge]: + + "AppVeyor Build Status" + +[appveyor jobs]: + + "AppVeyor Jobs" diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,93 @@ +OpenSSL User Support resources +============================== + +See the for details on how to +obtain commercial technical support. + +If you have general questions about using OpenSSL +------------------------------------------------- + +In this case the [openssl-users] mailing list is the right place for you. +The list is not only watched by the OpenSSL team members, but also by many +other OpenSSL users. Here you will most likely get the answer to your questions. +An overview over the [mailing lists](#mailing-lists) can be found below. + +If you think you found a Bug +---------------------------- + +*NOTE: this section assumes that you want to report it or figure it out and +fix it. What's written here is not to be taken as a recipe for how to get a +working production installation* + +If you have any problems with OpenSSL then please take the following steps +first: + +- Search the mailing lists and/or the GitHub issues to find out whether + the problem has already been reported. +- Download the latest version from the repository to see if the problem + has already been addressed. +- Configure without assembler support (`no-asm`) and check whether the + problem persists. +- Remove compiler optimization flags. + +Please keep in mind: Just because something doesn't work the way you expect +does not mean it is necessarily a bug in OpenSSL. If you are not sure, +consider searching the mail archives and posting a question to the +[openssl-users] mailing list first. + +### Open an Issue + +If you wish to report a bug, please open an [issue][github-issues] on GitHub +and include the following information: + +- OpenSSL version: output of `openssl version -a` +- Configuration data: output of `perl configdata.pm --dump` +- OS Name, Version, Hardware platform +- Compiler Details (name, version) +- Application Details (name, version) +- Problem Description (steps that will reproduce the problem, if known) +- Stack Traceback (if the application dumps core) + +Not only errors in the software, also errors in the documentation, in +particular the manual pages, can be reported as issues. + +### Submit a Pull Request + +The fastest way to get a bug fixed is to fix it yourself ;-). If you are +experienced in programming and know how to fix the bug, you can open a +pull request. The details are covered in the [Contributing][contributing] section. + +Don't hesitate to open a pull request, even if it's only a small change +like a grammatical or typographical error in the documentation. + +Mailing Lists +============= + +The OpenSSL maintains a number of [mailing lists] for various purposes. +The most important lists are: + +- [openssl-users] for general questions about using the OpenSSL software + and discussions between OpenSSL users. + +- [openssl-announce] for official announcements to the OpenSSL community. + +- [openssl-project] for discussion about the development roadmap + and governance. + +Only subscribers can post to [openssl-users] or [openssl-project]. The +archives are made public, however. For more information, see the [mailing +lists] page. + +There was an [openssl-dev] list that has been discontinued since development +is now taking place in the form of GitHub pull requests. Although not active +anymore, the searchable archive may still contain useful information. + + + +[mailing lists]: https://www.openssl.org/community/mailinglists.html +[openssl-users]: https://mta.openssl.org/mailman/listinfo/openssl-users +[openssl-announce]: https://mta.openssl.org/mailman/listinfo/openssl-announce +[openssl-project]: https://mta.openssl.org/mailman/listinfo/openssl-project +[openssl-dev]: https://mta.openssl.org/mailman/listinfo/openssl-dev +[github-issues]: https://github.com/openssl/openssl/issues/new/choose +[contributing]: https://github.com/openssl/openssl/blob/master/CONTRIBUTING.md diff --git a/VERSION.dat b/VERSION.dat new file mode 100644 --- /dev/null +++ b/VERSION.dat @@ -0,0 +1,7 @@ +MAJOR=3 +MINOR=0 +PATCH=8 +PRE_RELEASE_TAG= +BUILD_METADATA= +RELEASE_DATE="7 Feb 2023" +SHLIB_VERSION=3 diff --git a/apps/CA.pl.in b/apps/CA.pl.in --- a/apps/CA.pl.in +++ b/apps/CA.pl.in @@ -1,7 +1,7 @@ #!{- $config{HASHBANGPERL} -} -# Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -14,57 +14,63 @@ use strict; use warnings; -my $openssl = "openssl"; -if(defined $ENV{'OPENSSL'}) { - $openssl = $ENV{'OPENSSL'}; -} else { - $ENV{'OPENSSL'} = $openssl; -} - my $verbose = 1; +my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); -my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} || ""; -my $DAYS = "-days 365"; -my $CADAYS = "-days 1095"; # 3 years +my $openssl = $ENV{'OPENSSL'} // "openssl"; +$ENV{'OPENSSL'} = $openssl; +my $OPENSSL_CONFIG = $ENV{"OPENSSL_CONFIG"} // ""; + +# Command invocations. my $REQ = "$openssl req $OPENSSL_CONFIG"; my $CA = "$openssl ca $OPENSSL_CONFIG"; my $VERIFY = "$openssl verify"; my $X509 = "$openssl x509"; my $PKCS12 = "$openssl pkcs12"; -# default openssl.cnf file has setup as per the following +# Default values for various configuration settings. my $CATOP = "./demoCA"; my $CAKEY = "cakey.pem"; my $CAREQ = "careq.pem"; my $CACERT = "cacert.pem"; my $CACRL = "crl.pem"; -my $DIRMODE = 0777; - +my $DAYS = "-days 365"; +my $CADAYS = "-days 1095"; # 3 years my $NEWKEY = "newkey.pem"; my $NEWREQ = "newreq.pem"; my $NEWCERT = "newcert.pem"; my $NEWP12 = "newcert.p12"; -my $RET = 0; + +# Commandline parsing +my %EXTRA; my $WHAT = shift @ARGV || ""; -my @OPENSSL_CMDS = ("req", "ca", "pkcs12", "x509", "verify"); -my %EXTRA = extra_args(\@ARGV, "-extra-"); -my $FILE; - -sub extra_args { - my ($args_ref, $arg_prefix) = @_; - my %eargs = map { - if ($_ < $#$args_ref) { - my ($arg, $value) = splice(@$args_ref, $_, 2); - $arg =~ s/$arg_prefix//; - ($arg, $value); - } else { - (); - } - } reverse grep($$args_ref[$_] =~ /$arg_prefix/, 0..$#$args_ref); - my %empty = map { ($_, "") } @OPENSSL_CMDS; - return (%empty, %eargs); +@ARGV = parse_extra(@ARGV); +my $RET = 0; + +# Split out "-extra-CMD value", and return new |@ARGV|. Fill in +# |EXTRA{CMD}| with list of values. +sub parse_extra +{ + foreach ( @OPENSSL_CMDS ) { + $EXTRA{$_} = ''; + } + + my @result; + while ( scalar(@_) > 0 ) { + my $arg = shift; + if ( $arg !~ m/-extra-([a-z0-9]+)/ ) { + push @result, $arg; + next; + } + $arg =~ s/-extra-//; + die("Unknown \"-${arg}-extra\" option, exiting") + unless scalar grep { $arg eq $_ } @OPENSSL_CMDS; + $EXTRA{$arg} .= " " . shift; + } + return @result; } + # See if reason for a CRL entry is valid; exit if not. sub crl_reason_ok { @@ -113,19 +119,25 @@ if ( $WHAT =~ /^(-\?|-h|-help)$/ ) { - print STDERR "usage: CA.pl -newcert | -newreq | -newreq-nodes | -xsign | -sign | -signCA | -signcert | -crl | -newca [-extra-cmd extra-params]\n"; - print STDERR " CA.pl -pkcs12 [-extra-pkcs12 extra-params] [certname]\n"; - print STDERR " CA.pl -verify [-extra-verify extra-params] certfile ...\n"; - print STDERR " CA.pl -revoke [-extra-ca extra-params] certfile [reason]\n"; + print STDERR <${CATOP}/index.txt"; close OUT; open OUT, ">${CATOP}/crlnumber"; @@ -145,6 +166,7 @@ close OUT; # ask user for existing CA certificate print "CA certificate filename (or enter to create)\n"; + my $FILE; $FILE = "" unless defined($FILE = ); $FILE =~ s{\R$}{}; if ($FILE ne "") { @@ -152,43 +174,43 @@ copy_pemfile($FILE,"${CATOP}/$CACERT", "CERTIFICATE"); } else { print "Making CA certificate ...\n"; - $RET = run("$REQ -new -keyout" - . " ${CATOP}/private/$CAKEY" + $RET = run("$REQ -new -keyout ${CATOP}/private/$CAKEY" . " -out ${CATOP}/$CAREQ $EXTRA{req}"); $RET = run("$CA -create_serial" . " -out ${CATOP}/$CACERT $CADAYS -batch" . " -keyfile ${CATOP}/private/$CAKEY -selfsign" - . " -extensions v3_ca $EXTRA{ca}" - . " -infiles ${CATOP}/$CAREQ") if $RET == 0; + . " -extensions v3_ca" + . " -infiles ${CATOP}/$CAREQ $EXTRA{ca}") if $RET == 0; print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; } } elsif ($WHAT eq '-pkcs12' ) { my $cname = $ARGV[0]; $cname = "My Certificate" unless defined $cname; $RET = run("$PKCS12 -in $NEWCERT -inkey $NEWKEY" - . " -certfile ${CATOP}/$CACERT" - . " -out $NEWP12" + . " -certfile ${CATOP}/$CACERT -out $NEWP12" . " -export -name \"$cname\" $EXTRA{pkcs12}"); print "PKCS #12 file is in $NEWP12\n" if $RET == 0; } elsif ($WHAT eq '-xsign' ) { - $RET = run("$CA -policy policy_anything $EXTRA{ca} -infiles $NEWREQ"); + $RET = run("$CA -policy policy_anything -infiles $NEWREQ $EXTRA{ca}"); } elsif ($WHAT eq '-sign' ) { - $RET = run("$CA -policy policy_anything -out $NEWCERT $EXTRA{ca} -infiles $NEWREQ"); + $RET = run("$CA -policy policy_anything -out $NEWCERT" + . " -infiles $NEWREQ $EXTRA{ca}"); print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signCA' ) { $RET = run("$CA -policy policy_anything -out $NEWCERT" - . " -extensions v3_ca $EXTRA{ca} -infiles $NEWREQ"); + . " -extensions v3_ca -infiles $NEWREQ $EXTRA{ca}"); print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signcert' ) { $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" . " -out tmp.pem $EXTRA{x509}"); $RET = run("$CA -policy policy_anything -out $NEWCERT" - . "$EXTRA{ca} -infiles tmp.pem") if $RET == 0; + . "-infiles tmp.pem $EXTRA{ca}") if $RET == 0; print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-verify' ) { my @files = @ARGV ? @ARGV : ( $NEWCERT ); - my $file; - foreach $file (@files) { + foreach my $file (@files) { + # -CAfile quoted for VMS, since the C RTL downcases all unquoted + # arguments to C programs my $status = run("$VERIFY \"-CAfile\" ${CATOP}/$CACERT $file $EXTRA{verify}"); $RET = $status if $status != 0; } diff --git a/apps/app_rand.c b/apps/app_rand.c deleted file mode 100644 --- a/apps/app_rand.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "apps.h" -#include -#include -#include -#include - -static char *save_rand_file; - -void app_RAND_load_conf(CONF *c, const char *section) -{ - const char *randfile = NCONF_get_string(c, section, "RANDFILE"); - - if (randfile == NULL) { - ERR_clear_error(); - return; - } - if (RAND_load_file(randfile, -1) < 0) { - BIO_printf(bio_err, "Can't load %s into RNG\n", randfile); - ERR_print_errors(bio_err); - } - if (save_rand_file == NULL) - save_rand_file = OPENSSL_strdup(randfile); -} - -static int loadfiles(char *name) -{ - char *p; - int last, ret = 1; - - for ( ; ; ) { - last = 0; - for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++) - continue; - if (*p == '\0') - last = 1; - *p = '\0'; - if (RAND_load_file(name, -1) < 0) { - BIO_printf(bio_err, "Can't load %s into RNG\n", name); - ERR_print_errors(bio_err); - ret = 0; - } - if (last) - break; - name = p + 1; - if (*name == '\0') - break; - } - return ret; -} - -void app_RAND_write(void) -{ - if (save_rand_file == NULL) - return; - if (RAND_write_file(save_rand_file) == -1) { - BIO_printf(bio_err, "Cannot write random bytes:\n"); - ERR_print_errors(bio_err); - } - OPENSSL_free(save_rand_file); - save_rand_file = NULL; -} - - -/* - * See comments in opt_verify for explanation of this. - */ -enum r_range { OPT_R_ENUM }; - -int opt_rand(int opt) -{ - switch ((enum r_range)opt) { - case OPT_R__FIRST: - case OPT_R__LAST: - break; - case OPT_R_RAND: - return loadfiles(opt_arg()); - break; - case OPT_R_WRITERAND: - OPENSSL_free(save_rand_file); - save_rand_file = OPENSSL_strdup(opt_arg()); - break; - } - return 1; -} diff --git a/apps/apps.h b/apps/apps.h deleted file mode 100644 --- a/apps/apps.h +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright 1995-2022 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 - */ - -#ifndef OSSL_APPS_H -# define OSSL_APPS_H - -# include "e_os.h" /* struct timeval for DTLS */ -# include "internal/nelem.h" -# include - -# include -# ifndef OPENSSL_NO_POSIX_IO -# include -# include -# endif - -# include -# include -# include -# include -# include -# include -# include -# include -# include - -# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE) -# define openssl_fdset(a,b) FD_SET((unsigned int)a, b) -# else -# define openssl_fdset(a,b) FD_SET(a, b) -# endif - -/* - * quick macro when you need to pass an unsigned char instead of a char. - * this is true for some implementations of the is*() functions, for - * example. - */ -#define _UC(c) ((unsigned char)(c)) - -void app_RAND_load_conf(CONF *c, const char *section); -void app_RAND_write(void); - -extern char *default_config_file; -extern BIO *bio_in; -extern BIO *bio_out; -extern BIO *bio_err; -extern const unsigned char tls13_aes128gcmsha256_id[]; -extern const unsigned char tls13_aes256gcmsha384_id[]; -extern BIO_ADDR *ourpeer; - -BIO_METHOD *apps_bf_prefix(void); -/* - * The control used to set the prefix with BIO_ctrl() - * We make it high enough so the chance of ever clashing with the BIO library - * remains unlikely for the foreseeable future and beyond. - */ -#define PREFIX_CTRL_SET_PREFIX (1 << 15) -/* - * apps_bf_prefix() returns a dynamically created BIO_METHOD, which we - * need to destroy at some point. When created internally, it's stored - * in an internal pointer which can be freed with the following function - */ -void destroy_prefix_method(void); - -BIO *dup_bio_in(int format); -BIO *dup_bio_out(int format); -BIO *dup_bio_err(int format); -BIO *bio_open_owner(const char *filename, int format, int private); -BIO *bio_open_default(const char *filename, char mode, int format); -BIO *bio_open_default_quiet(const char *filename, char mode, int format); -CONF *app_load_config_bio(BIO *in, const char *filename); -CONF *app_load_config(const char *filename); -CONF *app_load_config_quiet(const char *filename); -int app_load_modules(const CONF *config); -void unbuffer(FILE *fp); -void wait_for_async(SSL *s); -# if defined(OPENSSL_SYS_MSDOS) -int has_stdin_waiting(void); -# endif - -void corrupt_signature(const ASN1_STRING *signature); -int set_cert_times(X509 *x, const char *startdate, const char *enddate, - int days); - -/* - * Common verification options. - */ -# define OPT_V_ENUM \ - OPT_V__FIRST=2000, \ - OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \ - OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \ - OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \ - OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \ - OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \ - OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \ - OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \ - OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \ - OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \ - OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \ - OPT_V__LAST - -# define OPT_V_OPTIONS \ - { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \ - { "purpose", OPT_V_PURPOSE, 's', \ - "certificate chain purpose"}, \ - { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \ - { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \ - "chain depth limit" }, \ - { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \ - "chain authentication security level" }, \ - { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \ - { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \ - "expected peer hostname" }, \ - { "verify_email", OPT_V_VERIFY_EMAIL, 's', \ - "expected peer email" }, \ - { "verify_ip", OPT_V_VERIFY_IP, 's', \ - "expected peer IP address" }, \ - { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \ - "permit unhandled critical extensions"}, \ - { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \ - { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \ - { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \ - { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \ - { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \ - "set policy variable require-explicit-policy"}, \ - { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \ - "set policy variable inhibit-any-policy"}, \ - { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \ - "set policy variable inhibit-policy-mapping"}, \ - { "x509_strict", OPT_V_X509_STRICT, '-', \ - "disable certificate compatibility work-arounds"}, \ - { "extended_crl", OPT_V_EXTENDED_CRL, '-', \ - "enable extended CRL features"}, \ - { "use_deltas", OPT_V_USE_DELTAS, '-', \ - "use delta CRLs"}, \ - { "policy_print", OPT_V_POLICY_PRINT, '-', \ - "print policy processing diagnostics"}, \ - { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \ - "check root CA self-signatures"}, \ - { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \ - "search trust store first (default)" }, \ - { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \ - { "suiteB_128", OPT_V_SUITEB_128, '-', \ - "Suite B 128-bit mode allowing 192-bit algorithms"}, \ - { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \ - { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \ - "accept chains anchored by intermediate trust-store CAs"}, \ - { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \ - { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \ - { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" } - -# define OPT_V_CASES \ - OPT_V__FIRST: case OPT_V__LAST: break; \ - case OPT_V_POLICY: \ - case OPT_V_PURPOSE: \ - case OPT_V_VERIFY_NAME: \ - case OPT_V_VERIFY_DEPTH: \ - case OPT_V_VERIFY_AUTH_LEVEL: \ - case OPT_V_ATTIME: \ - case OPT_V_VERIFY_HOSTNAME: \ - case OPT_V_VERIFY_EMAIL: \ - case OPT_V_VERIFY_IP: \ - case OPT_V_IGNORE_CRITICAL: \ - case OPT_V_ISSUER_CHECKS: \ - case OPT_V_CRL_CHECK: \ - case OPT_V_CRL_CHECK_ALL: \ - case OPT_V_POLICY_CHECK: \ - case OPT_V_EXPLICIT_POLICY: \ - case OPT_V_INHIBIT_ANY: \ - case OPT_V_INHIBIT_MAP: \ - case OPT_V_X509_STRICT: \ - case OPT_V_EXTENDED_CRL: \ - case OPT_V_USE_DELTAS: \ - case OPT_V_POLICY_PRINT: \ - case OPT_V_CHECK_SS_SIG: \ - case OPT_V_TRUSTED_FIRST: \ - case OPT_V_SUITEB_128_ONLY: \ - case OPT_V_SUITEB_128: \ - case OPT_V_SUITEB_192: \ - case OPT_V_PARTIAL_CHAIN: \ - case OPT_V_NO_ALT_CHAINS: \ - case OPT_V_NO_CHECK_TIME: \ - case OPT_V_ALLOW_PROXY_CERTS - -/* - * Common "extended validation" options. - */ -# define OPT_X_ENUM \ - OPT_X__FIRST=1000, \ - OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \ - OPT_X_CERTFORM, OPT_X_KEYFORM, \ - OPT_X__LAST - -# define OPT_X_OPTIONS \ - { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \ - { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \ - { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \ - { "xchain_build", OPT_X_CHAIN_BUILD, '-', \ - "build certificate chain for the extended certificates"}, \ - { "xcertform", OPT_X_CERTFORM, 'F', \ - "format of Extended certificate (PEM or DER) PEM default " }, \ - { "xkeyform", OPT_X_KEYFORM, 'F', \ - "format of Extended certificate's key (PEM or DER) PEM default"} - -# define OPT_X_CASES \ - OPT_X__FIRST: case OPT_X__LAST: break; \ - case OPT_X_KEY: \ - case OPT_X_CERT: \ - case OPT_X_CHAIN: \ - case OPT_X_CHAIN_BUILD: \ - case OPT_X_CERTFORM: \ - case OPT_X_KEYFORM - -/* - * Common SSL options. - * Any changes here must be coordinated with ../ssl/ssl_conf.c - */ -# define OPT_S_ENUM \ - OPT_S__FIRST=3000, \ - OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \ - OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ - OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \ - OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ - OPT_S_PRIORITIZE_CHACHA, \ - OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ - OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ - OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ - OPT_S_MINPROTO, OPT_S_MAXPROTO, \ - OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST - -# define OPT_S_OPTIONS \ - {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \ - {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \ - {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \ - {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \ - {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \ - {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ - {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ - {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ - {"no_ticket", OPT_S_NOTICKET, '-', \ - "Disable use of TLS session tickets"}, \ - {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ - {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \ - "Enable use of legacy renegotiation (dangerous)"}, \ - {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \ - "Disable all renegotiation."}, \ - {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \ - "Allow initial connection to servers that don't support RI"}, \ - {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \ - "Disallow session resumption on renegotiation"}, \ - {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \ - "Disallow initial connection to servers that don't support RI"}, \ - {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ - "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ - {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ - "Prioritize ChaCha ciphers when preferred by clients"}, \ - {"strict", OPT_S_STRICT, '-', \ - "Enforce strict certificate checks as per TLS standard"}, \ - {"sigalgs", OPT_S_SIGALGS, 's', \ - "Signature algorithms to support (colon-separated list)" }, \ - {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \ - "Signature algorithms to support for client certificate" \ - " authentication (colon-separated list)" }, \ - {"groups", OPT_S_GROUPS, 's', \ - "Groups to advertise (colon-separated list)" }, \ - {"curves", OPT_S_CURVES, 's', \ - "Groups to advertise (colon-separated list)" }, \ - {"named_curve", OPT_S_NAMEDCURVE, 's', \ - "Elliptic curve used for ECDHE (server-side only)" }, \ - {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ - {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ - {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \ - {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \ - {"record_padding", OPT_S_RECORD_PADDING, 's', \ - "Block size to pad TLS 1.3 records to."}, \ - {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ - "Perform all sorts of protocol violations for testing purposes"}, \ - {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ - "Disable TLSv1.3 middlebox compat mode" } - -# define OPT_S_CASES \ - OPT_S__FIRST: case OPT_S__LAST: break; \ - case OPT_S_NOSSL3: \ - case OPT_S_NOTLS1: \ - case OPT_S_NOTLS1_1: \ - case OPT_S_NOTLS1_2: \ - case OPT_S_NOTLS1_3: \ - case OPT_S_BUGS: \ - case OPT_S_NO_COMP: \ - case OPT_S_COMP: \ - case OPT_S_NOTICKET: \ - case OPT_S_SERVERPREF: \ - case OPT_S_LEGACYRENEG: \ - case OPT_S_LEGACYCONN: \ - case OPT_S_ONRESUMP: \ - case OPT_S_NOLEGACYCONN: \ - case OPT_S_ALLOW_NO_DHE_KEX: \ - case OPT_S_PRIORITIZE_CHACHA: \ - case OPT_S_STRICT: \ - case OPT_S_SIGALGS: \ - case OPT_S_CLIENTSIGALGS: \ - case OPT_S_GROUPS: \ - case OPT_S_CURVES: \ - case OPT_S_NAMEDCURVE: \ - case OPT_S_CIPHER: \ - case OPT_S_CIPHERSUITES: \ - case OPT_S_RECORD_PADDING: \ - case OPT_S_NO_RENEGOTIATION: \ - case OPT_S_MINPROTO: \ - case OPT_S_MAXPROTO: \ - case OPT_S_DEBUGBROKE: \ - case OPT_S_NO_MIDDLEBOX - -#define IS_NO_PROT_FLAG(o) \ - (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ - || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3) - -/* - * Random state options. - */ -# define OPT_R_ENUM \ - OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST - -# define OPT_R_OPTIONS \ - {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \ - {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"} - -# define OPT_R_CASES \ - OPT_R__FIRST: case OPT_R__LAST: break; \ - case OPT_R_RAND: case OPT_R_WRITERAND - -/* - * Option parsing. - */ -extern const char OPT_HELP_STR[]; -extern const char OPT_MORE_STR[]; -typedef struct options_st { - const char *name; - int retval; - /* - * value type: - no value (also the value zero), n number, p positive - * number, u unsigned, l long, s string, < input file, > output file, - * f any format, F der/pem format, E der/pem/engine format identifier. - * l, n and u include zero; p does not. - */ - int valtype; - const char *helpstr; -} OPTIONS; - -/* - * A string/int pairing; widely use for option value lookup, hence the - * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use - * the "generic" name STRINT_PAIR. - */ -typedef struct string_int_pair_st { - const char *name; - int retval; -} OPT_PAIR, STRINT_PAIR; - -/* Flags to pass into opt_format; see FORMAT_xxx, below. */ -# define OPT_FMT_PEMDER (1L << 1) -# define OPT_FMT_PKCS12 (1L << 2) -# define OPT_FMT_SMIME (1L << 3) -# define OPT_FMT_ENGINE (1L << 4) -# define OPT_FMT_MSBLOB (1L << 5) -/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */ -# define OPT_FMT_NSS (1L << 7) -# define OPT_FMT_TEXT (1L << 8) -# define OPT_FMT_HTTP (1L << 9) -# define OPT_FMT_PVK (1L << 10) -# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) -# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) -# define OPT_FMT_ANY ( \ - OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ - OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ - OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) - -char *opt_progname(const char *argv0); -char *opt_getprog(void); -char *opt_init(int ac, char **av, const OPTIONS * o); -int opt_next(void); -int opt_format(const char *s, unsigned long flags, int *result); -int opt_int(const char *arg, int *result); -int opt_ulong(const char *arg, unsigned long *result); -int opt_long(const char *arg, long *result); -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ - defined(INTMAX_MAX) && defined(UINTMAX_MAX) -int opt_imax(const char *arg, intmax_t *result); -int opt_umax(const char *arg, uintmax_t *result); -#else -# define opt_imax opt_long -# define opt_umax opt_ulong -# define intmax_t long -# define uintmax_t unsigned long -#endif -int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); -int opt_cipher(const char *name, const EVP_CIPHER **cipherp); -int opt_md(const char *name, const EVP_MD **mdp); -char *opt_arg(void); -char *opt_flag(void); -char *opt_unknown(void); -char **opt_rest(void); -int opt_num_rest(void); -int opt_verify(int i, X509_VERIFY_PARAM *vpm); -int opt_rand(int i); -void opt_help(const OPTIONS * list); -int opt_format_error(const char *s, unsigned long flags); - -typedef struct args_st { - int size; - int argc; - char **argv; -} ARGS; - -/* - * VMS C only for now, implemented in vms_decc_init.c - * If other C compilers forget to terminate argv with NULL, this function - * can be re-used. - */ -char **copy_argv(int *argc, char *argv[]); -/* - * Win32-specific argv initialization that splits OS-supplied UNICODE - * command line string to array of UTF8-encoded strings. - */ -void win32_utf8argv(int *argc, char **argv[]); - - -# define PW_MIN_LENGTH 4 -typedef struct pw_cb_data { - const void *password; - const char *prompt_info; -} PW_CB_DATA; - -int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data); - -int setup_ui_method(void); -void destroy_ui_method(void); -const UI_METHOD *get_ui_method(void); - -int chopup_args(ARGS *arg, char *buf); -int dump_cert_text(BIO *out, X509 *x); -void print_name(BIO *out, const char *title, X509_NAME *nm, - unsigned long lflags); -void print_bignum_var(BIO *, const BIGNUM *, const char*, - int, unsigned char *); -void print_array(BIO *, const char *, int, const unsigned char *); -int set_nameopt(const char *arg); -unsigned long get_nameopt(void); -int set_cert_ex(unsigned long *flags, const char *arg); -int set_name_ex(unsigned long *flags, const char *arg); -int set_ext_copy(int *copy_type, const char *arg); -int copy_extensions(X509 *x, X509_REQ *req, int copy_type); -int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2); -int add_oid_section(CONF *conf); -X509 *load_cert(const char *file, int format, const char *cert_descrip); -X509_CRL *load_crl(const char *infile, int format); -EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, - const char *pass, ENGINE *e, const char *key_descrip); -EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, - const char *pass, ENGINE *e, const char *key_descrip); -int load_certs(const char *file, STACK_OF(X509) **certs, int format, - const char *pass, const char *cert_descrip); -int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, - const char *pass, const char *cert_descrip); -X509_STORE *setup_verify(const char *CAfile, const char *CApath, - int noCAfile, int noCApath); -__owur int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, - const char *CApath, int noCAfile, - int noCApath); - -#ifndef OPENSSL_NO_CT - -/* - * Sets the file to load the Certificate Transparency log list from. - * If path is NULL, loads from the default file path. - * Returns 1 on success, 0 otherwise. - */ -__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path); - -#endif - -ENGINE *setup_engine(const char *engine, int debug); -void release_engine(ENGINE *e); - -# ifndef OPENSSL_NO_OCSP -OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, - const char *host, const char *path, - const char *port, int use_ssl, - STACK_OF(CONF_VALUE) *headers, - int req_timeout); -# endif - -/* Functions defined in ca.c and also used in ocsp.c */ -int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, - ASN1_GENERALIZEDTIME **pinvtm, const char *str); - -# define DB_type 0 -# define DB_exp_date 1 -# define DB_rev_date 2 -# define DB_serial 3 /* index - unique */ -# define DB_file 4 -# define DB_name 5 /* index - unique when active and not - * disabled */ -# define DB_NUMBER 6 - -# define DB_TYPE_REV 'R' /* Revoked */ -# define DB_TYPE_EXP 'E' /* Expired */ -# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */ -# define DB_TYPE_SUSP 'S' /* Suspended */ - -typedef struct db_attr_st { - int unique_subject; -} DB_ATTR; -typedef struct ca_db_st { - DB_ATTR attributes; - TXT_DB *db; - char *dbfname; -# ifndef OPENSSL_NO_POSIX_IO - struct stat dbst; -# endif -} CA_DB; - -void* app_malloc(int sz, const char *what); - -/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */ -BIGNUM *load_serial(const char *serialfile, int *exists, int create, - ASN1_INTEGER **retai); -int save_serial(const char *serialfile, const char *suffix, - const BIGNUM *serial, ASN1_INTEGER **retai); -int rotate_serial(const char *serialfile, const char *new_suffix, - const char *old_suffix); -int rand_serial(BIGNUM *b, ASN1_INTEGER *ai); -CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr); -int index_index(CA_DB *db); -int save_index(const char *dbfile, const char *suffix, CA_DB *db); -int rotate_index(const char *dbfile, const char *new_suffix, - const char *old_suffix); -void free_index(CA_DB *db); -# define index_name_cmp_noconst(a, b) \ - index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ - (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) -int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); -int parse_yesno(const char *str, int def); - -X509_NAME *parse_name(const char *str, long chtype, int multirdn); -void policies_print(X509_STORE_CTX *ctx); -int bio_to_mem(unsigned char **out, int maxlen, BIO *in); -int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value); -int init_gen_str(EVP_PKEY_CTX **pctx, - const char *algname, ENGINE *e, int do_param); -int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, - STACK_OF(OPENSSL_STRING) *sigopts); -int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, - STACK_OF(OPENSSL_STRING) *sigopts); -int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, - STACK_OF(OPENSSL_STRING) *sigopts); - -extern char *psk_key; - - -unsigned char *next_protos_parse(size_t *outlen, const char *in); - -void print_cert_checks(BIO *bio, X509 *x, - const char *checkhost, - const char *checkemail, const char *checkip); - -void store_setup_crl_download(X509_STORE *st); - -/* See OPT_FMT_xxx, above. */ -/* On some platforms, it's important to distinguish between text and binary - * files. On some, there might even be specific file formats for different - * contents. The FORMAT_xxx macros are meant to express an intent with the - * file being read or created. - */ -# define B_FORMAT_TEXT 0x8000 -# define FORMAT_UNDEF 0 -# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */ -# define FORMAT_BINARY 2 /* Generic binary */ -# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */ -# define FORMAT_ASN1 4 /* ASN.1/DER */ -# define FORMAT_PEM (5 | B_FORMAT_TEXT) -# define FORMAT_PKCS12 6 -# define FORMAT_SMIME (7 | B_FORMAT_TEXT) -# define FORMAT_ENGINE 8 /* Not really a file format */ -# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */ -# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */ -# define FORMAT_MSBLOB 11 /* MS Key blob format */ -# define FORMAT_PVK 12 /* MS PVK file format */ -# define FORMAT_HTTP 13 /* Download using HTTP */ -# define FORMAT_NSS 14 /* NSS keylog format */ - -# define EXT_COPY_NONE 0 -# define EXT_COPY_ADD 1 -# define EXT_COPY_ALL 2 - -# define NETSCAPE_CERT_HDR "certificate" - -# define APP_PASS_LEN 1024 - -/* - * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits - * so that the first bit will never be one, so that the DER encoding - * rules won't force a leading octet. - */ -# define SERIAL_RAND_BITS 159 - -int app_isdir(const char *); -int app_access(const char *, int flag); -int fileno_stdin(void); -int fileno_stdout(void); -int raw_read_stdin(void *, int); -int raw_write_stdout(const void *, int); - -# define TM_START 0 -# define TM_STOP 1 -double app_tminterval(int stop, int usertime); - -void make_uppercase(char *string); - -typedef struct verify_options_st { - int depth; - int quiet; - int error; - int return_error; -} VERIFY_CB_ARGS; - -extern VERIFY_CB_ARGS verify_args; - -#endif diff --git a/apps/apps.c b/apps/apps.c deleted file mode 100644 --- a/apps/apps.c +++ /dev/null @@ -1,2796 +0,0 @@ -/* - * Copyright 1995-2022 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 - */ - -#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) -/* - * On VMS, you need to define this to get the declaration of fileno(). The - * value 2 is to make sure no function defined in POSIX-2 is left undefined. - */ -# define _POSIX_C_SOURCE 2 -#endif - -#include -#include -#include -#include -#ifndef OPENSSL_NO_POSIX_IO -# include -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef OPENSSL_NO_ENGINE -# include -#endif -#ifndef OPENSSL_NO_RSA -# include -#endif -#include -#include -#include "apps.h" - -#ifdef _WIN32 -static int WIN32_rename(const char *from, const char *to); -# define rename(from,to) WIN32_rename((from),(to)) -#endif - -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) -# include -#endif - -#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) -# define _kbhit kbhit -#endif - -typedef struct { - const char *name; - unsigned long flag; - unsigned long mask; -} NAME_EX_TBL; - -static UI_METHOD *ui_method = NULL; -static const UI_METHOD *ui_fallback_method = NULL; - -static int set_table_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl); -static int set_multi_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl); - -int app_init(long mesgwin); - -int chopup_args(ARGS *arg, char *buf) -{ - int quoted; - char c = '\0', *p = NULL; - - arg->argc = 0; - if (arg->size == 0) { - arg->size = 20; - arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space"); - } - - for (p = buf;;) { - /* Skip whitespace. */ - while (*p && isspace(_UC(*p))) - p++; - if (!*p) - break; - - /* The start of something good :-) */ - if (arg->argc >= arg->size) { - char **tmp; - arg->size += 20; - tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size); - if (tmp == NULL) - return 0; - arg->argv = tmp; - } - quoted = *p == '\'' || *p == '"'; - if (quoted) - c = *p++; - arg->argv[arg->argc++] = p; - - /* now look for the end of this */ - if (quoted) { - while (*p && *p != c) - p++; - *p++ = '\0'; - } else { - while (*p && !isspace(_UC(*p))) - p++; - if (*p) - *p++ = '\0'; - } - } - arg->argv[arg->argc] = NULL; - return 1; -} - -#ifndef APP_INIT -int app_init(long mesgwin) -{ - return 1; -} -#endif - -int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, - const char *CApath, int noCAfile, int noCApath) -{ - if (CAfile == NULL && CApath == NULL) { - if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) - return 0; - if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) - return 0; - - return 1; - } - return SSL_CTX_load_verify_locations(ctx, CAfile, CApath); -} - -#ifndef OPENSSL_NO_CT - -int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path) -{ - if (path == NULL) - return SSL_CTX_set_default_ctlog_list_file(ctx); - - return SSL_CTX_set_ctlog_list_file(ctx, path); -} - -#endif - -static unsigned long nmflag = 0; -static char nmflag_set = 0; - -int set_nameopt(const char *arg) -{ - int ret = set_name_ex(&nmflag, arg); - - if (ret) - nmflag_set = 1; - - return ret; -} - -unsigned long get_nameopt(void) -{ - return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; -} - -int dump_cert_text(BIO *out, X509 *x) -{ - print_name(out, "subject=", X509_get_subject_name(x), get_nameopt()); - BIO_puts(out, "\n"); - print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); - BIO_puts(out, "\n"); - - return 0; -} - -static int ui_open(UI *ui) -{ - int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); - - if (opener) - return opener(ui); - return 1; -} - -static int ui_read(UI *ui, UI_STRING *uis) -{ - int (*reader)(UI *ui, UI_STRING *uis) = NULL; - - if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD - && UI_get0_user_data(ui)) { - switch (UI_get_string_type(uis)) { - case UIT_PROMPT: - case UIT_VERIFY: - { - const char *password = - ((PW_CB_DATA *)UI_get0_user_data(ui))->password; - if (password && password[0] != '\0') { - UI_set_result(ui, uis, password); - return 1; - } - } - break; - case UIT_NONE: - case UIT_BOOLEAN: - case UIT_INFO: - case UIT_ERROR: - break; - } - } - - reader = UI_method_get_reader(ui_fallback_method); - if (reader) - return reader(ui, uis); - return 1; -} - -static int ui_write(UI *ui, UI_STRING *uis) -{ - int (*writer)(UI *ui, UI_STRING *uis) = NULL; - - if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD - && UI_get0_user_data(ui)) { - switch (UI_get_string_type(uis)) { - case UIT_PROMPT: - case UIT_VERIFY: - { - const char *password = - ((PW_CB_DATA *)UI_get0_user_data(ui))->password; - if (password && password[0] != '\0') - return 1; - } - break; - case UIT_NONE: - case UIT_BOOLEAN: - case UIT_INFO: - case UIT_ERROR: - break; - } - } - - writer = UI_method_get_writer(ui_fallback_method); - if (writer) - return writer(ui, uis); - return 1; -} - -static int ui_close(UI *ui) -{ - int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); - - if (closer) - return closer(ui); - return 1; -} - -int setup_ui_method(void) -{ - ui_fallback_method = UI_null(); -#ifndef OPENSSL_NO_UI_CONSOLE - ui_fallback_method = UI_OpenSSL(); -#endif - ui_method = UI_create_method("OpenSSL application user interface"); - UI_method_set_opener(ui_method, ui_open); - UI_method_set_reader(ui_method, ui_read); - UI_method_set_writer(ui_method, ui_write); - UI_method_set_closer(ui_method, ui_close); - return 0; -} - -void destroy_ui_method(void) -{ - if (ui_method) { - UI_destroy_method(ui_method); - ui_method = NULL; - } -} - -const UI_METHOD *get_ui_method(void) -{ - return ui_method; -} - -int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) -{ - int res = 0; - UI *ui = NULL; - PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp; - - ui = UI_new_method(ui_method); - if (ui) { - int ok = 0; - char *buff = NULL; - int ui_flags = 0; - const char *prompt_info = NULL; - char *prompt; - int pw_min_len = PW_MIN_LENGTH; - - if (cb_data != NULL && cb_data->prompt_info != NULL) - prompt_info = cb_data->prompt_info; - if (cb_data != NULL && cb_data->password != NULL - && *(const char*)cb_data->password != '\0') - pw_min_len = 1; - else if (!verify) - pw_min_len = 0; - prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); - if (!prompt) { - BIO_printf(bio_err, "Out of memory\n"); - UI_free(ui); - return 0; - } - - ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; - UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); - - /* We know that there is no previous user data to return to us */ - (void)UI_add_user_data(ui, cb_data); - - ok = UI_add_input_string(ui, prompt, ui_flags, buf, - pw_min_len, bufsiz - 1); - - if (ok >= 0 && verify) { - buff = app_malloc(bufsiz, "password buffer"); - ok = UI_add_verify_string(ui, prompt, ui_flags, buff, - pw_min_len, bufsiz - 1, buf); - } - if (ok >= 0) - do { - ok = UI_process(ui); - } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); - - OPENSSL_clear_free(buff, (unsigned int)bufsiz); - - if (ok >= 0) - res = strlen(buf); - if (ok == -1) { - BIO_printf(bio_err, "User interface error\n"); - ERR_print_errors(bio_err); - OPENSSL_cleanse(buf, (unsigned int)bufsiz); - res = 0; - } - if (ok == -2) { - BIO_printf(bio_err, "aborted!\n"); - OPENSSL_cleanse(buf, (unsigned int)bufsiz); - res = 0; - } - UI_free(ui); - OPENSSL_free(prompt); - } - return res; -} - -static char *app_get_pass(const char *arg, int keepbio); - -int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) -{ - int same; - if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2)) - same = 0; - else - same = 1; - if (arg1 != NULL) { - *pass1 = app_get_pass(arg1, same); - if (*pass1 == NULL) - return 0; - } else if (pass1 != NULL) { - *pass1 = NULL; - } - if (arg2 != NULL) { - *pass2 = app_get_pass(arg2, same ? 2 : 0); - if (*pass2 == NULL) - return 0; - } else if (pass2 != NULL) { - *pass2 = NULL; - } - return 1; -} - -static char *app_get_pass(const char *arg, int keepbio) -{ - char *tmp, tpass[APP_PASS_LEN]; - static BIO *pwdbio = NULL; - int i; - - if (strncmp(arg, "pass:", 5) == 0) - return OPENSSL_strdup(arg + 5); - if (strncmp(arg, "env:", 4) == 0) { - tmp = getenv(arg + 4); - if (tmp == NULL) { - BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4); - return NULL; - } - return OPENSSL_strdup(tmp); - } - if (!keepbio || pwdbio == NULL) { - if (strncmp(arg, "file:", 5) == 0) { - pwdbio = BIO_new_file(arg + 5, "r"); - if (pwdbio == NULL) { - BIO_printf(bio_err, "Can't open file %s\n", arg + 5); - return NULL; - } -#if !defined(_WIN32) - /* - * Under _WIN32, which covers even Win64 and CE, file - * descriptors referenced by BIO_s_fd are not inherited - * by child process and therefore below is not an option. - * It could have been an option if bss_fd.c was operating - * on real Windows descriptors, such as those obtained - * with CreateFile. - */ - } else if (strncmp(arg, "fd:", 3) == 0) { - BIO *btmp; - i = atoi(arg + 3); - if (i >= 0) - pwdbio = BIO_new_fd(i, BIO_NOCLOSE); - if ((i < 0) || !pwdbio) { - BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3); - return NULL; - } - /* - * Can't do BIO_gets on an fd BIO so add a buffering BIO - */ - btmp = BIO_new(BIO_f_buffer()); - pwdbio = BIO_push(btmp, pwdbio); -#endif - } else if (strcmp(arg, "stdin") == 0) { - pwdbio = dup_bio_in(FORMAT_TEXT); - if (!pwdbio) { - BIO_printf(bio_err, "Can't open BIO for stdin\n"); - return NULL; - } - } else { - BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg); - return NULL; - } - } - i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); - if (keepbio != 1) { - BIO_free_all(pwdbio); - pwdbio = NULL; - } - if (i <= 0) { - BIO_printf(bio_err, "Error reading password from BIO\n"); - return NULL; - } - tmp = strchr(tpass, '\n'); - if (tmp != NULL) - *tmp = 0; - return OPENSSL_strdup(tpass); -} - -CONF *app_load_config_bio(BIO *in, const char *filename) -{ - long errorline = -1; - CONF *conf; - int i; - - conf = NCONF_new(NULL); - i = NCONF_load_bio(conf, in, &errorline); - if (i > 0) - return conf; - - if (errorline <= 0) { - BIO_printf(bio_err, "%s: Can't load ", opt_getprog()); - } else { - BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(), - errorline); - } - if (filename != NULL) - BIO_printf(bio_err, "config file \"%s\"\n", filename); - else - BIO_printf(bio_err, "config input"); - - NCONF_free(conf); - return NULL; -} - -CONF *app_load_config(const char *filename) -{ - BIO *in; - CONF *conf; - - in = bio_open_default(filename, 'r', FORMAT_TEXT); - if (in == NULL) - return NULL; - - conf = app_load_config_bio(in, filename); - BIO_free(in); - return conf; -} - -CONF *app_load_config_quiet(const char *filename) -{ - BIO *in; - CONF *conf; - - in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT); - if (in == NULL) - return NULL; - - conf = app_load_config_bio(in, filename); - BIO_free(in); - return conf; -} - -int app_load_modules(const CONF *config) -{ - CONF *to_free = NULL; - - if (config == NULL) - config = to_free = app_load_config_quiet(default_config_file); - if (config == NULL) - return 1; - - if (CONF_modules_load(config, NULL, 0) <= 0) { - BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); - ERR_print_errors(bio_err); - NCONF_free(to_free); - return 0; - } - NCONF_free(to_free); - return 1; -} - -int add_oid_section(CONF *conf) -{ - char *p; - STACK_OF(CONF_VALUE) *sktmp; - CONF_VALUE *cnf; - int i; - - if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { - ERR_clear_error(); - return 1; - } - if ((sktmp = NCONF_get_section(conf, p)) == NULL) { - BIO_printf(bio_err, "problem loading oid section %s\n", p); - return 0; - } - for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { - cnf = sk_CONF_VALUE_value(sktmp, i); - if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { - BIO_printf(bio_err, "problem creating object %s=%s\n", - cnf->name, cnf->value); - return 0; - } - } - return 1; -} - -static int load_pkcs12(BIO *in, const char *desc, - pem_password_cb *pem_cb, void *cb_data, - EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) -{ - const char *pass; - char tpass[PEM_BUFSIZE]; - int len, ret = 0; - PKCS12 *p12; - p12 = d2i_PKCS12_bio(in, NULL); - if (p12 == NULL) { - BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc); - goto die; - } - /* See if an empty password will do */ - if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) { - pass = ""; - } else { - if (!pem_cb) - pem_cb = (pem_password_cb *)password_callback; - len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); - if (len < 0) { - BIO_printf(bio_err, "Passphrase callback error for %s\n", desc); - goto die; - } - if (len < PEM_BUFSIZE) - tpass[len] = 0; - if (!PKCS12_verify_mac(p12, tpass, len)) { - BIO_printf(bio_err, - "Mac verify error (wrong password?) in PKCS12 file for %s\n", - desc); - goto die; - } - pass = tpass; - } - ret = PKCS12_parse(p12, pass, pkey, cert, ca); - die: - PKCS12_free(p12); - return ret; -} - -#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) -static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl) -{ - char *host = NULL, *port = NULL, *path = NULL; - BIO *bio = NULL; - OCSP_REQ_CTX *rctx = NULL; - int use_ssl, rv = 0; - if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) - goto err; - if (use_ssl) { - BIO_puts(bio_err, "https not supported\n"); - goto err; - } - bio = BIO_new_connect(host); - if (!bio || !BIO_set_conn_port(bio, port)) - goto err; - rctx = OCSP_REQ_CTX_new(bio, 1024); - if (rctx == NULL) - goto err; - if (!OCSP_REQ_CTX_http(rctx, "GET", path)) - goto err; - if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host)) - goto err; - if (pcert) { - do { - rv = X509_http_nbio(rctx, pcert); - } while (rv == -1); - } else { - do { - rv = X509_CRL_http_nbio(rctx, pcrl); - } while (rv == -1); - } - - err: - OPENSSL_free(host); - OPENSSL_free(path); - OPENSSL_free(port); - BIO_free_all(bio); - OCSP_REQ_CTX_free(rctx); - if (rv != 1) { - BIO_printf(bio_err, "Error loading %s from %s\n", - pcert ? "certificate" : "CRL", url); - ERR_print_errors(bio_err); - } - return rv; -} -#endif - -X509 *load_cert(const char *file, int format, const char *cert_descrip) -{ - X509 *x = NULL; - BIO *cert; - - if (format == FORMAT_HTTP) { -#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) - load_cert_crl_http(file, &x, NULL); -#endif - return x; - } - - if (file == NULL) { - unbuffer(stdin); - cert = dup_bio_in(format); - } else { - cert = bio_open_default(file, 'r', format); - } - if (cert == NULL) - goto end; - - if (format == FORMAT_ASN1) { - x = d2i_X509_bio(cert, NULL); - } else if (format == FORMAT_PEM) { - x = PEM_read_bio_X509_AUX(cert, NULL, - (pem_password_cb *)password_callback, NULL); - } else if (format == FORMAT_PKCS12) { - if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL)) - goto end; - } else { - BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip); - goto end; - } - end: - if (x == NULL) { - BIO_printf(bio_err, "unable to load certificate\n"); - ERR_print_errors(bio_err); - } - BIO_free(cert); - return x; -} - -X509_CRL *load_crl(const char *infile, int format) -{ - X509_CRL *x = NULL; - BIO *in = NULL; - - if (format == FORMAT_HTTP) { -#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) - load_cert_crl_http(infile, NULL, &x); -#endif - return x; - } - - in = bio_open_default(infile, 'r', format); - if (in == NULL) - goto end; - if (format == FORMAT_ASN1) { - x = d2i_X509_CRL_bio(in, NULL); - } else if (format == FORMAT_PEM) { - x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - } else { - BIO_printf(bio_err, "bad input format specified for input crl\n"); - goto end; - } - if (x == NULL) { - BIO_printf(bio_err, "unable to load CRL\n"); - ERR_print_errors(bio_err); - goto end; - } - - end: - BIO_free(in); - return x; -} - -EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, - const char *pass, ENGINE *e, const char *key_descrip) -{ - BIO *key = NULL; - EVP_PKEY *pkey = NULL; - PW_CB_DATA cb_data; - - cb_data.password = pass; - cb_data.prompt_info = file; - - if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { - BIO_printf(bio_err, "no keyfile specified\n"); - goto end; - } - if (format == FORMAT_ENGINE) { - if (e == NULL) { - BIO_printf(bio_err, "no engine specified\n"); - } else { -#ifndef OPENSSL_NO_ENGINE - if (ENGINE_init(e)) { - pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); - ENGINE_finish(e); - } - if (pkey == NULL) { - BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); - ERR_print_errors(bio_err); - } -#else - BIO_printf(bio_err, "engines not supported\n"); -#endif - } - goto end; - } - if (file == NULL && maybe_stdin) { - unbuffer(stdin); - key = dup_bio_in(format); - } else { - key = bio_open_default(file, 'r', format); - } - if (key == NULL) - goto end; - if (format == FORMAT_ASN1) { - pkey = d2i_PrivateKey_bio(key, NULL); - } else if (format == FORMAT_PEM) { - pkey = PEM_read_bio_PrivateKey(key, NULL, - (pem_password_cb *)password_callback, - &cb_data); - } else if (format == FORMAT_PKCS12) { - if (!load_pkcs12(key, key_descrip, - (pem_password_cb *)password_callback, &cb_data, - &pkey, NULL, NULL)) - goto end; -#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) - } else if (format == FORMAT_MSBLOB) { - pkey = b2i_PrivateKey_bio(key); - } else if (format == FORMAT_PVK) { - pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, - &cb_data); -#endif - } else { - BIO_printf(bio_err, "bad input format specified for key file\n"); - goto end; - } - end: - BIO_free(key); - if (pkey == NULL) { - BIO_printf(bio_err, "unable to load %s\n", key_descrip); - ERR_print_errors(bio_err); - } - return pkey; -} - -EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, - const char *pass, ENGINE *e, const char *key_descrip) -{ - BIO *key = NULL; - EVP_PKEY *pkey = NULL; - PW_CB_DATA cb_data; - - cb_data.password = pass; - cb_data.prompt_info = file; - - if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { - BIO_printf(bio_err, "no keyfile specified\n"); - goto end; - } - if (format == FORMAT_ENGINE) { - if (e == NULL) { - BIO_printf(bio_err, "no engine specified\n"); - } else { -#ifndef OPENSSL_NO_ENGINE - pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data); - if (pkey == NULL) { - BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); - ERR_print_errors(bio_err); - } -#else - BIO_printf(bio_err, "engines not supported\n"); -#endif - } - goto end; - } - if (file == NULL && maybe_stdin) { - unbuffer(stdin); - key = dup_bio_in(format); - } else { - key = bio_open_default(file, 'r', format); - } - if (key == NULL) - goto end; - if (format == FORMAT_ASN1) { - pkey = d2i_PUBKEY_bio(key, NULL); - } else if (format == FORMAT_ASN1RSA) { -#ifndef OPENSSL_NO_RSA - RSA *rsa; - rsa = d2i_RSAPublicKey_bio(key, NULL); - if (rsa) { - pkey = EVP_PKEY_new(); - if (pkey != NULL) - EVP_PKEY_set1_RSA(pkey, rsa); - RSA_free(rsa); - } else -#else - BIO_printf(bio_err, "RSA keys not supported\n"); -#endif - pkey = NULL; - } else if (format == FORMAT_PEMRSA) { -#ifndef OPENSSL_NO_RSA - RSA *rsa; - rsa = PEM_read_bio_RSAPublicKey(key, NULL, - (pem_password_cb *)password_callback, - &cb_data); - if (rsa != NULL) { - pkey = EVP_PKEY_new(); - if (pkey != NULL) - EVP_PKEY_set1_RSA(pkey, rsa); - RSA_free(rsa); - } else -#else - BIO_printf(bio_err, "RSA keys not supported\n"); -#endif - pkey = NULL; - } else if (format == FORMAT_PEM) { - pkey = PEM_read_bio_PUBKEY(key, NULL, - (pem_password_cb *)password_callback, - &cb_data); -#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) - } else if (format == FORMAT_MSBLOB) { - pkey = b2i_PublicKey_bio(key); -#endif - } - end: - BIO_free(key); - if (pkey == NULL) - BIO_printf(bio_err, "unable to load %s\n", key_descrip); - return pkey; -} - -static int load_certs_crls(const char *file, int format, - const char *pass, const char *desc, - STACK_OF(X509) **pcerts, - STACK_OF(X509_CRL) **pcrls) -{ - int i; - BIO *bio; - STACK_OF(X509_INFO) *xis = NULL; - X509_INFO *xi; - PW_CB_DATA cb_data; - int rv = 0; - - cb_data.password = pass; - cb_data.prompt_info = file; - - if (format != FORMAT_PEM) { - BIO_printf(bio_err, "bad input format specified for %s\n", desc); - return 0; - } - - bio = bio_open_default(file, 'r', FORMAT_PEM); - if (bio == NULL) - return 0; - - xis = PEM_X509_INFO_read_bio(bio, NULL, - (pem_password_cb *)password_callback, - &cb_data); - - BIO_free(bio); - - if (pcerts != NULL && *pcerts == NULL) { - *pcerts = sk_X509_new_null(); - if (*pcerts == NULL) - goto end; - } - - if (pcrls != NULL && *pcrls == NULL) { - *pcrls = sk_X509_CRL_new_null(); - if (*pcrls == NULL) - goto end; - } - - for (i = 0; i < sk_X509_INFO_num(xis); i++) { - xi = sk_X509_INFO_value(xis, i); - if (xi->x509 != NULL && pcerts != NULL) { - if (!sk_X509_push(*pcerts, xi->x509)) - goto end; - xi->x509 = NULL; - } - if (xi->crl != NULL && pcrls != NULL) { - if (!sk_X509_CRL_push(*pcrls, xi->crl)) - goto end; - xi->crl = NULL; - } - } - - if (pcerts != NULL && sk_X509_num(*pcerts) > 0) - rv = 1; - - if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0) - rv = 1; - - end: - - sk_X509_INFO_pop_free(xis, X509_INFO_free); - - if (rv == 0) { - if (pcerts != NULL) { - sk_X509_pop_free(*pcerts, X509_free); - *pcerts = NULL; - } - if (pcrls != NULL) { - sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); - *pcrls = NULL; - } - BIO_printf(bio_err, "unable to load %s\n", - pcerts ? "certificates" : "CRLs"); - ERR_print_errors(bio_err); - } - return rv; -} - -void* app_malloc(int sz, const char *what) -{ - void *vp = OPENSSL_malloc(sz); - - if (vp == NULL) { - BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n", - opt_getprog(), sz, what); - ERR_print_errors(bio_err); - exit(1); - } - return vp; -} - -/* - * Initialize or extend, if *certs != NULL, a certificate stack. - */ -int load_certs(const char *file, STACK_OF(X509) **certs, int format, - const char *pass, const char *desc) -{ - return load_certs_crls(file, format, pass, desc, certs, NULL); -} - -/* - * Initialize or extend, if *crls != NULL, a certificate stack. - */ -int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, - const char *pass, const char *desc) -{ - return load_certs_crls(file, format, pass, desc, NULL, crls); -} - -#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) -/* Return error for unknown extensions */ -#define X509V3_EXT_DEFAULT 0 -/* Print error for unknown extensions */ -#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) -/* ASN1 parse unknown extensions */ -#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) -/* BIO_dump unknown extensions */ -#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) - -#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ - X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) - -int set_cert_ex(unsigned long *flags, const char *arg) -{ - static const NAME_EX_TBL cert_tbl[] = { - {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, - {"ca_default", X509_FLAG_CA, 0xffffffffl}, - {"no_header", X509_FLAG_NO_HEADER, 0}, - {"no_version", X509_FLAG_NO_VERSION, 0}, - {"no_serial", X509_FLAG_NO_SERIAL, 0}, - {"no_signame", X509_FLAG_NO_SIGNAME, 0}, - {"no_validity", X509_FLAG_NO_VALIDITY, 0}, - {"no_subject", X509_FLAG_NO_SUBJECT, 0}, - {"no_issuer", X509_FLAG_NO_ISSUER, 0}, - {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, - {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, - {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, - {"no_aux", X509_FLAG_NO_AUX, 0}, - {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, - {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, - {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, - {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, - {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, - {NULL, 0, 0} - }; - return set_multi_opts(flags, arg, cert_tbl); -} - -int set_name_ex(unsigned long *flags, const char *arg) -{ - static const NAME_EX_TBL ex_tbl[] = { - {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, - {"esc_2254", ASN1_STRFLGS_ESC_2254, 0}, - {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, - {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, - {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, - {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, - {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, - {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, - {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, - {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, - {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, - {"compat", XN_FLAG_COMPAT, 0xffffffffL}, - {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, - {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, - {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, - {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, - {"dn_rev", XN_FLAG_DN_REV, 0}, - {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, - {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, - {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, - {"align", XN_FLAG_FN_ALIGN, 0}, - {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, - {"space_eq", XN_FLAG_SPC_EQ, 0}, - {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, - {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, - {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, - {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, - {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, - {NULL, 0, 0} - }; - if (set_multi_opts(flags, arg, ex_tbl) == 0) - return 0; - if (*flags != XN_FLAG_COMPAT - && (*flags & XN_FLAG_SEP_MASK) == 0) - *flags |= XN_FLAG_SEP_CPLUS_SPC; - return 1; -} - -int set_ext_copy(int *copy_type, const char *arg) -{ - if (strcasecmp(arg, "none") == 0) - *copy_type = EXT_COPY_NONE; - else if (strcasecmp(arg, "copy") == 0) - *copy_type = EXT_COPY_ADD; - else if (strcasecmp(arg, "copyall") == 0) - *copy_type = EXT_COPY_ALL; - else - return 0; - return 1; -} - -int copy_extensions(X509 *x, X509_REQ *req, int copy_type) -{ - STACK_OF(X509_EXTENSION) *exts = NULL; - X509_EXTENSION *ext, *tmpext; - ASN1_OBJECT *obj; - int i, idx, ret = 0; - if (!x || !req || (copy_type == EXT_COPY_NONE)) - return 1; - exts = X509_REQ_get_extensions(req); - - for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { - ext = sk_X509_EXTENSION_value(exts, i); - obj = X509_EXTENSION_get_object(ext); - idx = X509_get_ext_by_OBJ(x, obj, -1); - /* Does extension exist? */ - if (idx != -1) { - /* If normal copy don't override existing extension */ - if (copy_type == EXT_COPY_ADD) - continue; - /* Delete all extensions of same type */ - do { - tmpext = X509_get_ext(x, idx); - X509_delete_ext(x, idx); - X509_EXTENSION_free(tmpext); - idx = X509_get_ext_by_OBJ(x, obj, -1); - } while (idx != -1); - } - if (!X509_add_ext(x, ext, -1)) - goto end; - } - - ret = 1; - - end: - - sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); - - return ret; -} - -static int set_multi_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl) -{ - STACK_OF(CONF_VALUE) *vals; - CONF_VALUE *val; - int i, ret = 1; - if (!arg) - return 0; - vals = X509V3_parse_list(arg); - for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { - val = sk_CONF_VALUE_value(vals, i); - if (!set_table_opts(flags, val->name, in_tbl)) - ret = 0; - } - sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); - return ret; -} - -static int set_table_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl) -{ - char c; - const NAME_EX_TBL *ptbl; - c = arg[0]; - - if (c == '-') { - c = 0; - arg++; - } else if (c == '+') { - c = 1; - arg++; - } else { - c = 1; - } - - for (ptbl = in_tbl; ptbl->name; ptbl++) { - if (strcasecmp(arg, ptbl->name) == 0) { - *flags &= ~ptbl->mask; - if (c) - *flags |= ptbl->flag; - else - *flags &= ~ptbl->flag; - return 1; - } - } - return 0; -} - -void print_name(BIO *out, const char *title, X509_NAME *nm, - unsigned long lflags) -{ - char *buf; - char mline = 0; - int indent = 0; - - if (title) - BIO_puts(out, title); - if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { - mline = 1; - indent = 4; - } - if (lflags == XN_FLAG_COMPAT) { - buf = X509_NAME_oneline(nm, 0, 0); - BIO_puts(out, buf); - BIO_puts(out, "\n"); - OPENSSL_free(buf); - } else { - if (mline) - BIO_puts(out, "\n"); - X509_NAME_print_ex(out, nm, indent, lflags); - BIO_puts(out, "\n"); - } -} - -void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, - int len, unsigned char *buffer) -{ - BIO_printf(out, " static unsigned char %s_%d[] = {", var, len); - if (BN_is_zero(in)) { - BIO_printf(out, "\n 0x00"); - } else { - int i, l; - - l = BN_bn2bin(in, buffer); - for (i = 0; i < l; i++) { - BIO_printf(out, (i % 10) == 0 ? "\n " : " "); - if (i < l - 1) - BIO_printf(out, "0x%02X,", buffer[i]); - else - BIO_printf(out, "0x%02X", buffer[i]); - } - } - BIO_printf(out, "\n };\n"); -} - -void print_array(BIO *out, const char* title, int len, const unsigned char* d) -{ - int i; - - BIO_printf(out, "unsigned char %s[%d] = {", title, len); - for (i = 0; i < len; i++) { - if ((i % 10) == 0) - BIO_printf(out, "\n "); - if (i < len - 1) - BIO_printf(out, "0x%02X, ", d[i]); - else - BIO_printf(out, "0x%02X", d[i]); - } - BIO_printf(out, "\n};\n"); -} - -X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath) -{ - X509_STORE *store = X509_STORE_new(); - X509_LOOKUP *lookup; - - if (store == NULL) - goto end; - - if (CAfile != NULL || !noCAfile) { - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); - if (lookup == NULL) - goto end; - if (CAfile) { - if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { - BIO_printf(bio_err, "Error loading file %s\n", CAfile); - goto end; - } - } else { - X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); - } - } - - if (CApath != NULL || !noCApath) { - lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); - if (lookup == NULL) - goto end; - if (CApath) { - if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { - BIO_printf(bio_err, "Error loading directory %s\n", CApath); - goto end; - } - } else { - X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); - } - } - - ERR_clear_error(); - return store; - end: - X509_STORE_free(store); - return NULL; -} - -#ifndef OPENSSL_NO_ENGINE -/* Try to load an engine in a shareable library */ -static ENGINE *try_load_engine(const char *engine) -{ - ENGINE *e = ENGINE_by_id("dynamic"); - if (e) { - if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) - || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { - ENGINE_free(e); - e = NULL; - } - } - return e; -} -#endif - -ENGINE *setup_engine(const char *engine, int debug) -{ - ENGINE *e = NULL; - -#ifndef OPENSSL_NO_ENGINE - if (engine != NULL) { - if (strcmp(engine, "auto") == 0) { - BIO_printf(bio_err, "enabling auto ENGINE support\n"); - ENGINE_register_all_complete(); - return NULL; - } - if ((e = ENGINE_by_id(engine)) == NULL - && (e = try_load_engine(engine)) == NULL) { - BIO_printf(bio_err, "invalid engine \"%s\"\n", engine); - ERR_print_errors(bio_err); - return NULL; - } - if (debug) { - ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); - } - ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); - if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { - BIO_printf(bio_err, "can't use that engine\n"); - ERR_print_errors(bio_err); - ENGINE_free(e); - return NULL; - } - - BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e)); - } -#endif - return e; -} - -void release_engine(ENGINE *e) -{ -#ifndef OPENSSL_NO_ENGINE - if (e != NULL) - /* Free our "structural" reference. */ - ENGINE_free(e); -#endif -} - -static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) -{ - const char *n; - - n = a[DB_serial]; - while (*n == '0') - n++; - return OPENSSL_LH_strhash(n); -} - -static int index_serial_cmp(const OPENSSL_CSTRING *a, - const OPENSSL_CSTRING *b) -{ - const char *aa, *bb; - - for (aa = a[DB_serial]; *aa == '0'; aa++) ; - for (bb = b[DB_serial]; *bb == '0'; bb++) ; - return strcmp(aa, bb); -} - -static int index_name_qual(char **a) -{ - return (a[0][0] == 'V'); -} - -static unsigned long index_name_hash(const OPENSSL_CSTRING *a) -{ - return OPENSSL_LH_strhash(a[DB_name]); -} - -int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) -{ - return strcmp(a[DB_name], b[DB_name]); -} - -static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) -static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) -static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) -static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) -#undef BSIZE -#define BSIZE 256 -BIGNUM *load_serial(const char *serialfile, int *exists, int create, - ASN1_INTEGER **retai) -{ - BIO *in = NULL; - BIGNUM *ret = NULL; - char buf[1024]; - ASN1_INTEGER *ai = NULL; - - ai = ASN1_INTEGER_new(); - if (ai == NULL) - goto err; - - in = BIO_new_file(serialfile, "r"); - if (exists != NULL) - *exists = in != NULL; - if (in == NULL) { - if (!create) { - perror(serialfile); - goto err; - } - ERR_clear_error(); - ret = BN_new(); - if (ret == NULL) { - BIO_printf(bio_err, "Out of memory\n"); - } else if (!rand_serial(ret, ai)) { - BIO_printf(bio_err, "Error creating random number to store in %s\n", - serialfile); - BN_free(ret); - ret = NULL; - } - } else { - if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { - BIO_printf(bio_err, "unable to load number from %s\n", - serialfile); - goto err; - } - ret = ASN1_INTEGER_to_BN(ai, NULL); - if (ret == NULL) { - BIO_printf(bio_err, - "error converting number from bin to BIGNUM\n"); - goto err; - } - } - - if (ret && retai) { - *retai = ai; - ai = NULL; - } - err: - if (ret == NULL) - ERR_print_errors(bio_err); - BIO_free(in); - ASN1_INTEGER_free(ai); - return ret; -} - -int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, - ASN1_INTEGER **retai) -{ - char buf[1][BSIZE]; - BIO *out = NULL; - int ret = 0; - ASN1_INTEGER *ai = NULL; - int j; - - if (suffix == NULL) - j = strlen(serialfile); - else - j = strlen(serialfile) + strlen(suffix) + 1; - if (j >= BSIZE) { - BIO_printf(bio_err, "file name too long\n"); - goto err; - } - - if (suffix == NULL) - OPENSSL_strlcpy(buf[0], serialfile, BSIZE); - else { -#ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); -#else - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); -#endif - } - out = BIO_new_file(buf[0], "w"); - if (out == NULL) { - ERR_print_errors(bio_err); - goto err; - } - - if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { - BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); - goto err; - } - i2a_ASN1_INTEGER(out, ai); - BIO_puts(out, "\n"); - ret = 1; - if (retai) { - *retai = ai; - ai = NULL; - } - err: - BIO_free_all(out); - ASN1_INTEGER_free(ai); - return ret; -} - -int rotate_serial(const char *serialfile, const char *new_suffix, - const char *old_suffix) -{ - char buf[2][BSIZE]; - int i, j; - - i = strlen(serialfile) + strlen(old_suffix); - j = strlen(serialfile) + strlen(new_suffix); - if (i > j) - j = i; - if (j + 1 >= BSIZE) { - BIO_printf(bio_err, "file name too long\n"); - goto err; - } -#ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix); -#else - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); -#endif - if (rename(serialfile, buf[1]) < 0 && errno != ENOENT -#ifdef ENOTDIR - && errno != ENOTDIR -#endif - ) { - BIO_printf(bio_err, - "unable to rename %s to %s\n", serialfile, buf[1]); - perror("reason"); - goto err; - } - if (rename(buf[0], serialfile) < 0) { - BIO_printf(bio_err, - "unable to rename %s to %s\n", buf[0], serialfile); - perror("reason"); - rename(buf[1], serialfile); - goto err; - } - return 1; - err: - return 0; -} - -int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) -{ - BIGNUM *btmp; - int ret = 0; - - btmp = b == NULL ? BN_new() : b; - if (btmp == NULL) - return 0; - - if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) - goto error; - if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) - goto error; - - ret = 1; - - error: - - if (btmp != b) - BN_free(btmp); - - return ret; -} - -CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) -{ - CA_DB *retdb = NULL; - TXT_DB *tmpdb = NULL; - BIO *in; - CONF *dbattr_conf = NULL; - char buf[BSIZE]; -#ifndef OPENSSL_NO_POSIX_IO - FILE *dbfp; - struct stat dbst; -#endif - - in = BIO_new_file(dbfile, "r"); - if (in == NULL) { - ERR_print_errors(bio_err); - goto err; - } - -#ifndef OPENSSL_NO_POSIX_IO - BIO_get_fp(in, &dbfp); - if (fstat(fileno(dbfp), &dbst) == -1) { - SYSerr(SYS_F_FSTAT, errno); - ERR_add_error_data(3, "fstat('", dbfile, "')"); - ERR_print_errors(bio_err); - goto err; - } -#endif - - if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) - goto err; - -#ifndef OPENSSL_SYS_VMS - BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile); -#else - BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile); -#endif - dbattr_conf = app_load_config_quiet(buf); - - retdb = app_malloc(sizeof(*retdb), "new DB"); - retdb->db = tmpdb; - tmpdb = NULL; - if (db_attr) - retdb->attributes = *db_attr; - else { - retdb->attributes.unique_subject = 1; - } - - if (dbattr_conf) { - char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); - if (p) { - retdb->attributes.unique_subject = parse_yesno(p, 1); - } - } - - retdb->dbfname = OPENSSL_strdup(dbfile); -#ifndef OPENSSL_NO_POSIX_IO - retdb->dbst = dbst; -#endif - - err: - NCONF_free(dbattr_conf); - TXT_DB_free(tmpdb); - BIO_free_all(in); - return retdb; -} - -/* - * Returns > 0 on success, <= 0 on error - */ -int index_index(CA_DB *db) -{ - if (!TXT_DB_create_index(db->db, DB_serial, NULL, - LHASH_HASH_FN(index_serial), - LHASH_COMP_FN(index_serial))) { - BIO_printf(bio_err, - "error creating serial number index:(%ld,%ld,%ld)\n", - db->db->error, db->db->arg1, db->db->arg2); - return 0; - } - - if (db->attributes.unique_subject - && !TXT_DB_create_index(db->db, DB_name, index_name_qual, - LHASH_HASH_FN(index_name), - LHASH_COMP_FN(index_name))) { - BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n", - db->db->error, db->db->arg1, db->db->arg2); - return 0; - } - return 1; -} - -int save_index(const char *dbfile, const char *suffix, CA_DB *db) -{ - char buf[3][BSIZE]; - BIO *out; - int j; - - j = strlen(dbfile) + strlen(suffix); - if (j + 6 >= BSIZE) { - BIO_printf(bio_err, "file name too long\n"); - goto err; - } -#ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix); -#else - j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); -#endif - out = BIO_new_file(buf[0], "w"); - if (out == NULL) { - perror(dbfile); - BIO_printf(bio_err, "unable to open '%s'\n", dbfile); - goto err; - } - j = TXT_DB_write(out, db->db); - BIO_free(out); - if (j <= 0) - goto err; - - out = BIO_new_file(buf[1], "w"); - if (out == NULL) { - perror(buf[2]); - BIO_printf(bio_err, "unable to open '%s'\n", buf[2]); - goto err; - } - BIO_printf(out, "unique_subject = %s\n", - db->attributes.unique_subject ? "yes" : "no"); - BIO_free(out); - - return 1; - err: - return 0; -} - -int rotate_index(const char *dbfile, const char *new_suffix, - const char *old_suffix) -{ - char buf[5][BSIZE]; - int i, j; - - i = strlen(dbfile) + strlen(old_suffix); - j = strlen(dbfile) + strlen(new_suffix); - if (i > j) - j = i; - if (j + 6 >= BSIZE) { - BIO_printf(bio_err, "file name too long\n"); - goto err; - } -#ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); - j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); - j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); -#else - j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); - j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); - j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); - j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); -#endif - if (rename(dbfile, buf[1]) < 0 && errno != ENOENT -#ifdef ENOTDIR - && errno != ENOTDIR -#endif - ) { - BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]); - perror("reason"); - goto err; - } - if (rename(buf[0], dbfile) < 0) { - BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile); - perror("reason"); - rename(buf[1], dbfile); - goto err; - } - if (rename(buf[4], buf[3]) < 0 && errno != ENOENT -#ifdef ENOTDIR - && errno != ENOTDIR -#endif - ) { - BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]); - perror("reason"); - rename(dbfile, buf[0]); - rename(buf[1], dbfile); - goto err; - } - if (rename(buf[2], buf[4]) < 0) { - BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]); - perror("reason"); - rename(buf[3], buf[4]); - rename(dbfile, buf[0]); - rename(buf[1], dbfile); - goto err; - } - return 1; - err: - return 0; -} - -void free_index(CA_DB *db) -{ - if (db) { - TXT_DB_free(db->db); - OPENSSL_free(db->dbfname); - OPENSSL_free(db); - } -} - -int parse_yesno(const char *str, int def) -{ - if (str) { - switch (*str) { - case 'f': /* false */ - case 'F': /* FALSE */ - case 'n': /* no */ - case 'N': /* NO */ - case '0': /* 0 */ - return 0; - case 't': /* true */ - case 'T': /* TRUE */ - case 'y': /* yes */ - case 'Y': /* YES */ - case '1': /* 1 */ - return 1; - } - } - return def; -} - -/* - * name is expected to be in the format /type0=value0/type1=value1/type2=... - * where characters may be escaped by \ - */ -X509_NAME *parse_name(const char *cp, long chtype, int canmulti) -{ - int nextismulti = 0; - char *work; - X509_NAME *n; - - if (*cp++ != '/') { - BIO_printf(bio_err, - "name is expected to be in the format " - "/type0=value0/type1=value1/type2=... where characters may " - "be escaped by \\. This name is not in that format: '%s'\n", - --cp); - return NULL; - } - - n = X509_NAME_new(); - if (n == NULL) - return NULL; - work = OPENSSL_strdup(cp); - if (work == NULL) - goto err; - - while (*cp) { - char *bp = work; - char *typestr = bp; - unsigned char *valstr; - int nid; - int ismulti = nextismulti; - nextismulti = 0; - - /* Collect the type */ - while (*cp && *cp != '=') - *bp++ = *cp++; - if (*cp == '\0') { - BIO_printf(bio_err, - "%s: Hit end of string before finding the equals.\n", - opt_getprog()); - goto err; - } - *bp++ = '\0'; - ++cp; - - /* Collect the value. */ - valstr = (unsigned char *)bp; - for (; *cp && *cp != '/'; *bp++ = *cp++) { - if (canmulti && *cp == '+') { - nextismulti = 1; - break; - } - if (*cp == '\\' && *++cp == '\0') { - BIO_printf(bio_err, - "%s: escape character at end of string\n", - opt_getprog()); - goto err; - } - } - *bp++ = '\0'; - - /* If not at EOS (must be + or /), move forward. */ - if (*cp) - ++cp; - - /* Parse */ - nid = OBJ_txt2nid(typestr); - if (nid == NID_undef) { - BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n", - opt_getprog(), typestr); - continue; - } - if (*valstr == '\0') { - BIO_printf(bio_err, - "%s: No value provided for Subject Attribute %s, skipped\n", - opt_getprog(), typestr); - continue; - } - if (!X509_NAME_add_entry_by_NID(n, nid, chtype, - valstr, strlen((char *)valstr), - -1, ismulti ? -1 : 0)) - goto err; - } - - OPENSSL_free(work); - return n; - - err: - X509_NAME_free(n); - OPENSSL_free(work); - return NULL; -} - -/* - * Read whole contents of a BIO into an allocated memory buffer and return - * it. - */ - -int bio_to_mem(unsigned char **out, int maxlen, BIO *in) -{ - BIO *mem; - int len, ret; - unsigned char tbuf[1024]; - - mem = BIO_new(BIO_s_mem()); - if (mem == NULL) - return -1; - for (;;) { - if ((maxlen != -1) && maxlen < 1024) - len = maxlen; - else - len = 1024; - len = BIO_read(in, tbuf, len); - if (len < 0) { - BIO_free(mem); - return -1; - } - if (len == 0) - break; - if (BIO_write(mem, tbuf, len) != len) { - BIO_free(mem); - return -1; - } - maxlen -= len; - - if (maxlen == 0) - break; - } - ret = BIO_get_mem_data(mem, (char **)out); - BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); - BIO_free(mem); - return ret; -} - -int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) -{ - int rv; - char *stmp, *vtmp = NULL; - stmp = OPENSSL_strdup(value); - if (!stmp) - return -1; - vtmp = strchr(stmp, ':'); - if (vtmp) { - *vtmp = 0; - vtmp++; - } - rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); - OPENSSL_free(stmp); - return rv; -} - -static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes) -{ - X509_POLICY_NODE *node; - int i; - - BIO_printf(bio_err, "%s Policies:", name); - if (nodes) { - BIO_puts(bio_err, "\n"); - for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { - node = sk_X509_POLICY_NODE_value(nodes, i); - X509_POLICY_NODE_print(bio_err, node, 2); - } - } else { - BIO_puts(bio_err, " \n"); - } -} - -void policies_print(X509_STORE_CTX *ctx) -{ - X509_POLICY_TREE *tree; - int explicit_policy; - tree = X509_STORE_CTX_get0_policy_tree(ctx); - explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); - - BIO_printf(bio_err, "Require explicit Policy: %s\n", - explicit_policy ? "True" : "False"); - - nodes_print("Authority", X509_policy_tree_get0_policies(tree)); - nodes_print("User", X509_policy_tree_get0_user_policies(tree)); -} - -/*- - * next_protos_parse parses a comma separated list of strings into a string - * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. - * outlen: (output) set to the length of the resulting buffer on success. - * err: (maybe NULL) on failure, an error message line is written to this BIO. - * in: a NUL terminated string like "abc,def,ghi" - * - * returns: a malloc'd buffer or NULL on failure. - */ -unsigned char *next_protos_parse(size_t *outlen, const char *in) -{ - size_t len; - unsigned char *out; - size_t i, start = 0; - size_t skipped = 0; - - len = strlen(in); - if (len == 0 || len >= 65535) - return NULL; - - out = app_malloc(len + 1, "NPN buffer"); - for (i = 0; i <= len; ++i) { - if (i == len || in[i] == ',') { - /* - * Zero-length ALPN elements are invalid on the wire, we could be - * strict and reject the entire string, but just ignoring extra - * commas seems harmless and more friendly. - * - * Every comma we skip in this way puts the input buffer another - * byte ahead of the output buffer, so all stores into the output - * buffer need to be decremented by the number commas skipped. - */ - if (i == start) { - ++start; - ++skipped; - continue; - } - if (i - start > 255) { - OPENSSL_free(out); - return NULL; - } - out[start-skipped] = (unsigned char)(i - start); - start = i + 1; - } else { - out[i + 1 - skipped] = in[i]; - } - } - - if (len <= skipped) { - OPENSSL_free(out); - return NULL; - } - - *outlen = len + 1 - skipped; - return out; -} - -void print_cert_checks(BIO *bio, X509 *x, - const char *checkhost, - const char *checkemail, const char *checkip) -{ - if (x == NULL) - return; - if (checkhost) { - BIO_printf(bio, "Hostname %s does%s match certificate\n", - checkhost, - X509_check_host(x, checkhost, 0, 0, NULL) == 1 - ? "" : " NOT"); - } - - if (checkemail) { - BIO_printf(bio, "Email %s does%s match certificate\n", - checkemail, X509_check_email(x, checkemail, 0, 0) - ? "" : " NOT"); - } - - if (checkip) { - BIO_printf(bio, "IP %s does%s match certificate\n", - checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT"); - } -} - -/* Get first http URL from a DIST_POINT structure */ - -static const char *get_dp_url(DIST_POINT *dp) -{ - GENERAL_NAMES *gens; - GENERAL_NAME *gen; - int i, gtype; - ASN1_STRING *uri; - if (!dp->distpoint || dp->distpoint->type != 0) - return NULL; - gens = dp->distpoint->name.fullname; - for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - gen = sk_GENERAL_NAME_value(gens, i); - uri = GENERAL_NAME_get0_value(gen, >ype); - if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { - const char *uptr = (const char *)ASN1_STRING_get0_data(uri); - if (strncmp(uptr, "http://", 7) == 0) - return uptr; - } - } - return NULL; -} - -/* - * Look through a CRLDP structure and attempt to find an http URL to - * downloads a CRL from. - */ - -static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) -{ - int i; - const char *urlptr = NULL; - for (i = 0; i < sk_DIST_POINT_num(crldp); i++) { - DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); - urlptr = get_dp_url(dp); - if (urlptr) - return load_crl(urlptr, FORMAT_HTTP); - } - return NULL; -} - -/* - * Example of downloading CRLs from CRLDP: not usable for real world as it - * always downloads, doesn't support non-blocking I/O and doesn't cache - * anything. - */ - -static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm) -{ - X509 *x; - STACK_OF(X509_CRL) *crls = NULL; - X509_CRL *crl; - STACK_OF(DIST_POINT) *crldp; - - crls = sk_X509_CRL_new_null(); - if (!crls) - return NULL; - x = X509_STORE_CTX_get_current_cert(ctx); - crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); - crl = load_crl_crldp(crldp); - sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); - if (!crl) { - sk_X509_CRL_free(crls); - return NULL; - } - sk_X509_CRL_push(crls, crl); - /* Try to download delta CRL */ - crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); - crl = load_crl_crldp(crldp); - sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); - if (crl) - sk_X509_CRL_push(crls, crl); - return crls; -} - -void store_setup_crl_download(X509_STORE *st) -{ - X509_STORE_set_lookup_crls_cb(st, crls_http_cb); -} - -/* - * Platform-specific sections - */ -#if defined(_WIN32) -# ifdef fileno -# undef fileno -# define fileno(a) (int)_fileno(a) -# endif - -# include -# include - -static int WIN32_rename(const char *from, const char *to) -{ - TCHAR *tfrom = NULL, *tto; - DWORD err; - int ret = 0; - - if (sizeof(TCHAR) == 1) { - tfrom = (TCHAR *)from; - tto = (TCHAR *)to; - } else { /* UNICODE path */ - - size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; - tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); - if (tfrom == NULL) - goto err; - tto = tfrom + flen; -# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 - if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen)) -# endif - for (i = 0; i < flen; i++) - tfrom[i] = (TCHAR)from[i]; -# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 - if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) -# endif - for (i = 0; i < tlen; i++) - tto[i] = (TCHAR)to[i]; - } - - if (MoveFile(tfrom, tto)) - goto ok; - err = GetLastError(); - if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) { - if (DeleteFile(tto) && MoveFile(tfrom, tto)) - goto ok; - err = GetLastError(); - } - if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) - errno = ENOENT; - else if (err == ERROR_ACCESS_DENIED) - errno = EACCES; - else - errno = EINVAL; /* we could map more codes... */ - err: - ret = -1; - ok: - if (tfrom != NULL && tfrom != (TCHAR *)from) - free(tfrom); - return ret; -} -#endif - -/* app_tminterval section */ -#if defined(_WIN32) -double app_tminterval(int stop, int usertime) -{ - FILETIME now; - double ret = 0; - static ULARGE_INTEGER tmstart; - static int warning = 1; -# ifdef _WIN32_WINNT - static HANDLE proc = NULL; - - if (proc == NULL) { - if (check_winnt()) - proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, - GetCurrentProcessId()); - if (proc == NULL) - proc = (HANDLE) - 1; - } - - if (usertime && proc != (HANDLE) - 1) { - FILETIME junk; - GetProcessTimes(proc, &junk, &junk, &junk, &now); - } else -# endif - { - SYSTEMTIME systime; - - if (usertime && warning) { - BIO_printf(bio_err, "To get meaningful results, run " - "this program on idle system.\n"); - warning = 0; - } - GetSystemTime(&systime); - SystemTimeToFileTime(&systime, &now); - } - - if (stop == TM_START) { - tmstart.u.LowPart = now.dwLowDateTime; - tmstart.u.HighPart = now.dwHighDateTime; - } else { - ULARGE_INTEGER tmstop; - - tmstop.u.LowPart = now.dwLowDateTime; - tmstop.u.HighPart = now.dwHighDateTime; - - ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; - } - - return ret; -} -#elif defined(OPENSSL_SYS_VXWORKS) -# include - -double app_tminterval(int stop, int usertime) -{ - double ret = 0; -# ifdef CLOCK_REALTIME - static struct timespec tmstart; - struct timespec now; -# else - static unsigned long tmstart; - unsigned long now; -# endif - static int warning = 1; - - if (usertime && warning) { - BIO_printf(bio_err, "To get meaningful results, run " - "this program on idle system.\n"); - warning = 0; - } -# ifdef CLOCK_REALTIME - clock_gettime(CLOCK_REALTIME, &now); - if (stop == TM_START) - tmstart = now; - else - ret = ((now.tv_sec + now.tv_nsec * 1e-9) - - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9)); -# else - now = tickGet(); - if (stop == TM_START) - tmstart = now; - else - ret = (now - tmstart) / (double)sysClkRateGet(); -# endif - return ret; -} - -#elif defined(OPENSSL_SYSTEM_VMS) -# include -# include - -double app_tminterval(int stop, int usertime) -{ - static clock_t tmstart; - double ret = 0; - clock_t now; -# ifdef __TMS - struct tms rus; - - now = times(&rus); - if (usertime) - now = rus.tms_utime; -# else - if (usertime) - now = clock(); /* sum of user and kernel times */ - else { - struct timeval tv; - gettimeofday(&tv, NULL); - now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK + - (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK) - ); - } -# endif - if (stop == TM_START) - tmstart = now; - else - ret = (now - tmstart) / (double)(CLK_TCK); - - return ret; -} - -#elif defined(_SC_CLK_TCK) /* by means of unistd.h */ -# include - -double app_tminterval(int stop, int usertime) -{ - double ret = 0; - struct tms rus; - clock_t now = times(&rus); - static clock_t tmstart; - - if (usertime) - now = rus.tms_utime; - - if (stop == TM_START) { - tmstart = now; - } else { - long int tck = sysconf(_SC_CLK_TCK); - ret = (now - tmstart) / (double)tck; - } - - return ret; -} - -#else -# include -# include - -double app_tminterval(int stop, int usertime) -{ - double ret = 0; - struct rusage rus; - struct timeval now; - static struct timeval tmstart; - - if (usertime) - getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime; - else - gettimeofday(&now, NULL); - - if (stop == TM_START) - tmstart = now; - else - ret = ((now.tv_sec + now.tv_usec * 1e-6) - - (tmstart.tv_sec + tmstart.tv_usec * 1e-6)); - - return ret; -} -#endif - -int app_access(const char* name, int flag) -{ -#ifdef _WIN32 - return _access(name, flag); -#else - return access(name, flag); -#endif -} - -/* app_isdir section */ -#ifdef _WIN32 -int app_isdir(const char *name) -{ - DWORD attr; -# if defined(UNICODE) || defined(_UNICODE) - size_t i, len_0 = strlen(name) + 1; - WCHAR tempname[MAX_PATH]; - - if (len_0 > MAX_PATH) - return -1; - -# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 - if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) -# endif - for (i = 0; i < len_0; i++) - tempname[i] = (WCHAR)name[i]; - - attr = GetFileAttributes(tempname); -# else - attr = GetFileAttributes(name); -# endif - if (attr == INVALID_FILE_ATTRIBUTES) - return -1; - return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); -} -#else -# include -# ifndef S_ISDIR -# if defined(_S_IFMT) && defined(_S_IFDIR) -# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) -# else -# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) -# endif -# endif - -int app_isdir(const char *name) -{ -# if defined(S_ISDIR) - struct stat st; - - if (stat(name, &st) == 0) - return S_ISDIR(st.st_mode); - else - return -1; -# else - return -1; -# endif -} -#endif - -/* raw_read|write section */ -#if defined(__VMS) -# include "vms_term_sock.h" -static int stdin_sock = -1; - -static void close_stdin_sock(void) -{ - TerminalSocket (TERM_SOCK_DELETE, &stdin_sock); -} - -int fileno_stdin(void) -{ - if (stdin_sock == -1) { - TerminalSocket(TERM_SOCK_CREATE, &stdin_sock); - atexit(close_stdin_sock); - } - - return stdin_sock; -} -#else -int fileno_stdin(void) -{ - return fileno(stdin); -} -#endif - -int fileno_stdout(void) -{ - return fileno(stdout); -} - -#if defined(_WIN32) && defined(STD_INPUT_HANDLE) -int raw_read_stdin(void *buf, int siz) -{ - DWORD n; - if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) - return n; - else - return -1; -} -#elif defined(__VMS) -# include - -int raw_read_stdin(void *buf, int siz) -{ - return recv(fileno_stdin(), buf, siz, 0); -} -#else -int raw_read_stdin(void *buf, int siz) -{ - return read(fileno_stdin(), buf, siz); -} -#endif - -#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) -int raw_write_stdout(const void *buf, int siz) -{ - DWORD n; - if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) - return n; - else - return -1; -} -#else -int raw_write_stdout(const void *buf, int siz) -{ - return write(fileno_stdout(), buf, siz); -} -#endif - -/* - * Centralized handling if input and output files with format specification - * The format is meant to show what the input and output is supposed to be, - * and is therefore a show of intent more than anything else. However, it - * does impact behavior on some platform, such as differentiating between - * text and binary input/output on non-Unix platforms - */ -static int istext(int format) -{ - return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; -} - -BIO *dup_bio_in(int format) -{ - return BIO_new_fp(stdin, - BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); -} - -static BIO_METHOD *prefix_method = NULL; - -BIO *dup_bio_out(int format) -{ - BIO *b = BIO_new_fp(stdout, - BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); - void *prefix = NULL; - -#ifdef OPENSSL_SYS_VMS - if (istext(format)) - b = BIO_push(BIO_new(BIO_f_linebuffer()), b); -#endif - - if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { - if (prefix_method == NULL) - prefix_method = apps_bf_prefix(); - b = BIO_push(BIO_new(prefix_method), b); - BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix); - } - - return b; -} - -BIO *dup_bio_err(int format) -{ - BIO *b = BIO_new_fp(stderr, - BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); -#ifdef OPENSSL_SYS_VMS - if (istext(format)) - b = BIO_push(BIO_new(BIO_f_linebuffer()), b); -#endif - return b; -} - -void destroy_prefix_method(void) -{ - BIO_meth_free(prefix_method); - prefix_method = NULL; -} - -void unbuffer(FILE *fp) -{ -/* - * On VMS, setbuf() will only take 32-bit pointers, and a compilation - * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. - * However, we trust that the C RTL will never give us a FILE pointer - * above the first 4 GB of memory, so we simply turn off the warning - * temporarily. - */ -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma environment save -# pragma message disable maylosedata2 -#endif - setbuf(fp, NULL); -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma environment restore -#endif -} - -static const char *modestr(char mode, int format) -{ - OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); - - switch (mode) { - case 'a': - return istext(format) ? "a" : "ab"; - case 'r': - return istext(format) ? "r" : "rb"; - case 'w': - return istext(format) ? "w" : "wb"; - } - /* The assert above should make sure we never reach this point */ - return NULL; -} - -static const char *modeverb(char mode) -{ - switch (mode) { - case 'a': - return "appending"; - case 'r': - return "reading"; - case 'w': - return "writing"; - } - return "(doing something)"; -} - -/* - * Open a file for writing, owner-read-only. - */ -BIO *bio_open_owner(const char *filename, int format, int private) -{ - FILE *fp = NULL; - BIO *b = NULL; - int fd = -1, bflags, mode, textmode; - - if (!private || filename == NULL || strcmp(filename, "-") == 0) - return bio_open_default(filename, 'w', format); - - mode = O_WRONLY; -#ifdef O_CREAT - mode |= O_CREAT; -#endif -#ifdef O_TRUNC - mode |= O_TRUNC; -#endif - textmode = istext(format); - if (!textmode) { -#ifdef O_BINARY - mode |= O_BINARY; -#elif defined(_O_BINARY) - mode |= _O_BINARY; -#endif - } - -#ifdef OPENSSL_SYS_VMS - /* VMS doesn't have O_BINARY, it just doesn't make sense. But, - * it still needs to know that we're going binary, or fdopen() - * will fail with "invalid argument"... so we tell VMS what the - * context is. - */ - if (!textmode) - fd = open(filename, mode, 0600, "ctx=bin"); - else -#endif - fd = open(filename, mode, 0600); - if (fd < 0) - goto err; - fp = fdopen(fd, modestr('w', format)); - if (fp == NULL) - goto err; - bflags = BIO_CLOSE; - if (textmode) - bflags |= BIO_FP_TEXT; - b = BIO_new_fp(fp, bflags); - if (b) - return b; - - err: - BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", - opt_getprog(), filename, strerror(errno)); - ERR_print_errors(bio_err); - /* If we have fp, then fdopen took over fd, so don't close both. */ - if (fp) - fclose(fp); - else if (fd >= 0) - close(fd); - return NULL; -} - -static BIO *bio_open_default_(const char *filename, char mode, int format, - int quiet) -{ - BIO *ret; - - if (filename == NULL || strcmp(filename, "-") == 0) { - ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); - if (quiet) { - ERR_clear_error(); - return ret; - } - if (ret != NULL) - return ret; - BIO_printf(bio_err, - "Can't open %s, %s\n", - mode == 'r' ? "stdin" : "stdout", strerror(errno)); - } else { - ret = BIO_new_file(filename, modestr(mode, format)); - if (quiet) { - ERR_clear_error(); - return ret; - } - if (ret != NULL) - return ret; - BIO_printf(bio_err, - "Can't open %s for %s, %s\n", - filename, modeverb(mode), strerror(errno)); - } - ERR_print_errors(bio_err); - return NULL; -} - -BIO *bio_open_default(const char *filename, char mode, int format) -{ - return bio_open_default_(filename, mode, format, 0); -} - -BIO *bio_open_default_quiet(const char *filename, char mode, int format) -{ - return bio_open_default_(filename, mode, format, 1); -} - -void wait_for_async(SSL *s) -{ - /* On Windows select only works for sockets, so we simply don't wait */ -#ifndef OPENSSL_SYS_WINDOWS - int width = 0; - fd_set asyncfds; - OSSL_ASYNC_FD *fds; - size_t numfds; - size_t i; - - if (!SSL_get_all_async_fds(s, NULL, &numfds)) - return; - if (numfds == 0) - return; - fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds"); - if (!SSL_get_all_async_fds(s, fds, &numfds)) { - OPENSSL_free(fds); - return; - } - - FD_ZERO(&asyncfds); - for (i = 0; i < numfds; i++) { - if (width <= (int)fds[i]) - width = (int)fds[i] + 1; - openssl_fdset((int)fds[i], &asyncfds); - } - select(width, (void *)&asyncfds, NULL, NULL, NULL); - OPENSSL_free(fds); -#endif -} - -/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */ -#if defined(OPENSSL_SYS_MSDOS) -int has_stdin_waiting(void) -{ -# if defined(OPENSSL_SYS_WINDOWS) - HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE); - DWORD events = 0; - INPUT_RECORD inputrec; - DWORD insize = 1; - BOOL peeked; - - if (inhand == INVALID_HANDLE_VALUE) { - return 0; - } - - peeked = PeekConsoleInput(inhand, &inputrec, insize, &events); - if (!peeked) { - /* Probably redirected input? _kbhit() does not work in this case */ - if (!feof(stdin)) { - return 1; - } - return 0; - } -# endif - return _kbhit(); -} -#endif - -/* Corrupt a signature by modifying final byte */ -void corrupt_signature(const ASN1_STRING *signature) -{ - unsigned char *s = signature->data; - s[signature->length - 1] ^= 0x1; -} - -int set_cert_times(X509 *x, const char *startdate, const char *enddate, - int days) -{ - if (startdate == NULL || strcmp(startdate, "today") == 0) { - if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) - return 0; - } else { - if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) - return 0; - } - if (enddate == NULL) { - if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) - == NULL) - return 0; - } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { - return 0; - } - return 1; -} - -void make_uppercase(char *string) -{ - int i; - - for (i = 0; string[i] != '\0'; i++) - string[i] = toupper((unsigned char)string[i]); -} diff --git a/apps/asn1pars.c b/apps/asn1pars.c deleted file mode 100644 --- a/apps/asn1pars.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include "apps.h" -#include "progs.h" -#include -#include -#include -#include -#include - -typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT, - OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT, - OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM, - OPT_ITEM -} OPTION_CHOICE; - -const OPTIONS asn1parse_options[] = { - {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"}, - {"in", OPT_IN, '<', "input file"}, - {"out", OPT_OUT, '>', "output file (output format is always DER)"}, - {"i", OPT_INDENT, 0, "indents the output"}, - {"noout", OPT_NOOUT, 0, "do not produce any output"}, - {"offset", OPT_OFFSET, 'p', "offset into file"}, - {"length", OPT_LENGTH, 'p', "length of section in file"}, - {"oid", OPT_OID, '<', "file of extra oid definitions"}, - {"dump", OPT_DUMP, 0, "unknown data in hex form"}, - {"dlimit", OPT_DLIMIT, 'p', - "dump the first arg bytes of unknown data in hex form"}, - {"strparse", OPT_STRPARSE, 'p', - "offset; a series of these can be used to 'dig'"}, - {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"}, - {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"}, - {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"}, - {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"}, - {"strictpem", OPT_STRICTPEM, 0, - "do not attempt base64 decode outside PEM markers"}, - {"item", OPT_ITEM, 's', "item to parse and print"}, - {NULL} -}; - -static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf); - -int asn1parse_main(int argc, char **argv) -{ - ASN1_TYPE *at = NULL; - BIO *in = NULL, *b64 = NULL, *derout = NULL; - BUF_MEM *buf = NULL; - STACK_OF(OPENSSL_STRING) *osk = NULL; - char *genstr = NULL, *genconf = NULL; - char *infile = NULL, *oidfile = NULL, *derfile = NULL; - unsigned char *str = NULL; - char *name = NULL, *header = NULL, *prog; - const unsigned char *ctmpbuf; - int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM; - int offset = 0, ret = 1, i, j; - long num, tmplen; - unsigned char *tmpbuf; - unsigned int length = 0; - OPTION_CHOICE o; - const ASN1_ITEM *it = NULL; - - prog = opt_init(argc, argv, asn1parse_options); - - if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) { - BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); - goto end; - } - - while ((o = opt_next()) != OPT_EOF) { - switch (o) { - case OPT_EOF: - case OPT_ERR: - opthelp: - BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - goto end; - case OPT_HELP: - opt_help(asn1parse_options); - ret = 0; - goto end; - case OPT_INFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) - goto opthelp; - break; - case OPT_IN: - infile = opt_arg(); - break; - case OPT_OUT: - derfile = opt_arg(); - break; - case OPT_INDENT: - indent = 1; - break; - case OPT_NOOUT: - noout = 1; - break; - case OPT_OID: - oidfile = opt_arg(); - break; - case OPT_OFFSET: - offset = strtol(opt_arg(), NULL, 0); - break; - case OPT_LENGTH: - length = strtol(opt_arg(), NULL, 0); - break; - case OPT_DUMP: - dump = -1; - break; - case OPT_DLIMIT: - dump = strtol(opt_arg(), NULL, 0); - break; - case OPT_STRPARSE: - sk_OPENSSL_STRING_push(osk, opt_arg()); - break; - case OPT_GENSTR: - genstr = opt_arg(); - break; - case OPT_GENCONF: - genconf = opt_arg(); - break; - case OPT_STRICTPEM: - strictpem = 1; - informat = FORMAT_PEM; - break; - case OPT_ITEM: - it = ASN1_ITEM_lookup(opt_arg()); - if (it == NULL) { - size_t tmp; - - BIO_printf(bio_err, "Unknown item name %s\n", opt_arg()); - BIO_puts(bio_err, "Supported types:\n"); - for (tmp = 0;; tmp++) { - it = ASN1_ITEM_get(tmp); - if (it == NULL) - break; - BIO_printf(bio_err, " %s\n", it->sname); - } - goto end; - } - break; - } - } - argc = opt_num_rest(); - if (argc != 0) - goto opthelp; - - if (oidfile != NULL) { - in = bio_open_default(oidfile, 'r', FORMAT_TEXT); - if (in == NULL) - goto end; - OBJ_create_objects(in); - BIO_free(in); - } - - if ((in = bio_open_default(infile, 'r', informat)) == NULL) - goto end; - - if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL) - goto end; - - if ((buf = BUF_MEM_new()) == NULL) - goto end; - if (strictpem) { - if (PEM_read_bio(in, &name, &header, &str, &num) != 1) { - BIO_printf(bio_err, "Error reading PEM file\n"); - ERR_print_errors(bio_err); - goto end; - } - buf->data = (char *)str; - buf->length = buf->max = num; - } else { - if (!BUF_MEM_grow(buf, BUFSIZ * 8)) - goto end; /* Pre-allocate :-) */ - - if (genstr || genconf) { - num = do_generate(genstr, genconf, buf); - if (num < 0) { - ERR_print_errors(bio_err); - goto end; - } - } else { - - if (informat == FORMAT_PEM) { - BIO *tmp; - - if ((b64 = BIO_new(BIO_f_base64())) == NULL) - goto end; - BIO_push(b64, in); - tmp = in; - in = b64; - b64 = tmp; - } - - num = 0; - for (;;) { - if (!BUF_MEM_grow(buf, num + BUFSIZ)) - goto end; - i = BIO_read(in, &(buf->data[num]), BUFSIZ); - if (i <= 0) - break; - num += i; - } - } - str = (unsigned char *)buf->data; - - } - - /* If any structs to parse go through in sequence */ - - if (sk_OPENSSL_STRING_num(osk)) { - tmpbuf = str; - tmplen = num; - for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) { - ASN1_TYPE *atmp; - int typ; - j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0); - if (j <= 0 || j >= tmplen) { - BIO_printf(bio_err, "'%s' is out of range\n", - sk_OPENSSL_STRING_value(osk, i)); - continue; - } - tmpbuf += j; - tmplen -= j; - atmp = at; - ctmpbuf = tmpbuf; - at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen); - ASN1_TYPE_free(atmp); - if (!at) { - BIO_printf(bio_err, "Error parsing structure\n"); - ERR_print_errors(bio_err); - goto end; - } - typ = ASN1_TYPE_get(at); - if ((typ == V_ASN1_OBJECT) - || (typ == V_ASN1_BOOLEAN) - || (typ == V_ASN1_NULL)) { - BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ)); - ERR_print_errors(bio_err); - goto end; - } - /* hmm... this is a little evil but it works */ - tmpbuf = at->value.asn1_string->data; - tmplen = at->value.asn1_string->length; - } - str = tmpbuf; - num = tmplen; - } - - if (offset < 0 || offset >= num) { - BIO_printf(bio_err, "Error: offset out of range\n"); - goto end; - } - - num -= offset; - - if (length == 0 || length > (unsigned int)num) - length = (unsigned int)num; - if (derout != NULL) { - if (BIO_write(derout, str + offset, length) != (int)length) { - BIO_printf(bio_err, "Error writing output\n"); - ERR_print_errors(bio_err); - goto end; - } - } - if (!noout) { - const unsigned char *p = str + offset; - - if (it != NULL) { - ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it); - if (value == NULL) { - BIO_printf(bio_err, "Error parsing item %s\n", it->sname); - ERR_print_errors(bio_err); - goto end; - } - ASN1_item_print(bio_out, value, 0, it, NULL); - ASN1_item_free(value, it); - } else { - if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) { - ERR_print_errors(bio_err); - goto end; - } - } - } - ret = 0; - end: - BIO_free(derout); - BIO_free(in); - BIO_free(b64); - if (ret != 0) - ERR_print_errors(bio_err); - BUF_MEM_free(buf); - OPENSSL_free(name); - OPENSSL_free(header); - ASN1_TYPE_free(at); - sk_OPENSSL_STRING_free(osk); - return ret; -} - -static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf) -{ - CONF *cnf = NULL; - int len; - unsigned char *p; - ASN1_TYPE *atyp = NULL; - - if (genconf != NULL) { - if ((cnf = app_load_config(genconf)) == NULL) - goto err; - if (genstr == NULL) - genstr = NCONF_get_string(cnf, "default", "asn1"); - if (genstr == NULL) { - BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf); - goto err; - } - } - - atyp = ASN1_generate_nconf(genstr, cnf); - NCONF_free(cnf); - cnf = NULL; - - if (atyp == NULL) - return -1; - - len = i2d_ASN1_TYPE(atyp, NULL); - - if (len <= 0) - goto err; - - if (!BUF_MEM_grow(buf, len)) - goto err; - - p = (unsigned char *)buf->data; - - i2d_ASN1_TYPE(atyp, &p); - - ASN1_TYPE_free(atyp); - return len; - - err: - NCONF_free(cnf); - ASN1_TYPE_free(atyp); - return -1; -} diff --git a/apps/asn1parse.c b/apps/asn1parse.c new file mode 100644 --- /dev/null +++ b/apps/asn1parse.c @@ -0,0 +1,362 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT, + OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT, + OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM, + OPT_ITEM +} OPTION_CHOICE; + +const OPTIONS asn1parse_options[] = { + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"oid", OPT_OID, '<', "file of extra oid definitions"}, + + OPT_SECTION("I/O"), + {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"}, + {"in", OPT_IN, '<', "input file"}, + {"out", OPT_OUT, '>', "output file (output format is always DER)"}, + {"noout", OPT_NOOUT, 0, "do not produce any output"}, + {"offset", OPT_OFFSET, 'p', "offset into file"}, + {"length", OPT_LENGTH, 'p', "length of section in file"}, + {"strparse", OPT_STRPARSE, 'p', + "offset; a series of these can be used to 'dig'"}, + {"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"}, + {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"}, + {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"}, + {"strictpem", OPT_STRICTPEM, 0, + "do not attempt base64 decode outside PEM markers"}, + {"item", OPT_ITEM, 's', "item to parse and print"}, + {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"}, + + OPT_SECTION("Formatting"), + {"i", OPT_INDENT, 0, "indents the output"}, + {"dump", OPT_DUMP, 0, "unknown data in hex form"}, + {"dlimit", OPT_DLIMIT, 'p', + "dump the first arg bytes of unknown data in hex form"}, + {NULL} +}; + +static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf); + +int asn1parse_main(int argc, char **argv) +{ + ASN1_TYPE *at = NULL; + BIO *in = NULL, *b64 = NULL, *derout = NULL; + BUF_MEM *buf = NULL; + STACK_OF(OPENSSL_STRING) *osk = NULL; + char *genstr = NULL, *genconf = NULL; + char *infile = NULL, *oidfile = NULL, *derfile = NULL; + unsigned char *str = NULL; + char *name = NULL, *header = NULL, *prog; + const unsigned char *ctmpbuf; + int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM; + int offset = 0, ret = 1, i, j; + long num, tmplen; + unsigned char *tmpbuf; + unsigned int length = 0; + OPTION_CHOICE o; + const ASN1_ITEM *it = NULL; + + prog = opt_init(argc, argv, asn1parse_options); + + if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) { + BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); + goto end; + } + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(asn1parse_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + derfile = opt_arg(); + break; + case OPT_INDENT: + indent = 1; + break; + case OPT_NOOUT: + noout = 1; + break; + case OPT_OID: + oidfile = opt_arg(); + break; + case OPT_OFFSET: + offset = strtol(opt_arg(), NULL, 0); + break; + case OPT_LENGTH: + length = strtol(opt_arg(), NULL, 0); + break; + case OPT_DUMP: + dump = -1; + break; + case OPT_DLIMIT: + dump = strtol(opt_arg(), NULL, 0); + break; + case OPT_STRPARSE: + sk_OPENSSL_STRING_push(osk, opt_arg()); + break; + case OPT_GENSTR: + genstr = opt_arg(); + break; + case OPT_GENCONF: + genconf = opt_arg(); + break; + case OPT_STRICTPEM: + strictpem = 1; + informat = FORMAT_PEM; + break; + case OPT_ITEM: + it = ASN1_ITEM_lookup(opt_arg()); + if (it == NULL) { + size_t tmp; + + BIO_printf(bio_err, "Unknown item name %s\n", opt_arg()); + BIO_puts(bio_err, "Supported types:\n"); + for (tmp = 0;; tmp++) { + it = ASN1_ITEM_get(tmp); + if (it == NULL) + break; + BIO_printf(bio_err, " %s\n", it->sname); + } + goto end; + } + break; + } + } + + /* No extra args. */ + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (oidfile != NULL) { + in = bio_open_default(oidfile, 'r', FORMAT_TEXT); + if (in == NULL) + goto end; + OBJ_create_objects(in); + BIO_free(in); + } + + if ((in = bio_open_default(infile, 'r', informat)) == NULL) + goto end; + + if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL) + goto end; + + if ((buf = BUF_MEM_new()) == NULL) + goto end; + if (strictpem) { + if (PEM_read_bio(in, &name, &header, &str, &num) != 1) { + BIO_printf(bio_err, "Error reading PEM file\n"); + ERR_print_errors(bio_err); + goto end; + } + buf->data = (char *)str; + buf->length = buf->max = num; + } else { + if (!BUF_MEM_grow(buf, BUFSIZ * 8)) + goto end; /* Pre-allocate :-) */ + + if (genstr || genconf) { + num = do_generate(genstr, genconf, buf); + if (num < 0) { + ERR_print_errors(bio_err); + goto end; + } + } else { + + if (informat == FORMAT_PEM) { + BIO *tmp; + + if ((b64 = BIO_new(BIO_f_base64())) == NULL) + goto end; + BIO_push(b64, in); + tmp = in; + in = b64; + b64 = tmp; + } + + num = 0; + for (;;) { + if (!BUF_MEM_grow(buf, num + BUFSIZ)) + goto end; + i = BIO_read(in, &(buf->data[num]), BUFSIZ); + if (i <= 0) + break; + num += i; + } + } + str = (unsigned char *)buf->data; + + } + + /* If any structs to parse go through in sequence */ + + if (sk_OPENSSL_STRING_num(osk)) { + tmpbuf = str; + tmplen = num; + for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) { + ASN1_TYPE *atmp; + int typ; + j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0); + if (j <= 0 || j >= tmplen) { + BIO_printf(bio_err, "'%s' is out of range\n", + sk_OPENSSL_STRING_value(osk, i)); + continue; + } + tmpbuf += j; + tmplen -= j; + atmp = at; + ctmpbuf = tmpbuf; + at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen); + ASN1_TYPE_free(atmp); + if (!at) { + BIO_printf(bio_err, "Error parsing structure\n"); + ERR_print_errors(bio_err); + goto end; + } + typ = ASN1_TYPE_get(at); + if ((typ == V_ASN1_OBJECT) + || (typ == V_ASN1_BOOLEAN) + || (typ == V_ASN1_NULL)) { + BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ)); + ERR_print_errors(bio_err); + goto end; + } + /* hmm... this is a little evil but it works */ + tmpbuf = at->value.asn1_string->data; + tmplen = at->value.asn1_string->length; + } + str = tmpbuf; + num = tmplen; + } + + if (offset < 0 || offset >= num) { + BIO_printf(bio_err, "Error: offset out of range\n"); + goto end; + } + + num -= offset; + + if (length == 0 || length > (unsigned int)num) + length = (unsigned int)num; + if (derout != NULL) { + if (BIO_write(derout, str + offset, length) != (int)length) { + BIO_printf(bio_err, "Error writing output\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (!noout) { + const unsigned char *p = str + offset; + + if (it != NULL) { + ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it); + if (value == NULL) { + BIO_printf(bio_err, "Error parsing item %s\n", it->sname); + ERR_print_errors(bio_err); + goto end; + } + ASN1_item_print(bio_out, value, 0, it, NULL); + ASN1_item_free(value, it); + } else { + if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) { + ERR_print_errors(bio_err); + goto end; + } + } + } + ret = 0; + end: + BIO_free(derout); + BIO_free(in); + BIO_free(b64); + if (ret != 0) + ERR_print_errors(bio_err); + BUF_MEM_free(buf); + OPENSSL_free(name); + OPENSSL_free(header); + ASN1_TYPE_free(at); + sk_OPENSSL_STRING_free(osk); + return ret; +} + +static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf) +{ + CONF *cnf = NULL; + int len; + unsigned char *p; + ASN1_TYPE *atyp = NULL; + + if (genconf != NULL) { + if ((cnf = app_load_config(genconf)) == NULL) + goto err; + if (genstr == NULL) + genstr = NCONF_get_string(cnf, "default", "asn1"); + if (genstr == NULL) { + BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf); + goto err; + } + } + + atyp = ASN1_generate_nconf(genstr, cnf); + NCONF_free(cnf); + cnf = NULL; + + if (atyp == NULL) + return -1; + + len = i2d_ASN1_TYPE(atyp, NULL); + + if (len <= 0) + goto err; + + if (!BUF_MEM_grow(buf, len)) + goto err; + + p = (unsigned char *)buf->data; + + i2d_ASN1_TYPE(atyp, &p); + + ASN1_TYPE_free(atyp); + return len; + + err: + NCONF_free(cnf); + ASN1_TYPE_free(atyp); + return -1; +} diff --git a/apps/bf_prefix.c b/apps/bf_prefix.c deleted file mode 100644 --- a/apps/bf_prefix.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include "apps.h" - -static int prefix_write(BIO *b, const char *out, size_t outl, - size_t *numwritten); -static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); -static int prefix_puts(BIO *b, const char *str); -static int prefix_gets(BIO *b, char *str, int size); -static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); -static int prefix_create(BIO *b); -static int prefix_destroy(BIO *b); -static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); - -static BIO_METHOD *prefix_meth = NULL; - -BIO_METHOD *apps_bf_prefix(void) -{ - if (prefix_meth == NULL) { - if ((prefix_meth = - BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL - || !BIO_meth_set_create(prefix_meth, prefix_create) - || !BIO_meth_set_destroy(prefix_meth, prefix_destroy) - || !BIO_meth_set_write_ex(prefix_meth, prefix_write) - || !BIO_meth_set_read_ex(prefix_meth, prefix_read) - || !BIO_meth_set_puts(prefix_meth, prefix_puts) - || !BIO_meth_set_gets(prefix_meth, prefix_gets) - || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl) - || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) { - BIO_meth_free(prefix_meth); - prefix_meth = NULL; - } - } - return prefix_meth; -} - -typedef struct prefix_ctx_st { - char *prefix; - int linestart; /* flag to indicate we're at the line start */ -} PREFIX_CTX; - -static int prefix_create(BIO *b) -{ - PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); - - if (ctx == NULL) - return 0; - - ctx->prefix = NULL; - ctx->linestart = 1; - BIO_set_data(b, ctx); - BIO_set_init(b, 1); - return 1; -} - -static int prefix_destroy(BIO *b) -{ - PREFIX_CTX *ctx = BIO_get_data(b); - - OPENSSL_free(ctx->prefix); - OPENSSL_free(ctx); - return 1; -} - -static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) -{ - return BIO_read_ex(BIO_next(b), in, size, numread); -} - -static int prefix_write(BIO *b, const char *out, size_t outl, - size_t *numwritten) -{ - PREFIX_CTX *ctx = BIO_get_data(b); - - if (ctx == NULL) - return 0; - - /* If no prefix is set or if it's empty, we've got nothing to do here */ - if (ctx->prefix == NULL || *ctx->prefix == '\0') { - /* We do note if what comes next will be a new line, though */ - if (outl > 0) - ctx->linestart = (out[outl-1] == '\n'); - return BIO_write_ex(BIO_next(b), out, outl, numwritten); - } - - *numwritten = 0; - - while (outl > 0) { - size_t i; - char c; - - /* If we know that we're at the start of the line, output the prefix */ - if (ctx->linestart) { - size_t dontcare; - - if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), - &dontcare)) - return 0; - ctx->linestart = 0; - } - - /* Now, go look for the next LF, or the end of the string */ - for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) - continue; - if (c == '\n') - i++; - - /* Output what we found so far */ - while (i > 0) { - size_t num = 0; - - if (!BIO_write_ex(BIO_next(b), out, i, &num)) - return 0; - out += num; - outl -= num; - *numwritten += num; - i -= num; - } - - /* If we found a LF, what follows is a new line, so take note */ - if (c == '\n') - ctx->linestart = 1; - } - - return 1; -} - -static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) -{ - long ret = 0; - - switch (cmd) { - case PREFIX_CTRL_SET_PREFIX: - { - PREFIX_CTX *ctx = BIO_get_data(b); - - if (ctx == NULL) - break; - - OPENSSL_free(ctx->prefix); - ctx->prefix = OPENSSL_strdup((const char *)ptr); - ret = ctx->prefix != NULL; - } - break; - default: - if (BIO_next(b) != NULL) - ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); - break; - } - return ret; -} - -static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) -{ - return BIO_callback_ctrl(BIO_next(b), cmd, fp); -} - -static int prefix_gets(BIO *b, char *buf, int size) -{ - return BIO_gets(BIO_next(b), buf, size); -} - -static int prefix_puts(BIO *b, const char *str) -{ - return BIO_write(b, str, strlen(str)); -} diff --git a/apps/build.info b/apps/build.info --- a/apps/build.info +++ b/apps/build.info @@ -1,79 +1,90 @@ -{- our @apps_openssl_src = - qw(openssl.c - asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c - enc.c errstr.c - genpkey.c nseq.c passwd.c pkcs7.c pkcs8.c - pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c - s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.c - verify.c version.c x509.c rehash.c storeutl.c); - our @apps_lib_src = - ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c bf_prefix.c), - split(/\s+/, $target{apps_aux_src}) ); - our @apps_init_src = split(/\s+/, $target{apps_init_src}); - "" -} +SUBDIRS=lib -IF[{- !$disabled{apps} -}] - LIBS_NO_INST=libapps.a - SOURCE[libapps.a]={- join(" ", @apps_lib_src) -} - INCLUDE[libapps.a]=.. ../include +# Program init source, that don't have direct linkage with the rest of the +# source, and can therefore not be part of a library. +IF[{- !$disabled{uplink} -}] + $INITSRC=../ms/applink.c +ENDIF +IF[{- $config{target} =~ /^vms-/ -}] + $INITSRC=vms_decc_init.c +ENDIF - PROGRAMS=openssl - SOURCE[openssl]={- join(" ", @apps_init_src) -} - SOURCE[openssl]={- join(" ", @apps_openssl_src) -} - INCLUDE[openssl]=.. ../include - DEPEND[openssl]=libapps.a ../libssl - IF[{- !$disabled{'des'} -}] - SOURCE[openssl]=pkcs12.c - DEPEND[pkcs12.o]=progs.h - ENDIF - IF[{- !$disabled{'ec'} -}] - SOURCE[openssl]=ec.c ecparam.c - DEPEND[ec.o]=progs.h - DEPEND[ecparam.o]=progs.h - ENDIF - IF[{- !$disabled{'ocsp'} -}] - SOURCE[openssl]=ocsp.c - DEPEND[ocsp.o]=progs.h - ENDIF - IF[{- !$disabled{'srp'} -}] - SOURCE[openssl]=srp.c - DEPEND[srp.o]=progs.h - ENDIF - IF[{- !$disabled{'ts'} -}] - SOURCE[openssl]=ts.c - DEPEND[ts.o]=progs.h - ENDIF - IF[{- !$disabled{'dh'} -}] - SOURCE[openssl]=dhparam.c - DEPEND[dhparam.o]=progs.h - ENDIF - IF[{- !$disabled{'dsa'} -}] - SOURCE[openssl]=dsa.c dsaparam.c gendsa.c - DEPEND[dsa.o]=progs.h - DEPEND[dsaparam.o]=progs.h - DEPEND[gendsa.o]=progs.h - ENDIF - IF[{- !$disabled{'engine'} -}] - SOURCE[openssl]=engine.c - DEPEND[engine.o]=progs.h - ENDIF +# Source for the 'openssl' program +$OPENSSLSRC=\ + openssl.c \ + asn1parse.c ca.c ciphers.c crl.c crl2pkcs7.c dgst.c \ + enc.c errstr.c \ + genpkey.c kdf.c mac.c nseq.c passwd.c pkcs7.c \ + pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \ + s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \ + spkac.c verify.c version.c x509.c rehash.c storeutl.c \ + list.c info.c fipsinstall.c pkcs12.c +IF[{- !$disabled{'ec'} -}] + $OPENSSLSRC=$OPENSSLSRC ec.c ecparam.c +ENDIF +IF[{- !$disabled{'ocsp'} -}] + $OPENSSLSRC=$OPENSSLSRC ocsp.c +ENDIF +IF[{- !$disabled{'srp'} -}] + $OPENSSLSRC=$OPENSSLSRC srp.c +ENDIF +IF[{- !$disabled{'ts'} -}] + $OPENSSLSRC=$OPENSSLSRC ts.c +ENDIF +IF[{- !$disabled{'dh'} -}] +$OPENSSLSRC=$OPENSSLSRC dhparam.c +ENDIF +IF[{- !$disabled{'dsa'} -}] +$OPENSSLSRC=$OPENSSLSRC dsa.c dsaparam.c gendsa.c +ENDIF +IF[{- !$disabled{'engine'} -}] +$OPENSSLSRC=$OPENSSLSRC engine.c +ENDIF +IF[{- !$disabled{'rsa'} -}] +$OPENSSLSRC=$OPENSSLSRC rsa.c genrsa.c +ENDIF +IF[{- !$disabled{'deprecated-3.0'} -}] IF[{- !$disabled{'rsa'} -}] - SOURCE[openssl]=rsa.c rsautl.c genrsa.c - DEPEND[rsa.o]=progs.h - DEPEND[rsautl.o]=progs.h - DEPEND[genrsa.o]=progs.h + $OPENSSLSRC=$OPENSSLSRC rsautl.c ENDIF - IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}] +ENDIF +IF[{- !$disabled{'cms'} -}] + $OPENSSLSRC=$OPENSSLSRC cms.c +ENDIF +IF[{- !$disabled{'cmp'} -}] + $OPENSSLSRC=$OPENSSLSRC cmp.c lib/cmp_mock_srv.c +ENDIF + +IF[{- !$disabled{apps} -}] + PROGRAMS=openssl + SOURCE[openssl]=$INITSRC $OPENSSLSRC + INCLUDE[openssl]=.. ../include include + DEPEND[openssl]=libapps.a ../libssl + + # The nocheck attribute is picked up by progs.pl as a signal not to look + # at that file; some systems may have locked it as the output file, and + # therefore don't allow it to be read at the same time, making progs.pl + # fail. + SOURCE[openssl]{nocheck}=progs.c + DEPEND[${OPENSSLSRC/.c/.o} progs.o]=progs.h + GENERATE[progs.c]=progs.pl "-C" $(APPS_OPENSSL) + GENERATE[progs.h]=progs.pl "-H" $(APPS_OPENSSL) + # progs.pl tries to read all 'openssl' sources, including progs.c, so we make + # sure things are generated in the correct order. + DEPEND[progs.h]=progs.c + # Because the files to look through may change (depends on $OPENSSLSRC), + # always depend on a changed configuration. + DEPEND[progs.c]=../configdata.pm + + IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] GENERATE[openssl.rc]=../util/mkrc.pl openssl SOURCE[openssl]=openssl.rc ENDIF - {- join("\n ", map { (my $x = $_) =~ s|\.c$|.o|; "DEPEND[$x]=progs.h" } - @apps_openssl_src) -} - GENERATE[progs.h]=progs.pl $(APPS_OPENSSL) - DEPEND[progs.h]=../configdata.pm - - SCRIPTS=CA.pl tsget.pl + SCRIPTS{misc}=CA.pl SOURCE[CA.pl]=CA.pl.in + # linkname tells build files that a symbolic link or copy of this script + # without extension must be installed as well. Unix or Unix lookalike only. + SCRIPTS{misc,linkname=tsget}=tsget.pl SOURCE[tsget.pl]=tsget.in ENDIF diff --git a/apps/ca.c b/apps/ca.c old mode 100755 new mode 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -26,7 +26,7 @@ #ifndef W_OK # ifdef OPENSSL_SYS_VMS # include -# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) +# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_TANDEM) # include # endif #endif @@ -88,40 +88,46 @@ static char *lookup_conf(const CONF *conf, const char *group, const char *tag); -static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, +static int certify(X509 **xret, const char *infile, int informat, + EVP_PKEY *pkey, X509 *x509, + const char *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, - int default_op, int ext_copy, int selfsign); -static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + int default_op, int ext_copy, int selfsign, unsigned long dateopt); +static int certify_cert(X509 **xret, const char *infile, int certformat, + const char *passin, EVP_PKEY *pkey, X509 *x509, + const char *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy); + unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt); static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, - X509 *x509, const EVP_MD *dgst, + X509 *x509, const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy); + unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt); static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *conf, unsigned long certopt, unsigned long nameopt, - int default_op, int ext_copy, int selfsign); + int default_op, int ext_copy, int selfsign, unsigned long dateopt); static int get_certificate_status(const char *ser_status, CA_DB *db); static int do_updatedb(CA_DB *db); static int check_time_format(const char *str); @@ -132,77 +138,97 @@ static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str); static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); -static CONF *extconf = NULL; +static CONF *extfile_conf = NULL; static int preserve = 0; static int msie_hack = 0; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_ENGINE, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SUBJ, OPT_UTF8, OPT_CREATE_SERIAL, OPT_MULTIVALUE_RDN, OPT_STARTDATE, OPT_ENDDATE, OPT_DAYS, OPT_MD, OPT_POLICY, OPT_KEYFILE, OPT_KEYFORM, OPT_PASSIN, - OPT_KEY, OPT_CERT, OPT_SELFSIGN, OPT_IN, OPT_OUT, OPT_OUTDIR, + OPT_KEY, OPT_CERT, OPT_CERTFORM, OPT_SELFSIGN, + OPT_IN, OPT_INFORM, OPT_OUT, OPT_DATEOPT, OPT_OUTDIR, OPT_VFYOPT, OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN, - OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, + OPT_GENCRL, OPT_MSIE_HACK, OPT_CRL_LASTUPDATE, OPT_CRL_NEXTUPDATE, + OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, OPT_RAND_SERIAL, - OPT_R_ENUM, + OPT_R_ENUM, OPT_PROV_ENUM, /* Do not change the order here; see related case statements below */ OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE } OPTION_CHOICE; const OPTIONS ca_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [certreq...]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"}, + {"outdir", OPT_OUTDIR, '/', "Where to put output cert"}, + {"in", OPT_IN, '<', "The input cert request(s)"}, + {"inform", OPT_INFORM, 'F', "CSR input format (DER or PEM); default PEM"}, + {"infiles", OPT_INFILES, '-', "The last argument, requests to process"}, + {"out", OPT_OUT, '>', "Where to put the output file(s)"}, + {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, + {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"}, + {"batch", OPT_BATCH, '-', "Don't ask questions"}, + {"msie_hack", OPT_MSIE_HACK, '-', + "msie modifications to handle all Universal Strings"}, + {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"}, + {"spkac", OPT_SPKAC, '<', + "File contains DN and signed public key and challenge"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Configuration"), {"config", OPT_CONFIG, 's', "A config file"}, {"name", OPT_NAME, 's', "The particular CA definition to use"}, + {"section", OPT_NAME, 's', "An alias for -name"}, + {"policy", OPT_POLICY, 's', "The CA 'policy' to support"}, + + OPT_SECTION("Certificate"), {"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"}, - {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, + {"utf8", OPT_UTF8, '-', "Input characters are UTF8; default ASCII"}, {"create_serial", OPT_CREATE_SERIAL, '-', "If reading serial fails, create a new random serial"}, {"rand_serial", OPT_RAND_SERIAL, '-', "Always create a random serial; do not store it"}, {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', - "Enable support for multivalued RDNs"}, + "Deprecated; multi-valued RDNs support is always on."}, {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"}, {"enddate", OPT_ENDDATE, 's', "YYMMDDHHMMSSZ cert notAfter (overrides -days)"}, {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"}, - {"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"}, - {"policy", OPT_POLICY, 's', "The CA 'policy' to support"}, - {"keyfile", OPT_KEYFILE, 's', "Private key"}, - {"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"}, + {"extensions", OPT_EXTENSIONS, 's', + "Extension section (override value in config file)"}, + {"extfile", OPT_EXTFILE, '<', + "Configuration file with X509v3 extensions to add"}, + {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"}, + {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"}, + + OPT_SECTION("Signing"), + {"md", OPT_MD, 's', "Digest to use, such as sha256"}, + {"keyfile", OPT_KEYFILE, 's', "The CA private key"}, + {"keyform", OPT_KEYFORM, 'f', + "Private key file format (ENGINE, other values ignored)"}, + {"passin", OPT_PASSIN, 's', "Key and cert input file pass phrase source"}, + {"key", OPT_KEY, 's', + "Key to decrypt the private key or cert files if encrypted. Better use -passin"}, {"cert", OPT_CERT, '<', "The CA cert"}, + {"certform", OPT_CERTFORM, 'F', + "Certificate input format (DER/PEM/P12); has no effect"}, {"selfsign", OPT_SELFSIGN, '-', "Sign a cert with the key associated with it"}, - {"in", OPT_IN, '<', "The input PEM encoded cert request(s)"}, - {"out", OPT_OUT, '>', "Where to put the output file(s)"}, - {"outdir", OPT_OUTDIR, '/', "Where to put output cert"}, {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, - {"notext", OPT_NOTEXT, '-', "Do not print the generated certificate"}, - {"batch", OPT_BATCH, '-', "Don't ask questions"}, - {"preserveDN", OPT_PRESERVEDN, '-', "Don't re-order the DN"}, - {"noemailDN", OPT_NOEMAILDN, '-', "Don't add the EMAIL field to the DN"}, + {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"}, + + OPT_SECTION("Revocation"), {"gencrl", OPT_GENCRL, '-', "Generate a new CRL"}, - {"msie_hack", OPT_MSIE_HACK, '-', - "msie modifications to handle all those universal strings"}, - {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"}, - {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"}, - {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"}, - {"infiles", OPT_INFILES, '-', "The last argument, requests to process"}, - {"ss_cert", OPT_SS_CERT, '<', "File contains a self signed cert to sign"}, - {"spkac", OPT_SPKAC, '<', - "File contains DN and signed public key and challenge"}, - {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"}, {"valid", OPT_VALID, 's', "Add a Valid(not-revoked) DB entry about a cert (given in file)"}, - {"extensions", OPT_EXTENSIONS, 's', - "Extension section (override value in config file)"}, - {"extfile", OPT_EXTFILE, '<', - "Configuration file with X509v3 extensions to add"}, {"status", OPT_STATUS, 's', "Shows cert status given the serial number"}, {"updatedb", OPT_UPDATEDB, '-', "Updates db for expired cert"}, {"crlexts", OPT_CRLEXTS, 's', @@ -214,10 +240,20 @@ "sets compromise time to val and the revocation reason to keyCompromise"}, {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's', "sets compromise time to val and the revocation reason to CACompromise"}, + {"crl_lastupdate", OPT_CRL_LASTUPDATE, 's', + "Sets the CRL lastUpdate time to val (YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ)"}, + {"crl_nextupdate", OPT_CRL_NEXTUPDATE, 's', + "Sets the CRL nextUpdate time to val (YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ)"}, + {"crldays", OPT_CRLDAYS, 'p', "Days until the next CRL is due"}, + {"crlhours", OPT_CRLHOURS, 'p', "Hours until the next CRL is due"}, + {"crlsec", OPT_CRLSEC, 'p', "Seconds until the next CRL is due"}, + {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"certreq", 0, 0, "Certificate requests to be signed (optional)"}, {NULL} }; @@ -229,19 +265,21 @@ EVP_PKEY *pkey = NULL; BIO *in = NULL, *out = NULL, *Sout = NULL; ASN1_INTEGER *tmpser; - ASN1_TIME *tmptm; CA_DB *db = NULL; DB_ATTR db_attr; STACK_OF(CONF_VALUE) *attribs = NULL; - STACK_OF(OPENSSL_STRING) *sigopts = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL; STACK_OF(X509) *cert_sk = NULL; X509_CRL *crl = NULL; - const EVP_MD *dgst = NULL; char *configfile = default_config_file, *section = NULL; - char *md = NULL, *policy = NULL, *keyfile = NULL; - char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL; + char def_dgst[80] = ""; + char *dgst = NULL, *policy = NULL, *keyfile = NULL; + char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL; + int certformat = FORMAT_UNDEF, informat = FORMAT_UNDEF; + unsigned long dateopt = ASN1_DTFLGS_RFC822; const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL; const char *extensions = NULL, *extfile = NULL, *passinarg = NULL; + char *passin = NULL; char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL; const char *serialfile = NULL, *subj = NULL; char *prog, *startdate = NULL, *enddate = NULL; @@ -251,11 +289,12 @@ char *const *pp; const char *p; size_t outdirlen = 0; - int create_ser = 0, free_key = 0, total = 0, total_done = 0; + int create_ser = 0, free_passin = 0, total = 0, total_done = 0; int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE; - int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0; + int keyformat = FORMAT_UNDEF, multirdn = 1, notext = 0, output_der = 0; int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0; - int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret; + int rand_ser = 0, i, j, selfsign = 0, def_ret; + char *crl_lastupdate = NULL, *crl_nextupdate = NULL; long crldays = 0, crlhours = 0, crlsec = 0, days = 0; unsigned long chtype = MBSTRING_ASC, certopt = 0; X509 *x509 = NULL, *x509p = NULL, *x = NULL; @@ -279,9 +318,17 @@ req = 1; infile = opt_arg(); break; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; case OPT_OUT: outfile = opt_arg(); break; + case OPT_DATEOPT: + if (!set_dateopt(&dateopt, opt_arg())) + goto opthelp; + break; case OPT_VERBOSE: verbose = 1; break; @@ -305,7 +352,7 @@ create_ser = 1; break; case OPT_MULTIVALUE_RDN: - multirdn = 1; + /* obsolete */ break; case OPT_STARTDATE: startdate = opt_arg(); @@ -317,7 +364,7 @@ days = atoi(opt_arg()); break; case OPT_MD: - md = opt_arg(); + dgst = opt_arg(); break; case OPT_POLICY: policy = opt_arg(); @@ -336,12 +383,20 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_KEY: - key = opt_arg(); + passin = opt_arg(); break; case OPT_CERT: certfile = opt_arg(); break; + case OPT_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &certformat)) + goto opthelp; + break; case OPT_SELFSIGN: selfsign = 1; break; @@ -354,6 +409,12 @@ if (sigopts == NULL || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto end; break; + case OPT_VFYOPT: + if (vfyopts == NULL) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (vfyopts == NULL || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto end; + break; case OPT_NOTEXT: notext = 1; break; @@ -372,6 +433,12 @@ case OPT_MSIE_HACK: msie_hack = 1; break; + case OPT_CRL_LASTUPDATE: + crl_lastupdate = opt_arg(); + break; + case OPT_CRL_NEXTUPDATE: + crl_nextupdate = opt_arg(); + break; case OPT_CRLDAYS: crldays = atol(opt_arg()); break; @@ -427,13 +494,13 @@ break; } } + end_of_options: + /* Remaining args are files to certify. */ argc = opt_num_rest(); argv = opt_rest(); - BIO_printf(bio_err, "Using configuration from %s\n", configfile); - - if ((conf = app_load_config(configfile)) == NULL) + if ((conf = app_load_config_verbose(configfile, 1)) == NULL) goto end; if (configfile != default_config_file && !app_load_modules(conf)) goto end; @@ -456,12 +523,12 @@ BIO_free(oid_bio); } } - if (!add_oid_section(conf)) { - ERR_print_errors(bio_err); + if (!add_oid_section(conf)) goto end; - } app_RAND_load_conf(conf, BASE_SECTION); + if (!app_RAND_load()) + goto end; f = NCONF_get_string(conf, section, STRING_MASK); if (f == NULL) @@ -495,8 +562,10 @@ goto end; db = load_index(dbfile, &db_attr); - if (db == NULL) + if (db == NULL) { + BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", dbfile); goto end; + } if (index_index(db) <= 0) goto end; @@ -513,16 +582,15 @@ && (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL) goto end; - if (key == NULL) { - free_key = 1; - if (!app_passwd(passinarg, NULL, &key, NULL)) { + if (passin == NULL) { + free_passin = 1; + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } } - pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key"); - if (key != NULL) - OPENSSL_cleanse(key, strlen(key)); + pkey = load_key(keyfile, keyformat, 0, passin, e, "CA private key"); + cleanse(passin); if (pkey == NULL) /* load_key() has already printed an appropriate message */ goto end; @@ -534,7 +602,7 @@ && (certfile = lookup_conf(conf, section, ENV_CERTIFICATE)) == NULL) goto end; - x509 = load_cert(certfile, FORMAT_PEM, "CA certificate"); + x509 = load_cert_pass(certfile, certformat, 1, passin, "CA certificate"); if (x509 == NULL) goto end; @@ -624,8 +692,10 @@ goto end; db = load_index(dbfile, &db_attr); - if (db == NULL) + if (db == NULL) { + BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", dbfile); goto end; + } /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { @@ -703,7 +773,7 @@ /*****************************************************************/ /* Read extensions config file */ if (extfile) { - if ((extconf = app_load_config(extfile)) == NULL) { + if ((extfile_conf = app_load_config(extfile)) == NULL) { ret = 1; goto end; } @@ -714,7 +784,7 @@ /* We can have sections in the ext file */ if (extensions == NULL) { - extensions = NCONF_get_string(extconf, "default", "extensions"); + extensions = NCONF_get_string(extfile_conf, "default", "extensions"); if (extensions == NULL) extensions = "default"; } @@ -728,28 +798,25 @@ } } - def_ret = EVP_PKEY_get_default_digest_nid(pkey, &def_nid); + def_ret = EVP_PKEY_get_default_digest_name(pkey, def_dgst, sizeof(def_dgst)); /* - * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is + * EVP_PKEY_get_default_digest_name() returns 2 if the digest is * mandatory for this algorithm. */ - if (def_ret == 2 && def_nid == NID_undef) { + if (def_ret == 2 && strcmp(def_dgst, "UNDEF") == 0) { /* The signing algorithm requires there to be no digest */ - dgst = EVP_md_null(); - } else if (md == NULL - && (md = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) { + dgst = NULL; + } else if (dgst == NULL + && (dgst = lookup_conf(conf, section, ENV_DEFAULT_MD)) == NULL) { goto end; } else { - if (strcmp(md, "default") == 0) { + if (strcmp(dgst, "default") == 0) { if (def_ret <= 0) { BIO_puts(bio_err, "no default digest\n"); goto end; } - md = (char *)OBJ_nid2sn(def_nid); + dgst = def_dgst; } - - if (!opt_md(md, &dgst)) - goto end; } if (req) { @@ -761,8 +828,7 @@ email_dn = 0; } if (verbose) - BIO_printf(bio_err, "message digest is %s\n", - OBJ_nid2ln(EVP_MD_type(dgst))); + BIO_printf(bio_err, "message digest is %s\n", dgst); if (policy == NULL && (policy = lookup_conf(conf, section, ENV_POLICY)) == NULL) goto end; @@ -778,7 +844,20 @@ goto end; } - if (extconf == NULL) { + if (extfile_conf != NULL) { + /* Check syntax of extfile */ + X509V3_CTX ctx; + + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, extfile_conf); + if (!X509V3_EXT_add_nconf(extfile_conf, &ctx, extensions, NULL)) { + BIO_printf(bio_err, + "Error checking certificate extensions from extfile section %s\n", + extensions); + ret = 1; + goto end; + } + } else { /* * no '-extfile' option, so we look for extensions in the main * configuration file @@ -789,13 +868,14 @@ ERR_clear_error(); } if (extensions != NULL) { - /* Check syntax of file */ + /* Check syntax of config file section */ X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) { BIO_printf(bio_err, - "Error Loading extension section %s\n", + "Error checking certificate extension config section %s\n", extensions); ret = 1; goto end; @@ -874,7 +954,7 @@ attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, extensions, conf, verbose, certopt, get_nameopt(), default_op, - ext_copy); + ext_copy, dateopt); if (j < 0) goto end; if (j > 0) { @@ -890,12 +970,12 @@ } if (ss_cert_file != NULL) { total++; - j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts, - attribs, + j = certify_cert(&x, ss_cert_file, certformat, passin, pkey, + x509, dgst, sigopts, vfyopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, certopt, get_nameopt(), default_op, - ext_copy); + ext_copy, dateopt); if (j < 0) goto end; if (j > 0) { @@ -911,10 +991,11 @@ } if (infile != NULL) { total++; - j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, + j = certify(&x, infile, informat, pkey, x509p, dgst, + sigopts, vfyopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, get_nameopt(), default_op, ext_copy, selfsign); + certopt, get_nameopt(), default_op, ext_copy, selfsign, dateopt); if (j < 0) goto end; if (j > 0) { @@ -930,10 +1011,12 @@ } for (i = 0; i < argc; i++) { total++; - j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, + j = certify(&x, argv[i], informat, pkey, x509p, dgst, + sigopts, vfyopts, + attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, get_nameopt(), default_op, ext_copy, selfsign); + certopt, get_nameopt(), default_op, ext_copy, selfsign, dateopt); if (j < 0) goto end; if (j > 0) { @@ -996,7 +1079,7 @@ for (i = 0; i < sk_X509_num(cert_sk); i++) { BIO *Cout = NULL; X509 *xi = sk_X509_value(cert_sk, i); - ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi); + const ASN1_INTEGER *serialNumber = X509_get0_serialNumber(xi); const unsigned char *psn = ASN1_STRING_get0_data(serialNumber); const int snl = ASN1_STRING_length(serialNumber); const int filen_len = 2 * (snl > 0 ? snl : 1) + sizeof(".pem"); @@ -1067,11 +1150,12 @@ if (crl_ext != NULL) { /* Check syntax of file */ X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) { BIO_printf(bio_err, - "Error Loading CRL extension section %s\n", crl_ext); + "Error checking CRL extension section %s\n", crl_ext); ret = 1; goto end; } @@ -1094,7 +1178,8 @@ crlhours = 0; ERR_clear_error(); } - if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { + if ((crl_nextupdate == NULL) && + (crldays == 0) && (crlhours == 0) && (crlsec == 0)) { BIO_printf(bio_err, "cannot lookup how long until the next CRL is issued\n"); goto end; @@ -1102,24 +1187,23 @@ if (verbose) BIO_printf(bio_err, "making CRL\n"); - if ((crl = X509_CRL_new()) == NULL) + if ((crl = X509_CRL_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) goto end; if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto end; - tmptm = ASN1_TIME_new(); - if (tmptm == NULL - || X509_gmtime_adj(tmptm, 0) == NULL - || !X509_CRL_set1_lastUpdate(crl, tmptm) - || X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, - NULL) == NULL) { - BIO_puts(bio_err, "error setting CRL nextUpdate\n"); - ASN1_TIME_free(tmptm); + if (!set_crl_lastupdate(crl, crl_lastupdate)) { + BIO_puts(bio_err, "error setting CRL lastUpdate\n"); + ret = 1; goto end; } - X509_CRL_set1_nextUpdate(crl, tmptm); - ASN1_TIME_free(tmptm); + if (!set_crl_nextupdate(crl, crl_nextupdate, + crldays, crlhours, crlsec)) { + BIO_puts(bio_err, "error setting CRL nextUpdate\n"); + ret = 1; + goto end; + } for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { pp = sk_OPENSSL_PSTRING_value(db->db->data, i); @@ -1157,12 +1241,16 @@ if (crl_ext != NULL || crlnumberfile != NULL) { X509V3_CTX crlctx; + X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); X509V3_set_nconf(&crlctx, conf); if (crl_ext != NULL) - if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) + if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl)) { + BIO_printf(bio_err, + "Error adding CRL extensions from section %s\n", crl_ext); goto end; + } if (crlnumberfile != NULL) { tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); if (!tmpser) @@ -1175,8 +1263,8 @@ } } if (crl_ext != NULL || crl_v2) { - if (!X509_CRL_set_version(crl, 1)) - goto end; /* version 2 CRL */ + if (!X509_CRL_set_version(crl, X509_CRL_VERSION_2)) + goto end; } /* we have a CRL number that need updating */ @@ -1210,7 +1298,9 @@ goto end; } else { X509 *revcert; - revcert = load_cert(infile, FORMAT_PEM, infile); + + revcert = load_cert_pass(infile, informat, 1, passin, + "certificate to be revoked"); if (revcert == NULL) goto end; if (dorevoke == 2) @@ -1239,17 +1329,19 @@ BIO_free_all(in); sk_X509_pop_free(cert_sk, X509_free); - if (free_key) - OPENSSL_free(key); + cleanse(passin); + if (free_passin) + OPENSSL_free(passin); BN_free(serial); BN_free(crlnumber); free_index(db); sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(vfyopts); EVP_PKEY_free(pkey); X509_free(x509); X509_CRL_free(crl); NCONF_free(conf); - NCONF_free(extconf); + NCONF_free(extfile_conf); release_engine(e); return ret; } @@ -1262,101 +1354,94 @@ return entry; } -static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, +static int certify(X509 **xret, const char *infile, int informat, + EVP_PKEY *pkey, X509 *x509, + const char *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, - int default_op, int ext_copy, int selfsign) + int default_op, int ext_copy, int selfsign, unsigned long dateopt) { X509_REQ *req = NULL; - BIO *in = NULL; EVP_PKEY *pktmp = NULL; int ok = -1, i; - in = BIO_new_file(infile, "r"); - if (in == NULL) { - ERR_print_errors(bio_err); + req = load_csr(infile, informat, "certificate request"); + if (req == NULL) goto end; - } - if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { - BIO_printf(bio_err, "Error reading certificate request in %s\n", - infile); + if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "Error unpacking public key\n"); goto end; } if (verbose) X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT); BIO_printf(bio_err, "Check that the request matches the signature\n"); + ok = 0; if (selfsign && !X509_REQ_check_private_key(req, pkey)) { BIO_printf(bio_err, "Certificate request and CA private key do not match\n"); - ok = 0; - goto end; - } - if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { - BIO_printf(bio_err, "error unpacking public key\n"); goto end; } - i = X509_REQ_verify(req, pktmp); - pktmp = NULL; + i = do_X509_REQ_verify(req, pktmp, vfyopts); if (i < 0) { - ok = 0; - BIO_printf(bio_err, "Signature verification problems....\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Signature verification problems...\n"); goto end; } if (i == 0) { - ok = 0; BIO_printf(bio_err, "Signature did not match the certificate request\n"); - ERR_print_errors(bio_err); goto end; - } else { - BIO_printf(bio_err, "Signature ok\n"); } + BIO_printf(bio_err, "Signature ok\n"); ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, verbose, req, ext_sect, lconf, certopt, nameopt, default_op, - ext_copy, selfsign); + ext_copy, selfsign, dateopt); end: + ERR_print_errors(bio_err); X509_REQ_free(req); - BIO_free(in); return ok; } -static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, +static int certify_cert(X509 **xret, const char *infile, int certformat, + const char *passin, EVP_PKEY *pkey, X509 *x509, + const char *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(OPENSSL_STRING) *vfyopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy) + unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt) { - X509 *req = NULL; + X509 *template_cert = NULL; X509_REQ *rreq = NULL; EVP_PKEY *pktmp = NULL; int ok = -1, i; - if ((req = load_cert(infile, FORMAT_PEM, infile)) == NULL) + if ((template_cert = load_cert_pass(infile, certformat, 1, passin, + "template certificate")) == NULL) goto end; if (verbose) - X509_print(bio_err, req); + X509_print(bio_err, template_cert); BIO_printf(bio_err, "Check that the request matches the signature\n"); - if ((pktmp = X509_get0_pubkey(req)) == NULL) { + if ((pktmp = X509_get0_pubkey(template_cert)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); goto end; } - i = X509_verify(req, pktmp); + i = do_X509_verify(template_cert, pktmp, vfyopts); if (i < 0) { ok = 0; BIO_printf(bio_err, "Signature verification problems....\n"); @@ -1370,30 +1455,31 @@ BIO_printf(bio_err, "Signature ok\n"); } - if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL) + if ((rreq = X509_to_X509_REQ(template_cert, NULL, NULL)) == NULL) goto end; ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op, - ext_copy, 0); + ext_copy, 0, dateopt); end: X509_REQ_free(rreq); - X509_free(req); + X509_free(template_cert); return ok; } static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, - const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *lconf, unsigned long certopt, unsigned long nameopt, - int default_op, int ext_copy, int selfsign) + int default_op, int ext_copy, int selfsign, unsigned long dateopt) { - X509_NAME *name = NULL, *CAname = NULL, *subject = NULL; + const X509_NAME *name = NULL; + X509_NAME *CAname = NULL, *subject = NULL; const ASN1_TIME *tm; ASN1_STRING *str, *str2; ASN1_OBJECT *obj; @@ -1407,17 +1493,16 @@ OPENSSL_STRING *irow = NULL; OPENSSL_STRING *rrow = NULL; char buf[25]; + X509V3_CTX ext_ctx; for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; if (subj) { - X509_NAME *n = parse_name(subj, chtype, multirdn); + X509_NAME *n = parse_name(subj, chtype, multirdn, "subject"); - if (!n) { - ERR_print_errors(bio_err); + if (!n) goto end; - } X509_REQ_set_subject_name(req, n); X509_NAME_free(n); } @@ -1592,15 +1677,9 @@ BIO_printf(bio_err, "Everything appears to be ok, creating and signing the certificate\n"); - if ((ret = X509_new()) == NULL) + if ((ret = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) goto end; -#ifdef X509_V3 - /* Make it an X509 v3 certificate. */ - if (!X509_set_version(ret, 2)) - goto end; -#endif - if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) goto end; if (selfsign) { @@ -1630,32 +1709,24 @@ if (!i) goto end; + /* Initialize the context structure */ + X509V3_set_ctx(&ext_ctx, selfsign ? ret : x509, + ret, req, NULL, X509V3_CTX_REPLACE); + /* Lets add the extensions, if there are any */ if (ext_sect) { - X509V3_CTX ctx; - - /* Initialize the context structure */ - if (selfsign) - X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); - else - X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); - - if (extconf != NULL) { + if (extfile_conf != NULL) { if (verbose) BIO_printf(bio_err, "Extra configuration file found\n"); - /* Use the extconf configuration db LHASH */ - X509V3_set_nconf(&ctx, extconf); - - /* Test the structure (needed?) */ - /* X509V3_set_ctx_test(&ctx); */ + /* Use the extfile_conf configuration db LHASH */ + X509V3_set_nconf(&ext_ctx, extfile_conf); /* Adds exts contained in the configuration file */ - if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) { + if (!X509V3_EXT_add_nconf(extfile_conf, &ext_ctx, ext_sect, ret)) { BIO_printf(bio_err, - "ERROR: adding extensions in section %s\n", + "Error adding certificate extensions from extfile section %s\n", ext_sect); - ERR_print_errors(bio_err); goto end; } if (verbose) @@ -1663,13 +1734,12 @@ "Successfully added extensions from file.\n"); } else if (ext_sect) { /* We found extensions to be set from config file */ - X509V3_set_nconf(&ctx, lconf); + X509V3_set_nconf(&ext_ctx, lconf); - if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { + if (!X509V3_EXT_add_nconf(lconf, &ext_ctx, ext_sect, ret)) { BIO_printf(bio_err, - "ERROR: adding extensions in section %s\n", + "Error adding certificate extensions from config section %s\n", ext_sect); - ERR_print_errors(bio_err); goto end; } @@ -1683,19 +1753,9 @@ if (!copy_extensions(ret, req, ext_copy)) { BIO_printf(bio_err, "ERROR: adding extensions from request\n"); - ERR_print_errors(bio_err); goto end; } - { - const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret); - - if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0) - /* Make it an X509 v3 certificate. */ - if (!X509_set_version(ret, 2)) - goto end; - } - if (verbose) BIO_printf(bio_err, "The subject name appears to be ok, checking data base for clashes\n"); @@ -1825,7 +1885,7 @@ } BIO_printf(bio_err, "Certificate is to be certified until "); - ASN1_TIME_print(bio_err, X509_get0_notAfter(ret)); + ASN1_TIME_print_ex(bio_err, X509_get0_notAfter(ret), dateopt); if (days) BIO_printf(bio_err, " (%ld days)", days); BIO_printf(bio_err, "\n"); @@ -1853,7 +1913,7 @@ !EVP_PKEY_missing_parameters(pkey)) EVP_PKEY_copy_parameters(pktmp, pkey); - if (!do_X509_sign(ret, pkey, dgst, sigopts)) + if (!do_X509_sign(ret, pkey, dgst, sigopts, &ext_ctx)) goto end; /* We now just add it to the database as DB_TYPE_VAL('V') */ @@ -1911,14 +1971,14 @@ } static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, - X509 *x509, const EVP_MD *dgst, + X509 *x509, const char *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, const char *subj, unsigned long chtype, int multirdn, int email_dn, const char *startdate, const char *enddate, long days, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, - unsigned long nameopt, int default_op, int ext_copy) + unsigned long nameopt, int default_op, int ext_copy, unsigned long dateopt) { STACK_OF(CONF_VALUE) *sk = NULL; LHASH_OF(CONF_VALUE) *parms = NULL; @@ -1941,7 +2001,6 @@ parms = CONF_load(NULL, infile, &errline); if (parms == NULL) { BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile); - ERR_print_errors(bio_err); goto end; } @@ -1959,10 +2018,8 @@ * and we can use the same code as if you had a real X509 request. */ req = X509_REQ_new(); - if (req == NULL) { - ERR_print_errors(bio_err); + if (req == NULL) goto end; - } /* * Build up the subject name set. @@ -1993,7 +2050,6 @@ if (spki == NULL) { BIO_printf(bio_err, "unable to load Netscape SPKAC structure\n"); - ERR_print_errors(bio_err); goto end; } } @@ -2035,7 +2091,7 @@ ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, 1, verbose, req, ext_sect, lconf, certopt, nameopt, default_op, - ext_copy, 0); + ext_copy, 0, dateopt); end: X509_REQ_free(req); CONF_free(parms); @@ -2062,7 +2118,7 @@ for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); - bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); + bn = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x509), NULL); if (!bn) goto end; if (BN_is_zero(bn)) @@ -2313,7 +2369,7 @@ case REV_CRL_REASON: for (i = 0; i < 8; i++) { - if (strcasecmp(rev_arg, crl_reasons[i]) == 0) { + if (OPENSSL_strcasecmp(rev_arg, crl_reasons[i]) == 0) { reason = crl_reasons[i]; break; } @@ -2413,18 +2469,18 @@ rtmp = ASN1_ENUMERATED_new(); if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code)) goto end; - if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) + if (X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0) <= 0) goto end; } if (rev && comp_time) { - if (!X509_REVOKED_add1_ext_i2d - (rev, NID_invalidity_date, comp_time, 0, 0)) + if (X509_REVOKED_add1_ext_i2d + (rev, NID_invalidity_date, comp_time, 0, 0) <= 0) goto end; } if (rev && hold) { - if (!X509_REVOKED_add1_ext_i2d - (rev, NID_hold_instruction_code, hold, 0, 0)) + if (X509_REVOKED_add1_ext_i2d + (rev, NID_hold_instruction_code, hold, 0, 0) <= 0) goto end; } @@ -2530,7 +2586,7 @@ } if (reason_str) { for (i = 0; i < NUM_REASONS; i++) { - if (strcasecmp(reason_str, crl_reasons[i]) == 0) { + if (OPENSSL_strcasecmp(reason_str, crl_reasons[i]) == 0) { reason_code = i; break; } diff --git a/apps/ciphers.c b/apps/ciphers.c --- a/apps/ciphers.c +++ b/apps/ciphers.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -14,9 +14,10 @@ #include "progs.h" #include #include +#include "s_apps.h" typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_STDNAME, OPT_CONVERT, OPT_SSL3, @@ -27,39 +28,50 @@ OPT_PSK, OPT_SRP, OPT_CIPHERSUITES, - OPT_V, OPT_UPPER_V, OPT_S + OPT_V, OPT_UPPER_V, OPT_S, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS ciphers_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cipher]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Output"), {"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"}, {"V", OPT_UPPER_V, '-', "Even more verbose"}, + {"stdname", OPT_STDNAME, '-', "Show standard cipher names"}, + {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"}, + + OPT_SECTION("Cipher specification"), {"s", OPT_S, '-', "Only supported ciphers"}, #ifndef OPENSSL_NO_SSL3 - {"ssl3", OPT_SSL3, '-', "SSL3 mode"}, + {"ssl3", OPT_SSL3, '-', "Ciphers compatible with SSL3"}, #endif #ifndef OPENSSL_NO_TLS1 - {"tls1", OPT_TLS1, '-', "TLS1 mode"}, + {"tls1", OPT_TLS1, '-', "Ciphers compatible with TLS1"}, #endif #ifndef OPENSSL_NO_TLS1_1 - {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"}, + {"tls1_1", OPT_TLS1_1, '-', "Ciphers compatible with TLS1.1"}, #endif #ifndef OPENSSL_NO_TLS1_2 - {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"}, + {"tls1_2", OPT_TLS1_2, '-', "Ciphers compatible with TLS1.2"}, #endif #ifndef OPENSSL_NO_TLS1_3 - {"tls1_3", OPT_TLS1_3, '-', "TLS1.3 mode"}, + {"tls1_3", OPT_TLS1_3, '-', "Ciphers compatible with TLS1.3"}, #endif - {"stdname", OPT_STDNAME, '-', "Show standard cipher names"}, #ifndef OPENSSL_NO_PSK - {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"}, + {"psk", OPT_PSK, '-', "Include ciphersuites requiring PSK"}, #endif #ifndef OPENSSL_NO_SRP - {"srp", OPT_SRP, '-', "include ciphersuites requiring SRP"}, + {"srp", OPT_SRP, '-', "(deprecated) Include ciphersuites requiring SRP"}, #endif - {"convert", OPT_CONVERT, 's', "Convert standard name into OpenSSL name"}, {"ciphersuites", OPT_CIPHERSUITES, 's', "Configure the TLSv1.3 ciphersuites to use"}, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"cipher", 0, 0, "Cipher string to decode (optional)"}, {NULL} }; @@ -72,12 +84,6 @@ return 0; } #endif -#ifndef OPENSSL_NO_SRP -static char *dummy_srp(SSL *ssl, void *arg) -{ - return ""; -} -#endif int ciphers_main(int argc, char **argv) { @@ -159,13 +165,18 @@ case OPT_CIPHERSUITES: ciphersuites = opt_arg(); break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* Optional arg is cipher name. */ argv = opt_rest(); argc = opt_num_rest(); - if (argc == 1) - ciphers = *argv; + ciphers = argv[0]; else if (argc != 0) goto opthelp; @@ -176,7 +187,7 @@ goto end; } - ctx = SSL_CTX_new(meth); + ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth); if (ctx == NULL) goto err; if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0) @@ -190,7 +201,7 @@ #endif #ifndef OPENSSL_NO_SRP if (srp) - SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); + set_up_dummy_srp(ctx); #endif if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites)) { @@ -216,6 +227,10 @@ if (!verbose) { for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i); + + if (!ossl_assert(c != NULL)) + continue; + p = SSL_CIPHER_get_name(c); if (p == NULL) break; @@ -231,6 +246,9 @@ c = sk_SSL_CIPHER_value(sk, i); + if (!ossl_assert(c != NULL)) + continue; + if (Verbose) { unsigned long id = SSL_CIPHER_get_id(c); int id0 = (int)(id >> 24); @@ -248,7 +266,7 @@ const char *nm = SSL_CIPHER_standard_name(c); if (nm == NULL) nm = "UNKNOWN"; - BIO_printf(bio_out, "%s - ", nm); + BIO_printf(bio_out, "%-45s - ", nm); } BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof(buf))); } diff --git a/apps/cmp.c b/apps/cmp.c new file mode 100644 --- /dev/null +++ b/apps/cmp.c @@ -0,0 +1,3023 @@ +/* + * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Nokia 2007-2019 + * Copyright Siemens AG 2015-2019 + * + * 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 + * https://www.openssl.org/source/license.html + */ + +/* This app is disabled when OPENSSL_NO_CMP is defined. */ + +#include +#include + +#include "apps.h" +#include "http_server.h" +#include "s_apps.h" +#include "progs.h" + +#include "cmp_mock_srv.h" + +/* tweaks needed due to missing unistd.h on Windows */ +#if defined(_WIN32) && !defined(__BORLANDC__) +# define access _access +#endif +#ifndef F_OK +# define F_OK 0 +#endif + +#include +#include +#include + +/* explicit #includes not strictly needed since implied by the above: */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *prog; +static char *opt_config = NULL; +#define CMP_SECTION "cmp" +#define SECTION_NAME_MAX 40 /* max length of section name */ +#define DEFAULT_SECTION "default" +static char *opt_section = CMP_SECTION; +static int opt_verbosity = OSSL_CMP_LOG_INFO; + +static int read_config(void); + +static CONF *conf = NULL; /* OpenSSL config file context structure */ +static OSSL_CMP_CTX *cmp_ctx = NULL; /* the client-side CMP context */ + +/* the type of cmp command we want to send */ +typedef enum { + CMP_IR, + CMP_KUR, + CMP_CR, + CMP_P10CR, + CMP_RR, + CMP_GENM +} cmp_cmd_t; + +/* message transfer */ +#ifndef OPENSSL_NO_SOCK +static char *opt_server = NULL; +static char *opt_proxy = NULL; +static char *opt_no_proxy = NULL; +#endif +static char *opt_recipient = NULL; +static char *opt_path = NULL; +static int opt_keep_alive = 1; +static int opt_msg_timeout = -1; +static int opt_total_timeout = -1; + +/* server authentication */ +static char *opt_trusted = NULL; +static char *opt_untrusted = NULL; +static char *opt_srvcert = NULL; +static char *opt_expect_sender = NULL; +static int opt_ignore_keyusage = 0; +static int opt_unprotected_errors = 0; +static char *opt_extracertsout = NULL; +static char *opt_cacertsout = NULL; + +/* client authentication */ +static char *opt_ref = NULL; +static char *opt_secret = NULL; +static char *opt_cert = NULL; +static char *opt_own_trusted = NULL; +static char *opt_key = NULL; +static char *opt_keypass = NULL; +static char *opt_digest = NULL; +static char *opt_mac = NULL; +static char *opt_extracerts = NULL; +static int opt_unprotected_requests = 0; + +/* generic message */ +static char *opt_cmd_s = NULL; +static int opt_cmd = -1; +static char *opt_geninfo = NULL; +static char *opt_infotype_s = NULL; +static int opt_infotype = NID_undef; + +/* certificate enrollment */ +static char *opt_newkey = NULL; +static char *opt_newkeypass = NULL; +static char *opt_subject = NULL; +static char *opt_issuer = NULL; +static int opt_days = 0; +static char *opt_reqexts = NULL; +static char *opt_sans = NULL; +static int opt_san_nodefault = 0; +static char *opt_policies = NULL; +static char *opt_policy_oids = NULL; +static int opt_policy_oids_critical = 0; +static int opt_popo = OSSL_CRMF_POPO_NONE - 1; +static char *opt_csr = NULL; +static char *opt_out_trusted = NULL; +static int opt_implicit_confirm = 0; +static int opt_disable_confirm = 0; +static char *opt_certout = NULL; +static char *opt_chainout = NULL; + +/* certificate enrollment and revocation */ +static char *opt_oldcert = NULL; +static int opt_revreason = CRL_REASON_NONE; + +/* credentials format */ +static char *opt_certform_s = "PEM"; +static int opt_certform = FORMAT_PEM; +static char *opt_keyform_s = NULL; +static int opt_keyform = FORMAT_UNDEF; +static char *opt_otherpass = NULL; +static char *opt_engine = NULL; + +#ifndef OPENSSL_NO_SOCK +/* TLS connection */ +static int opt_tls_used = 0; +static char *opt_tls_cert = NULL; +static char *opt_tls_key = NULL; +static char *opt_tls_keypass = NULL; +static char *opt_tls_extra = NULL; +static char *opt_tls_trusted = NULL; +static char *opt_tls_host = NULL; +#endif + +/* client-side debugging */ +static int opt_batch = 0; +static int opt_repeat = 1; +static char *opt_reqin = NULL; +static int opt_reqin_new_tid = 0; +static char *opt_reqout = NULL; +static char *opt_rspin = NULL; +static char *opt_rspout = NULL; +static int opt_use_mock_srv = 0; + +/* mock server */ +#ifndef OPENSSL_NO_SOCK +static char *opt_port = NULL; +static int opt_max_msgs = 0; +#endif +static char *opt_srv_ref = NULL; +static char *opt_srv_secret = NULL; +static char *opt_srv_cert = NULL; +static char *opt_srv_key = NULL; +static char *opt_srv_keypass = NULL; + +static char *opt_srv_trusted = NULL; +static char *opt_srv_untrusted = NULL; +static char *opt_rsp_cert = NULL; +static char *opt_rsp_extracerts = NULL; +static char *opt_rsp_capubs = NULL; +static int opt_poll_count = 0; +static int opt_check_after = 1; +static int opt_grant_implicitconf = 0; + +static int opt_pkistatus = OSSL_CMP_PKISTATUS_accepted; +static int opt_failure = INT_MIN; +static int opt_failurebits = 0; +static char *opt_statusstring = NULL; +static int opt_send_error = 0; +static int opt_send_unprotected = 0; +static int opt_send_unprot_err = 0; +static int opt_accept_unprotected = 0; +static int opt_accept_unprot_err = 0; +static int opt_accept_raverified = 0; + +static X509_VERIFY_PARAM *vpm = NULL; + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY, + + OPT_CMD, OPT_INFOTYPE, OPT_GENINFO, + + OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_ISSUER, + OPT_DAYS, OPT_REQEXTS, + OPT_SANS, OPT_SAN_NODEFAULT, + OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL, + OPT_POPO, OPT_CSR, + OPT_OUT_TRUSTED, OPT_IMPLICIT_CONFIRM, OPT_DISABLE_CONFIRM, + OPT_CERTOUT, OPT_CHAINOUT, + + OPT_OLDCERT, OPT_REVREASON, + +#ifndef OPENSSL_NO_SOCK + OPT_SERVER, OPT_PROXY, OPT_NO_PROXY, +#endif + OPT_RECIPIENT, OPT_PATH, + OPT_KEEP_ALIVE, OPT_MSG_TIMEOUT, OPT_TOTAL_TIMEOUT, + + OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT, + OPT_EXPECT_SENDER, + OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, + OPT_EXTRACERTSOUT, OPT_CACERTSOUT, + + OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS, + OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS, + OPT_UNPROTECTED_REQUESTS, + + OPT_CERTFORM, OPT_KEYFORM, + OPT_OTHERPASS, +#ifndef OPENSSL_NO_ENGINE + OPT_ENGINE, +#endif + OPT_PROV_ENUM, + OPT_R_ENUM, + +#ifndef OPENSSL_NO_SOCK + OPT_TLS_USED, OPT_TLS_CERT, OPT_TLS_KEY, + OPT_TLS_KEYPASS, + OPT_TLS_EXTRA, OPT_TLS_TRUSTED, OPT_TLS_HOST, +#endif + + OPT_BATCH, OPT_REPEAT, + OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT, + OPT_USE_MOCK_SRV, + +#ifndef OPENSSL_NO_SOCK + OPT_PORT, OPT_MAX_MSGS, +#endif + OPT_SRV_REF, OPT_SRV_SECRET, + OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS, + OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED, + OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS, + OPT_POLL_COUNT, OPT_CHECK_AFTER, + OPT_GRANT_IMPLICITCONF, + OPT_PKISTATUS, OPT_FAILURE, + OPT_FAILUREBITS, OPT_STATUSSTRING, + OPT_SEND_ERROR, OPT_SEND_UNPROTECTED, + OPT_SEND_UNPROT_ERR, OPT_ACCEPT_UNPROTECTED, + OPT_ACCEPT_UNPROT_ERR, OPT_ACCEPT_RAVERIFIED, + + OPT_V_ENUM +} OPTION_CHOICE; + +const OPTIONS cmp_options[] = { + /* entries must be in the same order as enumerated above!! */ + {"help", OPT_HELP, '-', "Display this summary"}, + {"config", OPT_CONFIG, 's', + "Configuration file to use. \"\" = none. Default from env variable OPENSSL_CONF"}, + {"section", OPT_SECTION, 's', + "Section(s) in config file to get options from. \"\" = 'default'. Default 'cmp'"}, + {"verbosity", OPT_VERBOSITY, 'N', + "Log level; 3=ERR, 4=WARN, 6=INFO, 7=DEBUG, 8=TRACE. Default 6 = INFO"}, + + OPT_SECTION("Generic message"), + {"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"}, + {"infotype", OPT_INFOTYPE, 's', + "InfoType name for requesting specific info in genm, e.g. 'signKeyPairTypes'"}, + {"geninfo", OPT_GENINFO, 's', + "generalInfo integer values to place in request PKIHeader with given OID"}, + {OPT_MORE_STR, 0, 0, + "specified in the form :int:, e.g. \"1.2.3.4:int:56789\""}, + + OPT_SECTION("Certificate enrollment"), + {"newkey", OPT_NEWKEY, 's', + "Private or public key for the requested cert. Default: CSR key or client key"}, + {"newkeypass", OPT_NEWKEYPASS, 's', "New private key pass phrase source"}, + {"subject", OPT_SUBJECT, 's', + "Distinguished Name (DN) of subject to use in the requested cert template"}, + {OPT_MORE_STR, 0, 0, + "For kur, default is subject of -csr arg or reference cert (see -oldcert)"}, + {OPT_MORE_STR, 0, 0, + "this default is used for ir and cr only if no Subject Alt Names are set"}, + {"issuer", OPT_ISSUER, 's', + "DN of the issuer to place in the requested certificate template"}, + {OPT_MORE_STR, 0, 0, + "also used as recipient if neither -recipient nor -srvcert are given"}, + {"days", OPT_DAYS, 'N', + "Requested validity time of the new certificate in number of days"}, + {"reqexts", OPT_REQEXTS, 's', + "Name of config file section defining certificate request extensions."}, + {OPT_MORE_STR, 0, 0, + "Augments or replaces any extensions contained CSR given with -csr"}, + {"sans", OPT_SANS, 's', + "Subject Alt Names (IPADDR/DNS/URI) to add as (critical) cert req extension"}, + {"san_nodefault", OPT_SAN_NODEFAULT, '-', + "Do not take default SANs from reference certificate (see -oldcert)"}, + {"policies", OPT_POLICIES, 's', + "Name of config file section defining policies certificate request extension"}, + {"policy_oids", OPT_POLICY_OIDS, 's', + "Policy OID(s) to add as policies certificate request extension"}, + {"policy_oids_critical", OPT_POLICY_OIDS_CRITICAL, '-', + "Flag the policy OID(s) given with -policy_oids as critical"}, + {"popo", OPT_POPO, 'n', + "Proof-of-Possession (POPO) method to use for ir/cr/kur where"}, + {OPT_MORE_STR, 0, 0, + "-1 = NONE, 0 = RAVERIFIED, 1 = SIGNATURE (default), 2 = KEYENC"}, + {"csr", OPT_CSR, 's', + "PKCS#10 CSR file in PEM or DER format to convert or to use in p10cr"}, + {"out_trusted", OPT_OUT_TRUSTED, 's', + "Certificates to trust when verifying newly enrolled certificates"}, + {"implicit_confirm", OPT_IMPLICIT_CONFIRM, '-', + "Request implicit confirmation of newly enrolled certificates"}, + {"disable_confirm", OPT_DISABLE_CONFIRM, '-', + "Do not confirm newly enrolled certificate w/o requesting implicit"}, + {OPT_MORE_STR, 0, 0, + "confirmation. WARNING: This leads to behavior violating RFC 4210"}, + {"certout", OPT_CERTOUT, 's', + "File to save newly enrolled certificate"}, + {"chainout", OPT_CHAINOUT, 's', + "File to save the chain of newly enrolled certificate"}, + + OPT_SECTION("Certificate enrollment and revocation"), + + {"oldcert", OPT_OLDCERT, 's', + "Certificate to be updated (defaulting to -cert) or to be revoked in rr;"}, + {OPT_MORE_STR, 0, 0, + "also used as reference (defaulting to -cert) for subject DN and SANs."}, + {OPT_MORE_STR, 0, 0, + "Issuer is used as recipient unless -recipient, -srvcert, or -issuer given"}, + {"revreason", OPT_REVREASON, 'n', + "Reason code to include in revocation request (rr); possible values:"}, + {OPT_MORE_STR, 0, 0, + "0..6, 8..10 (see RFC5280, 5.3.1) or -1. Default -1 = none included"}, + + OPT_SECTION("Message transfer"), +#ifdef OPENSSL_NO_SOCK + {OPT_MORE_STR, 0, 0, + "NOTE: -server, -proxy, and -no_proxy not supported due to no-sock build"}, +#else + {"server", OPT_SERVER, 's', + "[http[s]://]address[:port][/path] of CMP server. Default port 80 or 443."}, + {OPT_MORE_STR, 0, 0, + "address may be a DNS name or an IP address; path can be overridden by -path"}, + {"proxy", OPT_PROXY, 's', + "[http[s]://]address[:port][/path] of HTTP(S) proxy to use; path is ignored"}, + {"no_proxy", OPT_NO_PROXY, 's', + "List of addresses of servers not to use HTTP(S) proxy for"}, + {OPT_MORE_STR, 0, 0, + "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"}, +#endif + {"recipient", OPT_RECIPIENT, 's', + "DN of CA. Default: subject of -srvcert, -issuer, issuer of -oldcert or -cert"}, + {"path", OPT_PATH, 's', + "HTTP path (aka CMP alias) at the CMP server. Default from -server, else \"/\""}, + {"keep_alive", OPT_KEEP_ALIVE, 'N', + "Persistent HTTP connections. 0: no, 1 (the default): request, 2: require"}, + {"msg_timeout", OPT_MSG_TIMEOUT, 'N', + "Number of seconds allowed per CMP message round trip, or 0 for infinite"}, + {"total_timeout", OPT_TOTAL_TIMEOUT, 'N', + "Overall time an enrollment incl. polling may take. Default 0 = infinite"}, + + OPT_SECTION("Server authentication"), + {"trusted", OPT_TRUSTED, 's', + "Certificates to trust as chain roots when verifying signed CMP responses"}, + {OPT_MORE_STR, 0, 0, "unless -srvcert is given"}, + {"untrusted", OPT_UNTRUSTED, 's', + "Intermediate CA certs for chain construction for CMP/TLS/enrolled certs"}, + {"srvcert", OPT_SRVCERT, 's', + "Server cert to pin and trust directly when verifying signed CMP responses"}, + {"expect_sender", OPT_EXPECT_SENDER, 's', + "DN of expected sender of responses. Defaults to subject of -srvcert, if any"}, + {"ignore_keyusage", OPT_IGNORE_KEYUSAGE, '-', + "Ignore CMP signer cert key usage, else 'digitalSignature' must be allowed"}, + {"unprotected_errors", OPT_UNPROTECTED_ERRORS, '-', + "Accept missing or invalid protection of regular error messages and negative"}, + {OPT_MORE_STR, 0, 0, + "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"}, + {OPT_MORE_STR, 0, 0, + "WARNING: This setting leads to behavior allowing violation of RFC 4210"}, + {"extracertsout", OPT_EXTRACERTSOUT, 's', + "File to save extra certificates received in the extraCerts field"}, + {"cacertsout", OPT_CACERTSOUT, 's', + "File to save CA certificates received in the caPubs field of 'ip' messages"}, + + OPT_SECTION("Client authentication"), + {"ref", OPT_REF, 's', + "Reference value to use as senderKID in case no -cert is given"}, + {"secret", OPT_SECRET, 's', + "Prefer PBM (over signatures) for protecting msgs with given password source"}, + {"cert", OPT_CERT, 's', + "Client's CMP signer certificate; its public key must match the -key argument"}, + {OPT_MORE_STR, 0, 0, + "This also used as default reference for subject DN and SANs."}, + {OPT_MORE_STR, 0, 0, + "Any further certs included are appended to the untrusted certs"}, + {"own_trusted", OPT_OWN_TRUSTED, 's', + "Optional certs to verify chain building for own CMP signer cert"}, + {"key", OPT_KEY, 's', "CMP signer private key, not used when -secret given"}, + {"keypass", OPT_KEYPASS, 's', + "Client private key (and cert and old cert) pass phrase source"}, + {"digest", OPT_DIGEST, 's', + "Digest to use in message protection and POPO signatures. Default \"sha256\""}, + {"mac", OPT_MAC, 's', + "MAC algorithm to use in PBM-based message protection. Default \"hmac-sha1\""}, + {"extracerts", OPT_EXTRACERTS, 's', + "Certificates to append in extraCerts field of outgoing messages."}, + {OPT_MORE_STR, 0, 0, + "This can be used as the default CMP signer cert chain to include"}, + {"unprotected_requests", OPT_UNPROTECTED_REQUESTS, '-', + "Send messages without CMP-level protection"}, + + OPT_SECTION("Credentials format"), + {"certform", OPT_CERTFORM, 's', + "Format (PEM or DER) to use when saving a certificate to a file. Default PEM"}, + {"keyform", OPT_KEYFORM, 's', + "Format of the key input (ENGINE, other values ignored)"}, + {"otherpass", OPT_OTHERPASS, 's', + "Pass phrase source potentially needed for loading certificates of others"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', + "Use crypto engine with given identifier, possibly a hardware device."}, + {OPT_MORE_STR, 0, 0, + "Engines may also be defined in OpenSSL config file engine section."}, +#endif + OPT_PROV_OPTIONS, + OPT_R_OPTIONS, + + OPT_SECTION("TLS connection"), +#ifdef OPENSSL_NO_SOCK + {OPT_MORE_STR, 0, 0, + "NOTE: -tls_used and all other TLS options not supported due to no-sock build"}, +#else + {"tls_used", OPT_TLS_USED, '-', + "Enable using TLS (also when other TLS options are not set)"}, + {"tls_cert", OPT_TLS_CERT, 's', + "Client's TLS certificate. May include chain to be provided to TLS server"}, + {"tls_key", OPT_TLS_KEY, 's', + "Private key for the client's TLS certificate"}, + {"tls_keypass", OPT_TLS_KEYPASS, 's', + "Pass phrase source for the client's private TLS key (and TLS cert)"}, + {"tls_extra", OPT_TLS_EXTRA, 's', + "Extra certificates to provide to TLS server during TLS handshake"}, + {"tls_trusted", OPT_TLS_TRUSTED, 's', + "Trusted certificates to use for verifying the TLS server certificate;"}, + {OPT_MORE_STR, 0, 0, "this implies host name validation"}, + {"tls_host", OPT_TLS_HOST, 's', + "Address to be checked (rather than -server) during TLS host name validation"}, +#endif + + OPT_SECTION("Client-side debugging"), + {"batch", OPT_BATCH, '-', + "Do not interactively prompt for input when a password is required etc."}, + {"repeat", OPT_REPEAT, 'p', + "Invoke the transaction the given positive number of times. Default 1"}, + {"reqin", OPT_REQIN, 's', "Take sequence of CMP requests from file(s)"}, + {"reqin_new_tid", OPT_REQIN_NEW_TID, '-', + "Use fresh transactionID for CMP requests read from -reqin"}, + {"reqout", OPT_REQOUT, 's', "Save sequence of CMP requests to file(s)"}, + {"rspin", OPT_RSPIN, 's', + "Process sequence of CMP responses provided in file(s), skipping server"}, + {"rspout", OPT_RSPOUT, 's', "Save sequence of CMP responses to file(s)"}, + + {"use_mock_srv", OPT_USE_MOCK_SRV, '-', + "Use internal mock server at API level, bypassing socket-based HTTP"}, + + OPT_SECTION("Mock server"), +#ifdef OPENSSL_NO_SOCK + {OPT_MORE_STR, 0, 0, + "NOTE: -port and -max_msgs not supported due to no-sock build"}, +#else + {"port", OPT_PORT, 's', + "Act as HTTP-based mock server listening on given port"}, + {"max_msgs", OPT_MAX_MSGS, 'N', + "max number of messages handled by HTTP mock server. Default: 0 = unlimited"}, +#endif + + {"srv_ref", OPT_SRV_REF, 's', + "Reference value to use as senderKID of server in case no -srv_cert is given"}, + {"srv_secret", OPT_SRV_SECRET, 's', + "Password source for server authentication with a pre-shared key (secret)"}, + {"srv_cert", OPT_SRV_CERT, 's', "Certificate of the server"}, + {"srv_key", OPT_SRV_KEY, 's', + "Private key used by the server for signing messages"}, + {"srv_keypass", OPT_SRV_KEYPASS, 's', + "Server private key (and cert) pass phrase source"}, + + {"srv_trusted", OPT_SRV_TRUSTED, 's', + "Trusted certificates for client authentication"}, + {"srv_untrusted", OPT_SRV_UNTRUSTED, 's', + "Intermediate certs that may be useful for verifying CMP protection"}, + {"rsp_cert", OPT_RSP_CERT, 's', + "Certificate to be returned as mock enrollment result"}, + {"rsp_extracerts", OPT_RSP_EXTRACERTS, 's', + "Extra certificates to be included in mock certification responses"}, + {"rsp_capubs", OPT_RSP_CAPUBS, 's', + "CA certificates to be included in mock ip response"}, + {"poll_count", OPT_POLL_COUNT, 'N', + "Number of times the client must poll before receiving a certificate"}, + {"check_after", OPT_CHECK_AFTER, 'N', + "The check_after value (time to wait) to include in poll response"}, + {"grant_implicitconf", OPT_GRANT_IMPLICITCONF, '-', + "Grant implicit confirmation of newly enrolled certificate"}, + + {"pkistatus", OPT_PKISTATUS, 'N', + "PKIStatus to be included in server response. Possible values: 0..6"}, + {"failure", OPT_FAILURE, 'N', + "A single failure info bit number to include in server response, 0..26"}, + {"failurebits", OPT_FAILUREBITS, 'N', + "Number representing failure bits to include in server response, 0..2^27 - 1"}, + {"statusstring", OPT_STATUSSTRING, 's', + "Status string to be included in server response"}, + {"send_error", OPT_SEND_ERROR, '-', + "Force server to reply with error message"}, + {"send_unprotected", OPT_SEND_UNPROTECTED, '-', + "Send response messages without CMP-level protection"}, + {"send_unprot_err", OPT_SEND_UNPROT_ERR, '-', + "In case of negative responses, server shall send unprotected error messages,"}, + {OPT_MORE_STR, 0, 0, + "certificate responses (ip/cp/kup), and revocation responses (rp)."}, + {OPT_MORE_STR, 0, 0, + "WARNING: This setting leads to behavior violating RFC 4210"}, + {"accept_unprotected", OPT_ACCEPT_UNPROTECTED, '-', + "Accept missing or invalid protection of requests"}, + {"accept_unprot_err", OPT_ACCEPT_UNPROT_ERR, '-', + "Accept unprotected error messages from client"}, + {"accept_raverified", OPT_ACCEPT_RAVERIFIED, '-', + "Accept RAVERIFIED as proof-of-possession (POPO)"}, + + OPT_V_OPTIONS, + {NULL} +}; + +typedef union { + char **txt; + int *num; + long *num_long; +} varref; +static varref cmp_vars[] = { /* must be in same order as enumerated above! */ + {&opt_config}, {&opt_section}, {(char **)&opt_verbosity}, + + {&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo}, + + {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {&opt_issuer}, + {(char **)&opt_days}, {&opt_reqexts}, + {&opt_sans}, {(char **)&opt_san_nodefault}, + {&opt_policies}, {&opt_policy_oids}, {(char **)&opt_policy_oids_critical}, + {(char **)&opt_popo}, {&opt_csr}, + {&opt_out_trusted}, + {(char **)&opt_implicit_confirm}, {(char **)&opt_disable_confirm}, + {&opt_certout}, {&opt_chainout}, + + {&opt_oldcert}, {(char **)&opt_revreason}, + +#ifndef OPENSSL_NO_SOCK + {&opt_server}, {&opt_proxy}, {&opt_no_proxy}, +#endif + {&opt_recipient}, {&opt_path}, {(char **)&opt_keep_alive}, + {(char **)&opt_msg_timeout}, {(char **)&opt_total_timeout}, + + {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert}, + {&opt_expect_sender}, + {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors}, + {&opt_extracertsout}, {&opt_cacertsout}, + + {&opt_ref}, {&opt_secret}, + {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass}, + {&opt_digest}, {&opt_mac}, {&opt_extracerts}, + {(char **)&opt_unprotected_requests}, + + {&opt_certform_s}, {&opt_keyform_s}, + {&opt_otherpass}, +#ifndef OPENSSL_NO_ENGINE + {&opt_engine}, +#endif + +#ifndef OPENSSL_NO_SOCK + {(char **)&opt_tls_used}, {&opt_tls_cert}, {&opt_tls_key}, + {&opt_tls_keypass}, + {&opt_tls_extra}, {&opt_tls_trusted}, {&opt_tls_host}, +#endif + + {(char **)&opt_batch}, {(char **)&opt_repeat}, + {&opt_reqin}, {(char **)&opt_reqin_new_tid}, + {&opt_reqout}, {&opt_rspin}, {&opt_rspout}, + + {(char **)&opt_use_mock_srv}, +#ifndef OPENSSL_NO_SOCK + {&opt_port}, {(char **)&opt_max_msgs}, +#endif + {&opt_srv_ref}, {&opt_srv_secret}, + {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass}, + {&opt_srv_trusted}, {&opt_srv_untrusted}, + {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs}, + {(char **)&opt_poll_count}, {(char **)&opt_check_after}, + {(char **)&opt_grant_implicitconf}, + {(char **)&opt_pkistatus}, {(char **)&opt_failure}, + {(char **)&opt_failurebits}, {&opt_statusstring}, + {(char **)&opt_send_error}, {(char **)&opt_send_unprotected}, + {(char **)&opt_send_unprot_err}, {(char **)&opt_accept_unprotected}, + {(char **)&opt_accept_unprot_err}, {(char **)&opt_accept_raverified}, + + {NULL} +}; + +#define FUNC (strcmp(OPENSSL_FUNC, "(unknown function)") == 0 \ + ? "CMP" : OPENSSL_FUNC) +#define CMP_print(bio, level, prefix, msg, a1, a2, a3) \ + ((void)(level > opt_verbosity ? 0 : \ + (BIO_printf(bio, "%s:%s:%d:CMP %s: " msg "\n", \ + FUNC, OPENSSL_FILE, OPENSSL_LINE, prefix, a1, a2, a3)))) +#define CMP_DEBUG(m, a1, a2, a3) \ + CMP_print(bio_out, OSSL_CMP_LOG_DEBUG, "debug", m, a1, a2, a3) +#define CMP_debug(msg) CMP_DEBUG(msg"%s%s%s", "", "", "") +#define CMP_debug1(msg, a1) CMP_DEBUG(msg"%s%s", a1, "", "") +#define CMP_debug2(msg, a1, a2) CMP_DEBUG(msg"%s", a1, a2, "") +#define CMP_debug3(msg, a1, a2, a3) CMP_DEBUG(msg, a1, a2, a3) +#define CMP_INFO(msg, a1, a2, a3) \ + CMP_print(bio_out, OSSL_CMP_LOG_INFO, "info", msg, a1, a2, a3) +#define CMP_info(msg) CMP_INFO(msg"%s%s%s", "", "", "") +#define CMP_info1(msg, a1) CMP_INFO(msg"%s%s", a1, "", "") +#define CMP_info2(msg, a1, a2) CMP_INFO(msg"%s", a1, a2, "") +#define CMP_info3(msg, a1, a2, a3) CMP_INFO(msg, a1, a2, a3) +#define CMP_WARN(m, a1, a2, a3) \ + CMP_print(bio_out, OSSL_CMP_LOG_WARNING, "warning", m, a1, a2, a3) +#define CMP_warn(msg) CMP_WARN(msg"%s%s%s", "", "", "") +#define CMP_warn1(msg, a1) CMP_WARN(msg"%s%s", a1, "", "") +#define CMP_warn2(msg, a1, a2) CMP_WARN(msg"%s", a1, a2, "") +#define CMP_warn3(msg, a1, a2, a3) CMP_WARN(msg, a1, a2, a3) +#define CMP_ERR(msg, a1, a2, a3) \ + CMP_print(bio_err, OSSL_CMP_LOG_ERR, "error", msg, a1, a2, a3) +#define CMP_err(msg) CMP_ERR(msg"%s%s%s", "", "", "") +#define CMP_err1(msg, a1) CMP_ERR(msg"%s%s", a1, "", "") +#define CMP_err2(msg, a1, a2) CMP_ERR(msg"%s", a1, a2, "") +#define CMP_err3(msg, a1, a2, a3) CMP_ERR(msg, a1, a2, a3) + +static int print_to_bio_out(const char *func, const char *file, int line, + OSSL_CMP_severity level, const char *msg) +{ + return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg); +} + +static int print_to_bio_err(const char *func, const char *file, int line, + OSSL_CMP_severity level, const char *msg) +{ + return OSSL_CMP_print_to_bio(bio_err, func, file, line, level, msg); +} + +static int set_verbosity(int level) +{ + if (level < OSSL_CMP_LOG_EMERG || level > OSSL_CMP_LOG_MAX) { + CMP_err1("Logging verbosity level %d out of range (0 .. 8)", level); + return 0; + } + opt_verbosity = level; + return 1; +} + +static EVP_PKEY *load_key_pwd(const char *uri, int format, + const char *pass, ENGINE *eng, const char *desc) +{ + char *pass_string = get_passwd(pass, desc); + EVP_PKEY *pkey = load_key(uri, format, 0, pass_string, eng, desc); + + clear_free(pass_string); + return pkey; +} + +static X509 *load_cert_pwd(const char *uri, const char *pass, const char *desc) +{ + X509 *cert; + char *pass_string = get_passwd(pass, desc); + + cert = load_cert_pass(uri, FORMAT_UNDEF, 0, pass_string, desc); + clear_free(pass_string); + return cert; +} + +static X509_REQ *load_csr_autofmt(const char *infile, const char *desc) +{ + X509_REQ *csr; + BIO *bio_bak = bio_err; + + bio_err = NULL; /* do not show errors on more than one try */ + csr = load_csr(infile, FORMAT_PEM, desc); + bio_err = bio_bak; + if (csr == NULL) { + ERR_clear_error(); + csr = load_csr(infile, FORMAT_ASN1, desc); + } + if (csr == NULL) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "error: unable to load %s from file '%s'\n", desc, + infile); + } else { + EVP_PKEY *pkey = X509_REQ_get0_pubkey(csr); + int ret = do_X509_REQ_verify(csr, pkey, NULL /* vfyopts */); + + if (pkey == NULL || ret < 0) + CMP_warn("error while verifying CSR self-signature"); + else if (ret == 0) + CMP_warn("CSR self-signature does not match the contents"); + } + return csr; +} + +/* set expected host name/IP addr and clears the email addr in the given ts */ +static int truststore_set_host_etc(X509_STORE *ts, const char *host) +{ + X509_VERIFY_PARAM *ts_vpm = X509_STORE_get0_param(ts); + + /* first clear any host names, IP, and email addresses */ + if (!X509_VERIFY_PARAM_set1_host(ts_vpm, NULL, 0) + || !X509_VERIFY_PARAM_set1_ip(ts_vpm, NULL, 0) + || !X509_VERIFY_PARAM_set1_email(ts_vpm, NULL, 0)) + return 0; + X509_VERIFY_PARAM_set_hostflags(ts_vpm, + X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT | + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + return (host != NULL && X509_VERIFY_PARAM_set1_ip_asc(ts_vpm, host)) + || X509_VERIFY_PARAM_set1_host(ts_vpm, host, 0); +} + +/* write OSSL_CMP_MSG DER-encoded to the specified file name item */ +static int write_PKIMESSAGE(const OSSL_CMP_MSG *msg, char **filenames) +{ + char *file; + + if (msg == NULL || filenames == NULL) { + CMP_err("NULL arg to write_PKIMESSAGE"); + return 0; + } + if (*filenames == NULL) { + CMP_err("not enough file names provided for writing PKIMessage"); + return 0; + } + + file = *filenames; + *filenames = next_item(file); + if (OSSL_CMP_MSG_write(file, msg) < 0) { + CMP_err1("cannot write PKIMessage to file '%s'", file); + return 0; + } + return 1; +} + +/* read DER-encoded OSSL_CMP_MSG from the specified file name item */ +static OSSL_CMP_MSG *read_PKIMESSAGE(char **filenames) +{ + char *file; + OSSL_CMP_MSG *ret; + + if (filenames == NULL) { + CMP_err("NULL arg to read_PKIMESSAGE"); + return NULL; + } + if (*filenames == NULL) { + CMP_err("not enough file names provided for reading PKIMessage"); + return NULL; + } + + file = *filenames; + *filenames = next_item(file); + + ret = OSSL_CMP_MSG_read(file, app_get0_libctx(), app_get0_propq()); + if (ret == NULL) + CMP_err1("cannot read PKIMessage from file '%s'", file); + return ret; +} + +/*- + * Sends the PKIMessage req and on success place the response in *res + * basically like OSSL_CMP_MSG_http_perform(), but in addition allows + * to dump the sequence of requests and responses to files and/or + * to take the sequence of requests and responses from files. + */ +static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_MSG *req_new = NULL; + OSSL_CMP_MSG *res = NULL; + OSSL_CMP_PKIHEADER *hdr; + const char *prev_opt_rspin = opt_rspin; + + if (req != NULL && opt_reqout != NULL + && !write_PKIMESSAGE(req, &opt_reqout)) + goto err; + if (opt_reqin != NULL && opt_rspin == NULL) { + if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL) + goto err; + /*- + * The transaction ID in req_new read from opt_reqin may not be fresh. + * In this case the server may complain "Transaction id already in use." + * The following workaround unfortunately requires re-protection. + */ + if (opt_reqin_new_tid + && !OSSL_CMP_MSG_update_transactionID(ctx, req_new)) + goto err; + } + + if (opt_rspin != NULL) { + res = read_PKIMESSAGE(&opt_rspin); + } else { + const OSSL_CMP_MSG *actual_req = opt_reqin != NULL ? req_new : req; + + res = opt_use_mock_srv + ? OSSL_CMP_CTX_server_perform(ctx, actual_req) + : OSSL_CMP_MSG_http_perform(ctx, actual_req); + } + if (res == NULL) + goto err; + + if (opt_reqin != NULL || prev_opt_rspin != NULL) { + /* need to satisfy nonce and transactionID checks */ + ASN1_OCTET_STRING *nonce; + ASN1_OCTET_STRING *tid; + + hdr = OSSL_CMP_MSG_get0_header(res); + nonce = OSSL_CMP_HDR_get0_recipNonce(hdr); + tid = OSSL_CMP_HDR_get0_transactionID(hdr); + if (!OSSL_CMP_CTX_set1_senderNonce(ctx, nonce) + || !OSSL_CMP_CTX_set1_transactionID(ctx, tid)) { + OSSL_CMP_MSG_free(res); + res = NULL; + goto err; + } + } + + if (opt_rspout != NULL && !write_PKIMESSAGE(res, &opt_rspout)) { + OSSL_CMP_MSG_free(res); + res = NULL; + } + + err: + OSSL_CMP_MSG_free(req_new); + return res; +} + +static int set_name(const char *str, + int (*set_fn) (OSSL_CMP_CTX *ctx, const X509_NAME *name), + OSSL_CMP_CTX *ctx, const char *desc) +{ + if (str != NULL) { + X509_NAME *n = parse_name(str, MBSTRING_ASC, 1, desc); + + if (n == NULL) + return 0; + if (!(*set_fn) (ctx, n)) { + X509_NAME_free(n); + CMP_err("out of memory"); + return 0; + } + X509_NAME_free(n); + } + return 1; +} + +static int set_gennames(OSSL_CMP_CTX *ctx, char *names, const char *desc) +{ + char *next; + + for (; names != NULL; names = next) { + GENERAL_NAME *n; + + next = next_item(names); + if (strcmp(names, "critical") == 0) { + (void)OSSL_CMP_CTX_set_option(ctx, + OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL, + 1); + continue; + } + + /* try IP address first, then URI or domain name */ + (void)ERR_set_mark(); + n = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_IPADD, names, 0); + if (n == NULL) + n = a2i_GENERAL_NAME(NULL, NULL, NULL, + strchr(names, ':') != NULL ? GEN_URI : GEN_DNS, + names, 0); + (void)ERR_pop_to_mark(); + + if (n == NULL) { + CMP_err2("bad syntax of %s '%s'", desc, names); + return 0; + } + if (!OSSL_CMP_CTX_push1_subjectAltName(ctx, n)) { + GENERAL_NAME_free(n); + CMP_err("out of memory"); + return 0; + } + GENERAL_NAME_free(n); + } + return 1; +} + +static X509_STORE *load_trusted(char *input, int for_new_cert, const char *desc) +{ + X509_STORE *ts = load_certstore(input, opt_otherpass, desc, vpm); + + if (ts == NULL) + return NULL; + X509_STORE_set_verify_cb(ts, X509_STORE_CTX_print_verify_cb); + + /* copy vpm to store */ + if (X509_STORE_set1_param(ts, vpm /* may be NULL */) + && (for_new_cert || truststore_set_host_etc(ts, NULL))) + return ts; + BIO_printf(bio_err, "error setting verification parameters for %s\n", desc); + OSSL_CMP_CTX_print_errors(cmp_ctx); + X509_STORE_free(ts); + return NULL; +} + +typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs); + +static int setup_certs(char *files, const char *desc, void *ctx, + add_X509_stack_fn_t set1_fn) +{ + STACK_OF(X509) *certs; + int ok; + + if (files == NULL) + return 1; + if ((certs = load_certs_multifile(files, opt_otherpass, desc, vpm)) == NULL) + return 0; + ok = (*set1_fn)(ctx, certs); + sk_X509_pop_free(certs, X509_free); + return ok; +} + + +/* + * parse and transform some options, checking their syntax. + * Returns 1 on success, 0 on error + */ +static int transform_opts(void) +{ + if (opt_cmd_s != NULL) { + if (!strcmp(opt_cmd_s, "ir")) { + opt_cmd = CMP_IR; + } else if (!strcmp(opt_cmd_s, "kur")) { + opt_cmd = CMP_KUR; + } else if (!strcmp(opt_cmd_s, "cr")) { + opt_cmd = CMP_CR; + } else if (!strcmp(opt_cmd_s, "p10cr")) { + opt_cmd = CMP_P10CR; + } else if (!strcmp(opt_cmd_s, "rr")) { + opt_cmd = CMP_RR; + } else if (!strcmp(opt_cmd_s, "genm")) { + opt_cmd = CMP_GENM; + } else { + CMP_err1("unknown cmp command '%s'", opt_cmd_s); + return 0; + } + } else { + CMP_err("no cmp command to execute"); + return 0; + } + +#ifndef OPENSSL_NO_ENGINE +# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_ENGINE) +#else +# define FORMAT_OPTIONS (OPT_FMT_PEMDER | OPT_FMT_PKCS12) +#endif + + if (opt_keyform_s != NULL + && !opt_format(opt_keyform_s, FORMAT_OPTIONS, &opt_keyform)) { + CMP_err("unknown option given for key loading format"); + return 0; + } + +#undef FORMAT_OPTIONS + + if (opt_certform_s != NULL + && !opt_format(opt_certform_s, OPT_FMT_PEMDER, &opt_certform)) { + CMP_err("unknown option given for certificate storing format"); + return 0; + } + + return 1; +} + +static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine) +{ + OSSL_CMP_CTX *ctx; /* extra CMP (client) ctx partly used by server */ + OSSL_CMP_SRV_CTX *srv_ctx = ossl_cmp_mock_srv_new(app_get0_libctx(), + app_get0_propq()); + + if (srv_ctx == NULL) + return NULL; + ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx); + + if (opt_srv_ref == NULL) { + if (opt_srv_cert == NULL) { + /* opt_srv_cert should determine the sender */ + CMP_err("must give -srv_ref for mock server if no -srv_cert given"); + goto err; + } + } else { + if (!OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_srv_ref, + strlen(opt_srv_ref))) + goto err; + } + + if (opt_srv_secret != NULL) { + int res; + char *pass_str = get_passwd(opt_srv_secret, "PBMAC secret of mock server"); + + if (pass_str != NULL) { + cleanse(opt_srv_secret); + res = OSSL_CMP_CTX_set1_secretValue(ctx, (unsigned char *)pass_str, + strlen(pass_str)); + clear_free(pass_str); + if (res == 0) + goto err; + } + } else if (opt_srv_cert == NULL) { + CMP_err("mock server credentials must be given if -use_mock_srv or -port is used"); + goto err; + } else { + CMP_warn("mock server will not be able to handle PBM-protected requests since -srv_secret is not given"); + } + + if (opt_srv_secret == NULL + && ((opt_srv_cert == NULL) != (opt_srv_key == NULL))) { + CMP_err("must give both -srv_cert and -srv_key options or neither"); + goto err; + } + if (opt_srv_cert != NULL) { + X509 *srv_cert = load_cert_pwd(opt_srv_cert, opt_srv_keypass, + "certificate of the mock server"); + + if (srv_cert == NULL || !OSSL_CMP_CTX_set1_cert(ctx, srv_cert)) { + X509_free(srv_cert); + goto err; + } + X509_free(srv_cert); + } + if (opt_srv_key != NULL) { + EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform, + opt_srv_keypass, + engine, "private key for mock server cert"); + + if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) { + EVP_PKEY_free(pkey); + goto err; + } + EVP_PKEY_free(pkey); + } + cleanse(opt_srv_keypass); + + if (opt_srv_trusted != NULL) { + X509_STORE *ts = + load_trusted(opt_srv_trusted, 0, "certs trusted by mock server"); + + if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) { + X509_STORE_free(ts); + goto err; + } + } else { + CMP_warn("mock server will not be able to handle signature-protected requests since -srv_trusted is not given"); + } + if (!setup_certs(opt_srv_untrusted, + "untrusted certificates for mock server", ctx, + (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted)) + goto err; + + if (opt_rsp_cert == NULL) { + CMP_warn("no -rsp_cert given for mock server"); + } else { + X509 *cert = load_cert_pwd(opt_rsp_cert, opt_keypass, + "cert to be returned by the mock server"); + + if (cert == NULL) + goto err; + /* from server perspective the server is the client */ + if (!ossl_cmp_mock_srv_set1_certOut(srv_ctx, cert)) { + X509_free(cert); + goto err; + } + X509_free(cert); + } + if (!setup_certs(opt_rsp_extracerts, + "CMP extra certificates for mock server", srv_ctx, + (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut)) + goto err; + if (!setup_certs(opt_rsp_capubs, "caPubs for mock server", srv_ctx, + (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_caPubsOut)) + goto err; + (void)ossl_cmp_mock_srv_set_pollCount(srv_ctx, opt_poll_count); + (void)ossl_cmp_mock_srv_set_checkAfterTime(srv_ctx, opt_check_after); + if (opt_grant_implicitconf) + (void)OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(srv_ctx, 1); + + if (opt_failure != INT_MIN) { /* option has been set explicity */ + if (opt_failure < 0 || OSSL_CMP_PKIFAILUREINFO_MAX < opt_failure) { + CMP_err1("-failure out of range, should be >= 0 and <= %d", + OSSL_CMP_PKIFAILUREINFO_MAX); + goto err; + } + if (opt_failurebits != 0) + CMP_warn("-failurebits overrides -failure"); + else + opt_failurebits = 1 << opt_failure; + } + if ((unsigned)opt_failurebits > OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN) { + CMP_err("-failurebits out of range"); + goto err; + } + if (!ossl_cmp_mock_srv_set_statusInfo(srv_ctx, opt_pkistatus, + opt_failurebits, opt_statusstring)) + goto err; + + if (opt_send_error) + (void)ossl_cmp_mock_srv_set_send_error(srv_ctx, 1); + + if (opt_send_unprotected) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1); + if (opt_send_unprot_err) + (void)OSSL_CMP_SRV_CTX_set_send_unprotected_errors(srv_ctx, 1); + if (opt_accept_unprotected) + (void)OSSL_CMP_SRV_CTX_set_accept_unprotected(srv_ctx, 1); + if (opt_accept_unprot_err) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1); + if (opt_accept_raverified) + (void)OSSL_CMP_SRV_CTX_set_accept_raverified(srv_ctx, 1); + + return srv_ctx; + + err: + ossl_cmp_mock_srv_free(srv_ctx); + return NULL; +} + +/* + * set up verification aspects of OSSL_CMP_CTX w.r.t. opts from config file/CLI. + * Returns pointer on success, NULL on error + */ +static int setup_verification_ctx(OSSL_CMP_CTX *ctx) +{ + if (!setup_certs(opt_untrusted, "untrusted certificates", ctx, + (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted)) + return 0; + + if (opt_srvcert != NULL || opt_trusted != NULL) { + X509 *srvcert; + X509_STORE *ts; + int ok; + + if (opt_srvcert != NULL) { + if (opt_trusted != NULL) { + CMP_warn("-trusted option is ignored since -srvcert option is present"); + opt_trusted = NULL; + } + if (opt_recipient != NULL) { + CMP_warn("-recipient option is ignored since -srvcert option is present"); + opt_recipient = NULL; + } + srvcert = load_cert_pwd(opt_srvcert, opt_otherpass, + "directly trusted CMP server certificate"); + ok = srvcert != NULL && OSSL_CMP_CTX_set1_srvCert(ctx, srvcert); + X509_free(srvcert); + if (!ok) + return 0; + } + if (opt_trusted != NULL) { + /* + * the 0 arg below clears any expected host/ip/email address; + * opt_expect_sender is used instead + */ + ts = load_trusted(opt_trusted, 0, "certs trusted by client"); + + if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) { + X509_STORE_free(ts); + return 0; + } + } + } + + if (opt_ignore_keyusage) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1); + + if (opt_unprotected_errors) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1); + + if (opt_out_trusted != NULL) { /* for use in OSSL_CMP_certConf_cb() */ + X509_VERIFY_PARAM *out_vpm = NULL; + X509_STORE *out_trusted = + load_trusted(opt_out_trusted, 1, + "trusted certs for verifying newly enrolled cert"); + + if (out_trusted == NULL) + return 0; + /* ignore any -attime here, new certs are current anyway */ + out_vpm = X509_STORE_get0_param(out_trusted); + X509_VERIFY_PARAM_clear_flags(out_vpm, X509_V_FLAG_USE_CHECK_TIME); + + (void)OSSL_CMP_CTX_set_certConf_cb_arg(ctx, out_trusted); + } + + if (opt_disable_confirm) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DISABLE_CONFIRM, 1); + + if (opt_implicit_confirm) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, 1); + + return 1; +} + +#ifndef OPENSSL_NO_SOCK +/* + * set up ssl_ctx for the OSSL_CMP_CTX based on options from config file/CLI. + * Returns pointer on success, NULL on error + */ +static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host, + ENGINE *engine) +{ + STACK_OF(X509) *untrusted = OSSL_CMP_CTX_get0_untrusted(ctx); + EVP_PKEY *pkey = NULL; + X509_STORE *trust_store = NULL; + SSL_CTX *ssl_ctx; + int i; + + ssl_ctx = SSL_CTX_new(TLS_client_method()); + if (ssl_ctx == NULL) + return NULL; + + if (opt_tls_trusted != NULL) { + trust_store = load_trusted(opt_tls_trusted, 0, "trusted TLS certs"); + if (trust_store == NULL) + goto err; + SSL_CTX_set_cert_store(ssl_ctx, trust_store); + } + + if (opt_tls_cert != NULL && opt_tls_key != NULL) { + X509 *cert; + STACK_OF(X509) *certs = NULL; + int ok; + + if (!load_cert_certs(opt_tls_cert, &cert, &certs, 0, opt_tls_keypass, + "TLS client certificate (optionally with chain)", + vpm)) + /* need opt_tls_keypass if opt_tls_cert is encrypted PKCS#12 file */ + goto err; + + ok = SSL_CTX_use_certificate(ssl_ctx, cert) > 0; + X509_free(cert); + + /* + * Any further certs and any untrusted certs are used for constructing + * the chain to be provided with the TLS client cert to the TLS server. + */ + if (!ok || !SSL_CTX_set0_chain(ssl_ctx, certs)) { + CMP_err1("unable to use client TLS certificate file '%s'", + opt_tls_cert); + sk_X509_pop_free(certs, X509_free); + goto err; + } + for (i = 0; i < sk_X509_num(untrusted); i++) { + cert = sk_X509_value(untrusted, i); + if (!SSL_CTX_add1_chain_cert(ssl_ctx, cert)) { + CMP_err("could not add untrusted cert to TLS client cert chain"); + goto err; + } + } + + { + X509_VERIFY_PARAM *tls_vpm = NULL; + unsigned long bak_flags = 0; /* compiler warns without init */ + + if (trust_store != NULL) { + tls_vpm = X509_STORE_get0_param(trust_store); + bak_flags = X509_VERIFY_PARAM_get_flags(tls_vpm); + /* disable any cert status/revocation checking etc. */ + X509_VERIFY_PARAM_clear_flags(tls_vpm, + ~(X509_V_FLAG_USE_CHECK_TIME + | X509_V_FLAG_NO_CHECK_TIME)); + } + CMP_debug("trying to build cert chain for own TLS cert"); + if (SSL_CTX_build_cert_chain(ssl_ctx, + SSL_BUILD_CHAIN_FLAG_UNTRUSTED | + SSL_BUILD_CHAIN_FLAG_NO_ROOT)) { + CMP_debug("success building cert chain for own TLS cert"); + } else { + OSSL_CMP_CTX_print_errors(ctx); + CMP_warn("could not build cert chain for own TLS cert"); + } + if (trust_store != NULL) + X509_VERIFY_PARAM_set_flags(tls_vpm, bak_flags); + } + + /* If present we append to the list also the certs from opt_tls_extra */ + if (opt_tls_extra != NULL) { + STACK_OF(X509) *tls_extra = load_certs_multifile(opt_tls_extra, + opt_otherpass, + "extra certificates for TLS", + vpm); + int res = 1; + + if (tls_extra == NULL) + goto err; + for (i = 0; i < sk_X509_num(tls_extra); i++) { + cert = sk_X509_value(tls_extra, i); + if (res != 0) + res = SSL_CTX_add_extra_chain_cert(ssl_ctx, cert); + if (res == 0) + X509_free(cert); + } + sk_X509_free(tls_extra); + if (res == 0) { + BIO_printf(bio_err, "error: unable to add TLS extra certs\n"); + goto err; + } + } + + pkey = load_key_pwd(opt_tls_key, opt_keyform, opt_tls_keypass, + engine, "TLS client private key"); + cleanse(opt_tls_keypass); + if (pkey == NULL) + goto err; + /* + * verify the key matches the cert, + * not using SSL_CTX_check_private_key(ssl_ctx) + * because it gives poor and sometimes misleading diagnostics + */ + if (!X509_check_private_key(SSL_CTX_get0_certificate(ssl_ctx), + pkey)) { + CMP_err2("TLS private key '%s' does not match the TLS certificate '%s'\n", + opt_tls_key, opt_tls_cert); + EVP_PKEY_free(pkey); + pkey = NULL; /* otherwise, for some reason double free! */ + goto err; + } + if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) <= 0) { + CMP_err1("unable to use TLS client private key '%s'", opt_tls_key); + EVP_PKEY_free(pkey); + pkey = NULL; /* otherwise, for some reason double free! */ + goto err; + } + EVP_PKEY_free(pkey); /* we do not need the handle any more */ + } + if (opt_tls_trusted != NULL) { + /* enable and parameterize server hostname/IP address check */ + if (!truststore_set_host_etc(trust_store, + opt_tls_host != NULL ? opt_tls_host : host)) + goto err; + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); + } + return ssl_ctx; + err: + SSL_CTX_free(ssl_ctx); + return NULL; +} +#endif /* OPENSSL_NO_SOCK */ + +/* + * set up protection aspects of OSSL_CMP_CTX based on options from config + * file/CLI while parsing options and checking their consistency. + * Returns 1 on success, 0 on error + */ +static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) +{ + if (!opt_unprotected_requests && opt_secret == NULL && opt_key == NULL) { + CMP_err("must give -key or -secret unless -unprotected_requests is used"); + return 0; + } + + if (opt_ref == NULL && opt_cert == NULL && opt_subject == NULL) { + /* cert or subject should determine the sender */ + CMP_err("must give -ref if no -cert and no -subject given"); + return 0; + } + if (!opt_secret && ((opt_cert == NULL) != (opt_key == NULL))) { + CMP_err("must give both -cert and -key options or neither"); + return 0; + } + if (opt_secret != NULL) { + char *pass_string = get_passwd(opt_secret, "PBMAC"); + int res; + + if (pass_string != NULL) { + cleanse(opt_secret); + res = OSSL_CMP_CTX_set1_secretValue(ctx, + (unsigned char *)pass_string, + strlen(pass_string)); + clear_free(pass_string); + if (res == 0) + return 0; + } + if (opt_cert != NULL || opt_key != NULL) + CMP_warn("-cert and -key not used for protection since -secret is given"); + } + if (opt_ref != NULL + && !OSSL_CMP_CTX_set1_referenceValue(ctx, (unsigned char *)opt_ref, + strlen(opt_ref))) + return 0; + + if (opt_key != NULL) { + EVP_PKEY *pkey = load_key_pwd(opt_key, opt_keyform, opt_keypass, engine, + "private key for CMP client certificate"); + + if (pkey == NULL || !OSSL_CMP_CTX_set1_pkey(ctx, pkey)) { + EVP_PKEY_free(pkey); + return 0; + } + EVP_PKEY_free(pkey); + } + if (opt_secret == NULL && opt_srvcert == NULL && opt_trusted == NULL) + CMP_warn("will not authenticate server due to missing -secret, -trusted, or -srvcert"); + + if (opt_cert != NULL) { + X509 *cert; + STACK_OF(X509) *certs = NULL; + X509_STORE *own_trusted = NULL; + int ok; + + if (!load_cert_certs(opt_cert, &cert, &certs, 0, opt_keypass, + "CMP client certificate (optionally with chain)", + vpm)) + /* opt_keypass is needed if opt_cert is an encrypted PKCS#12 file */ + return 0; + ok = OSSL_CMP_CTX_set1_cert(ctx, cert); + X509_free(cert); + if (!ok) { + CMP_err("out of memory"); + } else { + if (opt_own_trusted != NULL) { + own_trusted = load_trusted(opt_own_trusted, 0, + "trusted certs for verifying own CMP signer cert"); + ok = own_trusted != NULL; + } + ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs); + } + X509_STORE_free(own_trusted); + sk_X509_pop_free(certs, X509_free); + if (!ok) + return 0; + } else if (opt_own_trusted != NULL) { + CMP_warn("-own_trusted option is ignored without -cert"); + } + + if (!setup_certs(opt_extracerts, "extra certificates for CMP", ctx, + (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_extraCertsOut)) + return 0; + cleanse(opt_otherpass); + + if (opt_unprotected_requests) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1); + + if (opt_digest != NULL) { + int digest = OBJ_ln2nid(opt_digest); + + if (digest == NID_undef) { + CMP_err1("digest algorithm name not recognized: '%s'", opt_digest); + return 0; + } + if (!OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_DIGEST_ALGNID, digest) + || !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_OWF_ALGNID, digest)) { + CMP_err1("digest algorithm name not supported: '%s'", opt_digest); + return 0; + } + } + + if (opt_mac != NULL) { + int mac = OBJ_ln2nid(opt_mac); + if (mac == NID_undef) { + CMP_err1("MAC algorithm name not recognized: '%s'", opt_mac); + return 0; + } + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MAC_ALGNID, mac); + } + return 1; +} + +/* + * set up IR/CR/KUR/CertConf/RR specific parts of the OSSL_CMP_CTX + * based on options from config file/CLI. + * Returns pointer on success, NULL on error + */ +static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) +{ + X509_REQ *csr = NULL; + X509_EXTENSIONS *exts = NULL; + X509V3_CTX ext_ctx; + + if (opt_subject == NULL + && opt_csr == NULL && opt_oldcert == NULL && opt_cert == NULL + && opt_cmd != CMP_RR && opt_cmd != CMP_GENM) + CMP_warn("no -subject given; no -csr or -oldcert or -cert available for fallback"); + + if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) { + if (opt_newkey == NULL && opt_key == NULL && opt_csr == NULL) { + CMP_err("missing -newkey (or -key) to be certified and no -csr given"); + return 0; + } + if (opt_certout == NULL) { + CMP_err("-certout not given, nowhere to save newly enrolled certificate"); + return 0; + } + if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject") + || !set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer")) + return 0; + } else { + const char *msg = "option is ignored for commands other than 'ir', 'cr', and 'kur'"; + + if (opt_subject != NULL) { + if (opt_ref == NULL && opt_cert == NULL) { + /* use subject as default sender unless oldcert subject is used */ + if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject")) + return 0; + } else { + CMP_warn1("-subject %s since -ref or -cert is given", msg); + } + } + if (opt_issuer != NULL) + CMP_warn1("-issuer %s", msg); + if (opt_reqexts != NULL) + CMP_warn1("-reqexts %s", msg); + if (opt_san_nodefault) + CMP_warn1("-san_nodefault %s", msg); + if (opt_sans != NULL) + CMP_warn1("-sans %s", msg); + if (opt_policies != NULL) + CMP_warn1("-policies %s", msg); + if (opt_policy_oids != NULL) + CMP_warn1("-policy_oids %s", msg); + } + if (opt_cmd == CMP_KUR) { + char *ref_cert = opt_oldcert != NULL ? opt_oldcert : opt_cert; + + if (ref_cert == NULL && opt_csr == NULL) { + CMP_err("missing -oldcert for certificate to be updated and no -csr given"); + return 0; + } + if (opt_subject != NULL) + CMP_warn2("given -subject '%s' overrides the subject of '%s' for KUR", + opt_subject, ref_cert != NULL ? ref_cert : opt_csr); + } + if (opt_cmd == CMP_RR) { + if (opt_oldcert == NULL && opt_csr == NULL) { + CMP_err("missing -oldcert for certificate to be revoked and no -csr given"); + return 0; + } + if (opt_oldcert != NULL && opt_csr != NULL) + CMP_warn("ignoring -csr since certificate to be revoked is given"); + } + if (opt_cmd == CMP_P10CR && opt_csr == NULL) { + CMP_err("missing PKCS#10 CSR for p10cr"); + return 0; + } + + if (opt_recipient == NULL && opt_srvcert == NULL && opt_issuer == NULL + && opt_oldcert == NULL && opt_cert == NULL) + CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient will be set to \"NULL-DN\""); + + if (opt_cmd == CMP_P10CR || opt_cmd == CMP_RR) { + const char *msg = "option is ignored for 'p10cr' and 'rr' commands"; + + if (opt_newkeypass != NULL) + CMP_warn1("-newkeytype %s", msg); + if (opt_newkey != NULL) + CMP_warn1("-newkey %s", msg); + if (opt_days != 0) + CMP_warn1("-days %s", msg); + if (opt_popo != OSSL_CRMF_POPO_NONE - 1) + CMP_warn1("-popo %s", msg); + } else if (opt_newkey != NULL) { + const char *file = opt_newkey; + const int format = opt_keyform; + const char *pass = opt_newkeypass; + const char *desc = "new private key for cert to be enrolled"; + EVP_PKEY *pkey; + int priv = 1; + BIO *bio_bak = bio_err; + + bio_err = NULL; /* suppress diagnostics on first try loading key */ + pkey = load_key_pwd(file, format, pass, engine, desc); + bio_err = bio_bak; + if (pkey == NULL) { + ERR_clear_error(); + desc = opt_csr == NULL + ? "fallback public key for cert to be enrolled" + : "public key for checking cert resulting from p10cr"; + pkey = load_pubkey(file, format, 0, pass, engine, desc); + priv = 0; + } + cleanse(opt_newkeypass); + if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, priv, pkey)) { + EVP_PKEY_free(pkey); + return 0; + } + } + + if (opt_days > 0 + && !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_VALIDITY_DAYS, + opt_days)) { + CMP_err("could not set requested cert validity period"); + return 0; + } + + if (opt_policies != NULL && opt_policy_oids != NULL) { + CMP_err("cannot have policies both via -policies and via -policy_oids"); + return 0; + } + + if (opt_csr != NULL) { + if (opt_cmd == CMP_GENM) { + CMP_warn("-csr option is ignored for command 'genm'"); + } else { + if ((csr = load_csr_autofmt(opt_csr, "PKCS#10 CSR")) == NULL) + return 0; + if (!OSSL_CMP_CTX_set1_p10CSR(ctx, csr)) + goto oom; + } + } + if (opt_reqexts != NULL || opt_policies != NULL) { + if ((exts = sk_X509_EXTENSION_new_null()) == NULL) + goto oom; + X509V3_set_ctx(&ext_ctx, NULL, NULL, csr, NULL, X509V3_CTX_REPLACE); + X509V3_set_nconf(&ext_ctx, conf); + if (opt_reqexts != NULL + && !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_reqexts, &exts)) { + CMP_err1("cannot load certificate request extension section '%s'", + opt_reqexts); + goto exts_err; + } + if (opt_policies != NULL + && !X509V3_EXT_add_nconf_sk(conf, &ext_ctx, opt_policies, &exts)) { + CMP_err1("cannot load policy cert request extension section '%s'", + opt_policies); + goto exts_err; + } + OSSL_CMP_CTX_set0_reqExtensions(ctx, exts); + } + X509_REQ_free(csr); + /* After here, must not goto oom/exts_err */ + + if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) && opt_sans != NULL) { + CMP_err("cannot have Subject Alternative Names both via -reqexts and via -sans"); + return 0; + } + if (!set_gennames(ctx, opt_sans, "Subject Alternative Name")) + return 0; + + if (opt_san_nodefault) { + if (opt_sans != NULL) + CMP_warn("-opt_san_nodefault has no effect when -sans is used"); + (void)OSSL_CMP_CTX_set_option(ctx, + OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT, 1); + } + + if (opt_policy_oids_critical) { + if (opt_policy_oids == NULL) + CMP_warn("-opt_policy_oids_critical has no effect unless -policy_oids is given"); + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POLICIES_CRITICAL, 1); + } + + while (opt_policy_oids != NULL) { + ASN1_OBJECT *policy; + POLICYINFO *pinfo; + char *next = next_item(opt_policy_oids); + + if ((policy = OBJ_txt2obj(opt_policy_oids, 1)) == 0) { + CMP_err1("unknown policy OID '%s'", opt_policy_oids); + return 0; + } + + if ((pinfo = POLICYINFO_new()) == NULL) { + ASN1_OBJECT_free(policy); + return 0; + } + pinfo->policyid = policy; + + if (!OSSL_CMP_CTX_push0_policy(ctx, pinfo)) { + CMP_err1("cannot add policy with OID '%s'", opt_policy_oids); + POLICYINFO_free(pinfo); + return 0; + } + opt_policy_oids = next; + } + + if (opt_popo >= OSSL_CRMF_POPO_NONE) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POPO_METHOD, opt_popo); + + if (opt_oldcert != NULL) { + if (opt_cmd == CMP_GENM) { + CMP_warn("-oldcert option is ignored for command 'genm'"); + } else { + X509 *oldcert = load_cert_pwd(opt_oldcert, opt_keypass, + opt_cmd == CMP_KUR ? + "certificate to be updated" : + opt_cmd == CMP_RR ? + "certificate to be revoked" : + "reference certificate (oldcert)"); + /* opt_keypass needed if opt_oldcert is an encrypted PKCS#12 file */ + + if (oldcert == NULL) + return 0; + if (!OSSL_CMP_CTX_set1_oldCert(ctx, oldcert)) { + X509_free(oldcert); + CMP_err("out of memory"); + return 0; + } + X509_free(oldcert); + } + } + cleanse(opt_keypass); + if (opt_revreason > CRL_REASON_NONE) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_REVOCATION_REASON, + opt_revreason); + + return 1; + + oom: + CMP_err("out of memory"); + exts_err: + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + X509_REQ_free(csr); + return 0; +} + +static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) +{ + long value; + ASN1_OBJECT *type; + ASN1_INTEGER *aint; + ASN1_TYPE *val; + OSSL_CMP_ITAV *itav; + char *endstr; + char *valptr = strchr(opt_geninfo, ':'); + + if (valptr == NULL) { + CMP_err("missing ':' in -geninfo option"); + return 0; + } + valptr[0] = '\0'; + valptr++; + + if (OPENSSL_strncasecmp(valptr, "int:", 4) != 0) { + CMP_err("missing 'int:' in -geninfo option"); + return 0; + } + valptr += 4; + + value = strtol(valptr, &endstr, 10); + if (endstr == valptr || *endstr != '\0') { + CMP_err("cannot parse int in -geninfo option"); + return 0; + } + + type = OBJ_txt2obj(opt_geninfo, 1); + if (type == NULL) { + CMP_err("cannot parse OID in -geninfo option"); + return 0; + } + + if ((aint = ASN1_INTEGER_new()) == NULL) + goto oom; + + val = ASN1_TYPE_new(); + if (!ASN1_INTEGER_set(aint, value) || val == NULL) { + ASN1_INTEGER_free(aint); + goto oom; + } + ASN1_TYPE_set(val, V_ASN1_INTEGER, aint); + itav = OSSL_CMP_ITAV_create(type, val); + if (itav == NULL) { + ASN1_TYPE_free(val); + goto oom; + } + + if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) { + OSSL_CMP_ITAV_free(itav); + return 0; + } + return 1; + + oom: + ASN1_OBJECT_free(type); + CMP_err("out of memory"); + return 0; +} + + +/* + * set up the client-side OSSL_CMP_CTX based on options from config file/CLI + * while parsing options and checking their consistency. + * Prints reason for error to bio_err. + * Returns 1 on success, 0 on error + */ +static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) +{ + int ret = 0; + char *host = NULL, *port = NULL, *path = NULL, *used_path = opt_path; +#ifndef OPENSSL_NO_SOCK + int portnum, ssl; + static char server_port[32] = { '\0' }; + const char *proxy_host = NULL; +#endif + char server_buf[200] = "mock server"; + char proxy_buf[200] = ""; + + if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */ +#ifndef OPENSSL_NO_SOCK + if (opt_server == NULL) { + CMP_err("missing -server or -use_mock_srv or -rspin option"); + goto err; + } +#else + CMP_err("missing -use_mock_srv or -rspin option; -server option is not supported due to no-sock build"); + goto err; +#endif + } +#ifndef OPENSSL_NO_SOCK + if (opt_server == NULL) { + if (opt_proxy != NULL) + CMP_warn("ignoring -proxy option since -server is not given"); + if (opt_no_proxy != NULL) + CMP_warn("ignoring -no_proxy option since -server is not given"); + if (opt_tls_used) { + CMP_warn("ignoring -tls_used option since -server is not given"); + opt_tls_used = 0; + } + goto set_path; + } + if (!OSSL_HTTP_parse_url(opt_server, &ssl, NULL /* user */, &host, &port, + &portnum, &path, NULL /* q */, NULL /* frag */)) { + CMP_err1("cannot parse -server URL: %s", opt_server); + goto err; + } + if (ssl && !opt_tls_used) { + CMP_err("missing -tls_used option since -server URL indicates https"); + goto err; + } + + BIO_snprintf(server_port, sizeof(server_port), "%s", port); + if (opt_path == NULL) + used_path = path; + if (!OSSL_CMP_CTX_set1_server(ctx, host) + || !OSSL_CMP_CTX_set_serverPort(ctx, portnum)) + goto oom; + if (opt_proxy != NULL && !OSSL_CMP_CTX_set1_proxy(ctx, opt_proxy)) + goto oom; + if (opt_no_proxy != NULL && !OSSL_CMP_CTX_set1_no_proxy(ctx, opt_no_proxy)) + goto oom; + (void)BIO_snprintf(server_buf, sizeof(server_buf), "http%s://%s:%s/%s", + opt_tls_used ? "s" : "", host, port, + *used_path == '/' ? used_path + 1 : used_path); + + proxy_host = OSSL_HTTP_adapt_proxy(opt_proxy, opt_no_proxy, host, ssl); + if (proxy_host != NULL) + (void)BIO_snprintf(proxy_buf, sizeof(proxy_buf), " via %s", proxy_host); + + set_path: +#endif + + if (!OSSL_CMP_CTX_set1_serverPath(ctx, used_path)) + goto oom; + if (!transform_opts()) + goto err; + + if (opt_infotype_s != NULL) { + char id_buf[100] = "id-it-"; + + strncat(id_buf, opt_infotype_s, sizeof(id_buf) - strlen(id_buf) - 1); + if ((opt_infotype = OBJ_sn2nid(id_buf)) == NID_undef) { + CMP_err("unknown OID name in -infotype option"); + goto err; + } + } + + if (!setup_verification_ctx(ctx)) + goto err; + + if (opt_keep_alive != 1) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_KEEP_ALIVE, + opt_keep_alive); + if (opt_total_timeout > 0 && opt_msg_timeout > 0 + && opt_total_timeout < opt_msg_timeout) { + CMP_err2("-total_timeout argument = %d must not be < %d (-msg_timeout)", + opt_total_timeout, opt_msg_timeout); + goto err; + } + if (opt_msg_timeout >= 0) /* must do this before setup_ssl_ctx() */ + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT, + opt_msg_timeout); + if (opt_total_timeout >= 0) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT, + opt_total_timeout); + + if (opt_reqin != NULL && opt_rspin != NULL) + CMP_warn("-reqin is ignored since -rspin is present"); + if (opt_reqin_new_tid && opt_reqin == NULL) + CMP_warn("-reqin_new_tid is ignored since -reqin is not present"); + if (opt_reqin != NULL || opt_reqout != NULL + || opt_rspin != NULL || opt_rspout != NULL || opt_use_mock_srv) + (void)OSSL_CMP_CTX_set_transfer_cb(ctx, read_write_req_resp); + +#ifndef OPENSSL_NO_SOCK + if (opt_tls_used) { + APP_HTTP_TLS_INFO *info; + + if (opt_tls_cert != NULL + || opt_tls_key != NULL || opt_tls_keypass != NULL) { + if (opt_tls_key == NULL) { + CMP_err("missing -tls_key option"); + goto err; + } else if (opt_tls_cert == NULL) { + CMP_err("missing -tls_cert option"); + goto err; + } + } + + if ((info = OPENSSL_zalloc(sizeof(*info))) == NULL) + goto err; + (void)OSSL_CMP_CTX_set_http_cb_arg(ctx, info); + info->server = opt_server; + info->port = server_port; + /* workaround for callback design flaw, see #17088: */ + info->use_proxy = proxy_host != NULL; + info->timeout = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_MSG_TIMEOUT); + info->ssl_ctx = setup_ssl_ctx(ctx, host, engine); + + if (info->ssl_ctx == NULL) + goto err; + (void)OSSL_CMP_CTX_set_http_cb(ctx, app_http_tls_cb); + } +#endif + + if (!setup_protection_ctx(ctx, engine)) + goto err; + + if (!setup_request_ctx(ctx, engine)) + goto err; + + if (!set_name(opt_recipient, OSSL_CMP_CTX_set1_recipient, ctx, "recipient") + || !set_name(opt_expect_sender, OSSL_CMP_CTX_set1_expected_sender, + ctx, "expected sender")) + goto err; + + if (opt_geninfo != NULL && !handle_opt_geninfo(ctx)) + goto err; + + /* not printing earlier, to minimize confusion in case setup fails before */ + if (opt_rspin != NULL) + CMP_info("will not contact any server since -rspin is given"); + else + CMP_info2("will contact %s%s", server_buf, proxy_buf); + + ret = 1; + + err: + OPENSSL_free(host); + OPENSSL_free(port); + OPENSSL_free(path); + return ret; + oom: + CMP_err("out of memory"); + goto err; +} + +/* + * write out the given certificate to the output specified by bio. + * Depending on options use either PEM or DER format. + * Returns 1 on success, 0 on error + */ +static int write_cert(BIO *bio, X509 *cert) +{ + if ((opt_certform == FORMAT_PEM && PEM_write_bio_X509(bio, cert)) + || (opt_certform == FORMAT_ASN1 && i2d_X509_bio(bio, cert))) + return 1; + if (opt_certform != FORMAT_PEM && opt_certform != FORMAT_ASN1) + BIO_printf(bio_err, + "error: unsupported type '%s' for writing certificates\n", + opt_certform_s); + return 0; +} + +/* + * If destFile != NULL writes out a stack of certs to the given file. + * In any case frees the certs. + * Depending on options use either PEM or DER format, + * where DER does not make much sense for writing more than one cert! + * Returns number of written certificates on success, -1 on error. + */ +static int save_free_certs(OSSL_CMP_CTX *ctx, + STACK_OF(X509) *certs, char *destFile, char *desc) +{ + BIO *bio = NULL; + int i; + int n = sk_X509_num(certs); + + if (destFile == NULL) + goto end; + CMP_info3("received %d %s certificate(s), saving to file '%s'", + n, desc, destFile); + if (n > 1 && opt_certform != FORMAT_PEM) + CMP_warn("saving more than one certificate in non-PEM format"); + + if (destFile == NULL || (bio = BIO_new(BIO_s_file())) == NULL + || !BIO_write_filename(bio, (char *)destFile)) { + CMP_err1("could not open file '%s' for writing", destFile); + n = -1; + goto end; + } + + for (i = 0; i < n; i++) { + if (!write_cert(bio, sk_X509_value(certs, i))) { + CMP_err1("cannot write certificate to file '%s'", destFile); + n = -1; + goto end; + } + } + + end: + BIO_free(bio); + sk_X509_pop_free(certs, X509_free); + return n; +} + +static void print_itavs(STACK_OF(OSSL_CMP_ITAV) *itavs) +{ + OSSL_CMP_ITAV *itav = NULL; + char buf[128]; + int i, r; + int n = sk_OSSL_CMP_ITAV_num(itavs); /* itavs == NULL leads to 0 */ + + if (n == 0) { + CMP_info("genp contains no ITAV"); + return; + } + + for (i = 0; i < n; i++) { + itav = sk_OSSL_CMP_ITAV_value(itavs, i); + r = OBJ_obj2txt(buf, 128, OSSL_CMP_ITAV_get0_type(itav), 0); + if (r < 0) + CMP_err("could not get ITAV details"); + else if (r == 0) + CMP_info("genp contains empty ITAV"); + else + CMP_info1("genp contains ITAV of type: %s", buf); + } +} + +static char opt_item[SECTION_NAME_MAX + 1]; +/* get previous name from a comma or space-separated list of names */ +static const char *prev_item(const char *opt, const char *end) +{ + const char *beg; + size_t len; + + if (end == opt) + return NULL; + beg = end; + while (beg > opt) { + --beg; + if (beg[0] == ',' || isspace(beg[0])) { + ++beg; + break; + } + } + len = end - beg; + if (len > SECTION_NAME_MAX) { + CMP_warn3("using only first %d characters of section name starting with \"%.*s\"", + SECTION_NAME_MAX, SECTION_NAME_MAX, beg); + len = SECTION_NAME_MAX; + } + memcpy(opt_item, beg, len); + opt_item[len] = '\0'; + while (beg > opt) { + --beg; + if (beg[0] != ',' && !isspace(beg[0])) { + ++beg; + break; + } + } + return beg; +} + +/* get str value for name from a comma-separated hierarchy of config sections */ +static char *conf_get_string(const CONF *src_conf, const char *groups, + const char *name) +{ + char *res = NULL; + const char *end = groups + strlen(groups); + + while ((end = prev_item(groups, end)) != NULL) { + if ((res = NCONF_get_string(src_conf, opt_item, name)) != NULL) + return res; + } + return res; +} + +/* get long val for name from a comma-separated hierarchy of config sections */ +static int conf_get_number_e(const CONF *conf_, const char *groups, + const char *name, long *result) +{ + char *str = conf_get_string(conf_, groups, name); + char *tailptr; + long res; + + if (str == NULL || *str == '\0') + return 0; + + res = strtol(str, &tailptr, 10); + if (res == LONG_MIN || res == LONG_MAX || *tailptr != '\0') + return 0; + + *result = res; + return 1; +} + +/* + * use the command line option table to read values from the CMP section + * of openssl.cnf. Defaults are taken from the config file, they can be + * overwritten on the command line. + */ +static int read_config(void) +{ + unsigned int i; + long num = 0; + char *txt = NULL; + const OPTIONS *opt; + int start_opt = OPT_VERBOSITY - OPT_HELP; + int start_idx = OPT_VERBOSITY - 2; + /* + * starting with offset OPT_VERBOSITY because OPT_CONFIG and OPT_SECTION + * would not make sense within the config file. + */ + int n_options = OSSL_NELEM(cmp_options) - 1; + + for (opt = &cmp_options[start_opt], i = start_idx; + opt->name != NULL; i++, opt++) + if (!strcmp(opt->name, OPT_SECTION_STR) + || !strcmp(opt->name, OPT_MORE_STR)) + n_options--; + OPENSSL_assert(OSSL_NELEM(cmp_vars) == n_options + + OPT_PROV__FIRST + 1 - OPT_PROV__LAST + + OPT_R__FIRST + 1 - OPT_R__LAST + + OPT_V__FIRST + 1 - OPT_V__LAST); + for (opt = &cmp_options[start_opt], i = start_idx; + opt->name != NULL; i++, opt++) { + int provider_option = (OPT_PROV__FIRST <= opt->retval + && opt->retval < OPT_PROV__LAST); + int rand_state_option = (OPT_R__FIRST <= opt->retval + && opt->retval < OPT_R__LAST); + int verification_option = (OPT_V__FIRST <= opt->retval + && opt->retval < OPT_V__LAST); + + if (strcmp(opt->name, OPT_SECTION_STR) == 0 + || strcmp(opt->name, OPT_MORE_STR) == 0) { + i--; + continue; + } + if (provider_option || rand_state_option || verification_option) + i--; + switch (opt->valtype) { + case '-': + case 'p': + case 'n': + case 'N': + case 'l': + if (!conf_get_number_e(conf, opt_section, opt->name, &num)) { + ERR_clear_error(); + continue; /* option not provided */ + } + if (opt->valtype == 'p' && num <= 0) { + opt_printf_stderr("Non-positive number \"%ld\" for config option -%s\n", + num, opt->name); + return -1; + } + if (opt->valtype == 'N' && num < 0) { + opt_printf_stderr("Negative number \"%ld\" for config option -%s\n", + num, opt->name); + return -1; + } + break; + case 's': + case '>': + case 'M': + txt = conf_get_string(conf, opt_section, opt->name); + if (txt == NULL) { + ERR_clear_error(); + continue; /* option not provided */ + } + break; + default: + CMP_err2("internal: unsupported type '%c' for option '%s'", + opt->valtype, opt->name); + return 0; + break; + } + if (provider_option || verification_option) { + int conf_argc = 1; + char *conf_argv[3]; + char arg1[82]; + + BIO_snprintf(arg1, 81, "-%s", (char *)opt->name); + conf_argv[0] = prog; + conf_argv[1] = arg1; + if (opt->valtype == '-') { + if (num != 0) + conf_argc = 2; + } else { + conf_argc = 3; + conf_argv[2] = conf_get_string(conf, opt_section, opt->name); + /* not NULL */ + } + if (conf_argc > 1) { + (void)opt_init(conf_argc, conf_argv, cmp_options); + + if (provider_option + ? !opt_provider(opt_next()) + : !opt_verify(opt_next(), vpm)) { + CMP_err2("for option '%s' in config file section '%s'", + opt->name, opt_section); + return 0; + } + } + } else { + switch (opt->valtype) { + case '-': + case 'p': + case 'n': + case 'N': + if (num < INT_MIN || INT_MAX < num) { + BIO_printf(bio_err, + "integer value out of range for option '%s'\n", + opt->name); + return 0; + } + *cmp_vars[i].num = (int)num; + break; + case 'l': + *cmp_vars[i].num_long = num; + break; + default: + if (txt != NULL && txt[0] == '\0') + txt = NULL; /* reset option on empty string input */ + *cmp_vars[i].txt = txt; + break; + } + } + } + + return 1; +} + +static char *opt_str(void) +{ + char *arg = opt_arg(); + + if (arg[0] == '\0') { + CMP_warn1("%s option argument is empty string, resetting option", + opt_flag()); + arg = NULL; + } else if (arg[0] == '-') { + CMP_warn1("%s option argument starts with hyphen", opt_flag()); + } + return arg; +} + +/* returns 1 on success, 0 on error, -1 on -help (i.e., stop with success) */ +static int get_opts(int argc, char **argv) +{ + OPTION_CHOICE o; + + prog = opt_init(argc, argv, cmp_options); + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + return 0; + case OPT_HELP: + opt_help(cmp_options); + return -1; + case OPT_CONFIG: /* has already been handled */ + case OPT_SECTION: /* has already been handled */ + break; + case OPT_VERBOSITY: + if (!set_verbosity(opt_int_arg())) + goto opthelp; + break; +#ifndef OPENSSL_NO_SOCK + case OPT_SERVER: + opt_server = opt_str(); + break; + case OPT_PROXY: + opt_proxy = opt_str(); + break; + case OPT_NO_PROXY: + opt_no_proxy = opt_str(); + break; +#endif + case OPT_RECIPIENT: + opt_recipient = opt_str(); + break; + case OPT_PATH: + opt_path = opt_str(); + break; + case OPT_KEEP_ALIVE: + opt_keep_alive = opt_int_arg(); + if (opt_keep_alive > 2) { + CMP_err("-keep_alive argument must be 0, 1, or 2"); + goto opthelp; + } + break; + case OPT_MSG_TIMEOUT: + opt_msg_timeout = opt_int_arg(); + break; + case OPT_TOTAL_TIMEOUT: + opt_total_timeout = opt_int_arg(); + break; +#ifndef OPENSSL_NO_SOCK + case OPT_TLS_USED: + opt_tls_used = 1; + break; + case OPT_TLS_CERT: + opt_tls_cert = opt_str(); + break; + case OPT_TLS_KEY: + opt_tls_key = opt_str(); + break; + case OPT_TLS_KEYPASS: + opt_tls_keypass = opt_str(); + break; + case OPT_TLS_EXTRA: + opt_tls_extra = opt_str(); + break; + case OPT_TLS_TRUSTED: + opt_tls_trusted = opt_str(); + break; + case OPT_TLS_HOST: + opt_tls_host = opt_str(); + break; +#endif + + case OPT_REF: + opt_ref = opt_str(); + break; + case OPT_SECRET: + opt_secret = opt_str(); + break; + case OPT_CERT: + opt_cert = opt_str(); + break; + case OPT_OWN_TRUSTED: + opt_own_trusted = opt_str(); + break; + case OPT_KEY: + opt_key = opt_str(); + break; + case OPT_KEYPASS: + opt_keypass = opt_str(); + break; + case OPT_DIGEST: + opt_digest = opt_str(); + break; + case OPT_MAC: + opt_mac = opt_str(); + break; + case OPT_EXTRACERTS: + opt_extracerts = opt_str(); + break; + case OPT_UNPROTECTED_REQUESTS: + opt_unprotected_requests = 1; + break; + + case OPT_TRUSTED: + opt_trusted = opt_str(); + break; + case OPT_UNTRUSTED: + opt_untrusted = opt_str(); + break; + case OPT_SRVCERT: + opt_srvcert = opt_str(); + break; + case OPT_EXPECT_SENDER: + opt_expect_sender = opt_str(); + break; + case OPT_IGNORE_KEYUSAGE: + opt_ignore_keyusage = 1; + break; + case OPT_UNPROTECTED_ERRORS: + opt_unprotected_errors = 1; + break; + case OPT_EXTRACERTSOUT: + opt_extracertsout = opt_str(); + break; + case OPT_CACERTSOUT: + opt_cacertsout = opt_str(); + break; + + case OPT_V_CASES: + if (!opt_verify(o, vpm)) + goto opthelp; + break; + case OPT_CMD: + opt_cmd_s = opt_str(); + break; + case OPT_INFOTYPE: + opt_infotype_s = opt_str(); + break; + case OPT_GENINFO: + opt_geninfo = opt_str(); + break; + + case OPT_NEWKEY: + opt_newkey = opt_str(); + break; + case OPT_NEWKEYPASS: + opt_newkeypass = opt_str(); + break; + case OPT_SUBJECT: + opt_subject = opt_str(); + break; + case OPT_ISSUER: + opt_issuer = opt_str(); + break; + case OPT_DAYS: + opt_days = opt_int_arg(); + break; + case OPT_REQEXTS: + opt_reqexts = opt_str(); + break; + case OPT_SANS: + opt_sans = opt_str(); + break; + case OPT_SAN_NODEFAULT: + opt_san_nodefault = 1; + break; + case OPT_POLICIES: + opt_policies = opt_str(); + break; + case OPT_POLICY_OIDS: + opt_policy_oids = opt_str(); + break; + case OPT_POLICY_OIDS_CRITICAL: + opt_policy_oids_critical = 1; + break; + case OPT_POPO: + opt_popo = opt_int_arg(); + if (opt_popo < OSSL_CRMF_POPO_NONE + || opt_popo > OSSL_CRMF_POPO_KEYENC) { + CMP_err("invalid popo spec. Valid values are -1 .. 2"); + goto opthelp; + } + break; + case OPT_CSR: + opt_csr = opt_arg(); + break; + case OPT_OUT_TRUSTED: + opt_out_trusted = opt_str(); + break; + case OPT_IMPLICIT_CONFIRM: + opt_implicit_confirm = 1; + break; + case OPT_DISABLE_CONFIRM: + opt_disable_confirm = 1; + break; + case OPT_CERTOUT: + opt_certout = opt_str(); + break; + case OPT_CHAINOUT: + opt_chainout = opt_str(); + break; + case OPT_OLDCERT: + opt_oldcert = opt_str(); + break; + case OPT_REVREASON: + opt_revreason = opt_int_arg(); + if (opt_revreason < CRL_REASON_NONE + || opt_revreason > CRL_REASON_AA_COMPROMISE + || opt_revreason == 7) { + CMP_err("invalid revreason. Valid values are -1 .. 6, 8 .. 10"); + goto opthelp; + } + break; + case OPT_CERTFORM: + opt_certform_s = opt_str(); + break; + case OPT_KEYFORM: + opt_keyform_s = opt_str(); + break; + case OPT_OTHERPASS: + opt_otherpass = opt_str(); + break; +#ifndef OPENSSL_NO_ENGINE + case OPT_ENGINE: + opt_engine = opt_str(); + break; +#endif + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto opthelp; + break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto opthelp; + break; + + case OPT_BATCH: + opt_batch = 1; + break; + case OPT_REPEAT: + opt_repeat = opt_int_arg(); + break; + case OPT_REQIN: + opt_reqin = opt_str(); + break; + case OPT_REQIN_NEW_TID: + opt_reqin_new_tid = 1; + break; + case OPT_REQOUT: + opt_reqout = opt_str(); + break; + case OPT_RSPIN: + opt_rspin = opt_str(); + break; + case OPT_RSPOUT: + opt_rspout = opt_str(); + break; + case OPT_USE_MOCK_SRV: + opt_use_mock_srv = 1; + break; + +#ifndef OPENSSL_NO_SOCK + case OPT_PORT: + opt_port = opt_str(); + break; + case OPT_MAX_MSGS: + opt_max_msgs = opt_int_arg(); + break; +#endif + case OPT_SRV_REF: + opt_srv_ref = opt_str(); + break; + case OPT_SRV_SECRET: + opt_srv_secret = opt_str(); + break; + case OPT_SRV_CERT: + opt_srv_cert = opt_str(); + break; + case OPT_SRV_KEY: + opt_srv_key = opt_str(); + break; + case OPT_SRV_KEYPASS: + opt_srv_keypass = opt_str(); + break; + case OPT_SRV_TRUSTED: + opt_srv_trusted = opt_str(); + break; + case OPT_SRV_UNTRUSTED: + opt_srv_untrusted = opt_str(); + break; + case OPT_RSP_CERT: + opt_rsp_cert = opt_str(); + break; + case OPT_RSP_EXTRACERTS: + opt_rsp_extracerts = opt_str(); + break; + case OPT_RSP_CAPUBS: + opt_rsp_capubs = opt_str(); + break; + case OPT_POLL_COUNT: + opt_poll_count = opt_int_arg(); + break; + case OPT_CHECK_AFTER: + opt_check_after = opt_int_arg(); + break; + case OPT_GRANT_IMPLICITCONF: + opt_grant_implicitconf = 1; + break; + case OPT_PKISTATUS: + opt_pkistatus = opt_int_arg(); + break; + case OPT_FAILURE: + opt_failure = opt_int_arg(); + break; + case OPT_FAILUREBITS: + opt_failurebits = opt_int_arg(); + break; + case OPT_STATUSSTRING: + opt_statusstring = opt_str(); + break; + case OPT_SEND_ERROR: + opt_send_error = 1; + break; + case OPT_SEND_UNPROTECTED: + opt_send_unprotected = 1; + break; + case OPT_SEND_UNPROT_ERR: + opt_send_unprot_err = 1; + break; + case OPT_ACCEPT_UNPROTECTED: + opt_accept_unprotected = 1; + break; + case OPT_ACCEPT_UNPROT_ERR: + opt_accept_unprot_err = 1; + break; + case OPT_ACCEPT_RAVERIFIED: + opt_accept_raverified = 1; + break; + } + } + + /* No extra args. */ + argc = opt_num_rest(); + argv = opt_rest(); + if (argc != 0) + goto opthelp; + return 1; +} + +#ifndef OPENSSL_NO_SOCK +static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { + BIO *acbio; + BIO *cbio = NULL; + int keep_alive = 0; + int msgs = 0; + int retry = 1; + int ret = 1; + + if ((acbio = http_server_init_bio(prog, opt_port)) == NULL) + return 0; + while (opt_max_msgs <= 0 || msgs < opt_max_msgs) { + char *path = NULL; + OSSL_CMP_MSG *req = NULL; + OSSL_CMP_MSG *resp = NULL; + + ret = http_server_get_asn1_req(ASN1_ITEM_rptr(OSSL_CMP_MSG), + (ASN1_VALUE **)&req, &path, + &cbio, acbio, &keep_alive, + prog, opt_port, 0, 0); + if (ret == 0) { /* no request yet */ + if (retry) { + ossl_sleep(1000); + retry = 0; + continue; + } + ret = 0; + goto next; + } + if (ret++ == -1) /* fatal error */ + break; + + ret = 0; + msgs++; + if (req != NULL) { + if (strcmp(path, "") != 0 && strcmp(path, "pkix/") != 0) { + (void)http_server_send_status(cbio, 404, "Not Found"); + CMP_err1("expecting empty path or 'pkix/' but got '%s'", + path); + OPENSSL_free(path); + OSSL_CMP_MSG_free(req); + goto next; + } + OPENSSL_free(path); + resp = OSSL_CMP_CTX_server_perform(cmp_ctx, req); + OSSL_CMP_MSG_free(req); + if (resp == NULL) { + (void)http_server_send_status(cbio, + 500, "Internal Server Error"); + break; /* treated as fatal error */ + } + ret = http_server_send_asn1_resp(cbio, keep_alive, + "application/pkixcmp", + ASN1_ITEM_rptr(OSSL_CMP_MSG), + (const ASN1_VALUE *)resp); + OSSL_CMP_MSG_free(resp); + if (!ret) + break; /* treated as fatal error */ + } + next: + if (!ret) { /* on transmission error, cancel CMP transaction */ + (void)OSSL_CMP_CTX_set1_transactionID(srv_cmp_ctx, NULL); + (void)OSSL_CMP_CTX_set1_senderNonce(srv_cmp_ctx, NULL); + } + if (!ret || !keep_alive + || OSSL_CMP_CTX_get_status(srv_cmp_ctx) != OSSL_CMP_PKISTATUS_trans + /* transaction closed by OSSL_CMP_CTX_server_perform() */) { + BIO_free_all(cbio); + cbio = NULL; + } + } + + BIO_free_all(cbio); + BIO_free_all(acbio); + return ret; +} +#endif + +static void print_status(void) +{ + /* print PKIStatusInfo */ + int status = OSSL_CMP_CTX_get_status(cmp_ctx); + char *buf = app_malloc(OSSL_CMP_PKISI_BUFLEN, "PKIStatusInfo buf"); + const char *string = + OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf, OSSL_CMP_PKISI_BUFLEN); + const char *from = "", *server = ""; + +#ifndef OPENSSL_NO_SOCK + if (opt_server != NULL) { + from = " from "; + server = opt_server; + } +#endif + CMP_print(bio_err, + status == OSSL_CMP_PKISTATUS_accepted + ? OSSL_CMP_LOG_INFO : + status == OSSL_CMP_PKISTATUS_rejection + || status == OSSL_CMP_PKISTATUS_waiting + ? OSSL_CMP_LOG_ERR : OSSL_CMP_LOG_WARNING, + status == OSSL_CMP_PKISTATUS_accepted ? "info" : + status == OSSL_CMP_PKISTATUS_rejection ? "server error" : + status == OSSL_CMP_PKISTATUS_waiting ? "internal error" + : "warning", "received%s%s %s", from, server, + string != NULL ? string : ""); + OPENSSL_free(buf); +} + +int cmp_main(int argc, char **argv) +{ + char *configfile = NULL; + int i; + X509 *newcert = NULL; + ENGINE *engine = NULL; + OSSL_CMP_CTX *srv_cmp_ctx = NULL; + int ret = 0; /* default: failure */ + + prog = opt_appname(argv[0]); + if (argc <= 1) { + opt_help(cmp_options); + goto err; + } + + /* + * handle options -config, -section, and -verbosity upfront + * to take effect for other options + */ + for (i = 1; i < argc - 1; i++) { + if (*argv[i] == '-') { + if (!strcmp(argv[i] + 1, cmp_options[OPT_CONFIG - OPT_HELP].name)) + opt_config = argv[++i]; + else if (!strcmp(argv[i] + 1, + cmp_options[OPT_SECTION - OPT_HELP].name)) + opt_section = argv[++i]; + else if (strcmp(argv[i] + 1, + cmp_options[OPT_VERBOSITY - OPT_HELP].name) == 0 + && !set_verbosity(atoi(argv[++i]))) + goto err; + } + } + if (opt_section[0] == '\0') /* empty string */ + opt_section = DEFAULT_SECTION; + + vpm = X509_VERIFY_PARAM_new(); + if (vpm == NULL) { + CMP_err("out of memory"); + goto err; + } + + /* read default values for options from config file */ + configfile = opt_config != NULL ? opt_config : default_config_file; + if (configfile != NULL && configfile[0] != '\0' /* non-empty string */ + && (configfile != default_config_file || access(configfile, F_OK) != -1)) { + CMP_info2("using section(s) '%s' of OpenSSL configuration file '%s'", + opt_section, configfile); + conf = app_load_config(configfile); + if (conf == NULL) { + goto err; + } else { + if (strcmp(opt_section, CMP_SECTION) == 0) { /* default */ + if (!NCONF_get_section(conf, opt_section)) + CMP_info2("no [%s] section found in config file '%s';" + " will thus use just [default] and unnamed section if present", + opt_section, configfile); + } else { + const char *end = opt_section + strlen(opt_section); + while ((end = prev_item(opt_section, end)) != NULL) { + if (!NCONF_get_section(conf, opt_item)) { + CMP_err2("no [%s] section found in config file '%s'", + opt_item, configfile); + goto err; + } + } + } + ret = read_config(); + if (!set_verbosity(opt_verbosity)) /* just for checking range */ + ret = -1; + if (ret <= 0) { + if (ret == -1) + BIO_printf(bio_err, "Use -help for summary.\n"); + goto err; + } + } + } + (void)BIO_flush(bio_err); /* prevent interference with opt_help() */ + + ret = get_opts(argc, argv); + if (ret <= 0) + goto err; + ret = 0; + if (!app_RAND_load()) + goto err; + + if (opt_batch) + set_base_ui_method(UI_null()); + + if (opt_engine != NULL) { + engine = setup_engine_methods(opt_engine, 0 /* not: ENGINE_METHOD_ALL */, 0); + if (engine == NULL) { + CMP_err1("cannot load engine %s", opt_engine); + goto err; + } + } + + cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq()); + if (cmp_ctx == NULL) + goto err; + OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity); + if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) { + CMP_err1("cannot set up error reporting and logging for %s", prog); + goto err; + } + +#ifndef OPENSSL_NO_SOCK + if ((opt_tls_cert != NULL || opt_tls_key != NULL + || opt_tls_keypass != NULL || opt_tls_extra != NULL + || opt_tls_trusted != NULL || opt_tls_host != NULL) + && !opt_tls_used) + CMP_warn("Ingnoring TLS options(s) since -tls_used is not given"); + if (opt_port != NULL) { + if (opt_tls_used) { + CMP_err("-tls_used option not supported with -port option"); + goto err; + } + if (opt_use_mock_srv || opt_server != NULL || opt_rspin != NULL) { + CMP_err("cannot use -port with -use_mock_srv, -server, or -rspin options"); + goto err; + } + } + if (opt_server != NULL && opt_use_mock_srv) { + CMP_err("cannot use both -server and -use_mock_srv options"); + goto err; + } +#endif + if (opt_rspin != NULL && opt_use_mock_srv) { + CMP_err("cannot use both -rspin and -use_mock_srv options"); + goto err; + } + + if (opt_use_mock_srv +#ifndef OPENSSL_NO_SOCK + || opt_port != NULL +#endif + ) { + OSSL_CMP_SRV_CTX *srv_ctx; + + if ((srv_ctx = setup_srv_ctx(engine)) == NULL) + goto err; + srv_cmp_ctx = OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx); + OSSL_CMP_CTX_set_transfer_cb_arg(cmp_ctx, srv_ctx); + if (!OSSL_CMP_CTX_set_log_cb(srv_cmp_ctx, print_to_bio_err)) { + CMP_err1("cannot set up error reporting and logging for %s", prog); + goto err; + } + OSSL_CMP_CTX_set_log_verbosity(srv_cmp_ctx, opt_verbosity); + } + +#ifndef OPENSSL_NO_SOCK + if (opt_tls_used && (opt_use_mock_srv || opt_rspin != NULL)) { + CMP_warn("ignoring -tls_used option since -use_mock_srv or -rspin is given"); + opt_tls_used = 0; + } + + if (opt_port != NULL) { /* act as very basic CMP HTTP server */ + ret = cmp_server(srv_cmp_ctx); + goto err; + } + + /* act as CMP client, possibly using internal mock server */ + + if (opt_server != NULL) { + if (opt_rspin != NULL) { + CMP_warn("ignoring -server option since -rspin is given"); + opt_server = NULL; + } + } +#endif + + if (!setup_client_ctx(cmp_ctx, engine)) { + CMP_err("cannot set up CMP context"); + goto err; + } + for (i = 0; i < opt_repeat; i++) { + /* everything is ready, now connect and perform the command! */ + switch (opt_cmd) { + case CMP_IR: + newcert = OSSL_CMP_exec_IR_ses(cmp_ctx); + if (newcert != NULL) + ret = 1; + break; + case CMP_KUR: + newcert = OSSL_CMP_exec_KUR_ses(cmp_ctx); + if (newcert != NULL) + ret = 1; + break; + case CMP_CR: + newcert = OSSL_CMP_exec_CR_ses(cmp_ctx); + if (newcert != NULL) + ret = 1; + break; + case CMP_P10CR: + newcert = OSSL_CMP_exec_P10CR_ses(cmp_ctx); + if (newcert != NULL) + ret = 1; + break; + case CMP_RR: + ret = OSSL_CMP_exec_RR_ses(cmp_ctx); + break; + case CMP_GENM: + { + STACK_OF(OSSL_CMP_ITAV) *itavs; + + if (opt_infotype != NID_undef) { + OSSL_CMP_ITAV *itav = + OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL); + if (itav == NULL) + goto err; + OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav); + } + + if ((itavs = OSSL_CMP_exec_GENM_ses(cmp_ctx)) != NULL) { + print_itavs(itavs); + sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free); + ret = 1; + } + break; + } + default: + break; + } + if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted) + goto err; /* we got no response, maybe even did not send request */ + + print_status(); + if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx), + opt_extracertsout, "extra") < 0) + ret = 0; + if (!ret) + goto err; + ret = 0; + if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_caPubs(cmp_ctx), + opt_cacertsout, "CA") < 0) + goto err; + if (newcert != NULL) { + STACK_OF(X509) *certs = sk_X509_new_null(); + + if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) { + sk_X509_free(certs); + goto err; + } + if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0) + goto err; + } + if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx), + opt_chainout, "chain") < 0) + goto err; + + if (!OSSL_CMP_CTX_reinit(cmp_ctx)) + goto err; + } + ret = 1; + + err: + /* in case we ended up here on error without proper cleaning */ + cleanse(opt_keypass); + cleanse(opt_newkeypass); + cleanse(opt_otherpass); +#ifndef OPENSSL_NO_SOCK + cleanse(opt_tls_keypass); +#endif + cleanse(opt_secret); + cleanse(opt_srv_keypass); + cleanse(opt_srv_secret); + + if (ret != 1) + OSSL_CMP_CTX_print_errors(cmp_ctx); + + if (cmp_ctx != NULL) { +#ifndef OPENSSL_NO_SOCK + APP_HTTP_TLS_INFO *info = OSSL_CMP_CTX_get_http_cb_arg(cmp_ctx); + +#endif + ossl_cmp_mock_srv_free(OSSL_CMP_CTX_get_transfer_cb_arg(cmp_ctx)); + X509_STORE_free(OSSL_CMP_CTX_get_certConf_cb_arg(cmp_ctx)); + /* cannot free info already here, as it may be used indirectly by: */ + OSSL_CMP_CTX_free(cmp_ctx); +#ifndef OPENSSL_NO_SOCK + APP_HTTP_TLS_INFO_free(info); +#endif + } + X509_VERIFY_PARAM_free(vpm); + release_engine(engine); + + NCONF_free(conf); /* must not do as long as opt_... variables are used */ + OSSL_CMP_log_close(); + + return ret == 0 ? EXIT_FAILURE : EXIT_SUCCESS; /* ret == -1 for -help */ +} diff --git a/apps/cms.c b/apps/cms.c --- a/apps/cms.c +++ b/apps/cms.c @@ -1,7 +1,7 @@ /* - * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -14,43 +14,41 @@ #include "apps.h" #include "progs.h" -#ifndef OPENSSL_NO_CMS - -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include static int save_certs(char *signerfile, STACK_OF(X509) *signers); static int cms_cb(int ok, X509_STORE_CTX *ctx); static void receipt_request_print(CMS_ContentInfo *cms); -static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) - *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) - *rr_from); +static CMS_ReceiptRequest +*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, + STACK_OF(OPENSSL_STRING) *rr_from); static int cms_set_pkey_param(EVP_PKEY_CTX *pctx, STACK_OF(OPENSSL_STRING) *param); -# define SMIME_OP 0x10 -# define SMIME_IP 0x20 -# define SMIME_SIGNERS 0x40 -# define SMIME_ENCRYPT (1 | SMIME_OP) -# define SMIME_DECRYPT (2 | SMIME_IP) -# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) -# define SMIME_VERIFY (4 | SMIME_IP) -# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP) -# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) -# define SMIME_DATAOUT (7 | SMIME_IP) -# define SMIME_DATA_CREATE (8 | SMIME_OP) -# define SMIME_DIGEST_VERIFY (9 | SMIME_IP) -# define SMIME_DIGEST_CREATE (10 | SMIME_OP) -# define SMIME_UNCOMPRESS (11 | SMIME_IP) -# define SMIME_COMPRESS (12 | SMIME_OP) -# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP) -# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP) -# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP) -# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP) +#define SMIME_OP 0x100 +#define SMIME_IP 0x200 +#define SMIME_SIGNERS 0x400 +#define SMIME_ENCRYPT (1 | SMIME_OP) +#define SMIME_DECRYPT (2 | SMIME_IP) +#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) +#define SMIME_VERIFY (4 | SMIME_IP) +#define SMIME_RESIGN (5 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) +#define SMIME_SIGN_RECEIPT (6 | SMIME_IP | SMIME_OP) +#define SMIME_VERIFY_RECEIPT (7 | SMIME_IP) +#define SMIME_DIGEST_CREATE (8 | SMIME_OP) +#define SMIME_DIGEST_VERIFY (9 | SMIME_IP) +#define SMIME_COMPRESS (10 | SMIME_OP) +#define SMIME_UNCOMPRESS (11 | SMIME_IP) +#define SMIME_ENCRYPTED_ENCRYPT (12 | SMIME_OP) +#define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP) +#define SMIME_DATA_CREATE (14 | SMIME_OP) +#define SMIME_DATA_OUT (15 | SMIME_IP) +#define SMIME_CMSOUT (16 | SMIME_IP | SMIME_OP) static int verify_err = 0; @@ -63,9 +61,9 @@ }; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT, - OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN, + OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN, OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT, OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY, OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, @@ -75,151 +73,246 @@ OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF, OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT, OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE, - OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT, + OPT_CAPATH, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, + OPT_CONTENT, OPT_PRINT, OPT_NAMEOPT, OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE, OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM, OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP, - OPT_3DES_WRAP, OPT_ENGINE, + OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE, OPT_R_ENUM, + OPT_PROV_ENUM, OPT_CONFIG, OPT_V_ENUM, - OPT_CIPHER + OPT_CIPHER, + OPT_ORIGINATOR } OPTION_CHOICE; const OPTIONS cms_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, - {OPT_HELP_STR, 1, '-', - " cert.pem... recipient certs for encryption\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"}, {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, - {"outform", OPT_OUTFORM, 'c', - "Output format SMIME (default), PEM or DER"}, + + OPT_SECTION("General"), {"in", OPT_IN, '<', "Input file"}, {"out", OPT_OUT, '>', "Output file"}, + OPT_CONFIG_OPTION, + + OPT_SECTION("Operation"), {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, {"sign", OPT_SIGN, '-', "Sign message"}, - {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"}, - {"resign", OPT_RESIGN, '-', "Resign a signed message"}, {"verify", OPT_VERIFY, '-', "Verify signed message"}, - {"verify_retcode", OPT_VERIFY_RETCODE, '-'}, - {"verify_receipt", OPT_VERIFY_RECEIPT, '<'}, + {"resign", OPT_RESIGN, '-', "Resign a signed message"}, + {"sign_receipt", OPT_SIGN_RECEIPT, '-', + "Generate a signed receipt for a message"}, + {"verify_receipt", OPT_VERIFY_RECEIPT, '<', + "Verify receipts; exit if receipt signatures do not verify"}, + {"digest_create", OPT_DIGEST_CREATE, '-', + "Create a CMS \"DigestedData\" object"}, + {"digest_verify", OPT_DIGEST_VERIFY, '-', + "Verify a CMS \"DigestedData\" object and output it"}, + {"compress", OPT_COMPRESS, '-', "Create a CMS \"CompressedData\" object"}, + {"uncompress", OPT_UNCOMPRESS, '-', + "Uncompress a CMS \"CompressedData\" object"}, + {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-', + "Create CMS \"EncryptedData\" object using symmetric key"}, + {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-', + "Decrypt CMS \"EncryptedData\" object using symmetric key"}, + {"data_create", OPT_DATA_CREATE, '-', "Create a CMS \"Data\" object"}, + {"data_out", OPT_DATA_OUT, '-', "Copy CMS \"Data\" object to output"}, {"cmsout", OPT_CMSOUT, '-', "Output CMS structure"}, - {"data_out", OPT_DATA_OUT, '-'}, - {"data_create", OPT_DATA_CREATE, '-'}, - {"digest_verify", OPT_DIGEST_VERIFY, '-'}, - {"digest_create", OPT_DIGEST_CREATE, '-'}, - {"compress", OPT_COMPRESS, '-'}, - {"uncompress", OPT_UNCOMPRESS, '-'}, - {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'}, - {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'}, - {"debug_decrypt", OPT_DEBUG_DECRYPT, '-'}, - {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, - {"asciicrlf", OPT_ASCIICRLF, '-'}, - {"nointern", OPT_NOINTERN, '-', - "Don't search certificates in message for signer"}, - {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, - {"nocerts", OPT_NOCERTS, '-', - "Don't include signers certificate when signing"}, - {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, - {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, - {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, - {"binary", OPT_BINARY, '-', "Don't translate message to text"}, - {"keyid", OPT_KEYID, '-', "Use subject key identifier"}, - {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, - {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'}, - {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'}, + + OPT_SECTION("File format"), + {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, + {"outform", OPT_OUTFORM, 'c', + "Output format SMIME (default), PEM or DER"}, + {"rctform", OPT_RCTFORM, 'F', "Receipt file format"}, {"stream", OPT_INDEF, '-', "Enable CMS streaming"}, {"indef", OPT_INDEF, '-', "Same as -stream"}, {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, - {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" }, - {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"}, - {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" }, - {"receipt_request_all", OPT_RR_ALL, '-'}, - {"receipt_request_first", OPT_RR_FIRST, '-'}, - {"rctform", OPT_RCTFORM, 'F', "Receipt file format"}, + {"binary", OPT_BINARY, '-', + "Treat input as binary: do not translate to canonical form"}, + {"crlfeol", OPT_CRLFEOL, '-', + "Use CRLF as EOL termination instead of CR only" }, + {"asciicrlf", OPT_ASCIICRLF, '-', + "Perform CRLF canonicalisation when signing"}, + + OPT_SECTION("Keys and passwords"), + {"pwri_password", OPT_PWRI_PASSWORD, 's', + "Specific password for recipient"}, + {"secretkey", OPT_SECRETKEY, 's', + "Use specified hex-encoded key to decrypt/encrypt recipients or content"}, + {"secretkeyid", OPT_SECRETKEYID, 's', + "Identity of the -secretkey for CMS \"KEKRecipientInfo\" object"}, + {"inkey", OPT_INKEY, 's', + "Input private key (if not signer or recipient)"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"}, + {"keyform", OPT_KEYFORM, 'f', + "Input private key format (ENGINE, other values ignored)"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +#endif + OPT_PROV_OPTIONS, + OPT_R_OPTIONS, + + OPT_SECTION("Encryption and decryption"), + {"originator", OPT_ORIGINATOR, 's', "Originator certificate file"}, + {"recip", OPT_RECIP, '<', "Recipient cert file"}, + {"cert...", OPT_PARAM, '.', + "Recipient certs (optional; used only when encrypting)"}, + {"", OPT_CIPHER, '-', + "The encryption algorithm to use (any supported cipher)"}, + {"wrap", OPT_WRAP, 's', + "Key wrap algorithm to use when encrypting with key agreement"}, + {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"}, + {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"}, + {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"}, + {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"}, + {"debug_decrypt", OPT_DEBUG_DECRYPT, '-', + "Disable MMA protection, return error if no recipient found (see doc)"}, + + OPT_SECTION("Signing"), + {"md", OPT_MD, 's', "Digest algorithm to use"}, + {"signer", OPT_SIGNER, 's', "Signer certificate input file"}, {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"cades", OPT_CADES, '-', + "Include signingCertificate attribute (CAdES-BES)"}, + {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, + {"nocerts", OPT_NOCERTS, '-', + "Don't include signer's certificate when signing"}, + {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, + {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"receipt_request_all", OPT_RR_ALL, '-', + "When signing, create a receipt request for all recipients"}, + {"receipt_request_first", OPT_RR_FIRST, '-', + "When signing, create a receipt request for first recipient"}, + {"receipt_request_from", OPT_RR_FROM, 's', + "Create signed receipt request with specified email address"}, + {"receipt_request_to", OPT_RR_TO, 's', + "Create signed receipt targeted to specified address"}, + + OPT_SECTION("Verification"), + {"signer", OPT_DUP, 's', "Signer certificate(s) output file"}, + {"content", OPT_CONTENT, '<', + "Supply or override content for detached signature"}, + {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-', + "Do not verify signed content signatures"}, + {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-', + "Do not verify signed attribute signatures"}, + {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, + {"nointern", OPT_NOINTERN, '-', + "Don't search certificates in message for signer"}, + {"cades", OPT_DUP, '-', "Check signingCertificate (CAdES-BES)"}, + {"verify_retcode", OPT_VERIFY_RETCODE, '-', + "Exit non-zero on verification failure"}, {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, - {"CApath", OPT_CAPATH, '/', "trusted certificates directory"}, + {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, + {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"}, {"no-CAfile", OPT_NOCAFILE, '-', "Do not load the default certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', "Do not load certificates from the default certificates directory"}, - {"content", OPT_CONTENT, '<', - "Supply or override content for detached signature"}, - {"print", OPT_PRINT, '-', - "For the -cmsout operation print out all fields of the CMS structure"}, - {"secretkey", OPT_SECRETKEY, 's'}, - {"secretkeyid", OPT_SECRETKEYID, 's'}, - {"pwri_password", OPT_PWRI_PASSWORD, 's'}, - {"econtent_type", OPT_ECONTENT_TYPE, 's'}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store"}, + + OPT_SECTION("Output"), + {"keyid", OPT_KEYID, '-', "Use subject key identifier"}, + {"econtent_type", OPT_ECONTENT_TYPE, 's', "OID for external content"}, + {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, + {"certsout", OPT_CERTSOUT, '>', "Certificate output file"}, {"to", OPT_TO, 's', "To address"}, {"from", OPT_FROM, 's', "From address"}, {"subject", OPT_SUBJECT, 's', "Subject"}, - {"signer", OPT_SIGNER, 's', "Signer certificate file"}, - {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"}, - {"certsout", OPT_CERTSOUT, '>', "Certificate output file"}, - {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, - {"inkey", OPT_INKEY, 's', - "Input private key (if not signer or recipient)"}, - {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"}, - {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"}, - {"receipt_request_from", OPT_RR_FROM, 's'}, - {"receipt_request_to", OPT_RR_TO, 's'}, - {"", OPT_CIPHER, '-', "Any supported cipher"}, - OPT_R_OPTIONS, + + OPT_SECTION("Printing"), + {"noout", OPT_NOOUT, '-', + "For the -cmsout operation do not output the parsed CMS structure"}, + {"print", OPT_PRINT, '-', + "For the -cmsout operation print out all fields of the CMS structure"}, + {"nameopt", OPT_NAMEOPT, 's', + "For the -print option specifies various strings printing options"}, + {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" }, + OPT_V_OPTIONS, - {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"}, - {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"}, - {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"}, -# ifndef OPENSSL_NO_DES - {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"}, -# endif -# ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, -# endif {NULL} }; +static CMS_ContentInfo *load_content_info(int informat, BIO *in, int flags, + BIO **indata, const char *name) +{ + CMS_ContentInfo *ret, *ci; + + ret = CMS_ContentInfo_new_ex(app_get0_libctx(), app_get0_propq()); + if (ret == NULL) { + BIO_printf(bio_err, "Error allocating CMS_contentinfo\n"); + return NULL; + } + switch (informat) { + case FORMAT_SMIME: + ci = SMIME_read_CMS_ex(in, flags, indata, &ret); + break; + case FORMAT_PEM: + ci = PEM_read_bio_CMS(in, &ret, NULL, NULL); + break; + case FORMAT_ASN1: + ci = d2i_CMS_bio(in, &ret); + break; + default: + BIO_printf(bio_err, "Bad input format for %s\n", name); + goto err; + } + if (ci == NULL) { + BIO_printf(bio_err, "Error reading %s Content Info\n", name); + goto err; + } + return ret; + err: + CMS_ContentInfo_free(ret); + return NULL; +} + int cms_main(int argc, char **argv) { + CONF *conf = NULL; ASN1_OBJECT *econtent_type = NULL; BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; CMS_ContentInfo *cms = NULL, *rcms = NULL; CMS_ReceiptRequest *rr = NULL; ENGINE *e = NULL; EVP_PKEY *key = NULL; - const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL; - const EVP_MD *sign_md = NULL; + EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL; + EVP_MD *sign_md = NULL; STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; - STACK_OF(X509) *encerts = NULL, *other = NULL; - X509 *cert = NULL, *recip = NULL, *signer = NULL; + STACK_OF(X509) *encerts = sk_X509_new_null(), *other = NULL; + X509 *cert = NULL, *recip = NULL, *signer = NULL, *originator = NULL; X509_STORE *store = NULL; - X509_VERIFY_PARAM *vpm = NULL; + X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new(); char *certfile = NULL, *keyfile = NULL, *contfile = NULL; - const char *CAfile = NULL, *CApath = NULL; - char *certsoutfile = NULL; - int noCAfile = 0, noCApath = 0; + const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL; + char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL; + int noCAfile = 0, noCApath = 0, noCAstore = 0; char *infile = NULL, *outfile = NULL, *rctfile = NULL; - char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL; + char *passinarg = NULL, *passin = NULL, *signerfile = NULL; + char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL; char *to = NULL, *from = NULL, *subject = NULL, *prog; cms_key_param *key_first = NULL, *key_param = NULL; - int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0; + int flags = CMS_DETACHED, binary_files = 0; + int noout = 0, print = 0, keyidx = -1, vpmtouched = 0; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1; - int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM; + int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_UNDEF; size_t secret_keylen = 0, secret_keyidlen = 0; unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; unsigned char *secret_key = NULL, *secret_keyid = NULL; long ltmp; const char *mime_eol = "\n"; OPTION_CHOICE o; + OSSL_LIB_CTX *libctx = app_get0_libctx(); - if ((vpm = X509_VERIFY_PARAM_new()) == NULL) - return 1; + if (encerts == NULL || vpm == NULL) + goto end; prog = opt_init(argc, argv, cms_options); while ((o = opt_next()) != OPT_EOF) { @@ -244,6 +337,7 @@ case OPT_OUT: outfile = opt_arg(); break; + case OPT_ENCRYPT: operation = SMIME_ENCRYPT; break; @@ -253,49 +347,50 @@ case OPT_SIGN: operation = SMIME_SIGN; break; - case OPT_SIGN_RECEIPT: - operation = SMIME_SIGN_RECEIPT; + case OPT_VERIFY: + operation = SMIME_VERIFY; break; case OPT_RESIGN: operation = SMIME_RESIGN; break; - case OPT_VERIFY: - operation = SMIME_VERIFY; - break; - case OPT_VERIFY_RETCODE: - verify_retcode = 1; + case OPT_SIGN_RECEIPT: + operation = SMIME_SIGN_RECEIPT; break; case OPT_VERIFY_RECEIPT: operation = SMIME_VERIFY_RECEIPT; rctfile = opt_arg(); break; - case OPT_CMSOUT: - operation = SMIME_CMSOUT; - break; - case OPT_DATA_OUT: - operation = SMIME_DATAOUT; + case OPT_VERIFY_RETCODE: + verify_retcode = 1; break; - case OPT_DATA_CREATE: - operation = SMIME_DATA_CREATE; + case OPT_DIGEST_CREATE: + operation = SMIME_DIGEST_CREATE; break; case OPT_DIGEST_VERIFY: operation = SMIME_DIGEST_VERIFY; break; - case OPT_DIGEST_CREATE: - operation = SMIME_DIGEST_CREATE; - break; case OPT_COMPRESS: operation = SMIME_COMPRESS; break; case OPT_UNCOMPRESS: operation = SMIME_UNCOMPRESS; break; + case OPT_ED_ENCRYPT: + operation = SMIME_ENCRYPTED_ENCRYPT; + break; case OPT_ED_DECRYPT: operation = SMIME_ENCRYPTED_DECRYPT; break; - case OPT_ED_ENCRYPT: - operation = SMIME_ENCRYPTED_ENCRYPT; + case OPT_DATA_CREATE: + operation = SMIME_DATA_CREATE; + break; + case OPT_DATA_OUT: + operation = SMIME_DATA_OUT; break; + case OPT_CMSOUT: + operation = SMIME_CMSOUT; + break; + case OPT_DEBUG_DECRYPT: flags |= CMS_DEBUG_DECRYPT; break; @@ -326,6 +421,9 @@ case OPT_BINARY: flags |= CMS_BINARY; break; + case OPT_CADES: + flags |= CMS_CADES; + break; case OPT_KEYID: flags |= CMS_USE_KEYID; break; @@ -361,14 +459,9 @@ rr_allorfirst = 1; break; case OPT_RCTFORM: - if (rctformat == FORMAT_SMIME) - rcms = SMIME_read_CMS(rctin, NULL); - else if (rctformat == FORMAT_PEM) - rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); - else if (rctformat == FORMAT_ASN1) - if (!opt_format(opt_arg(), - OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat)) - goto opthelp; + if (!opt_format(opt_arg(), + OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat)) + goto opthelp; break; case OPT_CERTFILE: certfile = opt_arg(); @@ -379,12 +472,18 @@ case OPT_CAPATH: CApath = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_NOCAPATH: noCApath = 1; break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_IN: infile = opt_arg(); break; @@ -406,6 +505,10 @@ case OPT_PRINT: noout = print = 1; break; + case OPT_NAMEOPT: + if (!set_nameopt(opt_arg())) + goto opthelp; + break; case OPT_SECRETKEY: if (secret_key != NULL) { BIO_printf(bio_err, "Invalid key (supplied twice) %s\n", @@ -466,8 +569,7 @@ certsoutfile = opt_arg(); break; case OPT_MD: - if (!opt_md(opt_arg(), &sign_md)) - goto end; + digestname = opt_arg(); break; case OPT_SIGNER: /* If previous -signer argument add signer to list */ @@ -486,6 +588,9 @@ } signerfile = opt_arg(); break; + case OPT_ORIGINATOR: + originatorfile = opt_arg(); + break; case OPT_INKEY: /* If previous -inkey argument add signer to list */ if (keyfile != NULL) { @@ -511,9 +616,7 @@ break; case OPT_RECIP: if (operation == SMIME_ENCRYPT) { - if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL) - goto end; - cert = load_cert(opt_arg(), FORMAT_PEM, + cert = load_cert(opt_arg(), FORMAT_UNDEF, "recipient certificate file"); if (cert == NULL) goto end; @@ -524,13 +627,12 @@ } break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &cipher)) - goto end; + ciphername = opt_unknown(); break; case OPT_KEYOPT: keyidx = -1; if (operation == SMIME_ENCRYPT) { - if (encerts != NULL) + if (sk_X509_num(encerts) > 0) keyidx += sk_X509_num(encerts); } else { if (keyfile != NULL || signerfile != NULL) @@ -568,22 +670,43 @@ if (!opt_rand(o)) goto end; break; - case OPT_3DES_WRAP: -# ifndef OPENSSL_NO_DES - wrap_cipher = EVP_des_ede3_wrap(); -# endif + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; break; - case OPT_AES128_WRAP: - wrap_cipher = EVP_aes_128_wrap(); + case OPT_CONFIG: + conf = app_load_config_modules(opt_arg()); + if (conf == NULL) + goto end; break; - case OPT_AES192_WRAP: - wrap_cipher = EVP_aes_192_wrap(); + case OPT_WRAP: + wrapname = opt_arg(); break; + case OPT_AES128_WRAP: + case OPT_AES192_WRAP: case OPT_AES256_WRAP: - wrap_cipher = EVP_aes_256_wrap(); + case OPT_3DES_WRAP: + wrapname = opt_flag() + 1; break; } } + if (!app_RAND_load()) + goto end; + + if (digestname != NULL) { + if (!opt_md(digestname, &sign_md)) + goto end; + } + if (ciphername != NULL) { + if (!opt_cipher_any(ciphername, &cipher)) + goto end; + } + if (wrapname != NULL) { + if (!opt_cipher_any(wrapname, &wrap_cipher)) + goto end; + } + + /* Remaining args are files to process. */ argc = opt_num_rest(); argv = opt_rest(); @@ -601,6 +724,20 @@ goto opthelp; } + if ((flags & CMS_CADES) != 0) { + if ((flags & CMS_NOATTR) != 0) { + BIO_puts(bio_err, "Incompatible options: " + "CAdES requires signed attributes\n"); + goto opthelp; + } + if (operation == SMIME_VERIFY + && (flags & (CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY)) != 0) { + BIO_puts(bio_err, "Incompatible options: CAdES validation requires" + " certs and signed attributes validations\n"); + goto opthelp; + } + } + if (operation & SMIME_SIGNERS) { if (keyfile != NULL && signerfile == NULL) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); @@ -633,7 +770,7 @@ } } else if (operation == SMIME_ENCRYPT) { if (*argv == NULL && secret_key == NULL - && pwri_pass == NULL && encerts == NULL) { + && pwri_pass == NULL && sk_X509_num(encerts) <= 0) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); goto opthelp; } @@ -649,25 +786,36 @@ ret = 2; - if (!(operation & SMIME_SIGNERS)) + if ((operation & SMIME_SIGNERS) == 0) { + if ((flags & CMS_DETACHED) == 0) + BIO_printf(bio_err, + "Warning: -nodetach option is ignored for non-signing operation\n"); + flags &= ~CMS_DETACHED; + } + if ((operation & SMIME_IP) == 0 && contfile != NULL) + BIO_printf(bio_err, + "Warning: -contfile option is ignored for the given operation\n"); - if (!(operation & SMIME_OP)) - if (flags & CMS_BINARY) + if ((flags & CMS_BINARY) != 0) { + if (!(operation & SMIME_OP)) outformat = FORMAT_BINARY; - - if (!(operation & SMIME_IP)) - if (flags & CMS_BINARY) + if (!(operation & SMIME_IP)) informat = FORMAT_BINARY; + if ((operation & SMIME_SIGNERS) != 0 && (flags & CMS_DETACHED) != 0) + binary_files = 1; + if ((operation & SMIME_IP) != 0 && contfile == NULL) + binary_files = 1; + } if (operation == SMIME_ENCRYPT) { if (!cipher) { -# ifndef OPENSSL_NO_DES - cipher = EVP_des_ede3_cbc(); -# else +#ifndef OPENSSL_NO_DES + cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); +#else BIO_printf(bio_err, "No cipher selected\n"); goto end; -# endif +#endif } if (secret_key && !secret_keyid) { @@ -675,44 +823,54 @@ goto end; } - if (*argv && encerts == NULL) - if ((encerts = sk_X509_new_null()) == NULL) - goto end; - while (*argv) { - if ((cert = load_cert(*argv, FORMAT_PEM, - "recipient certificate file")) == NULL) - goto end; - sk_X509_push(encerts, cert); - cert = NULL; - argv++; + if (*argv != NULL) { + if (operation == SMIME_ENCRYPT) { + for (; *argv != NULL; argv++) { + cert = load_cert(*argv, FORMAT_UNDEF, + "recipient certificate file"); + if (cert == NULL) + goto end; + sk_X509_push(encerts, cert); + cert = NULL; + } + } else { + BIO_printf(bio_err, "Warning: recipient certificate file parameters ignored for operation other than -encrypt\n"); + } } } if (certfile != NULL) { - if (!load_certs(certfile, &other, FORMAT_PEM, NULL, - "certificate file")) { + if (!load_certs(certfile, 0, &other, NULL, "certificate file")) { ERR_print_errors(bio_err); goto end; } } if (recipfile != NULL && (operation == SMIME_DECRYPT)) { - if ((recip = load_cert(recipfile, FORMAT_PEM, + if ((recip = load_cert(recipfile, FORMAT_UNDEF, "recipient certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; } } + if (originatorfile != NULL) { + if ((originator = load_cert(originatorfile, FORMAT_UNDEF, + "originator certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + if (operation == SMIME_SIGN_RECEIPT) { - if ((signer = load_cert(signerfile, FORMAT_PEM, + if ((signer = load_cert(signerfile, FORMAT_UNDEF, "receipt signer certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; } } - if (operation == SMIME_DECRYPT) { + if ((operation == SMIME_DECRYPT) || (operation == SMIME_ENCRYPT)) { if (keyfile == NULL) keyfile = recipfile; } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { @@ -723,31 +881,20 @@ } if (keyfile != NULL) { - key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + key = load_key(keyfile, keyform, 0, passin, e, "signing key"); if (key == NULL) goto end; } - in = bio_open_default(infile, 'r', informat); + in = bio_open_default(infile, 'r', + binary_files ? FORMAT_BINARY : informat); if (in == NULL) goto end; if (operation & SMIME_IP) { - if (informat == FORMAT_SMIME) { - cms = SMIME_read_CMS(in, &indata); - } else if (informat == FORMAT_PEM) { - cms = PEM_read_bio_CMS(in, NULL, NULL, NULL); - } else if (informat == FORMAT_ASN1) { - cms = d2i_CMS_bio(in, NULL); - } else { - BIO_printf(bio_err, "Bad input format for CMS file\n"); - goto end; - } - - if (cms == NULL) { - BIO_printf(bio_err, "Error reading S/MIME message\n"); + cms = load_content_info(informat, in, flags, &indata, "SMIME"); + if (cms == NULL) goto end; - } if (contfile != NULL) { BIO_free(indata); if ((indata = BIO_new_file(contfile, "rb")) == NULL) { @@ -770,34 +917,25 @@ if (rctfile != NULL) { char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r"; + if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) { BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile); goto end; } - if (rctformat == FORMAT_SMIME) { - rcms = SMIME_read_CMS(rctin, NULL); - } else if (rctformat == FORMAT_PEM) { - rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); - } else if (rctformat == FORMAT_ASN1) { - rcms = d2i_CMS_bio(rctin, NULL); - } else { - BIO_printf(bio_err, "Bad input format for receipt\n"); - goto end; - } - - if (rcms == NULL) { - BIO_printf(bio_err, "Error reading receipt\n"); + rcms = load_content_info(rctformat, rctin, 0, NULL, "receipt"); + if (rcms == NULL) goto end; - } } - out = bio_open_default(outfile, 'w', outformat); + out = bio_open_default(outfile, 'w', + binary_files ? FORMAT_BINARY : outformat); if (out == NULL) goto end; if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) { - if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) == NULL) goto end; X509_STORE_set_verify_cb(store, cms_cb); if (vpmtouched) @@ -807,39 +945,49 @@ ret = 3; if (operation == SMIME_DATA_CREATE) { - cms = CMS_data_create(in, flags); + cms = CMS_data_create_ex(in, flags, libctx, app_get0_propq()); } else if (operation == SMIME_DIGEST_CREATE) { - cms = CMS_digest_create(in, sign_md, flags); + cms = CMS_digest_create_ex(in, sign_md, flags, libctx, app_get0_propq()); } else if (operation == SMIME_COMPRESS) { cms = CMS_compress(in, -1, flags); } else if (operation == SMIME_ENCRYPT) { int i; flags |= CMS_PARTIAL; - cms = CMS_encrypt(NULL, in, cipher, flags); + cms = CMS_encrypt_ex(NULL, in, cipher, flags, libctx, app_get0_propq()); if (cms == NULL) goto end; for (i = 0; i < sk_X509_num(encerts); i++) { CMS_RecipientInfo *ri; cms_key_param *kparam; - int tflags = flags; + int tflags = flags | CMS_KEY_PARAM; + /* This flag enforces allocating the EVP_PKEY_CTX for the recipient here */ + EVP_PKEY_CTX *pctx; X509 *x = sk_X509_value(encerts, i); + int res; + for (kparam = key_first; kparam; kparam = kparam->next) { if (kparam->idx == i) { - tflags |= CMS_KEY_PARAM; break; } } - ri = CMS_add1_recipient_cert(cms, x, tflags); + ri = CMS_add1_recipient(cms, x, key, originator, tflags); if (ri == NULL) goto end; + + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (kparam != NULL) { - EVP_PKEY_CTX *pctx; - pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!cms_set_pkey_param(pctx, kparam->param)) goto end; } + + res = EVP_PKEY_CTX_ctrl(pctx, -1, -1, + EVP_PKEY_CTRL_CIPHER, + EVP_CIPHER_get_nid(cipher), NULL); + if (res <= 0 && res != -2) + goto end; + if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE - && wrap_cipher) { + && wrap_cipher != NULL) { EVP_CIPHER_CTX *wctx; wctx = CMS_RecipientInfo_kari_get0_ctx(ri); EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL); @@ -871,8 +1019,8 @@ goto end; } } else if (operation == SMIME_ENCRYPTED_ENCRYPT) { - cms = CMS_EncryptedData_encrypt(in, cipher, - secret_key, secret_keylen, flags); + cms = CMS_EncryptedData_encrypt_ex(in, cipher, secret_key, + secret_keylen, flags, libctx, app_get0_propq()); } else if (operation == SMIME_SIGN_RECEIPT) { CMS_ContentInfo *srcms = NULL; @@ -900,19 +1048,17 @@ flags |= CMS_STREAM; } flags |= CMS_PARTIAL; - cms = CMS_sign(NULL, NULL, other, in, flags); + cms = CMS_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq()); if (cms == NULL) goto end; if (econtent_type != NULL) CMS_set1_eContentType(cms, econtent_type); - if (rr_to != NULL) { - rr = make_receipt_request(rr_to, rr_allorfirst, rr_from); - if (rr == NULL) { - BIO_puts(bio_err, - "Signed Receipt Request Creation Error\n"); - goto end; - } + if (rr_to != NULL + && ((rr = make_receipt_request(rr_to, rr_allorfirst, rr_from)) + == NULL)) { + BIO_puts(bio_err, "Signed Receipt Request Creation Error\n"); + goto end; } } else { flags |= CMS_REUSE_DIGEST; @@ -924,16 +1070,17 @@ signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); - signer = load_cert(signerfile, FORMAT_PEM, "signer certificate"); + signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate"); if (signer == NULL) { ret = 2; goto end; } - key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + key = load_key(keyfile, keyform, 0, passin, e, "signing key"); if (key == NULL) { ret = 2; goto end; } + for (kparam = key_first; kparam; kparam = kparam->next) { if (kparam->idx == i) { tflags |= CMS_KEY_PARAM; @@ -983,7 +1130,7 @@ } if (key != NULL) { - if (!CMS_decrypt_set1_pkey(cms, key, recip)) { + if (!CMS_decrypt_set1_pkey_and_peer(cms, key, recip, originator)) { BIO_puts(bio_err, "Error decrypting CMS using private key\n"); goto end; } @@ -1000,7 +1147,7 @@ BIO_printf(bio_err, "Error decrypting CMS structure\n"); goto end; } - } else if (operation == SMIME_DATAOUT) { + } else if (operation == SMIME_DATA_OUT) { if (!CMS_data(cms, out, flags)) goto end; } else if (operation == SMIME_UNCOMPRESS) { @@ -1019,16 +1166,18 @@ goto end; } else if (operation == SMIME_VERIFY) { if (CMS_verify(cms, other, store, indata, out, flags) > 0) { - BIO_printf(bio_err, "Verification successful\n"); + BIO_printf(bio_err, "%s Verification successful\n", + (flags & CMS_CADES) != 0 ? "CAdES" : "CMS"); } else { - BIO_printf(bio_err, "Verification failure\n"); + BIO_printf(bio_err, "%s Verification failure\n", + (flags & CMS_CADES) != 0 ? "CAdES" : "CMS"); if (verify_retcode) ret = verify_err + 32; goto end; } if (signerfile != NULL) { - STACK_OF(X509) *signers; - signers = CMS_get0_signers(cms); + STACK_OF(X509) *signers = CMS_get0_signers(cms); + if (!save_certs(signerfile, signers)) { BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); @@ -1049,8 +1198,19 @@ } } else { if (noout) { - if (print) - CMS_ContentInfo_print_ctx(out, cms, 0, NULL); + if (print) { + ASN1_PCTX *pctx = NULL; + if (get_nameopt() != XN_FLAG_ONELINE) { + pctx = ASN1_PCTX_new(); + if (pctx != NULL) { /* Print anyway if malloc failed */ + ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT); + ASN1_PCTX_set_str_flags(pctx, get_nameopt()); + ASN1_PCTX_set_nm_flags(pctx, get_nameopt()); + } + } + CMS_ContentInfo_print_ctx(out, cms, 0, pctx); + ASN1_PCTX_free(pctx); + } } else if (outformat == FORMAT_SMIME) { if (to) BIO_printf(out, "To: %s%s", to, mime_eol); @@ -1103,6 +1263,9 @@ X509_free(recip); X509_free(signer); EVP_PKEY_free(key); + EVP_CIPHER_free(cipher); + EVP_CIPHER_free(wrap_cipher); + EVP_MD_free(sign_md); CMS_ContentInfo_free(cms); CMS_ContentInfo_free(rcms); release_engine(e); @@ -1111,6 +1274,7 @@ BIO_free(indata); BIO_free_all(out); OPENSSL_free(passin); + NCONF_free(conf); return ret; } @@ -1247,12 +1411,12 @@ return NULL; } -static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) - *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING) - *rr_from) +static CMS_ReceiptRequest +*make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, + STACK_OF(OPENSSL_STRING) *rr_from) { STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL; - CMS_ReceiptRequest *rr; + rct_to = make_names_stack(rr_to); if (rct_to == NULL) goto err; @@ -1263,9 +1427,8 @@ } else { rct_from = NULL; } - rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from, - rct_to); - return rr; + return CMS_ReceiptRequest_create0_ex(NULL, -1, rr_allorfirst, rct_from, + rct_to, app_get0_libctx()); err: sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free); return NULL; @@ -1288,5 +1451,3 @@ } return 1; } - -#endif diff --git a/apps/crl.c b/apps/crl.c --- a/apps/crl.c +++ b/apps/crl.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,22 +19,38 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_IN, OPT_OUTFORM, OPT_OUT, OPT_KEYFORM, OPT_KEY, OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT, - OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, - OPT_NOCAPATH, OPT_NOCAFILE, OPT_VERIFY, OPT_TEXT, OPT_HASH, OPT_HASH_OLD, - OPT_NOOUT, OPT_NAMEOPT, OPT_MD + OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, + OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_VERIFY, OPT_DATEOPT, OPT_TEXT, OPT_HASH, + OPT_HASH_OLD, OPT_NOOUT, OPT_NAMEOPT, OPT_MD, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS crl_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "Input format; default PEM"}, + {"verify", OPT_VERIFY, '-', "Verify CRL signature"}, + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file - default stdin"}, - {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, - {"out", OPT_OUT, '>', "output file - default stdout"}, - {"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"}, + {"inform", OPT_INFORM, 'F', "CRL input format (DER or PEM); has no effect"}, {"key", OPT_KEY, '<', "CRL signing Private key to use"}, + {"keyform", OPT_KEYFORM, 'F', "Private key file format (DER/PEM/P12); has no effect"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "output file - default stdout"}, + {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, + {"text", OPT_TEXT, '-', "Print out a text format version"}, + {"hash", OPT_HASH, '-', "Print hash value"}, +#ifndef OPENSSL_NO_MD5 + {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"}, +#endif + {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"}, + {"", OPT_MD, '-', "Any supported digest"}, + + OPT_SECTION("CRL"), {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, {"lastupdate", OPT_LASTUPDATE, '-', "Set lastUpdate field"}, {"nextupdate", OPT_NEXTUPDATE, '-', "Set nextUpdate field"}, @@ -43,20 +59,18 @@ {"crlnumber", OPT_CRLNUMBER, '-', "Print CRL number"}, {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded CRL signature (for test)" }, {"gendelta", OPT_GENDELTA, '<', "Other CRL to compare/diff to the Input one"}, + + OPT_SECTION("Certificate"), {"CApath", OPT_CAPATH, '/', "Verify CRL using certificates in dir"}, {"CAfile", OPT_CAFILE, '<', "Verify CRL using certificates in file name"}, + {"CAstore", OPT_CASTORE, ':', "Verify CRL using certificates in store URI"}, {"no-CAfile", OPT_NOCAFILE, '-', "Do not load the default certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', "Do not load certificates from the default certificates directory"}, - {"verify", OPT_VERIFY, '-', "Verify CRL signature"}, - {"text", OPT_TEXT, '-', "Print out a text format version"}, - {"hash", OPT_HASH, '-', "Print hash value"}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, - {"", OPT_MD, '-', "Any supported digest"}, -#ifndef OPENSSL_NO_MD5 - {"hash_old", OPT_HASH_OLD, '-', "Print old-style (MD5) hash value"}, -#endif + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store"}, + OPT_PROV_OPTIONS, {NULL} }; @@ -69,14 +83,16 @@ X509_LOOKUP *lookup = NULL; X509_OBJECT *xobj = NULL; EVP_PKEY *pkey; - const EVP_MD *digest = EVP_sha1(); + EVP_MD *digest = (EVP_MD *)EVP_sha1(); char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; - const char *CAfile = NULL, *CApath = NULL, *prog; + char *digestname = NULL; + const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog; OPTION_CHOICE o; int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF; int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0; - int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0; + int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0, noCAstore = 0; + unsigned long dateopt = ASN1_DTFLGS_RFC822; int i; #ifndef OPENSSL_NO_MD5 int hash_old = 0; @@ -109,7 +125,7 @@ outfile = opt_arg(); break; case OPT_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) goto opthelp; break; case OPT_KEY: @@ -126,12 +142,19 @@ CAfile = opt_arg(); do_ver = 1; break; + case OPT_CASTORE: + CAstore = opt_arg(); + do_ver = 1; + break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_HASH_OLD: #ifndef OPENSSL_NO_MD5 hash_old = ++num; @@ -140,6 +163,10 @@ case OPT_VERIFY: do_ver = 1; break; + case OPT_DATEOPT: + if (!set_dateopt(&dateopt, opt_arg())) + goto opthelp; + break; case OPT_TEXT: text = 1; break; @@ -156,7 +183,7 @@ nextupdate = ++num; break; case OPT_NOOUT: - noout = ++num; + noout = 1; break; case OPT_FINGERPRINT: fingerprint = ++num; @@ -172,20 +199,31 @@ goto opthelp; break; case OPT_MD: - if (!opt_md(opt_unknown(), &digest)) - goto opthelp; + digestname = opt_unknown(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No remaining args. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; - x = load_crl(infile, informat); + if (digestname != NULL) { + if (!opt_md(digestname, &digest)) + goto opthelp; + } + x = load_crl(infile, informat, 1, "CRL"); if (x == NULL) goto end; if (do_ver) { - if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) == NULL) goto end; lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) @@ -204,7 +242,7 @@ } pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); X509_OBJECT_free(xobj); - if (!pkey) { + if (pkey == NULL) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } @@ -218,17 +256,17 @@ BIO_printf(bio_err, "verify OK\n"); } - if (crldiff) { + if (crldiff != NULL) { X509_CRL *newcrl, *delta; if (!keyfile) { BIO_puts(bio_err, "Missing CRL signing key\n"); goto end; } - newcrl = load_crl(crldiff, informat); + newcrl = load_crl(crldiff, informat, 0, "other CRL"); if (!newcrl) goto end; pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); - if (!pkey) { + if (pkey == NULL) { X509_CRL_free(newcrl); goto end; } @@ -254,39 +292,54 @@ if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { - print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), - get_nameopt()); + print_name(bio_out, "issuer=", X509_CRL_get_issuer(x)); } if (crlnumber == i) { ASN1_INTEGER *crlnum; + crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { + BIO_puts(bio_out, "0x"); i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); - } else + } else { BIO_puts(bio_out, ""); + } BIO_printf(bio_out, "\n"); } if (hash == i) { - BIO_printf(bio_out, "%08lx\n", - X509_NAME_hash(X509_CRL_get_issuer(x))); + int ok; + unsigned long hash_value = + X509_NAME_hash_ex(X509_CRL_get_issuer(x), app_get0_libctx(), + app_get0_propq(), &ok); + + if (num > 1) + BIO_printf(bio_out, "issuer name hash="); + if (ok) { + BIO_printf(bio_out, "%08lx\n", hash_value); + } else { + BIO_puts(bio_out, ""); + goto end; + } } #ifndef OPENSSL_NO_MD5 if (hash_old == i) { + if (num > 1) + BIO_printf(bio_out, "issuer name old hash="); BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); - ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x)); + ASN1_TIME_print_ex(bio_out, X509_CRL_get0_lastUpdate(x), dateopt); BIO_printf(bio_out, "\n"); } if (nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get0_nextUpdate(x)) - ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x)); + ASN1_TIME_print_ex(bio_out, X509_CRL_get0_nextUpdate(x), dateopt); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); @@ -301,7 +354,7 @@ goto end; } BIO_printf(bio_out, "%s Fingerprint=", - OBJ_nid2sn(EVP_MD_type(digest))); + EVP_MD_get0_name(digest)); for (j = 0; j < (int)n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); @@ -335,6 +388,7 @@ if (ret != 0) ERR_print_errors(bio_err); BIO_free_all(out); + EVP_MD_free(digest); X509_CRL_free(x); X509_STORE_CTX_free(ctx); X509_STORE_free(store); diff --git a/apps/crl2p7.c b/apps/crl2p7.c deleted file mode 100644 --- a/apps/crl2p7.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include "apps.h" -#include "progs.h" -#include -#include -#include -#include -#include -#include - -static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile); - -typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE -} OPTION_CHOICE; - -const OPTIONS crl2pkcs7_options[] = { - {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, - {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, - {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, - {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"}, - {"certfile", OPT_CERTFILE, '<', - "File of chain of certs to a trusted CA; can be repeated"}, - {NULL} -}; - -int crl2pkcs7_main(int argc, char **argv) -{ - BIO *in = NULL, *out = NULL; - PKCS7 *p7 = NULL; - PKCS7_SIGNED *p7s = NULL; - STACK_OF(OPENSSL_STRING) *certflst = NULL; - STACK_OF(X509) *cert_stack = NULL; - STACK_OF(X509_CRL) *crl_stack = NULL; - X509_CRL *crl = NULL; - char *infile = NULL, *outfile = NULL, *prog, *certfile; - int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl = - 0; - OPTION_CHOICE o; - - prog = opt_init(argc, argv, crl2pkcs7_options); - while ((o = opt_next()) != OPT_EOF) { - switch (o) { - case OPT_EOF: - case OPT_ERR: - opthelp: - BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - goto end; - case OPT_HELP: - opt_help(crl2pkcs7_options); - ret = 0; - goto end; - case OPT_INFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) - goto opthelp; - break; - case OPT_OUTFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) - goto opthelp; - break; - case OPT_IN: - infile = opt_arg(); - break; - case OPT_OUT: - outfile = opt_arg(); - break; - case OPT_NOCRL: - nocrl = 1; - break; - case OPT_CERTFILE: - if ((certflst == NULL) - && (certflst = sk_OPENSSL_STRING_new_null()) == NULL) - goto end; - if (!sk_OPENSSL_STRING_push(certflst, opt_arg())) - goto end; - break; - } - } - argc = opt_num_rest(); - if (argc != 0) - goto opthelp; - - if (!nocrl) { - in = bio_open_default(infile, 'r', informat); - if (in == NULL) - goto end; - - if (informat == FORMAT_ASN1) - crl = d2i_X509_CRL_bio(in, NULL); - else if (informat == FORMAT_PEM) - crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - if (crl == NULL) { - BIO_printf(bio_err, "unable to load CRL\n"); - ERR_print_errors(bio_err); - goto end; - } - } - - if ((p7 = PKCS7_new()) == NULL) - goto end; - if ((p7s = PKCS7_SIGNED_new()) == NULL) - goto end; - p7->type = OBJ_nid2obj(NID_pkcs7_signed); - p7->d.sign = p7s; - p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data); - - if (!ASN1_INTEGER_set(p7s->version, 1)) - goto end; - - if (crl != NULL) { - if ((crl_stack = sk_X509_CRL_new_null()) == NULL) - goto end; - p7s->crl = crl_stack; - sk_X509_CRL_push(crl_stack, crl); - crl = NULL; /* now part of p7 for OPENSSL_freeing */ - } - - if (certflst != NULL) { - if ((cert_stack = sk_X509_new_null()) == NULL) - goto end; - p7s->cert = cert_stack; - - for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) { - certfile = sk_OPENSSL_STRING_value(certflst, i); - if (add_certs_from_file(cert_stack, certfile) < 0) { - BIO_printf(bio_err, "error loading certificates\n"); - ERR_print_errors(bio_err); - goto end; - } - } - } - - out = bio_open_default(outfile, 'w', outformat); - if (out == NULL) - goto end; - - if (outformat == FORMAT_ASN1) - i = i2d_PKCS7_bio(out, p7); - else if (outformat == FORMAT_PEM) - i = PEM_write_bio_PKCS7(out, p7); - if (!i) { - BIO_printf(bio_err, "unable to write pkcs7 object\n"); - ERR_print_errors(bio_err); - goto end; - } - ret = 0; - end: - sk_OPENSSL_STRING_free(certflst); - BIO_free(in); - BIO_free_all(out); - PKCS7_free(p7); - X509_CRL_free(crl); - - return ret; -} - -/*- - *---------------------------------------------------------------------- - * int add_certs_from_file - * - * Read a list of certificates to be checked from a file. - * - * Results: - * number of certs added if successful, -1 if not. - *---------------------------------------------------------------------- - */ -static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile) -{ - BIO *in = NULL; - int count = 0; - int ret = -1; - STACK_OF(X509_INFO) *sk = NULL; - X509_INFO *xi; - - in = BIO_new_file(certfile, "r"); - if (in == NULL) { - BIO_printf(bio_err, "error opening the file, %s\n", certfile); - goto end; - } - - /* This loads from a file, a stack of x509/crl/pkey sets */ - sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); - if (sk == NULL) { - BIO_printf(bio_err, "error reading the file, %s\n", certfile); - goto end; - } - - /* scan over it and pull out the CRL's */ - while (sk_X509_INFO_num(sk)) { - xi = sk_X509_INFO_shift(sk); - if (xi->x509 != NULL) { - sk_X509_push(stack, xi->x509); - xi->x509 = NULL; - count++; - } - X509_INFO_free(xi); - } - - ret = count; - end: - /* never need to OPENSSL_free x */ - BIO_free(in); - sk_X509_INFO_free(sk); - return ret; -} diff --git a/apps/crl2pkcs7.c b/apps/crl2pkcs7.c new file mode 100644 --- /dev/null +++ b/apps/crl2pkcs7.c @@ -0,0 +1,233 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include +#include + +static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile); + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE, + OPT_PROV_ENUM +} OPTION_CHOICE; + +const OPTIONS crl2pkcs7_options[] = { + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"nocrl", OPT_NOCRL, '-', "No crl to load, just certs from '-certfile'"}, + {"certfile", OPT_CERTFILE, '<', + "File of chain of certs to a trusted CA; can be repeated"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + + OPT_PROV_OPTIONS, + {NULL} +}; + +int crl2pkcs7_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + PKCS7 *p7 = NULL; + PKCS7_SIGNED *p7s = NULL; + STACK_OF(OPENSSL_STRING) *certflst = NULL; + STACK_OF(X509) *cert_stack = NULL; + STACK_OF(X509_CRL) *crl_stack = NULL; + X509_CRL *crl = NULL; + char *infile = NULL, *outfile = NULL, *prog, *certfile; + int i = 0, informat = FORMAT_PEM, outformat = FORMAT_PEM, ret = 1, nocrl = + 0; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, crl2pkcs7_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: + opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(crl2pkcs7_options); + ret = 0; + goto end; + case OPT_INFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + goto opthelp; + break; + case OPT_OUTFORM: + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) + goto opthelp; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_NOCRL: + nocrl = 1; + break; + case OPT_CERTFILE: + if ((certflst == NULL) + && (certflst = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (!sk_OPENSSL_STRING_push(certflst, opt_arg())) + goto end; + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; + } + } + + /* No remaining args. */ + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (!nocrl) { + in = bio_open_default(infile, 'r', informat); + if (in == NULL) + goto end; + + if (informat == FORMAT_ASN1) + crl = d2i_X509_CRL_bio(in, NULL); + else if (informat == FORMAT_PEM) + crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + if (crl == NULL) { + BIO_printf(bio_err, "unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if ((p7 = PKCS7_new()) == NULL) + goto end; + if ((p7s = PKCS7_SIGNED_new()) == NULL) + goto end; + p7->type = OBJ_nid2obj(NID_pkcs7_signed); + p7->d.sign = p7s; + p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data); + + if (!ASN1_INTEGER_set(p7s->version, 1)) + goto end; + + if (crl != NULL) { + if ((crl_stack = sk_X509_CRL_new_null()) == NULL) + goto end; + p7s->crl = crl_stack; + sk_X509_CRL_push(crl_stack, crl); + crl = NULL; /* now part of p7 for OPENSSL_freeing */ + } + + if (certflst != NULL) { + if ((cert_stack = sk_X509_new_null()) == NULL) + goto end; + p7s->cert = cert_stack; + + for (i = 0; i < sk_OPENSSL_STRING_num(certflst); i++) { + certfile = sk_OPENSSL_STRING_value(certflst, i); + if (add_certs_from_file(cert_stack, certfile) < 0) { + BIO_printf(bio_err, "error loading certificates\n"); + ERR_print_errors(bio_err); + goto end; + } + } + } + + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + + if (outformat == FORMAT_ASN1) + i = i2d_PKCS7_bio(out, p7); + else if (outformat == FORMAT_PEM) + i = PEM_write_bio_PKCS7(out, p7); + if (!i) { + BIO_printf(bio_err, "unable to write pkcs7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + sk_OPENSSL_STRING_free(certflst); + BIO_free(in); + BIO_free_all(out); + PKCS7_free(p7); + X509_CRL_free(crl); + + return ret; +} + +/*- + *---------------------------------------------------------------------- + * int add_certs_from_file + * + * Read a list of certificates to be checked from a file. + * + * Results: + * number of certs added if successful, -1 if not. + *---------------------------------------------------------------------- + */ +static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile) +{ + BIO *in = NULL; + int count = 0; + int ret = -1; + STACK_OF(X509_INFO) *sk = NULL; + X509_INFO *xi; + + in = BIO_new_file(certfile, "r"); + if (in == NULL) { + BIO_printf(bio_err, "error opening the file, %s\n", certfile); + goto end; + } + + /* This loads from a file, a stack of x509/crl/pkey sets */ + sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + if (sk == NULL) { + BIO_printf(bio_err, "error reading the file, %s\n", certfile); + goto end; + } + + /* scan over it and pull out the CRL's */ + while (sk_X509_INFO_num(sk)) { + xi = sk_X509_INFO_shift(sk); + if (xi->x509 != NULL) { + sk_X509_push(stack, xi->x509); + xi->x509 = NULL; + count++; + } + X509_INFO_free(xi); + } + + ret = count; + end: + /* never need to OPENSSL_free x */ + BIO_free(in); + sk_X509_INFO_free(sk); + return ret; +} diff --git a/apps/dgst.c b/apps/dgst.c --- a/apps/dgst.c +++ b/apps/dgst.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -24,7 +24,7 @@ #undef BUFSIZE #define BUFSIZE 1024*8 -int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, +int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, const char *file); @@ -36,49 +36,58 @@ }; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_LIST, + OPT_COMMON, + OPT_LIST, OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY, OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL, OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT, - OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, + OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN, OPT_DIGEST, - OPT_R_ENUM + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS dgst_options[] = { {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"}, - {OPT_HELP_STR, 1, '-', - " file... files to digest (default is stdin)\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"list", OPT_LIST, '-', "List digests"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, + {"engine_impl", OPT_ENGINE_IMPL, '-', + "Also use engine given by -engine for digest operations"}, +#endif + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + + OPT_SECTION("Output"), {"c", OPT_C, '-', "Print the digest with separating colons"}, {"r", OPT_R, '-', "Print the digest in coreutils format"}, {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"sign", OPT_SIGN, 's', "Sign digest using private key"}, - {"verify", OPT_VERIFY, 's', - "Verify a signature using public key"}, - {"prverify", OPT_PRVERIFY, 's', - "Verify a signature using private key"}, - {"signature", OPT_SIGNATURE, '<', "File with signature to verify"}, - {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"}, {"hex", OPT_HEX, '-', "Print as hex dump"}, {"binary", OPT_BINARY, '-', "Print in binary form"}, + {"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256"}, {"d", OPT_DEBUG, '-', "Print debug info"}, {"debug", OPT_DEBUG, '-', "Print debug info"}, - {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-', - "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"}, + + OPT_SECTION("Signing"), + {"sign", OPT_SIGN, 's', "Sign digest using private key"}, + {"verify", OPT_VERIFY, 's', "Verify a signature using public key"}, + {"prverify", OPT_PRVERIFY, 's', "Verify a signature using private key"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"signature", OPT_SIGNATURE, '<', "File with signature to verify"}, {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"}, {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"}, - {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"}, {"", OPT_DIGEST, '-', "Any supported digest"}, + {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-', + "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, - {"engine_impl", OPT_ENGINE_IMPL, '-', - "Also use engine given by -engine for digest operations"}, -#endif + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"file", 0, 0, "Files to digest (optional; default is stdin)"}, {NULL} }; @@ -89,21 +98,24 @@ EVP_PKEY *sigkey = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; char *hmac_key = NULL; - char *mac_name = NULL; + char *mac_name = NULL, *digestname = NULL; char *passinarg = NULL, *passin = NULL; - const EVP_MD *md = NULL, *m; + EVP_MD *md = NULL; const char *outfile = NULL, *keyfile = NULL, *prog = NULL; const char *sigfile = NULL; + const char *md_name = NULL; OPTION_CHOICE o; - int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0; - int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0; + int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0; + int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0; + int xoflen = 0; unsigned char *buf = NULL, *sigbuf = NULL; int engine_impl = 0; struct doall_dgst_digests dec; - prog = opt_progname(argv[0]); buf = app_malloc(BUFSIZE, "I/O buffer"); - md = EVP_get_digestbyname(prog); + md = (EVP_MD *)EVP_get_digestbyname(argv[0]); + if (md != NULL) + digestname = argv[0]; prog = opt_init(argc, argv, dgst_options); while ((o = opt_next()) != OPT_EOF) { @@ -115,7 +127,7 @@ goto end; case OPT_HELP: opt_help(dgst_options); - ret = 0; + ret = EXIT_SUCCESS; goto end; case OPT_LIST: BIO_printf(bio_out, "Supported digests:\n"); @@ -124,7 +136,7 @@ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, show_digests, &dec); BIO_printf(bio_out, "\n"); - ret = 0; + ret = EXIT_SUCCESS; goto end; case OPT_C: separator = 1; @@ -172,6 +184,9 @@ case OPT_BINARY: out_bin = 1; break; + case OPT_XOFLEN: + xoflen = atoi(opt_arg()); + break; case OPT_DEBUG: debug = 1; break; @@ -197,18 +212,29 @@ goto opthelp; break; case OPT_DIGEST: - if (!opt_md(opt_unknown(), &m)) - goto opthelp; - md = m; + digestname = opt_unknown(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; break; } } + + /* Remaining args are files to digest. */ argc = opt_num_rest(); argv = opt_rest(); if (keyfile != NULL && argc > 1) { BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog); goto end; } + if (!app_RAND_load()) + goto end; + + if (digestname != NULL) { + if (!opt_md(digestname, &md)) + goto opthelp; + } if (do_verify && sigfile == NULL) { BIO_printf(bio_err, @@ -220,13 +246,11 @@ in = BIO_new(BIO_s_file()); bmd = BIO_new(BIO_f_md()); - if ((in == NULL) || (bmd == NULL)) { - ERR_print_errors(bio_err); + if (in == NULL || bmd == NULL) goto end; - } if (debug) { - BIO_set_callback(in, BIO_debug_callback); + BIO_set_callback_ex(in, BIO_debug_callback_ex); /* needed for windows 3.1 */ BIO_set_callback_arg(in, (char *)bio_err); } @@ -248,7 +272,7 @@ goto end; if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) { - BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n"); + BIO_printf(bio_err, "MAC and signing key cannot both be specified\n"); goto end; } @@ -256,16 +280,16 @@ int type; if (want_pub) - sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file"); + sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key"); else - sigkey = load_key(keyfile, keyform, 0, passin, e, "key file"); + sigkey = load_key(keyfile, keyform, 0, passin, e, "private key"); if (sigkey == NULL) { /* * load_[pub]key() has already printed an appropriate message */ goto end; } - type = EVP_PKEY_id(sigkey); + type = EVP_PKEY_get_id(sigkey); if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) { /* * We implement PureEdDSA for these which doesn't have a separate @@ -278,36 +302,34 @@ if (mac_name != NULL) { EVP_PKEY_CTX *mac_ctx = NULL; - int r = 0; - if (!init_gen_str(&mac_ctx, mac_name, impl, 0)) - goto mac_end; + + if (!init_gen_str(&mac_ctx, mac_name, impl, 0, NULL, NULL)) + goto end; if (macopts != NULL) { - char *macopt; for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) { - macopt = sk_OPENSSL_STRING_value(macopts, i); + char *macopt = sk_OPENSSL_STRING_value(macopts, i); + if (pkey_ctrl_string(mac_ctx, macopt) <= 0) { - BIO_printf(bio_err, - "MAC parameter error \"%s\"\n", macopt); - ERR_print_errors(bio_err); - goto mac_end; + EVP_PKEY_CTX_free(mac_ctx); + BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt); + goto end; } } } - if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) { - BIO_puts(bio_err, "Error generating key\n"); - ERR_print_errors(bio_err); - goto mac_end; - } - r = 1; - mac_end: + + sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */); + /* Verbose output would make external-tests gost-engine fail */ EVP_PKEY_CTX_free(mac_ctx); - if (r == 0) - goto end; } if (hmac_key != NULL) { + if (md == NULL) { + md = (EVP_MD *)EVP_sha256(); + digestname = SN_sha256; + } sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl, - (unsigned char *)hmac_key, -1); + (unsigned char *)hmac_key, + strlen(hmac_key)); if (sigkey == NULL) goto end; } @@ -315,28 +337,37 @@ if (sigkey != NULL) { EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; - int r; + int res; + if (BIO_get_md_ctx(bmd, &mctx) <= 0) { BIO_printf(bio_err, "Error getting context\n"); - ERR_print_errors(bio_err); goto end; } if (do_verify) - r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); + if (impl == NULL) + res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname, + app_get0_libctx(), + app_get0_propq(), sigkey, NULL); + else + res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); else - r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); - if (!r) { + if (impl == NULL) + res = EVP_DigestSignInit_ex(mctx, &pctx, digestname, + app_get0_libctx(), + app_get0_propq(), sigkey, NULL); + else + res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); + if (res == 0) { BIO_printf(bio_err, "Error setting context\n"); - ERR_print_errors(bio_err); goto end; } if (sigopts != NULL) { - char *sigopt; for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { - sigopt = sk_OPENSSL_STRING_value(sigopts, i); + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pctx, sigopt) <= 0) { - BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Signature parameter error \"%s\"\n", + sigopt); goto end; } } @@ -347,32 +378,29 @@ EVP_MD_CTX *mctx = NULL; if (BIO_get_md_ctx(bmd, &mctx) <= 0) { BIO_printf(bio_err, "Error getting context\n"); - ERR_print_errors(bio_err); goto end; } if (md == NULL) - md = EVP_sha256(); + md = (EVP_MD *)EVP_sha256(); if (!EVP_DigestInit_ex(mctx, md, impl)) { BIO_printf(bio_err, "Error setting digest\n"); - ERR_print_errors(bio_err); goto end; } } if (sigfile != NULL && sigkey != NULL) { BIO *sigbio = BIO_new_file(sigfile, "rb"); + if (sigbio == NULL) { BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); - ERR_print_errors(bio_err); goto end; } - siglen = EVP_PKEY_size(sigkey); + siglen = EVP_PKEY_get_size(sigkey); sigbuf = app_malloc(siglen, "signature buffer"); siglen = BIO_read(sigbio, sigbuf, siglen); BIO_free(sigbio); if (siglen <= 0) { BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); - ERR_print_errors(bio_err); goto end; } } @@ -380,48 +408,62 @@ if (md == NULL) { EVP_MD_CTX *tctx; + BIO_get_md_ctx(bmd, &tctx); - md = EVP_MD_CTX_md(tctx); + md = EVP_MD_CTX_get1_md(tctx); + } + if (md != NULL) + md_name = EVP_MD_get0_name(md); + + if (xoflen > 0) { + if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) { + BIO_printf(bio_err, "Length can only be specified for XOF\n"); + goto end; + } + /* + * Signing using XOF is not supported by any algorithms currently since + * each algorithm only calls EVP_DigestFinal_ex() in their sign_final + * and verify_final methods. + */ + if (sigkey != NULL) { + BIO_printf(bio_err, "Signing key cannot be specified for XOF\n"); + goto end; + } } if (argc == 0) { BIO_set_fp(in, stdin, BIO_NOCLOSE); - ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, - siglen, NULL, NULL, "stdin"); + ret = do_fp(out, buf, inp, separator, out_bin, xoflen, sigkey, sigbuf, + siglen, NULL, md_name, "stdin"); } else { - const char *md_name = NULL, *sig_name = NULL; - if (!out_bin) { - if (sigkey != NULL) { - const EVP_PKEY_ASN1_METHOD *ameth; - ameth = EVP_PKEY_get0_asn1(sigkey); - if (ameth) - EVP_PKEY_asn1_get0_info(NULL, NULL, - NULL, NULL, &sig_name, ameth); - } - if (md != NULL) - md_name = EVP_MD_name(md); + const char *sig_name = NULL; + + if (out_bin == 0) { + if (sigkey != NULL) + sig_name = EVP_PKEY_get0_type_name(sigkey); } - ret = 0; + ret = EXIT_SUCCESS; for (i = 0; i < argc; i++) { - int r; if (BIO_read_filename(in, argv[i]) <= 0) { perror(argv[i]); - ret++; + ret = EXIT_FAILURE; continue; } else { - r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, - siglen, sig_name, md_name, argv[i]); + if (do_fp(out, buf, inp, separator, out_bin, xoflen, + sigkey, sigbuf, siglen, sig_name, md_name, argv[i])) + ret = EXIT_FAILURE; } - if (r) - ret = r; (void)BIO_reset(bmd); } } end: + if (ret != EXIT_SUCCESS) + ERR_print_errors(bio_err); OPENSSL_clear_free(buf, BUFSIZE); BIO_free(in); OPENSSL_free(passin); BIO_free_all(out); + EVP_MD_free(md); EVP_PKEY_free(sigkey); sk_OPENSSL_STRING_free(sigopts); sk_OPENSSL_STRING_free(macopts); @@ -444,7 +486,7 @@ return; /* Filter out message digests that we cannot use */ - md = EVP_get_digestbyname(name->name); + md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq()); if (md == NULL) return; @@ -496,20 +538,19 @@ } -int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, +int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, const char *file) { size_t len = BUFSIZE; - int i, backslash = 0, ret = 1; - unsigned char *sigbuf = NULL; + int i, backslash = 0, ret = EXIT_FAILURE; + unsigned char *allocated_buf = NULL; while (BIO_pending(bp) || !BIO_eof(bp)) { i = BIO_read(bp, (char *)buf, BUFSIZE); if (i < 0) { - BIO_printf(bio_err, "Read Error in %s\n", file); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Read error in %s\n", file); goto end; } if (i == 0) @@ -522,37 +563,52 @@ if (i > 0) { BIO_printf(out, "Verified OK\n"); } else if (i == 0) { - BIO_printf(out, "Verification Failure\n"); + BIO_printf(out, "Verification failure\n"); goto end; } else { - BIO_printf(bio_err, "Error Verifying Data\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error verifying data\n"); goto end; } - ret = 0; + ret = EXIT_SUCCESS; goto end; } if (key != NULL) { EVP_MD_CTX *ctx; - int pkey_len; + size_t tmplen; + BIO_get_md_ctx(bp, &ctx); - pkey_len = EVP_PKEY_size(key); - if (pkey_len > BUFSIZE) { - len = pkey_len; - sigbuf = app_malloc(len, "Signature buffer"); - buf = sigbuf; + if (!EVP_DigestSignFinal(ctx, NULL, &tmplen)) { + BIO_printf(bio_err, "Error getting maximum length of signed data\n"); + goto end; + } + if (tmplen > BUFSIZE) { + len = tmplen; + allocated_buf = app_malloc(len, "Signature buffer"); + buf = allocated_buf; } if (!EVP_DigestSignFinal(ctx, buf, &len)) { - BIO_printf(bio_err, "Error Signing Data\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error signing data\n"); + goto end; + } + } else if (xoflen > 0) { + EVP_MD_CTX *ctx; + + len = xoflen; + if (len > BUFSIZE) { + allocated_buf = app_malloc(len, "Digest buffer"); + buf = allocated_buf; + } + + BIO_get_md_ctx(bp, &ctx); + + if (!EVP_DigestFinalXOF(ctx, buf, len)) { + BIO_printf(bio_err, "Error Digesting Data\n"); goto end; } } else { len = BIO_gets(bp, (char *)buf, BUFSIZE); - if ((int)len < 0) { - ERR_print_errors(bio_err); + if ((int)len < 0) goto end; - } } if (binout) { @@ -587,10 +643,10 @@ BIO_printf(out, "\n"); } - ret = 0; + ret = EXIT_SUCCESS; end: - if (sigbuf != NULL) - OPENSSL_clear_free(sigbuf, len); + if (allocated_buf != NULL) + OPENSSL_clear_free(allocated_buf, len); return ret; } diff --git a/apps/dh1024.pem b/apps/dh1024.pem deleted file mode 100644 --- a/apps/dh1024.pem +++ /dev/null @@ -1,10 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR -Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL -/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC ------END DH PARAMETERS----- - -These are the 1024-bit DH parameters from "Internet Key Exchange -Protocol Version 2 (IKEv2)": https://tools.ietf.org/html/rfc5996 - -See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh2048.pem b/apps/dh2048.pem deleted file mode 100644 --- a/apps/dh2048.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg== ------END DH PARAMETERS----- - -These are the 2048-bit DH parameters from "More Modular Exponential -(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": -https://tools.ietf.org/html/rfc3526 - -See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dh4096.pem b/apps/dh4096.pem deleted file mode 100644 --- a/apps/dh4096.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI= ------END DH PARAMETERS----- - -These are the 4096-bit DH parameters from "More Modular Exponential -(MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)": -https://tools.ietf.org/html/rfc3526 - -See https://tools.ietf.org/html/rfc2412 for how they were generated. diff --git a/apps/dhparam.c b/apps/dhparam.c --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -1,13 +1,14 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include #include #include @@ -17,61 +18,73 @@ #include #include #include +#include #include #include #include - -#ifndef OPENSSL_NO_DSA -# include -#endif +#include +#include +#include +#include +#include #define DEFBITS 2048 -static int dh_cb(int p, int n, BN_GENCB *cb); +static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh); +static int gendh_cb(EVP_PKEY_CTX *ctx); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT, - OPT_DSAPARAM, OPT_C, OPT_2, OPT_5, - OPT_R_ENUM + OPT_DSAPARAM, OPT_2, OPT_3, OPT_5, + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS dhparam_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [flags] [numbits]\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"in", OPT_IN, '<', "Input file"}, - {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"}, - {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"}, - {"out", OPT_OUT, '>', "Output file"}, {"check", OPT_CHECK, '-', "Check the DH parameters"}, - {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"}, - {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"}, - OPT_R_OPTIONS, - {"C", OPT_C, '-', "Print C code"}, - {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, - {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, -#ifndef OPENSSL_NO_DSA +#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_DEPRECATED_3_0) {"dsaparam", OPT_DSAPARAM, '-', "Read or generate DSA parameters, convert to DH"}, #endif #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, #endif + + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'F', "Input format, DER or PEM"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format, DER or PEM"}, + {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"}, + {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"}, + {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, + {"3", OPT_3, '-', "Generate parameters using 3 as the generator value"}, + {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"numbits", 0, 0, "Number of bits if generating parameters (optional)"}, {NULL} }; int dhparam_main(int argc, char **argv) { BIO *in = NULL, *out = NULL; - DH *dh = NULL; + EVP_PKEY *pkey = NULL, *tmppkey = NULL; + EVP_PKEY_CTX *ctx = NULL; char *infile = NULL, *outfile = NULL, *prog; ENGINE *e = NULL; -#ifndef OPENSSL_NO_DSA int dsaparam = 0; -#endif - int i, text = 0, C = 0, ret = 1, num = 0, g = 0; + int text = 0, ret = 1, num = 0, g = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; OPTION_CHOICE o; @@ -111,16 +124,14 @@ text = 1; break; case OPT_DSAPARAM: -#ifndef OPENSSL_NO_DSA dsaparam = 1; -#endif - break; - case OPT_C: - C = 1; break; case OPT_2: g = 2; break; + case OPT_3: + g = 3; + break; case OPT_5: g = 5; break; @@ -131,24 +142,33 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* One optional argument, bitsize to generate. */ argc = opt_num_rest(); argv = opt_rest(); - - if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0)) + if (argc == 1) { + if (!opt_int(argv[0], &num) || num <= 0) + goto opthelp; + } else if (argc != 0) { + goto opthelp; + } + if (!app_RAND_load()) goto end; if (g && !num) num = DEFBITS; -#ifndef OPENSSL_NO_DSA if (dsaparam && g) { BIO_printf(bio_err, - "generator may not be chosen for DSA parameters\n"); + "Error, generator may not be chosen for DSA parameters\n"); goto end; } -#endif out = bio_open_default(outfile, 'w', outformat); if (out == NULL) @@ -159,216 +179,238 @@ g = 2; if (num) { + const char *alg = dsaparam ? "DSA" : "DH"; + + if (infile != NULL) { + BIO_printf(bio_err, "Warning, input file %s ignored\n", infile); + } - BN_GENCB *cb; - cb = BN_GENCB_new(); - if (cb == NULL) { - ERR_print_errors(bio_err); + ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), alg, app_get0_propq()); + if (ctx == NULL) { + BIO_printf(bio_err, + "Error, %s param generation context allocation failed\n", + alg); goto end; } + EVP_PKEY_CTX_set_cb(ctx, gendh_cb); + EVP_PKEY_CTX_set_app_data(ctx, bio_err); + BIO_printf(bio_err, + "Generating %s parameters, %d bit long %sprime\n", + alg, num, dsaparam ? "" : "safe "); - BN_GENCB_set(cb, dh_cb, bio_err); + if (EVP_PKEY_paramgen_init(ctx) <= 0) { + BIO_printf(bio_err, + "Error, unable to initialise %s parameters\n", + alg); + goto end; + } -#ifndef OPENSSL_NO_DSA if (dsaparam) { - DSA *dsa = DSA_new(); - - BIO_printf(bio_err, - "Generating DSA parameters, %d bit long prime\n", num); - if (dsa == NULL - || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, - cb)) { - DSA_free(dsa); - BN_GENCB_free(cb); - ERR_print_errors(bio_err); + if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) { + BIO_printf(bio_err, "Error, unable to set DSA prime length\n"); goto end; } - - dh = DSA_dup_DH(dsa); - DSA_free(dsa); - if (dh == NULL) { - BN_GENCB_free(cb); - ERR_print_errors(bio_err); + } else { + if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, num) <= 0) { + BIO_printf(bio_err, "Error, unable to set DH prime length\n"); goto end; } - } else -#endif - { - dh = DH_new(); - BIO_printf(bio_err, - "Generating DH parameters, %d bit long safe prime, generator %d\n", - num, g); - BIO_printf(bio_err, "This is going to take a long time\n"); - if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) { - BN_GENCB_free(cb); - ERR_print_errors(bio_err); + if (EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, g) <= 0) { + BIO_printf(bio_err, "Error, unable to set generator\n"); goto end; } } - BN_GENCB_free(cb); + tmppkey = app_paramgen(ctx, alg); + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + if (dsaparam) { + pkey = dsa_to_dh(tmppkey); + if (pkey == NULL) + goto end; + EVP_PKEY_free(tmppkey); + } else { + pkey = tmppkey; + } + tmppkey = NULL; } else { + OSSL_DECODER_CTX *decoderctx = NULL; + const char *keytype = "DH"; + int done; in = bio_open_default(infile, 'r', informat); if (in == NULL) goto end; -#ifndef OPENSSL_NO_DSA - if (dsaparam) { - DSA *dsa; - - if (informat == FORMAT_ASN1) - dsa = d2i_DSAparams_bio(in, NULL); - else /* informat == FORMAT_PEM */ - dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); - - if (dsa == NULL) { - BIO_printf(bio_err, "unable to load DSA parameters\n"); - ERR_print_errors(bio_err); - goto end; - } - - dh = DSA_dup_DH(dsa); - DSA_free(dsa); - if (dh == NULL) { - ERR_print_errors(bio_err); - goto end; - } - } else -#endif - { - if (informat == FORMAT_ASN1) { + do { + /* + * We assume we're done unless we explicitly want to retry and set + * this to 0 below. + */ + done = 1; + /* + * We set NULL for the keytype to allow any key type. We don't know + * if we're going to get DH or DHX (or DSA in the event of dsaparam). + * We check that we got one of those key types afterwards. + */ + decoderctx + = OSSL_DECODER_CTX_new_for_pkey(&tmppkey, + (informat == FORMAT_ASN1) + ? "DER" : "PEM", + NULL, + (informat == FORMAT_ASN1) + ? keytype : NULL, + OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + NULL, NULL); + + if (decoderctx != NULL + && !OSSL_DECODER_from_bio(decoderctx, in) + && informat == FORMAT_ASN1 + && strcmp(keytype, "DH") == 0) { + /* + * When reading DER we explicitly state the expected keytype + * because, unlike PEM, there is no header to declare what + * the contents of the DER file are. The decoders just try + * and guess. Unfortunately with DHX key types they may guess + * wrong and think we have a DSA keytype. Therefore we try + * both DH and DHX sequentially. + */ + keytype = "DHX"; /* - * We have no PEM header to determine what type of DH params it - * is. We'll just try both. + * BIO_reset() returns 0 for success for file BIOs only!!! + * This won't work for stdin (and never has done) */ - dh = d2i_DHparams_bio(in, NULL); - /* BIO_reset() returns 0 for success for file BIOs only!!! */ - if (dh == NULL && BIO_reset(in) == 0) - dh = d2i_DHxparams_bio(in, NULL); - } else { - /* informat == FORMAT_PEM */ - dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (BIO_reset(in) == 0) + done = 0; } + OSSL_DECODER_CTX_free(decoderctx); + } while (!done); + if (tmppkey == NULL) { + BIO_printf(bio_err, "Error, unable to load parameters\n"); + goto end; + } - if (dh == NULL) { - BIO_printf(bio_err, "unable to load DH parameters\n"); - ERR_print_errors(bio_err); + if (dsaparam) { + if (!EVP_PKEY_is_a(tmppkey, "DSA")) { + BIO_printf(bio_err, "Error, unable to load DSA parameters\n"); goto end; } + pkey = dsa_to_dh(tmppkey); + if (pkey == NULL) + goto end; + } else { + if (!EVP_PKEY_is_a(tmppkey, "DH") + && !EVP_PKEY_is_a(tmppkey, "DHX")) { + BIO_printf(bio_err, "Error, unable to load DH parameters\n"); + goto end; + } + pkey = tmppkey; + tmppkey = NULL; } - - /* dh != NULL */ } - if (text) { - DHparams_print(out, dh); - } + if (text) + EVP_PKEY_print_params(out, pkey, 4, NULL); if (check) { - if (!DH_check(dh, &i)) { - ERR_print_errors(bio_err); + ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq()); + if (ctx == NULL) { + BIO_printf(bio_err, "Error, failed to check DH parameters\n"); goto end; } - if (i & DH_CHECK_P_NOT_PRIME) - BIO_printf(bio_err, "WARNING: p value is not prime\n"); - if (i & DH_CHECK_P_NOT_SAFE_PRIME) - BIO_printf(bio_err, "WARNING: p value is not a safe prime\n"); - if (i & DH_CHECK_Q_NOT_PRIME) - BIO_printf(bio_err, "WARNING: q value is not a prime\n"); - if (i & DH_CHECK_INVALID_Q_VALUE) - BIO_printf(bio_err, "WARNING: q value is invalid\n"); - if (i & DH_CHECK_INVALID_J_VALUE) - BIO_printf(bio_err, "WARNING: j value is invalid\n"); - if (i & DH_UNABLE_TO_CHECK_GENERATOR) - BIO_printf(bio_err, - "WARNING: unable to check the generator value\n"); - if (i & DH_NOT_SUITABLE_GENERATOR) - BIO_printf(bio_err, "WARNING: the g value is not a generator\n"); - if (i == 0) - BIO_printf(bio_err, "DH parameters appear to be ok.\n"); - if (num != 0 && i != 0) { - /* - * We have generated parameters but DH_check() indicates they are - * invalid! This should never happen! - */ - BIO_printf(bio_err, "ERROR: Invalid parameters generated\n"); + if (EVP_PKEY_param_check(ctx) <= 0) { + BIO_printf(bio_err, "Error, invalid parameters generated\n"); goto end; } - } - if (C) { - unsigned char *data; - int len, bits; - const BIGNUM *pbn, *gbn; - - len = DH_size(dh); - bits = DH_bits(dh); - DH_get0_pqg(dh, &pbn, NULL, &gbn); - data = app_malloc(len, "print a BN"); - - BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits); - print_bignum_var(out, pbn, "dhp", bits, data); - print_bignum_var(out, gbn, "dhg", bits, data); - BIO_printf(out, " DH *dh = DH_new();\n" - " BIGNUM *p, *g;\n" - "\n" - " if (dh == NULL)\n" - " return NULL;\n"); - BIO_printf(out, " p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n", - bits, bits); - BIO_printf(out, " g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n", - bits, bits); - BIO_printf(out, " if (p == NULL || g == NULL\n" - " || !DH_set0_pqg(dh, p, NULL, g)) {\n" - " DH_free(dh);\n" - " BN_free(p);\n" - " BN_free(g);\n" - " return NULL;\n" - " }\n"); - if (DH_get_length(dh) > 0) - BIO_printf(out, - " if (!DH_set_length(dh, %ld)) {\n" - " DH_free(dh);\n" - " return NULL;\n" - " }\n", DH_get_length(dh)); - BIO_printf(out, " return dh;\n}\n"); - OPENSSL_free(data); + BIO_printf(bio_err, "DH parameters appear to be ok.\n"); } if (!noout) { - const BIGNUM *q; - DH_get0_pqg(dh, NULL, &q, NULL); - if (outformat == FORMAT_ASN1) { - if (q != NULL) - i = i2d_DHxparams_bio(out, dh); - else - i = i2d_DHparams_bio(out, dh); - } else if (q != NULL) { - i = PEM_write_bio_DHxparams(out, dh); - } else { - i = PEM_write_bio_DHparams(out, dh); - } - if (!i) { - BIO_printf(bio_err, "unable to write DH parameters\n"); - ERR_print_errors(bio_err); + OSSL_ENCODER_CTX *ectx = + OSSL_ENCODER_CTX_new_for_pkey(pkey, + OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + outformat == FORMAT_ASN1 + ? "DER" : "PEM", + NULL, NULL); + + if (ectx == NULL || !OSSL_ENCODER_to_bio(ectx, out)) { + OSSL_ENCODER_CTX_free(ectx); + BIO_printf(bio_err, "Error, unable to write DH parameters\n"); goto end; } + OSSL_ENCODER_CTX_free(ectx); } ret = 0; end: + if (ret != 0) + ERR_print_errors(bio_err); BIO_free(in); BIO_free_all(out); - DH_free(dh); + EVP_PKEY_free(pkey); + EVP_PKEY_free(tmppkey); + EVP_PKEY_CTX_free(ctx); release_engine(e); return ret; } -static int dh_cb(int p, int n, BN_GENCB *cb) +/* + * Historically we had the low level call DSA_dup_DH() to do this. + * That is now deprecated with no replacement. Since we still need to do this + * for backwards compatibility reasons, we do it "manually". + */ +static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh) +{ + OSSL_PARAM_BLD *tmpl = NULL; + OSSL_PARAM *params = NULL; + BIGNUM *bn_p = NULL, *bn_q = NULL, *bn_g = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + + if (!EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_P, &bn_p) + || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_Q, &bn_q) + || !EVP_PKEY_get_bn_param(dh, OSSL_PKEY_PARAM_FFC_G, &bn_g)) { + BIO_printf(bio_err, "Error, failed to set DH parameters\n"); + goto err; + } + + if ((tmpl = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, + bn_p) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, + bn_q) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, + bn_g) + || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { + BIO_printf(bio_err, "Error, failed to set DH parameters\n"); + goto err; + } + + ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DHX", app_get0_propq()); + if (ctx == NULL + || EVP_PKEY_fromdata_init(ctx) <= 0 + || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS, params) <= 0) { + BIO_printf(bio_err, "Error, failed to set DH parameters\n"); + goto err; + } + + err: + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(tmpl); + BN_free(bn_p); + BN_free(bn_q); + BN_free(bn_g); + return pkey; +} + +static int gendh_cb(EVP_PKEY_CTX *ctx) { + int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); static const char symbols[] = ".+*\n"; char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; - BIO_write(BN_GENCB_get_arg(cb), &c, 1); - (void)BIO_flush(BN_GENCB_get_arg(cb)); + BIO_write(b, &c, 1); + (void)BIO_flush(b); return 1; } diff --git a/apps/dsa.c b/apps/dsa.c --- a/apps/dsa.c +++ b/apps/dsa.c @@ -1,13 +1,14 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include #include #include @@ -21,29 +22,29 @@ #include #include #include +#include +#include +#include + +#ifndef OPENSSL_NO_RC4 +# define DEFAULT_PVK_ENCR_STRENGTH 2 +#else +# define DEFAULT_PVK_ENCR_STRENGTH 0 +#endif typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE, /* Do not change the order here; see case statements below */ OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN, - OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT + OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS dsa_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"}, - {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"}, - {"in", OPT_IN, 's', "Input key"}, - {"out", OPT_OUT, '>', "Output file"}, - {"noout", OPT_NOOUT, '-', "Don't print key out"}, - {"text", OPT_TEXT, '-', "Print the key in text"}, - {"modulus", OPT_MODULUS, '-', "Print the DSA public value"}, - {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, - {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, {"", OPT_CIPHER, '-', "Any supported cipher"}, #ifndef OPENSSL_NO_RC4 {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, @@ -53,24 +54,43 @@ #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, #endif + + OPT_SECTION("Input"), + {"in", OPT_IN, 's', "Input key"}, + {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/PVK); has no effect"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'f', "Output format, DER PEM PVK"}, + {"noout", OPT_NOOUT, '-', "Don't print key out"}, + {"text", OPT_TEXT, '-', "Print the key in text"}, + {"modulus", OPT_MODULUS, '-', "Print the DSA public value"}, + {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + + OPT_PROV_OPTIONS, {NULL} }; int dsa_main(int argc, char **argv) { BIO *out = NULL; - DSA *dsa = NULL; ENGINE *e = NULL; - const EVP_CIPHER *enc = NULL; + EVP_PKEY *pkey = NULL; + EVP_CIPHER *enc = NULL; char *infile = NULL, *outfile = NULL, *prog; char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; OPTION_CHOICE o; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; - int i, modulus = 0, pubin = 0, pubout = 0, ret = 1; -#ifndef OPENSSL_NO_RC4 - int pvk_encr = 2; -#endif + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0; + int modulus = 0, pubin = 0, pubout = 0, ret = 1; + int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH; int private = 0; + const char *output_type = NULL, *ciphername = NULL; + const char *output_structure = NULL; + int selection = 0; + OSSL_ENCODER_CTX *ectx = NULL; prog = opt_init(argc, argv, dsa_options); while ((o = opt_next()) != OPT_EOF) { @@ -131,15 +151,24 @@ pubout = 1; break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &enc)) + ciphername = opt_unknown(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) goto end; break; } } + + /* No extra args. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &enc)) + goto end; + } private = pubin || pubout ? 0 : 1; if (text && !pubin) private = 1; @@ -150,24 +179,20 @@ } BIO_printf(bio_err, "read DSA key\n"); - { - EVP_PKEY *pkey; - - if (pubin) - pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); - else - pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + if (pubin) + pkey = load_pubkey(infile, informat, 1, passin, e, "public key"); + else + pkey = load_key(infile, informat, 1, passin, e, "private key"); - if (pkey != NULL) { - dsa = EVP_PKEY_get1_DSA(pkey); - EVP_PKEY_free(pkey); - } - } - if (dsa == NULL) { + if (pkey == NULL) { BIO_printf(bio_err, "unable to load Key\n"); ERR_print_errors(bio_err); goto end; } + if (!EVP_PKEY_is_a(pkey, "DSA")) { + BIO_printf(bio_err, "Not a DSA key\n"); + goto end; + } out = bio_open_owner(outfile, outformat, private); if (out == NULL) @@ -175,7 +200,8 @@ if (text) { assert(pubin || private); - if (!DSA_print(out, dsa, 0)) { + if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) + || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) { perror(outfile); ERR_print_errors(bio_err); goto end; @@ -183,11 +209,16 @@ } if (modulus) { - const BIGNUM *pub_key = NULL; - DSA_get0_key(dsa, &pub_key, NULL); + BIGNUM *pub_key = NULL; + + if (!EVP_PKEY_get_bn_param(pkey, "pub", &pub_key)) { + ERR_print_errors(bio_err); + goto end; + } BIO_printf(out, "Public Key="); BN_print(out, pub_key); BIO_printf(out, "\n"); + BN_free(pub_key); } if (noout) { @@ -196,63 +227,83 @@ } BIO_printf(bio_err, "writing DSA key\n"); if (outformat == FORMAT_ASN1) { - if (pubin || pubout) { - i = i2d_DSA_PUBKEY_bio(out, dsa); - } else { - assert(private); - i = i2d_DSAPrivateKey_bio(out, dsa); - } + output_type = "DER"; } else if (outformat == FORMAT_PEM) { - if (pubin || pubout) { - i = PEM_write_bio_DSA_PUBKEY(out, dsa); - } else { - assert(private); - i = PEM_write_bio_DSAPrivateKey(out, dsa, enc, - NULL, 0, NULL, passout); - } -#ifndef OPENSSL_NO_RSA - } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { - EVP_PKEY *pk; - pk = EVP_PKEY_new(); - if (pk == NULL) - goto end; - - EVP_PKEY_set1_DSA(pk, dsa); - if (outformat == FORMAT_PVK) { - if (pubin) { - BIO_printf(bio_err, "PVK form impossible with public key input\n"); - EVP_PKEY_free(pk); - goto end; - } - assert(private); -# ifdef OPENSSL_NO_RC4 - BIO_printf(bio_err, "PVK format not supported\n"); - EVP_PKEY_free(pk); + output_type = "PEM"; + } else if (outformat == FORMAT_MSBLOB) { + output_type = "MSBLOB"; + } else if (outformat == FORMAT_PVK) { + if (pubin) { + BIO_printf(bio_err, "PVK form impossible with public key input\n"); goto end; -# else - i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); -# endif - } else if (pubin || pubout) { - i = i2b_PublicKey_bio(out, pk); - } else { - assert(private); - i = i2b_PrivateKey_bio(out, pk); } - EVP_PKEY_free(pk); -#endif + output_type = "PVK"; } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } - if (i <= 0) { - BIO_printf(bio_err, "unable to write private key\n"); - ERR_print_errors(bio_err); + + if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) { + if (pubout || pubin) + output_structure = "SubjectPublicKeyInfo"; + else + output_structure = "type-specific"; + } + + /* Select what you want in the output */ + if (pubout || pubin) { + selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + } else { + assert(private); + selection = (OSSL_KEYMGMT_SELECT_KEYPAIR + | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + } + + /* Perform the encoding */ + ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, output_type, + output_structure, NULL); + if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) { + BIO_printf(bio_err, "%s format not supported\n", output_type); + goto end; + } + + /* Passphrase setup */ + if (enc != NULL) + OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL); + + /* Default passphrase prompter */ + if (enc != NULL || outformat == FORMAT_PVK) { + OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL); + if (passout != NULL) + /* When passout given, override the passphrase prompter */ + OSSL_ENCODER_CTX_set_passphrase(ectx, + (const unsigned char *)passout, + strlen(passout)); + } + + /* PVK requires a bit more */ + if (outformat == FORMAT_PVK) { + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr); + if (!OSSL_ENCODER_CTX_set_params(ectx, params)) { + BIO_printf(bio_err, "invalid PVK encryption level\n"); + goto end; + } + } + + if (!OSSL_ENCODER_to_bio(ectx, out)) { + BIO_printf(bio_err, "unable to write key\n"); goto end; } ret = 0; end: + if (ret != 0) + ERR_print_errors(bio_err); + OSSL_ENCODER_CTX_free(ectx); BIO_free_all(out); - DSA_free(dsa); + EVP_PKEY_free(pkey); + EVP_CIPHER_free(enc); release_engine(e); OPENSSL_free(passin); OPENSSL_free(passout); diff --git a/apps/dsaparam.c b/apps/dsaparam.c --- a/apps/dsaparam.c +++ b/apps/dsaparam.c @@ -1,15 +1,17 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include #include +#include "apps.h" #include #include #include "apps.h" @@ -21,39 +23,54 @@ #include #include -static int dsa_cb(int p, int n, BN_GENCB *cb); +static int verbose = 0; + +static int gendsa_cb(EVP_PKEY_CTX *ctx); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, - OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM + OPT_COMMON, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, + OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE, + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS dsaparam_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, - {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + + OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, {"text", OPT_TEXT, '-', "Print as text"}, - {"C", OPT_C, '-', "Output C code"}, {"noout", OPT_NOOUT, '-', "No output"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, {"genkey", OPT_GENKEY, '-', "Generate a DSA key"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"}, -#endif + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"numbits", 0, 0, "Number of bits if generating parameters (optional)"}, {NULL} }; int dsaparam_main(int argc, char **argv) { ENGINE *e = NULL; - DSA *dsa = NULL; - BIO *in = NULL, *out = NULL; - BN_GENCB *cb = NULL; + BIO *out = NULL; + EVP_PKEY *params = NULL, *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; int numbits = -1, num = 0, genkey = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, noout = 0; int ret = 1, i, text = 0, private = 0; char *infile = NULL, *outfile = NULL, *prog; OPTION_CHOICE o; @@ -90,9 +107,6 @@ case OPT_TEXT: text = 1; break; - case OPT_C: - C = 1; - break; case OPT_GENKEY: genkey = 1; break; @@ -100,29 +114,45 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_NOOUT: noout = 1; break; + case OPT_VERBOSE: + verbose = 1; + break; } } + + /* Optional arg is bitsize. */ argc = opt_num_rest(); argv = opt_rest(); - if (argc == 1) { if (!opt_int(argv[0], &num) || num < 0) - goto end; - /* generate a key */ - numbits = num; + goto opthelp; + } else if (argc != 0) { + goto opthelp; } + if (!app_RAND_load()) + goto end; + + /* generate a key */ + numbits = num; private = genkey ? 1 : 0; - in = bio_open_default(infile, 'r', informat); - if (in == NULL) - goto end; out = bio_open_owner(outfile, outformat, private); if (out == NULL) goto end; + ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DSA", app_get0_propq()); + if (ctx == NULL) { + BIO_printf(bio_err, + "Error, DSA parameter generation context allocation failed\n"); + goto end; + } if (numbits > 0) { if (numbits > OPENSSL_DSA_MAX_MODULUS_BITS) BIO_printf(bio_err, @@ -130,74 +160,34 @@ " Your key size is %d! Larger key size may behave not as expected.\n", OPENSSL_DSA_MAX_MODULUS_BITS, numbits); - cb = BN_GENCB_new(); - if (cb == NULL) { - BIO_printf(bio_err, "Error allocating BN_GENCB object\n"); - goto end; + EVP_PKEY_CTX_set_cb(ctx, gendsa_cb); + EVP_PKEY_CTX_set_app_data(ctx, bio_err); + if (verbose) { + BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", + num); + BIO_printf(bio_err, "This could take some time\n"); } - BN_GENCB_set(cb, dsa_cb, bio_err); - dsa = DSA_new(); - if (dsa == NULL) { - BIO_printf(bio_err, "Error allocating DSA object\n"); + if (EVP_PKEY_paramgen_init(ctx) <= 0) { + BIO_printf(bio_err, + "Error, DSA key generation paramgen init failed\n"); goto end; } - BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", - num); - BIO_printf(bio_err, "This could take some time\n"); - if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) { - ERR_print_errors(bio_err); - BIO_printf(bio_err, "Error, DSA key generation failed\n"); + if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, num) <= 0) { + BIO_printf(bio_err, + "Error, DSA key generation setting bit length failed\n"); goto end; } - } else if (informat == FORMAT_ASN1) { - dsa = d2i_DSAparams_bio(in, NULL); + params = app_paramgen(ctx, "DSA"); } else { - dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); + params = load_keyparams(infile, informat, 1, "DSA", "DSA parameters"); } - if (dsa == NULL) { - BIO_printf(bio_err, "unable to load DSA parameters\n"); - ERR_print_errors(bio_err); + if (params == NULL) { + /* Error message should already have been displayed */ goto end; } if (text) { - DSAparams_print(out, dsa); - } - - if (C) { - const BIGNUM *p = NULL, *q = NULL, *g = NULL; - unsigned char *data; - int len, bits_p; - - DSA_get0_pqg(dsa, &p, &q, &g); - len = BN_num_bytes(p); - bits_p = BN_num_bits(p); - - data = app_malloc(len + 20, "BN space"); - - BIO_printf(bio_out, "static DSA *get_dsa%d(void)\n{\n", bits_p); - print_bignum_var(bio_out, p, "dsap", bits_p, data); - print_bignum_var(bio_out, q, "dsaq", bits_p, data); - print_bignum_var(bio_out, g, "dsag", bits_p, data); - BIO_printf(bio_out, " DSA *dsa = DSA_new();\n" - " BIGNUM *p, *q, *g;\n" - "\n"); - BIO_printf(bio_out, " if (dsa == NULL)\n" - " return NULL;\n"); - BIO_printf(bio_out, " if (!DSA_set0_pqg(dsa, p = BN_bin2bn(dsap_%d, sizeof(dsap_%d), NULL),\n", - bits_p, bits_p); - BIO_printf(bio_out, " q = BN_bin2bn(dsaq_%d, sizeof(dsaq_%d), NULL),\n", - bits_p, bits_p); - BIO_printf(bio_out, " g = BN_bin2bn(dsag_%d, sizeof(dsag_%d), NULL))) {\n", - bits_p, bits_p); - BIO_printf(bio_out, " DSA_free(dsa);\n" - " BN_free(p);\n" - " BN_free(q);\n" - " BN_free(g);\n" - " return NULL;\n" - " }\n" - " return dsa;\n}\n"); - OPENSSL_free(data); + EVP_PKEY_print_params(out, params, 0, NULL); } if (outformat == FORMAT_ASN1 && genkey) @@ -205,49 +195,62 @@ if (!noout) { if (outformat == FORMAT_ASN1) - i = i2d_DSAparams_bio(out, dsa); + i = i2d_KeyParams_bio(out, params); else - i = PEM_write_bio_DSAparams(out, dsa); + i = PEM_write_bio_Parameters(out, params); if (!i) { - BIO_printf(bio_err, "unable to write DSA parameters\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error, unable to write DSA parameters\n"); goto end; } } if (genkey) { - DSA *dsakey; - - if ((dsakey = DSAparams_dup(dsa)) == NULL) + EVP_PKEY_CTX_free(ctx); + ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params, + app_get0_propq()); + if (ctx == NULL) { + BIO_printf(bio_err, + "Error, DSA key generation context allocation failed\n"); goto end; - if (!DSA_generate_key(dsakey)) { - ERR_print_errors(bio_err); - DSA_free(dsakey); + } + if (EVP_PKEY_keygen_init(ctx) <= 0) { + BIO_printf(bio_err, + "Error, unable to initialise for key generation\n"); goto end; } + pkey = app_keygen(ctx, "DSA", numbits, verbose); assert(private); if (outformat == FORMAT_ASN1) - i = i2d_DSAPrivateKey_bio(out, dsakey); + i = i2d_PrivateKey_bio(out, pkey); else - i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL, - NULL); - DSA_free(dsakey); + i = PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL); } ret = 0; end: - BN_GENCB_free(cb); - BIO_free(in); + if (ret != 0) + ERR_print_errors(bio_err); BIO_free_all(out); - DSA_free(dsa); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + EVP_PKEY_free(params); release_engine(e); return ret; } -static int dsa_cb(int p, int n, BN_GENCB *cb) +static int gendsa_cb(EVP_PKEY_CTX *ctx) { static const char symbols[] = ".+*\n"; - char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; + int p; + char c; + BIO *b; + + if (!verbose) + return 1; + + b = EVP_PKEY_CTX_get_app_data(ctx); + p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; - BIO_write(BN_GENCB_get_arg(cb), &c, 1); - (void)BIO_flush(BN_GENCB_get_arg(cb)); + BIO_write(b, &c, 1); + (void)BIO_flush(b); return 1; } diff --git a/apps/ec.c b/apps/ec.c --- a/apps/ec.c +++ b/apps/ec.c @@ -1,84 +1,84 @@ /* - * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ -#include -#include -#include #include -#include "apps.h" -#include "progs.h" -#include -#include +#include #include -#include - -static OPT_PAIR conv_forms[] = { - {"compressed", POINT_CONVERSION_COMPRESSED}, - {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, - {"hybrid", POINT_CONVERSION_HYBRID}, - {NULL} -}; +#include +#include +#include +#include +#include +#include -static OPT_PAIR param_enc[] = { - {"named_curve", OPENSSL_EC_NAMED_CURVE}, - {"explicit", 0}, - {NULL} -}; +#include "apps.h" +#include "progs.h" +#include "ec_common.h" typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER, - OPT_NO_PUBLIC, OPT_CHECK + OPT_NO_PUBLIC, OPT_CHECK, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS ec_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), {"in", OPT_IN, 's', "Input file"}, - {"inform", OPT_INFORM, 'f', "Input format - DER or PEM"}, + {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"}, + {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"check", OPT_CHECK, '-', "check key consistency"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, + {"param_enc", OPT_PARAM_ENC, 's', + "Specifies the way the ec parameters are encoded"}, + {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, + + OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output file"}, {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, {"noout", OPT_NOOUT, '-', "Don't print key out"}, {"text", OPT_TEXT, '-', "Print the key"}, {"param_out", OPT_PARAM_OUT, '-', "Print the elliptic curve parameters"}, - {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, {"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"}, - {"check", OPT_CHECK, '-', "check key consistency"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, - {"param_enc", OPT_PARAM_ENC, 's', - "Specifies the way the ec parameters are encoded"}, - {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, - {"", OPT_CIPHER, '-', "Any supported cipher"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + + OPT_PROV_OPTIONS, {NULL} }; int ec_main(int argc, char **argv) { - BIO *in = NULL, *out = NULL; + OSSL_ENCODER_CTX *ectx = NULL; + OSSL_DECODER_CTX *dctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *eckey = NULL; + BIO *out = NULL; ENGINE *e = NULL; - EC_KEY *eckey = NULL; - const EC_GROUP *group; - const EVP_CIPHER *enc = NULL; - point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; - char *infile = NULL, *outfile = NULL, *prog; + EVP_CIPHER *enc = NULL; + char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog; char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; OPTION_CHOICE o; - int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_form = 0, new_asn1_flag = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, noout = 0; - int pubin = 0, pubout = 0, param_out = 0, i, ret = 1, private = 0; - int no_public = 0, check = 0; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0; + int pubin = 0, pubout = 0, param_out = 0, ret = 1, private = 0; + int check = 0; + char *asn1_encoding = NULL; + char *point_format = NULL; + int no_public = 0; prog = opt_init(argc, argv, ec_options); while ((o = opt_next()) != OPT_EOF) { @@ -131,20 +131,17 @@ e = setup_engine(opt_arg(), 0); break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &enc)) - goto opthelp; + ciphername = opt_unknown(); break; case OPT_CONV_FORM: - if (!opt_pair(opt_arg(), conv_forms, &i)) + point_format = opt_arg(); + if (!opt_string(point_format, point_format_options)) goto opthelp; - new_form = 1; - form = i; break; case OPT_PARAM_ENC: - if (!opt_pair(opt_arg(), param_enc, &i)) + asn1_encoding = opt_arg(); + if (!opt_string(asn1_encoding, asn1_encoding_options)) goto opthelp; - new_asn1_flag = 1; - asn1_flag = i; break; case OPT_NO_PUBLIC: no_public = 1; @@ -152,12 +149,22 @@ case OPT_CHECK: check = 1; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &enc)) + goto opthelp; + } private = param_out || pubin || pubout ? 0 : 1; if (text && !pubin) private = 1; @@ -167,37 +174,15 @@ goto end; } - if (informat != FORMAT_ENGINE) { - in = bio_open_default(infile, 'r', informat); - if (in == NULL) - goto end; - } - BIO_printf(bio_err, "read EC key\n"); - if (informat == FORMAT_ASN1) { - if (pubin) - eckey = d2i_EC_PUBKEY_bio(in, NULL); - else - eckey = d2i_ECPrivateKey_bio(in, NULL); - } else if (informat == FORMAT_ENGINE) { - EVP_PKEY *pkey; - if (pubin) - pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); - else - pkey = load_key(infile, informat, 1, passin, e, "Private Key"); - if (pkey != NULL) { - eckey = EVP_PKEY_get1_EC_KEY(pkey); - EVP_PKEY_free(pkey); - } - } else { - if (pubin) - eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL); - else - eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, passin); - } + + if (pubin) + eckey = load_pubkey(infile, informat, 1, passin, e, "public key"); + else + eckey = load_key(infile, informat, 1, passin, e, "private key"); + if (eckey == NULL) { BIO_printf(bio_err, "unable to load Key\n"); - ERR_print_errors(bio_err); goto end; } @@ -205,74 +190,105 @@ if (out == NULL) goto end; - group = EC_KEY_get0_group(eckey); - - if (new_form) - EC_KEY_set_conv_form(eckey, form); + if (point_format + && !EVP_PKEY_set_utf8_string_param( + eckey, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + point_format)) { + BIO_printf(bio_err, "unable to set point conversion format\n"); + goto end; + } - if (new_asn1_flag) - EC_KEY_set_asn1_flag(eckey, asn1_flag); + if (asn1_encoding != NULL + && !EVP_PKEY_set_utf8_string_param( + eckey, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) { + BIO_printf(bio_err, "unable to set asn1 encoding format\n"); + goto end; + } - if (no_public) - EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + if (no_public) { + if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0)) { + BIO_printf(bio_err, "unable to disable public key encoding\n"); + goto end; + } + } else { + if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 1)) { + BIO_printf(bio_err, "unable to enable public key encoding\n"); + goto end; + } + } if (text) { assert(pubin || private); - if (!EC_KEY_print(out, eckey, 0)) { - perror(outfile); - ERR_print_errors(bio_err); + if ((pubin && EVP_PKEY_print_public(out, eckey, 0, NULL) <= 0) + || (!pubin && EVP_PKEY_print_private(out, eckey, 0, NULL) <= 0)) { + BIO_printf(bio_err, "unable to print EC key\n"); goto end; } } if (check) { - if (EC_KEY_check_key(eckey) == 1) { - BIO_printf(bio_err, "EC Key valid.\n"); - } else { - BIO_printf(bio_err, "EC Key Invalid!\n"); - ERR_print_errors(bio_err); + pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, NULL); + if (pctx == NULL) { + BIO_printf(bio_err, "unable to check EC key\n"); + goto end; } + if (EVP_PKEY_check(pctx) <= 0) + BIO_printf(bio_err, "EC Key Invalid!\n"); + else + BIO_printf(bio_err, "EC Key valid.\n"); + ERR_print_errors(bio_err); } - if (noout) { - ret = 0; - goto end; - } + if (!noout) { + int selection; + const char *output_type = outformat == FORMAT_ASN1 ? "DER" : "PEM"; + const char *output_structure = "type-specific"; - BIO_printf(bio_err, "writing EC key\n"); - if (outformat == FORMAT_ASN1) { + BIO_printf(bio_err, "writing EC key\n"); if (param_out) { - i = i2d_ECPKParameters_bio(out, group); + selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; } else if (pubin || pubout) { - i = i2d_EC_PUBKEY_bio(out, eckey); + selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS + | OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + output_structure = "SubjectPublicKeyInfo"; } else { + selection = OSSL_KEYMGMT_SELECT_ALL; assert(private); - i = i2d_ECPrivateKey_bio(out, eckey); } - } else { - if (param_out) { - i = PEM_write_bio_ECPKParameters(out, group); - } else if (pubin || pubout) { - i = PEM_write_bio_EC_PUBKEY(out, eckey); - } else { - assert(private); - i = PEM_write_bio_ECPrivateKey(out, eckey, enc, - NULL, 0, NULL, passout); + + ectx = OSSL_ENCODER_CTX_new_for_pkey(eckey, selection, + output_type, output_structure, + NULL); + if (enc != NULL) { + OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL); + /* Default passphrase prompter */ + OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL); + if (passout != NULL) + /* When passout given, override the passphrase prompter */ + OSSL_ENCODER_CTX_set_passphrase(ectx, + (const unsigned char *)passout, + strlen(passout)); + } + if (!OSSL_ENCODER_to_bio(ectx, out)) { + BIO_printf(bio_err, "unable to write EC key\n"); + goto end; } } - if (!i) { - BIO_printf(bio_err, "unable to write private key\n"); + ret = 0; +end: + if (ret != 0) ERR_print_errors(bio_err); - } else { - ret = 0; - } - end: - BIO_free(in); BIO_free_all(out); - EC_KEY_free(eckey); + EVP_PKEY_free(eckey); + EVP_CIPHER_free(enc); + OSSL_ENCODER_CTX_free(ectx); + OSSL_DECODER_CTX_free(dctx); + EVP_PKEY_CTX_free(pctx); release_engine(e); - OPENSSL_free(passin); - OPENSSL_free(passout); + if (passin != NULL) + OPENSSL_clear_free(passin, strlen(passin)); + if (passout != NULL) + OPENSSL_clear_free(passout, strlen(passout)); return ret; } diff --git a/apps/ecparam.c b/apps/ecparam.c --- a/apps/ecparam.c +++ b/apps/ecparam.c @@ -1,92 +1,115 @@ /* - * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "apps.h" #include "progs.h" -#include -#include -#include -#include -#include -#include +#include "ec_common.h" typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C, + OPT_COMMON, + OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME, - OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, - OPT_R_ENUM + OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, OPT_CHECK_NAMED, + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS ecparam_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, - {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + {"list_curves", OPT_LIST_CURVES, '-', + "Prints a list of all curve 'short names'"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + {"genkey", OPT_GENKEY, '-', "Generate ec key"}, {"in", OPT_IN, '<', "Input file - default stdin"}, + {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"}, + + OPT_SECTION("Output"), {"text", OPT_TEXT, '-', "Print the ec parameters in text form"}, - {"C", OPT_C, '-', "Print a 'C' function creating the parameters"}, + {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"}, + {"param_enc", OPT_PARAM_ENC, 's', + "Specifies the way the ec parameters are encoded"}, + + OPT_SECTION("Parameter"), {"check", OPT_CHECK, '-', "Validate the ec parameters"}, - {"list_curves", OPT_LIST_CURVES, '-', - "Prints a list of all curve 'short names'"}, + {"check_named", OPT_CHECK_NAMED, '-', + "Check that named EC curve parameters have not been modified"}, {"no_seed", OPT_NO_SEED, '-', "If 'explicit' parameters are chosen do not use the seed"}, - {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"}, {"name", OPT_NAME, 's', "Use the ec parameters with specified 'short name'"}, {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "}, - {"param_enc", OPT_PARAM_ENC, 's', - "Specifies the way the ec parameters are encoded"}, - {"genkey", OPT_GENKEY, '-', "Generate ec key"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + OPT_PROV_OPTIONS, {NULL} }; -static OPT_PAIR forms[] = { - {"compressed", POINT_CONVERSION_COMPRESSED}, - {"uncompressed", POINT_CONVERSION_UNCOMPRESSED}, - {"hybrid", POINT_CONVERSION_HYBRID}, - {NULL} -}; +static int list_builtin_curves(BIO *out) +{ + int ret = 0; + EC_builtin_curve *curves = NULL; + size_t n, crv_len = EC_get_builtin_curves(NULL, 0); -static OPT_PAIR encodings[] = { - {"named_curve", OPENSSL_EC_NAMED_CURVE}, - {"explicit", 0}, - {NULL} -}; + curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); + if (!EC_get_builtin_curves(curves, crv_len)) + goto end; + + for (n = 0; n < crv_len; n++) { + const char *comment = curves[n].comment; + const char *sname = OBJ_nid2sn(curves[n].nid); + + if (comment == NULL) + comment = "CURVE DESCRIPTION NOT AVAILABLE"; + if (sname == NULL) + sname = ""; + + BIO_printf(out, " %-10s: ", sname); + BIO_printf(out, "%s\n", comment); + } + ret = 1; +end: + OPENSSL_free(curves); + return ret; +} int ecparam_main(int argc, char **argv) { + EVP_PKEY_CTX *gctx_params = NULL, *gctx_key = NULL, *pctx = NULL; + EVP_PKEY *params_key = NULL, *key = NULL; + OSSL_ENCODER_CTX *ectx_key = NULL, *ectx_params = NULL; + OSSL_DECODER_CTX *dctx_params = NULL; ENGINE *e = NULL; - BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL; - BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL; - BIO *in = NULL, *out = NULL; - EC_GROUP *group = NULL; - point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; + BIO *out = NULL; char *curve_name = NULL; + char *asn1_encoding = NULL; + char *point_format = NULL; char *infile = NULL, *outfile = NULL, *prog; - unsigned char *buffer = NULL; OPTION_CHOICE o; - int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0; + int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0; int ret = 1, private = 0; - int list_curves = 0, no_seed = 0, check = 0, new_form = 0; - int text = 0, i, genkey = 0; + int no_seed = 0, check = 0, check_named = 0, text = 0, genkey = 0; + int list_curves = 0; prog = opt_init(argc, argv, ecparam_options); while ((o = opt_next()) != OPT_EOF) { @@ -117,12 +140,12 @@ case OPT_TEXT: text = 1; break; - case OPT_C: - C = 1; - break; case OPT_CHECK: check = 1; break; + case OPT_CHECK_NAMED: + check_named = 1; + break; case OPT_LIST_CURVES: list_curves = 1; break; @@ -136,15 +159,14 @@ curve_name = opt_arg(); break; case OPT_CONV_FORM: - if (!opt_pair(opt_arg(), forms, &new_form)) + point_format = opt_arg(); + if (!opt_string(point_format, point_format_options)) goto opthelp; - form = new_form; - new_form = 1; break; case OPT_PARAM_ENC: - if (!opt_pair(opt_arg(), encodings, &asn1_flag)) + asn1_encoding = opt_arg(); + if (!opt_string(asn1_encoding, asn1_encoding_options)) goto opthelp; - new_asn1_flag = 1; break; case OPT_GENKEY: genkey = 1; @@ -153,292 +175,178 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; } } + + /* No extra args. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (!app_RAND_load()) + goto end; + private = genkey ? 1 : 0; - in = bio_open_default(infile, 'r', informat); - if (in == NULL) - goto end; out = bio_open_owner(outfile, outformat, private); if (out == NULL) goto end; if (list_curves) { - EC_builtin_curve *curves = NULL; - size_t crv_len = EC_get_builtin_curves(NULL, 0); - size_t n; - - curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); - if (!EC_get_builtin_curves(curves, crv_len)) { - OPENSSL_free(curves); - goto end; - } - - for (n = 0; n < crv_len; n++) { - const char *comment; - const char *sname; - comment = curves[n].comment; - sname = OBJ_nid2sn(curves[n].nid); - if (comment == NULL) - comment = "CURVE DESCRIPTION NOT AVAILABLE"; - if (sname == NULL) - sname = ""; - - BIO_printf(out, " %-10s: ", sname); - BIO_printf(out, "%s\n", comment); - } - - OPENSSL_free(curves); - ret = 0; + if (list_builtin_curves(out)) + ret = 0; goto end; } if (curve_name != NULL) { - int nid; + OSSL_PARAM params[4]; + OSSL_PARAM *p = params; - /* - * workaround for the SECG curve names secp192r1 and secp256r1 (which - * are the same as the curves prime192v1 and prime256v1 defined in - * X9.62) - */ if (strcmp(curve_name, "secp192r1") == 0) { - BIO_printf(bio_err, "using curve name prime192v1 " - "instead of secp192r1\n"); - nid = NID_X9_62_prime192v1; + BIO_printf(bio_err, + "using curve name prime192v1 instead of secp192r1\n"); + curve_name = SN_X9_62_prime192v1; } else if (strcmp(curve_name, "secp256r1") == 0) { - BIO_printf(bio_err, "using curve name prime256v1 " - "instead of secp256r1\n"); - nid = NID_X9_62_prime256v1; - } else { - nid = OBJ_sn2nid(curve_name); + BIO_printf(bio_err, + "using curve name prime256v1 instead of secp256r1\n"); + curve_name = SN_X9_62_prime256v1; } - - if (nid == 0) - nid = EC_curve_nist2nid(curve_name); - - if (nid == 0) { - BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + curve_name, 0); + if (asn1_encoding != NULL) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, + asn1_encoding, 0); + if (point_format != NULL) + *p++ = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + point_format, 0); + *p = OSSL_PARAM_construct_end(); + + if (OPENSSL_strcasecmp(curve_name, "SM2") == 0) + gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "sm2", + app_get0_propq()); + else + gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "ec", + app_get0_propq()); + if (gctx_params == NULL + || EVP_PKEY_keygen_init(gctx_params) <= 0 + || EVP_PKEY_CTX_set_params(gctx_params, params) <= 0 + || EVP_PKEY_keygen(gctx_params, ¶ms_key) <= 0) { + BIO_printf(bio_err, "unable to generate key\n"); + goto end; + } + } else { + params_key = load_keyparams(infile, informat, 1, "EC", "EC parameters"); + if (params_key == NULL || !EVP_PKEY_is_a(params_key, "EC")) + goto end; + if (point_format + && !EVP_PKEY_set_utf8_string_param( + params_key, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + point_format)) { + BIO_printf(bio_err, "unable to set point conversion format\n"); goto end; } - group = EC_GROUP_new_by_curve_name(nid); - if (group == NULL) { - BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name); + if (asn1_encoding != NULL + && !EVP_PKEY_set_utf8_string_param( + params_key, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) { + BIO_printf(bio_err, "unable to set asn1 encoding format\n"); goto end; } - EC_GROUP_set_asn1_flag(group, asn1_flag); - EC_GROUP_set_point_conversion_form(group, form); - } else if (informat == FORMAT_ASN1) { - group = d2i_ECPKParameters_bio(in, NULL); - } else { - group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); } - if (group == NULL) { - BIO_printf(bio_err, "unable to load elliptic curve parameters\n"); - ERR_print_errors(bio_err); - goto end; - } - - if (new_form) - EC_GROUP_set_point_conversion_form(group, form); - if (new_asn1_flag) - EC_GROUP_set_asn1_flag(group, asn1_flag); - - if (no_seed) { - EC_GROUP_set_seed(group, NULL, 0); + if (no_seed + && !EVP_PKEY_set_octet_string_param(params_key, OSSL_PKEY_PARAM_EC_SEED, + NULL, 0)) { + BIO_printf(bio_err, "unable to clear seed\n"); + goto end; } - if (text) { - if (!ECPKParameters_print(out, group, 0)) - goto end; + if (text + && !EVP_PKEY_print_params(out, params_key, 0, NULL)) { + BIO_printf(bio_err, "unable to print params\n"); + goto end; } - if (check) { + if (check || check_named) { BIO_printf(bio_err, "checking elliptic curve parameters: "); - if (!EC_GROUP_check(group, NULL)) { - BIO_printf(bio_err, "failed\n"); - ERR_print_errors(bio_err); - goto end; - } - BIO_printf(bio_err, "ok\n"); - - } - - if (C) { - size_t buf_len = 0, tmp_len = 0; - const EC_POINT *point; - int is_prime, len = 0; - const EC_METHOD *meth = EC_GROUP_method_of(group); - if ((ec_p = BN_new()) == NULL - || (ec_a = BN_new()) == NULL - || (ec_b = BN_new()) == NULL - || (ec_gen = BN_new()) == NULL - || (ec_order = BN_new()) == NULL - || (ec_cofactor = BN_new()) == NULL) { - perror("Can't allocate BN"); - goto end; + if (check_named + && !EVP_PKEY_set_utf8_string_param(params_key, + OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, + OSSL_PKEY_EC_GROUP_CHECK_NAMED)) { + BIO_printf(bio_err, "unable to set check_type\n"); + goto end; } - - is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); - if (!is_prime) { - BIO_printf(bio_err, "Can only handle X9.62 prime fields\n"); + pctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key, + app_get0_propq()); + if (pctx == NULL || EVP_PKEY_param_check(pctx) <= 0) { + BIO_printf(bio_err, "failed\n"); goto end; } - - if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL)) - goto end; - - if ((point = EC_GROUP_get0_generator(group)) == NULL) - goto end; - if (!EC_POINT_point2bn(group, point, - EC_GROUP_get_point_conversion_form(group), - ec_gen, NULL)) - goto end; - if (!EC_GROUP_get_order(group, ec_order, NULL)) - goto end; - if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) - goto end; - - if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor) - goto end; - - len = BN_num_bits(ec_order); - - if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len) - buf_len = tmp_len; - if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len) - buf_len = tmp_len; - if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len) - buf_len = tmp_len; - if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len) - buf_len = tmp_len; - if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len) - buf_len = tmp_len; - if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len) - buf_len = tmp_len; - - buffer = app_malloc(buf_len, "BN buffer"); - - BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len); - print_bignum_var(out, ec_p, "ec_p", len, buffer); - print_bignum_var(out, ec_a, "ec_a", len, buffer); - print_bignum_var(out, ec_b, "ec_b", len, buffer); - print_bignum_var(out, ec_gen, "ec_gen", len, buffer); - print_bignum_var(out, ec_order, "ec_order", len, buffer); - print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer); - BIO_printf(out, " int ok = 0;\n" - " EC_GROUP *group = NULL;\n" - " EC_POINT *point = NULL;\n" - " BIGNUM *tmp_1 = NULL;\n" - " BIGNUM *tmp_2 = NULL;\n" - " BIGNUM *tmp_3 = NULL;\n" - "\n"); - - BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n" - " goto err;\n", len, len); - BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n" - " goto err;\n", len, len); - BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n" - " goto err;\n", len, len); - BIO_printf(out, " if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n" - " goto err;\n" - "\n"); - BIO_printf(out, " /* build generator */\n"); - BIO_printf(out, " if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n" - " goto err;\n", len, len); - BIO_printf(out, " point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n"); - BIO_printf(out, " if (point == NULL)\n" - " goto err;\n"); - BIO_printf(out, " if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n" - " goto err;\n", len, len); - BIO_printf(out, " if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n" - " goto err;\n", len, len); - BIO_printf(out, " if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n" - " goto err;\n" - "ok = 1;" - "\n"); - BIO_printf(out, "err:\n" - " BN_free(tmp_1);\n" - " BN_free(tmp_2);\n" - " BN_free(tmp_3);\n" - " EC_POINT_free(point);\n" - " if (!ok) {\n" - " EC_GROUP_free(group);\n" - " return NULL;\n" - " }\n" - " return (group);\n" - "}\n"); + BIO_printf(bio_err, "ok\n"); } if (outformat == FORMAT_ASN1 && genkey) noout = 1; if (!noout) { - if (outformat == FORMAT_ASN1) - i = i2d_ECPKParameters_bio(out, group); - else - i = PEM_write_bio_ECPKParameters(out, group); - if (!i) { - BIO_printf(bio_err, "unable to write elliptic " - "curve parameters\n"); - ERR_print_errors(bio_err); + ectx_params = OSSL_ENCODER_CTX_new_for_pkey( + params_key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, + outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL); + if (!OSSL_ENCODER_to_bio(ectx_params, out)) { + BIO_printf(bio_err, "unable to write elliptic curve parameters\n"); goto end; } } if (genkey) { - EC_KEY *eckey = EC_KEY_new(); - - if (eckey == NULL) - goto end; - - if (EC_KEY_set_group(eckey, group) == 0) { - BIO_printf(bio_err, "unable to set group when generating key\n"); - EC_KEY_free(eckey); - ERR_print_errors(bio_err); - goto end; - } - - if (new_form) - EC_KEY_set_conv_form(eckey, form); - - if (!EC_KEY_generate_key(eckey)) { + /* + * NOTE: EC keygen does not normally need to pass in the param_key + * for named curves. This can be achieved using: + * gctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + * EVP_PKEY_keygen_init(gctx); + * EVP_PKEY_CTX_set_group_name(gctx, curvename); + * EVP_PKEY_keygen(gctx, &key) <= 0) + */ + gctx_key = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key, + app_get0_propq()); + if (EVP_PKEY_keygen_init(gctx_key) <= 0 + || EVP_PKEY_keygen(gctx_key, &key) <= 0) { BIO_printf(bio_err, "unable to generate key\n"); - EC_KEY_free(eckey); - ERR_print_errors(bio_err); goto end; } assert(private); - if (outformat == FORMAT_ASN1) - i = i2d_ECPrivateKey_bio(out, eckey); - else - i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, - NULL, 0, NULL, NULL); - EC_KEY_free(eckey); + ectx_key = OSSL_ENCODER_CTX_new_for_pkey( + key, OSSL_KEYMGMT_SELECT_ALL, + outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL); + if (!OSSL_ENCODER_to_bio(ectx_key, out)) { + BIO_printf(bio_err, "unable to write elliptic " + "curve parameters\n"); + goto end; + } } ret = 0; - end: - BN_free(ec_p); - BN_free(ec_a); - BN_free(ec_b); - BN_free(ec_gen); - BN_free(ec_order); - BN_free(ec_cofactor); - OPENSSL_free(buffer); - EC_GROUP_free(group); +end: + if (ret != 0) + ERR_print_errors(bio_err); release_engine(e); - BIO_free(in); + EVP_PKEY_free(params_key); + EVP_PKEY_free(key); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_CTX_free(gctx_params); + EVP_PKEY_CTX_free(gctx_key); + OSSL_DECODER_CTX_free(dctx_params); + OSSL_ENCODER_CTX_free(ectx_params); + OSSL_ENCODER_CTX_free(ectx_key); BIO_free_all(out); return ret; } diff --git a/apps/enc.c b/apps/enc.c --- a/apps/enc.c +++ b/apps/enc.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -39,38 +39,51 @@ }; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_LIST, OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V, OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A, OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE, OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER, - OPT_R_ENUM + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS enc_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"list", OPT_LIST, '-', "List ciphers"}, +#ifndef OPENSSL_NO_DEPRECATED_3_0 {"ciphers", OPT_LIST, '-', "Alias for -list"}, - {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, - {"pass", OPT_PASS, 's', "Passphrase source"}, +#endif {"e", OPT_E, '-', "Encrypt"}, {"d", OPT_D, '-', "Decrypt"}, {"p", OPT_P, '-', "Print the iv/key"}, {"P", OPT_UPPER_P, '-', "Print the iv/key and exit"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input file"}, + {"k", OPT_K, 's', "Passphrase"}, + {"kfile", OPT_KFILE, '<', "Read passphrase from file"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"pass", OPT_PASS, 's', "Passphrase source"}, {"v", OPT_V, '-', "Verbose output"}, - {"nopad", OPT_NOPAD, '-', "Disable standard block padding"}, - {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"}, - {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"}, - {"debug", OPT_DEBUG, '-', "Print debug info"}, {"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"}, {"base64", OPT_A, '-', "Same as option -a"}, {"A", OPT_UPPER_A, '-', "Used with -[base64|a] to specify base64 buffer as a single line"}, + + OPT_SECTION("Encryption"), + {"nopad", OPT_NOPAD, '-', "Disable standard block padding"}, + {"salt", OPT_SALT, '-', "Use salt in the KDF (default)"}, + {"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"}, + {"debug", OPT_DEBUG, '-', "Print debug info"}, + {"bufsize", OPT_BUFSIZE, 's', "Buffer size"}, - {"k", OPT_K, 's', "Passphrase"}, - {"kfile", OPT_KFILE, '<', "Read passphrase from file"}, {"K", OPT_UPPER_K, 's', "Raw key, in hex"}, {"S", OPT_UPPER_S, 's', "Salt, in hex"}, {"iv", OPT_IV, 's', "IV in hex"}, @@ -78,14 +91,13 @@ {"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"}, {"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"}, {"none", OPT_NONE, '-', "Don't encrypt"}, - {"", OPT_CIPHER, '-', "Any supported cipher"}, - OPT_R_OPTIONS, #ifdef ZLIB {"z", OPT_Z, '-', "Compress or decompress encrypted data using zlib"}, #endif -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + {"", OPT_CIPHER, '-', "Any supported cipher"}, + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, {NULL} }; @@ -97,11 +109,13 @@ BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio = NULL, *wbio = NULL; EVP_CIPHER_CTX *ctx = NULL; - const EVP_CIPHER *cipher = NULL, *c; - const EVP_MD *dgst = NULL; + EVP_CIPHER *cipher = NULL; + EVP_MD *dgst = NULL; + const char *digestname = NULL; char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p; char *infile = NULL, *outfile = NULL, *prog; char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL; + const char *ciphername = NULL; char mbuf[sizeof(magic) - 1]; OPTION_CHOICE o; int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0; @@ -119,21 +133,15 @@ BIO *bzl = NULL; #endif - /* first check the program name */ - prog = opt_progname(argv[0]); - if (strcmp(prog, "base64") == 0) { + /* first check the command name */ + if (strcmp(argv[0], "base64") == 0) base64 = 1; #ifdef ZLIB - } else if (strcmp(prog, "zlib") == 0) { + else if (strcmp(argv[0], "zlib") == 0) do_zlib = 1; #endif - } else { - cipher = EVP_get_cipherbyname(prog); - if (cipher == NULL && strcmp(prog, "enc") != 0) { - BIO_printf(bio_err, "%s is not a known cipher\n", prog); - goto end; - } - } + else if (strcmp(argv[0], "enc") != 0) + ciphername = argv[0]; prog = opt_init(argc, argv, enc_options); while ((o = opt_next()) != OPT_EOF) { @@ -252,17 +260,13 @@ hiv = opt_arg(); break; case OPT_MD: - if (!opt_md(opt_arg(), &dgst)) - goto opthelp; + digestname = opt_arg(); break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &c)) - goto opthelp; - cipher = c; + ciphername = opt_unknown(); break; case OPT_ITER: - if (!opt_int(opt_arg(), &iter)) - goto opthelp; + iter = opt_int_arg(); pbkdf2 = 1; break; case OPT_PBKDF2: @@ -277,25 +281,31 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } - if (opt_num_rest() != 0) { - BIO_printf(bio_err, "Extra arguments given.\n"); - goto opthelp; - } - if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) { - BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog); + /* No extra arguments. */ + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + if (!app_RAND_load()) goto end; - } - if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) { - BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog); - goto end; + /* Get the cipher name, either from progname (if set) or flag. */ + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &cipher)) + goto opthelp; + } + if (digestname != NULL) { + if (!opt_md(digestname, &dgst)) + goto opthelp; } - if (dgst == NULL) - dgst = EVP_sha256(); + dgst = (EVP_MD *)EVP_sha256(); if (iter == 0) iter = 1; @@ -342,7 +352,7 @@ char prompt[200]; BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:", - OBJ_nid2ln(EVP_CIPHER_nid(cipher)), + EVP_CIPHER_get0_name(cipher), (enc) ? "encryption" : "decryption"); strbuf[0] = '\0'; i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc); @@ -371,8 +381,8 @@ goto end; if (debug) { - BIO_set_callback(in, BIO_debug_callback); - BIO_set_callback(out, BIO_debug_callback); + BIO_set_callback_ex(in, BIO_debug_callback_ex); + BIO_set_callback_ex(out, BIO_debug_callback_ex); BIO_set_callback_arg(in, (char *)bio_err); BIO_set_callback_arg(out, (char *)bio_err); } @@ -385,7 +395,7 @@ if ((bzl = BIO_new(BIO_f_zlib())) == NULL) goto end; if (debug) { - BIO_set_callback(bzl, BIO_debug_callback); + BIO_set_callback_ex(bzl, BIO_debug_callback_ex); BIO_set_callback_arg(bzl, (char *)bio_err); } if (enc) @@ -399,7 +409,7 @@ if ((b64 = BIO_new(BIO_f_base64())) == NULL) goto end; if (debug) { - BIO_set_callback(b64, BIO_debug_callback); + BIO_set_callback_ex(b64, BIO_debug_callback_ex); BIO_set_callback_arg(b64, (char *)bio_err); } if (olb64) @@ -411,14 +421,11 @@ } if (cipher != NULL) { - /* - * Note that str is NULL if a key was passed on the command line, so - * we get no salt in that case. Is this a bug? - */ - if (str != NULL) { + if (str != NULL) { /* a passphrase is available */ /* - * Salt handling: if encrypting generate a salt and write to - * output BIO. If decrypting read salt from input BIO. + * Salt handling: if encrypting generate a salt if not supplied, + * and write to output BIO. If decrypting use salt from input BIO + * if not given with args */ unsigned char *sptr; size_t str_len = strlen(str); @@ -426,36 +433,47 @@ if (nosalt) { sptr = NULL; } else { - if (enc) { - if (hsalt) { - if (!set_hex(hsalt, salt, sizeof(salt))) { - BIO_printf(bio_err, "invalid hex salt value\n"); + if (hsalt != NULL && !set_hex(hsalt, salt, sizeof(salt))) { + BIO_printf(bio_err, "invalid hex salt value\n"); + goto end; + } + if (enc) { /* encryption */ + if (hsalt == NULL) { + if (RAND_bytes(salt, sizeof(salt)) <= 0) { + BIO_printf(bio_err, "RAND_bytes failed\n"); + goto end; + } + /* + * If -P option then don't bother writing. + * If salt is given, shouldn't either ? + */ + if ((printkey != 2) + && (BIO_write(wbio, magic, + sizeof(magic) - 1) != sizeof(magic) - 1 + || BIO_write(wbio, + (char *)salt, + sizeof(salt)) != sizeof(salt))) { + BIO_printf(bio_err, "error writing output file\n"); goto end; } - } else if (RAND_bytes(salt, sizeof(salt)) <= 0) { - goto end; } - /* - * If -P option then don't bother writing - */ - if ((printkey != 2) - && (BIO_write(wbio, magic, - sizeof(magic) - 1) != sizeof(magic) - 1 - || BIO_write(wbio, - (char *)salt, - sizeof(salt)) != sizeof(salt))) { - BIO_printf(bio_err, "error writing output file\n"); - goto end; + } else { /* decryption */ + if (hsalt == NULL) { + if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)) { + BIO_printf(bio_err, "error reading input file\n"); + goto end; + } + if (memcmp(mbuf, magic, sizeof(mbuf)) == 0) { /* file IS salted */ + if (BIO_read(rbio, salt, + sizeof(salt)) != sizeof(salt)) { + BIO_printf(bio_err, "error reading input file\n"); + goto end; + } + } else { /* file is NOT salted, NO salt available */ + BIO_printf(bio_err, "bad magic number\n"); + goto end; + } } - } else if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf) - || BIO_read(rbio, - (unsigned char *)salt, - sizeof(salt)) != sizeof(salt)) { - BIO_printf(bio_err, "error reading input file\n"); - goto end; - } else if (memcmp(mbuf, magic, sizeof(magic) - 1)) { - BIO_printf(bio_err, "bad magic number\n"); - goto end; } sptr = salt; } @@ -466,8 +484,8 @@ * concatenated into a temporary buffer */ unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH]; - int iklen = EVP_CIPHER_key_length(cipher); - int ivlen = EVP_CIPHER_iv_length(cipher); + int iklen = EVP_CIPHER_get_key_length(cipher); + int ivlen = EVP_CIPHER_get_iv_length(cipher); /* not needed if HASH_UPDATE() is fixed : */ int islen = (sptr != NULL ? sizeof(salt) : 0); if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen, @@ -499,7 +517,7 @@ OPENSSL_cleanse(str, str_len); } if (hiv != NULL) { - int siz = EVP_CIPHER_iv_length(cipher); + int siz = EVP_CIPHER_get_iv_length(cipher); if (siz == 0) { BIO_printf(bio_err, "warning: iv not used by this cipher\n"); } else if (!set_hex(hiv, iv, siz)) { @@ -508,7 +526,7 @@ } } if ((hiv == NULL) && (str == NULL) - && EVP_CIPHER_iv_length(cipher) != 0) { + && EVP_CIPHER_get_iv_length(cipher) != 0) { /* * No IV was explicitly set and no IV was generated. * Hence the IV is undefined, making correct decryption impossible. @@ -517,12 +535,12 @@ goto end; } if (hkey != NULL) { - if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) { + if (!set_hex(hkey, key, EVP_CIPHER_get_key_length(cipher))) { BIO_printf(bio_err, "invalid hex key value\n"); goto end; } /* wiping secret data as we no longer need it */ - OPENSSL_cleanse(hkey, strlen(hkey)); + cleanse(hkey); } if ((benc = BIO_new(BIO_f_cipher())) == NULL) @@ -535,9 +553,9 @@ BIO_get_cipher_ctx(benc, &ctx); - if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) { + if (!EVP_CipherInit_ex(ctx, cipher, e, NULL, NULL, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", - EVP_CIPHER_name(cipher)); + EVP_CIPHER_get0_name(cipher)); ERR_print_errors(bio_err); goto end; } @@ -547,13 +565,13 @@ if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", - EVP_CIPHER_name(cipher)); + EVP_CIPHER_get0_name(cipher)); ERR_print_errors(bio_err); goto end; } if (debug) { - BIO_set_callback(benc, BIO_debug_callback); + BIO_set_callback_ex(benc, BIO_debug_callback_ex); BIO_set_callback_arg(benc, (char *)bio_err); } @@ -564,15 +582,15 @@ printf("%02X", salt[i]); printf("\n"); } - if (EVP_CIPHER_key_length(cipher) > 0) { + if (EVP_CIPHER_get_key_length(cipher) > 0) { printf("key="); - for (i = 0; i < EVP_CIPHER_key_length(cipher); i++) + for (i = 0; i < EVP_CIPHER_get_key_length(cipher); i++) printf("%02X", key[i]); printf("\n"); } - if (EVP_CIPHER_iv_length(cipher) > 0) { + if (EVP_CIPHER_get_iv_length(cipher) > 0) { printf("iv ="); - for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++) + for (i = 0; i < EVP_CIPHER_get_iv_length(cipher); i++) printf("%02X", iv[i]); printf("\n"); } @@ -614,6 +632,8 @@ BIO_free_all(out); BIO_free(benc); BIO_free(b64); + EVP_MD_free(dgst); + EVP_CIPHER_free(cipher); #ifdef ZLIB BIO_free(bzl); #endif @@ -632,9 +652,9 @@ /* Filter out ciphers that we cannot use */ cipher = EVP_get_cipherbyname(name->name); - if (cipher == NULL || - (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 || - EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) + if (cipher == NULL + || (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 + || EVP_CIPHER_get_mode(cipher) == EVP_CIPH_XTS_MODE) return; BIO_printf(dec->bio, "-%-25s", name->name); diff --git a/apps/engine.c b/apps/engine.c --- a/apps/engine.c +++ b/apps/engine.c @@ -1,13 +1,17 @@ /* - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* We need to use some engine deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include + #include "apps.h" #include "progs.h" #include @@ -19,27 +23,32 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST, OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV } OPTION_CHOICE; const OPTIONS engine_options[] = { {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"}, - {OPT_HELP_STR, 1, '-', - " engine... Engines to load\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"t", OPT_T, '-', "Check that specified engine is available"}, + {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"}, + {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"}, + + OPT_SECTION("Output"), {"v", OPT_V, '-', "List 'control commands' For each specified engine"}, {"vv", OPT_VV, '-', "Also display each command's description"}, {"vvv", OPT_VVV, '-', "Also add the input flags for each command"}, {"vvvv", OPT_VVVV, '-', "Also show internal input flags"}, {"c", OPT_C, '-', "List the capabilities of specified engine"}, - {"t", OPT_T, '-', "Check that specified engine is available"}, {"tt", OPT_TT, '-', "Display error trace for unavailable engines"}, - {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"}, - {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"}, {OPT_MORE_STR, OPT_EOF, 1, "Commands are like \"SO_PATH:/lib/libdriver.so\""}, + + OPT_PARAMETERS(), + {"engine", 0, 0, "ID of engine(s) to load"}, {NULL} }; @@ -351,7 +360,7 @@ } } - /* Allow any trailing parameters as engine names. */ + /* Any remaining arguments are engine names. */ argc = opt_num_rest(); argv = opt_rest(); for ( ; *argv; argv++) { diff --git a/apps/errstr.c b/apps/errstr.c --- a/apps/errstr.c +++ b/apps/errstr.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -22,8 +22,12 @@ const OPTIONS errstr_options[] = { {OPT_HELP_STR, 1, '-', "Usage: %s [options] errnum...\n"}, - {OPT_HELP_STR, 1, '-', " errnum Error number\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_PARAMETERS(), + {"errnum", 0, 0, "Error number(s) to decode"}, {NULL} }; @@ -48,16 +52,19 @@ } } + /* + * We're not really an SSL application so this won't auto-init, but + * we're still interested in SSL error strings + */ + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS + | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); + + /* All remaining arg are error code. */ ret = 0; - for (argv = opt_rest(); *argv; argv++) { + for (argv = opt_rest(); *argv != NULL; argv++) { if (sscanf(*argv, "%lx", &l) == 0) { ret++; } else { - /* We're not really an SSL application so this won't auto-init, but - * we're still interested in SSL error strings - */ - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS - | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); ERR_error_string_n(l, buf, sizeof(buf)); BIO_printf(bio_out, "%s\n", buf); } diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c new file mode 100644 --- /dev/null +++ b/apps/fipsinstall.c @@ -0,0 +1,590 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" + +#define BUFSIZE 4096 + +/* Configuration file values */ +#define VERSION_KEY "version" +#define VERSION_VAL "1" +#define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN" + +static OSSL_CALLBACK self_test_events; +static char *self_test_corrupt_desc = NULL; +static char *self_test_corrupt_type = NULL; +static int self_test_log = 1; +static int quiet = 0; + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_IN, OPT_OUT, OPT_MODULE, + OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY, + OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG, + OPT_NO_CONDITIONAL_ERRORS, + OPT_NO_SECURITY_CHECKS, + OPT_SELF_TEST_ONLOAD +} OPTION_CHOICE; + +const OPTIONS fipsinstall_options[] = { + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"verify", OPT_VERIFY, '-', + "Verify a config file instead of generating one"}, + {"module", OPT_MODULE, '<', "File name of the provider module"}, + {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"}, + {"section_name", OPT_SECTION_NAME, 's', + "FIPS Provider config section name (optional)"}, + {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-', + "Disable the ability of the fips module to enter an error state if" + " any conditional self tests fail"}, + {"no_security_checks", OPT_NO_SECURITY_CHECKS, '-', + "Disable the run-time FIPS security checks in the module"}, + {"self_test_onload", OPT_SELF_TEST_ONLOAD, '-', + "Forces self tests to always run on module load"}, + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input config file, used when verifying"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output config file, used when generating"}, + {"mac_name", OPT_MAC_NAME, 's', "MAC name"}, + {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. " + "See 'PARAMETER NAMES' in the EVP_MAC_ docs"}, + {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"}, + {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"}, + {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"}, + {"config", OPT_CONFIG, '<', "The parent config to verify"}, + {"quiet", OPT_QUIET, '-', "No messages, just exit status"}, + {NULL} +}; + +static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in, + unsigned char *out, size_t *out_len) +{ + int ret = 0; + int i; + size_t outsz = *out_len; + + if (!EVP_MAC_init(ctx, NULL, 0, NULL)) + goto err; + if (EVP_MAC_CTX_get_mac_size(ctx) > outsz) + goto end; + while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) { + if (i < 0 || !EVP_MAC_update(ctx, tmp, i)) + goto err; + } +end: + if (!EVP_MAC_final(ctx, out, out_len, outsz)) + goto err; + ret = 1; +err: + return ret; +} + +static int load_fips_prov_and_run_self_test(const char *prov_name) +{ + int ret = 0; + OSSL_PROVIDER *prov = NULL; + + prov = OSSL_PROVIDER_load(NULL, prov_name); + if (prov == NULL) { + BIO_printf(bio_err, "Failed to load FIPS module\n"); + goto end; + } + ret = 1; +end: + OSSL_PROVIDER_unload(prov); + return ret; +} + +static int print_mac(BIO *bio, const char *label, const unsigned char *mac, + size_t len) +{ + int ret; + char *hexstr = NULL; + + hexstr = OPENSSL_buf2hexstr(mac, (long)len); + if (hexstr == NULL) + return 0; + ret = BIO_printf(bio, "%s = %s\n", label, hexstr); + OPENSSL_free(hexstr); + return ret; +} + +static int write_config_header(BIO *out, const char *prov_name, + const char *section) +{ + return BIO_printf(out, "openssl_conf = openssl_init\n\n") + && BIO_printf(out, "[openssl_init]\n") + && BIO_printf(out, "providers = provider_section\n\n") + && BIO_printf(out, "[provider_section]\n") + && BIO_printf(out, "%s = %s\n\n", prov_name, section); +} + +/* + * Outputs a fips related config file that contains entries for the fips + * module checksum, installation indicator checksum and the options + * conditional_errors and security_checks. + * + * Returns 1 if the config file is written otherwise it returns 0 on error. + */ +static int write_config_fips_section(BIO *out, const char *section, + unsigned char *module_mac, + size_t module_mac_len, + int conditional_errors, + int security_checks, + unsigned char *install_mac, + size_t install_mac_len) +{ + int ret = 0; + + if (BIO_printf(out, "[%s]\n", section) <= 0 + || BIO_printf(out, "activate = 1\n") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION, + VERSION_VAL) <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS, + conditional_errors ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS, + security_checks ? "1" : "0") <= 0 + || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac, + module_mac_len)) + goto end; + + if (install_mac != NULL && install_mac_len > 0) { + if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac, + install_mac_len) + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS, + INSTALL_STATUS_VAL) <= 0) + goto end; + } + ret = 1; +end: + return ret; +} + +static CONF *generate_config_and_load(const char *prov_name, + const char *section, + unsigned char *module_mac, + size_t module_mac_len, + int conditional_errors, + int security_checks) +{ + BIO *mem_bio = NULL; + CONF *conf = NULL; + + mem_bio = BIO_new(BIO_s_mem()); + if (mem_bio == NULL) + return 0; + if (!write_config_header(mem_bio, prov_name, section) + || !write_config_fips_section(mem_bio, section, + module_mac, module_mac_len, + conditional_errors, + security_checks, + NULL, 0)) + goto end; + + conf = app_load_config_bio(mem_bio, NULL); + if (conf == NULL) + goto end; + + if (CONF_modules_load(conf, NULL, 0) <= 0) + goto end; + BIO_free(mem_bio); + return conf; +end: + NCONF_free(conf); + BIO_free(mem_bio); + return NULL; +} + +static void free_config_and_unload(CONF *conf) +{ + if (conf != NULL) { + NCONF_free(conf); + CONF_modules_unload(1); + } +} + +static int verify_module_load(const char *parent_config_file) +{ + return OSSL_LIB_CTX_load_config(NULL, parent_config_file); +} + +/* + * Returns 1 if the config file entries match the passed in module_mac and + * install_mac values, otherwise it returns 0. + */ +static int verify_config(const char *infile, const char *section, + unsigned char *module_mac, size_t module_mac_len, + unsigned char *install_mac, size_t install_mac_len) +{ + int ret = 0; + char *s = NULL; + unsigned char *buf1 = NULL, *buf2 = NULL; + long len; + CONF *conf = NULL; + + /* read in the existing values and check they match the saved values */ + conf = app_load_config(infile); + if (conf == NULL) + goto end; + + s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION); + if (s == NULL || strcmp(s, VERSION_VAL) != 0) { + BIO_printf(bio_err, "version not found\n"); + goto end; + } + s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC); + if (s == NULL) { + BIO_printf(bio_err, "Module integrity MAC not found\n"); + goto end; + } + buf1 = OPENSSL_hexstr2buf(s, &len); + if (buf1 == NULL + || (size_t)len != module_mac_len + || memcmp(module_mac, buf1, module_mac_len) != 0) { + BIO_printf(bio_err, "Module integrity mismatch\n"); + goto end; + } + if (install_mac != NULL && install_mac_len > 0) { + s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS); + if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) { + BIO_printf(bio_err, "install status not found\n"); + goto end; + } + s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC); + if (s == NULL) { + BIO_printf(bio_err, "Install indicator MAC not found\n"); + goto end; + } + buf2 = OPENSSL_hexstr2buf(s, &len); + if (buf2 == NULL + || (size_t)len != install_mac_len + || memcmp(install_mac, buf2, install_mac_len) != 0) { + BIO_printf(bio_err, "Install indicator status mismatch\n"); + goto end; + } + } + ret = 1; +end: + OPENSSL_free(buf1); + OPENSSL_free(buf2); + NCONF_free(conf); + return ret; +} + +int fipsinstall_main(int argc, char **argv) +{ + int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, self_test_onload = 0; + int enable_conditional_errors = 1, enable_security_checks = 1; + const char *section_name = "fips_sect"; + const char *mac_name = "HMAC"; + const char *prov_name = "fips"; + BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL; + char *in_fname = NULL, *out_fname = NULL, *prog; + char *module_fname = NULL, *parent_config = NULL, *module_path = NULL; + const char *tail; + EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL; + STACK_OF(OPENSSL_STRING) *opts = NULL; + OPTION_CHOICE o; + unsigned char *read_buffer = NULL; + unsigned char module_mac[EVP_MAX_MD_SIZE]; + size_t module_mac_len = EVP_MAX_MD_SIZE; + unsigned char install_mac[EVP_MAX_MD_SIZE]; + size_t install_mac_len = EVP_MAX_MD_SIZE; + EVP_MAC *mac = NULL; + CONF *conf = NULL; + + if ((opts = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + + prog = opt_init(argc, argv, fipsinstall_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto cleanup; + case OPT_HELP: + opt_help(fipsinstall_options); + ret = 0; + goto end; + case OPT_IN: + in_fname = opt_arg(); + break; + case OPT_OUT: + out_fname = opt_arg(); + break; + case OPT_NO_CONDITIONAL_ERRORS: + enable_conditional_errors = 0; + break; + case OPT_NO_SECURITY_CHECKS: + enable_security_checks = 0; + break; + case OPT_QUIET: + quiet = 1; + /* FALLTHROUGH */ + case OPT_NO_LOG: + self_test_log = 0; + break; + case OPT_CORRUPT_DESC: + self_test_corrupt_desc = opt_arg(); + break; + case OPT_CORRUPT_TYPE: + self_test_corrupt_type = opt_arg(); + break; + case OPT_PROV_NAME: + prov_name = opt_arg(); + break; + case OPT_MODULE: + module_fname = opt_arg(); + break; + case OPT_SECTION_NAME: + section_name = opt_arg(); + break; + case OPT_MAC_NAME: + mac_name = opt_arg(); + break; + case OPT_CONFIG: + parent_config = opt_arg(); + break; + case OPT_MACOPT: + if (!sk_OPENSSL_STRING_push(opts, opt_arg())) + goto opthelp; + if (strncmp(opt_arg(), "hexkey:", 7) == 0) + gotkey = 1; + else if (strncmp(opt_arg(), "digest:", 7) == 0) + gotdigest = 1; + break; + case OPT_VERIFY: + verify = 1; + break; + case OPT_SELF_TEST_ONLOAD: + self_test_onload = 1; + break; + } + } + + /* No extra arguments. */ + argc = opt_num_rest(); + if (argc != 0 || (verify && in_fname == NULL)) + goto opthelp; + + if (parent_config != NULL) { + /* Test that a parent config can load the module */ + if (verify_module_load(parent_config)) { + ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1; + if (!quiet) + BIO_printf(bio_err, "FIPS provider is %s\n", + ret == 0 ? "available" : " not available"); + } + goto end; + } + if (module_fname == NULL) + goto opthelp; + + tail = opt_path_end(module_fname); + if (tail != NULL) { + module_path = OPENSSL_strdup(module_fname); + if (module_path == NULL) + goto end; + module_path[tail - module_fname] = '\0'; + if (!OSSL_PROVIDER_set_default_search_path(NULL, module_path)) + goto end; + } + + if (self_test_log + || self_test_corrupt_desc != NULL + || self_test_corrupt_type != NULL) + OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL); + + /* Use the default FIPS HMAC digest and key if not specified. */ + if (!gotdigest && !sk_OPENSSL_STRING_push(opts, "digest:SHA256")) + goto end; + if (!gotkey && !sk_OPENSSL_STRING_push(opts, "hexkey:" FIPS_KEY_STRING)) + goto end; + + module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY); + if (module_bio == NULL) { + BIO_printf(bio_err, "Failed to open module file\n"); + goto end; + } + + read_buffer = app_malloc(BUFSIZE, "I/O buffer"); + if (read_buffer == NULL) + goto end; + + mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq()); + if (mac == NULL) { + BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name); + goto end; + } + + ctx = EVP_MAC_CTX_new(mac); + if (ctx == NULL) { + BIO_printf(bio_err, "Unable to create MAC CTX for module check\n"); + goto end; + } + + if (opts != NULL) { + int ok = 1; + OSSL_PARAM *params = + app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac)); + + if (params == NULL) + goto end; + + if (!EVP_MAC_CTX_set_params(ctx, params)) { + BIO_printf(bio_err, "MAC parameter error\n"); + ERR_print_errors(bio_err); + ok = 0; + } + app_params_free(params); + if (!ok) + goto end; + } + + ctx2 = EVP_MAC_CTX_dup(ctx); + if (ctx2 == NULL) { + BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n"); + goto end; + } + + if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len)) + goto end; + + if (self_test_onload == 0) { + mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL, + strlen(INSTALL_STATUS_VAL)); + if (mem_bio == NULL) { + BIO_printf(bio_err, "Unable to create memory BIO\n"); + goto end; + } + if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len)) + goto end; + } else { + install_mac_len = 0; + } + + if (verify) { + if (!verify_config(in_fname, section_name, module_mac, module_mac_len, + install_mac, install_mac_len)) + goto end; + if (!quiet) + BIO_printf(bio_err, "VERIFY PASSED\n"); + } else { + + conf = generate_config_and_load(prov_name, section_name, module_mac, + module_mac_len, + enable_conditional_errors, + enable_security_checks); + if (conf == NULL) + goto end; + if (!load_fips_prov_and_run_self_test(prov_name)) + goto end; + + fout = + out_fname == NULL ? dup_bio_out(FORMAT_TEXT) + : bio_open_default(out_fname, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file\n"); + goto end; + } + if (!write_config_fips_section(fout, section_name, + module_mac, module_mac_len, + enable_conditional_errors, + enable_security_checks, + install_mac, install_mac_len)) + goto end; + if (!quiet) + BIO_printf(bio_err, "INSTALL PASSED\n"); + } + + ret = 0; +end: + if (ret == 1) { + if (!quiet) + BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL"); + ERR_print_errors(bio_err); + } + +cleanup: + OPENSSL_free(module_path); + BIO_free(fout); + BIO_free(mem_bio); + BIO_free(module_bio); + sk_OPENSSL_STRING_free(opts); + EVP_MAC_free(mac); + EVP_MAC_CTX_free(ctx2); + EVP_MAC_CTX_free(ctx); + OPENSSL_free(read_buffer); + free_config_and_unload(conf); + return ret; +} + +static int self_test_events(const OSSL_PARAM params[], void *arg) +{ + const OSSL_PARAM *p = NULL; + const char *phase = NULL, *type = NULL, *desc = NULL; + int ret = 0; + + p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE); + if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) + goto err; + phase = (const char *)p->data; + + p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC); + if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) + goto err; + desc = (const char *)p->data; + + p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE); + if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) + goto err; + type = (const char *)p->data; + + if (self_test_log) { + if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0) + BIO_printf(bio_err, "%s : (%s) : ", desc, type); + else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0 + || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0) + BIO_printf(bio_err, "%s\n", phase); + } + /* + * The self test code will internally corrupt the KAT test result if an + * error is returned during the corrupt phase. + */ + if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0 + && (self_test_corrupt_desc != NULL + || self_test_corrupt_type != NULL)) { + if (self_test_corrupt_desc != NULL + && strcmp(self_test_corrupt_desc, desc) != 0) + goto end; + if (self_test_corrupt_type != NULL + && strcmp(self_test_corrupt_type, type) != 0) + goto end; + BIO_printf(bio_err, "%s ", phase); + goto err; + } +end: + ret = 1; +err: + return ret; +} diff --git a/apps/gendsa.c b/apps/gendsa.c --- a/apps/gendsa.c +++ b/apps/gendsa.c @@ -1,13 +1,14 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include #include #include @@ -22,22 +23,30 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, - OPT_R_ENUM + OPT_COMMON, + OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE, + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS gendsa_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [args] dsaparam-file\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] dsaparam-file\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output the key to the specified file"}, {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, OPT_R_OPTIONS, + OPT_PROV_OPTIONS, {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + + OPT_PARAMETERS(), + {"dsaparam-file", 0, 0, "File containing DSA parameters"}, {NULL} }; @@ -45,13 +54,13 @@ { ENGINE *e = NULL; BIO *out = NULL, *in = NULL; - DSA *dsa = NULL; - const EVP_CIPHER *enc = NULL; - char *dsaparams = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_CIPHER *enc = NULL; + char *dsaparams = NULL, *ciphername = NULL; char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog; OPTION_CHOICE o; - int ret = 1, private = 0; - const BIGNUM *p = NULL; + int ret = 1, private = 0, verbose = 0, nbits; prog = opt_init(argc, argv, gendsa_options); while ((o = opt_next()) != OPT_EOF) { @@ -78,55 +87,71 @@ if (!opt_rand(o)) goto end; break; - case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &enc)) + case OPT_PROV_CASES: + if (!opt_provider(o)) goto end; break; + case OPT_CIPHER: + ciphername = opt_unknown(); + break; + case OPT_VERBOSE: + verbose = 1; + break; } } + + /* One argument, the params file. */ argc = opt_num_rest(); argv = opt_rest(); - private = 1; - if (argc != 1) goto opthelp; - dsaparams = *argv; + dsaparams = argv[0]; - if (!app_passwd(NULL, passoutarg, NULL, &passout)) { - BIO_printf(bio_err, "Error getting password\n"); + if (!app_RAND_load()) goto end; - } - in = bio_open_default(dsaparams, 'r', FORMAT_PEM); - if (in == NULL) - goto end2; + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &enc)) + goto end; + } + private = 1; - if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) { - BIO_printf(bio_err, "unable to load DSA parameter file\n"); + if (!app_passwd(NULL, passoutarg, NULL, &passout)) { + BIO_printf(bio_err, "Error getting password\n"); goto end; } - BIO_free(in); - in = NULL; + + pkey = load_keyparams(dsaparams, FORMAT_UNDEF, 1, "DSA", "DSA parameters"); out = bio_open_owner(outfile, FORMAT_PEM, private); if (out == NULL) goto end2; - DSA_get0_pqg(dsa, &p, NULL, NULL); - - if (BN_num_bits(p) > OPENSSL_DSA_MAX_MODULUS_BITS) + nbits = EVP_PKEY_get_bits(pkey); + if (nbits > OPENSSL_DSA_MAX_MODULUS_BITS) BIO_printf(bio_err, "Warning: It is not recommended to use more than %d bit for DSA keys.\n" " Your key size is %d! Larger key size may behave not as expected.\n", - OPENSSL_DSA_MAX_MODULUS_BITS, BN_num_bits(p)); + OPENSSL_DSA_MAX_MODULUS_BITS, EVP_PKEY_get_bits(pkey)); - BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p)); - if (!DSA_generate_key(dsa)) + ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq()); + if (ctx == NULL) { + BIO_printf(bio_err, "unable to create PKEY context\n"); goto end; + } + EVP_PKEY_free(pkey); + pkey = NULL; + if (EVP_PKEY_keygen_init(ctx) <= 0) { + BIO_printf(bio_err, "unable to set up for key generation\n"); + goto end; + } + pkey = app_keygen(ctx, "DSA", nbits, verbose); assert(private); - if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout)) + if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) { + BIO_printf(bio_err, "unable to output generated key\n"); goto end; + } ret = 0; end: if (ret != 0) @@ -134,7 +159,9 @@ end2: BIO_free(in); BIO_free_all(out); - DSA_free(dsa); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + EVP_CIPHER_free(enc); release_engine(e); OPENSSL_free(passout); return ret; diff --git a/apps/genpkey.c b/apps/genpkey.c --- a/apps/genpkey.c +++ b/apps/genpkey.c @@ -1,7 +1,7 @@ /* - * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -14,34 +14,44 @@ #include #include #include -#ifndef OPENSSL_NO_ENGINE -# include -#endif -static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e); +static int quiet; + +static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e, + OSSL_LIB_CTX *libctx, const char *propq); static int genpkey_cb(EVP_PKEY_CTX *ctx); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE, - OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER + OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER, + OPT_QUIET, OPT_CONFIG, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS genpkey_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"out", OPT_OUT, '>', "Output file"}, - {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"}, - {"pass", OPT_PASS, 's', "Output file pass phrase source"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif {"paramfile", OPT_PARAMFILE, '<', "Parameters file"}, {"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"}, + {"quiet", OPT_QUIET, '-', "Do not output status while generating keys"}, {"pkeyopt", OPT_PKEYOPT, 's', "Set the public key algorithm option as opt:value"}, + OPT_CONFIG_OPTION, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"}, + {"pass", OPT_PASS, 's', "Output file pass phrase source"}, {"genparam", OPT_GENPARAM, '-', "Generate parameters, not key"}, {"text", OPT_TEXT, '-', "Print the in text"}, {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + + OPT_PROV_OPTIONS, + /* This is deliberately last. */ {OPT_HELP_STR, 1, 1, "Order of options may be important! See the documentation.\n"}, @@ -50,17 +60,24 @@ int genpkey_main(int argc, char **argv) { + CONF *conf = NULL; BIO *in = NULL, *out = NULL; ENGINE *e = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; - char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog; - const EVP_CIPHER *cipher = NULL; + char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog, *p; + const char *ciphername = NULL, *paramfile = NULL, *algname = NULL; + EVP_CIPHER *cipher = NULL; OPTION_CHOICE o; int outformat = FORMAT_PEM, text = 0, ret = 1, rv, do_param = 0; - int private = 0; + int private = 0, i; + OSSL_LIB_CTX *libctx = app_get0_libctx(); + STACK_OF(OPENSSL_STRING) *keyopt = NULL; prog = opt_init(argc, argv, genpkey_options); + keyopt = sk_OPENSSL_STRING_new_null(); + if (keyopt == NULL) + goto end; while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: @@ -88,56 +105,70 @@ case OPT_PARAMFILE: if (do_param == 1) goto opthelp; - if (!init_keygen_file(&ctx, opt_arg(), e)) - goto end; + paramfile = opt_arg(); break; case OPT_ALGORITHM: - if (!init_gen_str(&ctx, opt_arg(), e, do_param)) - goto end; + algname = opt_arg(); break; case OPT_PKEYOPT: - if (ctx == NULL) { - BIO_printf(bio_err, "%s: No keytype specified.\n", prog); - goto opthelp; - } - if (pkey_ctrl_string(ctx, opt_arg()) <= 0) { - BIO_printf(bio_err, - "%s: Error setting %s parameter:\n", - prog, opt_arg()); - ERR_print_errors(bio_err); + if (!sk_OPENSSL_STRING_push(keyopt, opt_arg())) goto end; - } + break; + case OPT_QUIET: + quiet = 1; break; case OPT_GENPARAM: - if (ctx != NULL) - goto opthelp; do_param = 1; break; case OPT_TEXT: text = 1; break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &cipher) - || do_param == 1) - goto opthelp; - if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE || - EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE || - EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE || - EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE) { - BIO_printf(bio_err, "%s: cipher mode not supported\n", prog); + ciphername = opt_unknown(); + break; + case OPT_CONFIG: + conf = app_load_config_modules(opt_arg()); + if (conf == NULL) goto end; - } + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; - private = do_param ? 0 : 1; - + /* Fetch cipher, etc. */ + if (paramfile != NULL) { + if (!init_keygen_file(&ctx, paramfile, e, libctx, app_get0_propq())) + goto end; + } + if (algname != NULL) { + if (!init_gen_str(&ctx, algname, e, do_param, libctx, app_get0_propq())) + goto end; + } if (ctx == NULL) goto opthelp; + for (i = 0; i < sk_OPENSSL_STRING_num(keyopt); i++) { + p = sk_OPENSSL_STRING_value(keyopt, i); + if (pkey_ctrl_string(ctx, p) <= 0) { + BIO_printf(bio_err, "%s: Error setting %s parameter:\n", prog, p); + ERR_print_errors(bio_err); + goto end; + } + } + if (ciphername != NULL) + if (!opt_cipher(ciphername, &cipher) || do_param == 1) + goto opthelp; + + private = do_param ? 0 : 1; + if (!app_passwd(passarg, NULL, &pass, NULL)) { BIO_puts(bio_err, "Error getting password\n"); goto end; @@ -150,19 +181,8 @@ EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); - if (do_param) { - if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { - BIO_puts(bio_err, "Error generating parameters\n"); - ERR_print_errors(bio_err); - goto end; - } - } else { - if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { - BIO_puts(bio_err, "Error generating key\n"); - ERR_print_errors(bio_err); - goto end; - } - } + pkey = do_param ? app_paramgen(ctx, algname) + : app_keygen(ctx, algname, 0, 0 /* not verbose */); if (do_param) { rv = PEM_write_bio_Parameters(out, pkey); @@ -181,7 +201,6 @@ if (rv <= 0) { BIO_puts(bio_err, "Error writing key\n"); - ERR_print_errors(bio_err); ret = 1; } @@ -193,22 +212,27 @@ if (rv <= 0) { BIO_puts(bio_err, "Error printing key\n"); - ERR_print_errors(bio_err); ret = 1; } } end: + sk_OPENSSL_STRING_free(keyopt); + if (ret != 0) + ERR_print_errors(bio_err); EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); + EVP_CIPHER_free(cipher); BIO_free_all(out); BIO_free(in); release_engine(e); OPENSSL_free(pass); + NCONF_free(conf); return ret; } -static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e) +static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e, + OSSL_LIB_CTX *libctx, const char *propq) { BIO *pbio; EVP_PKEY *pkey = NULL; @@ -219,20 +243,23 @@ } pbio = BIO_new_file(file, "r"); - if (!pbio) { + if (pbio == NULL) { BIO_printf(bio_err, "Can't open parameter file %s\n", file); return 0; } - pkey = PEM_read_bio_Parameters(pbio, NULL); + pkey = PEM_read_bio_Parameters_ex(pbio, NULL, libctx, propq); BIO_free(pbio); - if (!pkey) { + if (pkey == NULL) { BIO_printf(bio_err, "Error reading parameter file %s\n", file); return 0; } - ctx = EVP_PKEY_CTX_new(pkey, e); + if (e != NULL) + ctx = EVP_PKEY_CTX_new(pkey, e); + else + ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq); if (ctx == NULL) goto err; if (EVP_PKEY_keygen_init(ctx) <= 0) @@ -251,11 +278,10 @@ } int init_gen_str(EVP_PKEY_CTX **pctx, - const char *algname, ENGINE *e, int do_param) + const char *algname, ENGINE *e, int do_param, + OSSL_LIB_CTX *libctx, const char *propq) { EVP_PKEY_CTX *ctx = NULL; - const EVP_PKEY_ASN1_METHOD *ameth; - ENGINE *tmpeng = NULL; int pkey_id; if (*pctx) { @@ -263,27 +289,13 @@ return 0; } - ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1); - -#ifndef OPENSSL_NO_ENGINE - if (!ameth && e) - ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1); -#endif - - if (!ameth) { - BIO_printf(bio_err, "Algorithm %s not found\n", algname); - return 0; - } - - ERR_clear_error(); + pkey_id = get_legacy_pkey_id(libctx, algname, e); + if (pkey_id != NID_undef) + ctx = EVP_PKEY_CTX_new_id(pkey_id, e); + else + ctx = EVP_PKEY_CTX_new_from_name(libctx, algname, propq); - EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(tmpeng); -#endif - ctx = EVP_PKEY_CTX_new_id(pkey_id, e); - - if (!ctx) + if (ctx == NULL) goto err; if (do_param) { if (EVP_PKEY_paramgen_init(ctx) <= 0) @@ -308,16 +320,22 @@ { char c = '*'; BIO *b = EVP_PKEY_CTX_get_app_data(ctx); - int p; - p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); - if (p == 0) + + if (quiet) + return 1; + + switch (EVP_PKEY_CTX_get_keygen_info(ctx, 0)) { + case 0: c = '.'; - if (p == 1) + break; + case 1: c = '+'; - if (p == 2) - c = '*'; - if (p == 3) + break; + case 3: c = '\n'; + break; + } + BIO_write(b, &c, 1); (void)BIO_flush(b); return 1; diff --git a/apps/genrsa.c b/apps/genrsa.c --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -1,13 +1,14 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include #include #include @@ -26,52 +27,72 @@ #define DEFBITS 2048 #define DEFPRIMES 2 -static int genrsa_cb(int p, int n, BN_GENCB *cb); +static int verbose = 0; + +static int genrsa_cb(EVP_PKEY_CTX *ctx); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_3, OPT_F4, OPT_ENGINE, - OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, - OPT_R_ENUM + OPT_COMMON, +#ifndef OPENSSL_NO_DEPRECATED_3_0 + OPT_3, +#endif + OPT_F4, OPT_ENGINE, + OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE, + OPT_R_ENUM, OPT_PROV_ENUM, OPT_TRADITIONAL } OPTION_CHOICE; const OPTIONS genrsa_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] numbits\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"3", OPT_3, '-', "Use 3 for the E value"}, - {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, - {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"}, - {"out", OPT_OUT, '>', "Output the key to specified file"}, - OPT_R_OPTIONS, - {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, - {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif + + OPT_SECTION("Input"), +#ifndef OPENSSL_NO_DEPRECATED_3_0 + {"3", OPT_3, '-', "(deprecated) Use 3 for the E value"}, +#endif + {"F4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"}, + {"f4", OPT_F4, '-', "Use the Fermat number F4 (0x10001) for the E value"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output the key to specified file"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, {"primes", OPT_PRIMES, 'p', "Specify number of primes"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"traditional", OPT_TRADITIONAL, '-', + "Use traditional format for private keys"}, + {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"numbits", 0, 0, "Size of key in bits"}, {NULL} }; int genrsa_main(int argc, char **argv) { BN_GENCB *cb = BN_GENCB_new(); - PW_CB_DATA cb_data; ENGINE *eng = NULL; BIGNUM *bn = BN_new(); BIO *out = NULL; - const BIGNUM *e; - RSA *rsa = NULL; - const EVP_CIPHER *enc = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_CIPHER *enc = NULL; int ret = 1, num = DEFBITS, private = 0, primes = DEFPRIMES; unsigned long f4 = RSA_F4; char *outfile = NULL, *passoutarg = NULL, *passout = NULL; - char *prog, *hexe, *dece; + char *prog, *hexe, *dece, *ciphername = NULL; OPTION_CHOICE o; + int traditional = 0; if (bn == NULL || cb == NULL) goto end; - BN_GENCB_set(cb, genrsa_cb, bio_err); - prog = opt_init(argc, argv, genrsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -84,9 +105,11 @@ ret = 0; opt_help(genrsa_options); goto end; +#ifndef OPENSSL_NO_DEPRECATED_3_0 case OPT_3: - f4 = 3; + f4 = RSA_3; break; +#endif case OPT_F4: f4 = RSA_F4; break; @@ -100,19 +123,29 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_PASSOUT: passoutarg = opt_arg(); break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &enc)) - goto end; + ciphername = opt_unknown(); break; case OPT_PRIMES: - if (!opt_int(opt_arg(), &primes)) - goto end; + primes = opt_int_arg(); + break; + case OPT_VERBOSE: + verbose = 1; + break; + case OPT_TRADITIONAL: + traditional = 1; break; } } + + /* One optional argument, the bitsize. */ argc = opt_num_rest(); argv = opt_rest(); @@ -129,7 +162,14 @@ goto opthelp; } + if (!app_RAND_load()) + goto end; + private = 1; + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &enc)) + goto end; + } if (!app_passwd(NULL, passoutarg, NULL, &passout)) { BIO_printf(bio_err, "Error getting password\n"); goto end; @@ -139,37 +179,65 @@ if (out == NULL) goto end; - BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n", - num, primes); - rsa = eng ? RSA_new_method(eng) : RSA_new(); - if (rsa == NULL) + if (!init_gen_str(&ctx, "RSA", eng, 0, app_get0_libctx(), + app_get0_propq())) goto end; - if (!BN_set_word(bn, f4) - || !RSA_generate_multi_prime_key(rsa, num, primes, bn, cb)) - goto end; + EVP_PKEY_CTX_set_cb(ctx, genrsa_cb); + EVP_PKEY_CTX_set_app_data(ctx, bio_err); - RSA_get0_key(rsa, NULL, &e, NULL); - hexe = BN_bn2hex(e); - dece = BN_bn2dec(e); - if (hexe && dece) { - BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe); + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, num) <= 0) { + BIO_printf(bio_err, "Error setting RSA length\n"); + goto end; + } + if (!BN_set_word(bn, f4)) { + BIO_printf(bio_err, "Error allocating RSA public exponent\n"); + goto end; + } + if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bn) <= 0) { + BIO_printf(bio_err, "Error setting RSA public exponent\n"); + goto end; } - OPENSSL_free(hexe); - OPENSSL_free(dece); - cb_data.password = passout; - cb_data.prompt_info = outfile; - assert(private); - if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, - (pem_password_cb *)password_callback, - &cb_data)) + if (EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) <= 0) { + BIO_printf(bio_err, "Error setting number of primes\n"); goto end; + } + pkey = app_keygen(ctx, "RSA", num, verbose); + + if (verbose) { + BIGNUM *e = NULL; + + /* Every RSA key has an 'e' */ + EVP_PKEY_get_bn_param(pkey, "e", &e); + if (e == NULL) { + BIO_printf(bio_err, "Error cannot access RSA e\n"); + goto end; + } + hexe = BN_bn2hex(e); + dece = BN_bn2dec(e); + if (hexe && dece) { + BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe); + } + OPENSSL_free(hexe); + OPENSSL_free(dece); + BN_free(e); + } + if (traditional) { + if (!PEM_write_bio_PrivateKey_traditional(out, pkey, enc, NULL, 0, + NULL, passout)) + goto end; + } else { + if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) + goto end; + } ret = 0; end: BN_free(bn); BN_GENCB_free(cb); - RSA_free(rsa); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + EVP_CIPHER_free(enc); BIO_free_all(out); release_engine(eng); OPENSSL_free(passout); @@ -178,9 +246,14 @@ return ret; } -static int genrsa_cb(int p, int n, BN_GENCB *cb) +static int genrsa_cb(EVP_PKEY_CTX *ctx) { char c = '*'; + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + + if (!verbose) + return 1; if (p == 0) c = '.'; @@ -190,7 +263,7 @@ c = '*'; if (p == 3) c = '\n'; - BIO_write(BN_GENCB_get_arg(cb), &c, 1); - (void)BIO_flush(BN_GENCB_get_arg(cb)); + BIO_write(b, &c, 1); + (void)BIO_flush(b); return 1; } diff --git a/apps/include/__DECC_INCLUDE_EPILOGUE.H b/apps/include/__DECC_INCLUDE_EPILOGUE.H new file mode 100644 --- /dev/null +++ b/apps/include/__DECC_INCLUDE_EPILOGUE.H @@ -0,0 +1,22 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C/C++ on VMS, and is included automatically + * after each header file from this directory + */ + +/* + * The C++ compiler doesn't understand these pragmas, even though it + * understands the corresponding command line qualifier. + */ +#ifndef __cplusplus +/* restore state. Must correspond to the save in __decc_include_prologue.h */ +# pragma names restore +#endif diff --git a/apps/include/__DECC_INCLUDE_PROLOGUE.H b/apps/include/__DECC_INCLUDE_PROLOGUE.H new file mode 100644 --- /dev/null +++ b/apps/include/__DECC_INCLUDE_PROLOGUE.H @@ -0,0 +1,26 @@ +/* + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is only used by HP C/C++ on VMS, and is included automatically + * after each header file from this directory + */ + +/* + * The C++ compiler doesn't understand these pragmas, even though it + * understands the corresponding command line qualifier. + */ +#ifndef __cplusplus +/* save state */ +# pragma names save +/* have the compiler shorten symbols larger than 31 chars to 23 chars + * followed by a 8 hex char CRC + */ +# pragma names as_is,shortened +#endif diff --git a/apps/include/app_libctx.h b/apps/include/app_libctx.h new file mode 100644 --- /dev/null +++ b/apps/include/app_libctx.h @@ -0,0 +1,20 @@ +/* + * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_LIBCTX_H +# define OSSL_APPS_LIBCTX_H + +# include + +OSSL_LIB_CTX *app_create_libctx(void); +OSSL_LIB_CTX *app_get0_libctx(void); +int app_set_propq(const char *arg); +const char *app_get0_propq(void); + +#endif diff --git a/apps/include/app_params.h b/apps/include/app_params.h new file mode 100644 --- /dev/null +++ b/apps/include/app_params.h @@ -0,0 +1,14 @@ +/* + * Copyright 2019-2020 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 + * https://www.openssl.org/source/license.html + */ + +#include + +int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent); +void print_param_value(const OSSL_PARAM *p, int indent); + diff --git a/apps/include/apps.h b/apps/include/apps.h new file mode 100644 --- /dev/null +++ b/apps/include/apps.h @@ -0,0 +1,348 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_H +# define OSSL_APPS_H + +# include "e_os.h" /* struct timeval for DTLS */ +# include "internal/nelem.h" +# include "internal/sockets.h" /* for openssl_fdset() */ +# include "internal/cryptlib.h" /* ossl_assert() */ +# include + +# include +# include +# ifndef OPENSSL_NO_POSIX_IO +# include +# include +# endif + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include "apps_ui.h" +# include "opt.h" +# include "fmt.h" +# include "platform.h" +# include "engine_loader.h" +# include "app_libctx.h" + +/* + * quick macro when you need to pass an unsigned char instead of a char. + * this is true for some implementations of the is*() functions, for + * example. + */ +# define _UC(c) ((unsigned char)(c)) + +void app_RAND_load_conf(CONF *c, const char *section); +int app_RAND_write(void); +int app_RAND_load(void); + +extern char *default_config_file; /* may be "" */ +extern BIO *bio_in; +extern BIO *bio_out; +extern BIO *bio_err; +extern const unsigned char tls13_aes128gcmsha256_id[]; +extern const unsigned char tls13_aes256gcmsha384_id[]; +extern BIO_ADDR *ourpeer; + +BIO *dup_bio_in(int format); +BIO *dup_bio_out(int format); +BIO *dup_bio_err(int format); +BIO *bio_open_owner(const char *filename, int format, int private); +BIO *bio_open_default(const char *filename, char mode, int format); +BIO *bio_open_default_quiet(const char *filename, char mode, int format); +CONF *app_load_config_bio(BIO *in, const char *filename); +#define app_load_config(filename) app_load_config_internal(filename, 0) +#define app_load_config_quiet(filename) app_load_config_internal(filename, 1) +CONF *app_load_config_internal(const char *filename, int quiet); +CONF *app_load_config_verbose(const char *filename, int verbose); +int app_load_modules(const CONF *config); +CONF *app_load_config_modules(const char *configfile); +void unbuffer(FILE *fp); +void wait_for_async(SSL *s); +# if defined(OPENSSL_SYS_MSDOS) +int has_stdin_waiting(void); +# endif + +void corrupt_signature(const ASN1_STRING *signature); +int set_cert_times(X509 *x, const char *startdate, const char *enddate, + int days); +int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate); +int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate, + long days, long hours, long secs); + +typedef struct args_st { + int size; + int argc; + char **argv; +} ARGS; + +/* We need both wrap and the "real" function because libcrypto uses both. */ +int wrap_password_callback(char *buf, int bufsiz, int verify, void *cb_data); + +int chopup_args(ARGS *arg, char *buf); +void dump_cert_text(BIO *out, X509 *x); +void print_name(BIO *out, const char *title, const X509_NAME *nm); +void print_bignum_var(BIO *, const BIGNUM *, const char*, + int, unsigned char *); +void print_array(BIO *, const char *, int, const unsigned char *); +int set_nameopt(const char *arg); +unsigned long get_nameopt(void); +int set_dateopt(unsigned long *dateopt, const char *arg); +int set_cert_ex(unsigned long *flags, const char *arg); +int set_name_ex(unsigned long *flags, const char *arg); +int set_ext_copy(int *copy_type, const char *arg); +int copy_extensions(X509 *x, X509_REQ *req, int copy_type); +char *get_passwd(const char *pass, const char *desc); +int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2); +int add_oid_section(CONF *conf); +X509_REQ *load_csr(const char *file, int format, const char *desc); +X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc); +#define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc) +X509_CRL *load_crl(const char *uri, int format, int maybe_stdin, + const char *desc); +void cleanse(char *str); +void clear_free(char *str); +EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *desc); +EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *desc); +EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin, + const char *keytype, const char *desc); +EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin, + const char *keytype, const char *desc, + int suppress_decode_errors); +char *next_item(char *opt); /* in list separated by comma and/or space */ +int load_cert_certs(const char *uri, + X509 **pcert, STACK_OF(X509) **pcerts, + int exclude_http, const char *pass, const char *desc, + X509_VERIFY_PARAM *vpm); +STACK_OF(X509) *load_certs_multifile(char *files, const char *pass, + const char *desc, X509_VERIFY_PARAM *vpm); +X509_STORE *load_certstore(char *input, const char *pass, const char *desc, + X509_VERIFY_PARAM *vpm); +int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs, + const char *pass, const char *desc); +int load_crls(const char *uri, STACK_OF(X509_CRL) **crls, + const char *pass, const char *desc); +int load_key_certs_crls(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc, + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + EVP_PKEY **pparams, + X509 **pcert, STACK_OF(X509) **pcerts, + X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls); +int load_key_cert_crl(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc, + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + X509 **pcert, X509_CRL **pcrl); +X509_STORE *setup_verify(const char *CAfile, int noCAfile, + const char *CApath, int noCApath, + const char *CAstore, int noCAstore); +__owur int ctx_set_verify_locations(SSL_CTX *ctx, + const char *CAfile, int noCAfile, + const char *CApath, int noCApath, + const char *CAstore, int noCAstore); + +# ifndef OPENSSL_NO_CT + +/* + * Sets the file to load the Certificate Transparency log list from. + * If path is NULL, loads from the default file path. + * Returns 1 on success, 0 otherwise. + */ +__owur int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path); + +# endif + +ENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug); +# define setup_engine(e, debug) setup_engine_methods(e, (unsigned int)-1, debug) +void release_engine(ENGINE *e); +int init_engine(ENGINE *e); +int finish_engine(ENGINE *e); +char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc); + +int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e); +const EVP_MD *get_digest_from_engine(const char *name); +const EVP_CIPHER *get_cipher_from_engine(const char *name); + +# ifndef OPENSSL_NO_OCSP +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host, + const char *port, const char *path, + const char *proxy, const char *no_proxy, + int use_ssl, STACK_OF(CONF_VALUE) *headers, + int req_timeout); +# endif + +/* Functions defined in ca.c and also used in ocsp.c */ +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, + ASN1_GENERALIZEDTIME **pinvtm, const char *str); + +# define DB_type 0 +# define DB_exp_date 1 +# define DB_rev_date 2 +# define DB_serial 3 /* index - unique */ +# define DB_file 4 +# define DB_name 5 /* index - unique when active and not + * disabled */ +# define DB_NUMBER 6 + +# define DB_TYPE_REV 'R' /* Revoked */ +# define DB_TYPE_EXP 'E' /* Expired */ +# define DB_TYPE_VAL 'V' /* Valid ; inserted with: ca ... -valid */ +# define DB_TYPE_SUSP 'S' /* Suspended */ + +typedef struct db_attr_st { + int unique_subject; +} DB_ATTR; +typedef struct ca_db_st { + DB_ATTR attributes; + TXT_DB *db; + char *dbfname; +# ifndef OPENSSL_NO_POSIX_IO + struct stat dbst; +# endif +} CA_DB; + +void app_bail_out(char *fmt, ...); +void *app_malloc(size_t sz, const char *what); + +/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */ +BIGNUM *load_serial(const char *serialfile, int *exists, int create, + ASN1_INTEGER **retai); +int save_serial(const char *serialfile, const char *suffix, + const BIGNUM *serial, ASN1_INTEGER **retai); +int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix); +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai); + +CA_DB *load_index(const char *dbfile, DB_ATTR *dbattr); +int index_index(CA_DB *db); +int save_index(const char *dbfile, const char *suffix, CA_DB *db); +int rotate_index(const char *dbfile, const char *new_suffix, + const char *old_suffix); +void free_index(CA_DB *db); +# define index_name_cmp_noconst(a, b) \ + index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ + (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); +int parse_yesno(const char *str, int def); + +X509_NAME *parse_name(const char *str, int chtype, int multirdn, + const char *desc); +void policies_print(X509_STORE_CTX *ctx); +int bio_to_mem(unsigned char **out, int maxlen, BIO *in); +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value); +int x509_ctrl_string(X509 *x, const char *value); +int x509_req_ctrl_string(X509_REQ *x, const char *value); +int init_gen_str(EVP_PKEY_CTX **pctx, + const char *algname, ENGINE *e, int do_param, + OSSL_LIB_CTX *libctx, const char *propq); +int do_X509_sign(X509 *x, EVP_PKEY *pkey, const char *md, + STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx); +int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts); +int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md, + STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, + STACK_OF(OPENSSL_STRING) *vfyopts); +int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md, + STACK_OF(OPENSSL_STRING) *sigopts); + +extern char *psk_key; + + +unsigned char *next_protos_parse(size_t *outlen, const char *in); + +void print_cert_checks(BIO *bio, X509 *x, + const char *checkhost, + const char *checkemail, const char *checkip); + +void store_setup_crl_download(X509_STORE *st); + +typedef struct app_http_tls_info_st { + const char *server; + const char *port; + int use_proxy; + long timeout; + SSL_CTX *ssl_ctx; +} APP_HTTP_TLS_INFO; +BIO *app_http_tls_cb(BIO *hbio, /* APP_HTTP_TLS_INFO */ void *arg, + int connect, int detail); +void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info); +# ifndef OPENSSL_NO_SOCK +ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, + const char *no_proxy, SSL_CTX *ssl_ctx, + const STACK_OF(CONF_VALUE) *headers, + long timeout, const char *expected_content_type, + const ASN1_ITEM *it); +ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, + const char *path, const char *proxy, + const char *no_proxy, SSL_CTX *ctx, + const STACK_OF(CONF_VALUE) *headers, + const char *content_type, + ASN1_VALUE *req, const ASN1_ITEM *req_it, + const char *expected_content_type, + long timeout, const ASN1_ITEM *rsp_it); +# endif + +# define EXT_COPY_NONE 0 +# define EXT_COPY_ADD 1 +# define EXT_COPY_ALL 2 + +# define NETSCAPE_CERT_HDR "certificate" + +# define APP_PASS_LEN 1024 + +/* + * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits + * so that the first bit will never be one, so that the DER encoding + * rules won't force a leading octet. + */ +# define SERIAL_RAND_BITS 159 + +int app_isdir(const char *); +int app_access(const char *, int flag); +int fileno_stdin(void); +int fileno_stdout(void); +int raw_read_stdin(void *, int); +int raw_write_stdout(const void *, int); + +# define TM_START 0 +# define TM_STOP 1 +double app_tminterval(int stop, int usertime); + +void make_uppercase(char *string); + +typedef struct verify_options_st { + int depth; + int quiet; + int error; + int return_error; +} VERIFY_CB_ARGS; + +extern VERIFY_CB_ARGS verify_args; + +OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts, + const OSSL_PARAM *paramdefs); +void app_params_free(OSSL_PARAM *params); +int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name); +void app_providers_cleanup(void); + +EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose); +EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg); + +#endif diff --git a/apps/include/apps_ui.h b/apps/include/apps_ui.h new file mode 100644 --- /dev/null +++ b/apps/include/apps_ui.h @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2020 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_UI_H +# define OSSL_APPS_UI_H + + +# define PW_MIN_LENGTH 4 +typedef struct pw_cb_data { + const void *password; + const char *prompt_info; +} PW_CB_DATA; + +int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data); + +int setup_ui_method(void); +void destroy_ui_method(void); +int set_base_ui_method(const UI_METHOD *ui_method); +const UI_METHOD *get_ui_method(void); + +extern BIO *bio_err; + +#endif diff --git a/apps/include/cmp_mock_srv.h b/apps/include/cmp_mock_srv.h new file mode 100644 --- /dev/null +++ b/apps/include/cmp_mock_srv.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Siemens AG 2018-2020 + * + * 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_CMP_MOCK_SRV_H +# define OSSL_APPS_CMP_MOCK_SRV_H + +# include +# ifndef OPENSSL_NO_CMP + +# include + +OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, + const char *propq); +void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx); + +int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); +int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *chain); +int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *caPubs); +int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, + int fail_info, const char *text); +int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val); +int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count); +int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec); + +# endif /* !defined(OPENSSL_NO_CMP) */ +#endif /* !defined(OSSL_APPS_CMP_MOCK_SRV_H) */ diff --git a/apps/include/ec_common.h b/apps/include/ec_common.h new file mode 100644 --- /dev/null +++ b/apps/include/ec_common.h @@ -0,0 +1,23 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OPENSSL_NO_EC +static const char *point_format_options[] = { + "uncompressed", + "compressed", + "hybrid", + NULL +}; + +static const char *asn1_encoding_options[] = { + "named_curve", + "explicit", + NULL +}; +#endif diff --git a/apps/include/engine_loader.h b/apps/include/engine_loader.h new file mode 100644 --- /dev/null +++ b/apps/include/engine_loader.h @@ -0,0 +1,21 @@ +/* + * Copyright 2018-2022 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 + * https://www.openssl.org/source/license.html + */ +#ifndef HEADER_ENGINE_LOADER_H +# define HEADER_ENGINE_LOADER_H + +# include + +/* this is a private URI scheme */ +# define ENGINE_SCHEME "org.openssl.engine" +# define ENGINE_SCHEME_COLON (ENGINE_SCHEME ":") + +int setup_engine_loader(void); +void destroy_engine_loader(void); + +#endif diff --git a/apps/include/fmt.h b/apps/include/fmt.h new file mode 100644 --- /dev/null +++ b/apps/include/fmt.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Options are shared by apps (see apps.h) and the test system + * (see test/testutil.h'). + * In order to remove the dependency between apps and options, the following + * shared fields have been moved into this file. + */ + +#ifndef OSSL_APPS_FMT_H +#define OSSL_APPS_FMT_H + +/* + * On some platforms, it's important to distinguish between text and binary + * files. On some, there might even be specific file formats for different + * contents. The FORMAT_xxx macros are meant to express an intent with the + * file being read or created. + */ +# define B_FORMAT_TEXT 0x8000 +# define FORMAT_UNDEF 0 +# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */ +# define FORMAT_BINARY 2 /* Generic binary */ +# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */ +# define FORMAT_ASN1 4 /* ASN.1/DER */ +# define FORMAT_PEM (5 | B_FORMAT_TEXT) +# define FORMAT_PKCS12 6 +# define FORMAT_SMIME (7 | B_FORMAT_TEXT) +# define FORMAT_ENGINE 8 /* Not really a file format */ +# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPublicKey format */ +# define FORMAT_ASN1RSA 10 /* DER RSAPublicKey format */ +# define FORMAT_MSBLOB 11 /* MS Key blob format */ +# define FORMAT_PVK 12 /* MS PVK file format */ +# define FORMAT_HTTP 13 /* Download using HTTP */ +# define FORMAT_NSS 14 /* NSS keylog format */ + +int FMT_istext(int format); + +#endif /* OSSL_APPS_FMT_H_ */ diff --git a/apps/include/function.h b/apps/include/function.h new file mode 100644 --- /dev/null +++ b/apps/include/function.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019-2020 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_FUNCTION_H +# define OSSL_APPS_FUNCTION_H + +# include +# include "opt.h" + +#define DEPRECATED_NO_ALTERNATIVE "unknown" + +typedef enum FUNC_TYPE { + FT_none, FT_general, FT_md, FT_cipher, FT_pkey, + FT_md_alg, FT_cipher_alg +} FUNC_TYPE; + +typedef struct function_st { + FUNC_TYPE type; + const char *name; + int (*func)(int argc, char *argv[]); + const OPTIONS *help; + const char *deprecated_alternative; + const char *deprecated_version; +} FUNCTION; + +DEFINE_LHASH_OF(FUNCTION); + +/* Structure to hold the number of columns to be displayed and the + * field width used to display them. + */ +typedef struct { + int columns; + int width; +} DISPLAY_COLUMNS; + +void calculate_columns(FUNCTION *functions, DISPLAY_COLUMNS *dc); + +#endif diff --git a/apps/include/http_server.h b/apps/include/http_server.h new file mode 100644 --- /dev/null +++ b/apps/include/http_server.h @@ -0,0 +1,125 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_HTTP_SERVER_H +# define OSSL_HTTP_SERVER_H + +# include "apps.h" + +# ifndef HAVE_FORK +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) +# define HAVE_FORK 0 +# else +# define HAVE_FORK 1 +# endif +# endif + +# if HAVE_FORK +# undef NO_FORK +# else +# define NO_FORK +# endif + +# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \ + && !defined(OPENSSL_NO_POSIX_IO) +# define HTTP_DAEMON +# include +# include +# include +# include +# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ +# else +# undef LOG_DEBUG +# undef LOG_INFO +# undef LOG_WARNING +# undef LOG_ERR +# define LOG_DEBUG 7 +# define LOG_INFO 6 +# define LOG_WARNING 4 +# define LOG_ERR 3 +# endif + +/*- + * Log a message to syslog if multi-threaded HTTP_DAEMON, else to bio_err + * prog: the name of the current app + * level: the severity of the message, e.g., LOG_ERR + * fmt: message with potential extra parameters like with printf() + * returns nothing + */ +void log_message(const char *prog, int level, const char *fmt, ...); + +# ifndef OPENSSL_NO_SOCK +/*- + * Initialize an HTTP server by setting up its listening BIO + * prog: the name of the current app + * port: the port to listen on + * returns a BIO for accepting requests, NULL on error + */ +BIO *http_server_init_bio(const char *prog, const char *port); + +/*- + * Accept an ASN.1-formatted HTTP request + * it: the expected request ASN.1 type + * preq: pointer to variable where to place the parsed request + * ppath: pointer to variable where to place the request path, or NULL + * pcbio: pointer to variable where to place the BIO for sending the response to + * acbio: the listening bio (typically as returned by http_server_init_bio()) + * found_keep_alive: for returning flag if client requests persistent connection + * prog: the name of the current app, for diagnostics only + * port: the local port listening to, for diagnostics only + * accept_get: whether to accept GET requests (in addition to POST requests) + * timeout: connection timeout (in seconds), or 0 for none/infinite + * returns 0 in case caller should retry, then *preq == *ppath == *pcbio == NULL + * returns -1 on fatal error; also then holds *preq == *ppath == *pcbio == NULL + * returns 1 otherwise. In this case it is guaranteed that *pcbio != NULL while + * *ppath == NULL and *preq == NULL if and only if the request is invalid, + * On return value 1 the caller is responsible for sending an HTTP response, + * using http_server_send_asn1_resp() or http_server_send_status(). + * The caller must free any non-NULL *preq, *ppath, and *pcbio pointers. + */ +int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, + char **ppath, BIO **pcbio, BIO *acbio, + int *found_keep_alive, + const char *prog, const char *port, + int accept_get, int timeout); + +/*- + * Send an ASN.1-formatted HTTP response + * cbio: destination BIO (typically as returned by http_server_get_asn1_req()) + * note: cbio should not do an encoding that changes the output length + * keep_alive: grant persistent connnection + * content_type: string identifying the type of the response + * it: the response ASN.1 type + * resp: the response to send + * returns 1 on success, 0 on failure + */ +int http_server_send_asn1_resp(BIO *cbio, int keep_alive, + const char *content_type, + const ASN1_ITEM *it, const ASN1_VALUE *resp); + +/*- + * Send a trivial HTTP response, typically to report an error or OK + * cbio: destination BIO (typically as returned by http_server_get_asn1_req()) + * status: the status code to send + * reason: the corresponding human-readable string + * returns 1 on success, 0 on failure + */ +int http_server_send_status(BIO *cbio, int status, const char *reason); + +# endif + +# ifdef HTTP_DAEMON +extern int multi; +extern int acfd; + +void socket_timeout(int signum); +void spawn_loop(const char *prog); +# endif + +#endif diff --git a/apps/include/names.h b/apps/include/names.h new file mode 100644 --- /dev/null +++ b/apps/include/names.h @@ -0,0 +1,17 @@ +/* + * Copyright 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 + * https://www.openssl.org/source/license.html + */ + +#include + +/* Standard comparing function for names */ +int name_cmp(const char * const *a, const char * const *b); +/* collect_names is meant to be used with EVP_{type}_doall_names */ +void collect_names(const char *name, void *vdata); +/* Sorts and prints a stack of names to |out| */ +void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names); diff --git a/apps/include/opt.h b/apps/include/opt.h new file mode 100644 --- /dev/null +++ b/apps/include/opt.h @@ -0,0 +1,400 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef OSSL_APPS_OPT_H +#define OSSL_APPS_OPT_H + +#include +#include +#include +#include + +#define OPT_COMMON OPT_ERR = -1, OPT_EOF = 0, OPT_HELP + +/* + * Common verification options. + */ +# define OPT_V_ENUM \ + OPT_V__FIRST=2000, \ + OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \ + OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \ + OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \ + OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \ + OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \ + OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \ + OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \ + OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \ + OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \ + OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \ + OPT_V__LAST + +# define OPT_V_OPTIONS \ + OPT_SECTION("Validation"), \ + { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \ + { "purpose", OPT_V_PURPOSE, 's', \ + "certificate chain purpose"}, \ + { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \ + { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \ + "chain depth limit" }, \ + { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \ + "chain authentication security level" }, \ + { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \ + { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \ + "expected peer hostname" }, \ + { "verify_email", OPT_V_VERIFY_EMAIL, 's', \ + "expected peer email" }, \ + { "verify_ip", OPT_V_VERIFY_IP, 's', \ + "expected peer IP address" }, \ + { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \ + "permit unhandled critical extensions"}, \ + { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \ + { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \ + { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \ + { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \ + { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \ + "set policy variable require-explicit-policy"}, \ + { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \ + "set policy variable inhibit-any-policy"}, \ + { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \ + "set policy variable inhibit-policy-mapping"}, \ + { "x509_strict", OPT_V_X509_STRICT, '-', \ + "disable certificate compatibility work-arounds"}, \ + { "extended_crl", OPT_V_EXTENDED_CRL, '-', \ + "enable extended CRL features"}, \ + { "use_deltas", OPT_V_USE_DELTAS, '-', \ + "use delta CRLs"}, \ + { "policy_print", OPT_V_POLICY_PRINT, '-', \ + "print policy processing diagnostics"}, \ + { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \ + "check root CA self-signatures"}, \ + { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \ + "search trust store first (default)" }, \ + { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \ + { "suiteB_128", OPT_V_SUITEB_128, '-', \ + "Suite B 128-bit mode allowing 192-bit algorithms"}, \ + { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \ + { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \ + "accept chains anchored by intermediate trust-store CAs"}, \ + { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \ + { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \ + { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" } + +# define OPT_V_CASES \ + OPT_V__FIRST: case OPT_V__LAST: break; \ + case OPT_V_POLICY: \ + case OPT_V_PURPOSE: \ + case OPT_V_VERIFY_NAME: \ + case OPT_V_VERIFY_DEPTH: \ + case OPT_V_VERIFY_AUTH_LEVEL: \ + case OPT_V_ATTIME: \ + case OPT_V_VERIFY_HOSTNAME: \ + case OPT_V_VERIFY_EMAIL: \ + case OPT_V_VERIFY_IP: \ + case OPT_V_IGNORE_CRITICAL: \ + case OPT_V_ISSUER_CHECKS: \ + case OPT_V_CRL_CHECK: \ + case OPT_V_CRL_CHECK_ALL: \ + case OPT_V_POLICY_CHECK: \ + case OPT_V_EXPLICIT_POLICY: \ + case OPT_V_INHIBIT_ANY: \ + case OPT_V_INHIBIT_MAP: \ + case OPT_V_X509_STRICT: \ + case OPT_V_EXTENDED_CRL: \ + case OPT_V_USE_DELTAS: \ + case OPT_V_POLICY_PRINT: \ + case OPT_V_CHECK_SS_SIG: \ + case OPT_V_TRUSTED_FIRST: \ + case OPT_V_SUITEB_128_ONLY: \ + case OPT_V_SUITEB_128: \ + case OPT_V_SUITEB_192: \ + case OPT_V_PARTIAL_CHAIN: \ + case OPT_V_NO_ALT_CHAINS: \ + case OPT_V_NO_CHECK_TIME: \ + case OPT_V_ALLOW_PROXY_CERTS + +/* + * Common "extended validation" options. + */ +# define OPT_X_ENUM \ + OPT_X__FIRST=1000, \ + OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \ + OPT_X_CERTFORM, OPT_X_KEYFORM, \ + OPT_X__LAST + +# define OPT_X_OPTIONS \ + OPT_SECTION("Extended certificate"), \ + { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \ + { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \ + { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \ + { "xchain_build", OPT_X_CHAIN_BUILD, '-', \ + "build certificate chain for the extended certificates"}, \ + { "xcertform", OPT_X_CERTFORM, 'F', \ + "format of Extended certificate (PEM/DER/P12); has no effect" }, \ + { "xkeyform", OPT_X_KEYFORM, 'F', \ + "format of Extended certificate's key (DER/PEM/P12); has no effect"} + +# define OPT_X_CASES \ + OPT_X__FIRST: case OPT_X__LAST: break; \ + case OPT_X_KEY: \ + case OPT_X_CERT: \ + case OPT_X_CHAIN: \ + case OPT_X_CHAIN_BUILD: \ + case OPT_X_CERTFORM: \ + case OPT_X_KEYFORM + +/* + * Common SSL options. + * Any changes here must be coordinated with ../ssl/ssl_conf.c + */ +# define OPT_S_ENUM \ + OPT_S__FIRST=3000, \ + OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \ + OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ + OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_CLIENTRENEG, \ + OPT_S_LEGACYCONN, \ + OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ + OPT_S_PRIORITIZE_CHACHA, \ + OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ + OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ + OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ + OPT_S_MINPROTO, OPT_S_MAXPROTO, \ + OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S_NO_ETM, OPT_S__LAST + +# define OPT_S_OPTIONS \ + OPT_SECTION("TLS/SSL"), \ + {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \ + {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \ + {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \ + {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \ + {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \ + {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ + {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ + {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ + {"no_ticket", OPT_S_NOTICKET, '-', \ + "Disable use of TLS session tickets"}, \ + {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ + {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \ + "Enable use of legacy renegotiation (dangerous)"}, \ + {"client_renegotiation", OPT_S_CLIENTRENEG, '-', \ + "Allow client-initiated renegotiation" }, \ + {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \ + "Disable all renegotiation."}, \ + {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \ + "Allow initial connection to servers that don't support RI"}, \ + {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \ + "Disallow session resumption on renegotiation"}, \ + {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \ + "Disallow initial connection to servers that don't support RI"}, \ + {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ + "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ + {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ + "Prioritize ChaCha ciphers when preferred by clients"}, \ + {"strict", OPT_S_STRICT, '-', \ + "Enforce strict certificate checks as per TLS standard"}, \ + {"sigalgs", OPT_S_SIGALGS, 's', \ + "Signature algorithms to support (colon-separated list)" }, \ + {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \ + "Signature algorithms to support for client certificate" \ + " authentication (colon-separated list)" }, \ + {"groups", OPT_S_GROUPS, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"curves", OPT_S_CURVES, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"named_curve", OPT_S_NAMEDCURVE, 's', \ + "Elliptic curve used for ECDHE (server-side only)" }, \ + {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ + {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ + {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \ + {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \ + {"record_padding", OPT_S_RECORD_PADDING, 's', \ + "Block size to pad TLS 1.3 records to."}, \ + {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ + "Perform all sorts of protocol violations for testing purposes"}, \ + {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ + "Disable TLSv1.3 middlebox compat mode" }, \ + {"no_etm", OPT_S_NO_ETM, '-', \ + "Disable Encrypt-then-Mac extension"} + +# define OPT_S_CASES \ + OPT_S__FIRST: case OPT_S__LAST: break; \ + case OPT_S_NOSSL3: \ + case OPT_S_NOTLS1: \ + case OPT_S_NOTLS1_1: \ + case OPT_S_NOTLS1_2: \ + case OPT_S_NOTLS1_3: \ + case OPT_S_BUGS: \ + case OPT_S_NO_COMP: \ + case OPT_S_COMP: \ + case OPT_S_NOTICKET: \ + case OPT_S_SERVERPREF: \ + case OPT_S_LEGACYRENEG: \ + case OPT_S_CLIENTRENEG: \ + case OPT_S_LEGACYCONN: \ + case OPT_S_ONRESUMP: \ + case OPT_S_NOLEGACYCONN: \ + case OPT_S_ALLOW_NO_DHE_KEX: \ + case OPT_S_PRIORITIZE_CHACHA: \ + case OPT_S_STRICT: \ + case OPT_S_SIGALGS: \ + case OPT_S_CLIENTSIGALGS: \ + case OPT_S_GROUPS: \ + case OPT_S_CURVES: \ + case OPT_S_NAMEDCURVE: \ + case OPT_S_CIPHER: \ + case OPT_S_CIPHERSUITES: \ + case OPT_S_RECORD_PADDING: \ + case OPT_S_NO_RENEGOTIATION: \ + case OPT_S_MINPROTO: \ + case OPT_S_MAXPROTO: \ + case OPT_S_DEBUGBROKE: \ + case OPT_S_NO_MIDDLEBOX: \ + case OPT_S_NO_ETM + +#define IS_NO_PROT_FLAG(o) \ + (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ + || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3) + +/* + * Random state options. + */ +# define OPT_R_ENUM \ + OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST + +# define OPT_R_OPTIONS \ + OPT_SECTION("Random state"), \ + {"rand", OPT_R_RAND, 's', "Load the given file(s) into the random number generator"}, \ + {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"} + +# define OPT_R_CASES \ + OPT_R__FIRST: case OPT_R__LAST: break; \ + case OPT_R_RAND: case OPT_R_WRITERAND + +/* + * Provider options. + */ +# define OPT_PROV_ENUM \ + OPT_PROV__FIRST=1600, \ + OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \ + OPT_PROV__LAST + +# define OPT_CONFIG_OPTION \ + { "config", OPT_CONFIG, '<', "Load a configuration file (this may load modules)" } + +# define OPT_PROV_OPTIONS \ + OPT_SECTION("Provider"), \ + { "provider-path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \ + { "provider", OPT_PROV_PROVIDER, 's', "Provider to load (can be specified multiple times)" }, \ + { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" } + +# define OPT_PROV_CASES \ + OPT_PROV__FIRST: case OPT_PROV__LAST: break; \ + case OPT_PROV_PROVIDER: \ + case OPT_PROV_PROVIDER_PATH: \ + case OPT_PROV_PROPQUERY + +/* + * Option parsing. + */ +extern const char OPT_HELP_STR[]; +extern const char OPT_MORE_STR[]; +extern const char OPT_SECTION_STR[]; +extern const char OPT_PARAM_STR[]; + +typedef struct options_st { + const char *name; + int retval; + /* + * value type: - no value (also the value zero), n number, p positive + * number, u unsigned, l long, s string, < input file, > output file, + * f any format, F der/pem format, E der/pem/engine format identifier. + * l, n and u include zero; p does not. + */ + int valtype; + const char *helpstr; +} OPTIONS; +/* Special retval values: */ +#define OPT_PARAM 0 /* same as OPT_EOF usually defined in apps */ +#define OPT_DUP -2 /* marks duplicate occurrence of option in help output */ + +/* + * A string/int pairing; widely use for option value lookup, hence the + * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use + * the "generic" name STRINT_PAIR. + */ +typedef struct string_int_pair_st { + const char *name; + int retval; +} OPT_PAIR, STRINT_PAIR; + +/* Flags to pass into opt_format; see FORMAT_xxx, below. */ +# define OPT_FMT_PEMDER (1L << 1) +# define OPT_FMT_PKCS12 (1L << 2) +# define OPT_FMT_SMIME (1L << 3) +# define OPT_FMT_ENGINE (1L << 4) +# define OPT_FMT_MSBLOB (1L << 5) +/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */ +# define OPT_FMT_NSS (1L << 7) +# define OPT_FMT_TEXT (1L << 8) +# define OPT_FMT_HTTP (1L << 9) +# define OPT_FMT_PVK (1L << 10) +# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) +# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) +# define OPT_FMT_ANY ( \ + OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ + OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ + OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) + +/* Divide options into sections when displaying usage */ +#define OPT_SECTION(sec) { OPT_SECTION_STR, 1, '-', sec " options:\n" } +#define OPT_PARAMETERS() { OPT_PARAM_STR, 1, '-', "Parameters:\n" } + +const char *opt_path_end(const char *filename); +char *opt_init(int ac, char **av, const OPTIONS * o); +char *opt_progname(const char *argv0); +char *opt_appname(const char *argv0); +char *opt_getprog(void); +void opt_help(const OPTIONS * list); + +void opt_begin(void); +int opt_next(void); +char *opt_flag(void); +char *opt_arg(void); +char *opt_unknown(void); +int opt_cipher(const char *name, EVP_CIPHER **cipherp); +int opt_cipher_any(const char *name, EVP_CIPHER **cipherp); +int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp); +int opt_md(const char *name, EVP_MD **mdp); +int opt_md_silent(const char *name, EVP_MD **mdp); + +int opt_int(const char *arg, int *result); +int opt_int_arg(void); +int opt_long(const char *arg, long *result); +int opt_ulong(const char *arg, unsigned long *result); +int opt_intmax(const char *arg, ossl_intmax_t *result); +int opt_uintmax(const char *arg, ossl_uintmax_t *result); + +int opt_isdir(const char *name); +int opt_format(const char *s, unsigned long flags, int *result); +void print_format_error(int format, unsigned long flags); +int opt_printf_stderr(const char *fmt, ...); +int opt_string(const char *name, const char **options); +int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); + +int opt_verify(int i, X509_VERIFY_PARAM *vpm); +int opt_rand(int i); +int opt_provider(int i); +int opt_provider_option_given(void); + +char **opt_rest(void); +int opt_num_rest(void); + +/* Returns non-zero if legacy paths are still available */ +int opt_legacy_okay(void); + + +#endif /* OSSL_APPS_OPT_H */ diff --git a/apps/include/platform.h b/apps/include/platform.h new file mode 100644 --- /dev/null +++ b/apps/include/platform.h @@ -0,0 +1,32 @@ +/* + * Copyright 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_PLATFORM_H +# define OSSL_APPS_PLATFORM_H + +# include + +# if defined(OPENSSL_SYS_VMS) && defined(__DECC) +/* + * VMS C only for now, implemented in vms_decc_init.c + * If other C compilers forget to terminate argv with NULL, this function + * can be re-used. + */ +char **copy_argv(int *argc, char *argv[]); +# endif + +# ifdef _WIN32 +/* + * Win32-specific argv initialization that splits OS-supplied UNICODE + * command line string to array of UTF8-encoded strings. + */ +void win32_utf8argv(int *argc, char **argv[]); +# endif + +#endif diff --git a/apps/include/s_apps.h b/apps/include/s_apps.h new file mode 100644 --- /dev/null +++ b/apps/include/s_apps.h @@ -0,0 +1,108 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include + +#define PORT "4433" +#define PROTOCOL "tcp" + +typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context); +int report_server_accept(BIO *out, int asock, int with_address, int with_pid); +int do_server(int *accept_sock, const char *host, const char *port, + int family, int type, int protocol, do_server_cb cb, + unsigned char *context, int naccept, BIO *bio_s_out); + +int verify_callback(int ok, X509_STORE_CTX *ctx); + +int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); +int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, + STACK_OF(X509) *chain, int build_chain); +int ssl_print_sigalgs(BIO *out, SSL *s); +int ssl_print_point_formats(BIO *out, SSL *s); +int ssl_print_groups(BIO *out, SSL *s, int noshared); +int ssl_print_tmp_key(BIO *out, SSL *s); +int init_client(int *sock, const char *host, const char *port, + const char *bindhost, const char *bindport, + int family, int type, int protocol); +int should_retry(int i); +void do_ssl_shutdown(SSL *ssl); + +long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len, + int argi, long argl, int ret, size_t *processed); + +void apps_ssl_info_callback(const SSL *s, int where, int ret); +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg); +void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data, + int len, void *arg); + +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); + +#ifdef __VMS /* 31 char symbol name limit */ +# define generate_stateless_cookie_callback generate_stateless_cookie_cb +# define verify_stateless_cookie_callback verify_stateless_cookie_cb +#endif + +int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, + size_t *cookie_len); +int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, + size_t cookie_len); + +typedef struct ssl_excert_st SSL_EXCERT; + +void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc); +void ssl_excert_free(SSL_EXCERT *exc); +int args_excert(int option, SSL_EXCERT **pexc); +int load_excert(SSL_EXCERT **pexc); +void print_verify_detail(SSL *s, BIO *bio); +void print_ssl_summary(SSL *s); +int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx); +int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, + int crl_download); +int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath, + const char *vfyCAfile, const char *vfyCAstore, + const char *chCApath, const char *chCAfile, + const char *chCAstore, STACK_OF(X509_CRL) *crls, + int crl_download); +void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose); +int set_keylog_file(SSL_CTX *ctx, const char *keylog_file); +void print_ca_names(BIO *bio, SSL *s); + +#ifndef OPENSSL_NO_SRP +/* The client side SRP context that we pass to all SRP related callbacks */ +typedef struct srp_arg_st { + char *srppassin; + char *srplogin; + int msg; /* copy from c_msg */ + int debug; /* copy from c_debug */ + int amp; /* allow more groups */ + int strength; /* minimal size for N */ +} SRP_ARG; + +int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg, + int c_debug); +void set_up_dummy_srp(SSL_CTX *ctx); + +/* The server side SRP context that we pass to all SRP related callbacks */ +typedef struct srpsrvparm_st { + char *login; + SRP_VBASE *vb; + SRP_user_pwd *user; +} srpsrvparm; + +int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm, + char *srpuserseed, char *srp_verifier_file); +void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out); +#endif /* OPENSSL_NO_SRP */ diff --git a/apps/include/vms_term_sock.h b/apps/include/vms_term_sock.h new file mode 100644 --- /dev/null +++ b/apps/include/vms_term_sock.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016 VMS Software, Inc. 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_APPS_VMS_TERM_SOCK_H +# define OSSL_APPS_VMS_TERM_SOCK_H + +/* +** Terminal Socket Function Codes +*/ +# define TERM_SOCK_CREATE 1 +# define TERM_SOCK_DELETE 2 + +/* +** Terminal Socket Status Codes +*/ +# define TERM_SOCK_FAILURE 0 +# define TERM_SOCK_SUCCESS 1 + +/* +** Terminal Socket Prototype +*/ +int TerminalSocket (int FunctionCode, int *ReturnSocket); + +#endif diff --git a/apps/info.c b/apps/info.c new file mode 100644 --- /dev/null +++ b/apps/info.c @@ -0,0 +1,104 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "apps.h" +#include "progs.h" + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_CONFIGDIR, OPT_ENGINESDIR, OPT_MODULESDIR, OPT_DSOEXT, OPT_DIRNAMESEP, + OPT_LISTSEP, OPT_SEEDS, OPT_CPUSETTINGS +} OPTION_CHOICE; + +const OPTIONS info_options[] = { + + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Output"), + {"configdir", OPT_CONFIGDIR, '-', "Default configuration file directory"}, + {"enginesdir", OPT_ENGINESDIR, '-', "Default engine module directory"}, + {"modulesdir", OPT_MODULESDIR, '-', + "Default module directory (other than engine modules)"}, + {"dsoext", OPT_DSOEXT, '-', "Configured extension for modules"}, + {"dirnamesep", OPT_DIRNAMESEP, '-', "Directory-filename separator"}, + {"listsep", OPT_LISTSEP, '-', "List separator character"}, + {"seeds", OPT_SEEDS, '-', "Seed sources"}, + {"cpusettings", OPT_CPUSETTINGS, '-', "CPU settings info"}, + {NULL} +}; + +int info_main(int argc, char **argv) +{ + int ret = 1, dirty = 0, type = 0; + char *prog; + OPTION_CHOICE o; + + prog = opt_init(argc, argv, info_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + default: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(info_options); + ret = 0; + goto end; + case OPT_CONFIGDIR: + type = OPENSSL_INFO_CONFIG_DIR; + dirty++; + break; + case OPT_ENGINESDIR: + type = OPENSSL_INFO_ENGINES_DIR; + dirty++; + break; + case OPT_MODULESDIR: + type = OPENSSL_INFO_MODULES_DIR; + dirty++; + break; + case OPT_DSOEXT: + type = OPENSSL_INFO_DSO_EXTENSION; + dirty++; + break; + case OPT_DIRNAMESEP: + type = OPENSSL_INFO_DIR_FILENAME_SEPARATOR; + dirty++; + break; + case OPT_LISTSEP: + type = OPENSSL_INFO_LIST_SEPARATOR; + dirty++; + break; + case OPT_SEEDS: + type = OPENSSL_INFO_SEED_SOURCE; + dirty++; + break; + case OPT_CPUSETTINGS: + type = OPENSSL_INFO_CPU_SETTINGS; + dirty++; + break; + } + } + if (opt_num_rest() != 0) + goto opthelp; + if (dirty > 1) { + BIO_printf(bio_err, "%s: Only one item allowed\n", prog); + goto opthelp; + } + if (dirty == 0) { + BIO_printf(bio_err, "%s: No items chosen\n", prog); + goto opthelp; + } + + BIO_printf(bio_out, "%s\n", OPENSSL_info(type)); + ret = 0; + end: + return ret; +} diff --git a/apps/insta.ca.crt b/apps/insta.ca.crt new file mode 100644 index 0000000000000000000000000000000000000000..6aea6d4f9794cdfb0900a3f0aba6f67b5221fde0 GIT binary patch literal 916 zc$_n6VxC~o#8k0>nTe5!iJ5b%sR1t=r&gOs+jm|@Mpjk^11m#r15P&PP!={}CO1z* zVFN)BhfA2tGq1QLQNblOH{VdqKm;VnEX<1#RB(1QkQ3)MFf%YTFfy<(u`srX66ZBC zH8e6dgmNh|yNOW=*{O`I49rc8{0u;GE~X|%Muwx$w_Q49zc8&*L0{>u*ePCxyR|E% z|4MXei7r@V_s1%fgC|zDa{IH&jn~-A)!mk#`*~u*j{{cQw6`l8HB4vN<6W&)Rib7U z@nM&o?}fdyecT=#IDdYN>AtKCJv-}nci!11{>ipcoAJ-rd(x!rRL&qaTh%3zOH{># zu2p)Ta?O|S59oB_p88IM_4-XVhozE#!;*j16)G0B7oU909hU9=+eASyw3Acvb>-!f z%co`e#CM=cHN)7Zt0)-i`PxH=9+i=OgVE{>Md=pX45CO zPiLIF5Rh(>%p;9;IO4{G%Lt{&}5D%!~|-iyP+|G|o1V z2Zo@mGK++PSc8a7#oZkTd&9r7YQ^O~h$!;<<)WHsAPZ8!$0EjpU78Oh&CkgApM?dO zPS^~DKzv~kpTmF+NHH-o7?`qgCbW4lw*7Eo^^!kto_|06m$YT1Wrg_n`mI%; z7IoifIMOxu{>eEjsv_e3wX(kVsclqpb+QsY$6kHPLt}>zU*Y4)ADhLZG)+R8%fBnbHEV--eypEh^T5`D&0HbGF4gdfE literal 0 Hc$@ + +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT, + OPT_CIPHER, OPT_DIGEST, OPT_MAC, + OPT_PROV_ENUM +} OPTION_CHOICE; + +const OPTIONS kdf_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"}, + + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form"}, + {"cipher", OPT_CIPHER, 's', "Cipher"}, + {"digest", OPT_DIGEST, 's', "Digest"}, + {"mac", OPT_MAC, 's', "MAC"}, + {OPT_MORE_STR, 1, '-', "See 'Supported Controls' in the EVP_KDF_ docs\n"}, + {"keylen", OPT_KEYLEN, 's', "The size of the output derived key"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, + {"binary", OPT_BIN, '-', + "Output in binary format (default is hexadecimal)"}, + + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"kdf_name", 0, 0, "Name of the KDF algorithm"}, + {NULL} +}; + +static char *alloc_kdf_algorithm_name(STACK_OF(OPENSSL_STRING) **optp, + const char *name, const char *arg) +{ + size_t len = strlen(name) + strlen(arg) + 2; + char *res; + + if (*optp == NULL) + *optp = sk_OPENSSL_STRING_new_null(); + if (*optp == NULL) + return NULL; + + res = app_malloc(len, "algorithm name"); + BIO_snprintf(res, len, "%s:%s", name, arg); + if (sk_OPENSSL_STRING_push(*optp, res)) + return res; + OPENSSL_free(res); + return NULL; +} + +int kdf_main(int argc, char **argv) +{ + int ret = 1, out_bin = 0; + OPTION_CHOICE o; + STACK_OF(OPENSSL_STRING) *opts = NULL; + char *prog, *hexout = NULL; + const char *outfile = NULL; + unsigned char *dkm_bytes = NULL; + size_t dkm_len = 0; + BIO *out = NULL; + EVP_KDF *kdf = NULL; + EVP_KDF_CTX *ctx = NULL; + char *digest = NULL, *cipher = NULL, *mac = NULL; + + prog = opt_init(argc, argv, kdf_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + default: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto err; + case OPT_HELP: + opt_help(kdf_options); + ret = 0; + goto err; + case OPT_BIN: + out_bin = 1; + break; + case OPT_KEYLEN: + dkm_len = (size_t)atoi(opt_arg()); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_KDFOPT: + if (opts == NULL) + opts = sk_OPENSSL_STRING_new_null(); + if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) + goto opthelp; + break; + case OPT_CIPHER: + OPENSSL_free(cipher); + cipher = alloc_kdf_algorithm_name(&opts, "cipher", opt_arg()); + if (cipher == NULL) + goto opthelp; + break; + case OPT_DIGEST: + OPENSSL_free(digest); + digest = alloc_kdf_algorithm_name(&opts, "digest", opt_arg()); + if (digest == NULL) + goto opthelp; + break; + case OPT_MAC: + OPENSSL_free(mac); + mac = alloc_kdf_algorithm_name(&opts, "mac", opt_arg()); + if (mac == NULL) + goto opthelp; + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto err; + break; + } + } + + /* One argument, the KDF name. */ + argc = opt_num_rest(); + argv = opt_rest(); + if (argc != 1) + goto opthelp; + + if ((kdf = EVP_KDF_fetch(app_get0_libctx(), argv[0], + app_get0_propq())) == NULL) { + BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]); + goto opthelp; + } + + ctx = EVP_KDF_CTX_new(kdf); + if (ctx == NULL) + goto err; + + if (opts != NULL) { + int ok = 1; + OSSL_PARAM *params = + app_params_new_from_opts(opts, EVP_KDF_settable_ctx_params(kdf)); + + if (params == NULL) + goto err; + + if (!EVP_KDF_CTX_set_params(ctx, params)) { + BIO_printf(bio_err, "KDF parameter error\n"); + ERR_print_errors(bio_err); + ok = 0; + } + app_params_free(params); + if (!ok) + goto err; + } + + out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); + if (out == NULL) + goto err; + + if (dkm_len <= 0) { + BIO_printf(bio_err, "Invalid derived key length.\n"); + goto err; + } + dkm_bytes = app_malloc(dkm_len, "out buffer"); + if (dkm_bytes == NULL) + goto err; + + if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len, NULL)) { + BIO_printf(bio_err, "EVP_KDF_derive failed\n"); + goto err; + } + + if (out_bin) { + BIO_write(out, dkm_bytes, dkm_len); + } else { + hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len); + if (hexout == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + BIO_printf(out, "%s\n\n", hexout); + } + + ret = 0; +err: + if (ret != 0) + ERR_print_errors(bio_err); + OPENSSL_clear_free(dkm_bytes, dkm_len); + sk_OPENSSL_STRING_free(opts); + EVP_KDF_free(kdf); + EVP_KDF_CTX_free(ctx); + BIO_free(out); + OPENSSL_free(hexout); + OPENSSL_free(cipher); + OPENSSL_free(digest); + OPENSSL_free(mac); + return ret; +} diff --git a/apps/lib/app_libctx.c b/apps/lib/app_libctx.c new file mode 100644 --- /dev/null +++ b/apps/lib/app_libctx.c @@ -0,0 +1,48 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include "app_libctx.h" +#include "apps.h" + +static OSSL_LIB_CTX *app_libctx = NULL; +static const char *app_propq = NULL; + +int app_set_propq(const char *arg) +{ + app_propq = arg; + return 1; +} + +const char *app_get0_propq(void) +{ + return app_propq; +} + +OSSL_LIB_CTX *app_get0_libctx(void) +{ + return app_libctx; +} + +OSSL_LIB_CTX *app_create_libctx(void) +{ + /* + * Load the NULL provider into the default library context and create a + * library context which will then be used for any OPT_PROV options. + */ + if (app_libctx == NULL) { + if (!app_provider_load(NULL, "null")) { + opt_printf_stderr( "Failed to create null provider\n"); + return NULL; + } + app_libctx = OSSL_LIB_CTX_new(); + } + if (app_libctx == NULL) + opt_printf_stderr("Failed to create library context\n"); + return app_libctx; +} + diff --git a/apps/lib/app_params.c b/apps/lib/app_params.c new file mode 100644 --- /dev/null +++ b/apps/lib/app_params.c @@ -0,0 +1,132 @@ +/* + * Copyright 2019-2020 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 + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "app_params.h" + +static int describe_param_type(char *buf, size_t bufsz, const OSSL_PARAM *param) +{ + const char *type_mod = ""; + const char *type = NULL; + int show_type_number = 0; + int printed_len; + + switch (param->data_type) { + case OSSL_PARAM_UNSIGNED_INTEGER: + type_mod = "unsigned "; + /* FALLTHRU */ + case OSSL_PARAM_INTEGER: + type = "integer"; + break; + case OSSL_PARAM_UTF8_PTR: + type_mod = "pointer to a "; + /* FALLTHRU */ + case OSSL_PARAM_UTF8_STRING: + type = "UTF8 encoded string"; + break; + case OSSL_PARAM_OCTET_PTR: + type_mod = "pointer to an "; + /* FALLTHRU */ + case OSSL_PARAM_OCTET_STRING: + type = "octet string"; + break; + default: + type = "unknown type"; + show_type_number = 1; + break; + } + + printed_len = BIO_snprintf(buf, bufsz, "%s: ", param->key); + if (printed_len > 0) { + buf += printed_len; + bufsz -= printed_len; + } + printed_len = BIO_snprintf(buf, bufsz, "%s%s", type_mod, type); + if (printed_len > 0) { + buf += printed_len; + bufsz -= printed_len; + } + if (show_type_number) { + printed_len = BIO_snprintf(buf, bufsz, " [%d]", param->data_type); + if (printed_len > 0) { + buf += printed_len; + bufsz -= printed_len; + } + } + if (param->data_size == 0) + printed_len = BIO_snprintf(buf, bufsz, " (arbitrary size)"); + else + printed_len = BIO_snprintf(buf, bufsz, " (max %zu bytes large)", + param->data_size); + if (printed_len > 0) { + buf += printed_len; + bufsz -= printed_len; + } + *buf = '\0'; + return 1; +} + +int print_param_types(const char *thing, const OSSL_PARAM *pdefs, int indent) +{ + if (pdefs == NULL) { + return 1; + } else if (pdefs->key == NULL) { + /* + * An empty list? This shouldn't happen, but let's just make sure to + * say something if there's a badly written provider... + */ + BIO_printf(bio_out, "%*sEmpty list of %s (!!!)\n", indent, "", thing); + } else { + BIO_printf(bio_out, "%*s%s:\n", indent, "", thing); + for (; pdefs->key != NULL; pdefs++) { + char buf[200]; /* This should be ample space */ + + describe_param_type(buf, sizeof(buf), pdefs); + BIO_printf(bio_out, "%*s %s\n", indent, "", buf); + } + } + return 1; +} + +void print_param_value(const OSSL_PARAM *p, int indent) +{ + int64_t i; + uint64_t u; + + printf("%*s%s: ", indent, "", p->key); + switch (p->data_type) { + case OSSL_PARAM_UNSIGNED_INTEGER: + if (OSSL_PARAM_get_uint64(p, &u)) + BIO_printf(bio_out, "%llu\n", (unsigned long long int)u); + else + BIO_printf(bio_out, "error getting value\n"); + break; + case OSSL_PARAM_INTEGER: + if (OSSL_PARAM_get_int64(p, &i)) + BIO_printf(bio_out, "%lld\n", (long long int)i); + else + BIO_printf(bio_out, "error getting value\n"); + break; + case OSSL_PARAM_UTF8_PTR: + BIO_printf(bio_out, "'%s'\n", *(char **)(p->data)); + break; + case OSSL_PARAM_UTF8_STRING: + BIO_printf(bio_out, "'%s'\n", (char *)p->data); + break; + case OSSL_PARAM_OCTET_PTR: + case OSSL_PARAM_OCTET_STRING: + BIO_printf(bio_out, "<%zu bytes>\n", p->data_size); + break; + default: + BIO_printf(bio_out, "unknown type (%u) of %zu bytes\n", + p->data_type, p->data_size); + break; + } +} + diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c new file mode 100644 --- /dev/null +++ b/apps/lib/app_provider.c @@ -0,0 +1,92 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include +#include +#include +#include + +/* Non-zero if any of the provider options have been seen */ +static int provider_option_given = 0; + +DEFINE_STACK_OF(OSSL_PROVIDER) + +/* + * See comments in opt_verify for explanation of this. + */ +enum prov_range { OPT_PROV_ENUM }; + +static STACK_OF(OSSL_PROVIDER) *app_providers = NULL; + +static void provider_free(OSSL_PROVIDER *prov) +{ + OSSL_PROVIDER_unload(prov); +} + +int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name) +{ + OSSL_PROVIDER *prov; + + prov = OSSL_PROVIDER_load(libctx, provider_name); + if (prov == NULL) { + opt_printf_stderr("%s: unable to load provider %s\n" + "Hint: use -provider-path option or OPENSSL_MODULES environment variable.\n", + opt_getprog(), provider_name); + ERR_print_errors(bio_err); + return 0; + } + if (app_providers == NULL) + app_providers = sk_OSSL_PROVIDER_new_null(); + if (app_providers == NULL + || !sk_OSSL_PROVIDER_push(app_providers, prov)) { + app_providers_cleanup(); + return 0; + } + return 1; +} + +void app_providers_cleanup(void) +{ + sk_OSSL_PROVIDER_pop_free(app_providers, provider_free); + app_providers = NULL; +} + +static int opt_provider_path(const char *path) +{ + if (path != NULL && *path == '\0') + path = NULL; + return OSSL_PROVIDER_set_default_search_path(app_get0_libctx(), path); +} + +int opt_provider(int opt) +{ + const int given = provider_option_given; + + provider_option_given = 1; + switch ((enum prov_range)opt) { + case OPT_PROV__FIRST: + case OPT_PROV__LAST: + return 1; + case OPT_PROV_PROVIDER: + return app_provider_load(app_get0_libctx(), opt_arg()); + case OPT_PROV_PROVIDER_PATH: + return opt_provider_path(opt_arg()); + case OPT_PROV_PROPQUERY: + return app_set_propq(opt_arg()); + } + /* Should never get here but if we do, undo what we did earlier */ + provider_option_given = given; + return 0; +} + +int opt_provider_option_given(void) +{ + return provider_option_given; +} diff --git a/apps/lib/app_rand.c b/apps/lib/app_rand.c new file mode 100644 --- /dev/null +++ b/apps/lib/app_rand.c @@ -0,0 +1,124 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include +#include +#include +#include + +static char *save_rand_file; +static STACK_OF(OPENSSL_STRING) *randfiles; + +void app_RAND_load_conf(CONF *c, const char *section) +{ + const char *randfile = NCONF_get_string(c, section, "RANDFILE"); + + if (randfile == NULL) { + ERR_clear_error(); + return; + } + if (RAND_load_file(randfile, -1) < 0) { + BIO_printf(bio_err, "Can't load %s into RNG\n", randfile); + ERR_print_errors(bio_err); + } + if (save_rand_file == NULL) { + save_rand_file = OPENSSL_strdup(randfile); + /* If some internal memory errors have occurred */ + if (save_rand_file == NULL) { + BIO_printf(bio_err, "Can't duplicate %s\n", randfile); + ERR_print_errors(bio_err); + } + } +} + +static int loadfiles(char *name) +{ + char *p; + int last, ret = 1; + + for ( ; ; ) { + last = 0; + for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++) + continue; + if (*p == '\0') + last = 1; + *p = '\0'; + if (RAND_load_file(name, -1) < 0) { + BIO_printf(bio_err, "Can't load %s into RNG\n", name); + ERR_print_errors(bio_err); + ret = 0; + } + if (last) + break; + name = p + 1; + if (*name == '\0') + break; + } + return ret; +} + +int app_RAND_load(void) +{ + char *p; + int i, ret = 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(randfiles); i++) { + p = sk_OPENSSL_STRING_value(randfiles, i); + if (!loadfiles(p)) + ret = 0; + } + sk_OPENSSL_STRING_free(randfiles); + return ret; +} + +int app_RAND_write(void) +{ + int ret = 1; + + if (save_rand_file == NULL) + return 1; + if (RAND_write_file(save_rand_file) == -1) { + BIO_printf(bio_err, "Cannot write random bytes:\n"); + ERR_print_errors(bio_err); + ret = 0; + } + OPENSSL_free(save_rand_file); + save_rand_file = NULL; + return ret; +} + + +/* + * See comments in opt_verify for explanation of this. + */ +enum r_range { OPT_R_ENUM }; + +int opt_rand(int opt) +{ + switch ((enum r_range)opt) { + case OPT_R__FIRST: + case OPT_R__LAST: + break; + case OPT_R_RAND: + if (randfiles == NULL + && (randfiles = sk_OPENSSL_STRING_new_null()) == NULL) + return 0; + if (!sk_OPENSSL_STRING_push(randfiles, opt_arg())) + return 0; + break; + case OPT_R_WRITERAND: + OPENSSL_free(save_rand_file); + save_rand_file = OPENSSL_strdup(opt_arg()); + if (save_rand_file == NULL) + return 0; + break; + } + return 1; +} diff --git a/apps/lib/app_x509.c b/apps/lib/app_x509.c new file mode 100644 --- /dev/null +++ b/apps/lib/app_x509.c @@ -0,0 +1,137 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "apps.h" + +/* + * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to + * allow the application to process verification options in a manner similar + * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(), + * for uniformity. + * + * As soon as more stuff is added, the code will need serious rework. For + * the moment, it only handles the FIPS 196 / SM2 distinguishing ID. + */ +#ifdef EVP_PKEY_CTRL_SET1_ID +static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n) +{ + ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new(); + + if (v == NULL) { + BIO_printf(bio_err, "error: allocation failed\n"); + } else if (!ASN1_OCTET_STRING_set(v, value, (int)value_n)) { + ASN1_OCTET_STRING_free(v); + v = NULL; + } + return v; +} +#endif + +static int x509_ctrl(void *object, int cmd, void *value, size_t value_n) +{ + switch (cmd) { +#ifdef EVP_PKEY_CTRL_SET1_ID + case EVP_PKEY_CTRL_SET1_ID: + { + ASN1_OCTET_STRING *v = mk_octet_string(value, value_n); + + if (v == NULL) { + BIO_printf(bio_err, + "error: setting distinguishing ID in certificate failed\n"); + return 0; + } + + X509_set0_distinguishing_id(object, v); + return 1; + } +#endif + default: + break; + } + return -2; /* typical EVP_PKEY return for "unsupported" */ +} + +static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n) +{ + switch (cmd) { +#ifdef EVP_PKEY_CTRL_SET1_ID + case EVP_PKEY_CTRL_SET1_ID: + { + ASN1_OCTET_STRING *v = mk_octet_string(value, value_n); + + if (v == NULL) { + BIO_printf(bio_err, + "error: setting distinguishing ID in certificate signing request failed\n"); + return 0; + } + + X509_REQ_set0_distinguishing_id(object, v); + return 1; + } +#endif + default: + break; + } + return -2; /* typical EVP_PKEY return for "unsupported" */ +} + +static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd, + void *value, size_t value_n), + void *object, const char *value) +{ + int rv = 0; + char *stmp, *vtmp = NULL; + size_t vtmp_len = 0; + int cmd = 0; /* Will get command values that make sense somehow */ + + stmp = OPENSSL_strdup(value); + if (stmp == NULL) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp != NULL) { + *vtmp = 0; + vtmp++; + vtmp_len = strlen(vtmp); + } + + if (strcmp(stmp, "distid") == 0) { +#ifdef EVP_PKEY_CTRL_SET1_ID + cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */ +#endif + } else if (strcmp(stmp, "hexdistid") == 0) { + if (vtmp != NULL) { + void *hexid; + long hexid_len = 0; + + hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len); + OPENSSL_free(stmp); + stmp = vtmp = hexid; + vtmp_len = (size_t)hexid_len; + } +#ifdef EVP_PKEY_CTRL_SET1_ID + cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */ +#endif + } + + rv = ctrl(object, cmd, vtmp, vtmp_len); + + OPENSSL_free(stmp); + return rv; +} + +int x509_ctrl_string(X509 *x, const char *value) +{ + return do_x509_ctrl_string(x509_ctrl, x, value); +} + +int x509_req_ctrl_string(X509_REQ *x, const char *value) +{ + return do_x509_ctrl_string(x509_req_ctrl, x, value); +} diff --git a/apps/lib/apps.c b/apps/lib/apps.c new file mode 100644 --- /dev/null +++ b/apps/lib/apps.c @@ -0,0 +1,3389 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +/* + * On VMS, you need to define this to get the declaration of fileno(). The + * value 2 is to make sure no function defined in POSIX-2 is left undefined. + */ +# define _POSIX_C_SOURCE 2 +#endif + +#ifndef OPENSSL_NO_ENGINE +/* We need to use some deprecated APIs */ +# define OPENSSL_SUPPRESS_DEPRECATED +# include +#endif + +#include +#include +#include +#include +#ifndef OPENSSL_NO_POSIX_IO +# include +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "s_apps.h" +#include "apps.h" + +#ifdef _WIN32 +static int WIN32_rename(const char *from, const char *to); +# define rename(from,to) WIN32_rename((from),(to)) +#endif + +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) +# include +#endif + +#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) || defined(__BORLANDC__) +# define _kbhit kbhit +#endif + +static BIO *bio_open_default_(const char *filename, char mode, int format, + int quiet); + +#define PASS_SOURCE_SIZE_MAX 4 + +DEFINE_STACK_OF(CONF) + +typedef struct { + const char *name; + unsigned long flag; + unsigned long mask; +} NAME_EX_TBL; + +static int set_table_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl); +static int set_multi_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl); +static +int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc, + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + EVP_PKEY **pparams, + X509 **pcert, STACK_OF(X509) **pcerts, + X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls, + int suppress_decode_errors); + +int app_init(long mesgwin); + +int chopup_args(ARGS *arg, char *buf) +{ + int quoted; + char c = '\0', *p = NULL; + + arg->argc = 0; + if (arg->size == 0) { + arg->size = 20; + arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space"); + } + + for (p = buf;;) { + /* Skip whitespace. */ + while (*p && isspace(_UC(*p))) + p++; + if (*p == '\0') + break; + + /* The start of something good :-) */ + if (arg->argc >= arg->size) { + char **tmp; + arg->size += 20; + tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size); + if (tmp == NULL) + return 0; + arg->argv = tmp; + } + quoted = *p == '\'' || *p == '"'; + if (quoted) + c = *p++; + arg->argv[arg->argc++] = p; + + /* now look for the end of this */ + if (quoted) { + while (*p && *p != c) + p++; + *p++ = '\0'; + } else { + while (*p && !isspace(_UC(*p))) + p++; + if (*p) + *p++ = '\0'; + } + } + arg->argv[arg->argc] = NULL; + return 1; +} + +#ifndef APP_INIT +int app_init(long mesgwin) +{ + return 1; +} +#endif + +int ctx_set_verify_locations(SSL_CTX *ctx, + const char *CAfile, int noCAfile, + const char *CApath, int noCApath, + const char *CAstore, int noCAstore) +{ + if (CAfile == NULL && CApath == NULL && CAstore == NULL) { + if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) + return 0; + if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) + return 0; + if (!noCAstore && SSL_CTX_set_default_verify_store(ctx) <= 0) + return 0; + + return 1; + } + + if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile)) + return 0; + if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath)) + return 0; + if (CAstore != NULL && !SSL_CTX_load_verify_store(ctx, CAstore)) + return 0; + return 1; +} + +#ifndef OPENSSL_NO_CT + +int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path) +{ + if (path == NULL) + return SSL_CTX_set_default_ctlog_list_file(ctx); + + return SSL_CTX_set_ctlog_list_file(ctx, path); +} + +#endif + +static unsigned long nmflag = 0; +static char nmflag_set = 0; + +int set_nameopt(const char *arg) +{ + int ret = set_name_ex(&nmflag, arg); + + if (ret) + nmflag_set = 1; + + return ret; +} + +unsigned long get_nameopt(void) +{ + return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; +} + +void dump_cert_text(BIO *out, X509 *x) +{ + print_name(out, "subject=", X509_get_subject_name(x)); + print_name(out, "issuer=", X509_get_issuer_name(x)); +} + +int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata) +{ + return password_callback(buf, bufsiz, verify, (PW_CB_DATA *)userdata); +} + + +static char *app_get_pass(const char *arg, int keepbio); + +char *get_passwd(const char *pass, const char *desc) +{ + char *result = NULL; + + if (desc == NULL) + desc = ""; + if (!app_passwd(pass, NULL, &result, NULL)) + BIO_printf(bio_err, "Error getting password for %s\n", desc); + if (pass != NULL && result == NULL) { + BIO_printf(bio_err, + "Trying plain input string (better precede with 'pass:')\n"); + result = OPENSSL_strdup(pass); + if (result == NULL) + BIO_printf(bio_err, "Out of memory getting password for %s\n", desc); + } + return result; +} + +int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) +{ + int same = arg1 != NULL && arg2 != NULL && strcmp(arg1, arg2) == 0; + + if (arg1 != NULL) { + *pass1 = app_get_pass(arg1, same); + if (*pass1 == NULL) + return 0; + } else if (pass1 != NULL) { + *pass1 = NULL; + } + if (arg2 != NULL) { + *pass2 = app_get_pass(arg2, same ? 2 : 0); + if (*pass2 == NULL) + return 0; + } else if (pass2 != NULL) { + *pass2 = NULL; + } + return 1; +} + +static char *app_get_pass(const char *arg, int keepbio) +{ + static BIO *pwdbio = NULL; + char *tmp, tpass[APP_PASS_LEN]; + int i; + + /* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */ + if (strncmp(arg, "pass:", 5) == 0) + return OPENSSL_strdup(arg + 5); + if (strncmp(arg, "env:", 4) == 0) { + tmp = getenv(arg + 4); + if (tmp == NULL) { + BIO_printf(bio_err, "No environment variable %s\n", arg + 4); + return NULL; + } + return OPENSSL_strdup(tmp); + } + if (!keepbio || pwdbio == NULL) { + if (strncmp(arg, "file:", 5) == 0) { + pwdbio = BIO_new_file(arg + 5, "r"); + if (pwdbio == NULL) { + BIO_printf(bio_err, "Can't open file %s\n", arg + 5); + return NULL; + } +#if !defined(_WIN32) + /* + * Under _WIN32, which covers even Win64 and CE, file + * descriptors referenced by BIO_s_fd are not inherited + * by child process and therefore below is not an option. + * It could have been an option if bss_fd.c was operating + * on real Windows descriptors, such as those obtained + * with CreateFile. + */ + } else if (strncmp(arg, "fd:", 3) == 0) { + BIO *btmp; + i = atoi(arg + 3); + if (i >= 0) + pwdbio = BIO_new_fd(i, BIO_NOCLOSE); + if ((i < 0) || pwdbio == NULL) { + BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3); + return NULL; + } + /* + * Can't do BIO_gets on an fd BIO so add a buffering BIO + */ + btmp = BIO_new(BIO_f_buffer()); + if (btmp == NULL) { + BIO_free_all(pwdbio); + pwdbio = NULL; + BIO_printf(bio_err, "Out of memory\n"); + return NULL; + } + pwdbio = BIO_push(btmp, pwdbio); +#endif + } else if (strcmp(arg, "stdin") == 0) { + unbuffer(stdin); + pwdbio = dup_bio_in(FORMAT_TEXT); + if (pwdbio == NULL) { + BIO_printf(bio_err, "Can't open BIO for stdin\n"); + return NULL; + } + } else { + /* argument syntax error; do not reveal too much about arg */ + tmp = strchr(arg, ':'); + if (tmp == NULL || tmp - arg > PASS_SOURCE_SIZE_MAX) + BIO_printf(bio_err, + "Invalid password argument, missing ':' within the first %d chars\n", + PASS_SOURCE_SIZE_MAX + 1); + else + BIO_printf(bio_err, + "Invalid password argument, starting with \"%.*s\"\n", + (int)(tmp - arg + 1), arg); + return NULL; + } + } + i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); + if (keepbio != 1) { + BIO_free_all(pwdbio); + pwdbio = NULL; + } + if (i <= 0) { + BIO_printf(bio_err, "Error reading password from BIO\n"); + return NULL; + } + tmp = strchr(tpass, '\n'); + if (tmp != NULL) + *tmp = 0; + return OPENSSL_strdup(tpass); +} + +CONF *app_load_config_bio(BIO *in, const char *filename) +{ + long errorline = -1; + CONF *conf; + int i; + + conf = NCONF_new_ex(app_get0_libctx(), NULL); + i = NCONF_load_bio(conf, in, &errorline); + if (i > 0) + return conf; + + if (errorline <= 0) { + BIO_printf(bio_err, "%s: Can't load ", opt_getprog()); + } else { + BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(), + errorline); + } + if (filename != NULL) + BIO_printf(bio_err, "config file \"%s\"\n", filename); + else + BIO_printf(bio_err, "config input"); + + NCONF_free(conf); + return NULL; +} + +CONF *app_load_config_verbose(const char *filename, int verbose) +{ + if (verbose) { + if (*filename == '\0') + BIO_printf(bio_err, "No configuration used\n"); + else + BIO_printf(bio_err, "Using configuration from %s\n", filename); + } + return app_load_config_internal(filename, 0); +} + +CONF *app_load_config_internal(const char *filename, int quiet) +{ + BIO *in; + CONF *conf; + + if (filename == NULL || *filename != '\0') { + if ((in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL) + return NULL; + conf = app_load_config_bio(in, filename); + BIO_free(in); + } else { + /* Return empty config if filename is empty string. */ + conf = NCONF_new_ex(app_get0_libctx(), NULL); + } + return conf; +} + +int app_load_modules(const CONF *config) +{ + CONF *to_free = NULL; + + if (config == NULL) + config = to_free = app_load_config_quiet(default_config_file); + if (config == NULL) + return 1; + + if (CONF_modules_load(config, NULL, 0) <= 0) { + BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); + ERR_print_errors(bio_err); + NCONF_free(to_free); + return 0; + } + NCONF_free(to_free); + return 1; +} + +int add_oid_section(CONF *conf) +{ + char *p; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *cnf; + int i; + + if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { + ERR_clear_error(); + return 1; + } + if ((sktmp = NCONF_get_section(conf, p)) == NULL) { + BIO_printf(bio_err, "problem loading oid section %s\n", p); + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { + cnf = sk_CONF_VALUE_value(sktmp, i); + if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { + BIO_printf(bio_err, "problem creating object %s=%s\n", + cnf->name, cnf->value); + return 0; + } + } + return 1; +} + +CONF *app_load_config_modules(const char *configfile) +{ + CONF *conf = NULL; + + if (configfile != NULL) { + if ((conf = app_load_config_verbose(configfile, 1)) == NULL) + return NULL; + if (configfile != default_config_file && !app_load_modules(conf)) { + NCONF_free(conf); + conf = NULL; + } + } + return conf; +} + +#define IS_HTTP(uri) ((uri) != NULL \ + && strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0) +#define IS_HTTPS(uri) ((uri) != NULL \ + && strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0) + +X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc) +{ + X509 *cert = NULL; + + if (desc == NULL) + desc = "certificate"; + if (IS_HTTPS(uri)) + BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc); + else if (IS_HTTP(uri)) + cert = X509_load_http(uri, NULL, NULL, 0 /* timeout */); + else + (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, + NULL, NULL, NULL, &cert, NULL, NULL, NULL); + if (cert == NULL) { + BIO_printf(bio_err, "Unable to load %s\n", desc); + ERR_print_errors(bio_err); + } + return cert; +} + +X509_CRL *load_crl(const char *uri, int format, int maybe_stdin, + const char *desc) +{ + X509_CRL *crl = NULL; + + if (desc == NULL) + desc = "CRL"; + if (IS_HTTPS(uri)) + BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc); + else if (IS_HTTP(uri)) + crl = X509_CRL_load_http(uri, NULL, NULL, 0 /* timeout */); + else + (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, + NULL, NULL, NULL, NULL, NULL, &crl, NULL); + if (crl == NULL) { + BIO_printf(bio_err, "Unable to load %s\n", desc); + ERR_print_errors(bio_err); + } + return crl; +} + +X509_REQ *load_csr(const char *file, int format, const char *desc) +{ + X509_REQ *req = NULL; + BIO *in; + + if (format == FORMAT_UNDEF) + format = FORMAT_PEM; + if (desc == NULL) + desc = "CSR"; + in = bio_open_default(file, 'r', format); + if (in == NULL) + goto end; + + if (format == FORMAT_ASN1) + req = d2i_X509_REQ_bio(in, NULL); + else if (format == FORMAT_PEM) + req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); + else + print_format_error(format, OPT_FMT_PEMDER); + + end: + if (req == NULL) { + BIO_printf(bio_err, "Unable to load %s\n", desc); + ERR_print_errors(bio_err); + } + BIO_free(in); + return req; +} + +void cleanse(char *str) +{ + if (str != NULL) + OPENSSL_cleanse(str, strlen(str)); +} + +void clear_free(char *str) +{ + if (str != NULL) + OPENSSL_clear_free(str, strlen(str)); +} + +EVP_PKEY *load_key(const char *uri, int format, int may_stdin, + const char *pass, ENGINE *e, const char *desc) +{ + EVP_PKEY *pkey = NULL; + char *allocated_uri = NULL; + + if (desc == NULL) + desc = "private key"; + + if (format == FORMAT_ENGINE) { + uri = allocated_uri = make_engine_uri(e, uri, desc); + } + (void)load_key_certs_crls(uri, format, may_stdin, pass, desc, + &pkey, NULL, NULL, NULL, NULL, NULL, NULL); + + OPENSSL_free(allocated_uri); + return pkey; +} + +EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, + const char *pass, ENGINE *e, const char *desc) +{ + EVP_PKEY *pkey = NULL; + char *allocated_uri = NULL; + + if (desc == NULL) + desc = "public key"; + + if (format == FORMAT_ENGINE) { + uri = allocated_uri = make_engine_uri(e, uri, desc); + } + (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, + NULL, &pkey, NULL, NULL, NULL, NULL, NULL); + + OPENSSL_free(allocated_uri); + return pkey; +} + +EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin, + const char *keytype, const char *desc, + int suppress_decode_errors) +{ + EVP_PKEY *params = NULL; + + if (desc == NULL) + desc = "key parameters"; + + (void)load_key_certs_crls_suppress(uri, format, maybe_stdin, NULL, desc, + NULL, NULL, ¶ms, NULL, NULL, NULL, + NULL, suppress_decode_errors); + if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) { + if (!suppress_decode_errors) { + BIO_printf(bio_err, + "Unable to load %s from %s (unexpected parameters type)\n", + desc, uri); + ERR_print_errors(bio_err); + } + EVP_PKEY_free(params); + params = NULL; + } + return params; +} + +EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin, + const char *keytype, const char *desc) +{ + return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0); +} + +void app_bail_out(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + BIO_vprintf(bio_err, fmt, args); + va_end(args); + ERR_print_errors(bio_err); + exit(EXIT_FAILURE); +} + +void *app_malloc(size_t sz, const char *what) +{ + void *vp = OPENSSL_malloc(sz); + + if (vp == NULL) + app_bail_out("%s: Could not allocate %zu bytes for %s\n", + opt_getprog(), sz, what); + return vp; +} + +char *next_item(char *opt) /* in list separated by comma and/or space */ +{ + /* advance to separator (comma or whitespace), if any */ + while (*opt != ',' && !isspace(*opt) && *opt != '\0') + opt++; + if (*opt != '\0') { + /* terminate current item */ + *opt++ = '\0'; + /* skip over any whitespace after separator */ + while (isspace(*opt)) + opt++; + } + return *opt == '\0' ? NULL : opt; /* NULL indicates end of input */ +} + +static void warn_cert_msg(const char *uri, X509 *cert, const char *msg) +{ + char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + + BIO_printf(bio_err, "Warning: certificate from '%s' with subject '%s' %s\n", + uri, subj, msg); + OPENSSL_free(subj); +} + +static void warn_cert(const char *uri, X509 *cert, int warn_EE, + X509_VERIFY_PARAM *vpm) +{ + uint32_t ex_flags = X509_get_extension_flags(cert); + int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert), + X509_get0_notAfter(cert)); + + if (res != 0) + warn_cert_msg(uri, cert, res > 0 ? "has expired" : "not yet valid"); + if (warn_EE && (ex_flags & EXFLAG_V1) == 0 && (ex_flags & EXFLAG_CA) == 0) + warn_cert_msg(uri, cert, "is not a CA cert"); +} + +static void warn_certs(const char *uri, STACK_OF(X509) *certs, int warn_EE, + X509_VERIFY_PARAM *vpm) +{ + int i; + + for (i = 0; i < sk_X509_num(certs); i++) + warn_cert(uri, sk_X509_value(certs, i), warn_EE, vpm); +} + +int load_cert_certs(const char *uri, + X509 **pcert, STACK_OF(X509) **pcerts, + int exclude_http, const char *pass, const char *desc, + X509_VERIFY_PARAM *vpm) +{ + int ret = 0; + char *pass_string; + + if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0 + || OPENSSL_strncasecmp(uri, "https://", 8) == 0)) { + BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc); + return ret; + } + pass_string = get_passwd(pass, desc); + ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, + NULL, NULL, NULL, + pcert, pcerts, NULL, NULL); + clear_free(pass_string); + + if (ret) { + if (pcert != NULL) + warn_cert(uri, *pcert, 0, vpm); + if (pcerts != NULL) + warn_certs(uri, *pcerts, 1, vpm); + } else { + if (pcerts != NULL) { + sk_X509_pop_free(*pcerts, X509_free); + *pcerts = NULL; + } + } + return ret; +} + +STACK_OF(X509) *load_certs_multifile(char *files, const char *pass, + const char *desc, X509_VERIFY_PARAM *vpm) +{ + STACK_OF(X509) *certs = NULL; + STACK_OF(X509) *result = sk_X509_new_null(); + + if (files == NULL) + goto err; + if (result == NULL) + goto oom; + + while (files != NULL) { + char *next = next_item(files); + + if (!load_cert_certs(files, NULL, &certs, 0, pass, desc, vpm)) + goto err; + if (!X509_add_certs(result, certs, + X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP)) + goto oom; + sk_X509_pop_free(certs, X509_free); + certs = NULL; + files = next; + } + return result; + + oom: + BIO_printf(bio_err, "out of memory\n"); + err: + sk_X509_pop_free(certs, X509_free); + sk_X509_pop_free(result, X509_free); + return NULL; +} + +static X509_STORE *sk_X509_to_store(X509_STORE *store /* may be NULL */, + const STACK_OF(X509) *certs /* may NULL */) +{ + int i; + + if (store == NULL) + store = X509_STORE_new(); + if (store == NULL) + return NULL; + for (i = 0; i < sk_X509_num(certs); i++) { + if (!X509_STORE_add_cert(store, sk_X509_value(certs, i))) { + X509_STORE_free(store); + return NULL; + } + } + return store; +} + +/* + * Create cert store structure with certificates read from given file(s). + * Returns pointer to created X509_STORE on success, NULL on error. + */ +X509_STORE *load_certstore(char *input, const char *pass, const char *desc, + X509_VERIFY_PARAM *vpm) +{ + X509_STORE *store = NULL; + STACK_OF(X509) *certs = NULL; + + while (input != NULL) { + char *next = next_item(input); + int ok; + + if (!load_cert_certs(input, NULL, &certs, 1, pass, desc, vpm)) { + X509_STORE_free(store); + return NULL; + } + ok = (store = sk_X509_to_store(store, certs)) != NULL; + sk_X509_pop_free(certs, X509_free); + certs = NULL; + if (!ok) + return NULL; + input = next; + } + return store; +} + +/* + * Initialize or extend, if *certs != NULL, a certificate stack. + * The caller is responsible for freeing *certs if its value is left not NULL. + */ +int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs, + const char *pass, const char *desc) +{ + int was_NULL = *certs == NULL; + int ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, + pass, desc, NULL, NULL, + NULL, NULL, certs, NULL, NULL); + + if (!ret && was_NULL) { + sk_X509_pop_free(*certs, X509_free); + *certs = NULL; + } + return ret; +} + +/* + * Initialize or extend, if *crls != NULL, a certificate stack. + * The caller is responsible for freeing *crls if its value is left not NULL. + */ +int load_crls(const char *uri, STACK_OF(X509_CRL) **crls, + const char *pass, const char *desc) +{ + int was_NULL = *crls == NULL; + int ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, + NULL, NULL, NULL, + NULL, NULL, NULL, crls); + + if (!ret && was_NULL) { + sk_X509_CRL_pop_free(*crls, X509_CRL_free); + *crls = NULL; + } + return ret; +} + +static const char *format2string(int format) +{ + switch(format) { + case FORMAT_PEM: + return "PEM"; + case FORMAT_ASN1: + return "DER"; + } + return NULL; +} + +/* Set type expectation, but clear it if objects of different types expected. */ +#define SET_EXPECT(expect, val) ((expect) = (expect) < 0 ? (val) : ((expect) == (val) ? (val) : 0)) +/* + * Load those types of credentials for which the result pointer is not NULL. + * Reads from stdio if uri is NULL and maybe_stdin is nonzero. + * For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded. + * If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated. + * If pcerts is non-NULL then all available certificates are appended to *pcerts + * except any certificate assigned to *pcert. + * If pcrls is non-NULL and *pcrls == NULL then a new list of CRLs is allocated. + * If pcrls is non-NULL then all available CRLs are appended to *pcerts + * except any CRL assigned to *pcrl. + * In any case (also on error) the caller is responsible for freeing all members + * of *pcerts and *pcrls (as far as they are not NULL). + */ +static +int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc, + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + EVP_PKEY **pparams, + X509 **pcert, STACK_OF(X509) **pcerts, + X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls, + int suppress_decode_errors) +{ + PW_CB_DATA uidata; + OSSL_STORE_CTX *ctx = NULL; + OSSL_LIB_CTX *libctx = app_get0_libctx(); + const char *propq = app_get0_propq(); + int ncerts = 0; + int ncrls = 0; + const char *failed = + ppkey != NULL ? "key" : ppubkey != NULL ? "public key" : + pparams != NULL ? "params" : pcert != NULL ? "cert" : + pcrl != NULL ? "CRL" : pcerts != NULL ? "certs" : + pcrls != NULL ? "CRLs" : NULL; + int cnt_expectations = 0; + int expect = -1; + const char *input_type; + OSSL_PARAM itp[2]; + const OSSL_PARAM *params = NULL; + + if (ppkey != NULL) { + *ppkey = NULL; + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_PKEY); + } + if (ppubkey != NULL) { + *ppubkey = NULL; + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_PUBKEY); + } + if (pparams != NULL) { + *pparams = NULL; + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_PARAMS); + } + if (pcert != NULL) { + *pcert = NULL; + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_CERT); + } + if (pcerts != NULL) { + if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) { + BIO_printf(bio_err, "Out of memory loading"); + goto end; + } + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_CERT); + } + if (pcrl != NULL) { + *pcrl = NULL; + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_CRL); + } + if (pcrls != NULL) { + if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) { + BIO_printf(bio_err, "Out of memory loading"); + goto end; + } + cnt_expectations++; + SET_EXPECT(expect, OSSL_STORE_INFO_CRL); + } + if (cnt_expectations == 0) { + BIO_printf(bio_err, "Internal error: nothing to load from %s\n", + uri != NULL ? uri : ""); + return 0; + } + + uidata.password = pass; + uidata.prompt_info = uri; + + if ((input_type = format2string(format)) != NULL) { + itp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE, + (char *)input_type, 0); + itp[1] = OSSL_PARAM_construct_end(); + params = itp; + } + + if (uri == NULL) { + BIO *bio; + + if (!maybe_stdin) { + BIO_printf(bio_err, "No filename or uri specified for loading"); + goto end; + } + uri = ""; + unbuffer(stdin); + bio = BIO_new_fp(stdin, 0); + if (bio != NULL) { + ctx = OSSL_STORE_attach(bio, "file", libctx, propq, + get_ui_method(), &uidata, params, + NULL, NULL); + BIO_free(bio); + } + } else { + ctx = OSSL_STORE_open_ex(uri, libctx, propq, get_ui_method(), &uidata, + params, NULL, NULL); + } + if (ctx == NULL) { + BIO_printf(bio_err, "Could not open file or uri for loading"); + goto end; + } + if (expect > 0 && !OSSL_STORE_expect(ctx, expect)) + goto end; + + failed = NULL; + while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) { + OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); + int type, ok = 1; + + /* + * This can happen (for example) if we attempt to load a file with + * multiple different types of things in it - but the thing we just + * tried to load wasn't one of the ones we wanted, e.g. if we're trying + * to load a certificate but the file has both the private key and the + * certificate in it. We just retry until eof. + */ + if (info == NULL) { + continue; + } + + type = OSSL_STORE_INFO_get_type(info); + switch (type) { + case OSSL_STORE_INFO_PKEY: + if (ppkey != NULL && *ppkey == NULL) { + ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL; + cnt_expectations -= ok; + } + /* + * An EVP_PKEY with private parts also holds the public parts, + * so if the caller asked for a public key, and we got a private + * key, we can still pass it back. + */ + if (ok && ppubkey != NULL && *ppubkey == NULL) { + ok = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL); + cnt_expectations -= ok; + } + break; + case OSSL_STORE_INFO_PUBKEY: + if (ppubkey != NULL && *ppubkey == NULL) { + ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL); + cnt_expectations -= ok; + } + break; + case OSSL_STORE_INFO_PARAMS: + if (pparams != NULL && *pparams == NULL) { + ok = ((*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL); + cnt_expectations -= ok; + } + break; + case OSSL_STORE_INFO_CERT: + if (pcert != NULL && *pcert == NULL) { + ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL; + cnt_expectations -= ok; + } + else if (pcerts != NULL) + ok = X509_add_cert(*pcerts, + OSSL_STORE_INFO_get1_CERT(info), + X509_ADD_FLAG_DEFAULT); + ncerts += ok; + break; + case OSSL_STORE_INFO_CRL: + if (pcrl != NULL && *pcrl == NULL) { + ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL; + cnt_expectations -= ok; + } + else if (pcrls != NULL) + ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info)); + ncrls += ok; + break; + default: + /* skip any other type */ + break; + } + OSSL_STORE_INFO_free(info); + if (!ok) { + failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); + BIO_printf(bio_err, "Error reading"); + break; + } + } + + end: + OSSL_STORE_close(ctx); + if (failed == NULL) { + int any = 0; + + if ((ppkey != NULL && *ppkey == NULL) + || (ppubkey != NULL && *ppubkey == NULL)) { + failed = "key"; + } else if (pparams != NULL && *pparams == NULL) { + failed = "params"; + } else if ((pcert != NULL || pcerts != NULL) && ncerts == 0) { + if (pcert == NULL) + any = 1; + failed = "cert"; + } else if ((pcrl != NULL || pcrls != NULL) && ncrls == 0) { + if (pcrl == NULL) + any = 1; + failed = "CRL"; + } + if (!suppress_decode_errors) { + if (failed != NULL) + BIO_printf(bio_err, "Could not read"); + if (any) + BIO_printf(bio_err, " any"); + } + } + if (!suppress_decode_errors && failed != NULL) { + if (desc != NULL && strstr(desc, failed) != NULL) { + BIO_printf(bio_err, " %s", desc); + } else { + BIO_printf(bio_err, " %s", failed); + if (desc != NULL) + BIO_printf(bio_err, " of %s", desc); + } + if (uri != NULL) + BIO_printf(bio_err, " from %s", uri); + BIO_printf(bio_err, "\n"); + ERR_print_errors(bio_err); + } + if (suppress_decode_errors || failed == NULL) + /* clear any spurious errors */ + ERR_clear_error(); + return failed == NULL; +} + +int load_key_certs_crls(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc, + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + EVP_PKEY **pparams, + X509 **pcert, STACK_OF(X509) **pcerts, + X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls) +{ + return load_key_certs_crls_suppress(uri, format, maybe_stdin, pass, desc, + ppkey, ppubkey, pparams, pcert, pcerts, + pcrl, pcrls, 0); +} + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +#define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ + X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) + +int set_cert_ex(unsigned long *flags, const char *arg) +{ + static const NAME_EX_TBL cert_tbl[] = { + {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, + {"ca_default", X509_FLAG_CA, 0xffffffffl}, + {"no_header", X509_FLAG_NO_HEADER, 0}, + {"no_version", X509_FLAG_NO_VERSION, 0}, + {"no_serial", X509_FLAG_NO_SERIAL, 0}, + {"no_signame", X509_FLAG_NO_SIGNAME, 0}, + {"no_validity", X509_FLAG_NO_VALIDITY, 0}, + {"no_subject", X509_FLAG_NO_SUBJECT, 0}, + {"no_issuer", X509_FLAG_NO_ISSUER, 0}, + {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, + {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, + {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, + {"no_aux", X509_FLAG_NO_AUX, 0}, + {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, + {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, + {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {NULL, 0, 0} + }; + return set_multi_opts(flags, arg, cert_tbl); +} + +int set_name_ex(unsigned long *flags, const char *arg) +{ + static const NAME_EX_TBL ex_tbl[] = { + {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, + {"esc_2254", ASN1_STRFLGS_ESC_2254, 0}, + {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, + {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, + {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, + {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, + {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, + {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, + {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, + {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, + {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, + {"compat", XN_FLAG_COMPAT, 0xffffffffL}, + {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, + {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, + {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, + {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, + {"dn_rev", XN_FLAG_DN_REV, 0}, + {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, + {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, + {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, + {"align", XN_FLAG_FN_ALIGN, 0}, + {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, + {"space_eq", XN_FLAG_SPC_EQ, 0}, + {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, + {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, + {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, + {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, + {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, + {NULL, 0, 0} + }; + if (set_multi_opts(flags, arg, ex_tbl) == 0) + return 0; + if (*flags != XN_FLAG_COMPAT + && (*flags & XN_FLAG_SEP_MASK) == 0) + *flags |= XN_FLAG_SEP_CPLUS_SPC; + return 1; +} + +int set_dateopt(unsigned long *dateopt, const char *arg) +{ + if (OPENSSL_strcasecmp(arg, "rfc_822") == 0) + *dateopt = ASN1_DTFLGS_RFC822; + else if (OPENSSL_strcasecmp(arg, "iso_8601") == 0) + *dateopt = ASN1_DTFLGS_ISO8601; + else + return 0; + return 1; +} + +int set_ext_copy(int *copy_type, const char *arg) +{ + if (OPENSSL_strcasecmp(arg, "none") == 0) + *copy_type = EXT_COPY_NONE; + else if (OPENSSL_strcasecmp(arg, "copy") == 0) + *copy_type = EXT_COPY_ADD; + else if (OPENSSL_strcasecmp(arg, "copyall") == 0) + *copy_type = EXT_COPY_ALL; + else + return 0; + return 1; +} + +int copy_extensions(X509 *x, X509_REQ *req, int copy_type) +{ + STACK_OF(X509_EXTENSION) *exts; + int i, ret = 0; + + if (x == NULL || req == NULL) + return 0; + if (copy_type == EXT_COPY_NONE) + return 1; + exts = X509_REQ_get_extensions(req); + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); + ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); + int idx = X509_get_ext_by_OBJ(x, obj, -1); + + /* Does extension exist in target? */ + if (idx != -1) { + /* If normal copy don't override existing extension */ + if (copy_type == EXT_COPY_ADD) + continue; + /* Delete all extensions of same type */ + do { + X509_EXTENSION_free(X509_delete_ext(x, idx)); + idx = X509_get_ext_by_OBJ(x, obj, -1); + } while (idx != -1); + } + if (!X509_add_ext(x, ext, -1)) + goto end; + } + ret = 1; + + end: + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + return ret; +} + +static int set_multi_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl) +{ + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *val; + int i, ret = 1; + if (!arg) + return 0; + vals = X509V3_parse_list(arg); + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + val = sk_CONF_VALUE_value(vals, i); + if (!set_table_opts(flags, val->name, in_tbl)) + ret = 0; + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return ret; +} + +static int set_table_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL * in_tbl) +{ + char c; + const NAME_EX_TBL *ptbl; + c = arg[0]; + + if (c == '-') { + c = 0; + arg++; + } else if (c == '+') { + c = 1; + arg++; + } else { + c = 1; + } + + for (ptbl = in_tbl; ptbl->name; ptbl++) { + if (OPENSSL_strcasecmp(arg, ptbl->name) == 0) { + *flags &= ~ptbl->mask; + if (c) + *flags |= ptbl->flag; + else + *flags &= ~ptbl->flag; + return 1; + } + } + return 0; +} + +void print_name(BIO *out, const char *title, const X509_NAME *nm) +{ + char *buf; + char mline = 0; + int indent = 0; + unsigned long lflags = get_nameopt(); + + if (out == NULL) + return; + if (title != NULL) + BIO_puts(out, title); + if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mline = 1; + indent = 4; + } + if (lflags == XN_FLAG_COMPAT) { + buf = X509_NAME_oneline(nm, 0, 0); + BIO_puts(out, buf); + BIO_puts(out, "\n"); + OPENSSL_free(buf); + } else { + if (mline) + BIO_puts(out, "\n"); + X509_NAME_print_ex(out, nm, indent, lflags); + BIO_puts(out, "\n"); + } +} + +void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, + int len, unsigned char *buffer) +{ + BIO_printf(out, " static unsigned char %s_%d[] = {", var, len); + if (BN_is_zero(in)) { + BIO_printf(out, "\n 0x00"); + } else { + int i, l; + + l = BN_bn2bin(in, buffer); + for (i = 0; i < l; i++) { + BIO_printf(out, (i % 10) == 0 ? "\n " : " "); + if (i < l - 1) + BIO_printf(out, "0x%02X,", buffer[i]); + else + BIO_printf(out, "0x%02X", buffer[i]); + } + } + BIO_printf(out, "\n };\n"); +} + +void print_array(BIO *out, const char* title, int len, const unsigned char* d) +{ + int i; + + BIO_printf(out, "unsigned char %s[%d] = {", title, len); + for (i = 0; i < len; i++) { + if ((i % 10) == 0) + BIO_printf(out, "\n "); + if (i < len - 1) + BIO_printf(out, "0x%02X, ", d[i]); + else + BIO_printf(out, "0x%02X", d[i]); + } + BIO_printf(out, "\n};\n"); +} + +X509_STORE *setup_verify(const char *CAfile, int noCAfile, + const char *CApath, int noCApath, + const char *CAstore, int noCAstore) +{ + X509_STORE *store = X509_STORE_new(); + X509_LOOKUP *lookup; + OSSL_LIB_CTX *libctx = app_get0_libctx(); + const char *propq = app_get0_propq(); + + if (store == NULL) + goto end; + + if (CAfile != NULL || !noCAfile) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) + goto end; + if (CAfile != NULL) { + if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM, + libctx, propq) <= 0) { + BIO_printf(bio_err, "Error loading file %s\n", CAfile); + goto end; + } + } else { + X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT, + libctx, propq); + } + } + + if (CApath != NULL || !noCApath) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + goto end; + if (CApath != NULL) { + if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, "Error loading directory %s\n", CApath); + goto end; + } + } else { + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + } + } + + if (CAstore != NULL || !noCAstore) { + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_store()); + if (lookup == NULL) + goto end; + if (!X509_LOOKUP_add_store_ex(lookup, CAstore, libctx, propq)) { + if (CAstore != NULL) + BIO_printf(bio_err, "Error loading store URI %s\n", CAstore); + goto end; + } + } + + ERR_clear_error(); + return store; + end: + ERR_print_errors(bio_err); + X509_STORE_free(store); + return NULL; +} + +static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) +{ + const char *n; + + n = a[DB_serial]; + while (*n == '0') + n++; + return OPENSSL_LH_strhash(n); +} + +static int index_serial_cmp(const OPENSSL_CSTRING *a, + const OPENSSL_CSTRING *b) +{ + const char *aa, *bb; + + for (aa = a[DB_serial]; *aa == '0'; aa++) ; + for (bb = b[DB_serial]; *bb == '0'; bb++) ; + return strcmp(aa, bb); +} + +static int index_name_qual(char **a) +{ + return (a[0][0] == 'V'); +} + +static unsigned long index_name_hash(const OPENSSL_CSTRING *a) +{ + return OPENSSL_LH_strhash(a[DB_name]); +} + +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) +{ + return strcmp(a[DB_name], b[DB_name]); +} + +static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) +#undef BSIZE +#define BSIZE 256 +BIGNUM *load_serial(const char *serialfile, int *exists, int create, + ASN1_INTEGER **retai) +{ + BIO *in = NULL; + BIGNUM *ret = NULL; + char buf[1024]; + ASN1_INTEGER *ai = NULL; + + ai = ASN1_INTEGER_new(); + if (ai == NULL) + goto err; + + in = BIO_new_file(serialfile, "r"); + if (exists != NULL) + *exists = in != NULL; + if (in == NULL) { + if (!create) { + perror(serialfile); + goto err; + } + ERR_clear_error(); + ret = BN_new(); + if (ret == NULL) { + BIO_printf(bio_err, "Out of memory\n"); + } else if (!rand_serial(ret, ai)) { + BIO_printf(bio_err, "Error creating random number to store in %s\n", + serialfile); + BN_free(ret); + ret = NULL; + } + } else { + if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { + BIO_printf(bio_err, "Unable to load number from %s\n", + serialfile); + goto err; + } + ret = ASN1_INTEGER_to_BN(ai, NULL); + if (ret == NULL) { + BIO_printf(bio_err, "Error converting number from bin to BIGNUM\n"); + goto err; + } + } + + if (ret != NULL && retai != NULL) { + *retai = ai; + ai = NULL; + } + err: + if (ret == NULL) + ERR_print_errors(bio_err); + BIO_free(in); + ASN1_INTEGER_free(ai); + return ret; +} + +int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, + ASN1_INTEGER **retai) +{ + char buf[1][BSIZE]; + BIO *out = NULL; + int ret = 0; + ASN1_INTEGER *ai = NULL; + int j; + + if (suffix == NULL) + j = strlen(serialfile); + else + j = strlen(serialfile) + strlen(suffix) + 1; + if (j >= BSIZE) { + BIO_printf(bio_err, "File name too long\n"); + goto err; + } + + if (suffix == NULL) + OPENSSL_strlcpy(buf[0], serialfile, BSIZE); + else { +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); +#else + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); +#endif + } + out = BIO_new_file(buf[0], "w"); + if (out == NULL) { + goto err; + } + + if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { + BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); + goto err; + } + i2a_ASN1_INTEGER(out, ai); + BIO_puts(out, "\n"); + ret = 1; + if (retai) { + *retai = ai; + ai = NULL; + } + err: + if (!ret) + ERR_print_errors(bio_err); + BIO_free_all(out); + ASN1_INTEGER_free(ai); + return ret; +} + +int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix) +{ + char buf[2][BSIZE]; + int i, j; + + i = strlen(serialfile) + strlen(old_suffix); + j = strlen(serialfile) + strlen(new_suffix); + if (i > j) + j = i; + if (j + 1 >= BSIZE) { + BIO_printf(bio_err, "File name too long\n"); + goto err; + } +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix); +#else + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); +#endif + if (rename(serialfile, buf[1]) < 0 && errno != ENOENT +#ifdef ENOTDIR + && errno != ENOTDIR +#endif + ) { + BIO_printf(bio_err, + "Unable to rename %s to %s\n", serialfile, buf[1]); + perror("reason"); + goto err; + } + if (rename(buf[0], serialfile) < 0) { + BIO_printf(bio_err, + "Unable to rename %s to %s\n", buf[0], serialfile); + perror("reason"); + rename(buf[1], serialfile); + goto err; + } + return 1; + err: + ERR_print_errors(bio_err); + return 0; +} + +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) +{ + BIGNUM *btmp; + int ret = 0; + + btmp = b == NULL ? BN_new() : b; + if (btmp == NULL) + return 0; + + if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + goto error; + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) + goto error; + + ret = 1; + + error: + + if (btmp != b) + BN_free(btmp); + + return ret; +} + +CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) +{ + CA_DB *retdb = NULL; + TXT_DB *tmpdb = NULL; + BIO *in; + CONF *dbattr_conf = NULL; + char buf[BSIZE]; +#ifndef OPENSSL_NO_POSIX_IO + FILE *dbfp; + struct stat dbst; +#endif + + in = BIO_new_file(dbfile, "r"); + if (in == NULL) + goto err; + +#ifndef OPENSSL_NO_POSIX_IO + BIO_get_fp(in, &dbfp); + if (fstat(fileno(dbfp), &dbst) == -1) { + ERR_raise_data(ERR_LIB_SYS, errno, + "calling fstat(%s)", dbfile); + goto err; + } +#endif + + if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) + goto err; + +#ifndef OPENSSL_SYS_VMS + BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile); +#else + BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile); +#endif + dbattr_conf = app_load_config_quiet(buf); + + retdb = app_malloc(sizeof(*retdb), "new DB"); + retdb->db = tmpdb; + tmpdb = NULL; + if (db_attr) + retdb->attributes = *db_attr; + else { + retdb->attributes.unique_subject = 1; + } + + if (dbattr_conf) { + char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); + if (p) { + retdb->attributes.unique_subject = parse_yesno(p, 1); + } + } + + retdb->dbfname = OPENSSL_strdup(dbfile); +#ifndef OPENSSL_NO_POSIX_IO + retdb->dbst = dbst; +#endif + + err: + ERR_print_errors(bio_err); + NCONF_free(dbattr_conf); + TXT_DB_free(tmpdb); + BIO_free_all(in); + return retdb; +} + +/* + * Returns > 0 on success, <= 0 on error + */ +int index_index(CA_DB *db) +{ + if (!TXT_DB_create_index(db->db, DB_serial, NULL, + LHASH_HASH_FN(index_serial), + LHASH_COMP_FN(index_serial))) { + BIO_printf(bio_err, + "Error creating serial number index:(%ld,%ld,%ld)\n", + db->db->error, db->db->arg1, db->db->arg2); + goto err; + } + + if (db->attributes.unique_subject + && !TXT_DB_create_index(db->db, DB_name, index_name_qual, + LHASH_HASH_FN(index_name), + LHASH_COMP_FN(index_name))) { + BIO_printf(bio_err, "Error creating name index:(%ld,%ld,%ld)\n", + db->db->error, db->db->arg1, db->db->arg2); + goto err; + } + return 1; + err: + ERR_print_errors(bio_err); + return 0; +} + +int save_index(const char *dbfile, const char *suffix, CA_DB *db) +{ + char buf[3][BSIZE]; + BIO *out; + int j; + + j = strlen(dbfile) + strlen(suffix); + if (j + 6 >= BSIZE) { + BIO_printf(bio_err, "File name too long\n"); + goto err; + } +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix); +#else + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); +#endif + out = BIO_new_file(buf[0], "w"); + if (out == NULL) { + perror(dbfile); + BIO_printf(bio_err, "Unable to open '%s'\n", dbfile); + goto err; + } + j = TXT_DB_write(out, db->db); + BIO_free(out); + if (j <= 0) + goto err; + + out = BIO_new_file(buf[1], "w"); + if (out == NULL) { + perror(buf[2]); + BIO_printf(bio_err, "Unable to open '%s'\n", buf[2]); + goto err; + } + BIO_printf(out, "unique_subject = %s\n", + db->attributes.unique_subject ? "yes" : "no"); + BIO_free(out); + + return 1; + err: + ERR_print_errors(bio_err); + return 0; +} + +int rotate_index(const char *dbfile, const char *new_suffix, + const char *old_suffix) +{ + char buf[5][BSIZE]; + int i, j; + + i = strlen(dbfile) + strlen(old_suffix); + j = strlen(dbfile) + strlen(new_suffix); + if (i > j) + j = i; + if (j + 6 >= BSIZE) { + BIO_printf(bio_err, "File name too long\n"); + goto err; + } +#ifndef OPENSSL_SYS_VMS + j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); + j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); +#else + j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); + j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); + j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); + j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); + j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); +#endif + if (rename(dbfile, buf[1]) < 0 && errno != ENOENT +#ifdef ENOTDIR + && errno != ENOTDIR +#endif + ) { + BIO_printf(bio_err, "Unable to rename %s to %s\n", dbfile, buf[1]); + perror("reason"); + goto err; + } + if (rename(buf[0], dbfile) < 0) { + BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[0], dbfile); + perror("reason"); + rename(buf[1], dbfile); + goto err; + } + if (rename(buf[4], buf[3]) < 0 && errno != ENOENT +#ifdef ENOTDIR + && errno != ENOTDIR +#endif + ) { + BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[4], buf[3]); + perror("reason"); + rename(dbfile, buf[0]); + rename(buf[1], dbfile); + goto err; + } + if (rename(buf[2], buf[4]) < 0) { + BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[2], buf[4]); + perror("reason"); + rename(buf[3], buf[4]); + rename(dbfile, buf[0]); + rename(buf[1], dbfile); + goto err; + } + return 1; + err: + ERR_print_errors(bio_err); + return 0; +} + +void free_index(CA_DB *db) +{ + if (db) { + TXT_DB_free(db->db); + OPENSSL_free(db->dbfname); + OPENSSL_free(db); + } +} + +int parse_yesno(const char *str, int def) +{ + if (str) { + switch (*str) { + case 'f': /* false */ + case 'F': /* FALSE */ + case 'n': /* no */ + case 'N': /* NO */ + case '0': /* 0 */ + return 0; + case 't': /* true */ + case 'T': /* TRUE */ + case 'y': /* yes */ + case 'Y': /* YES */ + case '1': /* 1 */ + return 1; + } + } + return def; +} + +/* + * name is expected to be in the format /type0=value0/type1=value1/type2=... + * where + can be used instead of / to form multi-valued RDNs if canmulti + * and characters may be escaped by \ + */ +X509_NAME *parse_name(const char *cp, int chtype, int canmulti, + const char *desc) +{ + int nextismulti = 0; + char *work; + X509_NAME *n; + + if (*cp++ != '/') { + BIO_printf(bio_err, + "%s: %s name is expected to be in the format " + "/type0=value0/type1=value1/type2=... where characters may " + "be escaped by \\. This name is not in that format: '%s'\n", + opt_getprog(), desc, --cp); + return NULL; + } + + n = X509_NAME_new(); + if (n == NULL) { + BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog()); + return NULL; + } + work = OPENSSL_strdup(cp); + if (work == NULL) { + BIO_printf(bio_err, "%s: Error copying %s name input\n", + opt_getprog(), desc); + goto err; + } + + while (*cp != '\0') { + char *bp = work; + char *typestr = bp; + unsigned char *valstr; + int nid; + int ismulti = nextismulti; + nextismulti = 0; + + /* Collect the type */ + while (*cp != '\0' && *cp != '=') + *bp++ = *cp++; + *bp++ = '\0'; + if (*cp == '\0') { + BIO_printf(bio_err, + "%s: Missing '=' after RDN type string '%s' in %s name string\n", + opt_getprog(), typestr, desc); + goto err; + } + ++cp; + + /* Collect the value. */ + valstr = (unsigned char *)bp; + for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) { + /* unescaped '+' symbol string signals further member of multiRDN */ + if (canmulti && *cp == '+') { + nextismulti = 1; + break; + } + if (*cp == '\\' && *++cp == '\0') { + BIO_printf(bio_err, + "%s: Escape character at end of %s name string\n", + opt_getprog(), desc); + goto err; + } + } + *bp++ = '\0'; + + /* If not at EOS (must be + or /), move forward. */ + if (*cp != '\0') + ++cp; + + /* Parse */ + nid = OBJ_txt2nid(typestr); + if (nid == NID_undef) { + BIO_printf(bio_err, + "%s: Skipping unknown %s name attribute \"%s\"\n", + opt_getprog(), desc, typestr); + if (ismulti) + BIO_printf(bio_err, + "Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n"); + continue; + } + if (*valstr == '\0') { + BIO_printf(bio_err, + "%s: No value provided for %s name attribute \"%s\", skipped\n", + opt_getprog(), desc, typestr); + continue; + } + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + valstr, strlen((char *)valstr), + -1, ismulti ? -1 : 0)) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, + "%s: Error adding %s name attribute \"/%s=%s\"\n", + opt_getprog(), desc, typestr ,valstr); + goto err; + } + } + + OPENSSL_free(work); + return n; + + err: + X509_NAME_free(n); + OPENSSL_free(work); + return NULL; +} + +/* + * Read whole contents of a BIO into an allocated memory buffer and return + * it. + */ + +int bio_to_mem(unsigned char **out, int maxlen, BIO *in) +{ + BIO *mem; + int len, ret; + unsigned char tbuf[1024]; + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) + return -1; + for (;;) { + if ((maxlen != -1) && maxlen < 1024) + len = maxlen; + else + len = 1024; + len = BIO_read(in, tbuf, len); + if (len < 0) { + BIO_free(mem); + return -1; + } + if (len == 0) + break; + if (BIO_write(mem, tbuf, len) != len) { + BIO_free(mem); + return -1; + } + maxlen -= len; + + if (maxlen == 0) + break; + } + ret = BIO_get_mem_data(mem, (char **)out); + BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); + BIO_free(mem); + return ret; +} + +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) +{ + int rv = 0; + char *stmp, *vtmp = NULL; + + stmp = OPENSSL_strdup(value); + if (stmp == NULL) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp == NULL) + goto err; + + *vtmp = 0; + vtmp++; + rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); + + err: + OPENSSL_free(stmp); + return rv; +} + +static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes) +{ + X509_POLICY_NODE *node; + int i; + + BIO_printf(bio_err, "%s Policies:", name); + if (nodes) { + BIO_puts(bio_err, "\n"); + for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { + node = sk_X509_POLICY_NODE_value(nodes, i); + X509_POLICY_NODE_print(bio_err, node, 2); + } + } else { + BIO_puts(bio_err, " \n"); + } +} + +void policies_print(X509_STORE_CTX *ctx) +{ + X509_POLICY_TREE *tree; + int explicit_policy; + tree = X509_STORE_CTX_get0_policy_tree(ctx); + explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); + + BIO_printf(bio_err, "Require explicit Policy: %s\n", + explicit_policy ? "True" : "False"); + + nodes_print("Authority", X509_policy_tree_get0_policies(tree)); + nodes_print("User", X509_policy_tree_get0_user_policies(tree)); +} + +/*- + * next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL terminated string like "abc,def,ghi" + * + * returns: a malloc'd buffer or NULL on failure. + */ +unsigned char *next_protos_parse(size_t *outlen, const char *in) +{ + size_t len; + unsigned char *out; + size_t i, start = 0; + size_t skipped = 0; + + len = strlen(in); + if (len == 0 || len >= 65535) + return NULL; + + out = app_malloc(len + 1, "NPN buffer"); + for (i = 0; i <= len; ++i) { + if (i == len || in[i] == ',') { + /* + * Zero-length ALPN elements are invalid on the wire, we could be + * strict and reject the entire string, but just ignoring extra + * commas seems harmless and more friendly. + * + * Every comma we skip in this way puts the input buffer another + * byte ahead of the output buffer, so all stores into the output + * buffer need to be decremented by the number commas skipped. + */ + if (i == start) { + ++start; + ++skipped; + continue; + } + if (i - start > 255) { + OPENSSL_free(out); + return NULL; + } + out[start-skipped] = (unsigned char)(i - start); + start = i + 1; + } else { + out[i + 1 - skipped] = in[i]; + } + } + + if (len <= skipped) { + OPENSSL_free(out); + return NULL; + } + + *outlen = len + 1 - skipped; + return out; +} + +void print_cert_checks(BIO *bio, X509 *x, + const char *checkhost, + const char *checkemail, const char *checkip) +{ + if (x == NULL) + return; + if (checkhost) { + BIO_printf(bio, "Hostname %s does%s match certificate\n", + checkhost, + X509_check_host(x, checkhost, 0, 0, NULL) == 1 + ? "" : " NOT"); + } + + if (checkemail) { + BIO_printf(bio, "Email %s does%s match certificate\n", + checkemail, X509_check_email(x, checkemail, 0, 0) + ? "" : " NOT"); + } + + if (checkip) { + BIO_printf(bio, "IP %s does%s match certificate\n", + checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT"); + } +} + +static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts) +{ + int i; + + if (opts == NULL) + return 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (pkey_ctrl_string(pkctx, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } + } + + return 1; +} + +static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts) +{ + int i; + + if (opts == NULL) + return 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (x509_ctrl_string(x, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } + } + + return 1; +} + +static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts) +{ + int i; + + if (opts == NULL) + return 1; + + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (x509_req_ctrl_string(x, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + return 0; + } + } + + return 1; +} + +static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, + const char *md, STACK_OF(OPENSSL_STRING) *sigopts) +{ + EVP_PKEY_CTX *pkctx = NULL; + char def_md[80]; + + if (ctx == NULL) + return 0; + /* + * EVP_PKEY_get_default_digest_name() returns 2 if the digest is mandatory + * for this algorithm. + */ + if (EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2 + && strcmp(def_md, "UNDEF") == 0) { + /* The signing algorithm requires there to be no digest */ + md = NULL; + } + + return EVP_DigestSignInit_ex(ctx, &pkctx, md, app_get0_libctx(), + app_get0_propq(), pkey, NULL) + && do_pkey_ctx_init(pkctx, sigopts); +} + +static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx, + const char *name, const char *value, int add_default) +{ + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); + X509_EXTENSION *new_ext = X509V3_EXT_nconf(NULL, ext_ctx, name, value); + int idx, rv = 0; + + if (new_ext == NULL) + return rv; + + idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1); + if (idx >= 0) { + X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx); + ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext); + int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */ + + if (disabled) { + X509_delete_ext(cert, idx); + X509_EXTENSION_free(found_ext); + } /* else keep existing key identifier, which might be outdated */ + rv = 1; + } else { + rv = !add_default || X509_add_ext(cert, new_ext, -1); + } + X509_EXTENSION_free(new_ext); + return rv; +} + +/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */ +int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md, + STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx) +{ + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + int self_sign; + int rv = 0; + + if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) { + /* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */ + if (!X509_set_version(cert, X509_VERSION_3)) + goto end; + + /* + * Add default SKID before such that default AKID can make use of it + * in case the certificate is self-signed + */ + /* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */ + if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1)) + goto end; + /* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */ + ERR_set_mark(); + self_sign = X509_check_private_key(cert, pkey); + ERR_pop_to_mark(); + if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier", + "keyid, issuer", !self_sign)) + goto end; + } + + if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0) + rv = (X509_sign_ctx(cert, mctx) > 0); + end: + EVP_MD_CTX_free(mctx); + return rv; +} + +/* Sign the certificate request info */ +int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md, + STACK_OF(OPENSSL_STRING) *sigopts) +{ + int rv = 0; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + + if (do_sign_init(mctx, pkey, md, sigopts) > 0) + rv = (X509_REQ_sign_ctx(x, mctx) > 0); + EVP_MD_CTX_free(mctx); + return rv; +} + +/* Sign the CRL info */ +int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md, + STACK_OF(OPENSSL_STRING) *sigopts) +{ + int rv = 0; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + + if (do_sign_init(mctx, pkey, md, sigopts) > 0) + rv = (X509_CRL_sign_ctx(x, mctx) > 0); + EVP_MD_CTX_free(mctx); + return rv; +} + +/* + * do_X509_verify returns 1 if the signature is valid, + * 0 if the signature check fails, or -1 if error occurs. + */ +int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts) +{ + int rv = 0; + + if (do_x509_init(x, vfyopts) > 0) + rv = X509_verify(x, pkey); + else + rv = -1; + return rv; +} + +/* + * do_X509_REQ_verify returns 1 if the signature is valid, + * 0 if the signature check fails, or -1 if error occurs. + */ +int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, + STACK_OF(OPENSSL_STRING) *vfyopts) +{ + int rv = 0; + + if (do_x509_req_init(x, vfyopts) > 0) + rv = X509_REQ_verify_ex(x, pkey, + app_get0_libctx(), app_get0_propq()); + else + rv = -1; + return rv; +} + +/* Get first http URL from a DIST_POINT structure */ + +static const char *get_dp_url(DIST_POINT *dp) +{ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + int i, gtype; + ASN1_STRING *uri; + if (!dp->distpoint || dp->distpoint->type != 0) + return NULL; + gens = dp->distpoint->name.fullname; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + uri = GENERAL_NAME_get0_value(gen, >ype); + if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { + const char *uptr = (const char *)ASN1_STRING_get0_data(uri); + + if (IS_HTTP(uptr)) /* can/should not use HTTPS here */ + return uptr; + } + } + return NULL; +} + +/* + * Look through a CRLDP structure and attempt to find an http URL to + * downloads a CRL from. + */ + +static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) +{ + int i; + const char *urlptr = NULL; + for (i = 0; i < sk_DIST_POINT_num(crldp); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); + urlptr = get_dp_url(dp); + if (urlptr != NULL) + return load_crl(urlptr, FORMAT_UNDEF, 0, "CRL via CDP"); + } + return NULL; +} + +/* + * Example of downloading CRLs from CRLDP: + * not usable for real world as it always downloads and doesn't cache anything. + */ + +static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *ctx, + const X509_NAME *nm) +{ + X509 *x; + STACK_OF(X509_CRL) *crls = NULL; + X509_CRL *crl; + STACK_OF(DIST_POINT) *crldp; + + crls = sk_X509_CRL_new_null(); + if (!crls) + return NULL; + x = X509_STORE_CTX_get_current_cert(ctx); + crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + crl = load_crl_crldp(crldp); + sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); + if (!crl) { + sk_X509_CRL_free(crls); + return NULL; + } + sk_X509_CRL_push(crls, crl); + /* Try to download delta CRL */ + crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); + crl = load_crl_crldp(crldp); + sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); + if (crl) + sk_X509_CRL_push(crls, crl); + return crls; +} + +void store_setup_crl_download(X509_STORE *st) +{ + X509_STORE_set_lookup_crls_cb(st, crls_http_cb); +} + +#ifndef OPENSSL_NO_SOCK +static const char *tls_error_hint(void) +{ + unsigned long err = ERR_peek_error(); + + if (ERR_GET_LIB(err) != ERR_LIB_SSL) + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) != ERR_LIB_SSL) + return NULL; + + switch (ERR_GET_REASON(err)) { + case SSL_R_WRONG_VERSION_NUMBER: + return "The server does not support (a suitable version of) TLS"; + case SSL_R_UNKNOWN_PROTOCOL: + return "The server does not support HTTPS"; + case SSL_R_CERTIFICATE_VERIFY_FAILED: + return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status"; + case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA: + return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status"; + case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE: + return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it"; + default: /* no error or no hint available for error */ + return NULL; + } +} + +/* HTTP callback function that supports TLS connection also via HTTPS proxy */ +BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail) +{ + APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg; + SSL_CTX *ssl_ctx = info->ssl_ctx; + + if (ssl_ctx == NULL) /* not using TLS */ + return bio; + if (connect) { + SSL *ssl; + BIO *sbio = NULL; + + /* adapt after fixing callback design flaw, see #17088 */ + if ((info->use_proxy + && !OSSL_HTTP_proxy_connect(bio, info->server, info->port, + NULL, NULL, /* no proxy credentials */ + info->timeout, bio_err, opt_getprog())) + || (sbio = BIO_new(BIO_f_ssl())) == NULL) { + return NULL; + } + if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) { + BIO_free(sbio); + return NULL; + } + + /* adapt after fixing callback design flaw, see #17088 */ + SSL_set_tlsext_host_name(ssl, info->server); /* not critical to do */ + + SSL_set_connect_state(ssl); + BIO_set_ssl(sbio, ssl, BIO_CLOSE); + + bio = BIO_push(sbio, bio); + } + if (!connect) { + const char *hint; + BIO *cbio; + + if (!detail) { /* disconnecting after error */ + hint = tls_error_hint(); + if (hint != NULL) + ERR_add_error_data(2, " : ", hint); + } + if (ssl_ctx != NULL) { + (void)ERR_set_mark(); + BIO_ssl_shutdown(bio); + cbio = BIO_pop(bio); /* connect+HTTP BIO */ + BIO_free(bio); /* SSL BIO */ + (void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */ + bio = cbio; + } + } + return bio; +} + +void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info) +{ + if (info != NULL) { + SSL_CTX_free(info->ssl_ctx); + OPENSSL_free(info); + } +} + +ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, + const char *no_proxy, SSL_CTX *ssl_ctx, + const STACK_OF(CONF_VALUE) *headers, + long timeout, const char *expected_content_type, + const ASN1_ITEM *it) +{ + APP_HTTP_TLS_INFO info; + char *server; + char *port; + int use_ssl; + BIO *mem; + ASN1_VALUE *resp = NULL; + + if (url == NULL || it == NULL) { + ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!OSSL_HTTP_parse_url(url, &use_ssl, NULL /* userinfo */, &server, &port, + NULL /* port_num, */, NULL, NULL, NULL)) + return NULL; + if (use_ssl && ssl_ctx == NULL) { + ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER, + "missing SSL_CTX"); + goto end; + } + if (!use_ssl && ssl_ctx != NULL) { + ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT, + "SSL_CTX given but use_ssl == 0"); + goto end; + } + + info.server = server; + info.port = port; + info.use_proxy = /* workaround for callback design flaw, see #17088 */ + OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl) != NULL; + info.timeout = timeout; + info.ssl_ctx = ssl_ctx; + mem = OSSL_HTTP_get(url, proxy, no_proxy, NULL /* bio */, NULL /* rbio */, + app_http_tls_cb, &info, 0 /* buf_size */, headers, + expected_content_type, 1 /* expect_asn1 */, + OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout); + resp = ASN1_item_d2i_bio(it, mem, NULL); + BIO_free(mem); + + end: + OPENSSL_free(server); + OPENSSL_free(port); + return resp; + +} + +ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, + const char *path, const char *proxy, + const char *no_proxy, SSL_CTX *ssl_ctx, + const STACK_OF(CONF_VALUE) *headers, + const char *content_type, + ASN1_VALUE *req, const ASN1_ITEM *req_it, + const char *expected_content_type, + long timeout, const ASN1_ITEM *rsp_it) +{ + int use_ssl = ssl_ctx != NULL; + APP_HTTP_TLS_INFO info; + BIO *rsp, *req_mem = ASN1_item_i2d_mem_bio(req_it, req); + ASN1_VALUE *res; + + if (req_mem == NULL) + return NULL; + + info.server = host; + info.port = port; + info.use_proxy = /* workaround for callback design flaw, see #17088 */ + OSSL_HTTP_adapt_proxy(proxy, no_proxy, host, use_ssl) != NULL; + info.timeout = timeout; + info.ssl_ctx = ssl_ctx; + rsp = OSSL_HTTP_transfer(NULL, host, port, path, use_ssl, + proxy, no_proxy, NULL /* bio */, NULL /* rbio */, + app_http_tls_cb, &info, + 0 /* buf_size */, headers, content_type, req_mem, + expected_content_type, 1 /* expect_asn1 */, + OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout, + 0 /* keep_alive */); + BIO_free(req_mem); + res = ASN1_item_d2i_bio(rsp_it, rsp, NULL); + BIO_free(rsp); + return res; +} + +#endif + +/* + * Platform-specific sections + */ +#if defined(_WIN32) +# ifdef fileno +# undef fileno +# define fileno(a) (int)_fileno(a) +# endif + +# include +# include + +static int WIN32_rename(const char *from, const char *to) +{ + TCHAR *tfrom = NULL, *tto; + DWORD err; + int ret = 0; + + if (sizeof(TCHAR) == 1) { + tfrom = (TCHAR *)from; + tto = (TCHAR *)to; + } else { /* UNICODE path */ + + size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; + tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); + if (tfrom == NULL) + goto err; + tto = tfrom + flen; +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen)) +# endif + for (i = 0; i < flen; i++) + tfrom[i] = (TCHAR)from[i]; +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) +# endif + for (i = 0; i < tlen; i++) + tto[i] = (TCHAR)to[i]; + } + + if (MoveFile(tfrom, tto)) + goto ok; + err = GetLastError(); + if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) { + if (DeleteFile(tto) && MoveFile(tfrom, tto)) + goto ok; + err = GetLastError(); + } + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + errno = ENOENT; + else if (err == ERROR_ACCESS_DENIED) + errno = EACCES; + else + errno = EINVAL; /* we could map more codes... */ + err: + ret = -1; + ok: + if (tfrom != NULL && tfrom != (TCHAR *)from) + free(tfrom); + return ret; +} +#endif + +/* app_tminterval section */ +#if defined(_WIN32) +double app_tminterval(int stop, int usertime) +{ + FILETIME now; + double ret = 0; + static ULARGE_INTEGER tmstart; + static int warning = 1; +# ifdef _WIN32_WINNT + static HANDLE proc = NULL; + + if (proc == NULL) { + if (check_winnt()) + proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, + GetCurrentProcessId()); + if (proc == NULL) + proc = (HANDLE) - 1; + } + + if (usertime && proc != (HANDLE) - 1) { + FILETIME junk; + GetProcessTimes(proc, &junk, &junk, &junk, &now); + } else +# endif + { + SYSTEMTIME systime; + + if (usertime && warning) { + BIO_printf(bio_err, "To get meaningful results, run " + "this program on idle system.\n"); + warning = 0; + } + GetSystemTime(&systime); + SystemTimeToFileTime(&systime, &now); + } + + if (stop == TM_START) { + tmstart.u.LowPart = now.dwLowDateTime; + tmstart.u.HighPart = now.dwHighDateTime; + } else { + ULARGE_INTEGER tmstop; + + tmstop.u.LowPart = now.dwLowDateTime; + tmstop.u.HighPart = now.dwHighDateTime; + + ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; + } + + return ret; +} +#elif defined(OPENSSL_SYS_VXWORKS) +# include + +double app_tminterval(int stop, int usertime) +{ + double ret = 0; +# ifdef CLOCK_REALTIME + static struct timespec tmstart; + struct timespec now; +# else + static unsigned long tmstart; + unsigned long now; +# endif + static int warning = 1; + + if (usertime && warning) { + BIO_printf(bio_err, "To get meaningful results, run " + "this program on idle system.\n"); + warning = 0; + } +# ifdef CLOCK_REALTIME + clock_gettime(CLOCK_REALTIME, &now); + if (stop == TM_START) + tmstart = now; + else + ret = ((now.tv_sec + now.tv_nsec * 1e-9) + - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9)); +# else + now = tickGet(); + if (stop == TM_START) + tmstart = now; + else + ret = (now - tmstart) / (double)sysClkRateGet(); +# endif + return ret; +} + +#elif defined(_SC_CLK_TCK) /* by means of unistd.h */ +# include + +double app_tminterval(int stop, int usertime) +{ + double ret = 0; + struct tms rus; + clock_t now = times(&rus); + static clock_t tmstart; + + if (usertime) + now = rus.tms_utime; + + if (stop == TM_START) { + tmstart = now; + } else { + long int tck = sysconf(_SC_CLK_TCK); + ret = (now - tmstart) / (double)tck; + } + + return ret; +} + +#else +# include +# include + +double app_tminterval(int stop, int usertime) +{ + double ret = 0; + struct rusage rus; + struct timeval now; + static struct timeval tmstart; + + if (usertime) + getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime; + else + gettimeofday(&now, NULL); + + if (stop == TM_START) + tmstart = now; + else + ret = ((now.tv_sec + now.tv_usec * 1e-6) + - (tmstart.tv_sec + tmstart.tv_usec * 1e-6)); + + return ret; +} +#endif + +int app_access(const char* name, int flag) +{ +#ifdef _WIN32 + return _access(name, flag); +#else + return access(name, flag); +#endif +} + +int app_isdir(const char *name) +{ + return opt_isdir(name); +} + +/* raw_read|write section */ +#if defined(__VMS) +# include "vms_term_sock.h" +static int stdin_sock = -1; + +static void close_stdin_sock(void) +{ + TerminalSocket (TERM_SOCK_DELETE, &stdin_sock); +} + +int fileno_stdin(void) +{ + if (stdin_sock == -1) { + TerminalSocket(TERM_SOCK_CREATE, &stdin_sock); + atexit(close_stdin_sock); + } + + return stdin_sock; +} +#else +int fileno_stdin(void) +{ + return fileno(stdin); +} +#endif + +int fileno_stdout(void) +{ + return fileno(stdout); +} + +#if defined(_WIN32) && defined(STD_INPUT_HANDLE) +int raw_read_stdin(void *buf, int siz) +{ + DWORD n; + if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) + return n; + else + return -1; +} +#elif defined(__VMS) +# include + +int raw_read_stdin(void *buf, int siz) +{ + return recv(fileno_stdin(), buf, siz, 0); +} +#else +# if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif +# endif +int raw_read_stdin(void *buf, int siz) +{ + return read(fileno_stdin(), buf, siz); +} +#endif + +#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) +int raw_write_stdout(const void *buf, int siz) +{ + DWORD n; + if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) + return n; + else + return -1; +} +#elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) && defined(_SPT_MODEL_) +# if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif +# endif +int raw_write_stdout(const void *buf,int siz) +{ + return write(fileno(stdout),(void*)buf,siz); +} +#else +# if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif +# endif +int raw_write_stdout(const void *buf, int siz) +{ + return write(fileno_stdout(), buf, siz); +} +#endif + +/* + * Centralized handling of input and output files with format specification + * The format is meant to show what the input and output is supposed to be, + * and is therefore a show of intent more than anything else. However, it + * does impact behavior on some platforms, such as differentiating between + * text and binary input/output on non-Unix platforms + */ +BIO *dup_bio_in(int format) +{ + return BIO_new_fp(stdin, + BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); +} + +BIO *dup_bio_out(int format) +{ + BIO *b = BIO_new_fp(stdout, + BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); + void *prefix = NULL; + + if (b == NULL) + return NULL; + +#ifdef OPENSSL_SYS_VMS + if (FMT_istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + + if (FMT_istext(format) + && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { + b = BIO_push(BIO_new(BIO_f_prefix()), b); + BIO_set_prefix(b, prefix); + } + + return b; +} + +BIO *dup_bio_err(int format) +{ + BIO *b = BIO_new_fp(stderr, + BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); +#ifdef OPENSSL_SYS_VMS + if (b != NULL && FMT_istext(format)) + b = BIO_push(BIO_new(BIO_f_linebuffer()), b); +#endif + return b; +} + +void unbuffer(FILE *fp) +{ +/* + * On VMS, setbuf() will only take 32-bit pointers, and a compilation + * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. + * However, we trust that the C RTL will never give us a FILE pointer + * above the first 4 GB of memory, so we simply turn off the warning + * temporarily. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment save +# pragma message disable maylosedata2 +#endif + setbuf(fp, NULL); +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma environment restore +#endif +} + +static const char *modestr(char mode, int format) +{ + OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); + + switch (mode) { + case 'a': + return FMT_istext(format) ? "a" : "ab"; + case 'r': + return FMT_istext(format) ? "r" : "rb"; + case 'w': + return FMT_istext(format) ? "w" : "wb"; + } + /* The assert above should make sure we never reach this point */ + return NULL; +} + +static const char *modeverb(char mode) +{ + switch (mode) { + case 'a': + return "appending"; + case 'r': + return "reading"; + case 'w': + return "writing"; + } + return "(doing something)"; +} + +/* + * Open a file for writing, owner-read-only. + */ +BIO *bio_open_owner(const char *filename, int format, int private) +{ + FILE *fp = NULL; + BIO *b = NULL; + int textmode, bflags; +#ifndef OPENSSL_NO_POSIX_IO + int fd = -1, mode; +#endif + + if (!private || filename == NULL || strcmp(filename, "-") == 0) + return bio_open_default(filename, 'w', format); + + textmode = FMT_istext(format); +#ifndef OPENSSL_NO_POSIX_IO + mode = O_WRONLY; +# ifdef O_CREAT + mode |= O_CREAT; +# endif +# ifdef O_TRUNC + mode |= O_TRUNC; +# endif + if (!textmode) { +# ifdef O_BINARY + mode |= O_BINARY; +# elif defined(_O_BINARY) + mode |= _O_BINARY; +# endif + } + +# ifdef OPENSSL_SYS_VMS + /* VMS doesn't have O_BINARY, it just doesn't make sense. But, + * it still needs to know that we're going binary, or fdopen() + * will fail with "invalid argument"... so we tell VMS what the + * context is. + */ + if (!textmode) + fd = open(filename, mode, 0600, "ctx=bin"); + else +# endif + fd = open(filename, mode, 0600); + if (fd < 0) + goto err; + fp = fdopen(fd, modestr('w', format)); +#else /* OPENSSL_NO_POSIX_IO */ + /* Have stdio but not Posix IO, do the best we can */ + fp = fopen(filename, modestr('w', format)); +#endif /* OPENSSL_NO_POSIX_IO */ + if (fp == NULL) + goto err; + bflags = BIO_CLOSE; + if (textmode) + bflags |= BIO_FP_TEXT; + b = BIO_new_fp(fp, bflags); + if (b != NULL) + return b; + + err: + BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", + opt_getprog(), filename, strerror(errno)); + ERR_print_errors(bio_err); + /* If we have fp, then fdopen took over fd, so don't close both. */ + if (fp != NULL) + fclose(fp); +#ifndef OPENSSL_NO_POSIX_IO + else if (fd >= 0) + close(fd); +#endif + return NULL; +} + +static BIO *bio_open_default_(const char *filename, char mode, int format, + int quiet) +{ + BIO *ret; + + if (filename == NULL || strcmp(filename, "-") == 0) { + ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open %s, %s\n", + mode == 'r' ? "stdin" : "stdout", strerror(errno)); + } else { + ret = BIO_new_file(filename, modestr(mode, format)); + if (quiet) { + ERR_clear_error(); + return ret; + } + if (ret != NULL) + return ret; + BIO_printf(bio_err, + "Can't open \"%s\" for %s, %s\n", + filename, modeverb(mode), strerror(errno)); + } + ERR_print_errors(bio_err); + return NULL; +} + +BIO *bio_open_default(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 0); +} + +BIO *bio_open_default_quiet(const char *filename, char mode, int format) +{ + return bio_open_default_(filename, mode, format, 1); +} + +void wait_for_async(SSL *s) +{ + /* On Windows select only works for sockets, so we simply don't wait */ +#ifndef OPENSSL_SYS_WINDOWS + int width = 0; + fd_set asyncfds; + OSSL_ASYNC_FD *fds; + size_t numfds; + size_t i; + + if (!SSL_get_all_async_fds(s, NULL, &numfds)) + return; + if (numfds == 0) + return; + fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds"); + if (!SSL_get_all_async_fds(s, fds, &numfds)) { + OPENSSL_free(fds); + return; + } + + FD_ZERO(&asyncfds); + for (i = 0; i < numfds; i++) { + if (width <= (int)fds[i]) + width = (int)fds[i] + 1; + openssl_fdset((int)fds[i], &asyncfds); + } + select(width, (void *)&asyncfds, NULL, NULL, NULL); + OPENSSL_free(fds); +#endif +} + +/* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */ +#if defined(OPENSSL_SYS_MSDOS) +int has_stdin_waiting(void) +{ +# if defined(OPENSSL_SYS_WINDOWS) + HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE); + DWORD events = 0; + INPUT_RECORD inputrec; + DWORD insize = 1; + BOOL peeked; + + if (inhand == INVALID_HANDLE_VALUE) { + return 0; + } + + peeked = PeekConsoleInput(inhand, &inputrec, insize, &events); + if (!peeked) { + /* Probably redirected input? _kbhit() does not work in this case */ + if (!feof(stdin)) { + return 1; + } + return 0; + } +# endif + return _kbhit(); +} +#endif + +/* Corrupt a signature by modifying final byte */ +void corrupt_signature(const ASN1_STRING *signature) +{ + unsigned char *s = signature->data; + s[signature->length - 1] ^= 0x1; +} + +int set_cert_times(X509 *x, const char *startdate, const char *enddate, + int days) +{ + if (startdate == NULL || strcmp(startdate, "today") == 0) { + if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) + return 0; + } else { + if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) + return 0; + } + if (enddate == NULL) { + if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) + == NULL) + return 0; + } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { + return 0; + } + return 1; +} + +int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate) +{ + int ret = 0; + ASN1_TIME *tm = ASN1_TIME_new(); + + if (tm == NULL) + goto end; + + if (lastupdate == NULL) { + if (X509_gmtime_adj(tm, 0) == NULL) + goto end; + } else { + if (!ASN1_TIME_set_string_X509(tm, lastupdate)) + goto end; + } + + if (!X509_CRL_set1_lastUpdate(crl, tm)) + goto end; + + ret = 1; +end: + ASN1_TIME_free(tm); + return ret; +} + +int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate, + long days, long hours, long secs) +{ + int ret = 0; + ASN1_TIME *tm = ASN1_TIME_new(); + + if (tm == NULL) + goto end; + + if (nextupdate == NULL) { + if (X509_time_adj_ex(tm, days, hours * 60 * 60 + secs, NULL) == NULL) + goto end; + } else { + if (!ASN1_TIME_set_string_X509(tm, nextupdate)) + goto end; + } + + if (!X509_CRL_set1_nextUpdate(crl, tm)) + goto end; + + ret = 1; +end: + ASN1_TIME_free(tm); + return ret; +} + +void make_uppercase(char *string) +{ + int i; + + for (i = 0; string[i] != '\0'; i++) + string[i] = toupper((unsigned char)string[i]); +} + +/* This function is defined here due to visibility of bio_err */ +int opt_printf_stderr(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = BIO_vprintf(bio_err, fmt, ap); + va_end(ap); + return ret; +} + +OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts, + const OSSL_PARAM *paramdefs) +{ + OSSL_PARAM *params = NULL; + size_t sz = (size_t)sk_OPENSSL_STRING_num(opts); + size_t params_n; + char *opt = "", *stmp, *vtmp = NULL; + int found = 1; + + if (opts == NULL) + return NULL; + + params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * (sz + 1)); + if (params == NULL) + return NULL; + + for (params_n = 0; params_n < sz; params_n++) { + opt = sk_OPENSSL_STRING_value(opts, (int)params_n); + if ((stmp = OPENSSL_strdup(opt)) == NULL + || (vtmp = strchr(stmp, ':')) == NULL) + goto err; + /* Replace ':' with 0 to terminate the string pointed to by stmp */ + *vtmp = 0; + /* Skip over the separator so that vmtp points to the value */ + vtmp++; + if (!OSSL_PARAM_allocate_from_text(¶ms[params_n], paramdefs, + stmp, vtmp, strlen(vtmp), &found)) + goto err; + OPENSSL_free(stmp); + } + params[params_n] = OSSL_PARAM_construct_end(); + return params; +err: + OPENSSL_free(stmp); + BIO_printf(bio_err, "Parameter %s '%s'\n", found ? "error" : "unknown", + opt); + ERR_print_errors(bio_err); + app_params_free(params); + return NULL; +} + +void app_params_free(OSSL_PARAM *params) +{ + int i; + + if (params != NULL) { + for (i = 0; params[i].key != NULL; ++i) + OPENSSL_free(params[i].data); + OPENSSL_free(params); + } +} + +EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose) +{ + EVP_PKEY *res = NULL; + + if (verbose && alg != NULL) { + BIO_printf(bio_err, "Generating %s key", alg); + if (bits > 0) + BIO_printf(bio_err, " with %d bits\n", bits); + else + BIO_printf(bio_err, "\n"); + } + if (!RAND_status()) + BIO_printf(bio_err, "Warning: generating random key material may take a long time\n" + "if the system has a poor entropy source\n"); + if (EVP_PKEY_keygen(ctx, &res) <= 0) + app_bail_out("%s: Error generating %s key\n", opt_getprog(), + alg != NULL ? alg : "asymmetric"); + return res; +} + +EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg) +{ + EVP_PKEY *res = NULL; + + if (!RAND_status()) + BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n" + "if the system has a poor entropy source\n"); + if (EVP_PKEY_paramgen(ctx, &res) <= 0) + app_bail_out("%s: Generating %s key parameters failed\n", + opt_getprog(), alg != NULL ? alg : "asymmetric"); + return res; +} + +/* + * Return non-zero if the legacy path is still an option. + * This decision is based on the global command line operations and the + * behaviour thus far. + */ +int opt_legacy_okay(void) +{ + int provider_options = opt_provider_option_given(); + int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL; + /* + * Having a provider option specified or a custom library context or + * property query, is a sure sign we're not using legacy. + */ + if (provider_options || libctx) + return 0; + return 1; +} diff --git a/apps/lib/apps_ui.c b/apps/lib/apps_ui.c new file mode 100644 --- /dev/null +++ b/apps/lib/apps_ui.c @@ -0,0 +1,223 @@ +/* + * Copyright 1995-2020 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps_ui.h" + +static UI_METHOD *ui_method = NULL; +static const UI_METHOD *ui_base_method = NULL; + +static int ui_open(UI *ui) +{ + int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method); + + if (opener != NULL) + return opener(ui); + return 1; +} + +static int ui_read(UI *ui, UI_STRING *uis) +{ + int (*reader)(UI *ui, UI_STRING *uis) = NULL; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD + && UI_get0_user_data(ui)) { + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + { + const char *password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + + if (password != NULL) { + UI_set_result(ui, uis, password); + return 1; + } + } + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + } + + reader = UI_method_get_reader(ui_base_method); + if (reader != NULL) + return reader(ui, uis); + /* Default to the empty password if we've got nothing better */ + UI_set_result(ui, uis, ""); + return 1; +} + +static int ui_write(UI *ui, UI_STRING *uis) +{ + int (*writer)(UI *ui, UI_STRING *uis) = NULL; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD + && UI_get0_user_data(ui)) { + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + { + const char *password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + + if (password != NULL) + return 1; + } + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + } + + writer = UI_method_get_writer(ui_base_method); + if (writer != NULL) + return writer(ui, uis); + return 1; +} + +static int ui_close(UI *ui) +{ + int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method); + + if (closer != NULL) + return closer(ui); + return 1; +} + +/* object_name defaults to prompt_info from ui user data if present */ +static char *ui_prompt_construct(UI *ui, const char *phrase_desc, + const char *object_name) +{ + PW_CB_DATA *cb_data = (PW_CB_DATA *)UI_get0_user_data(ui); + + if (phrase_desc == NULL) + phrase_desc = "pass phrase"; + if (object_name == NULL && cb_data != NULL) + object_name = cb_data->prompt_info; + return UI_construct_prompt(NULL, phrase_desc, object_name); +} + +int set_base_ui_method(const UI_METHOD *ui_meth) +{ + if (ui_meth == NULL) + ui_meth = UI_null(); + ui_base_method = ui_meth; + return 1; +} + +int setup_ui_method(void) +{ + ui_base_method = UI_null(); +#ifndef OPENSSL_NO_UI_CONSOLE + ui_base_method = UI_OpenSSL(); +#endif + ui_method = UI_create_method("OpenSSL application user interface"); + return ui_method != NULL + && 0 == UI_method_set_opener(ui_method, ui_open) + && 0 == UI_method_set_reader(ui_method, ui_read) + && 0 == UI_method_set_writer(ui_method, ui_write) + && 0 == UI_method_set_closer(ui_method, ui_close) + && 0 == UI_method_set_prompt_constructor(ui_method, + ui_prompt_construct); +} + +void destroy_ui_method(void) +{ + if (ui_method != NULL) { + UI_destroy_method(ui_method); + ui_method = NULL; + } +} + +const UI_METHOD *get_ui_method(void) +{ + return ui_method; +} + +static void *ui_malloc(int sz, const char *what) +{ + void *vp = OPENSSL_malloc(sz); + + if (vp == NULL) { + BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what); + ERR_print_errors(bio_err); + exit(1); + } + return vp; +} + +int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data) +{ + int res = 0; + UI *ui; + int ok = 0; + char *buff = NULL; + int ui_flags = 0; + const char *prompt_info = NULL; + char *prompt; + + if ((ui = UI_new_method(ui_method)) == NULL) + return 0; + + if (cb_data != NULL && cb_data->prompt_info != NULL) + prompt_info = cb_data->prompt_info; + prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); + if (prompt == NULL) { + BIO_printf(bio_err, "Out of memory\n"); + UI_free(ui); + return 0; + } + + ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; + UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); + + /* We know that there is no previous user data to return to us */ + (void)UI_add_user_data(ui, cb_data); + + ok = UI_add_input_string(ui, prompt, ui_flags, buf, + PW_MIN_LENGTH, bufsiz - 1); + + if (ok >= 0 && verify) { + buff = ui_malloc(bufsiz, "password buffer"); + ok = UI_add_verify_string(ui, prompt, ui_flags, buff, + PW_MIN_LENGTH, bufsiz - 1, buf); + } + if (ok >= 0) + do { + ok = UI_process(ui); + } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); + + OPENSSL_clear_free(buff, (unsigned int)bufsiz); + + if (ok >= 0) + res = strlen(buf); + if (ok == -1) { + BIO_printf(bio_err, "User interface error\n"); + ERR_print_errors(bio_err); + OPENSSL_cleanse(buf, (unsigned int)bufsiz); + res = 0; + } + if (ok == -2) { + BIO_printf(bio_err, "aborted!\n"); + OPENSSL_cleanse(buf, (unsigned int)bufsiz); + res = 0; + } + UI_free(ui); + OPENSSL_free(prompt); + return res; +} diff --git a/apps/lib/build.info b/apps/lib/build.info new file mode 100644 --- /dev/null +++ b/apps/lib/build.info @@ -0,0 +1,23 @@ +# Auxiliary program source +IF[{- $config{target} =~ /^(?:VC-|mingw|BC-)/ -}] + # It's called 'init', but doesn't have much 'init' in it... + $AUXLIBAPPSSRC=win32_init.c +ENDIF +IF[{- $config{target} =~ /^vms-/ -}] + $AUXLIBAPPSSRC=vms_term_sock.c vms_decc_argv.c +ENDIF + +# Source for libapps +$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \ + columns.c app_params.c names.c app_provider.c app_x509.c http_server.c \ + engine.c engine_loader.c app_libctx.c + +IF[{- !$disabled{apps} -}] + LIBS{noinst}=../libapps.a + SOURCE[../libapps.a]=$LIBAPPSSRC $AUXLIBAPPSSRC + INCLUDE[../libapps.a]=../.. ../../include ../include +ENDIF + +IF[{- !$disabled{srp} -}] + SOURCE[../libapps.a]=tlssrp_depr.c +ENDIF diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c new file mode 100644 --- /dev/null +++ b/apps/lib/cmp_mock_srv.c @@ -0,0 +1,450 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright Siemens AG 2018-2020 + * + * 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 atf + * https://www.openssl.org/source/license.html + */ + +#include "apps.h" +#include "cmp_mock_srv.h" + +#include +#include +#include + +/* the context for the CMP mock server */ +typedef struct +{ + X509 *certOut; /* certificate to be returned in cp/ip/kup msg */ + STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */ + STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */ + OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */ + int sendError; /* send error response also on valid requests */ + OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */ + int certReqId; /* id of last ir/cr/kur, used for polling */ + int pollCount; /* number of polls before actual cert response */ + int curr_pollCount; /* number of polls so far for current request */ + int checkAfterTime; /* time the client should wait between polling */ +} mock_srv_ctx; + + +static void mock_srv_ctx_free(mock_srv_ctx *ctx) +{ + if (ctx == NULL) + return; + + OSSL_CMP_PKISI_free(ctx->statusOut); + X509_free(ctx->certOut); + sk_X509_pop_free(ctx->chainOut, X509_free); + sk_X509_pop_free(ctx->caPubsOut, X509_free); + OSSL_CMP_MSG_free(ctx->certReq); + OPENSSL_free(ctx); +} + +static mock_srv_ctx *mock_srv_ctx_new(void) +{ + mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx)); + + if (ctx == NULL) + goto err; + + if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL) + goto err; + + ctx->certReqId = -1; + + /* all other elements are initialized to 0 or NULL, respectively */ + return ctx; + err: + mock_srv_ctx_free(ctx); + return NULL; +} + +int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (cert == NULL || X509_up_ref(cert)) { + X509_free(ctx->certOut); + ctx->certOut = cert; + return 1; + } + return 0; +} + +int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *chain) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + STACK_OF(X509) *chain_copy = NULL; + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL) + return 0; + sk_X509_pop_free(ctx->chainOut, X509_free); + ctx->chainOut = chain_copy; + return 1; +} + +int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, + STACK_OF(X509) *caPubs) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + STACK_OF(X509) *caPubs_copy = NULL; + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL) + return 0; + sk_X509_pop_free(ctx->caPubsOut, X509_free); + ctx->caPubsOut = caPubs_copy; + return 1; +} + +int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, + int fail_info, const char *text) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + OSSL_CMP_PKISI *si; + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL) + return 0; + OSSL_CMP_PKISI_free(ctx->statusOut); + ctx->statusOut = si; + return 1; +} + +int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + ctx->sendError = val != 0; + return 1; +} + +int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (count < 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS); + return 0; + } + ctx->pollCount = count; + return 1; +} + +int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + ctx->checkAfterTime = sec; + return 1; +} + +static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *cert_req, + int certReqId, + const OSSL_CRMF_MSG *crm, + const X509_REQ *p10cr, + X509 **certOut, + STACK_OF(X509) **chainOut, + STACK_OF(X509) **caPubs) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + OSSL_CMP_PKISI *si = NULL; + + if (ctx == NULL || cert_req == NULL + || certOut == NULL || chainOut == NULL || caPubs == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + if (ctx->sendError) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + return NULL; + } + + *certOut = NULL; + *chainOut = NULL; + *caPubs = NULL; + ctx->certReqId = certReqId; + + if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { + /* start polling */ + if (ctx->certReq != NULL) { + /* already in polling mode */ + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return NULL; + } + if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL) + return NULL; + return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); + } + if (ctx->curr_pollCount >= ctx->pollCount) + /* give final response after polling */ + ctx->curr_pollCount = 0; + + if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_KUR + && crm != NULL && ctx->certOut != NULL) { + const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm); + const X509_NAME *issuer = X509_get_issuer_name(ctx->certOut); + const ASN1_INTEGER *serial = X509_get0_serialNumber(ctx->certOut); + + if (cid == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID); + return NULL; + } + if (issuer != NULL + && X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID); + return NULL; + } + if (serial != NULL + && ASN1_INTEGER_cmp(serial, + OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID); + return NULL; + } + } + + if (ctx->certOut != NULL + && (*certOut = X509_dup(ctx->certOut)) == NULL) + goto err; + if (ctx->chainOut != NULL + && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL) + goto err; + if (ctx->caPubsOut != NULL + && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL) + goto err; + if (ctx->statusOut != NULL + && (si = OSSL_CMP_PKISI_dup(ctx->statusOut)) == NULL) + goto err; + return si; + + err: + X509_free(*certOut); + *certOut = NULL; + sk_X509_pop_free(*chainOut, X509_free); + *chainOut = NULL; + sk_X509_pop_free(*caPubs, X509_free); + *caPubs = NULL; + return NULL; +} + +static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *rr, + const X509_NAME *issuer, + const ASN1_INTEGER *serial) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL || rr == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + if (ctx->sendError || ctx->certOut == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + return NULL; + } + + /* Allow any RR derived from CSR, which may include subject and serial */ + if (issuer == NULL || serial == NULL) + return OSSL_CMP_PKISI_dup(ctx->statusOut); + + /* accept revocation only for the certificate we sent in ir/cr/kur */ + if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0 + || ASN1_INTEGER_cmp(serial, + X509_get0_serialNumber(ctx->certOut)) != 0) { + ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED, + "wrong certificate to revoke"); + return NULL; + } + return OSSL_CMP_PKISI_dup(ctx->statusOut); +} + +static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *genm, + const STACK_OF(OSSL_CMP_ITAV) *in, + STACK_OF(OSSL_CMP_ITAV) **out) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL || genm == NULL || in == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (sk_OSSL_CMP_ITAV_num(in) > 1 || ctx->sendError) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + return 0; + } + + *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup, + OSSL_CMP_ITAV_free); + return *out != NULL; +} + +static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error, + const OSSL_CMP_PKISI *statusInfo, + const ASN1_INTEGER *errorCode, + const OSSL_CMP_PKIFREETEXT *errorDetails) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + char buf[OSSL_CMP_PKISI_BUFLEN]; + char *sibuf; + int i; + + if (ctx == NULL || error == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return; + } + + BIO_printf(bio_err, "mock server received error:\n"); + + if (statusInfo == NULL) { + BIO_printf(bio_err, "pkiStatusInfo absent\n"); + } else { + sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf)); + BIO_printf(bio_err, "pkiStatusInfo: %s\n", + sibuf != NULL ? sibuf: ""); + } + + if (errorCode == NULL) + BIO_printf(bio_err, "errorCode absent\n"); + else + BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode)); + + if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) { + BIO_printf(bio_err, "errorDetails absent\n"); + } else { + BIO_printf(bio_err, "errorDetails: "); + for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) { + if (i > 0) + BIO_printf(bio_err, ", "); + BIO_printf(bio_err, "\""); + ASN1_STRING_print(bio_err, + sk_ASN1_UTF8STRING_value(errorDetails, i)); + BIO_printf(bio_err, "\""); + } + BIO_printf(bio_err, "\n"); + } +} + +static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *certConf, int certReqId, + const ASN1_OCTET_STRING *certHash, + const OSSL_CMP_PKISI *si) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + ASN1_OCTET_STRING *digest; + + if (ctx == NULL || certConf == NULL || certHash == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (ctx->sendError || ctx->certOut == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + return 0; + } + + if (certReqId != ctx->certReqId) { + /* in case of error, invalid reqId -1 */ + ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); + return 0; + } + + if ((digest = X509_digest_sig(ctx->certOut, NULL, NULL)) == NULL) + return 0; + if (ASN1_OCTET_STRING_cmp(certHash, digest) != 0) { + ASN1_OCTET_STRING_free(digest); + ERR_raise(ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED); + return 0; + } + ASN1_OCTET_STRING_free(digest); + return 1; +} + +static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *pollReq, int certReqId, + OSSL_CMP_MSG **certReq, int64_t *check_after) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + + if (ctx == NULL || pollReq == NULL + || certReq == NULL || check_after == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if (ctx->sendError) { + *certReq = NULL; + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + return 0; + } + if (ctx->certReq == NULL) { + /* not currently in polling mode */ + *certReq = NULL; + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; + } + + if (++ctx->curr_pollCount >= ctx->pollCount) { + /* end polling */ + *certReq = ctx->certReq; + ctx->certReq = NULL; + *check_after = 0; + } else { + *certReq = NULL; + *check_after = ctx->checkAfterTime; + } + return 1; +} + +OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq) +{ + OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq); + mock_srv_ctx *ctx = mock_srv_ctx_new(); + + if (srv_ctx != NULL && ctx != NULL + && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request, + process_rr, process_genm, process_error, + process_certConf, process_pollReq)) + return srv_ctx; + + mock_srv_ctx_free(ctx); + OSSL_CMP_SRV_CTX_free(srv_ctx); + return NULL; +} + +void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx) +{ + if (srv_ctx != NULL) + mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx)); + OSSL_CMP_SRV_CTX_free(srv_ctx); +} diff --git a/apps/lib/columns.c b/apps/lib/columns.c new file mode 100644 --- /dev/null +++ b/apps/lib/columns.c @@ -0,0 +1,27 @@ +/* + * 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "apps.h" +#include "function.h" + +void calculate_columns(FUNCTION *functions, DISPLAY_COLUMNS *dc) +{ + FUNCTION *f; + int len, maxlen = 0; + + for (f = functions; f->name != NULL; ++f) + if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher) + if ((len = strlen(f->name)) > maxlen) + maxlen = len; + + dc->width = maxlen + 2; + dc->columns = (80 - 1) / dc->width; +} + diff --git a/apps/lib/engine.c b/apps/lib/engine.c new file mode 100644 --- /dev/null +++ b/apps/lib/engine.c @@ -0,0 +1,193 @@ +/* + * Copyright 2020 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 + * https://www.openssl.org/source/license.html + */ + +/* + * Here is a set of wrappers for the ENGINE API, which are no-ops when the + * ENGINE API is disabled / removed. + * We need to suppress deprecation warnings to make this work. + */ +#define OPENSSL_SUPPRESS_DEPRECATED + +#include /* strcmp */ + +#include /* Ensure we have the ENGINE type, regardless */ +#include +#ifndef OPENSSL_NO_ENGINE +# include +#endif +#include "apps.h" + +#ifndef OPENSSL_NO_ENGINE +/* Try to load an engine in a shareable library */ +static ENGINE *try_load_engine(const char *engine) +{ + ENGINE *e = NULL; + + if ((e = ENGINE_by_id("dynamic")) != NULL) { + if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) + || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { + ENGINE_free(e); + e = NULL; + } + } + return e; +} +#endif + +ENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug) +{ + ENGINE *e = NULL; + +#ifndef OPENSSL_NO_ENGINE + if (id != NULL) { + if (strcmp(id, "auto") == 0) { + BIO_printf(bio_err, "Enabling auto ENGINE support\n"); + ENGINE_register_all_complete(); + return NULL; + } + if ((e = ENGINE_by_id(id)) == NULL + && (e = try_load_engine(id)) == NULL) { + BIO_printf(bio_err, "Invalid engine \"%s\"\n", id); + ERR_print_errors(bio_err); + return NULL; + } + if (debug) + (void)ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); + if (!ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, + (void *)get_ui_method(), 0, 1) + || !ENGINE_set_default(e, methods)) { + BIO_printf(bio_err, "Cannot use engine \"%s\"\n", ENGINE_get_id(e)); + ERR_print_errors(bio_err); + ENGINE_free(e); + return NULL; + } + + BIO_printf(bio_err, "Engine \"%s\" set.\n", ENGINE_get_id(e)); + } +#endif + return e; +} + +void release_engine(ENGINE *e) +{ +#ifndef OPENSSL_NO_ENGINE + /* Free our "structural" reference. */ + ENGINE_free(e); +#endif +} + +int init_engine(ENGINE *e) +{ + int rv = 1; + +#ifndef OPENSSL_NO_ENGINE + rv = ENGINE_init(e); +#endif + return rv; +} + +int finish_engine(ENGINE *e) +{ + int rv = 1; + +#ifndef OPENSSL_NO_ENGINE + rv = ENGINE_finish(e); +#endif + return rv; +} + +char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc) +{ + char *new_uri = NULL; + +#ifndef OPENSSL_NO_ENGINE + if (e == NULL) { + BIO_printf(bio_err, "No engine specified for loading %s\n", desc); + } else if (key_id == NULL) { + BIO_printf(bio_err, "No engine key id specified for loading %s\n", desc); + } else { + const char *engineid = ENGINE_get_id(e); + size_t uri_sz = + sizeof(ENGINE_SCHEME_COLON) - 1 + + strlen(engineid) + + 1 /* : */ + + strlen(key_id) + + 1 /* \0 */ + ; + + new_uri = OPENSSL_malloc(uri_sz); + if (new_uri != NULL) { + OPENSSL_strlcpy(new_uri, ENGINE_SCHEME_COLON, uri_sz); + OPENSSL_strlcat(new_uri, engineid, uri_sz); + OPENSSL_strlcat(new_uri, ":", uri_sz); + OPENSSL_strlcat(new_uri, key_id, uri_sz); + } + } +#else + BIO_printf(bio_err, "Engines not supported for loading %s\n", desc); +#endif + return new_uri; +} + +int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *tmpeng = NULL; + int pkey_id = NID_undef; + + ERR_set_mark(); + ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1); + +#if !defined(OPENSSL_NO_ENGINE) + ENGINE_finish(tmpeng); + + if (ameth == NULL && e != NULL) + ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1); + else +#endif + /* We're only interested if it comes from an ENGINE */ + if (tmpeng == NULL) + ameth = NULL; + + ERR_pop_to_mark(); + if (ameth == NULL) + return NID_undef; + + EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); + + return pkey_id; +} + +const EVP_MD *get_digest_from_engine(const char *name) +{ +#ifndef OPENSSL_NO_ENGINE + ENGINE *eng; + + eng = ENGINE_get_digest_engine(OBJ_sn2nid(name)); + if (eng != NULL) { + ENGINE_finish(eng); + return EVP_get_digestbyname(name); + } +#endif + return NULL; +} + +const EVP_CIPHER *get_cipher_from_engine(const char *name) +{ +#ifndef OPENSSL_NO_ENGINE + ENGINE *eng; + + eng = ENGINE_get_cipher_engine(OBJ_sn2nid(name)); + if (eng != NULL) { + ENGINE_finish(eng); + return EVP_get_cipherbyname(name); + } +#endif + return NULL; +} diff --git a/apps/lib/engine_loader.c b/apps/lib/engine_loader.c new file mode 100644 --- /dev/null +++ b/apps/lib/engine_loader.c @@ -0,0 +1,203 @@ +/* + * Copyright 2018-2022 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 + * https://www.openssl.org/source/license.html + */ + +/* + * Here is an STORE loader for ENGINE backed keys. It relies on deprecated + * functions, and therefore need to have deprecation warnings suppressed. + * This file is not compiled at all in a '--api=3 no-deprecated' configuration. + */ +#define OPENSSL_SUPPRESS_DEPRECATED + +#include "apps.h" + +#ifndef OPENSSL_NO_ENGINE + +# include +# include +# include +# include + +/* + * Support for legacy private engine keys via the 'org.openssl.engine:' scheme + * + * org.openssl.engine:{engineid}:{keyid} + * + * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key() + * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly + * this sort of purpose. + */ + +/* Local definition of OSSL_STORE_LOADER_CTX */ +struct ossl_store_loader_ctx_st { + ENGINE *e; /* Structural reference */ + char *keyid; + int expected; + int loaded; /* 0 = key not loaded yet, 1 = key loaded */ +}; + +static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid) +{ + OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) { + ctx->e = e; + ctx->keyid = keyid; + } + return ctx; +} + +static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx) +{ + if (ctx != NULL) { + ENGINE_free(ctx->e); + OPENSSL_free(ctx->keyid); + OPENSSL_free(ctx); + } +} + +static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader, + const char *uri, + const UI_METHOD *ui_method, + void *ui_data) +{ + const char *p = uri, *q; + ENGINE *e = NULL; + char *keyid = NULL; + OSSL_STORE_LOADER_CTX *ctx = NULL; + + if (OPENSSL_strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1) + != 0) + return NULL; + p += sizeof(ENGINE_SCHEME_COLON) - 1; + + /* Look for engine ID */ + q = strchr(p, ':'); + if (q != NULL /* There is both an engine ID and a key ID */ + && p[0] != ':' /* The engine ID is at least one character */ + && q[1] != '\0') { /* The key ID is at least one character */ + char engineid[256]; + size_t engineid_l = q - p; + + strncpy(engineid, p, engineid_l); + engineid[engineid_l] = '\0'; + e = ENGINE_by_id(engineid); + + keyid = OPENSSL_strdup(q + 1); + } + + if (e != NULL && keyid != NULL) + ctx = OSSL_STORE_LOADER_CTX_new(e, keyid); + + if (ctx == NULL) { + OPENSSL_free(keyid); + ENGINE_free(e); + } + + return ctx; +} + +static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected) +{ + if (expected == 0 + || expected == OSSL_STORE_INFO_PUBKEY + || expected == OSSL_STORE_INFO_PKEY) { + ctx->expected = expected; + return 1; + } + return 0; +} + +static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx, + const UI_METHOD *ui_method, void *ui_data) +{ + EVP_PKEY *pkey = NULL, *pubkey = NULL; + OSSL_STORE_INFO *info = NULL; + + if (ctx->loaded == 0) { + if (ENGINE_init(ctx->e)) { + if (ctx->expected == 0 + || ctx->expected == OSSL_STORE_INFO_PKEY) + pkey = + ENGINE_load_private_key(ctx->e, ctx->keyid, + (UI_METHOD *)ui_method, ui_data); + if ((pkey == NULL && ctx->expected == 0) + || ctx->expected == OSSL_STORE_INFO_PUBKEY) + pubkey = + ENGINE_load_public_key(ctx->e, ctx->keyid, + (UI_METHOD *)ui_method, ui_data); + ENGINE_finish(ctx->e); + } + } + + ctx->loaded = 1; + + if (pubkey != NULL) + info = OSSL_STORE_INFO_new_PUBKEY(pubkey); + else if (pkey != NULL) + info = OSSL_STORE_INFO_new_PKEY(pkey); + if (info == NULL) { + EVP_PKEY_free(pkey); + EVP_PKEY_free(pubkey); + } + return info; +} + +static int engine_eof(OSSL_STORE_LOADER_CTX *ctx) +{ + return ctx->loaded != 0; +} + +static int engine_error(OSSL_STORE_LOADER_CTX *ctx) +{ + return 0; +} + +static int engine_close(OSSL_STORE_LOADER_CTX *ctx) +{ + OSSL_STORE_LOADER_CTX_free(ctx); + return 1; +} + +int setup_engine_loader(void) +{ + OSSL_STORE_LOADER *loader = NULL; + + if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL + || !OSSL_STORE_LOADER_set_open(loader, engine_open) + || !OSSL_STORE_LOADER_set_expect(loader, engine_expect) + || !OSSL_STORE_LOADER_set_load(loader, engine_load) + || !OSSL_STORE_LOADER_set_eof(loader, engine_eof) + || !OSSL_STORE_LOADER_set_error(loader, engine_error) + || !OSSL_STORE_LOADER_set_close(loader, engine_close) + || !OSSL_STORE_register_loader(loader)) { + OSSL_STORE_LOADER_free(loader); + loader = NULL; + } + + return loader != NULL; +} + +void destroy_engine_loader(void) +{ + OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME); + OSSL_STORE_LOADER_free(loader); +} + +#else /* !OPENSSL_NO_ENGINE */ + +int setup_engine_loader(void) +{ + return 0; +} + +void destroy_engine_loader(void) +{ +} + +#endif diff --git a/apps/lib/fmt.c b/apps/lib/fmt.c new file mode 100644 --- /dev/null +++ b/apps/lib/fmt.c @@ -0,0 +1,15 @@ +/* + * Copyright 2018-2020 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 + * https://www.openssl.org/source/license.html + */ + +#include "fmt.h" + +int FMT_istext(int format) +{ + return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; +} diff --git a/apps/lib/http_server.c b/apps/lib/http_server.c new file mode 100644 --- /dev/null +++ b/apps/lib/http_server.c @@ -0,0 +1,533 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +/* Very basic HTTP server */ + +#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +/* + * On VMS, you need to define this to get the declaration of fileno(). The + * value 2 is to make sure no function defined in POSIX-2 is left undefined. + */ +# define _POSIX_C_SOURCE 2 +#endif + +#include +#include +#include "http_server.h" +#include "internal/sockets.h" +#include +#include +#include "s_apps.h" + +#if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif +#endif + +static int verbosity = LOG_INFO; + +#define HTTP_PREFIX "HTTP/" +#define HTTP_VERSION_PATT "1." /* allow 1.x */ +#define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT +#define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */ + +#ifdef HTTP_DAEMON + +int multi = 0; /* run multiple responder processes */ +int acfd = (int) INVALID_SOCKET; + +static int print_syslog(const char *str, size_t len, void *levPtr) +{ + int level = *(int *)levPtr; + int ilen = len > MAXERRLEN ? MAXERRLEN : len; + + syslog(level, "%.*s", ilen, str); + + return ilen; +} +#endif + +void log_message(const char *prog, int level, const char *fmt, ...) +{ + va_list ap; + + if (verbosity < level) + return; + + va_start(ap, fmt); +#ifdef HTTP_DAEMON + if (multi) { + char buf[1024]; + + if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) + syslog(level, "%s", buf); + if (level <= LOG_ERR) + ERR_print_errors_cb(print_syslog, &level); + } else +#endif + { + BIO_printf(bio_err, "%s: ", prog); + BIO_vprintf(bio_err, fmt, ap); + BIO_printf(bio_err, "\n"); + (void)BIO_flush(bio_err); + } + va_end(ap); +} + +#ifdef HTTP_DAEMON +void socket_timeout(int signum) +{ + if (acfd != (int)INVALID_SOCKET) + (void)shutdown(acfd, SHUT_RD); +} + +static void killall(int ret, pid_t *kidpids) +{ + int i; + + for (i = 0; i < multi; ++i) + if (kidpids[i] != 0) + (void)kill(kidpids[i], SIGTERM); + OPENSSL_free(kidpids); + ossl_sleep(1000); + exit(ret); +} + +static int termsig = 0; + +static void noteterm(int sig) +{ + termsig = sig; +} + +/* + * Loop spawning up to `multi` child processes, only child processes return + * from this function. The parent process loops until receiving a termination + * signal, kills extant children and exits without returning. + */ +void spawn_loop(const char *prog) +{ + pid_t *kidpids = NULL; + int status; + int procs = 0; + int i; + + openlog(prog, LOG_PID, LOG_DAEMON); + + if (setpgid(0, 0)) { + syslog(LOG_ERR, "fatal: error detaching from parent process group: %s", + strerror(errno)); + exit(1); + } + kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array"); + for (i = 0; i < multi; ++i) + kidpids[i] = 0; + + signal(SIGINT, noteterm); + signal(SIGTERM, noteterm); + + while (termsig == 0) { + pid_t fpid; + + /* + * Wait for a child to replace when we're at the limit. + * Slow down if a child exited abnormally or waitpid() < 0 + */ + while (termsig == 0 && procs >= multi) { + if ((fpid = waitpid(-1, &status, 0)) > 0) { + for (i = 0; i < procs; ++i) { + if (kidpids[i] == fpid) { + kidpids[i] = 0; + --procs; + break; + } + } + if (i >= multi) { + syslog(LOG_ERR, "fatal: internal error: " + "no matching child slot for pid: %ld", + (long) fpid); + killall(1, kidpids); + } + if (status != 0) { + if (WIFEXITED(status)) + syslog(LOG_WARNING, "child process: %ld, exit status: %d", + (long)fpid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + syslog(LOG_WARNING, "child process: %ld, term signal %d%s", + (long)fpid, WTERMSIG(status), +# ifdef WCOREDUMP + WCOREDUMP(status) ? " (core dumped)" : +# endif + ""); + ossl_sleep(1000); + } + break; + } else if (errno != EINTR) { + syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno)); + killall(1, kidpids); + } + } + if (termsig) + break; + + switch (fpid = fork()) { + case -1: /* error */ + /* System critically low on memory, pause and try again later */ + ossl_sleep(30000); + break; + case 0: /* child */ + OPENSSL_free(kidpids); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + if (termsig) + _exit(0); + if (RAND_poll() <= 0) { + syslog(LOG_ERR, "fatal: RAND_poll() failed"); + _exit(1); + } + return; + default: /* parent */ + for (i = 0; i < multi; ++i) { + if (kidpids[i] == 0) { + kidpids[i] = fpid; + procs++; + break; + } + } + if (i >= multi) { + syslog(LOG_ERR, "fatal: internal error: no free child slots"); + killall(1, kidpids); + } + break; + } + } + + /* The loop above can only break on termsig */ + syslog(LOG_INFO, "terminating on signal: %d", termsig); + killall(0, kidpids); +} +#endif + +#ifndef OPENSSL_NO_SOCK +BIO *http_server_init_bio(const char *prog, const char *port) +{ + BIO *acbio = NULL, *bufbio; + int asock; + + bufbio = BIO_new(BIO_f_buffer()); + if (bufbio == NULL) + goto err; + acbio = BIO_new(BIO_s_accept()); + if (acbio == NULL + || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0 + || BIO_set_accept_port(acbio, port) < 0) { + log_message(prog, LOG_ERR, "Error setting up accept BIO"); + goto err; + } + + BIO_set_accept_bios(acbio, bufbio); + bufbio = NULL; + if (BIO_do_accept(acbio) <= 0) { + log_message(prog, LOG_ERR, "Error starting accept"); + goto err; + } + + /* Report back what address and port are used */ + BIO_get_fd(acbio, &asock); + if (!report_server_accept(bio_out, asock, 1, 1)) { + log_message(prog, LOG_ERR, "Error printing ACCEPT string"); + goto err; + } + + return acbio; + + err: + BIO_free_all(acbio); + BIO_free(bufbio); + return NULL; +} + +/* + * Decode %xx URL-decoding in-place. Ignores malformed sequences. + */ +static int urldecode(char *p) +{ + unsigned char *out = (unsigned char *)p; + unsigned char *save = out; + + for (; *p; p++) { + if (*p != '%') { + *out++ = *p; + } else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) { + /* Don't check, can't fail because of ixdigit() call. */ + *out++ = (OPENSSL_hexchar2int(p[1]) << 4) + | OPENSSL_hexchar2int(p[2]); + p += 2; + } else { + return -1; + } + } + *out = '\0'; + return (int)(out - save); +} + +/* if *pcbio != NULL, continue given connected session, else accept new */ +/* if found_keep_alive != NULL, return this way connection persistence state */ +int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, + char **ppath, BIO **pcbio, BIO *acbio, + int *found_keep_alive, + const char *prog, const char *port, + int accept_get, int timeout) +{ + BIO *cbio = *pcbio, *getbio = NULL, *b64 = NULL; + int len; + char reqbuf[2048], inbuf[2048]; + char *meth, *url, *end; + ASN1_VALUE *req; + int ret = 0; + + *preq = NULL; + if (ppath != NULL) + *ppath = NULL; + + if (cbio == NULL) { + log_message(prog, LOG_DEBUG, + "Awaiting new connection on port %s...", port); + if (BIO_do_accept(acbio) <= 0) + /* Connection loss before accept() is routine, ignore silently */ + return ret; + + *pcbio = cbio = BIO_pop(acbio); + } else { + log_message(prog, LOG_DEBUG, "Awaiting next request..."); + } + if (cbio == NULL) { + /* Cannot call http_server_send_status(cbio, ...) */ + ret = -1; + goto out; + } + +# ifdef HTTP_DAEMON + if (timeout > 0) { + (void)BIO_get_fd(cbio, &acfd); + alarm(timeout); + } +# endif + + /* Read the request line. */ + len = BIO_gets(cbio, reqbuf, sizeof(reqbuf)); + if (len == 0) + return ret; + ret = 1; + if (len < 0) { + log_message(prog, LOG_WARNING, "Request line read error"); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + if ((end = strchr(reqbuf, '\r')) != NULL + || (end = strchr(reqbuf, '\n')) != NULL) + *end = '\0'; + log_message(prog, LOG_INFO, "Received request, 1st line: %s", reqbuf); + + meth = reqbuf; + url = meth + 3; + if ((accept_get && strncmp(meth, "GET ", 4) == 0) + || (url++, strncmp(meth, "POST ", 5) == 0)) { + static const char http_version_str[] = " "HTTP_PREFIX_VERSION; + static const size_t http_version_str_len = sizeof(http_version_str) - 1; + + /* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */ + *(url++) = '\0'; + while (*url == ' ') + url++; + if (*url != '/') { + log_message(prog, LOG_WARNING, + "Invalid %s -- URL does not begin with '/': %s", + meth, url); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + url++; + + /* Splice off the HTTP version identifier. */ + for (end = url; *end != '\0'; end++) + if (*end == ' ') + break; + if (strncmp(end, http_version_str, http_version_str_len) != 0) { + log_message(prog, LOG_WARNING, + "Invalid %s -- bad HTTP/version string: %s", + meth, end + 1); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + *end = '\0'; + /* above HTTP 1.0, connection persistence is the default */ + if (found_keep_alive != NULL) + *found_keep_alive = end[http_version_str_len] > '0'; + + /*- + * Skip "GET / HTTP..." requests often used by load-balancers. + * 'url' was incremented above to point to the first byte *after* + * the leading slash, so in case 'GET / ' it is now an empty string. + */ + if (strlen(meth) == 3 && url[0] == '\0') { + (void)http_server_send_status(cbio, 200, "OK"); + goto out; + } + + len = urldecode(url); + if (len < 0) { + log_message(prog, LOG_WARNING, + "Invalid %s request -- bad URL encoding: %s", + meth, url); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + if (strlen(meth) == 3) { /* GET */ + if ((getbio = BIO_new_mem_buf(url, len)) == NULL + || (b64 = BIO_new(BIO_f_base64())) == NULL) { + log_message(prog, LOG_ERR, + "Could not allocate base64 bio with size = %d", + len); + goto fatal; + } + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + getbio = BIO_push(b64, getbio); + } + } else { + log_message(prog, LOG_WARNING, + "HTTP request does not begin with %sPOST: %s", + accept_get ? "GET or " : "", reqbuf); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + + /* chop any further/duplicate leading or trailing '/' */ + while (*url == '/') + url++; + while (end >= url + 2 && end[-2] == '/' && end[-1] == '/') + end--; + *end = '\0'; + + /* Read and skip past the headers. */ + for (;;) { + char *key, *value, *line_end = NULL; + + len = BIO_gets(cbio, inbuf, sizeof(inbuf)); + if (len <= 0) { + log_message(prog, LOG_WARNING, "Error reading HTTP header"); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + + if (inbuf[0] == '\r' || inbuf[0] == '\n') + break; + + key = inbuf; + value = strchr(key, ':'); + if (value == NULL) { + log_message(prog, LOG_WARNING, + "Error parsing HTTP header: missing ':'"); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + *(value++) = '\0'; + while (*value == ' ') + value++; + line_end = strchr(value, '\r'); + if (line_end == NULL) { + line_end = strchr(value, '\n'); + if (line_end == NULL) { + log_message(prog, LOG_WARNING, + "Error parsing HTTP header: missing end of line"); + (void)http_server_send_status(cbio, 400, "Bad Request"); + goto out; + } + } + *line_end = '\0'; + /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */ + if (found_keep_alive != NULL + && OPENSSL_strcasecmp(key, "Connection") == 0) { + if (OPENSSL_strcasecmp(value, "keep-alive") == 0) + *found_keep_alive = 1; + else if (OPENSSL_strcasecmp(value, "close") == 0) + *found_keep_alive = 0; + } + } + +# ifdef HTTP_DAEMON + /* Clear alarm before we close the client socket */ + alarm(0); + timeout = 0; +# endif + + /* Try to read and parse request */ + req = ASN1_item_d2i_bio(it, getbio != NULL ? getbio : cbio, NULL); + if (req == NULL) { + log_message(prog, LOG_WARNING, + "Error parsing DER-encoded request content"); + (void)http_server_send_status(cbio, 400, "Bad Request"); + } else if (ppath != NULL && (*ppath = OPENSSL_strdup(url)) == NULL) { + log_message(prog, LOG_ERR, + "Out of memory allocating %zu bytes", strlen(url) + 1); + ASN1_item_free(req, it); + goto fatal; + } + + *preq = req; + + out: + BIO_free_all(getbio); +# ifdef HTTP_DAEMON + if (timeout > 0) + alarm(0); + acfd = (int)INVALID_SOCKET; +# endif + return ret; + + fatal: + (void)http_server_send_status(cbio, 500, "Internal Server Error"); + if (ppath != NULL) { + OPENSSL_free(*ppath); + *ppath = NULL; + } + BIO_free_all(cbio); + *pcbio = NULL; + ret = -1; + goto out; +} + +/* assumes that cbio does not do an encoding that changes the output length */ +int http_server_send_asn1_resp(BIO *cbio, int keep_alive, + const char *content_type, + const ASN1_ITEM *it, const ASN1_VALUE *resp) +{ + int ret = BIO_printf(cbio, HTTP_1_0" 200 OK\r\n%s" + "Content-type: %s\r\n" + "Content-Length: %d\r\n\r\n", + keep_alive ? "Connection: keep-alive\r\n" : "", + content_type, + ASN1_item_i2d(resp, NULL, it)) > 0 + && ASN1_item_i2d_bio(it, cbio, resp) > 0; + + (void)BIO_flush(cbio); + return ret; +} + +int http_server_send_status(BIO *cbio, int status, const char *reason) +{ + int ret = BIO_printf(cbio, HTTP_1_0" %d %s\r\n\r\n", + /* This implicitly cancels keep-alive */ + status, reason) > 0; + + (void)BIO_flush(cbio); + return ret; +} +#endif diff --git a/apps/lib/names.c b/apps/lib/names.c new file mode 100644 --- /dev/null +++ b/apps/lib/names.c @@ -0,0 +1,45 @@ +/* + * Copyright 2019-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "names.h" +#include "openssl/crypto.h" + +int name_cmp(const char * const *a, const char * const *b) +{ + return OPENSSL_strcasecmp(*a, *b); +} + +void collect_names(const char *name, void *vdata) +{ + STACK_OF(OPENSSL_CSTRING) *names = vdata; + + sk_OPENSSL_CSTRING_push(names, name); +} + +void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names) +{ + int i = sk_OPENSSL_CSTRING_num(names); + int j; + + sk_OPENSSL_CSTRING_sort(names); + if (i > 1) + BIO_printf(out, "{ "); + for (j = 0; j < i; j++) { + const char *name = sk_OPENSSL_CSTRING_value(names, j); + + if (j > 0) + BIO_printf(out, ", "); + BIO_printf(out, "%s", name); + } + if (i > 1) + BIO_printf(out, " }"); +} diff --git a/apps/lib/opt.c b/apps/lib/opt.c new file mode 100644 --- /dev/null +++ b/apps/lib/opt.c @@ -0,0 +1,1198 @@ +/* + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file is also used by the test suite. Do not #include "apps.h". + */ +#include "opt.h" +#include "fmt.h" +#include "app_libctx.h" +#include "internal/nelem.h" +#include "internal/numbers.h" +#include +#if !defined(OPENSSL_SYS_MSDOS) +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_OPT_HELP_WIDTH 30 +const char OPT_HELP_STR[] = "-H"; +const char OPT_MORE_STR[] = "-M"; +const char OPT_SECTION_STR[] = "-S"; +const char OPT_PARAM_STR[] = "-P"; + +/* Our state */ +static char **argv; +static int argc; +static int opt_index; +static char *arg; +static char *flag; +static char *dunno; +static const OPTIONS *unknown; +static const OPTIONS *opts; +static char prog[40]; + +/* + * Return the simple name of the program; removing various platform gunk. + */ +#if defined(OPENSSL_SYS_WIN32) + +const char *opt_path_end(const char *filename) +{ + const char *p; + + /* find the last '/', '\' or ':' */ + for (p = filename + strlen(filename); --p > filename; ) + if (*p == '/' || *p == '\\' || *p == ':') { + p++; + break; + } + return p; +} + +char *opt_progname(const char *argv0) +{ + size_t i, n; + const char *p; + char *q; + + p = opt_path_end(argv0); + + /* Strip off trailing nonsense. */ + n = strlen(p); + if (n > 4 && + (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0)) + n -= 4; + + /* Copy over the name, in lowercase. */ + if (n > sizeof(prog) - 1) + n = sizeof(prog) - 1; + for (q = prog, i = 0; i < n; i++, p++) + *q++ = tolower((unsigned char)*p); + *q = '\0'; + return prog; +} + +#elif defined(OPENSSL_SYS_VMS) + +const char *opt_path_end(const char *filename) +{ + const char *p; + + /* Find last special character sys:[foo.bar]openssl */ + for (p = filename + strlen(filename); --p > filename;) + if (*p == ':' || *p == ']' || *p == '>') { + p++; + break; + } + return p; +} + +char *opt_progname(const char *argv0) +{ + const char *p, *q; + + /* Find last special character sys:[foo.bar]openssl */ + p = opt_path_end(argv0); + q = strrchr(p, '.'); + if (prog != p) + strncpy(prog, p, sizeof(prog) - 1); + prog[sizeof(prog) - 1] = '\0'; + if (q != NULL && q - p < sizeof(prog)) + prog[q - p] = '\0'; + return prog; +} + +#else + +const char *opt_path_end(const char *filename) +{ + const char *p; + + /* Could use strchr, but this is like the ones above. */ + for (p = filename + strlen(filename); --p > filename;) + if (*p == '/') { + p++; + break; + } + return p; +} + +char *opt_progname(const char *argv0) +{ + const char *p; + + p = opt_path_end(argv0); + if (prog != p) + strncpy(prog, p, sizeof(prog) - 1); + prog[sizeof(prog) - 1] = '\0'; + return prog; +} +#endif + +char *opt_appname(const char *argv0) +{ + size_t len = strlen(prog); + + if (argv0 != NULL) + BIO_snprintf(prog + len, sizeof(prog) - len - 1, " %s", argv0); + return prog; +} + +char *opt_getprog(void) +{ + return prog; +} + +/* Set up the arg parsing. */ +char *opt_init(int ac, char **av, const OPTIONS *o) +{ + /* Store state. */ + argc = ac; + argv = av; + opt_begin(); + opts = o; + unknown = NULL; + + /* Make sure prog name is set for usage output */ + (void)opt_progname(argv[0]); + + /* Check all options up until the PARAM marker (if present) */ + for (; o->name != NULL && o->name != OPT_PARAM_STR; ++o) { +#ifndef NDEBUG + const OPTIONS *next; + int duplicated, i; +#endif + + if (o->name == OPT_HELP_STR + || o->name == OPT_MORE_STR + || o->name == OPT_SECTION_STR) + continue; +#ifndef NDEBUG + i = o->valtype; + + /* Make sure options are legit. */ + OPENSSL_assert(o->name[0] != '-'); + if (o->valtype == '.') + OPENSSL_assert(o->retval == OPT_PARAM); + else + OPENSSL_assert(o->retval == OPT_DUP || o->retval > OPT_PARAM); + switch (i) { + case 0: case '-': case '.': + case '/': case '<': case '>': case 'E': case 'F': + case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': + case 'u': case 'c': case ':': case 'N': + break; + default: + OPENSSL_assert(0); + } + + /* Make sure there are no duplicates. */ + for (next = o + 1; next->name; ++next) { + /* + * Some compilers inline strcmp and the assert string is too long. + */ + duplicated = next->retval != OPT_DUP + && strcmp(o->name, next->name) == 0; + if (duplicated) { + opt_printf_stderr("%s: Internal error: duplicate option %s\n", + prog, o->name); + OPENSSL_assert(!duplicated); + } + } +#endif + if (o->name[0] == '\0') { + OPENSSL_assert(unknown == NULL); + unknown = o; + OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-'); + } + } + return prog; +} + +static OPT_PAIR formats[] = { + {"PEM/DER", OPT_FMT_PEMDER}, + {"pkcs12", OPT_FMT_PKCS12}, + {"smime", OPT_FMT_SMIME}, + {"engine", OPT_FMT_ENGINE}, + {"msblob", OPT_FMT_MSBLOB}, + {"nss", OPT_FMT_NSS}, + {"text", OPT_FMT_TEXT}, + {"http", OPT_FMT_HTTP}, + {"pvk", OPT_FMT_PVK}, + {NULL} +}; + +/* Print an error message about a failed format parse. */ +static int opt_format_error(const char *s, unsigned long flags) +{ + OPT_PAIR *ap; + + if (flags == OPT_FMT_PEMDER) { + opt_printf_stderr("%s: Bad format \"%s\"; must be pem or der\n", + prog, s); + } else { + opt_printf_stderr("%s: Bad format \"%s\"; must be one of:\n", + prog, s); + for (ap = formats; ap->name; ap++) + if (flags & ap->retval) + opt_printf_stderr(" %s\n", ap->name); + } + return 0; +} + +/* Parse a format string, put it into *result; return 0 on failure, else 1. */ +int opt_format(const char *s, unsigned long flags, int *result) +{ + switch (*s) { + default: + opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s); + return 0; + case 'D': + case 'd': + if ((flags & OPT_FMT_PEMDER) == 0) + return opt_format_error(s, flags); + *result = FORMAT_ASN1; + break; + case 'T': + case 't': + if ((flags & OPT_FMT_TEXT) == 0) + return opt_format_error(s, flags); + *result = FORMAT_TEXT; + break; + case 'N': + case 'n': + if ((flags & OPT_FMT_NSS) == 0) + return opt_format_error(s, flags); + if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0) + return opt_format_error(s, flags); + *result = FORMAT_NSS; + break; + case 'S': + case 's': + if ((flags & OPT_FMT_SMIME) == 0) + return opt_format_error(s, flags); + *result = FORMAT_SMIME; + break; + case 'M': + case 'm': + if ((flags & OPT_FMT_MSBLOB) == 0) + return opt_format_error(s, flags); + *result = FORMAT_MSBLOB; + break; + case 'E': + case 'e': + if ((flags & OPT_FMT_ENGINE) == 0) + return opt_format_error(s, flags); + *result = FORMAT_ENGINE; + break; + case 'H': + case 'h': + if ((flags & OPT_FMT_HTTP) == 0) + return opt_format_error(s, flags); + *result = FORMAT_HTTP; + break; + case '1': + if ((flags & OPT_FMT_PKCS12) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PKCS12; + break; + case 'P': + case 'p': + if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { + if ((flags & OPT_FMT_PEMDER) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PEM; + } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { + if ((flags & OPT_FMT_PVK) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PVK; + } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0 + || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) { + if ((flags & OPT_FMT_PKCS12) == 0) + return opt_format_error(s, flags); + *result = FORMAT_PKCS12; + } else { + opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s); + return 0; + } + break; + } + return 1; +} + +/* Return string representing the given format. */ +static const char *format2str(int format) +{ + switch (format) { + default: + return "(undefined)"; + case FORMAT_PEM: + return "PEM"; + case FORMAT_ASN1: + return "DER"; + case FORMAT_TEXT: + return "TEXT"; + case FORMAT_NSS: + return "NSS"; + case FORMAT_SMIME: + return "SMIME"; + case FORMAT_MSBLOB: + return "MSBLOB"; + case FORMAT_ENGINE: + return "ENGINE"; + case FORMAT_HTTP: + return "HTTP"; + case FORMAT_PKCS12: + return "P12"; + case FORMAT_PVK: + return "PVK"; + } +} + +/* Print an error message about unsuitable/unsupported format requested. */ +void print_format_error(int format, unsigned long flags) +{ + (void)opt_format_error(format2str(format), flags); +} + +/* + * Parse a cipher name, put it in *cipherp after freeing what was there, if + * cipherp is not NULL. Return 0 on failure, else 1. + */ +int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp) +{ + EVP_CIPHER *c; + + ERR_set_mark(); + if ((c = EVP_CIPHER_fetch(app_get0_libctx(), name, + app_get0_propq())) != NULL + || (opt_legacy_okay() + && (c = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL)) { + ERR_pop_to_mark(); + if (cipherp != NULL) { + EVP_CIPHER_free(*cipherp); + *cipherp = c; + } else { + EVP_CIPHER_free(c); + } + return 1; + } + ERR_clear_last_mark(); + return 0; +} + +int opt_cipher_any(const char *name, EVP_CIPHER **cipherp) +{ + int ret; + + if ((ret = opt_cipher_silent(name, cipherp)) == 0) + opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); + return ret; +} + +int opt_cipher(const char *name, EVP_CIPHER **cipherp) +{ + int mode, ret = 0; + unsigned long int flags; + EVP_CIPHER *c = NULL; + + if (opt_cipher_any(name, &c)) { + mode = EVP_CIPHER_get_mode(c); + flags = EVP_CIPHER_get_flags(c); + if (mode == EVP_CIPH_XTS_MODE) { + opt_printf_stderr("%s XTS ciphers not supported\n", prog); + } else if ((flags & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { + opt_printf_stderr("%s: AEAD ciphers not supported\n", prog); + } else { + ret = 1; + if (cipherp != NULL) + *cipherp = c; + } + } + return ret; +} + +/* + * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. + */ +int opt_md_silent(const char *name, EVP_MD **mdp) +{ + EVP_MD *md; + + ERR_set_mark(); + if ((md = EVP_MD_fetch(app_get0_libctx(), name, app_get0_propq())) != NULL + || (opt_legacy_okay() + && (md = (EVP_MD *)EVP_get_digestbyname(name)) != NULL)) { + ERR_pop_to_mark(); + if (mdp != NULL) { + EVP_MD_free(*mdp); + *mdp = md; + } else { + EVP_MD_free(md); + } + return 1; + } + ERR_clear_last_mark(); + return 0; +} + +int opt_md(const char *name, EVP_MD **mdp) +{ + int ret; + + if ((ret = opt_md_silent(name, mdp)) == 0) + opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog, + name != NULL ? name : "\"\""); + return ret; +} + +/* Look through a list of name/value pairs. */ +int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) +{ + const OPT_PAIR *pp; + + for (pp = pairs; pp->name; pp++) + if (strcmp(pp->name, name) == 0) { + *result = pp->retval; + return 1; + } + opt_printf_stderr("%s: Value must be one of:\n", prog); + for (pp = pairs; pp->name; pp++) + opt_printf_stderr("\t%s\n", pp->name); + return 0; +} + +/* Look through a list of valid names */ +int opt_string(const char *name, const char **options) +{ + const char **p; + + for (p = options; *p != NULL; p++) + if (strcmp(*p, name) == 0) + return 1; + opt_printf_stderr("%s: Value must be one of:\n", prog); + for (p = options; *p != NULL; p++) + opt_printf_stderr("\t%s\n", *p); + return 0; +} + +/* Parse an int, put it into *result; return 0 on failure, else 1. */ +int opt_int(const char *value, int *result) +{ + long l; + + if (!opt_long(value, &l)) + return 0; + *result = (int)l; + if (*result != l) { + opt_printf_stderr("%s: Value \"%s\" outside integer range\n", + prog, value); + return 0; + } + return 1; +} + +/* Parse and return an integer, assuming range has been checked before. */ +int opt_int_arg(void) +{ + int result = -1; + + (void)opt_int(arg, &result); + return result; +} + +static void opt_number_error(const char *v) +{ + size_t i = 0; + struct strstr_pair_st { + char *prefix; + char *name; + } b[] = { + {"0x", "a hexadecimal"}, + {"0X", "a hexadecimal"}, + {"0", "an octal"} + }; + + for (i = 0; i < OSSL_NELEM(b); i++) { + if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { + opt_printf_stderr("%s: Can't parse \"%s\" as %s number\n", + prog, v, b[i].name); + return; + } + } + opt_printf_stderr("%s: Can't parse \"%s\" as a number\n", prog, v); + return; +} + +/* Parse a long, put it into *result; return 0 on failure, else 1. */ +int opt_long(const char *value, long *result) +{ + int oerrno = errno; + long l; + char *endp; + + errno = 0; + l = strtol(value, &endp, 0); + if (*endp + || endp == value + || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) + || (l == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = l; + errno = oerrno; + return 1; +} + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) && \ + !defined(OPENSSL_NO_INTTYPES_H) + +/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ +int opt_intmax(const char *value, ossl_intmax_t *result) +{ + int oerrno = errno; + intmax_t m; + char *endp; + + errno = 0; + m = strtoimax(value, &endp, 0); + if (*endp + || endp == value + || ((m == INTMAX_MAX || m == INTMAX_MIN) + && errno == ERANGE) + || (m == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + /* Ensure that the value in |m| is never too big for |*result| */ + if (sizeof(m) > sizeof(*result) + && (m < OSSL_INTMAX_MIN || m > OSSL_INTMAX_MAX)) { + opt_number_error(value); + return 0; + } + *result = (ossl_intmax_t)m; + errno = oerrno; + return 1; +} + +/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ +int opt_uintmax(const char *value, ossl_uintmax_t *result) +{ + int oerrno = errno; + uintmax_t m; + char *endp; + + errno = 0; + m = strtoumax(value, &endp, 0); + if (*endp + || endp == value + || (m == UINTMAX_MAX && errno == ERANGE) + || (m == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + /* Ensure that the value in |m| is never too big for |*result| */ + if (sizeof(m) > sizeof(*result) + && m > OSSL_UINTMAX_MAX) { + opt_number_error(value); + return 0; + } + *result = (ossl_intmax_t)m; + errno = oerrno; + return 1; +} +#else +/* Fallback implementations based on long */ +int opt_intmax(const char *value, ossl_intmax_t *result) +{ + long m; + int ret; + + if ((ret = opt_long(value, &m))) + *result = m; + return ret; +} + +int opt_uintmax(const char *value, ossl_uintmax_t *result) +{ + unsigned long m; + int ret; + + if ((ret = opt_ulong(value, &m))) + *result = m; + return ret; +} +#endif + +/* + * Parse an unsigned long, put it into *result; return 0 on failure, else 1. + */ +int opt_ulong(const char *value, unsigned long *result) +{ + int oerrno = errno; + char *endptr; + unsigned long l; + + errno = 0; + l = strtoul(value, &endptr, 0); + if (*endptr + || endptr == value + || ((l == ULONG_MAX) && errno == ERANGE) + || (l == 0 && errno != 0)) { + opt_number_error(value); + errno = oerrno; + return 0; + } + *result = l; + errno = oerrno; + return 1; +} + +/* + * We pass opt as an int but cast it to "enum range" so that all the + * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch + * in gcc do the right thing. + */ +enum range { OPT_V_ENUM }; + +int opt_verify(int opt, X509_VERIFY_PARAM *vpm) +{ + int i; + ossl_intmax_t t = 0; + ASN1_OBJECT *otmp; + X509_PURPOSE *xptmp; + const X509_VERIFY_PARAM *vtmp; + + OPENSSL_assert(vpm != NULL); + OPENSSL_assert(opt > OPT_V__FIRST); + OPENSSL_assert(opt < OPT_V__LAST); + + switch ((enum range)opt) { + case OPT_V__FIRST: + case OPT_V__LAST: + return 0; + case OPT_V_POLICY: + otmp = OBJ_txt2obj(opt_arg(), 0); + if (otmp == NULL) { + opt_printf_stderr("%s: Invalid Policy %s\n", prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_add0_policy(vpm, otmp); + break; + case OPT_V_PURPOSE: + /* purpose name -> purpose index */ + i = X509_PURPOSE_get_by_sname(opt_arg()); + if (i < 0) { + opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg()); + return 0; + } + + /* purpose index -> purpose object */ + xptmp = X509_PURPOSE_get0(i); + + /* purpose object -> purpose value */ + i = X509_PURPOSE_get_id(xptmp); + + if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { + opt_printf_stderr("%s: Internal error setting purpose %s\n", + prog, opt_arg()); + return 0; + } + break; + case OPT_V_VERIFY_NAME: + vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); + if (vtmp == NULL) { + opt_printf_stderr("%s: Invalid verify name %s\n", + prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_set1(vpm, vtmp); + break; + case OPT_V_VERIFY_DEPTH: + i = atoi(opt_arg()); + if (i >= 0) + X509_VERIFY_PARAM_set_depth(vpm, i); + break; + case OPT_V_VERIFY_AUTH_LEVEL: + i = atoi(opt_arg()); + if (i >= 0) + X509_VERIFY_PARAM_set_auth_level(vpm, i); + break; + case OPT_V_ATTIME: + if (!opt_intmax(opt_arg(), &t)) + return 0; + if (t != (time_t)t) { + opt_printf_stderr("%s: epoch time out of range %s\n", + prog, opt_arg()); + return 0; + } + X509_VERIFY_PARAM_set_time(vpm, (time_t)t); + break; + case OPT_V_VERIFY_HOSTNAME: + if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) + return 0; + break; + case OPT_V_VERIFY_EMAIL: + if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) + return 0; + break; + case OPT_V_VERIFY_IP: + if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) + return 0; + break; + case OPT_V_IGNORE_CRITICAL: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); + break; + case OPT_V_ISSUER_CHECKS: + /* NOP, deprecated */ + break; + case OPT_V_CRL_CHECK: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); + break; + case OPT_V_CRL_CHECK_ALL: + X509_VERIFY_PARAM_set_flags(vpm, + X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL); + break; + case OPT_V_POLICY_CHECK: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); + break; + case OPT_V_EXPLICIT_POLICY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); + break; + case OPT_V_INHIBIT_ANY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); + break; + case OPT_V_INHIBIT_MAP: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); + break; + case OPT_V_X509_STRICT: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); + break; + case OPT_V_EXTENDED_CRL: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); + break; + case OPT_V_USE_DELTAS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); + break; + case OPT_V_POLICY_PRINT: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); + break; + case OPT_V_CHECK_SS_SIG: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); + break; + case OPT_V_TRUSTED_FIRST: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); + break; + case OPT_V_SUITEB_128_ONLY: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); + break; + case OPT_V_SUITEB_128: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); + break; + case OPT_V_SUITEB_192: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); + break; + case OPT_V_PARTIAL_CHAIN: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); + break; + case OPT_V_NO_ALT_CHAINS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); + break; + case OPT_V_NO_CHECK_TIME: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); + break; + case OPT_V_ALLOW_PROXY_CERTS: + X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); + break; + } + return 1; + +} + +void opt_begin(void) +{ + opt_index = 1; + arg = NULL; + flag = NULL; +} + +/* + * Parse the next flag (and value if specified), return 0 if done, -1 on + * error, otherwise the flag's retval. + */ +int opt_next(void) +{ + char *p; + const OPTIONS *o; + int ival; + long lval; + unsigned long ulval; + ossl_intmax_t imval; + ossl_uintmax_t umval; + + /* Look at current arg; at end of the list? */ + arg = NULL; + p = argv[opt_index]; + if (p == NULL) + return 0; + + /* If word doesn't start with a -, we're done. */ + if (*p != '-') + return 0; + + /* Hit "--" ? We're done. */ + opt_index++; + if (strcmp(p, "--") == 0) + return 0; + + /* Allow -nnn and --nnn */ + if (*++p == '-') + p++; + flag = p - 1; + + /* If we have --flag=foo, snip it off */ + if ((arg = strchr(p, '=')) != NULL) + *arg++ = '\0'; + for (o = opts; o->name; ++o) { + /* If not this option, move on to the next one. */ + if (!(strcmp(p, "h") == 0 && strcmp(o->name, "help") == 0) + && strcmp(p, o->name) != 0) + continue; + + /* If it doesn't take a value, make sure none was given. */ + if (o->valtype == 0 || o->valtype == '-') { + if (arg) { + opt_printf_stderr("%s: Option -%s does not take a value\n", + prog, p); + return -1; + } + return o->retval; + } + + /* Want a value; get the next param if =foo not used. */ + if (arg == NULL) { + if (argv[opt_index] == NULL) { + opt_printf_stderr("%s: Option -%s needs a value\n", + prog, o->name); + return -1; + } + arg = argv[opt_index++]; + } + + /* Syntax-check value. */ + switch (o->valtype) { + default: + case 's': + case ':': + /* Just a string. */ + break; + case '.': + /* Parameters */ + break; + case '/': + if (opt_isdir(arg) > 0) + break; + opt_printf_stderr("%s: Not a directory: %s\n", prog, arg); + return -1; + case '<': + /* Input file. */ + break; + case '>': + /* Output file. */ + break; + case 'p': + case 'n': + case 'N': + if (!opt_int(arg, &ival)) + return -1; + if (o->valtype == 'p' && ival <= 0) { + opt_printf_stderr("%s: Non-positive number \"%s\" for option -%s\n", + prog, arg, o->name); + return -1; + } + if (o->valtype == 'N' && ival < 0) { + opt_printf_stderr("%s: Negative number \"%s\" for option -%s\n", + prog, arg, o->name); + return -1; + } + break; + case 'M': + if (!opt_intmax(arg, &imval)) + return -1; + break; + case 'U': + if (!opt_uintmax(arg, &umval)) + return -1; + break; + case 'l': + if (!opt_long(arg, &lval)) + return -1; + break; + case 'u': + if (!opt_ulong(arg, &ulval)) + return -1; + break; + case 'c': + case 'E': + case 'F': + case 'f': + if (opt_format(arg, + o->valtype == 'c' ? OPT_FMT_PDS : + o->valtype == 'E' ? OPT_FMT_PDE : + o->valtype == 'F' ? OPT_FMT_PEMDER + : OPT_FMT_ANY, &ival)) + break; + opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n", + prog, arg, o->name); + return -1; + } + + /* Return the flag value. */ + return o->retval; + } + if (unknown != NULL) { + dunno = p; + return unknown->retval; + } + opt_printf_stderr("%s: Unknown option: -%s\n", prog, p); + return -1; +} + +/* Return the most recent flag parameter. */ +char *opt_arg(void) +{ + return arg; +} + +/* Return the most recent flag (option name including the preceding '-'). */ +char *opt_flag(void) +{ + return flag; +} + +/* Return the unknown option. */ +char *opt_unknown(void) +{ + return dunno; +} + +/* Return the rest of the arguments after parsing flags. */ +char **opt_rest(void) +{ + return &argv[opt_index]; +} + +/* How many items in remaining args? */ +int opt_num_rest(void) +{ + int i = 0; + char **pp; + + for (pp = opt_rest(); *pp; pp++, i++) + continue; + return i; +} + +/* Return a string describing the parameter type. */ +static const char *valtype2param(const OPTIONS *o) +{ + switch (o->valtype) { + case 0: + case '-': + return ""; + case ':': + return "uri"; + case 's': + return "val"; + case '/': + return "dir"; + case '<': + return "infile"; + case '>': + return "outfile"; + case 'p': + return "+int"; + case 'n': + return "int"; + case 'l': + return "long"; + case 'u': + return "ulong"; + case 'E': + return "PEM|DER|ENGINE"; + case 'F': + return "PEM|DER"; + case 'f': + return "format"; + case 'M': + return "intmax"; + case 'N': + return "nonneg"; + case 'U': + return "uintmax"; + } + return "parm"; +} + +static void opt_print(const OPTIONS *o, int doingparams, int width) +{ + const char* help; + char start[80 + 1]; + char *p; + + help = o->helpstr ? o->helpstr : "(No additional info)"; + if (o->name == OPT_HELP_STR) { + opt_printf_stderr(help, prog); + return; + } + if (o->name == OPT_SECTION_STR) { + opt_printf_stderr("\n"); + opt_printf_stderr(help, prog); + return; + } + if (o->name == OPT_PARAM_STR) { + opt_printf_stderr("\nParameters:\n"); + return; + } + + /* Pad out prefix */ + memset(start, ' ', sizeof(start) - 1); + start[sizeof(start) - 1] = '\0'; + + if (o->name == OPT_MORE_STR) { + /* Continuation of previous line; pad and print. */ + start[width] = '\0'; + opt_printf_stderr("%s %s\n", start, help); + return; + } + + /* Build up the "-flag [param]" part. */ + p = start; + *p++ = ' '; + if (!doingparams) + *p++ = '-'; + if (o->name[0]) + p += strlen(strcpy(p, o->name)); + else + *p++ = '*'; + if (o->valtype != '-') { + *p++ = ' '; + p += strlen(strcpy(p, valtype2param(o))); + } + *p = ' '; + if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { + *p = '\0'; + opt_printf_stderr("%s\n", start); + memset(start, ' ', sizeof(start)); + } + start[width] = '\0'; + opt_printf_stderr("%s %s\n", start, help); +} + +void opt_help(const OPTIONS *list) +{ + const OPTIONS *o; + int i, sawparams = 0, width = 5; + int standard_prolog; + char start[80 + 1]; + + /* Starts with its own help message? */ + standard_prolog = list[0].name != OPT_HELP_STR; + + /* Find the widest help. */ + for (o = list; o->name; o++) { + if (o->name == OPT_MORE_STR) + continue; + i = 2 + (int)strlen(o->name); + if (o->valtype != '-') + i += 1 + strlen(valtype2param(o)); + if (i < MAX_OPT_HELP_WIDTH && i > width) + width = i; + OPENSSL_assert(i < (int)sizeof(start)); + } + + if (standard_prolog) { + opt_printf_stderr("Usage: %s [options]\n", prog); + if (list[0].name != OPT_SECTION_STR) + opt_printf_stderr("Valid options are:\n", prog); + } + + /* Now let's print. */ + for (o = list; o->name; o++) { + if (o->name == OPT_PARAM_STR) + sawparams = 1; + opt_print(o, sawparams, width); + } +} + +/* opt_isdir section */ +#ifdef _WIN32 +# include +int opt_isdir(const char *name) +{ + DWORD attr; +# if defined(UNICODE) || defined(_UNICODE) + size_t i, len_0 = strlen(name) + 1; + WCHAR tempname[MAX_PATH]; + + if (len_0 > MAX_PATH) + return -1; + +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) +# endif + for (i = 0; i < len_0; i++) + tempname[i] = (WCHAR)name[i]; + + attr = GetFileAttributes(tempname); +# else + attr = GetFileAttributes(name); +# endif + if (attr == INVALID_FILE_ATTRIBUTES) + return -1; + return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); +} +#else +# include +# ifndef S_ISDIR +# if defined(_S_IFMT) && defined(_S_IFDIR) +# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) +# else +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +# endif +# endif + +int opt_isdir(const char *name) +{ +# if defined(S_ISDIR) + struct stat st; + + if (stat(name, &st) == 0) + return S_ISDIR(st.st_mode); + else + return -1; +# else + return -1; +# endif +} +#endif diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c new file mode 100644 --- /dev/null +++ b/apps/lib/s_cb.c @@ -0,0 +1,1569 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +/* callback functions used by s_client, s_server, and s_time */ +#include +#include +#include /* for memcpy() and strcmp() */ +#include "apps.h" +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_DH +# include +#endif +#include "s_apps.h" + +#define COOKIE_SECRET_LENGTH 16 + +VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 }; + +#ifndef OPENSSL_NO_SOCK +static unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; +static int cookie_initialized = 0; +#endif +static BIO *bio_keylog = NULL; + +static const char *lookup(int val, const STRINT_PAIR* list, const char* def) +{ + for ( ; list->name; ++list) + if (list->retval == val) + return list->name; + return def; +} + +int verify_callback(int ok, X509_STORE_CTX *ctx) +{ + X509 *err_cert; + int err, depth; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + if (!verify_args.quiet || !ok) { + BIO_printf(bio_err, "depth=%d ", depth); + if (err_cert != NULL) { + X509_NAME_print_ex(bio_err, + X509_get_subject_name(err_cert), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); + } else { + BIO_puts(bio_err, "\n"); + } + } + if (!ok) { + BIO_printf(bio_err, "verify error:num=%d:%s\n", err, + X509_verify_cert_error_string(err)); + if (verify_args.depth < 0 || verify_args.depth >= depth) { + if (!verify_args.return_error) + ok = 1; + verify_args.error = err; + } else { + ok = 0; + verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG; + } + } + switch (err) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + if (err_cert != NULL) { + BIO_puts(bio_err, "issuer= "); + X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); + } + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + if (err_cert != NULL) { + BIO_printf(bio_err, "notBefore="); + ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert)); + BIO_printf(bio_err, "\n"); + } + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + if (err_cert != NULL) { + BIO_printf(bio_err, "notAfter="); + ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert)); + BIO_printf(bio_err, "\n"); + } + break; + case X509_V_ERR_NO_EXPLICIT_POLICY: + if (!verify_args.quiet) + policies_print(ctx); + break; + } + if (err == X509_V_OK && ok == 2 && !verify_args.quiet) + policies_print(ctx); + if (ok && !verify_args.quiet) + BIO_printf(bio_err, "verify return:%d\n", ok); + return ok; +} + +int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) +{ + if (cert_file != NULL) { + if (SSL_CTX_use_certificate_file(ctx, cert_file, + SSL_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, "unable to get certificate from '%s'\n", + cert_file); + ERR_print_errors(bio_err); + return 0; + } + if (key_file == NULL) + key_file = cert_file; + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, "unable to get private key from '%s'\n", + key_file); + ERR_print_errors(bio_err); + return 0; + } + + /* + * If we are using DSA, we can copy the parameters from the private + * key + */ + + /* + * Now we know that a key and cert have been set against the SSL + * context + */ + if (!SSL_CTX_check_private_key(ctx)) { + BIO_printf(bio_err, + "Private key does not match the certificate public key\n"); + return 0; + } + } + return 1; +} + +int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, + STACK_OF(X509) *chain, int build_chain) +{ + int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0; + + if (cert == NULL) + return 1; + if (SSL_CTX_use_certificate(ctx, cert) <= 0) { + BIO_printf(bio_err, "error setting certificate\n"); + ERR_print_errors(bio_err); + return 0; + } + + if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) { + BIO_printf(bio_err, "error setting private key\n"); + ERR_print_errors(bio_err); + return 0; + } + + /* + * Now we know that a key and cert have been set against the SSL context + */ + if (!SSL_CTX_check_private_key(ctx)) { + BIO_printf(bio_err, + "Private key does not match the certificate public key\n"); + return 0; + } + if (chain && !SSL_CTX_set1_chain(ctx, chain)) { + BIO_printf(bio_err, "error setting certificate chain\n"); + ERR_print_errors(bio_err); + return 0; + } + if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) { + BIO_printf(bio_err, "error building certificate chain\n"); + ERR_print_errors(bio_err); + return 0; + } + return 1; +} + +static STRINT_PAIR cert_type_list[] = { + {"RSA sign", TLS_CT_RSA_SIGN}, + {"DSA sign", TLS_CT_DSS_SIGN}, + {"RSA fixed DH", TLS_CT_RSA_FIXED_DH}, + {"DSS fixed DH", TLS_CT_DSS_FIXED_DH}, + {"ECDSA sign", TLS_CT_ECDSA_SIGN}, + {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH}, + {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH}, + {"GOST01 Sign", TLS_CT_GOST01_SIGN}, + {"GOST12 Sign", TLS_CT_GOST12_IANA_SIGN}, + {NULL} +}; + +static void ssl_print_client_cert_types(BIO *bio, SSL *s) +{ + const unsigned char *p; + int i; + int cert_type_num = SSL_get0_certificate_types(s, &p); + + if (!cert_type_num) + return; + BIO_puts(bio, "Client Certificate Types: "); + for (i = 0; i < cert_type_num; i++) { + unsigned char cert_type = p[i]; + const char *cname = lookup((int)cert_type, cert_type_list, NULL); + + if (i) + BIO_puts(bio, ", "); + if (cname != NULL) + BIO_puts(bio, cname); + else + BIO_printf(bio, "UNKNOWN (%d),", cert_type); + } + BIO_puts(bio, "\n"); +} + +static const char *get_sigtype(int nid) +{ + switch (nid) { + case EVP_PKEY_RSA: + return "RSA"; + + case EVP_PKEY_RSA_PSS: + return "RSA-PSS"; + + case EVP_PKEY_DSA: + return "DSA"; + + case EVP_PKEY_EC: + return "ECDSA"; + + case NID_ED25519: + return "Ed25519"; + + case NID_ED448: + return "Ed448"; + + case NID_id_GostR3410_2001: + return "gost2001"; + + case NID_id_GostR3410_2012_256: + return "gost2012_256"; + + case NID_id_GostR3410_2012_512: + return "gost2012_512"; + + default: + return NULL; + } +} + +static int do_print_sigalgs(BIO *out, SSL *s, int shared) +{ + int i, nsig, client; + + client = SSL_is_server(s) ? 0 : 1; + if (shared) + nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL); + else + nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL); + if (nsig == 0) + return 1; + + if (shared) + BIO_puts(out, "Shared "); + + if (client) + BIO_puts(out, "Requested "); + BIO_puts(out, "Signature Algorithms: "); + for (i = 0; i < nsig; i++) { + int hash_nid, sign_nid; + unsigned char rhash, rsign; + const char *sstr = NULL; + if (shared) + SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL, + &rsign, &rhash); + else + SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash); + if (i) + BIO_puts(out, ":"); + sstr = get_sigtype(sign_nid); + if (sstr) + BIO_printf(out, "%s", sstr); + else + BIO_printf(out, "0x%02X", (int)rsign); + if (hash_nid != NID_undef) + BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid)); + else if (sstr == NULL) + BIO_printf(out, "+0x%02X", (int)rhash); + } + BIO_puts(out, "\n"); + return 1; +} + +int ssl_print_sigalgs(BIO *out, SSL *s) +{ + int nid; + + if (!SSL_is_server(s)) + ssl_print_client_cert_types(out, s); + do_print_sigalgs(out, s, 0); + do_print_sigalgs(out, s, 1); + if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef) + BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid)); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid)); + return 1; +} + +#ifndef OPENSSL_NO_EC +int ssl_print_point_formats(BIO *out, SSL *s) +{ + int i, nformats; + const char *pformats; + + nformats = SSL_get0_ec_point_formats(s, &pformats); + if (nformats <= 0) + return 1; + BIO_puts(out, "Supported Elliptic Curve Point Formats: "); + for (i = 0; i < nformats; i++, pformats++) { + if (i) + BIO_puts(out, ":"); + switch (*pformats) { + case TLSEXT_ECPOINTFORMAT_uncompressed: + BIO_puts(out, "uncompressed"); + break; + + case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime: + BIO_puts(out, "ansiX962_compressed_prime"); + break; + + case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2: + BIO_puts(out, "ansiX962_compressed_char2"); + break; + + default: + BIO_printf(out, "unknown(%d)", (int)*pformats); + break; + + } + } + BIO_puts(out, "\n"); + return 1; +} + +int ssl_print_groups(BIO *out, SSL *s, int noshared) +{ + int i, ngroups, *groups, nid; + + ngroups = SSL_get1_groups(s, NULL); + if (ngroups <= 0) + return 1; + groups = app_malloc(ngroups * sizeof(int), "groups to print"); + SSL_get1_groups(s, groups); + + BIO_puts(out, "Supported groups: "); + for (i = 0; i < ngroups; i++) { + if (i) + BIO_puts(out, ":"); + nid = groups[i]; + BIO_printf(out, "%s", SSL_group_to_name(s, nid)); + } + OPENSSL_free(groups); + if (noshared) { + BIO_puts(out, "\n"); + return 1; + } + BIO_puts(out, "\nShared groups: "); + ngroups = SSL_get_shared_group(s, -1); + for (i = 0; i < ngroups; i++) { + if (i) + BIO_puts(out, ":"); + nid = SSL_get_shared_group(s, i); + BIO_printf(out, "%s", SSL_group_to_name(s, nid)); + } + if (ngroups == 0) + BIO_puts(out, "NONE"); + BIO_puts(out, "\n"); + return 1; +} +#endif + +int ssl_print_tmp_key(BIO *out, SSL *s) +{ + EVP_PKEY *key; + + if (!SSL_get_peer_tmp_key(s, &key)) + return 1; + BIO_puts(out, "Server Temp Key: "); + switch (EVP_PKEY_get_id(key)) { + case EVP_PKEY_RSA: + BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_get_bits(key)); + break; + + case EVP_PKEY_DH: + BIO_printf(out, "DH, %d bits\n", EVP_PKEY_get_bits(key)); + break; +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + { + char name[80]; + size_t name_len; + + if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME, + name, sizeof(name), &name_len)) + strcpy(name, "?"); + BIO_printf(out, "ECDH, %s, %d bits\n", name, EVP_PKEY_get_bits(key)); + } + break; +#endif + default: + BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_get_id(key)), + EVP_PKEY_get_bits(key)); + } + EVP_PKEY_free(key); + return 1; +} + +long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len, + int argi, long argl, int ret, size_t *processed) +{ + BIO *out; + + out = (BIO *)BIO_get_callback_arg(bio); + if (out == NULL) + return ret; + + if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { + if (ret > 0 && processed != NULL) { + BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n", + (void *)bio, (void *)argp, len, *processed, *processed); + BIO_dump(out, argp, (int)*processed); + } else { + BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n", + (void *)bio, (void *)argp, len, ret); + } + } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { + if (ret > 0 && processed != NULL) { + BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n", + (void *)bio, (void *)argp, len, *processed, *processed); + BIO_dump(out, argp, (int)*processed); + } else { + BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n", + (void *)bio, (void *)argp, len, ret); + } + } + return ret; +} + +void apps_ssl_info_callback(const SSL *s, int where, int ret) +{ + const char *str; + int w; + + w = where & ~SSL_ST_MASK; + + if (w & SSL_ST_CONNECT) + str = "SSL_connect"; + else if (w & SSL_ST_ACCEPT) + str = "SSL_accept"; + else + str = "undefined"; + + if (where & SSL_CB_LOOP) { + BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s)); + } else if (where & SSL_CB_ALERT) { + str = (where & SSL_CB_READ) ? "read" : "write"; + BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", + str, + SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } else if (where & SSL_CB_EXIT) { + if (ret == 0) + BIO_printf(bio_err, "%s:failed in %s\n", + str, SSL_state_string_long(s)); + else if (ret < 0) + BIO_printf(bio_err, "%s:error in %s\n", + str, SSL_state_string_long(s)); + } +} + +static STRINT_PAIR ssl_versions[] = { + {"SSL 3.0", SSL3_VERSION}, + {"TLS 1.0", TLS1_VERSION}, + {"TLS 1.1", TLS1_1_VERSION}, + {"TLS 1.2", TLS1_2_VERSION}, + {"TLS 1.3", TLS1_3_VERSION}, + {"DTLS 1.0", DTLS1_VERSION}, + {"DTLS 1.0 (bad)", DTLS1_BAD_VER}, + {NULL} +}; + +static STRINT_PAIR alert_types[] = { + {" close_notify", 0}, + {" end_of_early_data", 1}, + {" unexpected_message", 10}, + {" bad_record_mac", 20}, + {" decryption_failed", 21}, + {" record_overflow", 22}, + {" decompression_failure", 30}, + {" handshake_failure", 40}, + {" bad_certificate", 42}, + {" unsupported_certificate", 43}, + {" certificate_revoked", 44}, + {" certificate_expired", 45}, + {" certificate_unknown", 46}, + {" illegal_parameter", 47}, + {" unknown_ca", 48}, + {" access_denied", 49}, + {" decode_error", 50}, + {" decrypt_error", 51}, + {" export_restriction", 60}, + {" protocol_version", 70}, + {" insufficient_security", 71}, + {" internal_error", 80}, + {" inappropriate_fallback", 86}, + {" user_canceled", 90}, + {" no_renegotiation", 100}, + {" missing_extension", 109}, + {" unsupported_extension", 110}, + {" certificate_unobtainable", 111}, + {" unrecognized_name", 112}, + {" bad_certificate_status_response", 113}, + {" bad_certificate_hash_value", 114}, + {" unknown_psk_identity", 115}, + {" certificate_required", 116}, + {NULL} +}; + +static STRINT_PAIR handshakes[] = { + {", HelloRequest", SSL3_MT_HELLO_REQUEST}, + {", ClientHello", SSL3_MT_CLIENT_HELLO}, + {", ServerHello", SSL3_MT_SERVER_HELLO}, + {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST}, + {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET}, + {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA}, + {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS}, + {", Certificate", SSL3_MT_CERTIFICATE}, + {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE}, + {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST}, + {", ServerHelloDone", SSL3_MT_SERVER_DONE}, + {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY}, + {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE}, + {", Finished", SSL3_MT_FINISHED}, + {", CertificateUrl", SSL3_MT_CERTIFICATE_URL}, + {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS}, + {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA}, + {", KeyUpdate", SSL3_MT_KEY_UPDATE}, +#ifndef OPENSSL_NO_NEXTPROTONEG + {", NextProto", SSL3_MT_NEXT_PROTO}, +#endif + {", MessageHash", SSL3_MT_MESSAGE_HASH}, + {NULL} +}; + +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg) +{ + BIO *bio = arg; + const char *str_write_p = write_p ? ">>>" : "<<<"; + char tmpbuf[128]; + const char *str_version, *str_content_type = "", *str_details1 = "", *str_details2 = ""; + const unsigned char* bp = buf; + + if (version == SSL3_VERSION || + version == TLS1_VERSION || + version == TLS1_1_VERSION || + version == TLS1_2_VERSION || + version == TLS1_3_VERSION || + version == DTLS1_VERSION || version == DTLS1_BAD_VER) { + str_version = lookup(version, ssl_versions, "???"); + switch (content_type) { + case SSL3_RT_CHANGE_CIPHER_SPEC: + /* type 20 */ + str_content_type = ", ChangeCipherSpec"; + break; + case SSL3_RT_ALERT: + /* type 21 */ + str_content_type = ", Alert"; + str_details1 = ", ???"; + if (len == 2) { + switch (bp[0]) { + case 1: + str_details1 = ", warning"; + break; + case 2: + str_details1 = ", fatal"; + break; + } + str_details2 = lookup((int)bp[1], alert_types, " ???"); + } + break; + case SSL3_RT_HANDSHAKE: + /* type 22 */ + str_content_type = ", Handshake"; + str_details1 = "???"; + if (len > 0) + str_details1 = lookup((int)bp[0], handshakes, "???"); + break; + case SSL3_RT_APPLICATION_DATA: + /* type 23 */ + str_content_type = ", ApplicationData"; + break; + case SSL3_RT_HEADER: + /* type 256 */ + str_content_type = ", RecordHeader"; + break; + case SSL3_RT_INNER_CONTENT_TYPE: + /* type 257 */ + str_content_type = ", InnerContent"; + break; + default: + BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, ", Unknown (content_type=%d)", content_type); + str_content_type = tmpbuf; + } + } else { + BIO_snprintf(tmpbuf, sizeof(tmpbuf)-1, "Not TLS data or unknown version (version=%d, content_type=%d)", version, content_type); + str_version = tmpbuf; + } + + BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version, + str_content_type, (unsigned long)len, str_details1, + str_details2); + + if (len > 0) { + size_t num, i; + + BIO_printf(bio, " "); + num = len; + for (i = 0; i < num; i++) { + if (i % 16 == 0 && i > 0) + BIO_printf(bio, "\n "); + BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]); + } + if (i < len) + BIO_printf(bio, " ..."); + BIO_printf(bio, "\n"); + } + (void)BIO_flush(bio); +} + +static STRINT_PAIR tlsext_types[] = { + {"server name", TLSEXT_TYPE_server_name}, + {"max fragment length", TLSEXT_TYPE_max_fragment_length}, + {"client certificate URL", TLSEXT_TYPE_client_certificate_url}, + {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys}, + {"truncated HMAC", TLSEXT_TYPE_truncated_hmac}, + {"status request", TLSEXT_TYPE_status_request}, + {"user mapping", TLSEXT_TYPE_user_mapping}, + {"client authz", TLSEXT_TYPE_client_authz}, + {"server authz", TLSEXT_TYPE_server_authz}, + {"cert type", TLSEXT_TYPE_cert_type}, + {"supported_groups", TLSEXT_TYPE_supported_groups}, + {"EC point formats", TLSEXT_TYPE_ec_point_formats}, + {"SRP", TLSEXT_TYPE_srp}, + {"signature algorithms", TLSEXT_TYPE_signature_algorithms}, + {"use SRTP", TLSEXT_TYPE_use_srtp}, + {"session ticket", TLSEXT_TYPE_session_ticket}, + {"renegotiation info", TLSEXT_TYPE_renegotiate}, + {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp}, + {"TLS padding", TLSEXT_TYPE_padding}, +#ifdef TLSEXT_TYPE_next_proto_neg + {"next protocol", TLSEXT_TYPE_next_proto_neg}, +#endif +#ifdef TLSEXT_TYPE_encrypt_then_mac + {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac}, +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + {"application layer protocol negotiation", + TLSEXT_TYPE_application_layer_protocol_negotiation}, +#endif +#ifdef TLSEXT_TYPE_extended_master_secret + {"extended master secret", TLSEXT_TYPE_extended_master_secret}, +#endif + {"key share", TLSEXT_TYPE_key_share}, + {"supported versions", TLSEXT_TYPE_supported_versions}, + {"psk", TLSEXT_TYPE_psk}, + {"psk kex modes", TLSEXT_TYPE_psk_kex_modes}, + {"certificate authorities", TLSEXT_TYPE_certificate_authorities}, + {"post handshake auth", TLSEXT_TYPE_post_handshake_auth}, + {NULL} +}; + +/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */ +static STRINT_PAIR signature_tls13_scheme_list[] = { + {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */}, + {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */}, +/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */ +/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */ + {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */}, + {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */}, + {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */}, + {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */}, + {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */}, + {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */}, + {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */}, + {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */}, + {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */}, + {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */}, + {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */}, + {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */}, + {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */}, + {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */}, + {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */}, + {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */}, + {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */}, + {NULL} +}; + +/* from rfc5246 7.4.1.4.1. */ +static STRINT_PAIR signature_tls12_alg_list[] = { + {"anonymous", TLSEXT_signature_anonymous /* 0 */}, + {"RSA", TLSEXT_signature_rsa /* 1 */}, + {"DSA", TLSEXT_signature_dsa /* 2 */}, + {"ECDSA", TLSEXT_signature_ecdsa /* 3 */}, + {NULL} +}; + +/* from rfc5246 7.4.1.4.1. */ +static STRINT_PAIR signature_tls12_hash_list[] = { + {"none", TLSEXT_hash_none /* 0 */}, + {"MD5", TLSEXT_hash_md5 /* 1 */}, + {"SHA1", TLSEXT_hash_sha1 /* 2 */}, + {"SHA224", TLSEXT_hash_sha224 /* 3 */}, + {"SHA256", TLSEXT_hash_sha256 /* 4 */}, + {"SHA384", TLSEXT_hash_sha384 /* 5 */}, + {"SHA512", TLSEXT_hash_sha512 /* 6 */}, + {NULL} +}; + +void tlsext_cb(SSL *s, int client_server, int type, + const unsigned char *data, int len, void *arg) +{ + BIO *bio = arg; + const char *extname = lookup(type, tlsext_types, "unknown"); + + BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n", + client_server ? "server" : "client", extname, type, len); + BIO_dump(bio, (const char *)data, len); + (void)BIO_flush(bio); +} + +#ifndef OPENSSL_NO_SOCK +int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, + size_t *cookie_len) +{ + unsigned char *buffer = NULL; + size_t length = 0; + unsigned short port; + BIO_ADDR *lpeer = NULL, *peer = NULL; + int res = 0; + + /* Initialize a random secret */ + if (!cookie_initialized) { + if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) { + BIO_printf(bio_err, "error setting random cookie secret\n"); + return 0; + } + cookie_initialized = 1; + } + + if (SSL_is_dtls(ssl)) { + lpeer = peer = BIO_ADDR_new(); + if (peer == NULL) { + BIO_printf(bio_err, "memory full\n"); + return 0; + } + + /* Read peer information */ + (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); + } else { + peer = ourpeer; + } + + /* Create buffer with peer's address and port */ + if (!BIO_ADDR_rawaddress(peer, NULL, &length)) { + BIO_printf(bio_err, "Failed getting peer address\n"); + BIO_ADDR_free(lpeer); + return 0; + } + OPENSSL_assert(length != 0); + port = BIO_ADDR_rawport(peer); + length += sizeof(port); + buffer = app_malloc(length, "cookie generate buffer"); + + memcpy(buffer, &port, sizeof(port)); + BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL); + + if (EVP_Q_mac(NULL, "HMAC", NULL, "SHA1", NULL, + cookie_secret, COOKIE_SECRET_LENGTH, buffer, length, + cookie, DTLS1_COOKIE_LENGTH, cookie_len) == NULL) { + BIO_printf(bio_err, + "Error calculating HMAC-SHA1 of buffer with secret\n"); + goto end; + } + res = 1; +end: + OPENSSL_free(buffer); + BIO_ADDR_free(lpeer); + + return res; +} + +int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, + size_t cookie_len) +{ + unsigned char result[EVP_MAX_MD_SIZE]; + size_t resultlength; + + /* Note: we check cookie_initialized because if it's not, + * it cannot be valid */ + if (cookie_initialized + && generate_stateless_cookie_callback(ssl, result, &resultlength) + && cookie_len == resultlength + && memcmp(result, cookie, resultlength) == 0) + return 1; + + return 0; +} + +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len) +{ + size_t temp = 0; + int res = generate_stateless_cookie_callback(ssl, cookie, &temp); + + if (res != 0) + *cookie_len = (unsigned int)temp; + return res; +} + +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len) +{ + return verify_stateless_cookie_callback(ssl, cookie, cookie_len); +} + +#endif + +/* + * Example of extended certificate handling. Where the standard support of + * one certificate per algorithm is not sufficient an application can decide + * which certificate(s) to use at runtime based on whatever criteria it deems + * appropriate. + */ + +/* Linked list of certificates, keys and chains */ +struct ssl_excert_st { + int certform; + const char *certfile; + int keyform; + const char *keyfile; + const char *chainfile; + X509 *cert; + EVP_PKEY *key; + STACK_OF(X509) *chain; + int build_chain; + struct ssl_excert_st *next, *prev; +}; + +static STRINT_PAIR chain_flags[] = { + {"Overall Validity", CERT_PKEY_VALID}, + {"Sign with EE key", CERT_PKEY_SIGN}, + {"EE signature", CERT_PKEY_EE_SIGNATURE}, + {"CA signature", CERT_PKEY_CA_SIGNATURE}, + {"EE key parameters", CERT_PKEY_EE_PARAM}, + {"CA key parameters", CERT_PKEY_CA_PARAM}, + {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN}, + {"Issuer Name", CERT_PKEY_ISSUER_NAME}, + {"Certificate Type", CERT_PKEY_CERT_TYPE}, + {NULL} +}; + +static void print_chain_flags(SSL *s, int flags) +{ + STRINT_PAIR *pp; + + for (pp = chain_flags; pp->name; ++pp) + BIO_printf(bio_err, "\t%s: %s\n", + pp->name, + (flags & pp->retval) ? "OK" : "NOT OK"); + BIO_printf(bio_err, "\tSuite B: "); + if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS) + BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n"); + else + BIO_printf(bio_err, "not tested\n"); +} + +/* + * Very basic selection callback: just use any certificate chain reported as + * valid. More sophisticated could prioritise according to local policy. + */ +static int set_cert_cb(SSL *ssl, void *arg) +{ + int i, rv; + SSL_EXCERT *exc = arg; +#ifdef CERT_CB_TEST_RETRY + static int retry_cnt; + + if (retry_cnt < 5) { + retry_cnt++; + BIO_printf(bio_err, + "Certificate callback retry test: count %d\n", + retry_cnt); + return -1; + } +#endif + SSL_certs_clear(ssl); + + if (exc == NULL) + return 1; + + /* + * Go to end of list and traverse backwards since we prepend newer + * entries this retains the original order. + */ + while (exc->next != NULL) + exc = exc->next; + + i = 0; + + while (exc != NULL) { + i++; + rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain); + BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i); + X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0, + get_nameopt()); + BIO_puts(bio_err, "\n"); + print_chain_flags(ssl, rv); + if (rv & CERT_PKEY_VALID) { + if (!SSL_use_certificate(ssl, exc->cert) + || !SSL_use_PrivateKey(ssl, exc->key)) { + return 0; + } + /* + * NB: we wouldn't normally do this as it is not efficient + * building chains on each connection better to cache the chain + * in advance. + */ + if (exc->build_chain) { + if (!SSL_build_cert_chain(ssl, 0)) + return 0; + } else if (exc->chain != NULL) { + if (!SSL_set1_chain(ssl, exc->chain)) + return 0; + } + } + exc = exc->prev; + } + return 1; +} + +void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc) +{ + SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc); +} + +static int ssl_excert_prepend(SSL_EXCERT **pexc) +{ + SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert"); + + memset(exc, 0, sizeof(*exc)); + + exc->next = *pexc; + *pexc = exc; + + if (exc->next) { + exc->certform = exc->next->certform; + exc->keyform = exc->next->keyform; + exc->next->prev = exc; + } else { + exc->certform = FORMAT_PEM; + exc->keyform = FORMAT_PEM; + } + return 1; + +} + +void ssl_excert_free(SSL_EXCERT *exc) +{ + SSL_EXCERT *curr; + + if (exc == NULL) + return; + while (exc) { + X509_free(exc->cert); + EVP_PKEY_free(exc->key); + sk_X509_pop_free(exc->chain, X509_free); + curr = exc; + exc = exc->next; + OPENSSL_free(curr); + } +} + +int load_excert(SSL_EXCERT **pexc) +{ + SSL_EXCERT *exc = *pexc; + + if (exc == NULL) + return 1; + /* If nothing in list, free and set to NULL */ + if (exc->certfile == NULL && exc->next == NULL) { + ssl_excert_free(exc); + *pexc = NULL; + return 1; + } + for (; exc; exc = exc->next) { + if (exc->certfile == NULL) { + BIO_printf(bio_err, "Missing filename\n"); + return 0; + } + exc->cert = load_cert(exc->certfile, exc->certform, + "Server Certificate"); + if (exc->cert == NULL) + return 0; + if (exc->keyfile != NULL) { + exc->key = load_key(exc->keyfile, exc->keyform, + 0, NULL, NULL, "server key"); + } else { + exc->key = load_key(exc->certfile, exc->certform, + 0, NULL, NULL, "server key"); + } + if (exc->key == NULL) + return 0; + if (exc->chainfile != NULL) { + if (!load_certs(exc->chainfile, 0, &exc->chain, NULL, "server chain")) + return 0; + } + } + return 1; +} + +enum range { OPT_X_ENUM }; + +int args_excert(int opt, SSL_EXCERT **pexc) +{ + SSL_EXCERT *exc = *pexc; + + assert(opt > OPT_X__FIRST); + assert(opt < OPT_X__LAST); + + if (exc == NULL) { + if (!ssl_excert_prepend(&exc)) { + BIO_printf(bio_err, " %s: Error initialising xcert\n", + opt_getprog()); + goto err; + } + *pexc = exc; + } + + switch ((enum range)opt) { + case OPT_X__FIRST: + case OPT_X__LAST: + return 0; + case OPT_X_CERT: + if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) { + BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog()); + goto err; + } + *pexc = exc; + exc->certfile = opt_arg(); + break; + case OPT_X_KEY: + if (exc->keyfile != NULL) { + BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog()); + goto err; + } + exc->keyfile = opt_arg(); + break; + case OPT_X_CHAIN: + if (exc->chainfile != NULL) { + BIO_printf(bio_err, "%s: Chain already specified\n", + opt_getprog()); + goto err; + } + exc->chainfile = opt_arg(); + break; + case OPT_X_CHAIN_BUILD: + exc->build_chain = 1; + break; + case OPT_X_CERTFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->certform)) + return 0; + break; + case OPT_X_KEYFORM: + if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->keyform)) + return 0; + break; + } + return 1; + + err: + ERR_print_errors(bio_err); + ssl_excert_free(exc); + *pexc = NULL; + return 0; +} + +static void print_raw_cipherlist(SSL *s) +{ + const unsigned char *rlist; + static const unsigned char scsv_id[] = { 0, 0xFF }; + size_t i, rlistlen, num; + + if (!SSL_is_server(s)) + return; + num = SSL_get0_raw_cipherlist(s, NULL); + OPENSSL_assert(num == 2); + rlistlen = SSL_get0_raw_cipherlist(s, &rlist); + BIO_puts(bio_err, "Client cipher list: "); + for (i = 0; i < rlistlen; i += num, rlist += num) { + const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist); + if (i) + BIO_puts(bio_err, ":"); + if (c != NULL) { + BIO_puts(bio_err, SSL_CIPHER_get_name(c)); + } else if (memcmp(rlist, scsv_id, num) == 0) { + BIO_puts(bio_err, "SCSV"); + } else { + size_t j; + BIO_puts(bio_err, "0x"); + for (j = 0; j < num; j++) + BIO_printf(bio_err, "%02X", rlist[j]); + } + } + BIO_puts(bio_err, "\n"); +} + +/* + * Hex encoder for TLSA RRdata, not ':' delimited. + */ +static char *hexencode(const unsigned char *data, size_t len) +{ + static const char *hex = "0123456789abcdef"; + char *out; + char *cp; + size_t outlen = 2 * len + 1; + int ilen = (int) outlen; + + if (outlen < len || ilen < 0 || outlen != (size_t)ilen) { + BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n", + opt_getprog(), len); + exit(1); + } + cp = out = app_malloc(ilen, "TLSA hex data buffer"); + + while (len-- > 0) { + *cp++ = hex[(*data >> 4) & 0x0f]; + *cp++ = hex[*data++ & 0x0f]; + } + *cp = '\0'; + return out; +} + +void print_verify_detail(SSL *s, BIO *bio) +{ + int mdpth; + EVP_PKEY *mspki; + long verify_err = SSL_get_verify_result(s); + + if (verify_err == X509_V_OK) { + const char *peername = SSL_get0_peername(s); + + BIO_printf(bio, "Verification: OK\n"); + if (peername != NULL) + BIO_printf(bio, "Verified peername: %s\n", peername); + } else { + const char *reason = X509_verify_cert_error_string(verify_err); + + BIO_printf(bio, "Verification error: %s\n", reason); + } + + if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) { + uint8_t usage, selector, mtype; + const unsigned char *data = NULL; + size_t dlen = 0; + char *hexdata; + + mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen); + + /* + * The TLSA data field can be quite long when it is a certificate, + * public key or even a SHA2-512 digest. Because the initial octets of + * ASN.1 certificates and public keys contain mostly boilerplate OIDs + * and lengths, we show the last 12 bytes of the data instead, as these + * are more likely to distinguish distinct TLSA records. + */ +#define TLSA_TAIL_SIZE 12 + if (dlen > TLSA_TAIL_SIZE) + hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); + else + hexdata = hexencode(data, dlen); + BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", + usage, selector, mtype, + (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, + (mspki != NULL) ? "signed the certificate" : + mdpth ? "matched TA certificate" : "matched EE certificate", + mdpth); + OPENSSL_free(hexdata); + } +} + +void print_ssl_summary(SSL *s) +{ + const SSL_CIPHER *c; + X509 *peer; + + BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s)); + print_raw_cipherlist(s); + c = SSL_get_current_cipher(s); + BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); + do_print_sigalgs(bio_err, s, 0); + peer = SSL_get0_peer_certificate(s); + if (peer != NULL) { + int nid; + + BIO_puts(bio_err, "Peer certificate: "); + X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), + 0, get_nameopt()); + BIO_puts(bio_err, "\n"); + if (SSL_get_peer_signature_nid(s, &nid)) + BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid)); + if (SSL_get_peer_signature_type_nid(s, &nid)) + BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); + print_verify_detail(s, bio_err); + } else { + BIO_puts(bio_err, "No peer certificate\n"); + } +#ifndef OPENSSL_NO_EC + ssl_print_point_formats(bio_err, s); + if (SSL_is_server(s)) + ssl_print_groups(bio_err, s, 1); + else + ssl_print_tmp_key(bio_err, s); +#else + if (!SSL_is_server(s)) + ssl_print_tmp_key(bio_err, s); +#endif +} + +int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, + SSL_CTX *ctx) +{ + int i; + + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) { + const char *flag = sk_OPENSSL_STRING_value(str, i); + const char *arg = sk_OPENSSL_STRING_value(str, i + 1); + + if (SSL_CONF_cmd(cctx, flag, arg) <= 0) { + BIO_printf(bio_err, "Call to SSL_CONF_cmd(%s, %s) failed\n", + flag, arg == NULL ? "" : arg); + ERR_print_errors(bio_err); + return 0; + } + } + if (!SSL_CONF_CTX_finish(cctx)) { + BIO_puts(bio_err, "Error finishing context\n"); + ERR_print_errors(bio_err); + return 0; + } + return 1; +} + +static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls) +{ + X509_CRL *crl; + int i, ret = 1; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + if (!X509_STORE_add_crl(st, crl)) + ret = 0; + } + return ret; +} + +int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download) +{ + X509_STORE *st; + + st = SSL_CTX_get_cert_store(ctx); + add_crls_store(st, crls); + if (crl_download) + store_setup_crl_download(st); + return 1; +} + +int ssl_load_stores(SSL_CTX *ctx, + const char *vfyCApath, const char *vfyCAfile, + const char *vfyCAstore, + const char *chCApath, const char *chCAfile, + const char *chCAstore, + STACK_OF(X509_CRL) *crls, int crl_download) +{ + X509_STORE *vfy = NULL, *ch = NULL; + int rv = 0; + + if (vfyCApath != NULL || vfyCAfile != NULL || vfyCAstore != NULL) { + vfy = X509_STORE_new(); + if (vfy == NULL) + goto err; + if (vfyCAfile != NULL && !X509_STORE_load_file(vfy, vfyCAfile)) + goto err; + if (vfyCApath != NULL && !X509_STORE_load_path(vfy, vfyCApath)) + goto err; + if (vfyCAstore != NULL && !X509_STORE_load_store(vfy, vfyCAstore)) + goto err; + add_crls_store(vfy, crls); + SSL_CTX_set1_verify_cert_store(ctx, vfy); + if (crl_download) + store_setup_crl_download(vfy); + } + if (chCApath != NULL || chCAfile != NULL || chCAstore != NULL) { + ch = X509_STORE_new(); + if (ch == NULL) + goto err; + if (chCAfile != NULL && !X509_STORE_load_file(ch, chCAfile)) + goto err; + if (chCApath != NULL && !X509_STORE_load_path(ch, chCApath)) + goto err; + if (chCAstore != NULL && !X509_STORE_load_store(ch, chCAstore)) + goto err; + SSL_CTX_set1_chain_cert_store(ctx, ch); + } + rv = 1; + err: + X509_STORE_free(vfy); + X509_STORE_free(ch); + return rv; +} + +/* Verbose print out of security callback */ + +typedef struct { + BIO *out; + int verbose; + int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, + void *other, void *ex); +} security_debug_ex; + +static STRINT_PAIR callback_types[] = { + {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED}, + {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED}, + {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK}, +#ifndef OPENSSL_NO_DH + {"Temp DH key bits", SSL_SECOP_TMP_DH}, +#endif + {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED}, + {"Shared Curve", SSL_SECOP_CURVE_SHARED}, + {"Check Curve", SSL_SECOP_CURVE_CHECK}, + {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED}, + {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED}, + {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK}, + {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK}, + {"Certificate chain EE key", SSL_SECOP_EE_KEY}, + {"Certificate chain CA key", SSL_SECOP_CA_KEY}, + {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY}, + {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY}, + {"Certificate chain CA digest", SSL_SECOP_CA_MD}, + {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD}, + {"SSL compression", SSL_SECOP_COMPRESSION}, + {"Session ticket", SSL_SECOP_TICKET}, + {NULL} +}; + +static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, + int op, int bits, int nid, + void *other, void *ex) +{ + security_debug_ex *sdb = ex; + int rv, show_bits = 1, cert_md = 0; + const char *nm; + int show_nm; + + rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex); + if (rv == 1 && sdb->verbose < 2) + return 1; + BIO_puts(sdb->out, "Security callback: "); + + nm = lookup(op, callback_types, NULL); + show_nm = nm != NULL; + switch (op) { + case SSL_SECOP_TICKET: + case SSL_SECOP_COMPRESSION: + show_bits = 0; + show_nm = 0; + break; + case SSL_SECOP_VERSION: + BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???")); + show_bits = 0; + show_nm = 0; + break; + case SSL_SECOP_CA_MD: + case SSL_SECOP_PEER_CA_MD: + cert_md = 1; + break; + case SSL_SECOP_SIGALG_SUPPORTED: + case SSL_SECOP_SIGALG_SHARED: + case SSL_SECOP_SIGALG_CHECK: + case SSL_SECOP_SIGALG_MASK: + show_nm = 0; + break; + } + if (show_nm) + BIO_printf(sdb->out, "%s=", nm); + + switch (op & SSL_SECOP_OTHER_TYPE) { + + case SSL_SECOP_OTHER_CIPHER: + BIO_puts(sdb->out, SSL_CIPHER_get_name(other)); + break; + +#ifndef OPENSSL_NO_EC + case SSL_SECOP_OTHER_CURVE: + { + const char *cname; + cname = EC_curve_nid2nist(nid); + if (cname == NULL) + cname = OBJ_nid2sn(nid); + BIO_puts(sdb->out, cname); + } + break; +#endif + case SSL_SECOP_OTHER_CERT: + { + if (cert_md) { + int sig_nid = X509_get_signature_nid(other); + + BIO_puts(sdb->out, OBJ_nid2sn(sig_nid)); + } else { + EVP_PKEY *pkey = X509_get0_pubkey(other); + + if (pkey == NULL) { + BIO_printf(sdb->out, "Public key missing"); + } else { + const char *algname = ""; + + EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, + &algname, EVP_PKEY_get0_asn1(pkey)); + BIO_printf(sdb->out, "%s, bits=%d", + algname, EVP_PKEY_get_bits(pkey)); + } + } + break; + } + case SSL_SECOP_OTHER_SIGALG: + { + const unsigned char *salg = other; + const char *sname = NULL; + int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */ + /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */ + + if (nm != NULL) + BIO_printf(sdb->out, "%s", nm); + else + BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op); + + sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL); + if (sname != NULL) { + BIO_printf(sdb->out, " scheme=%s", sname); + } else { + int alg_code = salg[1]; + int hash_code = salg[0]; + const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL); + const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL); + + if (alg_str != NULL && hash_str != NULL) + BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str); + else + BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code); + } + } + + } + + if (show_bits) + BIO_printf(sdb->out, ", security bits=%d", bits); + BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no"); + return rv; +} + +void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose) +{ + static security_debug_ex sdb; + + sdb.out = bio_err; + sdb.verbose = verbose; + sdb.old_cb = SSL_CTX_get_security_callback(ctx); + SSL_CTX_set_security_callback(ctx, security_callback_debug); + SSL_CTX_set0_security_ex_data(ctx, &sdb); +} + +static void keylog_callback(const SSL *ssl, const char *line) +{ + if (bio_keylog == NULL) { + BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n"); + return; + } + + /* + * There might be concurrent writers to the keylog file, so we must ensure + * that the given line is written at once. + */ + BIO_printf(bio_keylog, "%s\n", line); + (void)BIO_flush(bio_keylog); +} + +int set_keylog_file(SSL_CTX *ctx, const char *keylog_file) +{ + /* Close any open files */ + BIO_free_all(bio_keylog); + bio_keylog = NULL; + + if (ctx == NULL || keylog_file == NULL) { + /* Keylogging is disabled, OK. */ + return 0; + } + + /* + * Append rather than write in order to allow concurrent modification. + * Furthermore, this preserves existing keylog files which is useful when + * the tool is run multiple times. + */ + bio_keylog = BIO_new_file(keylog_file, "a"); + if (bio_keylog == NULL) { + BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file); + return 1; + } + + /* Write a header for seekable, empty files (this excludes pipes). */ + if (BIO_tell(bio_keylog) == 0) { + BIO_puts(bio_keylog, + "# SSL/TLS secrets log file, generated by OpenSSL\n"); + (void)BIO_flush(bio_keylog); + } + SSL_CTX_set_keylog_callback(ctx, keylog_callback); + return 0; +} + +void print_ca_names(BIO *bio, SSL *s) +{ + const char *cs = SSL_is_server(s) ? "server" : "client"; + const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s); + int i; + + if (sk == NULL || sk_X509_NAME_num(sk) == 0) { + if (!SSL_is_server(s)) + BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs); + return; + } + + BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs); + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt()); + BIO_write(bio, "\n", 1); + } +} diff --git a/apps/lib/s_socket.c b/apps/lib/s_socket.c new file mode 100644 --- /dev/null +++ b/apps/lib/s_socket.c @@ -0,0 +1,455 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +/* socket-related functions used by s_client and s_server */ +#include +#include +#include +#include +#include +#include + +/* + * With IPv6, it looks like Digital has mixed up the proper order of + * recursive header file inclusion, resulting in the compiler complaining + * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is + * needed to have fileno() declared correctly... So let's define u_int + */ +#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) +# define __U_INT +typedef unsigned int u_int; +#endif + +#ifdef _WIN32 +# include + +/* MSVC renamed some POSIX functions to have an underscore prefix. */ +# ifdef _MSC_VER +# define getpid _getpid +# endif +#endif + +#ifndef OPENSSL_NO_SOCK + +# include "apps.h" +# include "s_apps.h" +# include "internal/sockets.h" + +# if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif +# endif + +# include +# include + +/* Keep track of our peer's address for the cookie callback */ +BIO_ADDR *ourpeer = NULL; + +/* + * init_client - helper routine to set up socket communication + * @sock: pointer to storage of resulting socket. + * @host: the host name or path (for AF_UNIX) to connect to. + * @port: the port to connect to (ignored for AF_UNIX). + * @bindhost: source host or path (for AF_UNIX). + * @bindport: source port (ignored for AF_UNIX). + * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or + * AF_UNSPEC + * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM + * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any) + * + * This will create a socket and use it to connect to a host:port, or if + * family == AF_UNIX, to the path found in host. + * + * If the host has more than one address, it will try them one by one until + * a successful connection is established. The resulting socket will be + * found in *sock on success, it will be given INVALID_SOCKET otherwise. + * + * Returns 1 on success, 0 on failure. + */ +int init_client(int *sock, const char *host, const char *port, + const char *bindhost, const char *bindport, + int family, int type, int protocol) +{ + BIO_ADDRINFO *res = NULL; + BIO_ADDRINFO *bindaddr = NULL; + const BIO_ADDRINFO *ai = NULL; + const BIO_ADDRINFO *bi = NULL; + int found = 0; + int ret; + + if (BIO_sock_init() != 1) + return 0; + + ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol, + &res); + if (ret == 0) { + ERR_print_errors(bio_err); + return 0; + } + + if (bindhost != NULL || bindport != NULL) { + ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT, + family, type, protocol, &bindaddr); + if (ret == 0) { + ERR_print_errors (bio_err); + goto out; + } + } + + ret = 0; + for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { + /* Admittedly, these checks are quite paranoid, we should not get + * anything in the BIO_ADDRINFO chain that we haven't + * asked for. */ + OPENSSL_assert((family == AF_UNSPEC + || family == BIO_ADDRINFO_family(ai)) + && (type == 0 || type == BIO_ADDRINFO_socktype(ai)) + && (protocol == 0 + || protocol == BIO_ADDRINFO_protocol(ai))); + + if (bindaddr != NULL) { + for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) { + if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai)) + break; + } + if (bi == NULL) + continue; + ++found; + } + + *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai), + BIO_ADDRINFO_protocol(ai), 0); + if (*sock == INVALID_SOCKET) { + /* Maybe the kernel doesn't support the socket family, even if + * BIO_lookup() added it in the returned result... + */ + continue; + } + + if (bi != NULL) { + if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi), + BIO_SOCK_REUSEADDR)) { + BIO_closesocket(*sock); + *sock = INVALID_SOCKET; + break; + } + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + /* + * For SCTP we have to set various options on the socket prior to + * connecting. This is done automatically by BIO_new_dgram_sctp(). + * We don't actually need the created BIO though so we free it again + * immediately. + */ + BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE); + + if (tmpbio == NULL) { + ERR_print_errors(bio_err); + return 0; + } + BIO_free(tmpbio); + } +#endif + + if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), + BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) { + BIO_closesocket(*sock); + *sock = INVALID_SOCKET; + continue; + } + + /* Success, don't try any more addresses */ + break; + } + + if (*sock == INVALID_SOCKET) { + if (bindaddr != NULL && !found) { + BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n", +#ifdef AF_INET6 + BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " : +#endif + BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " : + BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "", + bindhost != NULL ? bindhost : "", + bindport != NULL ? ":" : "", + bindport != NULL ? bindport : ""); + ERR_clear_error(); + ret = 0; + } + ERR_print_errors(bio_err); + } else { + /* Remove any stale errors from previous connection attempts */ + ERR_clear_error(); + ret = 1; + } +out: + if (bindaddr != NULL) { + BIO_ADDRINFO_free (bindaddr); + } + BIO_ADDRINFO_free(res); + return ret; +} + +int report_server_accept(BIO *out, int asock, int with_address, int with_pid) +{ + int success = 1; + + if (BIO_printf(out, "ACCEPT") <= 0) + return 0; + if (with_address) { + union BIO_sock_info_u info; + char *hostname = NULL; + char *service = NULL; + + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info) + && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL + && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL) { + success = BIO_printf(out, + strchr(hostname, ':') == NULL + ? /* IPv4 */ " %s:%s" + : /* IPv6 */ " [%s]:%s", + hostname, service) > 0; + } else { + (void)BIO_printf(out, "unknown:error\n"); + success = 0; + } + OPENSSL_free(hostname); + OPENSSL_free(service); + BIO_ADDR_free(info.addr); + } + if (with_pid) + success = success && BIO_printf(out, " PID=%d", getpid()) > 0; + success = success && BIO_printf(out, "\n") > 0; + (void)BIO_flush(out); + + return success; +} + +/* + * do_server - helper routine to perform a server operation + * @accept_sock: pointer to storage of resulting socket. + * @host: the host name or path (for AF_UNIX) to connect to. + * @port: the port to connect to (ignored for AF_UNIX). + * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or + * AF_UNSPEC + * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM + * @cb: pointer to a function that receives the accepted socket and + * should perform the communication with the connecting client. + * @context: pointer to memory that's passed verbatim to the cb function. + * @naccept: number of times an incoming connect should be accepted. If -1, + * unlimited number. + * + * This will create a socket and use it to listen to a host:port, or if + * family == AF_UNIX, to the path found in host, then start accepting + * incoming connections and run cb on the resulting socket. + * + * 0 on failure, something other on success. + */ +int do_server(int *accept_sock, const char *host, const char *port, + int family, int type, int protocol, do_server_cb cb, + unsigned char *context, int naccept, BIO *bio_s_out) +{ + int asock = 0; + int sock; + int i; + BIO_ADDRINFO *res = NULL; + const BIO_ADDRINFO *next; + int sock_family, sock_type, sock_protocol, sock_port; + const BIO_ADDR *sock_address; + int sock_family_fallback = AF_UNSPEC; + const BIO_ADDR *sock_address_fallback = NULL; + int sock_options = BIO_SOCK_REUSEADDR; + int ret = 0; + + if (BIO_sock_init() != 1) + return 0; + + if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol, + &res)) { + ERR_print_errors(bio_err); + return 0; + } + + /* Admittedly, these checks are quite paranoid, we should not get + * anything in the BIO_ADDRINFO chain that we haven't asked for */ + OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res)) + && (type == 0 || type == BIO_ADDRINFO_socktype(res)) + && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res))); + + sock_family = BIO_ADDRINFO_family(res); + sock_type = BIO_ADDRINFO_socktype(res); + sock_protocol = BIO_ADDRINFO_protocol(res); + sock_address = BIO_ADDRINFO_address(res); + next = BIO_ADDRINFO_next(res); +#ifdef AF_INET6 + if (sock_family == AF_INET6) + sock_options |= BIO_SOCK_V6_ONLY; + if (next != NULL + && BIO_ADDRINFO_socktype(next) == sock_type + && BIO_ADDRINFO_protocol(next) == sock_protocol) { + if (sock_family == AF_INET + && BIO_ADDRINFO_family(next) == AF_INET6) { + /* In case AF_INET6 is returned but not supported by the + * kernel, retry with the first detected address family */ + sock_family_fallback = sock_family; + sock_address_fallback = sock_address; + sock_family = AF_INET6; + sock_address = BIO_ADDRINFO_address(next); + } else if (sock_family == AF_INET6 + && BIO_ADDRINFO_family(next) == AF_INET) { + sock_options &= ~BIO_SOCK_V6_ONLY; + } + } +#endif + + asock = BIO_socket(sock_family, sock_type, sock_protocol, 0); + if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) { + asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0); + sock_address = sock_address_fallback; + } + if (asock == INVALID_SOCKET + || !BIO_listen(asock, sock_address, sock_options)) { + BIO_ADDRINFO_free(res); + ERR_print_errors(bio_err); + if (asock != INVALID_SOCKET) + BIO_closesocket(asock); + goto end; + } + +#ifndef OPENSSL_NO_SCTP + if (protocol == IPPROTO_SCTP) { + /* + * For SCTP we have to set various options on the socket prior to + * accepting. This is done automatically by BIO_new_dgram_sctp(). + * We don't actually need the created BIO though so we free it again + * immediately. + */ + BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE); + + if (tmpbio == NULL) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + BIO_free(tmpbio); + } +#endif + + sock_port = BIO_ADDR_rawport(sock_address); + + BIO_ADDRINFO_free(res); + res = NULL; + + if (!report_server_accept(bio_s_out, asock, sock_port == 0, 0)) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + + if (accept_sock != NULL) + *accept_sock = asock; + for (;;) { + char sink[64]; + struct timeval timeout; + fd_set readfds; + + if (type == SOCK_STREAM) { + BIO_ADDR_free(ourpeer); + ourpeer = BIO_ADDR_new(); + if (ourpeer == NULL) { + BIO_closesocket(asock); + ERR_print_errors(bio_err); + goto end; + } + do { + sock = BIO_accept_ex(asock, ourpeer, 0); + } while (sock < 0 && BIO_sock_should_retry(sock)); + if (sock < 0) { + ERR_print_errors(bio_err); + BIO_closesocket(asock); + break; + } + BIO_set_tcp_ndelay(sock, 1); + i = (*cb)(sock, type, protocol, context); + + /* + * If we ended with an alert being sent, but still with data in the + * network buffer to be read, then calling BIO_closesocket() will + * result in a TCP-RST being sent. On some platforms (notably + * Windows) then this will result in the peer immediately abandoning + * the connection including any buffered alert data before it has + * had a chance to be read. Shutting down the sending side first, + * and then closing the socket sends TCP-FIN first followed by + * TCP-RST. This seems to allow the peer to read the alert data. + */ + shutdown(sock, 1); /* SHUT_WR */ + /* + * We just said we have nothing else to say, but it doesn't mean + * that the other side has nothing. It's even recommended to + * consume incoming data. [In testing context this ensures that + * alerts are passed on...] + */ + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* some extreme round-trip */ + do { + FD_ZERO(&readfds); + openssl_fdset(sock, &readfds); + } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 + && readsocket(sock, sink, sizeof(sink)) > 0); + + BIO_closesocket(sock); + } else { + i = (*cb)(asock, type, protocol, context); + } + + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) { + BIO_closesocket(asock); + ret = i; + break; + } + } + end: +# ifdef AF_UNIX + if (family == AF_UNIX) + unlink(host); +# endif + BIO_ADDR_free(ourpeer); + ourpeer = NULL; + return ret; +} + +void do_ssl_shutdown(SSL *ssl) +{ + int ret; + + do { + /* We only do unidirectional shutdown */ + ret = SSL_shutdown(ssl); + if (ret < 0) { + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_ASYNC: + case SSL_ERROR_WANT_ASYNC_JOB: + /* We just do busy waiting. Nothing clever */ + continue; + } + ret = 0; + } + } while (ret < 0); +} + +#endif /* OPENSSL_NO_SOCK */ diff --git a/apps/lib/tlssrp_depr.c b/apps/lib/tlssrp_depr.c new file mode 100644 --- /dev/null +++ b/apps/lib/tlssrp_depr.c @@ -0,0 +1,231 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005 Nokia. 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 + * https://www.openssl.org/source/license.html + */ + +/* + * This file is to enable backwards compatibility for the SRP features of + * s_client, s_server and ciphers. All of those features are deprecated and will + * eventually disappear. In the meantime, to continue to support them, we + * need to access deprecated SRP APIs. + */ +#define OPENSSL_SUPPRESS_DEPRECATED + +#include +#include +#include +#include +#include "apps_ui.h" +#include "apps.h" +#include "s_apps.h" + +static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) +{ + BN_CTX *bn_ctx = BN_CTX_new(); + BIGNUM *p = BN_new(); + BIGNUM *r = BN_new(); + int ret = + g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && + BN_check_prime(N, bn_ctx, NULL) == 1 && + p != NULL && BN_rshift1(p, N) && + /* p = (N-1)/2 */ + BN_check_prime(p, bn_ctx, NULL) == 1 && + r != NULL && + /* verify g^((N-1)/2) == -1 (mod N) */ + BN_mod_exp(r, g, p, N, bn_ctx) && + BN_add_word(r, 1) && BN_cmp(r, N) == 0; + + BN_free(r); + BN_free(p); + BN_CTX_free(bn_ctx); + return ret; +} + +/*- + * This callback is used here for two purposes: + * - extended debugging + * - making some primality tests for unknown groups + * The callback is only called for a non default group. + * + * An application does not need the call back at all if + * only the standard groups are used. In real life situations, + * client and server already share well known groups, + * thus there is no need to verify them. + * Furthermore, in case that a server actually proposes a group that + * is not one of those defined in RFC 5054, it is more appropriate + * to add the group to a static list and then compare since + * primality tests are rather cpu consuming. + */ + +static int ssl_srp_verify_param_cb(SSL *s, void *arg) +{ + SRP_ARG *srp_arg = (SRP_ARG *)arg; + BIGNUM *N = NULL, *g = NULL; + + if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL)) + return 0; + if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) { + BIO_printf(bio_err, "SRP parameters:\n"); + BIO_printf(bio_err, "\tN="); + BN_print(bio_err, N); + BIO_printf(bio_err, "\n\tg="); + BN_print(bio_err, g); + BIO_printf(bio_err, "\n"); + } + + if (SRP_check_known_gN_param(g, N)) + return 1; + + if (srp_arg->amp == 1) { + if (srp_arg->debug) + BIO_printf(bio_err, + "SRP param N and g are not known params, going to check deeper.\n"); + + /* + * The srp_moregroups is a real debugging feature. Implementors + * should rather add the value to the known ones. The minimal size + * has already been tested. + */ + if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g)) + return 1; + } + BIO_printf(bio_err, "SRP param N and g rejected.\n"); + return 0; +} + +#define PWD_STRLEN 1024 + +static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) +{ + SRP_ARG *srp_arg = (SRP_ARG *)arg; + char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer"); + PW_CB_DATA cb_tmp; + int l; + + cb_tmp.password = (char *)srp_arg->srppassin; + cb_tmp.prompt_info = "SRP user"; + if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) { + BIO_printf(bio_err, "Can't read Password\n"); + OPENSSL_free(pass); + return NULL; + } + *(pass + l) = '\0'; + + return pass; +} + +int set_up_srp_arg(SSL_CTX *ctx, SRP_ARG *srp_arg, int srp_lateuser, int c_msg, + int c_debug) +{ + if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg->srplogin)) { + BIO_printf(bio_err, "Unable to set SRP username\n"); + return 0; + } + srp_arg->msg = c_msg; + srp_arg->debug = c_debug; + SSL_CTX_set_srp_cb_arg(ctx, &srp_arg); + SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb); + SSL_CTX_set_srp_strength(ctx, srp_arg->strength); + if (c_msg || c_debug || srp_arg->amp == 0) + SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb); + + return 1; +} + +static char *dummy_srp(SSL *ssl, void *arg) +{ + return ""; +} + +void set_up_dummy_srp(SSL_CTX *ctx) +{ + SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); +} + +/* + * This callback pretends to require some asynchronous logic in order to + * obtain a verifier. When the callback is called for a new connection we + * return with a negative value. This will provoke the accept etc to return + * with an LOOKUP_X509. The main logic of the reinvokes the suspended call + * (which would normally occur after a worker has finished) and we set the + * user parameters. + */ +static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) +{ + srpsrvparm *p = (srpsrvparm *) arg; + int ret = SSL3_AL_FATAL; + + if (p->login == NULL && p->user == NULL) { + p->login = SSL_get_srp_username(s); + BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); + return -1; + } + + if (p->user == NULL) { + BIO_printf(bio_err, "User %s doesn't exist\n", p->login); + goto err; + } + + if (SSL_set_srp_server_param + (s, p->user->N, p->user->g, p->user->s, p->user->v, + p->user->info) < 0) { + *ad = SSL_AD_INTERNAL_ERROR; + goto err; + } + BIO_printf(bio_err, + "SRP parameters set: username = \"%s\" info=\"%s\" \n", + p->login, p->user->info); + ret = SSL_ERROR_NONE; + + err: + SRP_user_pwd_free(p->user); + p->user = NULL; + p->login = NULL; + return ret; +} + +int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm, + char *srpuserseed, char *srp_verifier_file) +{ + int ret; + + srp_callback_parm->vb = SRP_VBASE_new(srpuserseed); + srp_callback_parm->user = NULL; + srp_callback_parm->login = NULL; + + if (srp_callback_parm->vb == NULL) { + BIO_printf(bio_err, "Failed to initialize SRP verifier file \n"); + return 0; + } + if ((ret = + SRP_VBASE_init(srp_callback_parm->vb, + srp_verifier_file)) != SRP_NO_ERROR) { + BIO_printf(bio_err, + "Cannot initialize SRP verifier file \"%s\":ret=%d\n", + srp_verifier_file, ret); + return 0; + } + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); + SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); + SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); + + return 1; +} + +void lookup_srp_user(srpsrvparm *srp_callback_parm, BIO *bio_s_out) +{ + SRP_user_pwd_free(srp_callback_parm->user); + srp_callback_parm->user = SRP_VBASE_get1_by_user(srp_callback_parm->vb, + srp_callback_parm->login); + + if (srp_callback_parm->user != NULL) + BIO_printf(bio_s_out, "LOOKUP done %s\n", + srp_callback_parm->user->info); + else + BIO_printf(bio_s_out, "LOOKUP not successful\n"); +} diff --git a/apps/lib/vms_decc_argv.c b/apps/lib/vms_decc_argv.c new file mode 100644 --- /dev/null +++ b/apps/lib/vms_decc_argv.c @@ -0,0 +1,72 @@ +/* + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "platform.h" /* for copy_argv() */ + +char **newargv = NULL; + +static void cleanup_argv(void) +{ + OPENSSL_free(newargv); + newargv = NULL; +} + +char **copy_argv(int *argc, char *argv[]) +{ + /*- + * The note below is for historical purpose. On VMS now we always + * copy argv "safely." + * + * 2011-03-22 SMS. + * If we have 32-bit pointers everywhere, then we're safe, and + * we bypass this mess, as on non-VMS systems. + * Problem 1: Compaq/HP C before V7.3 always used 32-bit + * pointers for argv[]. + * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers + * everywhere else, we always allocate and use a 64-bit + * duplicate of argv[]. + * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed + * to NULL-terminate a 64-bit argv[]. (As this was written, the + * compiler ECO was available only on IA64.) + * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a + * 64-bit argv[argc] for NULL, and, if necessary, use a + * (properly) NULL-terminated (64-bit) duplicate of argv[]. + * The same code is used in either case to duplicate argv[]. + * Some of these decisions could be handled in preprocessing, + * but the code tends to get even uglier, and the penalty for + * deciding at compile- or run-time is tiny. + */ + + int i, count = *argc; + char **p = newargv; + + cleanup_argv(); + + /* + * We purposefully use OPENSSL_malloc() rather than app_malloc() here, + * to avoid symbol name clashes in test programs that would otherwise + * get them when linking with all of libapps.a. + * See comment in test/build.info. + */ + newargv = OPENSSL_malloc(sizeof(*newargv) * (count + 1)); + if (newargv == NULL) + return NULL; + + /* Register automatic cleanup on first use */ + if (p == NULL) + OPENSSL_atexit(cleanup_argv); + + for (i = 0; i < count; i++) + newargv[i] = argv[i]; + newargv[i] = NULL; + *argc = i; + return newargv; +} diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c new file mode 100644 --- /dev/null +++ b/apps/lib/vms_term_sock.c @@ -0,0 +1,591 @@ +/* + * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016 VMS Software, Inc. 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 + * https://www.openssl.org/source/license.html + */ + +#ifdef __VMS +# define OPENSSL_SYS_VMS +# pragma message disable DOLLARID + + +# include + +# if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +/* + * On VMS, you need to define this to get the declaration of fileno(). The + * value 2 is to make sure no function defined in POSIX-2 is left undefined. + */ +# define _POSIX_C_SOURCE 2 +# endif + +# include + +# undef _POSIX_C_SOURCE + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef __alpha +# include +# else +typedef struct _iosb { /* Copied from IOSBDEF.H for Alpha */ +# pragma __nomember_alignment + __union { + __struct { + unsigned short int iosb$w_status; /* Final I/O status */ + __union { + __struct { /* 16-bit byte count variant */ + unsigned short int iosb$w_bcnt; /* 16-bit byte count */ + __union { + unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */ + unsigned int iosb$l_pid; /* 32-bit pid */ + } iosb$r_l; + } iosb$r_bcnt_16; + __struct { /* 32-bit byte count variant */ + unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */ + unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */ + } iosb$r_bcnt_32; + } iosb$r_devdepend; + } iosb$r_io_64; + __struct { + __union { + unsigned int iosb$l_getxxi_status; /* Final GETxxI status */ + unsigned int iosb$l_reg_status; /* Final $Registry status */ + } iosb$r_l_status; + unsigned int iosb$l_reserved; /* Reserved field */ + } iosb$r_get_64; + } iosb$r_io_get; +} IOSB; + +# if !defined(__VAXC) +# define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status +# define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt +# define iosb$r_l iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l +# define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend +# define iosb$l_pid iosb$r_l.iosb$l_pid +# define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt +# define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high +# define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status +# define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status +# endif /* #if !defined(__VAXC) */ + +# endif /* End of IOSBDEF */ + +# include +# include +# include +# include +# include +# include + +# include "vms_term_sock.h" + +# ifdef __alpha +static struct _iosb TerminalDeviceIosb; +# else +IOSB TerminalDeviceIosb; +# endif + +static char TerminalDeviceBuff[255 + 2]; +static int TerminalSocketPair[2] = {0, 0}; +static unsigned short TerminalDeviceChan = 0; + +static int CreateSocketPair (int, int, int, int *); +static void SocketPairTimeoutAst (int); +static int TerminalDeviceAst (int); +static void LogMessage (char *, ...); + +/* +** Socket Pair Timeout Value (must be 0-59 seconds) +*/ +# define SOCKET_PAIR_TIMEOUT_VALUE 20 + +/* +** Socket Pair Timeout Block which is passed to timeout AST +*/ +typedef struct _SocketPairTimeoutBlock { + unsigned short SockChan1; + unsigned short SockChan2; +} SPTB; + +# ifdef TERM_SOCK_TEST + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +int main (int argc, char *argv[], char *envp[]) +{ + char TermBuff[80]; + int TermSock, + status, + len; + + LogMessage ("Enter 'q' or 'Q' to quit ..."); + while (OPENSSL_strcasecmp (TermBuff, "Q")) { + /* + ** Create the terminal socket + */ + status = TerminalSocket (TERM_SOCK_CREATE, &TermSock); + if (status != TERM_SOCK_SUCCESS) + exit (1); + + /* + ** Process the terminal input + */ + LogMessage ("Waiting on terminal I/O ...\n"); + len = recv (TermSock, TermBuff, sizeof(TermBuff), 0) ; + TermBuff[len] = '\0'; + LogMessage ("Received terminal I/O [%s]", TermBuff); + + /* + ** Delete the terminal socket + */ + status = TerminalSocket (TERM_SOCK_DELETE, &TermSock); + if (status != TERM_SOCK_SUCCESS) + exit (1); + } + + return 1; + +} +# endif + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +int TerminalSocket (int FunctionCode, int *ReturnSocket) +{ + int status; + $DESCRIPTOR (TerminalDeviceDesc, "SYS$COMMAND"); + + /* + ** Process the requested function code + */ + switch (FunctionCode) { + case TERM_SOCK_CREATE: + /* + ** Create a socket pair + */ + status = CreateSocketPair (AF_INET, SOCK_STREAM, 0, TerminalSocketPair); + if (status == -1) { + LogMessage ("TerminalSocket: CreateSocketPair () - %08X", status); + if (TerminalSocketPair[0]) + close (TerminalSocketPair[0]); + if (TerminalSocketPair[1]) + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Assign a channel to the terminal device + */ + status = sys$assign (&TerminalDeviceDesc, + &TerminalDeviceChan, + 0, 0, 0); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$ASSIGN () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Queue an async IO to the terminal device + */ + status = sys$qio (EFN$C_ENF, + TerminalDeviceChan, + IO$_READVBLK, + &TerminalDeviceIosb, + TerminalDeviceAst, + 0, + TerminalDeviceBuff, + sizeof(TerminalDeviceBuff) - 2, + 0, 0, 0, 0); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$QIO () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Return the input side of the socket pair + */ + *ReturnSocket = TerminalSocketPair[1]; + break; + + case TERM_SOCK_DELETE: + /* + ** Cancel any pending IO on the terminal channel + */ + status = sys$cancel (TerminalDeviceChan); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$CANCEL () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Deassign the terminal channel + */ + status = sys$dassgn (TerminalDeviceChan); + if (! (status & 1)) { + LogMessage ("TerminalSocket: SYS$DASSGN () - %08X", status); + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + return TERM_SOCK_FAILURE; + } + + /* + ** Close the terminal socket pair + */ + close (TerminalSocketPair[0]); + close (TerminalSocketPair[1]); + + /* + ** Return the initialized socket + */ + *ReturnSocket = 0; + break; + + default: + /* + ** Invalid function code + */ + LogMessage ("TerminalSocket: Invalid Function Code - %d", FunctionCode); + return TERM_SOCK_FAILURE; + break; + } + + /* + ** Return success + */ + return TERM_SOCK_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static int CreateSocketPair (int SocketFamily, + int SocketType, + int SocketProtocol, + int *SocketPair) +{ + struct dsc$descriptor AscTimeDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL}; + static const char* LocalHostAddr = {"127.0.0.1"}; + unsigned short TcpAcceptChan = 0, + TcpDeviceChan = 0; + unsigned long BinTimeBuff[2]; + struct sockaddr_in sin; + char AscTimeBuff[32]; + short LocalHostPort; + int status; + unsigned int slen; + +# ifdef __alpha + struct _iosb iosb; +# else + IOSB iosb; +# endif + + int SockDesc1 = 0, + SockDesc2 = 0; + SPTB sptb; + $DESCRIPTOR (TcpDeviceDesc, "TCPIP$DEVICE"); + + /* + ** Create a socket + */ + SockDesc1 = socket (SocketFamily, SocketType, 0); + if (SockDesc1 < 0) { + LogMessage ("CreateSocketPair: socket () - %d", errno); + return -1; + } + + /* + ** Initialize the socket information + */ + slen = sizeof(sin); + memset ((char *) &sin, 0, slen); + sin.sin_family = SocketFamily; + sin.sin_addr.s_addr = inet_addr (LocalHostAddr); + sin.sin_port = 0; + + /* + ** Bind the socket to the local IP + */ + status = bind (SockDesc1, (struct sockaddr *) &sin, slen); + if (status < 0) { + LogMessage ("CreateSocketPair: bind () - %d", errno); + close (SockDesc1); + return -1; + } + + /* + ** Get the socket name so we can save the port number + */ + status = getsockname (SockDesc1, (struct sockaddr *) &sin, &slen); + if (status < 0) { + LogMessage ("CreateSocketPair: getsockname () - %d", errno); + close (SockDesc1); + return -1; + } else + LocalHostPort = sin.sin_port; + + /* + ** Setup a listen for the socket + */ + listen (SockDesc1, 5); + + /* + ** Get the binary (64-bit) time of the specified timeout value + */ + sprintf (AscTimeBuff, "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE); + AscTimeDesc.dsc$w_length = strlen (AscTimeBuff); + AscTimeDesc.dsc$a_pointer = AscTimeBuff; + status = sys$bintim (&AscTimeDesc, BinTimeBuff); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$BINTIM () - %08X", status); + close (SockDesc1); + return -1; + } + + /* + ** Assign another channel to the TCP/IP device for the accept. + ** This is the channel that ends up being connected to. + */ + status = sys$assign (&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$ASSIGN () - %08X", status); + close (SockDesc1); + return -1; + } + + /* + ** Get the channel of the first socket for the accept + */ + TcpAcceptChan = decc$get_sdc (SockDesc1); + + /* + ** Perform the accept using $QIO so we can do this asynchronously + */ + status = sys$qio (EFN$C_ENF, + TcpAcceptChan, + IO$_ACCESS | IO$M_ACCEPT, + &iosb, + 0, 0, 0, 0, 0, + &TcpDeviceChan, + 0, 0); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$QIO () - %08X", status); + close (SockDesc1); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Create the second socket to do the connect + */ + SockDesc2 = socket (SocketFamily, SocketType, 0); + if (SockDesc2 < 0) { + LogMessage ("CreateSocketPair: socket () - %d", errno); + sys$cancel (TcpAcceptChan); + close (SockDesc1); + sys$dassgn (TcpDeviceChan); + return (-1) ; + } + + /* + ** Setup the Socket Pair Timeout Block + */ + sptb.SockChan1 = TcpAcceptChan; + sptb.SockChan2 = decc$get_sdc (SockDesc2); + + /* + ** Before we block on the connect, set a timer that can cancel I/O on our + ** two sockets if it never connects. + */ + status = sys$setimr (EFN$C_ENF, + BinTimeBuff, + SocketPairTimeoutAst, + &sptb, + 0); + if (! (status & 1)) { + LogMessage ("CreateSocketPair: SYS$SETIMR () - %08X", status); + sys$cancel (TcpAcceptChan); + close (SockDesc1); + close (SockDesc2); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Now issue the connect + */ + memset ((char *) &sin, 0, sizeof(sin)) ; + sin.sin_family = SocketFamily; + sin.sin_addr.s_addr = inet_addr (LocalHostAddr) ; + sin.sin_port = LocalHostPort ; + + status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin)); + if (status < 0 ) { + LogMessage ("CreateSocketPair: connect () - %d", errno); + sys$cantim (&sptb, 0); + sys$cancel (TcpAcceptChan); + close (SockDesc1); + close (SockDesc2); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Wait for the asynch $QIO to finish. Note that if the I/O was aborted + ** (SS$_ABORT), then we probably canceled it from the AST routine - so log + ** a timeout. + */ + status = sys$synch (EFN$C_ENF, &iosb); + if (! (iosb.iosb$w_status & 1)) { + if (iosb.iosb$w_status == SS$_ABORT) + LogMessage ("CreateSocketPair: SYS$QIO(iosb) timeout"); + else { + LogMessage ("CreateSocketPair: SYS$QIO(iosb) - %d", + iosb.iosb$w_status); + sys$cantim (&sptb, 0); + } + close (SockDesc1); + close (SockDesc2); + sys$dassgn (TcpDeviceChan); + return -1; + } + + /* + ** Here we're successfully connected, so cancel the timer, convert the + ** I/O channel to a socket fd, close the listener socket and return the + ** connected pair. + */ + sys$cantim (&sptb, 0); + + close (SockDesc1) ; + SocketPair[0] = SockDesc2 ; + SocketPair[1] = socket_fd (TcpDeviceChan); + + return (0) ; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static void SocketPairTimeoutAst (int astparm) +{ + SPTB *sptb = (SPTB *) astparm; + + sys$cancel (sptb->SockChan2); /* Cancel the connect() */ + sys$cancel (sptb->SockChan1); /* Cancel the accept() */ + + return; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static int TerminalDeviceAst (int astparm) +{ + int status; + + /* + ** Terminate the terminal buffer + */ + TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0'; + strcat (TerminalDeviceBuff, "\n"); + + /* + ** Send the data read from the terminal device through the socket pair + */ + send (TerminalSocketPair[0], TerminalDeviceBuff, + TerminalDeviceIosb.iosb$w_bcnt + 1, 0); + + /* + ** Queue another async IO to the terminal device + */ + status = sys$qio (EFN$C_ENF, + TerminalDeviceChan, + IO$_READVBLK, + &TerminalDeviceIosb, + TerminalDeviceAst, + 0, + TerminalDeviceBuff, + sizeof(TerminalDeviceBuff) - 1, + 0, 0, 0, 0); + + /* + ** Return status + */ + return status; + +} + +/*----------------------------------------------------------------------------*/ +/* */ +/*----------------------------------------------------------------------------*/ +static void LogMessage (char *msg, ...) +{ + char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + static unsigned int pid = 0; + va_list args; + time_t CurTime; + struct tm *LocTime; + char MsgBuff[256]; + + /* + ** Get the process pid + */ + if (pid == 0) + pid = getpid (); + + /* + ** Convert the current time into local time + */ + CurTime = time (NULL); + LocTime = localtime (&CurTime); + + /* + ** Format the message buffer + */ + sprintf (MsgBuff, "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n", + LocTime->tm_mday, Month[LocTime->tm_mon], + (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min, + LocTime->tm_sec, pid, msg); + + /* + ** Get any variable arguments and add them to the print of the message + ** buffer + */ + va_start (args, msg); + vfprintf (stderr, MsgBuff, args); + va_end (args); + + /* + ** Flush standard error output + */ + fsync (fileno (stderr)); + + return; + +} +#endif diff --git a/apps/lib/win32_init.c b/apps/lib/win32_init.c new file mode 100644 --- /dev/null +++ b/apps/lib/win32_init.c @@ -0,0 +1,307 @@ +/* + * Copyright 2016-2020 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#if defined(CP_UTF8) + +static UINT saved_cp; +static int newargc; +static char **newargv; + +static void cleanup(void) +{ + int i; + + SetConsoleOutputCP(saved_cp); + + for (i = 0; i < newargc; i++) + free(newargv[i]); + + free(newargv); +} + +/* + * Incrementally [re]allocate newargv and keep it NULL-terminated. + */ +static int validate_argv(int argc) +{ + static int size = 0; + + if (argc >= size) { + char **ptr; + + while (argc >= size) + size += 64; + + ptr = realloc(newargv, size * sizeof(newargv[0])); + if (ptr == NULL) + return 0; + + (newargv = ptr)[argc] = NULL; + } else { + newargv[argc] = NULL; + } + + return 1; +} + +static int process_glob(WCHAR *wstr, int wlen) +{ + int i, slash, udlen; + WCHAR saved_char; + WIN32_FIND_DATAW data; + HANDLE h; + + /* + * Note that we support wildcard characters only in filename part + * of the path, and not in directories. Windows users are used to + * this, that's why recursive glob processing is not implemented. + */ + /* + * Start by looking for last slash or backslash, ... + */ + for (slash = 0, i = 0; i < wlen; i++) + if (wstr[i] == L'/' || wstr[i] == L'\\') + slash = i + 1; + /* + * ... then look for asterisk or question mark in the file name. + */ + for (i = slash; i < wlen; i++) + if (wstr[i] == L'*' || wstr[i] == L'?') + break; + + if (i == wlen) + return 0; /* definitely not a glob */ + + saved_char = wstr[wlen]; + wstr[wlen] = L'\0'; + h = FindFirstFileW(wstr, &data); + wstr[wlen] = saved_char; + if (h == INVALID_HANDLE_VALUE) + return 0; /* not a valid glob, just pass... */ + + if (slash) + udlen = WideCharToMultiByte(CP_UTF8, 0, wstr, slash, + NULL, 0, NULL, NULL); + else + udlen = 0; + + do { + int uflen; + char *arg; + + /* + * skip over . and .. + */ + if (data.cFileName[0] == L'.') { + if ((data.cFileName[1] == L'\0') || + (data.cFileName[1] == L'.' && data.cFileName[2] == L'\0')) + continue; + } + + if (!validate_argv(newargc + 1)) + break; + + /* + * -1 below means "scan for trailing '\0' *and* count it", + * so that |uflen| covers even trailing '\0'. + */ + uflen = WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1, + NULL, 0, NULL, NULL); + + arg = malloc(udlen + uflen); + if (arg == NULL) + break; + + if (udlen) + WideCharToMultiByte(CP_UTF8, 0, wstr, slash, + arg, udlen, NULL, NULL); + + WideCharToMultiByte(CP_UTF8, 0, data.cFileName, -1, + arg + udlen, uflen, NULL, NULL); + + newargv[newargc++] = arg; + } while (FindNextFileW(h, &data)); + + CloseHandle(h); + + return 1; +} + +void win32_utf8argv(int *argc, char **argv[]) +{ + const WCHAR *wcmdline; + WCHAR *warg, *wend, *p; + int wlen, ulen, valid = 1; + char *arg; + + if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) == 0) + return; + + newargc = 0; + newargv = NULL; + if (!validate_argv(newargc)) + return; + + wcmdline = GetCommandLineW(); + if (wcmdline == NULL) return; + + /* + * make a copy of the command line, since we might have to modify it... + */ + wlen = wcslen(wcmdline); + p = _alloca((wlen + 1) * sizeof(WCHAR)); + wcscpy(p, wcmdline); + + while (*p != L'\0') { + int in_quote = 0; + + if (*p == L' ' || *p == L'\t') { + p++; /* skip over whitespace */ + continue; + } + + /* + * Note: because we may need to fiddle with the number of backslashes, + * the argument string is copied into itself. This is safe because + * the number of characters will never expand. + */ + warg = wend = p; + while (*p != L'\0' + && (in_quote || (*p != L' ' && *p != L'\t'))) { + switch (*p) { + case L'\\': + /* + * Microsoft documentation on how backslashes are treated + * is: + * + * + Backslashes are interpreted literally, unless they + * immediately precede a double quotation mark. + * + If an even number of backslashes is followed by a double + * quotation mark, one backslash is placed in the argv array + * for every pair of backslashes, and the double quotation + * mark is interpreted as a string delimiter. + * + If an odd number of backslashes is followed by a double + * quotation mark, one backslash is placed in the argv array + * for every pair of backslashes, and the double quotation + * mark is "escaped" by the remaining backslash, causing a + * literal double quotation mark (") to be placed in argv. + * + * Ref: https://msdn.microsoft.com/en-us/library/17w5ykft.aspx + * + * Though referred page doesn't mention it, multiple qouble + * quotes are also special. Pair of double quotes in quoted + * string is counted as single double quote. + */ + { + const WCHAR *q = p; + int i; + + while (*p == L'\\') + p++; + + if (*p == L'"') { + int i; + + for (i = (p - q) / 2; i > 0; i--) + *wend++ = L'\\'; + + /* + * if odd amount of backslashes before the quote, + * said quote is part of the argument, not a delimiter + */ + if ((p - q) % 2 == 1) + *wend++ = *p++; + } else { + for (i = p - q; i > 0; i--) + *wend++ = L'\\'; + } + } + break; + case L'"': + /* + * Without the preceding backslash (or when preceded with an + * even number of backslashes), the double quote is a simple + * string delimiter and just slightly change the parsing state + */ + if (in_quote && p[1] == L'"') + *wend++ = *p++; + else + in_quote = !in_quote; + p++; + break; + default: + /* + * Any other non-delimiter character is just taken verbatim + */ + *wend++ = *p++; + } + } + + wlen = wend - warg; + + if (wlen == 0 || !process_glob(warg, wlen)) { + if (!validate_argv(newargc + 1)) { + valid = 0; + break; + } + + ulen = 0; + if (wlen > 0) { + ulen = WideCharToMultiByte(CP_UTF8, 0, warg, wlen, + NULL, 0, NULL, NULL); + if (ulen <= 0) + continue; + } + + arg = malloc(ulen + 1); + if (arg == NULL) { + valid = 0; + break; + } + + if (wlen > 0) + WideCharToMultiByte(CP_UTF8, 0, warg, wlen, + arg, ulen, NULL, NULL); + arg[ulen] = '\0'; + + newargv[newargc++] = arg; + } + } + + if (valid) { + saved_cp = GetConsoleOutputCP(); + SetConsoleOutputCP(CP_UTF8); + + *argc = newargc; + *argv = newargv; + + atexit(cleanup); + } else if (newargv != NULL) { + int i; + + for (i = 0; i < newargc; i++) + free(newargv[i]); + + free(newargv); + + newargc = 0; + newargv = NULL; + } + + return; +} +#else +void win32_utf8argv(int *argc, char **argv[]) +{ return; } +#endif diff --git a/apps/list.c b/apps/list.c new file mode 100644 --- /dev/null +++ b/apps/list.c @@ -0,0 +1,1706 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +/* We need to use some deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "apps.h" +#include "app_params.h" +#include "progs.h" +#include "opt.h" +#include "names.h" + +static int verbose = 0; +static const char *select_name = NULL; + +/* Checks to see if algorithms are fetchable */ +#define IS_FETCHABLE(type, TYPE) \ + static int is_ ## type ## _fetchable(const TYPE *alg) \ + { \ + TYPE *impl; \ + const char *propq = app_get0_propq(); \ + OSSL_LIB_CTX *libctx = app_get0_libctx(); \ + const char *name = TYPE ## _get0_name(alg); \ + \ + ERR_set_mark(); \ + impl = TYPE ## _fetch(libctx, name, propq); \ + ERR_pop_to_mark(); \ + if (impl == NULL) \ + return 0; \ + TYPE ## _free(impl); \ + return 1; \ + } +IS_FETCHABLE(cipher, EVP_CIPHER) +IS_FETCHABLE(digest, EVP_MD) +IS_FETCHABLE(mac, EVP_MAC) +IS_FETCHABLE(kdf, EVP_KDF) +IS_FETCHABLE(rand, EVP_RAND) +IS_FETCHABLE(keymgmt, EVP_KEYMGMT) +IS_FETCHABLE(signature, EVP_SIGNATURE) +IS_FETCHABLE(kem, EVP_KEM) +IS_FETCHABLE(asym_cipher, EVP_ASYM_CIPHER) +IS_FETCHABLE(keyexch, EVP_KEYEXCH) +IS_FETCHABLE(decoder, OSSL_DECODER) +IS_FETCHABLE(encoder, OSSL_ENCODER) + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +static int include_legacy(void) +{ + return app_get0_propq() == NULL; +} + +static void legacy_cipher_fn(const EVP_CIPHER *c, + const char *from, const char *to, void *arg) +{ + if (select_name != NULL + && (c == NULL + || OPENSSL_strcasecmp(select_name, EVP_CIPHER_get0_name(c)) != 0)) + return; + if (c != NULL) { + BIO_printf(arg, " %s\n", EVP_CIPHER_get0_name(c)); + } else { + if (from == NULL) + from = ""; + if (to == NULL) + to = ""; + BIO_printf(arg, " %s => %s\n", from, to); + } +} +#endif + +DEFINE_STACK_OF(EVP_CIPHER) +static int cipher_cmp(const EVP_CIPHER * const *a, + const EVP_CIPHER * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(*b))); +} + +static void collect_ciphers(EVP_CIPHER *cipher, void *stack) +{ + STACK_OF(EVP_CIPHER) *cipher_stack = stack; + + if (is_cipher_fetchable(cipher) + && sk_EVP_CIPHER_push(cipher_stack, cipher) > 0) + EVP_CIPHER_up_ref(cipher); +} + +static void list_ciphers(void) +{ + STACK_OF(EVP_CIPHER) *ciphers = sk_EVP_CIPHER_new(cipher_cmp); + int i; + + if (ciphers == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (include_legacy()) { + BIO_printf(bio_out, "Legacy:\n"); + EVP_CIPHER_do_all_sorted(legacy_cipher_fn, bio_out); + } +#endif + + BIO_printf(bio_out, "Provided:\n"); + EVP_CIPHER_do_all_provided(app_get0_libctx(), collect_ciphers, ciphers); + sk_EVP_CIPHER_sort(ciphers); + for (i = 0; i < sk_EVP_CIPHER_num(ciphers); i++) { + const EVP_CIPHER *c = sk_EVP_CIPHER_value(ciphers, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_CIPHER_is_a(c, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_CIPHER_names_do_all(c, collect_names, names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_CIPHER_get0_provider(c))); + + if (verbose) { + const char *desc = EVP_CIPHER_get0_description(c); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("retrievable algorithm parameters", + EVP_CIPHER_gettable_params(c), 4); + print_param_types("retrievable operation parameters", + EVP_CIPHER_gettable_ctx_params(c), 4); + print_param_types("settable operation parameters", + EVP_CIPHER_settable_ctx_params(c), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_CIPHER_pop_free(ciphers, EVP_CIPHER_free); +} + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +static void legacy_md_fn(const EVP_MD *m, + const char *from, const char *to, void *arg) +{ + if (m != NULL) { + BIO_printf(arg, " %s\n", EVP_MD_get0_name(m)); + } else { + if (from == NULL) + from = ""; + if (to == NULL) + to = ""; + BIO_printf((BIO *)arg, " %s => %s\n", from, to); + } +} +#endif + +DEFINE_STACK_OF(EVP_MD) +static int md_cmp(const EVP_MD * const *a, const EVP_MD * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(*b))); +} + +static void collect_digests(EVP_MD *digest, void *stack) +{ + STACK_OF(EVP_MD) *digest_stack = stack; + + if (is_digest_fetchable(digest) + && sk_EVP_MD_push(digest_stack, digest) > 0) + EVP_MD_up_ref(digest); +} + +static void list_digests(void) +{ + STACK_OF(EVP_MD) *digests = sk_EVP_MD_new(md_cmp); + int i; + + if (digests == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (include_legacy()) { + BIO_printf(bio_out, "Legacy:\n"); + EVP_MD_do_all_sorted(legacy_md_fn, bio_out); + } +#endif + + BIO_printf(bio_out, "Provided:\n"); + EVP_MD_do_all_provided(app_get0_libctx(), collect_digests, digests); + sk_EVP_MD_sort(digests); + for (i = 0; i < sk_EVP_MD_num(digests); i++) { + const EVP_MD *m = sk_EVP_MD_value(digests, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_MD_is_a(m, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_MD_names_do_all(m, collect_names, names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(m))); + + if (verbose) { + const char *desc = EVP_MD_get0_description(m); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("retrievable algorithm parameters", + EVP_MD_gettable_params(m), 4); + print_param_types("retrievable operation parameters", + EVP_MD_gettable_ctx_params(m), 4); + print_param_types("settable operation parameters", + EVP_MD_settable_ctx_params(m), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_MD_pop_free(digests, EVP_MD_free); +} + +DEFINE_STACK_OF(EVP_MAC) +static int mac_cmp(const EVP_MAC * const *a, const EVP_MAC * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(*b))); +} + +static void collect_macs(EVP_MAC *mac, void *stack) +{ + STACK_OF(EVP_MAC) *mac_stack = stack; + + if (is_mac_fetchable(mac) + && sk_EVP_MAC_push(mac_stack, mac) > 0) + EVP_MAC_up_ref(mac); +} + +static void list_macs(void) +{ + STACK_OF(EVP_MAC) *macs = sk_EVP_MAC_new(mac_cmp); + int i; + + if (macs == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Provided MACs:\n"); + EVP_MAC_do_all_provided(app_get0_libctx(), collect_macs, macs); + sk_EVP_MAC_sort(macs); + for (i = 0; i < sk_EVP_MAC_num(macs); i++) { + const EVP_MAC *m = sk_EVP_MAC_value(macs, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_MAC_is_a(m, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_MAC_names_do_all(m, collect_names, names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_MAC_get0_provider(m))); + + if (verbose) { + const char *desc = EVP_MAC_get0_description(m); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("retrievable algorithm parameters", + EVP_MAC_gettable_params(m), 4); + print_param_types("retrievable operation parameters", + EVP_MAC_gettable_ctx_params(m), 4); + print_param_types("settable operation parameters", + EVP_MAC_settable_ctx_params(m), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_MAC_pop_free(macs, EVP_MAC_free); +} + +/* + * KDFs and PRFs + */ +DEFINE_STACK_OF(EVP_KDF) +static int kdf_cmp(const EVP_KDF * const *a, const EVP_KDF * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(*b))); +} + +static void collect_kdfs(EVP_KDF *kdf, void *stack) +{ + STACK_OF(EVP_KDF) *kdf_stack = stack; + + if (is_kdf_fetchable(kdf) + && sk_EVP_KDF_push(kdf_stack, kdf) > 0) + EVP_KDF_up_ref(kdf); +} + +static void list_kdfs(void) +{ + STACK_OF(EVP_KDF) *kdfs = sk_EVP_KDF_new(kdf_cmp); + int i; + + if (kdfs == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Provided KDFs and PDFs:\n"); + EVP_KDF_do_all_provided(app_get0_libctx(), collect_kdfs, kdfs); + sk_EVP_KDF_sort(kdfs); + for (i = 0; i < sk_EVP_KDF_num(kdfs); i++) { + const EVP_KDF *k = sk_EVP_KDF_value(kdfs, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_KDF_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_KDF_names_do_all(k, collect_names, names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_KDF_get0_provider(k))); + + if (verbose) { + const char *desc = EVP_KDF_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("retrievable algorithm parameters", + EVP_KDF_gettable_params(k), 4); + print_param_types("retrievable operation parameters", + EVP_KDF_gettable_ctx_params(k), 4); + print_param_types("settable operation parameters", + EVP_KDF_settable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_KDF_pop_free(kdfs, EVP_KDF_free); +} + +/* + * RANDs + */ +DEFINE_STACK_OF(EVP_RAND) + +static int rand_cmp(const EVP_RAND * const *a, const EVP_RAND * const *b) +{ + int ret = OPENSSL_strcasecmp(EVP_RAND_get0_name(*a), EVP_RAND_get0_name(*b)); + + if (ret == 0) + ret = strcmp(OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(*b))); + + return ret; +} + +static void collect_rands(EVP_RAND *rand, void *stack) +{ + STACK_OF(EVP_RAND) *rand_stack = stack; + + if (is_rand_fetchable(rand) + && sk_EVP_RAND_push(rand_stack, rand) > 0) + EVP_RAND_up_ref(rand); +} + +static void list_random_generators(void) +{ + STACK_OF(EVP_RAND) *rands = sk_EVP_RAND_new(rand_cmp); + int i; + + if (rands == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Provided RNGs and seed sources:\n"); + EVP_RAND_do_all_provided(app_get0_libctx(), collect_rands, rands); + sk_EVP_RAND_sort(rands); + for (i = 0; i < sk_EVP_RAND_num(rands); i++) { + const EVP_RAND *m = sk_EVP_RAND_value(rands, i); + + if (select_name != NULL + && OPENSSL_strcasecmp(EVP_RAND_get0_name(m), select_name) != 0) + continue; + BIO_printf(bio_out, " %s", EVP_RAND_get0_name(m)); + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(m))); + + if (verbose) { + const char *desc = EVP_RAND_get0_description(m); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("retrievable algorithm parameters", + EVP_RAND_gettable_params(m), 4); + print_param_types("retrievable operation parameters", + EVP_RAND_gettable_ctx_params(m), 4); + print_param_types("settable operation parameters", + EVP_RAND_settable_ctx_params(m), 4); + } + } + sk_EVP_RAND_pop_free(rands, EVP_RAND_free); +} + +static void display_random(const char *name, EVP_RAND_CTX *drbg) +{ + EVP_RAND *rand; + uint64_t u; + const char *p; + const OSSL_PARAM *gettables; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + unsigned char buf[1000]; + + BIO_printf(bio_out, "%s:\n", name); + if (drbg != NULL) { + rand = EVP_RAND_CTX_get0_rand(drbg); + + BIO_printf(bio_out, " %s", EVP_RAND_get0_name(rand)); + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_RAND_get0_provider(rand))); + + switch (EVP_RAND_get_state(drbg)) { + case EVP_RAND_STATE_UNINITIALISED: + p = "uninitialised"; + break; + case EVP_RAND_STATE_READY: + p = "ready"; + break; + case EVP_RAND_STATE_ERROR: + p = "error"; + break; + default: + p = "unknown"; + break; + } + BIO_printf(bio_out, " state = %s\n", p); + + gettables = EVP_RAND_gettable_ctx_params(rand); + if (gettables != NULL) + for (; gettables->key != NULL; gettables++) { + /* State has been dealt with already, so ignore */ + if (OPENSSL_strcasecmp(gettables->key, OSSL_RAND_PARAM_STATE) == 0) + continue; + /* Outside of verbose mode, we skip non-string values */ + if (gettables->data_type != OSSL_PARAM_UTF8_STRING + && gettables->data_type != OSSL_PARAM_UTF8_PTR + && !verbose) + continue; + params->key = gettables->key; + params->data_type = gettables->data_type; + if (gettables->data_type == OSSL_PARAM_UNSIGNED_INTEGER + || gettables->data_type == OSSL_PARAM_INTEGER) { + params->data = &u; + params->data_size = sizeof(u); + } else { + params->data = buf; + params->data_size = sizeof(buf); + } + params->return_size = 0; + if (EVP_RAND_CTX_get_params(drbg, params)) + print_param_value(params, 2); + } + } +} + +static void list_random_instances(void) +{ + display_random("primary", RAND_get0_primary(NULL)); + display_random("public", RAND_get0_public(NULL)); + display_random("private", RAND_get0_private(NULL)); +} + +/* + * Encoders + */ +DEFINE_STACK_OF(OSSL_ENCODER) +static int encoder_cmp(const OSSL_ENCODER * const *a, + const OSSL_ENCODER * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(*a)), + OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(*b))); +} + +static void collect_encoders(OSSL_ENCODER *encoder, void *stack) +{ + STACK_OF(OSSL_ENCODER) *encoder_stack = stack; + + if (is_encoder_fetchable(encoder) + && sk_OSSL_ENCODER_push(encoder_stack, encoder) > 0) + OSSL_ENCODER_up_ref(encoder); +} + +static void list_encoders(void) +{ + STACK_OF(OSSL_ENCODER) *encoders; + int i; + + encoders = sk_OSSL_ENCODER_new(encoder_cmp); + if (encoders == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Provided ENCODERs:\n"); + OSSL_ENCODER_do_all_provided(app_get0_libctx(), collect_encoders, + encoders); + sk_OSSL_ENCODER_sort(encoders); + + for (i = 0; i < sk_OSSL_ENCODER_num(encoders); i++) { + OSSL_ENCODER *k = sk_OSSL_ENCODER_value(encoders, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !OSSL_ENCODER_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && OSSL_ENCODER_names_do_all(k, collect_names, names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s (%s)\n", + OSSL_PROVIDER_get0_name(OSSL_ENCODER_get0_provider(k)), + OSSL_ENCODER_get0_properties(k)); + + if (verbose) { + const char *desc = OSSL_ENCODER_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("settable operation parameters", + OSSL_ENCODER_settable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_OSSL_ENCODER_pop_free(encoders, OSSL_ENCODER_free); +} + +/* + * Decoders + */ +DEFINE_STACK_OF(OSSL_DECODER) +static int decoder_cmp(const OSSL_DECODER * const *a, + const OSSL_DECODER * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(*a)), + OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(*b))); +} + +static void collect_decoders(OSSL_DECODER *decoder, void *stack) +{ + STACK_OF(OSSL_DECODER) *decoder_stack = stack; + + if (is_decoder_fetchable(decoder) + && sk_OSSL_DECODER_push(decoder_stack, decoder) > 0) + OSSL_DECODER_up_ref(decoder); +} + +static void list_decoders(void) +{ + STACK_OF(OSSL_DECODER) *decoders; + int i; + + decoders = sk_OSSL_DECODER_new(decoder_cmp); + if (decoders == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Provided DECODERs:\n"); + OSSL_DECODER_do_all_provided(app_get0_libctx(), collect_decoders, + decoders); + sk_OSSL_DECODER_sort(decoders); + + for (i = 0; i < sk_OSSL_DECODER_num(decoders); i++) { + OSSL_DECODER *k = sk_OSSL_DECODER_value(decoders, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !OSSL_DECODER_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && OSSL_DECODER_names_do_all(k, collect_names, names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s (%s)\n", + OSSL_PROVIDER_get0_name(OSSL_DECODER_get0_provider(k)), + OSSL_DECODER_get0_properties(k)); + + if (verbose) { + const char *desc = OSSL_DECODER_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("settable operation parameters", + OSSL_DECODER_settable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_OSSL_DECODER_pop_free(decoders, OSSL_DECODER_free); +} + +DEFINE_STACK_OF(EVP_KEYMGMT) +static int keymanager_cmp(const EVP_KEYMGMT * const *a, + const EVP_KEYMGMT * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(*b))); +} + +static void collect_keymanagers(EVP_KEYMGMT *km, void *stack) +{ + STACK_OF(EVP_KEYMGMT) *km_stack = stack; + + if (is_keymgmt_fetchable(km) + && sk_EVP_KEYMGMT_push(km_stack, km) > 0) + EVP_KEYMGMT_up_ref(km); +} + +static void list_keymanagers(void) +{ + int i; + STACK_OF(EVP_KEYMGMT) *km_stack = sk_EVP_KEYMGMT_new(keymanager_cmp); + + EVP_KEYMGMT_do_all_provided(app_get0_libctx(), collect_keymanagers, + km_stack); + sk_EVP_KEYMGMT_sort(km_stack); + + for (i = 0; i < sk_EVP_KEYMGMT_num(km_stack); i++) { + EVP_KEYMGMT *k = sk_EVP_KEYMGMT_value(km_stack, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_KEYMGMT_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_KEYMGMT_names_do_all(k, collect_names, names)) { + const char *desc = EVP_KEYMGMT_get0_description(k); + + BIO_printf(bio_out, " Name: "); + if (desc != NULL) + BIO_printf(bio_out, "%s", desc); + else + BIO_printf(bio_out, "%s", sk_OPENSSL_CSTRING_value(names, 0)); + BIO_printf(bio_out, "\n"); + BIO_printf(bio_out, " Type: Provider Algorithm\n"); + BIO_printf(bio_out, " IDs: "); + print_names(bio_out, names); + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_KEYMGMT_get0_provider(k))); + + if (verbose) { + print_param_types("settable key generation parameters", + EVP_KEYMGMT_gen_settable_params(k), 4); + print_param_types("settable operation parameters", + EVP_KEYMGMT_settable_params(k), 4); + print_param_types("retrievable operation parameters", + EVP_KEYMGMT_gettable_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_KEYMGMT_pop_free(km_stack, EVP_KEYMGMT_free); +} + +DEFINE_STACK_OF(EVP_SIGNATURE) +static int signature_cmp(const EVP_SIGNATURE * const *a, + const EVP_SIGNATURE * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*b))); +} + +static void collect_signatures(EVP_SIGNATURE *sig, void *stack) +{ + STACK_OF(EVP_SIGNATURE) *sig_stack = stack; + + if (is_signature_fetchable(sig) + && sk_EVP_SIGNATURE_push(sig_stack, sig) > 0) + EVP_SIGNATURE_up_ref(sig); +} + +static void list_signatures(void) +{ + int i, count = 0; + STACK_OF(EVP_SIGNATURE) *sig_stack = sk_EVP_SIGNATURE_new(signature_cmp); + + EVP_SIGNATURE_do_all_provided(app_get0_libctx(), collect_signatures, + sig_stack); + sk_EVP_SIGNATURE_sort(sig_stack); + + for (i = 0; i < sk_EVP_SIGNATURE_num(sig_stack); i++) { + EVP_SIGNATURE *k = sk_EVP_SIGNATURE_value(sig_stack, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_SIGNATURE_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_SIGNATURE_names_do_all(k, collect_names, names)) { + count++; + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(k))); + + if (verbose) { + const char *desc = EVP_SIGNATURE_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("settable operation parameters", + EVP_SIGNATURE_settable_ctx_params(k), 4); + print_param_types("retrievable operation parameters", + EVP_SIGNATURE_gettable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_SIGNATURE_pop_free(sig_stack, EVP_SIGNATURE_free); + if (count == 0) + BIO_printf(bio_out, " -\n"); +} + +DEFINE_STACK_OF(EVP_KEM) +static int kem_cmp(const EVP_KEM * const *a, + const EVP_KEM * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*b))); +} + +static void collect_kem(EVP_KEM *kem, void *stack) +{ + STACK_OF(EVP_KEM) *kem_stack = stack; + + if (is_kem_fetchable(kem) + && sk_EVP_KEM_push(kem_stack, kem) > 0) + EVP_KEM_up_ref(kem); +} + +static void list_kems(void) +{ + int i, count = 0; + STACK_OF(EVP_KEM) *kem_stack = sk_EVP_KEM_new(kem_cmp); + + EVP_KEM_do_all_provided(app_get0_libctx(), collect_kem, kem_stack); + sk_EVP_KEM_sort(kem_stack); + + for (i = 0; i < sk_EVP_KEM_num(kem_stack); i++) { + EVP_KEM *k = sk_EVP_KEM_value(kem_stack, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_KEM_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_KEM_names_do_all(k, collect_names, names)) { + count++; + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(k))); + + if (verbose) { + const char *desc = EVP_KEM_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("settable operation parameters", + EVP_KEM_settable_ctx_params(k), 4); + print_param_types("retrievable operation parameters", + EVP_KEM_gettable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_KEM_pop_free(kem_stack, EVP_KEM_free); + if (count == 0) + BIO_printf(bio_out, " -\n"); +} + +DEFINE_STACK_OF(EVP_ASYM_CIPHER) +static int asymcipher_cmp(const EVP_ASYM_CIPHER * const *a, + const EVP_ASYM_CIPHER * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(*b))); +} + +static void collect_asymciph(EVP_ASYM_CIPHER *asym_cipher, void *stack) +{ + STACK_OF(EVP_ASYM_CIPHER) *asym_cipher_stack = stack; + + if (is_asym_cipher_fetchable(asym_cipher) + && sk_EVP_ASYM_CIPHER_push(asym_cipher_stack, asym_cipher) > 0) + EVP_ASYM_CIPHER_up_ref(asym_cipher); +} + +static void list_asymciphers(void) +{ + int i, count = 0; + STACK_OF(EVP_ASYM_CIPHER) *asymciph_stack = + sk_EVP_ASYM_CIPHER_new(asymcipher_cmp); + + EVP_ASYM_CIPHER_do_all_provided(app_get0_libctx(), collect_asymciph, + asymciph_stack); + sk_EVP_ASYM_CIPHER_sort(asymciph_stack); + + for (i = 0; i < sk_EVP_ASYM_CIPHER_num(asymciph_stack); i++) { + EVP_ASYM_CIPHER *k = sk_EVP_ASYM_CIPHER_value(asymciph_stack, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_ASYM_CIPHER_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL + && EVP_ASYM_CIPHER_names_do_all(k, collect_names, names)) { + count++; + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_ASYM_CIPHER_get0_provider(k))); + + if (verbose) { + const char *desc = EVP_ASYM_CIPHER_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("settable operation parameters", + EVP_ASYM_CIPHER_settable_ctx_params(k), 4); + print_param_types("retrievable operation parameters", + EVP_ASYM_CIPHER_gettable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_ASYM_CIPHER_pop_free(asymciph_stack, EVP_ASYM_CIPHER_free); + if (count == 0) + BIO_printf(bio_out, " -\n"); +} + +DEFINE_STACK_OF(EVP_KEYEXCH) +static int kex_cmp(const EVP_KEYEXCH * const *a, + const EVP_KEYEXCH * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(*b))); +} + +static void collect_kex(EVP_KEYEXCH *kex, void *stack) +{ + STACK_OF(EVP_KEYEXCH) *kex_stack = stack; + + if (is_keyexch_fetchable(kex) + && sk_EVP_KEYEXCH_push(kex_stack, kex) > 0) + EVP_KEYEXCH_up_ref(kex); +} + +static void list_keyexchanges(void) +{ + int i, count = 0; + STACK_OF(EVP_KEYEXCH) *kex_stack = sk_EVP_KEYEXCH_new(kex_cmp); + + EVP_KEYEXCH_do_all_provided(app_get0_libctx(), collect_kex, kex_stack); + sk_EVP_KEYEXCH_sort(kex_stack); + + for (i = 0; i < sk_EVP_KEYEXCH_num(kex_stack); i++) { + EVP_KEYEXCH *k = sk_EVP_KEYEXCH_value(kex_stack, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_KEYEXCH_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_KEYEXCH_names_do_all(k, collect_names, names)) { + count++; + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_KEYEXCH_get0_provider(k))); + + if (verbose) { + const char *desc = EVP_KEYEXCH_get0_description(k); + + if (desc != NULL) + BIO_printf(bio_out, " description: %s\n", desc); + print_param_types("settable operation parameters", + EVP_KEYEXCH_settable_ctx_params(k), 4); + print_param_types("retrievable operation parameters", + EVP_KEYEXCH_gettable_ctx_params(k), 4); + } + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_KEYEXCH_pop_free(kex_stack, EVP_KEYEXCH_free); + if (count == 0) + BIO_printf(bio_out, " -\n"); +} + +static void list_objects(void) +{ + int max_nid = OBJ_new_nid(0); + int i; + char *oid_buf = NULL; + int oid_size = 0; + + /* Skip 0, since that's NID_undef */ + for (i = 1; i < max_nid; i++) { + const ASN1_OBJECT *obj = OBJ_nid2obj(i); + const char *sn = OBJ_nid2sn(i); + const char *ln = OBJ_nid2ln(i); + int n = 0; + + /* + * If one of the retrieved objects somehow generated an error, + * we ignore it. The check for NID_undef below will detect the + * error and simply skip to the next NID. + */ + ERR_clear_error(); + + if (OBJ_obj2nid(obj) == NID_undef) + continue; + + if ((n = OBJ_obj2txt(NULL, 0, obj, 1)) == 0) { + BIO_printf(bio_out, "# None-OID object: %s, %s\n", sn, ln); + continue; + } + if (n < 0) + break; /* Error */ + + if (n > oid_size) { + oid_buf = OPENSSL_realloc(oid_buf, n + 1); + if (oid_buf == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + break; /* Error */ + } + oid_size = n + 1; + } + if (OBJ_obj2txt(oid_buf, oid_size, obj, 1) < 0) + break; /* Error */ + if (ln == NULL || strcmp(sn, ln) == 0) + BIO_printf(bio_out, "%s = %s\n", sn, oid_buf); + else + BIO_printf(bio_out, "%s = %s, %s\n", sn, ln, oid_buf); + } + + OPENSSL_free(oid_buf); +} + +static void list_options_for_command(const char *command) +{ + const FUNCTION *fp; + const OPTIONS *o; + + for (fp = functions; fp->name != NULL; fp++) + if (strcmp(fp->name, command) == 0) + break; + if (fp->name == NULL) { + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", + command); + return; + } + + if ((o = fp->help) == NULL) + return; + + for ( ; o->name != NULL; o++) { + char c = o->valtype; + + if (o->name == OPT_PARAM_STR) + break; + + if (o->name == OPT_HELP_STR + || o->name == OPT_MORE_STR + || o->name == OPT_SECTION_STR + || o->name[0] == '\0') + continue; + BIO_printf(bio_out, "%s %c\n", o->name, c == '\0' ? '-' : c); + } + /* Always output the -- marker since it is sometimes documented. */ + BIO_printf(bio_out, "- -\n"); +} + +static int is_md_available(const char *name) +{ + EVP_MD *md; + const char *propq = app_get0_propq(); + + /* Look through providers' digests */ + ERR_set_mark(); + md = EVP_MD_fetch(app_get0_libctx(), name, propq); + ERR_pop_to_mark(); + if (md != NULL) { + EVP_MD_free(md); + return 1; + } + + return propq != NULL || get_digest_from_engine(name) == NULL ? 0 : 1; +} + +static int is_cipher_available(const char *name) +{ + EVP_CIPHER *cipher; + const char *propq = app_get0_propq(); + + /* Look through providers' ciphers */ + ERR_set_mark(); + cipher = EVP_CIPHER_fetch(app_get0_libctx(), name, propq); + ERR_pop_to_mark(); + if (cipher != NULL) { + EVP_CIPHER_free(cipher); + return 1; + } + + return propq != NULL || get_cipher_from_engine(name) == NULL ? 0 : 1; +} + +static void list_type(FUNC_TYPE ft, int one) +{ + FUNCTION *fp; + int i = 0; + DISPLAY_COLUMNS dc; + + memset(&dc, 0, sizeof(dc)); + if (!one) + calculate_columns(functions, &dc); + + for (fp = functions; fp->name != NULL; fp++) { + if (fp->type != ft) + continue; + switch (ft) { + case FT_cipher: + if (!is_cipher_available(fp->name)) + continue; + break; + case FT_md: + if (!is_md_available(fp->name)) + continue; + break; + default: + break; + } + if (one) { + BIO_printf(bio_out, "%s\n", fp->name); + } else { + if (i % dc.columns == 0 && i > 0) + BIO_printf(bio_out, "\n"); + BIO_printf(bio_out, "%-*s", dc.width, fp->name); + i++; + } + } + if (!one) + BIO_printf(bio_out, "\n\n"); +} + +static void list_pkey(void) +{ +#ifndef OPENSSL_NO_DEPRECATED_3_0 + int i; + + if (select_name == NULL && include_legacy()) { + BIO_printf(bio_out, "Legacy:\n"); + for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { + const EVP_PKEY_ASN1_METHOD *ameth; + int pkey_id, pkey_base_id, pkey_flags; + const char *pinfo, *pem_str; + ameth = EVP_PKEY_asn1_get0(i); + EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, + &pinfo, &pem_str, ameth); + if (pkey_flags & ASN1_PKEY_ALIAS) { + BIO_printf(bio_out, " Name: %s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tAlias for: %s\n", + OBJ_nid2ln(pkey_base_id)); + } else { + BIO_printf(bio_out, " Name: %s\n", pinfo); + BIO_printf(bio_out, "\tType: %s Algorithm\n", + pkey_flags & ASN1_PKEY_DYNAMIC ? + "External" : "Builtin"); + BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); + if (pem_str == NULL) + pem_str = "(none)"; + BIO_printf(bio_out, "\tPEM string: %s\n", pem_str); + } + } + } +#endif + BIO_printf(bio_out, "Provided:\n"); + BIO_printf(bio_out, " Key Managers:\n"); + list_keymanagers(); +} + +static void list_pkey_meth(void) +{ +#ifndef OPENSSL_NO_DEPRECATED_3_0 + size_t i; + size_t meth_count = EVP_PKEY_meth_get_count(); + + if (select_name == NULL && include_legacy()) { + BIO_printf(bio_out, "Legacy:\n"); + for (i = 0; i < meth_count; i++) { + const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i); + int pkey_id, pkey_flags; + + EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth); + BIO_printf(bio_out, " %s\n", OBJ_nid2ln(pkey_id)); + BIO_printf(bio_out, "\tType: %s Algorithm\n", + pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin"); + } + } +#endif + BIO_printf(bio_out, "Provided:\n"); + BIO_printf(bio_out, " Encryption:\n"); + list_asymciphers(); + BIO_printf(bio_out, " Key Exchange:\n"); + list_keyexchanges(); + BIO_printf(bio_out, " Signatures:\n"); + list_signatures(); + BIO_printf(bio_out, " Key encapsulation:\n"); + list_kems(); +} + +DEFINE_STACK_OF(OSSL_STORE_LOADER) +static int store_cmp(const OSSL_STORE_LOADER * const *a, + const OSSL_STORE_LOADER * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(*a)), + OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(*b))); +} + +static void collect_store_loaders(OSSL_STORE_LOADER *store, void *stack) +{ + STACK_OF(OSSL_STORE_LOADER) *store_stack = stack; + + if (sk_OSSL_STORE_LOADER_push(store_stack, store) > 0) + OSSL_STORE_LOADER_up_ref(store); +} + +static void list_store_loaders(void) +{ + STACK_OF(OSSL_STORE_LOADER) *stores = sk_OSSL_STORE_LOADER_new(store_cmp); + int i; + + if (stores == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Provided STORE LOADERs:\n"); + OSSL_STORE_LOADER_do_all_provided(app_get0_libctx(), collect_store_loaders, + stores); + sk_OSSL_STORE_LOADER_sort(stores); + for (i = 0; i < sk_OSSL_STORE_LOADER_num(stores); i++) { + const OSSL_STORE_LOADER *m = sk_OSSL_STORE_LOADER_value(stores, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !OSSL_STORE_LOADER_is_a(m, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && OSSL_STORE_LOADER_names_do_all(m, collect_names, + names)) { + BIO_printf(bio_out, " "); + print_names(bio_out, names); + + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(OSSL_STORE_LOADER_get0_provider(m))); + } + sk_OPENSSL_CSTRING_free(names); + } + sk_OSSL_STORE_LOADER_pop_free(stores, OSSL_STORE_LOADER_free); +} + +DEFINE_STACK_OF(OSSL_PROVIDER) +static int provider_cmp(const OSSL_PROVIDER * const *a, + const OSSL_PROVIDER * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(*a), OSSL_PROVIDER_get0_name(*b)); +} + +static int collect_providers(OSSL_PROVIDER *provider, void *stack) +{ + STACK_OF(OSSL_PROVIDER) *provider_stack = stack; + + sk_OSSL_PROVIDER_push(provider_stack, provider); + return 1; +} + +static void list_provider_info(void) +{ + STACK_OF(OSSL_PROVIDER) *providers = sk_OSSL_PROVIDER_new(provider_cmp); + OSSL_PARAM params[5]; + char *name, *version, *buildinfo; + int status; + int i; + + if (providers == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + BIO_printf(bio_out, "Providers:\n"); + OSSL_PROVIDER_do_all(NULL, &collect_providers, providers); + sk_OSSL_PROVIDER_sort(providers); + for (i = 0; i < sk_OSSL_PROVIDER_num(providers); i++) { + const OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(providers, i); + + /* Query the "known" information parameters, the order matches below */ + params[0] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_NAME, + &name, 0); + params[1] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION, + &version, 0); + params[2] = OSSL_PARAM_construct_int(OSSL_PROV_PARAM_STATUS, &status); + params[3] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_BUILDINFO, + &buildinfo, 0); + params[4] = OSSL_PARAM_construct_end(); + OSSL_PARAM_set_all_unmodified(params); + if (!OSSL_PROVIDER_get_params(prov, params)) { + BIO_printf(bio_err, "ERROR: Unable to query provider parameters\n"); + return; + } + + /* Print out the provider information, the params order matches above */ + BIO_printf(bio_out, " %s\n", OSSL_PROVIDER_get0_name(prov)); + if (OSSL_PARAM_modified(params)) + BIO_printf(bio_out, " name: %s\n", name); + if (OSSL_PARAM_modified(params + 1)) + BIO_printf(bio_out, " version: %s\n", version); + if (OSSL_PARAM_modified(params + 2)) + BIO_printf(bio_out, " status: %sactive\n", status ? "" : "in"); + if (verbose) { + if (OSSL_PARAM_modified(params + 3)) + BIO_printf(bio_out, " build info: %s\n", buildinfo); + print_param_types("gettable provider parameters", + OSSL_PROVIDER_gettable_params(prov), 4); + } + } + sk_OSSL_PROVIDER_free(providers); +} + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +static void list_engines(void) +{ +# ifndef OPENSSL_NO_ENGINE + ENGINE *e; + + BIO_puts(bio_out, "Engines:\n"); + e = ENGINE_get_first(); + while (e) { + BIO_printf(bio_out, "%s\n", ENGINE_get_id(e)); + e = ENGINE_get_next(e); + } +# else + BIO_puts(bio_out, "Engine support is disabled.\n"); +# endif +} +#endif + +static void list_disabled(void) +{ + BIO_puts(bio_out, "Disabled algorithms:\n"); +#ifdef OPENSSL_NO_ARIA + BIO_puts(bio_out, "ARIA\n"); +#endif +#ifdef OPENSSL_NO_BF + BIO_puts(bio_out, "BF\n"); +#endif +#ifdef OPENSSL_NO_BLAKE2 + BIO_puts(bio_out, "BLAKE2\n"); +#endif +#ifdef OPENSSL_NO_CAMELLIA + BIO_puts(bio_out, "CAMELLIA\n"); +#endif +#ifdef OPENSSL_NO_CAST + BIO_puts(bio_out, "CAST\n"); +#endif +#ifdef OPENSSL_NO_CMAC + BIO_puts(bio_out, "CMAC\n"); +#endif +#ifdef OPENSSL_NO_CMS + BIO_puts(bio_out, "CMS\n"); +#endif +#ifdef OPENSSL_NO_COMP + BIO_puts(bio_out, "COMP\n"); +#endif +#ifdef OPENSSL_NO_DES + BIO_puts(bio_out, "DES\n"); +#endif +#ifdef OPENSSL_NO_DGRAM + BIO_puts(bio_out, "DGRAM\n"); +#endif +#ifdef OPENSSL_NO_DH + BIO_puts(bio_out, "DH\n"); +#endif +#ifdef OPENSSL_NO_DSA + BIO_puts(bio_out, "DSA\n"); +#endif +#if defined(OPENSSL_NO_DTLS) + BIO_puts(bio_out, "DTLS\n"); +#endif +#if defined(OPENSSL_NO_DTLS1) + BIO_puts(bio_out, "DTLS1\n"); +#endif +#if defined(OPENSSL_NO_DTLS1_2) + BIO_puts(bio_out, "DTLS1_2\n"); +#endif +#ifdef OPENSSL_NO_EC + BIO_puts(bio_out, "EC\n"); +#endif +#ifdef OPENSSL_NO_EC2M + BIO_puts(bio_out, "EC2M\n"); +#endif +#if defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) + BIO_puts(bio_out, "ENGINE\n"); +#endif +#ifdef OPENSSL_NO_GOST + BIO_puts(bio_out, "GOST\n"); +#endif +#ifdef OPENSSL_NO_IDEA + BIO_puts(bio_out, "IDEA\n"); +#endif +#ifdef OPENSSL_NO_MD2 + BIO_puts(bio_out, "MD2\n"); +#endif +#ifdef OPENSSL_NO_MD4 + BIO_puts(bio_out, "MD4\n"); +#endif +#ifdef OPENSSL_NO_MD5 + BIO_puts(bio_out, "MD5\n"); +#endif +#ifdef OPENSSL_NO_MDC2 + BIO_puts(bio_out, "MDC2\n"); +#endif +#ifdef OPENSSL_NO_OCB + BIO_puts(bio_out, "OCB\n"); +#endif +#ifdef OPENSSL_NO_OCSP + BIO_puts(bio_out, "OCSP\n"); +#endif +#ifdef OPENSSL_NO_PSK + BIO_puts(bio_out, "PSK\n"); +#endif +#ifdef OPENSSL_NO_RC2 + BIO_puts(bio_out, "RC2\n"); +#endif +#ifdef OPENSSL_NO_RC4 + BIO_puts(bio_out, "RC4\n"); +#endif +#ifdef OPENSSL_NO_RC5 + BIO_puts(bio_out, "RC5\n"); +#endif +#ifdef OPENSSL_NO_RMD160 + BIO_puts(bio_out, "RMD160\n"); +#endif +#ifdef OPENSSL_NO_SCRYPT + BIO_puts(bio_out, "SCRYPT\n"); +#endif +#ifdef OPENSSL_NO_SCTP + BIO_puts(bio_out, "SCTP\n"); +#endif +#ifdef OPENSSL_NO_SEED + BIO_puts(bio_out, "SEED\n"); +#endif +#ifdef OPENSSL_NO_SM2 + BIO_puts(bio_out, "SM2\n"); +#endif +#ifdef OPENSSL_NO_SM3 + BIO_puts(bio_out, "SM3\n"); +#endif +#ifdef OPENSSL_NO_SM4 + BIO_puts(bio_out, "SM4\n"); +#endif +#ifdef OPENSSL_NO_SOCK + BIO_puts(bio_out, "SOCK\n"); +#endif +#ifdef OPENSSL_NO_SRP + BIO_puts(bio_out, "SRP\n"); +#endif +#ifdef OPENSSL_NO_SRTP + BIO_puts(bio_out, "SRTP\n"); +#endif +#ifdef OPENSSL_NO_SSL3 + BIO_puts(bio_out, "SSL3\n"); +#endif +#ifdef OPENSSL_NO_TLS1 + BIO_puts(bio_out, "TLS1\n"); +#endif +#ifdef OPENSSL_NO_TLS1_1 + BIO_puts(bio_out, "TLS1_1\n"); +#endif +#ifdef OPENSSL_NO_TLS1_2 + BIO_puts(bio_out, "TLS1_2\n"); +#endif +#ifdef OPENSSL_NO_WHIRLPOOL + BIO_puts(bio_out, "WHIRLPOOL\n"); +#endif +#ifndef ZLIB + BIO_puts(bio_out, "ZLIB\n"); +#endif +} + +/* Unified enum for help and list commands. */ +typedef enum HELPLIST_CHOICE { + OPT_COMMON, + OPT_ONE, OPT_VERBOSE, + OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS, + OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS, + OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, + OPT_KDF_ALGORITHMS, OPT_RANDOM_INSTANCES, OPT_RANDOM_GENERATORS, + OPT_ENCODERS, OPT_DECODERS, OPT_KEYMANAGERS, OPT_KEYEXCHANGE_ALGORITHMS, + OPT_KEM_ALGORITHMS, OPT_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS, + OPT_STORE_LOADERS, OPT_PROVIDER_INFO, + OPT_OBJECTS, OPT_SELECT_NAME, +#ifndef OPENSSL_NO_DEPRECATED_3_0 + OPT_ENGINES, +#endif + OPT_PROV_ENUM +} HELPLIST_CHOICE; + +const OPTIONS list_options[] = { + + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Output"), + {"1", OPT_ONE, '-', "List in one column"}, + {"verbose", OPT_VERBOSE, '-', "Verbose listing"}, + {"select", OPT_SELECT_NAME, 's', "Select a single algorithm"}, + {"commands", OPT_COMMANDS, '-', "List of standard commands"}, + {"standard-commands", OPT_COMMANDS, '-', "List of standard commands"}, +#ifndef OPENSSL_NO_DEPRECATED_3_0 + {"digest-commands", OPT_DIGEST_COMMANDS, '-', + "List of message digest commands (deprecated)"}, +#endif + {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-', + "List of message digest algorithms"}, + {"kdf-algorithms", OPT_KDF_ALGORITHMS, '-', + "List of key derivation and pseudo random function algorithms"}, + {"random-instances", OPT_RANDOM_INSTANCES, '-', + "List the primary, public and private random number generator details"}, + {"random-generators", OPT_RANDOM_GENERATORS, '-', + "List of random number generators"}, + {"mac-algorithms", OPT_MAC_ALGORITHMS, '-', + "List of message authentication code algorithms"}, +#ifndef OPENSSL_NO_DEPRECATED_3_0 + {"cipher-commands", OPT_CIPHER_COMMANDS, '-', + "List of cipher commands (deprecated)"}, +#endif + {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-', + "List of symmetric cipher algorithms"}, + {"encoders", OPT_ENCODERS, '-', "List of encoding methods" }, + {"decoders", OPT_DECODERS, '-', "List of decoding methods" }, + {"key-managers", OPT_KEYMANAGERS, '-', "List of key managers" }, + {"key-exchange-algorithms", OPT_KEYEXCHANGE_ALGORITHMS, '-', + "List of key exchange algorithms" }, + {"kem-algorithms", OPT_KEM_ALGORITHMS, '-', + "List of key encapsulation mechanism algorithms" }, + {"signature-algorithms", OPT_SIGNATURE_ALGORITHMS, '-', + "List of signature algorithms" }, + {"asymcipher-algorithms", OPT_ASYM_CIPHER_ALGORITHMS, '-', + "List of asymmetric cipher algorithms" }, + {"public-key-algorithms", OPT_PK_ALGORITHMS, '-', + "List of public key algorithms"}, + {"public-key-methods", OPT_PK_METHOD, '-', + "List of public key methods"}, + {"store-loaders", OPT_STORE_LOADERS, '-', + "List of store loaders"}, + {"providers", OPT_PROVIDER_INFO, '-', + "List of provider information"}, +#ifndef OPENSSL_NO_DEPRECATED_3_0 + {"engines", OPT_ENGINES, '-', + "List of loaded engines"}, +#endif + {"disabled", OPT_DISABLED, '-', "List of disabled features"}, + {"options", OPT_OPTIONS, 's', + "List options for specified command"}, + {"objects", OPT_OBJECTS, '-', + "List built in objects (OID<->name mappings)"}, + + OPT_PROV_OPTIONS, + {NULL} +}; + +int list_main(int argc, char **argv) +{ + char *prog; + HELPLIST_CHOICE o; + int one = 0, done = 0; + struct { + unsigned int commands:1; + unsigned int random_instances:1; + unsigned int random_generators:1; + unsigned int digest_commands:1; + unsigned int digest_algorithms:1; + unsigned int kdf_algorithms:1; + unsigned int mac_algorithms:1; + unsigned int cipher_commands:1; + unsigned int cipher_algorithms:1; + unsigned int encoder_algorithms:1; + unsigned int decoder_algorithms:1; + unsigned int keymanager_algorithms:1; + unsigned int signature_algorithms:1; + unsigned int keyexchange_algorithms:1; + unsigned int kem_algorithms:1; + unsigned int asym_cipher_algorithms:1; + unsigned int pk_algorithms:1; + unsigned int pk_method:1; + unsigned int store_loaders:1; + unsigned int provider_info:1; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + unsigned int engines:1; +#endif + unsigned int disabled:1; + unsigned int objects:1; + unsigned int options:1; + } todo = { 0, }; + + verbose = 0; /* Clear a possible previous call */ + + prog = opt_init(argc, argv, list_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: /* Never hit, but suppresses warning */ + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + return 1; + case OPT_HELP: + opt_help(list_options); + return 0; + case OPT_ONE: + one = 1; + break; + case OPT_COMMANDS: + todo.commands = 1; + break; + case OPT_DIGEST_COMMANDS: + todo.digest_commands = 1; + break; + case OPT_DIGEST_ALGORITHMS: + todo.digest_algorithms = 1; + break; + case OPT_KDF_ALGORITHMS: + todo.kdf_algorithms = 1; + break; + case OPT_RANDOM_INSTANCES: + todo.random_instances = 1; + break; + case OPT_RANDOM_GENERATORS: + todo.random_generators = 1; + break; + case OPT_MAC_ALGORITHMS: + todo.mac_algorithms = 1; + break; + case OPT_CIPHER_COMMANDS: + todo.cipher_commands = 1; + break; + case OPT_CIPHER_ALGORITHMS: + todo.cipher_algorithms = 1; + break; + case OPT_ENCODERS: + todo.encoder_algorithms = 1; + break; + case OPT_DECODERS: + todo.decoder_algorithms = 1; + break; + case OPT_KEYMANAGERS: + todo.keymanager_algorithms = 1; + break; + case OPT_SIGNATURE_ALGORITHMS: + todo.signature_algorithms = 1; + break; + case OPT_KEYEXCHANGE_ALGORITHMS: + todo.keyexchange_algorithms = 1; + break; + case OPT_KEM_ALGORITHMS: + todo.kem_algorithms = 1; + break; + case OPT_ASYM_CIPHER_ALGORITHMS: + todo.asym_cipher_algorithms = 1; + break; + case OPT_PK_ALGORITHMS: + todo.pk_algorithms = 1; + break; + case OPT_PK_METHOD: + todo.pk_method = 1; + break; + case OPT_STORE_LOADERS: + todo.store_loaders = 1; + break; + case OPT_PROVIDER_INFO: + todo.provider_info = 1; + break; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + case OPT_ENGINES: + todo.engines = 1; + break; +#endif + case OPT_DISABLED: + todo.disabled = 1; + break; + case OPT_OBJECTS: + todo.objects = 1; + break; + case OPT_OPTIONS: + list_options_for_command(opt_arg()); + break; + case OPT_VERBOSE: + verbose = 1; + break; + case OPT_SELECT_NAME: + select_name = opt_arg(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + return 1; + break; + } + done = 1; + } + + /* No extra arguments. */ + if (opt_num_rest() != 0) + goto opthelp; + + if (todo.commands) + list_type(FT_general, one); + if (todo.random_instances) + list_random_instances(); + if (todo.random_generators) + list_random_generators(); + if (todo.digest_commands) + list_type(FT_md, one); + if (todo.digest_algorithms) + list_digests(); + if (todo.kdf_algorithms) + list_kdfs(); + if (todo.mac_algorithms) + list_macs(); + if (todo.cipher_commands) + list_type(FT_cipher, one); + if (todo.cipher_algorithms) + list_ciphers(); + if (todo.encoder_algorithms) + list_encoders(); + if (todo.decoder_algorithms) + list_decoders(); + if (todo.keymanager_algorithms) + list_keymanagers(); + if (todo.signature_algorithms) + list_signatures(); + if (todo.asym_cipher_algorithms) + list_asymciphers(); + if (todo.keyexchange_algorithms) + list_keyexchanges(); + if (todo.kem_algorithms) + list_kems(); + if (todo.pk_algorithms) + list_pkey(); + if (todo.pk_method) + list_pkey_meth(); + if (todo.store_loaders) + list_store_loaders(); + if (todo.provider_info) + list_provider_info(); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (todo.engines) + list_engines(); +#endif + if (todo.disabled) + list_disabled(); + if (todo.objects) + list_objects(); + + if (!done) + goto opthelp; + + return 0; +} diff --git a/apps/mac.c b/apps/mac.c new file mode 100644 --- /dev/null +++ b/apps/mac.c @@ -0,0 +1,237 @@ +/* + * Copyright 2018-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include + +#include "apps.h" +#include "progs.h" +#include +#include +#include +#include +#include + +#undef BUFSIZE +#define BUFSIZE 1024*8 + +typedef enum OPTION_choice { + OPT_COMMON, + OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT, + OPT_CIPHER, OPT_DIGEST, + OPT_PROV_ENUM +} OPTION_CHOICE; + +const OPTIONS mac_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] mac_name\n"}, + + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form"}, + {"cipher", OPT_CIPHER, 's', "Cipher"}, + {"digest", OPT_DIGEST, 's', "Digest"}, + {OPT_MORE_STR, 1, '-', "See 'PARAMETER NAMES' in the EVP_MAC_ docs"}, + + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input file to MAC (default is stdin)"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, + {"binary", OPT_BIN, '-', + "Output in binary format (default is hexadecimal)"}, + + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"mac_name", 0, 0, "MAC algorithm"}, + {NULL} +}; + +static char *alloc_mac_algorithm_name(STACK_OF(OPENSSL_STRING) **optp, + const char *name, const char *arg) +{ + size_t len = strlen(name) + strlen(arg) + 2; + char *res; + + if (*optp == NULL) + *optp = sk_OPENSSL_STRING_new_null(); + if (*optp == NULL) + return NULL; + + res = app_malloc(len, "algorithm name"); + BIO_snprintf(res, len, "%s:%s", name, arg); + if (sk_OPENSSL_STRING_push(*optp, res)) + return res; + OPENSSL_free(res); + return NULL; +} + +int mac_main(int argc, char **argv) +{ + int ret = 1; + char *prog; + EVP_MAC *mac = NULL; + OPTION_CHOICE o; + EVP_MAC_CTX *ctx = NULL; + STACK_OF(OPENSSL_STRING) *opts = NULL; + unsigned char *buf = NULL; + size_t len; + int i; + BIO *in = NULL, *out = NULL; + const char *outfile = NULL; + const char *infile = NULL; + int out_bin = 0; + int inform = FORMAT_BINARY; + char *digest = NULL, *cipher = NULL; + OSSL_PARAM *params = NULL; + + prog = opt_init(argc, argv, mac_options); + buf = app_malloc(BUFSIZE, "I/O buffer"); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + default: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto err; + case OPT_HELP: + opt_help(mac_options); + ret = 0; + goto err; + case OPT_BIN: + out_bin = 1; + break; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_MACOPT: + if (opts == NULL) + opts = sk_OPENSSL_STRING_new_null(); + if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) + goto opthelp; + break; + case OPT_CIPHER: + OPENSSL_free(cipher); + cipher = alloc_mac_algorithm_name(&opts, "cipher", opt_arg()); + if (cipher == NULL) + goto opthelp; + break; + case OPT_DIGEST: + OPENSSL_free(digest); + digest = alloc_mac_algorithm_name(&opts, "digest", opt_arg()); + if (digest == NULL) + goto opthelp; + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto err; + break; + } + } + + /* One argument, the MAC name. */ + argc = opt_num_rest(); + argv = opt_rest(); + if (argc != 1) + goto opthelp; + + mac = EVP_MAC_fetch(app_get0_libctx(), argv[0], app_get0_propq()); + if (mac == NULL) { + BIO_printf(bio_err, "Invalid MAC name %s\n", argv[0]); + goto opthelp; + } + + ctx = EVP_MAC_CTX_new(mac); + if (ctx == NULL) + goto err; + + if (opts != NULL) { + int ok = 1; + + params = app_params_new_from_opts(opts, + EVP_MAC_settable_ctx_params(mac)); + if (params == NULL) + goto err; + + if (!EVP_MAC_CTX_set_params(ctx, params)) { + BIO_printf(bio_err, "MAC parameter error\n"); + ERR_print_errors(bio_err); + ok = 0; + } + app_params_free(params); + if (!ok) + goto err; + } + + in = bio_open_default(infile, 'r', inform); + if (in == NULL) + goto err; + + out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); + if (out == NULL) + goto err; + + if (!EVP_MAC_init(ctx, NULL, 0, NULL)) { + BIO_printf(bio_err, "EVP_MAC_Init failed\n"); + goto err; + } + + while (BIO_pending(in) || !BIO_eof(in)) { + i = BIO_read(in, (char *)buf, BUFSIZE); + if (i < 0) { + BIO_printf(bio_err, "Read Error in '%s'\n", infile); + ERR_print_errors(bio_err); + goto err; + } + if (i == 0) + break; + if (!EVP_MAC_update(ctx, buf, i)) { + BIO_printf(bio_err, "EVP_MAC_update failed\n"); + goto err; + } + } + + if (!EVP_MAC_final(ctx, NULL, &len, 0)) { + BIO_printf(bio_err, "EVP_MAC_final failed\n"); + goto err; + } + if (len > BUFSIZE) { + BIO_printf(bio_err, "output len is too large\n"); + goto err; + } + + if (!EVP_MAC_final(ctx, buf, &len, BUFSIZE)) { + BIO_printf(bio_err, "EVP_MAC_final failed\n"); + goto err; + } + + if (out_bin) { + BIO_write(out, buf, len); + } else { + for (i = 0; i < (int)len; ++i) + BIO_printf(out, "%02X", buf[i]); + if (outfile == NULL) + BIO_printf(out,"\n"); + } + + ret = 0; +err: + if (ret != 0) + ERR_print_errors(bio_err); + OPENSSL_clear_free(buf, BUFSIZE); + OPENSSL_free(cipher); + OPENSSL_free(digest); + sk_OPENSSL_STRING_free(opts); + BIO_free(in); + BIO_free(out); + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + return ret; +} diff --git a/apps/nseq.c b/apps/nseq.c --- a/apps/nseq.c +++ b/apps/nseq.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -15,15 +15,23 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_TOSEQ, OPT_IN, OPT_OUT + OPT_COMMON, + OPT_TOSEQ, OPT_IN, OPT_OUT, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS nseq_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"}, + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, + + OPT_SECTION("Output"), + {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"}, {"out", OPT_OUT, '>', "Output file"}, + + OPT_PROV_OPTIONS, {NULL} }; @@ -57,8 +65,14 @@ case OPT_OUT: outfile = opt_arg(); break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; @@ -77,8 +91,10 @@ seq->certs = sk_X509_new_null(); if (seq->certs == NULL) goto end; - while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) - sk_X509_push(seq->certs, x509); + while ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) { + if (!sk_X509_push(seq->certs, x509)) + goto end; + } if (!sk_X509_num(seq->certs)) { BIO_printf(bio_err, "%s: Error reading certs file %s\n", diff --git a/apps/ocsp.c b/apps/ocsp.c --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -1,7 +1,7 @@ /* * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,8 +10,8 @@ #include #ifdef OPENSSL_SYS_VMS -# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined - * on OpenVMS */ + /* So fd_set and friends get properly defined on OpenVMS */ +# define _XOPEN_SOURCE_EXTENDED #endif #include @@ -22,6 +22,7 @@ /* Needs to be included before the openssl headers */ #include "apps.h" +#include "http_server.h" #include "progs.h" #include "internal/sockets.h" #include @@ -31,37 +32,11 @@ #include #include #include -#include -#ifndef HAVE_FORK -#if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) -# define HAVE_FORK 0 -#else -# define HAVE_FORK 1 -#endif -#endif - -#if HAVE_FORK -#undef NO_FORK -#else -#define NO_FORK -#endif - -#if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \ - && !defined(OPENSSL_NO_POSIX_IO) -# define OCSP_DAEMON -# include -# include -# include -# include -# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ -#else -# undef LOG_INFO -# undef LOG_WARNING -# undef LOG_ERR -# define LOG_INFO 0 -# define LOG_WARNING 1 -# define LOG_ERR 2 +#if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif #endif #if defined(OPENSSL_SYS_VXWORKS) @@ -87,7 +62,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID) *ids); -static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, +static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, STACK_OF(OPENSSL_STRING) *names, STACK_OF(OCSP_CERTID) *ids, long nsec, long maxage); @@ -96,76 +71,118 @@ EVP_PKEY *rkey, const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(X509) *rother, unsigned long flags, - int nmin, int ndays, int badsig); + int nmin, int ndays, int badsig, + const EVP_MD *resp_md); static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser); -static BIO *init_responder(const char *port); -static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout); -static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp); -static void log_message(int level, const char *fmt, ...); +static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, + const char *port, int timeout); +static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp); static char *prog; -static int multi = 0; -#ifdef OCSP_DAEMON -static int acfd = (int) INVALID_SOCKET; +#ifdef HTTP_DAEMON static int index_changed(CA_DB *); -static void spawn_loop(void); -static int print_syslog(const char *str, size_t len, void *levPtr); -static void socket_timeout(int signum); -#endif - -#ifndef OPENSSL_NO_SOCK -static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, - const char *path, - const STACK_OF(CONF_VALUE) *headers, - OCSP_REQUEST *req, int req_timeout); #endif typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT, +#ifndef OPENSSL_NO_SOCK + OPT_PROXY, OPT_NO_PROXY, +#endif OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE, OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS, OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN, OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER, OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT, OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER, - OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, + OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, + OPT_NOCAPATH, OPT_NOCASTORE, OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT, OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL, OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER, OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER, + OPT_PASSIN, + OPT_RCID, OPT_V_ENUM, OPT_MD, - OPT_MULTI + OPT_MULTI, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS ocsp_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"out", OPT_OUTFILE, '>', "Output filename"}, - {"timeout", OPT_TIMEOUT, 'p', - "Connection timeout (in seconds) to the OCSP responder"}, - {"url", OPT_URL, 's', "Responder URL"}, - {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"}, - {"port", OPT_PORT, 'p', "Port to run responder on"}, {"ignore_err", OPT_IGNORE_ERR, '-', "Ignore error on OCSP request or response and continue running"}, - {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"}, - {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"}, - {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"}, + {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"}, + {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store"}, + + OPT_SECTION("Responder"), + {"timeout", OPT_TIMEOUT, 'p', + "Connection timeout (in seconds) to the OCSP responder"}, {"resp_no_certs", OPT_RESP_NO_CERTS, '-', "Don't include any certificates in response"}, - {"resp_key_id", OPT_RESP_KEY_ID, '-', - "Identify response by signing certificate key ID"}, -#ifdef OCSP_DAEMON +#ifdef HTTP_DAEMON {"multi", OPT_MULTI, 'p', "run multiple responder processes"}, #endif {"no_certs", OPT_NO_CERTS, '-', "Don't include any certificates in signed request"}, + {"badsig", OPT_BADSIG, '-', + "Corrupt last byte of loaded OCSP response signature (for test)"}, + {"CA", OPT_CA, '<', "CA certificate"}, + {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"}, + {"nrequest", OPT_REQUEST, 'p', + "Number of requests to accept (default unlimited)"}, + {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"}, + {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"}, + {"sign_other", OPT_SIGN_OTHER, '<', + "Additional certificates to include in signed request"}, + {"index", OPT_INDEX, '<', "Certificate status index file"}, + {"ndays", OPT_NDAYS, 'p', "Number of days before next update"}, + {"rsigner", OPT_RSIGNER, '<', + "Responder certificate to sign responses with"}, + {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"}, + {"passin", OPT_PASSIN, 's', "Responder key pass phrase source"}, + {"rother", OPT_ROTHER, '<', "Other certificates to include in response"}, + {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"}, + {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"}, + {"header", OPT_HEADER, 's', "key=value header to add"}, + {"rcid", OPT_RCID, 's', "Use specified algorithm for cert id in response"}, + {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"}, + + OPT_SECTION("Client"), + {"url", OPT_URL, 's', "Responder URL"}, + {"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"}, + {"port", OPT_PORT, 'N', "Port to run responder on"}, + {"path", OPT_PATH, 's', "Path to use in OCSP request"}, +#ifndef OPENSSL_NO_SOCK + {"proxy", OPT_PROXY, 's', + "[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"}, + {"no_proxy", OPT_NO_PROXY, 's', + "List of addresses of servers not to use HTTP(S) proxy for"}, + {OPT_MORE_STR, 0, 0, + "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"}, +#endif + {"out", OPT_OUTFILE, '>', "Output filename"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"}, + {"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"}, + {"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"}, {"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-', "Don't check signature on response"}, + {"resp_key_id", OPT_RESP_KEY_ID, '-', + "Identify response by signing certificate key ID"}, {"no_cert_verify", OPT_NO_CERT_VERIFY, '-', "Don't check signing certificate"}, + {"text", OPT_TEXT, '-', "Print text form of request and response"}, + {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"}, + {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"}, {"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"}, {"no_cert_checks", OPT_NO_CERT_CHECKS, '-', "Don't do additional checks on signing certificate"}, @@ -175,57 +192,29 @@ "Don't verify additional certificates"}, {"no_intern", OPT_NO_INTERN, '-', "Don't search certificates contained in response for signer"}, - {"badsig", OPT_BADSIG, '-', - "Corrupt last byte of loaded OCSP response signature (for test)"}, - {"text", OPT_TEXT, '-', "Print text form of request and response"}, - {"req_text", OPT_REQ_TEXT, '-', "Print text form of request"}, - {"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"}, - {"reqin", OPT_REQIN, 's', "File with the DER-encoded request"}, {"respin", OPT_RESPIN, 's', "File with the DER-encoded response"}, - {"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"}, {"VAfile", OPT_VAFILE, '<', "Validator certificates file"}, - {"sign_other", OPT_SIGN_OTHER, '<', - "Additional certificates to include in signed request"}, {"verify_other", OPT_VERIFY_OTHER, '<', "Additional certificates to search for signer"}, - {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, - {"CApath", OPT_CAPATH, '<', "Trusted certificates directory"}, - {"no-CAfile", OPT_NOCAFILE, '-', - "Do not load the default certificates file"}, - {"no-CApath", OPT_NOCAPATH, '-', - "Do not load certificates from the default certificates directory"}, + {"cert", OPT_CERT, '<', "Certificate to check"}, + {"serial", OPT_SERIAL, 's', "Serial number to check"}, {"validity_period", OPT_VALIDITY_PERIOD, 'u', "Maximum validity discrepancy in seconds"}, - {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"}, {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"}, {"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"}, {"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"}, - {"path", OPT_PATH, 's', "Path to use in OCSP request"}, {"issuer", OPT_ISSUER, '<', "Issuer certificate"}, - {"cert", OPT_CERT, '<', "Certificate to check"}, - {"serial", OPT_SERIAL, 's', "Serial number to check"}, - {"index", OPT_INDEX, '<', "Certificate status index file"}, - {"CA", OPT_CA, '<', "CA certificate"}, - {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"}, - {"nrequest", OPT_REQUEST, 'p', - "Number of requests to accept (default unlimited)"}, - {"ndays", OPT_NDAYS, 'p', "Number of days before next update"}, - {"rsigner", OPT_RSIGNER, '<', - "Responder certificate to sign responses with"}, - {"rkey", OPT_RKEY, '<', "Responder key to sign responses with"}, - {"rother", OPT_ROTHER, '<', "Other certificates to include in response"}, - {"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"}, - {"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"}, - {"header", OPT_HEADER, 's', "key=value header to add"}, - {"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"}, + {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"}, + OPT_V_OPTIONS, + OPT_PROV_OPTIONS, {NULL} }; int ocsp_main(int argc, char **argv) { BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL; - const EVP_MD *cert_id_md = NULL, *rsign_md = NULL; + EVP_MD *cert_id_md = NULL, *rsign_md = NULL; STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL; int trailing_md = 0; CA_DB *rdb = NULL; @@ -240,35 +229,37 @@ STACK_OF(X509) *issuers = NULL; X509 *issuer = NULL, *cert = NULL; STACK_OF(X509) *rca_cert = NULL; + EVP_MD *resp_certid_md = NULL; X509 *signer = NULL, *rsigner = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; - const char *CAfile = NULL, *CApath = NULL; - char *header, *value; + const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL; + char *header, *value, *respdigname = NULL; char *host = NULL, *port = NULL, *path = "/", *outfile = NULL; +#ifndef OPENSSL_NO_SOCK + char *opt_proxy = NULL; + char *opt_no_proxy = NULL; +#endif char *rca_filename = NULL, *reqin = NULL, *respin = NULL; char *reqout = NULL, *respout = NULL, *ridx_filename = NULL; char *rsignfile = NULL, *rkeyfile = NULL; + char *passinarg = NULL, *passin = NULL; char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL; char *signfile = NULL, *keyfile = NULL; char *thost = NULL, *tport = NULL, *tpath = NULL; - int noCAfile = 0, noCApath = 0; + int noCAfile = 0, noCApath = 0, noCAstore = 0; int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1; int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1; - int req_text = 0, resp_text = 0, ret = 1; + int req_text = 0, resp_text = 0, res, ret = 1; int req_timeout = -1; long nsec = MAX_VALIDITY_PERIOD, maxage = -1; unsigned long sign_flags = 0, verify_flags = 0, rflags = 0; OPTION_CHOICE o; - reqnames = sk_OPENSSL_STRING_new_null(); - if (reqnames == NULL) - goto end; - ids = sk_OCSP_CERTID_new_null(); - if (ids == NULL) + if ((reqnames = sk_OPENSSL_STRING_new_null()) == NULL + || (ids = sk_OCSP_CERTID_new_null()) == NULL + || (vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; - if ((vpm = X509_VERIFY_PARAM_new()) == NULL) - return 1; prog = opt_init(argc, argv, ocsp_options); while ((o = opt_next()) != OPT_EOF) { @@ -295,8 +286,10 @@ OPENSSL_free(tport); OPENSSL_free(tpath); thost = tport = tpath = NULL; - if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) { - BIO_printf(bio_err, "%s Error parsing URL\n", prog); + if (!OSSL_HTTP_parse_url(opt_arg(), &use_ssl, NULL /* userinfo */, + &host, &port, NULL /* port_num */, + &path, NULL /* qry */, NULL /* frag */)) { + BIO_printf(bio_err, "%s Error parsing -url argument\n", prog); goto end; } thost = host; @@ -309,6 +302,17 @@ case OPT_PORT: port = opt_arg(); break; + case OPT_PATH: + path = opt_arg(); + break; +#ifndef OPENSSL_NO_SOCK + case OPT_PROXY: + opt_proxy = opt_arg(); + break; + case OPT_NO_PROXY: + opt_no_proxy = opt_arg(); + break; +#endif case OPT_IGNORE_ERR: ignore_err = 1; break; @@ -388,12 +392,18 @@ case OPT_CAPATH: CApath = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_NOCAPATH: noCApath = 1; break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_V_CASES: if (!opt_verify(o, vpm)) goto end; @@ -414,26 +424,24 @@ case OPT_RESPOUT: respout = opt_arg(); break; - case OPT_PATH: - path = opt_arg(); - break; case OPT_ISSUER: - issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate"); + issuer = load_cert(opt_arg(), FORMAT_UNDEF, "issuer certificate"); if (issuer == NULL) goto end; if (issuers == NULL) { if ((issuers = sk_X509_new_null()) == NULL) goto end; } - sk_X509_push(issuers, issuer); + if (!sk_X509_push(issuers, issuer)) + goto end; break; case OPT_CERT: X509_free(cert); - cert = load_cert(opt_arg(), FORMAT_PEM, "certificate"); + cert = load_cert(opt_arg(), FORMAT_UNDEF, "certificate"); if (cert == NULL) goto end; if (cert_id_md == NULL) - cert_id_md = EVP_sha1(); + cert_id_md = (EVP_MD *)EVP_sha1(); if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids)) goto end; if (!sk_OPENSSL_STRING_push(reqnames, opt_arg())) @@ -442,7 +450,7 @@ break; case OPT_SERIAL: if (cert_id_md == NULL) - cert_id_md = EVP_sha1(); + cert_id_md = (EVP_MD *)EVP_sha1(); if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids)) goto end; if (!sk_OPENSSL_STRING_push(reqnames, opt_arg())) @@ -456,12 +464,12 @@ rca_filename = opt_arg(); break; case OPT_NMIN: - opt_int(opt_arg(), &nmin); + nmin = opt_int_arg(); if (ndays == -1) ndays = 0; break; case OPT_REQUEST: - opt_int(opt_arg(), &accept_count); + accept_count = opt_int_arg(); break; case OPT_NDAYS: ndays = atoi(opt_arg()); @@ -472,17 +480,20 @@ case OPT_RKEY: rkeyfile = opt_arg(); break; + case OPT_PASSIN: + passinarg = opt_arg(); + break; case OPT_ROTHER: rcertfile = opt_arg(); break; case OPT_RMD: /* Response MessageDigest */ - if (!opt_md(opt_arg(), &rsign_md)) - goto end; + respdigname = opt_arg(); break; case OPT_RSIGOPT: if (rsign_sigopts == NULL) rsign_sigopts = sk_OPENSSL_STRING_new_null(); - if (rsign_sigopts == NULL || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg())) + if (rsign_sigopts == NULL + || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg())) goto end; break; case OPT_HEADER: @@ -496,6 +507,10 @@ if (!X509V3_add_value(header, value, &headers)) goto end; break; + case OPT_RCID: + if (!opt_md(opt_arg(), &resp_certid_md)) + goto opthelp; + break; case OPT_MD: if (trailing_md) { BIO_printf(bio_err, @@ -508,20 +523,32 @@ trailing_md = 1; break; case OPT_MULTI: -#ifdef OCSP_DAEMON +#ifdef HTTP_DAEMON multi = atoi(opt_arg()); #endif break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + if (trailing_md) { BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n", prog); goto opthelp; } - argc = opt_num_rest(); - if (argc != 0) - goto opthelp; + + if (respdigname != NULL) { + if (!opt_md(respdigname, &rsign_md)) + goto end; + } /* Have we anything to do? */ if (req == NULL && reqin == NULL @@ -548,28 +575,36 @@ } if (req == NULL && port != NULL) { - acbio = init_responder(port); +#ifndef OPENSSL_NO_SOCK + acbio = http_server_init_bio(prog, port); if (acbio == NULL) goto end; +#else + BIO_printf(bio_err, "Cannot act as server - sockets not supported\n"); + goto end; +#endif } if (rsignfile != NULL) { if (rkeyfile == NULL) rkeyfile = rsignfile; - rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate"); + rsigner = load_cert(rsignfile, FORMAT_UNDEF, "responder certificate"); if (rsigner == NULL) { BIO_printf(bio_err, "Error loading responder certificate\n"); goto end; } - if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM, - NULL, "CA certificate")) + if (!load_certs(rca_filename, 0, &rca_cert, NULL, "CA certificates")) goto end; if (rcertfile != NULL) { - if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL, + if (!load_certs(rcertfile, 0, &rother, NULL, "responder other certificates")) goto end; } - rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL, + if (!app_passwd(passinarg, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + rkey = load_key(rkeyfile, FORMAT_UNDEF, 0, passin, NULL, "responder private key"); if (rkey == NULL) goto end; @@ -585,25 +620,28 @@ if (ridx_filename != NULL) { rdb = load_index(ridx_filename, NULL); if (rdb == NULL || index_index(rdb) <= 0) { + BIO_printf(bio_err, + "Problem with index file: %s (could not load/parse file)\n", + ridx_filename); ret = 1; goto end; } } -#ifdef OCSP_DAEMON +#ifdef HTTP_DAEMON if (multi && acbio != NULL) - spawn_loop(); + spawn_loop(prog); if (acbio != NULL && req_timeout > 0) signal(SIGALRM, socket_timeout); #endif if (acbio != NULL) - log_message(LOG_INFO, "waiting for OCSP client connections..."); + log_message(prog, LOG_INFO, "waiting for OCSP client connections..."); redo_accept: if (acbio != NULL) { -#ifdef OCSP_DAEMON +#ifdef HTTP_DAEMON if (index_changed(rdb)) { CA_DB *newrdb = load_index(ridx_filename, NULL); @@ -612,21 +650,24 @@ rdb = newrdb; } else { free_index(newrdb); - log_message(LOG_ERR, "error reloading updated index: %s", + log_message(prog, LOG_ERR, "error reloading updated index: %s", ridx_filename); } } #endif req = NULL; - if (!do_responder(&req, &cbio, acbio, req_timeout)) + res = do_responder(&req, &cbio, acbio, port, req_timeout); + if (res == 0) goto redo_accept; if (req == NULL) { - resp = - OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, - NULL); - send_ocsp_response(cbio, resp); + if (res == 1) { + resp = + OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, + NULL); + send_ocsp_response(cbio, resp); + } goto done_resp; } } @@ -646,23 +687,23 @@ if (signfile != NULL) { if (keyfile == NULL) keyfile = signfile; - signer = load_cert(signfile, FORMAT_PEM, "signer certificate"); + signer = load_cert(signfile, FORMAT_UNDEF, "signer certificate"); if (signer == NULL) { BIO_printf(bio_err, "Error loading signer certificate\n"); goto end; } if (sign_certfile != NULL) { - if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL, + if (!load_certs(sign_certfile, 0, &sign_other, NULL, "signer certificates")) goto end; } - key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL, + key = load_key(keyfile, FORMAT_UNDEF, 0, NULL, NULL, "signer private key"); if (key == NULL) goto end; - if (!OCSP_request_sign - (req, signer, key, NULL, sign_other, sign_flags)) { + if (!OCSP_request_sign(req, signer, key, NULL, + sign_other, sign_flags)) { BIO_printf(bio_err, "Error signing OCSP request\n"); goto end; } @@ -681,18 +722,21 @@ if (rdb != NULL) { make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey, - rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig); + rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, + badsig, resp_certid_md); + if (resp == NULL) + goto end; if (cbio != NULL) send_ocsp_response(cbio, resp); } else if (host != NULL) { #ifndef OPENSSL_NO_SOCK - resp = process_responder(req, host, path, - port, use_ssl, headers, req_timeout); + resp = process_responder(req, host, port, path, opt_proxy, opt_no_proxy, + use_ssl, headers, req_timeout); if (resp == NULL) goto end; #else BIO_printf(bio_err, - "Error creating connect BIO - sockets not supported.\n"); + "Error creating connect BIO - sockets not supported\n"); goto end; #endif } else if (respin != NULL) { @@ -752,15 +796,16 @@ } if (store == NULL) { - store = setup_verify(CAfile, CApath, noCAfile, noCApath); + store = setup_verify(CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore); if (!store) goto end; } if (vpmtouched) X509_STORE_set1_param(store, vpm); if (verify_certfile != NULL) { - if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL, - "validator certificate")) + if (!load_certs(verify_certfile, 0, &verify_other, NULL, + "validator certificates")) goto end; } @@ -798,7 +843,8 @@ } } - print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage); + if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage)) + ret = 1; end: ERR_print_errors(bio_err); @@ -808,6 +854,9 @@ sk_OPENSSL_STRING_free(rsign_sigopts); EVP_PKEY_free(key); EVP_PKEY_free(rkey); + EVP_MD_free(cert_id_md); + EVP_MD_free(rsign_md); + EVP_MD_free(resp_certid_md); X509_free(cert); sk_X509_pop_free(issuers, X509_free); X509_free(rsigner); @@ -831,41 +880,7 @@ return ret; } -static void -log_message(int level, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); -#ifdef OCSP_DAEMON - if (multi) { - char buf[1024]; - if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) { - syslog(level, "%s", buf); - } - if (level >= LOG_ERR) - ERR_print_errors_cb(print_syslog, &level); - } -#endif - if (!multi) { - BIO_printf(bio_err, "%s: ", prog); - BIO_vprintf(bio_err, fmt, ap); - BIO_printf(bio_err, "\n"); - } - va_end(ap); -} - -#ifdef OCSP_DAEMON - -static int print_syslog(const char *str, size_t len, void *levPtr) -{ - int level = *(int *)levPtr; - int ilen = (len > MAXERRLEN) ? MAXERRLEN : len; - - syslog(level, "%.*s", ilen, str); - - return ilen; -} +#ifdef HTTP_DAEMON static int index_changed(CA_DB *rdb) { @@ -883,131 +898,6 @@ return 0; } -static void killall(int ret, pid_t *kidpids) -{ - int i; - - for (i = 0; i < multi; ++i) - if (kidpids[i] != 0) - (void)kill(kidpids[i], SIGTERM); - OPENSSL_free(kidpids); - sleep(1); - exit(ret); -} - -static int termsig = 0; - -static void noteterm (int sig) -{ - termsig = sig; -} - -/* - * Loop spawning up to `multi` child processes, only child processes return - * from this function. The parent process loops until receiving a termination - * signal, kills extant children and exits without returning. - */ -static void spawn_loop(void) -{ - pid_t *kidpids = NULL; - int status; - int procs = 0; - int i; - - openlog(prog, LOG_PID, LOG_DAEMON); - - if (setpgid(0, 0)) { - syslog(LOG_ERR, "fatal: error detaching from parent process group: %s", - strerror(errno)); - exit(1); - } - kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array"); - for (i = 0; i < multi; ++i) - kidpids[i] = 0; - - signal(SIGINT, noteterm); - signal(SIGTERM, noteterm); - - while (termsig == 0) { - pid_t fpid; - - /* - * Wait for a child to replace when we're at the limit. - * Slow down if a child exited abnormally or waitpid() < 0 - */ - while (termsig == 0 && procs >= multi) { - if ((fpid = waitpid(-1, &status, 0)) > 0) { - for (i = 0; i < procs; ++i) { - if (kidpids[i] == fpid) { - kidpids[i] = 0; - --procs; - break; - } - } - if (i >= multi) { - syslog(LOG_ERR, "fatal: internal error: " - "no matching child slot for pid: %ld", - (long) fpid); - killall(1, kidpids); - } - if (status != 0) { - if (WIFEXITED(status)) - syslog(LOG_WARNING, "child process: %ld, exit status: %d", - (long)fpid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_WARNING, "child process: %ld, term signal %d%s", - (long)fpid, WTERMSIG(status), -#ifdef WCOREDUMP - WCOREDUMP(status) ? " (core dumped)" : -#endif - ""); - sleep(1); - } - break; - } else if (errno != EINTR) { - syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno)); - killall(1, kidpids); - } - } - if (termsig) - break; - - switch(fpid = fork()) { - case -1: /* error */ - /* System critically low on memory, pause and try again later */ - sleep(30); - break; - case 0: /* child */ - OPENSSL_free(kidpids); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - if (termsig) - _exit(0); - if (RAND_poll() <= 0) { - syslog(LOG_ERR, "fatal: RAND_poll() failed"); - _exit(1); - } - return; - default: /* parent */ - for (i = 0; i < multi; ++i) { - if (kidpids[i] == 0) { - kidpids[i] = fpid; - procs++; - break; - } - } - if (i >= multi) { - syslog(LOG_ERR, "fatal: internal error: no free child slots"); - killall(1, kidpids); - } - break; - } - } - - /* The loop above can only break on termsig */ - syslog(LOG_INFO, "terminating on signal: %d", termsig); - killall(0, kidpids); -} #endif static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, @@ -1041,7 +931,7 @@ STACK_OF(OCSP_CERTID) *ids) { OCSP_CERTID *id; - X509_NAME *iname; + const X509_NAME *iname; ASN1_BIT_STRING *ikey; ASN1_INTEGER *sno; @@ -1073,7 +963,7 @@ return 0; } -static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, +static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, STACK_OF(OPENSSL_STRING) *names, STACK_OF(OCSP_CERTID) *ids, long nsec, long maxage) @@ -1082,10 +972,13 @@ const char *name; int i, status, reason; ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + int ret = 1; - if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names) - || !sk_OCSP_CERTID_num(ids)) - return; + if (req == NULL || !sk_OPENSSL_STRING_num(names)) + return 1; + + if (bs == NULL || !sk_OCSP_CERTID_num(ids)) + return 0; for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) { id = sk_OCSP_CERTID_value(ids, i); @@ -1095,6 +988,7 @@ if (!OCSP_resp_find_status(bs, id, &status, &reason, &rev, &thisupd, &nextupd)) { BIO_puts(out, "ERROR: No Status found.\n"); + ret = 0; continue; } @@ -1128,6 +1022,7 @@ ASN1_GENERALIZEDTIME_print(out, rev); BIO_puts(out, "\n"); } + return ret; } static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req, @@ -1135,7 +1030,8 @@ EVP_PKEY *rkey, const EVP_MD *rmd, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(X509) *rother, unsigned long flags, - int nmin, int ndays, int badsig) + int nmin, int ndays, int badsig, + const EVP_MD *resp_md) { ASN1_TIME *thisupd = NULL, *nextupd = NULL; OCSP_CERTID *cid; @@ -1166,6 +1062,8 @@ int found = 0; ASN1_OBJECT *cert_id_md_oid; const EVP_MD *cert_id_md; + OCSP_CERTID *cid_resp_md = NULL; + one = OCSP_request_onereq_get0(req, i); cid = OCSP_onereq_get0_id(one); @@ -1181,11 +1079,18 @@ X509 *ca_cert = sk_X509_value(ca, jj); OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert); - if (OCSP_id_issuer_cmp(ca_id, cid) == 0) + if (OCSP_id_issuer_cmp(ca_id, cid) == 0) { found = 1; - + if (resp_md != NULL) + cid_resp_md = OCSP_cert_to_id(resp_md, NULL, ca_cert); + } OCSP_CERTID_free(ca_id); } + OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); + inf = lookup_serial(db, serial); + + /* at this point, we can have cid be an alias of cid_resp_md */ + cid = (cid_resp_md != NULL) ? cid_resp_md : cid; if (!found) { OCSP_basic_add1_status(bs, cid, @@ -1193,8 +1098,6 @@ 0, NULL, thisupd, nextupd); continue; } - OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); - inf = lookup_serial(db, serial); if (inf == NULL) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, @@ -1209,10 +1112,16 @@ ASN1_GENERALIZEDTIME *invtm = NULL; OCSP_SINGLERESP *single; int reason = -1; + unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]); single = OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_REVOKED, reason, revtm, thisupd, nextupd); + if (single == NULL) { + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, + NULL); + goto end; + } if (invtm != NULL) OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0); @@ -1224,6 +1133,7 @@ ASN1_TIME_free(revtm); ASN1_GENERALIZEDTIME_free(invtm); } + OCSP_CERTID_free(cid_resp_md); } OCSP_copy_nonce(bs, req); @@ -1273,10 +1183,12 @@ bn = ASN1_INTEGER_to_BN(ser, NULL); OPENSSL_assert(bn); /* FIXME: should report an error at this * point and abort */ - if (BN_is_zero(bn)) + if (BN_is_zero(bn)) { itmp = OPENSSL_strdup("00"); - else + OPENSSL_assert(itmp); + } else { itmp = BN_bn2hex(bn); + } row[DB_serial] = itmp; BN_free(bn); rrow = TXT_DB_get_by_index(db->db, DB_serial, row); @@ -1284,339 +1196,66 @@ return rrow; } -/* Quick and dirty OCSP server: read in and parse input request */ - -static BIO *init_responder(const char *port) -{ -#ifdef OPENSSL_NO_SOCK - BIO_printf(bio_err, - "Error setting up accept BIO - sockets not supported.\n"); - return NULL; -#else - BIO *acbio = NULL, *bufbio = NULL; - - bufbio = BIO_new(BIO_f_buffer()); - if (bufbio == NULL) - goto err; - acbio = BIO_new(BIO_s_accept()); - if (acbio == NULL - || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0 - || BIO_set_accept_port(acbio, port) < 0) { - log_message(LOG_ERR, "Error setting up accept BIO"); - goto err; - } - - BIO_set_accept_bios(acbio, bufbio); - bufbio = NULL; - if (BIO_do_accept(acbio) <= 0) { - log_message(LOG_ERR, "Error starting accept"); - goto err; - } - - return acbio; - - err: - BIO_free_all(acbio); - BIO_free(bufbio); - return NULL; -#endif -} - -#ifndef OPENSSL_NO_SOCK -/* - * Decode %xx URL-decoding in-place. Ignores mal-formed sequences. - */ -static int urldecode(char *p) -{ - unsigned char *out = (unsigned char *)p; - unsigned char *save = out; - - for (; *p; p++) { - if (*p != '%') - *out++ = *p; - else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) { - /* Don't check, can't fail because of ixdigit() call. */ - *out++ = (OPENSSL_hexchar2int(p[1]) << 4) - | OPENSSL_hexchar2int(p[2]); - p += 2; - } - else - return -1; - } - *out = '\0'; - return (int)(out - save); -} -#endif - -#ifdef OCSP_DAEMON -static void socket_timeout(int signum) -{ - if (acfd != (int)INVALID_SOCKET) - (void)shutdown(acfd, SHUT_RD); -} -#endif - static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, - int timeout) + const char *port, int timeout) { -#ifdef OPENSSL_NO_SOCK - return 0; +#ifndef OPENSSL_NO_SOCK + return http_server_get_asn1_req(ASN1_ITEM_rptr(OCSP_REQUEST), + (ASN1_VALUE **)preq, NULL, pcbio, acbio, + NULL /* found_keep_alive */, + prog, port, 1 /* accept_get */, timeout); #else - int len; - OCSP_REQUEST *req = NULL; - char inbuf[2048], reqbuf[2048]; - char *p, *q; - BIO *cbio = NULL, *getbio = NULL, *b64 = NULL; - const char *client; - + BIO_printf(bio_err, + "Error getting OCSP request - sockets not supported\n"); *preq = NULL; - - /* Connection loss before accept() is routine, ignore silently */ - if (BIO_do_accept(acbio) <= 0) - return 0; - - cbio = BIO_pop(acbio); - *pcbio = cbio; - client = BIO_get_peer_name(cbio); - -# ifdef OCSP_DAEMON - if (timeout > 0) { - (void) BIO_get_fd(cbio, &acfd); - alarm(timeout); - } -# endif - - /* Read the request line. */ - len = BIO_gets(cbio, reqbuf, sizeof(reqbuf)); - if (len <= 0) - goto out; - - if (strncmp(reqbuf, "GET ", 4) == 0) { - /* Expecting GET {sp} /URL {sp} HTTP/1.x */ - for (p = reqbuf + 4; *p == ' '; ++p) - continue; - if (*p != '/') { - log_message(LOG_INFO, "Invalid request -- bad URL: %s", client); - goto out; - } - p++; - - /* Splice off the HTTP version identifier. */ - for (q = p; *q; q++) - if (*q == ' ') - break; - if (strncmp(q, " HTTP/1.", 8) != 0) { - log_message(LOG_INFO, - "Invalid request -- bad HTTP version: %s", client); - goto out; - } - *q = '\0'; - - /* - * Skip "GET / HTTP..." requests often used by load-balancers. Note: - * 'p' was incremented above to point to the first byte *after* the - * leading slash, so with 'GET / ' it is now an empty string. - */ - if (p[0] == '\0') - goto out; - - len = urldecode(p); - if (len <= 0) { - log_message(LOG_INFO, - "Invalid request -- bad URL encoding: %s", client); - goto out; - } - if ((getbio = BIO_new_mem_buf(p, len)) == NULL - || (b64 = BIO_new(BIO_f_base64())) == NULL) { - log_message(LOG_ERR, "Could not allocate base64 bio: %s", client); - goto out; - } - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - getbio = BIO_push(b64, getbio); - } else if (strncmp(reqbuf, "POST ", 5) != 0) { - log_message(LOG_INFO, "Invalid request -- bad HTTP verb: %s", client); - goto out; - } - - /* Read and skip past the headers. */ - for (;;) { - len = BIO_gets(cbio, inbuf, sizeof(inbuf)); - if (len <= 0) - goto out; - if ((inbuf[0] == '\r') || (inbuf[0] == '\n')) - break; - } - -# ifdef OCSP_DAEMON - /* Clear alarm before we close the client socket */ - alarm(0); - timeout = 0; -# endif - - /* Try to read OCSP request */ - if (getbio != NULL) { - req = d2i_OCSP_REQUEST_bio(getbio, NULL); - BIO_free_all(getbio); - } else { - req = d2i_OCSP_REQUEST_bio(cbio, NULL); - } - - if (req == NULL) - log_message(LOG_ERR, "Error parsing OCSP request"); - - *preq = req; - -out: -# ifdef OCSP_DAEMON - if (timeout > 0) - alarm(0); - acfd = (int)INVALID_SOCKET; -# endif - return 1; + return 0; #endif } -static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) +static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp) { - char http_resp[] = - "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n" - "Content-Length: %d\r\n\r\n"; - if (cbio == NULL) - return 0; - BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL)); - i2d_OCSP_RESPONSE_bio(cbio, resp); - (void)BIO_flush(cbio); - return 1; -} - #ifndef OPENSSL_NO_SOCK -static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host, - const char *path, - const STACK_OF(CONF_VALUE) *headers, - OCSP_REQUEST *req, int req_timeout) -{ - int fd; - int rv; - int i; - int add_host = 1; - OCSP_REQ_CTX *ctx = NULL; - OCSP_RESPONSE *rsp = NULL; - fd_set confds; - struct timeval tv; - - if (req_timeout != -1) - BIO_set_nbio(cbio, 1); - - rv = BIO_do_connect(cbio); - - if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) { - BIO_puts(bio_err, "Error connecting BIO\n"); - return NULL; - } - - if (BIO_get_fd(cbio, &fd) < 0) { - BIO_puts(bio_err, "Can't get connection fd\n"); - goto err; - } - - if (req_timeout != -1 && rv <= 0) { - FD_ZERO(&confds); - openssl_fdset(fd, &confds); - tv.tv_usec = 0; - tv.tv_sec = req_timeout; - rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); - if (rv == 0) { - BIO_puts(bio_err, "Timeout on connect\n"); - return NULL; - } - } - - ctx = OCSP_sendreq_new(cbio, path, NULL, -1); - if (ctx == NULL) - return NULL; - - for (i = 0; i < sk_CONF_VALUE_num(headers); i++) { - CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i); - if (add_host == 1 && strcasecmp("host", hdr->name) == 0) - add_host = 0; - if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value)) - goto err; - } - - if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0) - goto err; - - if (!OCSP_REQ_CTX_set1_req(ctx, req)) - goto err; - - for (;;) { - rv = OCSP_sendreq_nbio(&rsp, ctx); - if (rv != -1) - break; - if (req_timeout == -1) - continue; - FD_ZERO(&confds); - openssl_fdset(fd, &confds); - tv.tv_usec = 0; - tv.tv_sec = req_timeout; - if (BIO_should_read(cbio)) { - rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv); - } else if (BIO_should_write(cbio)) { - rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); - } else { - BIO_puts(bio_err, "Unexpected retry condition\n"); - goto err; - } - if (rv == 0) { - BIO_puts(bio_err, "Timeout on request\n"); - break; - } - if (rv == -1) { - BIO_puts(bio_err, "Select error\n"); - break; - } - - } - err: - OCSP_REQ_CTX_free(ctx); - - return rsp; + return http_server_send_asn1_resp(cbio, + 0 /* no keep-alive */, + "application/ocsp-response", + ASN1_ITEM_rptr(OCSP_RESPONSE), + (const ASN1_VALUE *)resp); +#else + BIO_printf(bio_err, + "Error sending OCSP response - sockets not supported\n"); + return 0; +#endif } -OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, - const char *host, const char *path, - const char *port, int use_ssl, - STACK_OF(CONF_VALUE) *headers, +#ifndef OPENSSL_NO_SOCK +OCSP_RESPONSE *process_responder(OCSP_REQUEST *req, const char *host, + const char *port, const char *path, + const char *proxy, const char *no_proxy, + int use_ssl, STACK_OF(CONF_VALUE) *headers, int req_timeout) { - BIO *cbio = NULL; SSL_CTX *ctx = NULL; OCSP_RESPONSE *resp = NULL; - cbio = BIO_new_connect(host); - if (cbio == NULL) { - BIO_printf(bio_err, "Error creating connect BIO\n"); - goto end; - } - if (port != NULL) - BIO_set_conn_port(cbio, port); if (use_ssl == 1) { - BIO *sbio; ctx = SSL_CTX_new(TLS_client_method()); if (ctx == NULL) { BIO_printf(bio_err, "Error creating SSL context.\n"); goto end; } - SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); - sbio = BIO_new_ssl(ctx, 1); - cbio = BIO_push(sbio, cbio); } - resp = query_responder(cbio, host, path, headers, req, req_timeout); + resp = (OCSP_RESPONSE *) + app_http_post_asn1(host, port, path, proxy, no_proxy, + ctx, headers, "application/ocsp-request", + (ASN1_VALUE *)req, ASN1_ITEM_rptr(OCSP_REQUEST), + "application/ocsp-response", + req_timeout, ASN1_ITEM_rptr(OCSP_RESPONSE)); + if (resp == NULL) BIO_printf(bio_err, "Error querying OCSP responder\n"); + end: - BIO_free_all(cbio); SSL_CTX_free(ctx); return resp; } diff --git a/apps/openssl.c b/apps/openssl.c --- a/apps/openssl.c +++ b/apps/openssl.c @@ -1,18 +1,18 @@ /* * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ -#include #include #include #include #include #include +#include #include #include #include @@ -27,20 +27,8 @@ # include #endif #include "apps.h" -#define INCLUDE_FUNCTION_TABLE #include "progs.h" -/* Structure to hold the number of columns to be displayed and the - * field width used to display them. - */ -typedef struct { - int columns; - int width; -} DISPLAY_COLUMNS; - -/* Special sentinel to exit the program. */ -#define EXIT_THE_PROGRAM (-1) - /* * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with * the base prototypes (we cast each variable inside the function to the @@ -49,32 +37,27 @@ */ static LHASH_OF(FUNCTION) *prog_init(void); static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]); -static void list_pkey(void); -static void list_pkey_meth(void); -static void list_type(FUNC_TYPE ft, int one); -static void list_disabled(void); char *default_config_file = NULL; BIO *bio_in = NULL; BIO *bio_out = NULL; BIO *bio_err = NULL; -static void calculate_columns(DISPLAY_COLUMNS *dc) +static void warn_deprecated(const FUNCTION *fp) { - FUNCTION *f; - int len, maxlen = 0; - - for (f = functions; f->name != NULL; ++f) - if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher) - if ((len = strlen(f->name)) > maxlen) - maxlen = len; - - dc->width = maxlen + 2; - dc->columns = (80 - 1) / dc->width; + if (fp->deprecated_version != NULL) + BIO_printf(bio_err, "The command %s was deprecated in version %s.", + fp->name, fp->deprecated_version); + else + BIO_printf(bio_err, "The command %s is deprecated.", fp->name); + if (strcmp(fp->deprecated_alternative, DEPRECATED_NO_ALTERNATIVE) != 0) + BIO_printf(bio_err, " Use '%s' instead.", fp->deprecated_alternative); + BIO_printf(bio_err, "\n"); } static int apps_startup(void) { + const char *use_libctx = NULL; #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif @@ -84,53 +67,186 @@ | OPENSSL_INIT_LOAD_CONFIG, NULL)) return 0; - setup_ui_method(); + (void)setup_ui_method(); + (void)setup_engine_loader(); + + /* + * NOTE: This is an undocumented feature required for testing only. + * There are no guarantees that it will exist in future builds. + */ + use_libctx = getenv("OPENSSL_TEST_LIBCTX"); + if (use_libctx != NULL) { + /* Set this to "1" to create a global libctx */ + if (strcmp(use_libctx, "1") == 0) { + if (app_create_libctx() == NULL) + return 0; + } + } return 1; } static void apps_shutdown(void) { + app_providers_cleanup(); + OSSL_LIB_CTX_free(app_get0_libctx()); + destroy_engine_loader(); destroy_ui_method(); - destroy_prefix_method(); } -static char *make_config_name(void) + +#ifndef OPENSSL_NO_TRACE +typedef struct tracedata_st { + BIO *bio; + unsigned int ingroup:1; +} tracedata; + +static size_t internal_trace_cb(const char *buf, size_t cnt, + int category, int cmd, void *vdata) { - const char *t; - size_t len; - char *p; - - if ((t = getenv("OPENSSL_CONF")) != NULL) - return OPENSSL_strdup(t); - - t = X509_get_default_cert_area(); - len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1; - p = app_malloc(len, "config filename buffer"); - strcpy(p, t); -#ifndef OPENSSL_SYS_VMS - strcat(p, "/"); -#endif - strcat(p, OPENSSL_CONF); + int ret = 0; + tracedata *trace_data = vdata; + char buffer[256], *hex; + CRYPTO_THREAD_ID tid; + + switch (cmd) { + case OSSL_TRACE_CTRL_BEGIN: + if (trace_data->ingroup) { + BIO_printf(bio_err, "ERROR: tracing already started\n"); + return 0; + } + trace_data->ingroup = 1; + + tid = CRYPTO_THREAD_get_current_id(); + hex = OPENSSL_buf2hexstr((const unsigned char *)&tid, sizeof(tid)); + BIO_snprintf(buffer, sizeof(buffer), "TRACE[%s]:%s: ", + hex == NULL ? "" : hex, + OSSL_trace_get_category_name(category)); + OPENSSL_free(hex); + BIO_set_prefix(trace_data->bio, buffer); + break; + case OSSL_TRACE_CTRL_WRITE: + if (!trace_data->ingroup) { + BIO_printf(bio_err, "ERROR: writing when tracing not started\n"); + return 0; + } + + ret = BIO_write(trace_data->bio, buf, cnt); + break; + case OSSL_TRACE_CTRL_END: + if (!trace_data->ingroup) { + BIO_printf(bio_err, "ERROR: finishing when tracing not started\n"); + return 0; + } + trace_data->ingroup = 0; + + BIO_set_prefix(trace_data->bio, NULL); + + break; + } + + return ret < 0 ? 0 : ret; +} + +DEFINE_STACK_OF(tracedata) +static STACK_OF(tracedata) *trace_data_stack; - return p; +static void tracedata_free(tracedata *data) +{ + BIO_free_all(data->bio); + OPENSSL_free(data); } +static STACK_OF(tracedata) *trace_data_stack; + +static void cleanup_trace(void) +{ + sk_tracedata_pop_free(trace_data_stack, tracedata_free); +} + +static void setup_trace_category(int category) +{ + BIO *channel; + tracedata *trace_data; + BIO *bio = NULL; + + if (OSSL_trace_enabled(category)) + return; + + bio = BIO_new(BIO_f_prefix()); + channel = BIO_push(bio, dup_bio_err(FORMAT_TEXT)); + trace_data = OPENSSL_zalloc(sizeof(*trace_data)); + + if (trace_data == NULL + || bio == NULL + || (trace_data->bio = channel) == NULL + || OSSL_trace_set_callback(category, internal_trace_cb, + trace_data) == 0 + || sk_tracedata_push(trace_data_stack, trace_data) == 0) { + + fprintf(stderr, + "warning: unable to setup trace callback for category '%s'.\n", + OSSL_trace_get_category_name(category)); + + OSSL_trace_set_callback(category, NULL, NULL); + BIO_free_all(channel); + } +} + +static void setup_trace(const char *str) +{ + char *val; + + /* + * We add this handler as early as possible to ensure it's executed + * as late as possible, i.e. after the TRACE code has done its cleanup + * (which happens last in OPENSSL_cleanup). + */ + atexit(cleanup_trace); + + trace_data_stack = sk_tracedata_new_null(); + val = OPENSSL_strdup(str); + + if (val != NULL) { + char *valp = val; + char *item; + + for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) { + int category = OSSL_trace_get_category_num(item); + + if (category == OSSL_TRACE_CATEGORY_ALL) { + while (++category < OSSL_TRACE_CATEGORY_NUM) + setup_trace_category(category); + break; + } else if (category > 0) { + setup_trace_category(category); + } else { + fprintf(stderr, + "warning: unknown trace category: '%s'.\n", item); + } + } + } + + OPENSSL_free(val); +} +#endif /* OPENSSL_NO_TRACE */ + +static char *help_argv[] = { "help", NULL }; + int main(int argc, char *argv[]) { FUNCTION f, *fp; LHASH_OF(FUNCTION) *prog = NULL; - char *p, *pname; - char buf[1024]; - const char *prompt; + char *pname; + const char *fname; ARGS arg; - int first, n, i, ret = 0; + int global_help = 0; + int ret = 0; arg.argv = NULL; arg.size = 0; /* Set up some of the environment. */ - default_config_file = make_config_name(); bio_in = dup_bio_in(FORMAT_TEXT); bio_out = dup_bio_out(FORMAT_TEXT); bio_err = dup_bio_err(FORMAT_TEXT); @@ -138,319 +254,75 @@ #if defined(OPENSSL_SYS_VMS) && defined(__DECC) argv = copy_argv(&argc, argv); #elif defined(_WIN32) - /* - * Replace argv[] with UTF-8 encoded strings. - */ + /* Replace argv[] with UTF-8 encoded strings. */ win32_utf8argv(&argc, &argv); #endif - p = getenv("OPENSSL_DEBUG_MEMORY"); - if (p != NULL && strcmp(p, "on") == 0) - CRYPTO_set_mem_debug(1); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - if (getenv("OPENSSL_FIPS")) { - BIO_printf(bio_err, "FIPS mode not supported.\n"); - return 1; - } - - if (!apps_startup()) { - BIO_printf(bio_err, - "FATAL: Startup failure (dev note: apps_startup() failed)\n"); - ERR_print_errors(bio_err); - ret = 1; - goto end; - } +#ifndef OPENSSL_NO_TRACE + setup_trace(getenv("OPENSSL_TRACE")); +#endif - prog = prog_init(); - if (prog == NULL) { + if ((fname = "apps_startup", !apps_startup()) + || (fname = "prog_init", (prog = prog_init()) == NULL)) { BIO_printf(bio_err, - "FATAL: Startup failure (dev note: prog_init() failed)\n"); + "FATAL: Startup failure (dev note: %s()) for %s\n", + fname, argv[0]); ERR_print_errors(bio_err); ret = 1; goto end; } pname = opt_progname(argv[0]); + default_config_file = CONF_get1_default_config_file(); + if (default_config_file == NULL) + app_bail_out("%s: could not get default config file\n", pname); + /* first check the program name */ f.name = pname; fp = lh_FUNCTION_retrieve(prog, &f); - if (fp != NULL) { - argv[0] = pname; - ret = fp->func(argc, argv); - goto end; - } - - /* If there is stuff on the command line, run with that. */ - if (argc != 1) { + if (fp == NULL) { + /* We assume we've been called as 'openssl ...' */ + global_help = argc > 1 + && (strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0 + || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0); argc--; argv++; - ret = do_cmd(prog, argc, argv); - if (ret < 0) - ret = 0; - goto end; + opt_appname(argc == 1 || global_help ? "help" : argv[0]); + } else { + argv[0] = pname; } - /* ok, lets enter interactive mode */ - for (;;) { - ret = 0; - /* Read a line, continue reading if line ends with \ */ - for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) { - prompt = first ? "OpenSSL> " : "> "; - p[0] = '\0'; -#ifndef READLINE - fputs(prompt, stdout); - fflush(stdout); - if (!fgets(p, n, stdin)) - goto end; - if (p[0] == '\0') - goto end; - i = strlen(p); - if (i <= 1) - break; - if (p[i - 2] != '\\') - break; - i -= 2; - p += i; - n -= i; -#else - { - extern char *readline(const char *); - extern void add_history(const char *cp); - char *text; - - text = readline(prompt); - if (text == NULL) - goto end; - i = strlen(text); - if (i == 0 || i > n) - break; - if (text[i - 1] != '\\') { - p += strlen(strcpy(p, text)); - free(text); - add_history(buf); - break; - } - - text[i - 1] = '\0'; - p += strlen(strcpy(p, text)); - free(text); - n -= i; - } -#endif - } + /* If there's a command, run with that, otherwise "help". */ + ret = argc == 0 || global_help + ? do_cmd(prog, 1, help_argv) + : do_cmd(prog, argc, argv); - if (!chopup_args(&arg, buf)) { - BIO_printf(bio_err, "Can't parse (no memory?)\n"); - break; - } - - ret = do_cmd(prog, arg.argc, arg.argv); - if (ret == EXIT_THE_PROGRAM) { - ret = 0; - goto end; - } - if (ret != 0) - BIO_printf(bio_err, "error in %s\n", arg.argv[0]); - (void)BIO_flush(bio_out); - (void)BIO_flush(bio_err); - } - ret = 1; end: OPENSSL_free(default_config_file); lh_FUNCTION_free(prog); OPENSSL_free(arg.argv); - app_RAND_write(); + if (!app_RAND_write()) + ret = EXIT_FAILURE; BIO_free(bio_in); BIO_free_all(bio_out); apps_shutdown(); -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - if (CRYPTO_mem_leaks(bio_err) <= 0) - ret = 1; -#endif - BIO_free(bio_err); + BIO_free_all(bio_err); EXIT(ret); } -static void list_cipher_fn(const EVP_CIPHER *c, - const char *from, const char *to, void *arg) -{ - if (c != NULL) { - BIO_printf(arg, "%s\n", EVP_CIPHER_name(c)); - } else { - if (from == NULL) - from = ""; - if (to == NULL) - to = ""; - BIO_printf(arg, "%s => %s\n", from, to); - } -} - -static void list_md_fn(const EVP_MD *m, - const char *from, const char *to, void *arg) -{ - if (m != NULL) { - BIO_printf(arg, "%s\n", EVP_MD_name(m)); - } else { - if (from == NULL) - from = ""; - if (to == NULL) - to = ""; - BIO_printf((BIO *)arg, "%s => %s\n", from, to); - } -} - -static void list_missing_help(void) -{ - const FUNCTION *fp; - const OPTIONS *o; - - for (fp = functions; fp->name != NULL; fp++) { - if ((o = fp->help) != NULL) { - /* If there is help, list what flags are not documented. */ - for ( ; o->name != NULL; o++) { - if (o->helpstr == NULL) - BIO_printf(bio_out, "%s %s\n", fp->name, o->name); - } - } else if (fp->func != dgst_main) { - /* If not aliased to the dgst command, */ - BIO_printf(bio_out, "%s *\n", fp->name); - } - } -} - -static void list_options_for_command(const char *command) -{ - const FUNCTION *fp; - const OPTIONS *o; - - for (fp = functions; fp->name != NULL; fp++) - if (strcmp(fp->name, command) == 0) - break; - if (fp->name == NULL) { - BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", - command); - return; - } - - if ((o = fp->help) == NULL) - return; - - for ( ; o->name != NULL; o++) { - if (o->name == OPT_HELP_STR - || o->name == OPT_MORE_STR - || o->name[0] == '\0') - continue; - BIO_printf(bio_out, "%s %c\n", o->name, o->valtype); - } -} - - -/* Unified enum for help and list commands. */ -typedef enum HELPLIST_CHOICE { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE, - OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_OPTIONS, - OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS, - OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_MISSING_HELP -} HELPLIST_CHOICE; - -const OPTIONS list_options[] = { - {"help", OPT_HELP, '-', "Display this summary"}, - {"1", OPT_ONE, '-', "List in one column"}, - {"commands", OPT_COMMANDS, '-', "List of standard commands"}, - {"digest-commands", OPT_DIGEST_COMMANDS, '-', - "List of message digest commands"}, - {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-', - "List of message digest algorithms"}, - {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"}, - {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-', - "List of cipher algorithms"}, - {"public-key-algorithms", OPT_PK_ALGORITHMS, '-', - "List of public key algorithms"}, - {"public-key-methods", OPT_PK_METHOD, '-', - "List of public key methods"}, - {"disabled", OPT_DISABLED, '-', - "List of disabled features"}, - {"missing-help", OPT_MISSING_HELP, '-', - "List missing detailed help strings"}, - {"options", OPT_OPTIONS, 's', - "List options for specified command"}, - {NULL} -}; - -int list_main(int argc, char **argv) -{ - char *prog; - HELPLIST_CHOICE o; - int one = 0, done = 0; - - prog = opt_init(argc, argv, list_options); - while ((o = opt_next()) != OPT_EOF) { - switch (o) { - case OPT_EOF: /* Never hit, but suppresses warning */ - case OPT_ERR: -opthelp: - BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - return 1; - case OPT_HELP: - opt_help(list_options); - break; - case OPT_ONE: - one = 1; - break; - case OPT_COMMANDS: - list_type(FT_general, one); - break; - case OPT_DIGEST_COMMANDS: - list_type(FT_md, one); - break; - case OPT_DIGEST_ALGORITHMS: - EVP_MD_do_all_sorted(list_md_fn, bio_out); - break; - case OPT_CIPHER_COMMANDS: - list_type(FT_cipher, one); - break; - case OPT_CIPHER_ALGORITHMS: - EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out); - break; - case OPT_PK_ALGORITHMS: - list_pkey(); - break; - case OPT_PK_METHOD: - list_pkey_meth(); - break; - case OPT_DISABLED: - list_disabled(); - break; - case OPT_MISSING_HELP: - list_missing_help(); - break; - case OPT_OPTIONS: - list_options_for_command(opt_arg()); - break; - } - done = 1; - } - if (opt_num_rest() != 0) { - BIO_printf(bio_err, "Extra arguments given.\n"); - goto opthelp; - } - - if (!done) - goto opthelp; - - return 0; -} - typedef enum HELP_CHOICE { OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP } HELP_CHOICE; const OPTIONS help_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: help [options]\n"}, - {OPT_HELP_STR, 1, '-', " help [command]\n"}, + {OPT_HELP_STR, 1, '-', "Usage: help [options] [command]\n"}, + + OPT_SECTION("General"), {"help", OPT_hHELP, '-', "Display this summary"}, + + OPT_PARAMETERS(), + {"command", 0, 0, "Name of command to display help (optional)"}, {NULL} }; @@ -463,6 +335,7 @@ char *prog; HELP_CHOICE o; DISPLAY_COLUMNS dc; + char *new_argv[3]; prog = opt_init(argc, argv, help_options); while ((o = opt_next()) != OPT_hEOF) { @@ -477,9 +350,8 @@ } } + /* One optional argument, the command to get help for. */ if (opt_num_rest() == 1) { - char *new_argv[3]; - new_argv[0] = opt_rest()[0]; new_argv[1] = "--help"; new_argv[2] = NULL; @@ -490,8 +362,8 @@ return 1; } - calculate_columns(&dc); - BIO_printf(bio_err, "Standard commands"); + calculate_columns(functions, &dc); + BIO_printf(bio_err, "%s:\n\nStandard commands", prog); i = 0; tp = FT_none; for (fp = functions; fp->name != NULL; fp++) { @@ -520,37 +392,13 @@ return 0; } -static void list_type(FUNC_TYPE ft, int one) -{ - FUNCTION *fp; - int i = 0; - DISPLAY_COLUMNS dc = {0}; - - if (!one) - calculate_columns(&dc); - - for (fp = functions; fp->name != NULL; fp++) { - if (fp->type != ft) - continue; - if (one) { - BIO_printf(bio_out, "%s\n", fp->name); - } else { - if (i % dc.columns == 0 && i > 0) - BIO_printf(bio_out, "\n"); - BIO_printf(bio_out, "%-*s", dc.width, fp->name); - i++; - } - } - if (!one) - BIO_printf(bio_out, "\n\n"); -} - static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) { FUNCTION f, *fp; if (argc <= 0 || argv[0] == NULL) return 0; + memset(&f, 0, sizeof(f)); f.name = argv[0]; fp = lh_FUNCTION_retrieve(prog, &f); if (fp == NULL) { @@ -565,6 +413,8 @@ } } if (fp != NULL) { + if (fp->deprecated_alternative != NULL) + warn_deprecated(fp); return fp->func(argc, argv); } if ((strncmp(argv[0], "no-", 3)) == 0) { @@ -580,61 +430,12 @@ BIO_printf(bio_out, "%s\n", argv[0] + 3); return 1; } - if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 || - strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0) - /* Special value to mean "exit the program. */ - return EXIT_THE_PROGRAM; BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", argv[0]); return 1; } -static void list_pkey(void) -{ - int i; - - for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { - const EVP_PKEY_ASN1_METHOD *ameth; - int pkey_id, pkey_base_id, pkey_flags; - const char *pinfo, *pem_str; - ameth = EVP_PKEY_asn1_get0(i); - EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, - &pinfo, &pem_str, ameth); - if (pkey_flags & ASN1_PKEY_ALIAS) { - BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id)); - BIO_printf(bio_out, "\tAlias for: %s\n", - OBJ_nid2ln(pkey_base_id)); - } else { - BIO_printf(bio_out, "Name: %s\n", pinfo); - BIO_printf(bio_out, "\tType: %s Algorithm\n", - pkey_flags & ASN1_PKEY_DYNAMIC ? - "External" : "Builtin"); - BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); - if (pem_str == NULL) - pem_str = "(none)"; - BIO_printf(bio_out, "\tPEM string: %s\n", pem_str); - } - - } -} - -static void list_pkey_meth(void) -{ - size_t i; - size_t meth_count = EVP_PKEY_meth_get_count(); - - for (i = 0; i < meth_count; i++) { - const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i); - int pkey_id, pkey_flags; - - EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth); - BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id)); - BIO_printf(bio_out, "\tType: %s Algorithm\n", - pkey_flags & ASN1_PKEY_DYNAMIC ? "External" : "Builtin"); - } -} - static int function_cmp(const FUNCTION * a, const FUNCTION * b) { return strncmp(a->name, b->name, 8); @@ -655,155 +456,6 @@ return strcmp(f1->name, f2->name); } -static void list_disabled(void) -{ - BIO_puts(bio_out, "Disabled algorithms:\n"); -#ifdef OPENSSL_NO_ARIA - BIO_puts(bio_out, "ARIA\n"); -#endif -#ifdef OPENSSL_NO_BF - BIO_puts(bio_out, "BF\n"); -#endif -#ifdef OPENSSL_NO_BLAKE2 - BIO_puts(bio_out, "BLAKE2\n"); -#endif -#ifdef OPENSSL_NO_CAMELLIA - BIO_puts(bio_out, "CAMELLIA\n"); -#endif -#ifdef OPENSSL_NO_CAST - BIO_puts(bio_out, "CAST\n"); -#endif -#ifdef OPENSSL_NO_CMAC - BIO_puts(bio_out, "CMAC\n"); -#endif -#ifdef OPENSSL_NO_CMS - BIO_puts(bio_out, "CMS\n"); -#endif -#ifdef OPENSSL_NO_COMP - BIO_puts(bio_out, "COMP\n"); -#endif -#ifdef OPENSSL_NO_DES - BIO_puts(bio_out, "DES\n"); -#endif -#ifdef OPENSSL_NO_DGRAM - BIO_puts(bio_out, "DGRAM\n"); -#endif -#ifdef OPENSSL_NO_DH - BIO_puts(bio_out, "DH\n"); -#endif -#ifdef OPENSSL_NO_DSA - BIO_puts(bio_out, "DSA\n"); -#endif -#if defined(OPENSSL_NO_DTLS) - BIO_puts(bio_out, "DTLS\n"); -#endif -#if defined(OPENSSL_NO_DTLS1) - BIO_puts(bio_out, "DTLS1\n"); -#endif -#if defined(OPENSSL_NO_DTLS1_2) - BIO_puts(bio_out, "DTLS1_2\n"); -#endif -#ifdef OPENSSL_NO_EC - BIO_puts(bio_out, "EC\n"); -#endif -#ifdef OPENSSL_NO_EC2M - BIO_puts(bio_out, "EC2M\n"); -#endif -#ifdef OPENSSL_NO_ENGINE - BIO_puts(bio_out, "ENGINE\n"); -#endif -#ifdef OPENSSL_NO_GOST - BIO_puts(bio_out, "GOST\n"); -#endif -#ifdef OPENSSL_NO_HEARTBEATS - BIO_puts(bio_out, "HEARTBEATS\n"); -#endif -#ifdef OPENSSL_NO_IDEA - BIO_puts(bio_out, "IDEA\n"); -#endif -#ifdef OPENSSL_NO_MD2 - BIO_puts(bio_out, "MD2\n"); -#endif -#ifdef OPENSSL_NO_MD4 - BIO_puts(bio_out, "MD4\n"); -#endif -#ifdef OPENSSL_NO_MD5 - BIO_puts(bio_out, "MD5\n"); -#endif -#ifdef OPENSSL_NO_MDC2 - BIO_puts(bio_out, "MDC2\n"); -#endif -#ifdef OPENSSL_NO_OCB - BIO_puts(bio_out, "OCB\n"); -#endif -#ifdef OPENSSL_NO_OCSP - BIO_puts(bio_out, "OCSP\n"); -#endif -#ifdef OPENSSL_NO_PSK - BIO_puts(bio_out, "PSK\n"); -#endif -#ifdef OPENSSL_NO_RC2 - BIO_puts(bio_out, "RC2\n"); -#endif -#ifdef OPENSSL_NO_RC4 - BIO_puts(bio_out, "RC4\n"); -#endif -#ifdef OPENSSL_NO_RC5 - BIO_puts(bio_out, "RC5\n"); -#endif -#ifdef OPENSSL_NO_RMD160 - BIO_puts(bio_out, "RMD160\n"); -#endif -#ifdef OPENSSL_NO_RSA - BIO_puts(bio_out, "RSA\n"); -#endif -#ifdef OPENSSL_NO_SCRYPT - BIO_puts(bio_out, "SCRYPT\n"); -#endif -#ifdef OPENSSL_NO_SCTP - BIO_puts(bio_out, "SCTP\n"); -#endif -#ifdef OPENSSL_NO_SEED - BIO_puts(bio_out, "SEED\n"); -#endif -#ifdef OPENSSL_NO_SM2 - BIO_puts(bio_out, "SM2\n"); -#endif -#ifdef OPENSSL_NO_SM3 - BIO_puts(bio_out, "SM3\n"); -#endif -#ifdef OPENSSL_NO_SM4 - BIO_puts(bio_out, "SM4\n"); -#endif -#ifdef OPENSSL_NO_SOCK - BIO_puts(bio_out, "SOCK\n"); -#endif -#ifdef OPENSSL_NO_SRP - BIO_puts(bio_out, "SRP\n"); -#endif -#ifdef OPENSSL_NO_SRTP - BIO_puts(bio_out, "SRTP\n"); -#endif -#ifdef OPENSSL_NO_SSL3 - BIO_puts(bio_out, "SSL3\n"); -#endif -#ifdef OPENSSL_NO_TLS1 - BIO_puts(bio_out, "TLS1\n"); -#endif -#ifdef OPENSSL_NO_TLS1_1 - BIO_puts(bio_out, "TLS1_1\n"); -#endif -#ifdef OPENSSL_NO_TLS1_2 - BIO_puts(bio_out, "TLS1_2\n"); -#endif -#ifdef OPENSSL_NO_WHIRLPOOL - BIO_puts(bio_out, "WHIRLPOOL\n"); -#endif -#ifndef ZLIB - BIO_puts(bio_out, "ZLIB\n"); -#endif -} - static LHASH_OF(FUNCTION) *prog_init(void) { static LHASH_OF(FUNCTION) *ret = NULL; diff --git a/apps/openssl.cnf b/apps/openssl.cnf --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -1,7 +1,9 @@ # # OpenSSL example configuration file. -# This is mostly being used for generation of certificate requests. +# See doc/man5/config.pod for more info. # +# This is mostly being used for generation of certificate requests, +# but may be used for auto loading of providers # Note that you can include other files from the main configuration # file using the .include directive. @@ -11,9 +13,15 @@ # defined. HOME = . + # Use this in order to automatically load providers. +openssl_conf = openssl_init + +# Comment out the next line to ignore configuration errors +config_diagnostics = 1 + # Extra OBJECT IDENTIFIER info: -#oid_file = $ENV::HOME/.oid -oid_section = new_oids +# oid_file = $ENV::HOME/.oid +oid_section = new_oids # To use this configuration file with the "-extfile" option of the # "openssl x509" utility, name here the section containing the @@ -23,7 +31,6 @@ # X.509v3 extensions in its main [= default] section.) [ new_oids ] - # We can add new OIDs in here for use by 'ca', 'req' and 'ts'. # Add a simple OID like this: # testoid1=1.2.3.4 @@ -35,6 +42,36 @@ tsa_policy2 = 1.2.3.4.5.6 tsa_policy3 = 1.2.3.4.5.7 +# For FIPS +# Optionally include a file that is generated by the OpenSSL fipsinstall +# application. This file contains configuration data required by the OpenSSL +# fips provider. It contains a named section e.g. [fips_sect] which is +# referenced from the [provider_sect] below. +# Refer to the OpenSSL security policy for more information. +# .include fipsmodule.cnf + +[openssl_init] +providers = provider_sect + +# List of providers to load +[provider_sect] +default = default_sect +# The fips section name should match the section name inside the +# included fipsmodule.cnf. +# fips = fips_sect + +# If no providers are activated explicitly, the default one is activated implicitly. +# See man 7 OSSL_PROVIDER-default for more details. +# +# If you add a section explicitly activating any other provider(s), you most +# probably need to explicitly activate the default provider, otherwise it +# becomes unavailable in openssl. As a consequence applications depending on +# OpenSSL may not work correctly which could lead to significant system +# problems including inability to remotely access the system. +[default_sect] +# activate = 1 + + #################################################################### [ ca ] default_ca = CA_default # The default ca section @@ -171,27 +208,9 @@ basicConstraints=CA:FALSE -# Here are some examples of the usage of nsCertType. If it is omitted -# the certificate can be used for anything *except* object signing. - -# This is OK for an SSL server. -# nsCertType = server - -# For an object signing certificate this would be used. -# nsCertType = objsign - -# For normal client use this is typical -# nsCertType = client, email - -# and for everything including object signing: -# nsCertType = client, email, objsign - # This is typical in keyUsage for a client certificate. # keyUsage = nonRepudiation, digitalSignature, keyEncipherment -# This will be displayed in Netscape's comment listbox. -nsComment = "OpenSSL Generated Certificate" - # PKIX recommendations harmless if included in all certificates. subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer @@ -206,13 +225,6 @@ # Copy subject details # issuerAltName=issuer:copy -#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem -#nsBaseUrl -#nsRevocationUrl -#nsRenewalUrl -#nsCaPolicyUrl -#nsSslServerName - # This is required for TSA certificates. # extendedKeyUsage = critical,timeStamping @@ -242,9 +254,6 @@ # left out by default. # keyUsage = cRLSign, keyCertSign -# Some might want this also -# nsCertType = sslCA, emailCA - # Include email address in subject alt name: another PKIX recommendation # subjectAltName=email:copy # Copy issuer details @@ -272,27 +281,9 @@ basicConstraints=CA:FALSE -# Here are some examples of the usage of nsCertType. If it is omitted -# the certificate can be used for anything *except* object signing. - -# This is OK for an SSL server. -# nsCertType = server - -# For an object signing certificate this would be used. -# nsCertType = objsign - -# For normal client use this is typical -# nsCertType = client, email - -# and for everything including object signing: -# nsCertType = client, email, objsign - # This is typical in keyUsage for a client certificate. # keyUsage = nonRepudiation, digitalSignature, keyEncipherment -# This will be displayed in Netscape's comment listbox. -nsComment = "OpenSSL Generated Certificate" - # PKIX recommendations harmless if included in all certificates. subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer @@ -307,13 +298,6 @@ # Copy subject details # issuerAltName=issuer:copy -#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem -#nsBaseUrl -#nsRevocationUrl -#nsRenewalUrl -#nsCaPolicyUrl -#nsSslServerName - # This really needs to be in place for it to be a proxy certificate. proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo @@ -348,3 +332,59 @@ # (optional, default: no) ess_cert_id_alg = sha1 # algorithm to compute certificate # identifier (optional, default: sha1) + +[insta] # CMP using Insta Demo CA +# Message transfer +server = pki.certificate.fi:8700 +# proxy = # set this as far as needed, e.g., http://192.168.1.1:8080 +# tls_use = 0 +path = pkix/ + +# Server authentication +recipient = "/C=FI/O=Insta Demo/CN=Insta Demo CA" # or set srvcert or issuer +ignore_keyusage = 1 # potentially needed quirk +unprotected_errors = 1 # potentially needed quirk +extracertsout = insta.extracerts.pem + +# Client authentication +ref = 3078 # user identification +secret = pass:insta # can be used for both client and server side + +# Generic message options +cmd = ir # default operation, can be overridden on cmd line with, e.g., kur + +# Certificate enrollment +subject = "/CN=openssl-cmp-test" +newkey = insta.priv.pem +out_trusted = insta.ca.crt +certout = insta.cert.pem + +[pbm] # Password-based protection for Insta CA +# Server and client authentication +ref = $insta::ref # 3078 +secret = $insta::secret # pass:insta + +[signature] # Signature-based protection for Insta CA +# Server authentication +trusted = insta.ca.crt # does not include keyUsage digitalSignature + +# Client authentication +secret = # disable PBM +key = $insta::newkey # insta.priv.pem +cert = $insta::certout # insta.cert.pem + +[ir] +cmd = ir + +[cr] +cmd = cr + +[kur] +# Certificate update +cmd = kur +oldcert = $insta::certout # insta.cert.pem + +[rr] +# Certificate revocation +cmd = rr +oldcert = $insta::certout # insta.cert.pem diff --git a/apps/opt.c b/apps/opt.c deleted file mode 100644 --- a/apps/opt.c +++ /dev/null @@ -1,898 +0,0 @@ -/* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ -#include "apps.h" -#include -#if !defined(OPENSSL_SYS_MSDOS) -# include OPENSSL_UNISTD -#endif - -#include -#include -#include -#include -#include -#include - -#define MAX_OPT_HELP_WIDTH 30 -const char OPT_HELP_STR[] = "--"; -const char OPT_MORE_STR[] = "---"; - -/* Our state */ -static char **argv; -static int argc; -static int opt_index; -static char *arg; -static char *flag; -static char *dunno; -static const OPTIONS *unknown; -static const OPTIONS *opts; -static char prog[40]; - -/* - * Return the simple name of the program; removing various platform gunk. - */ -#if defined(OPENSSL_SYS_WIN32) -char *opt_progname(const char *argv0) -{ - size_t i, n; - const char *p; - char *q; - - /* find the last '/', '\' or ':' */ - for (p = argv0 + strlen(argv0); --p > argv0;) - if (*p == '/' || *p == '\\' || *p == ':') { - p++; - break; - } - - /* Strip off trailing nonsense. */ - n = strlen(p); - if (n > 4 && - (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0)) - n -= 4; - - /* Copy over the name, in lowercase. */ - if (n > sizeof(prog) - 1) - n = sizeof(prog) - 1; - for (q = prog, i = 0; i < n; i++, p++) - *q++ = tolower((unsigned char)*p); - *q = '\0'; - return prog; -} - -#elif defined(OPENSSL_SYS_VMS) - -char *opt_progname(const char *argv0) -{ - const char *p, *q; - - /* Find last special character sys:[foo.bar]openssl */ - for (p = argv0 + strlen(argv0); --p > argv0;) - if (*p == ':' || *p == ']' || *p == '>') { - p++; - break; - } - - q = strrchr(p, '.'); - strncpy(prog, p, sizeof(prog) - 1); - prog[sizeof(prog) - 1] = '\0'; - if (q != NULL && q - p < sizeof(prog)) - prog[q - p] = '\0'; - return prog; -} - -#else - -char *opt_progname(const char *argv0) -{ - const char *p; - - /* Could use strchr, but this is like the ones above. */ - for (p = argv0 + strlen(argv0); --p > argv0;) - if (*p == '/') { - p++; - break; - } - strncpy(prog, p, sizeof(prog) - 1); - prog[sizeof(prog) - 1] = '\0'; - return prog; -} -#endif - -char *opt_getprog(void) -{ - return prog; -} - -/* Set up the arg parsing. */ -char *opt_init(int ac, char **av, const OPTIONS *o) -{ - /* Store state. */ - argc = ac; - argv = av; - opt_index = 1; - opts = o; - opt_progname(av[0]); - unknown = NULL; - - for (; o->name; ++o) { -#ifndef NDEBUG - const OPTIONS *next; - int duplicated, i; -#endif - - if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR) - continue; -#ifndef NDEBUG - i = o->valtype; - - /* Make sure options are legit. */ - assert(o->name[0] != '-'); - assert(o->retval > 0); - switch (i) { - case 0: case '-': case '/': case '<': case '>': case 'E': case 'F': - case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': - case 'u': case 'c': - break; - default: - assert(0); - } - - /* Make sure there are no duplicates. */ - for (next = o + 1; next->name; ++next) { - /* - * Some compilers inline strcmp and the assert string is too long. - */ - duplicated = strcmp(o->name, next->name) == 0; - assert(!duplicated); - } -#endif - if (o->name[0] == '\0') { - assert(unknown == NULL); - unknown = o; - assert(unknown->valtype == 0 || unknown->valtype == '-'); - } - } - return prog; -} - -static OPT_PAIR formats[] = { - {"PEM/DER", OPT_FMT_PEMDER}, - {"pkcs12", OPT_FMT_PKCS12}, - {"smime", OPT_FMT_SMIME}, - {"engine", OPT_FMT_ENGINE}, - {"msblob", OPT_FMT_MSBLOB}, - {"nss", OPT_FMT_NSS}, - {"text", OPT_FMT_TEXT}, - {"http", OPT_FMT_HTTP}, - {"pvk", OPT_FMT_PVK}, - {NULL} -}; - -/* Print an error message about a failed format parse. */ -int opt_format_error(const char *s, unsigned long flags) -{ - OPT_PAIR *ap; - - if (flags == OPT_FMT_PEMDER) { - BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n", - prog, s); - } else { - BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n", - prog, s); - for (ap = formats; ap->name; ap++) - if (flags & ap->retval) - BIO_printf(bio_err, " %s\n", ap->name); - } - return 0; -} - -/* Parse a format string, put it into *result; return 0 on failure, else 1. */ -int opt_format(const char *s, unsigned long flags, int *result) -{ - switch (*s) { - default: - return 0; - case 'D': - case 'd': - if ((flags & OPT_FMT_PEMDER) == 0) - return opt_format_error(s, flags); - *result = FORMAT_ASN1; - break; - case 'T': - case 't': - if ((flags & OPT_FMT_TEXT) == 0) - return opt_format_error(s, flags); - *result = FORMAT_TEXT; - break; - case 'N': - case 'n': - if ((flags & OPT_FMT_NSS) == 0) - return opt_format_error(s, flags); - if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0) - return opt_format_error(s, flags); - *result = FORMAT_NSS; - break; - case 'S': - case 's': - if ((flags & OPT_FMT_SMIME) == 0) - return opt_format_error(s, flags); - *result = FORMAT_SMIME; - break; - case 'M': - case 'm': - if ((flags & OPT_FMT_MSBLOB) == 0) - return opt_format_error(s, flags); - *result = FORMAT_MSBLOB; - break; - case 'E': - case 'e': - if ((flags & OPT_FMT_ENGINE) == 0) - return opt_format_error(s, flags); - *result = FORMAT_ENGINE; - break; - case 'H': - case 'h': - if ((flags & OPT_FMT_HTTP) == 0) - return opt_format_error(s, flags); - *result = FORMAT_HTTP; - break; - case '1': - if ((flags & OPT_FMT_PKCS12) == 0) - return opt_format_error(s, flags); - *result = FORMAT_PKCS12; - break; - case 'P': - case 'p': - if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { - if ((flags & OPT_FMT_PEMDER) == 0) - return opt_format_error(s, flags); - *result = FORMAT_PEM; - } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { - if ((flags & OPT_FMT_PVK) == 0) - return opt_format_error(s, flags); - *result = FORMAT_PVK; - } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0 - || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) { - if ((flags & OPT_FMT_PKCS12) == 0) - return opt_format_error(s, flags); - *result = FORMAT_PKCS12; - } else { - return 0; - } - break; - } - return 1; -} - -/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */ -int opt_cipher(const char *name, const EVP_CIPHER **cipherp) -{ - *cipherp = EVP_get_cipherbyname(name); - if (*cipherp != NULL) - return 1; - BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); - return 0; -} - -/* - * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. - */ -int opt_md(const char *name, const EVP_MD **mdp) -{ - *mdp = EVP_get_digestbyname(name); - if (*mdp != NULL) - return 1; - BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); - return 0; -} - -/* Look through a list of name/value pairs. */ -int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) -{ - const OPT_PAIR *pp; - - for (pp = pairs; pp->name; pp++) - if (strcmp(pp->name, name) == 0) { - *result = pp->retval; - return 1; - } - BIO_printf(bio_err, "%s: Value must be one of:\n", prog); - for (pp = pairs; pp->name; pp++) - BIO_printf(bio_err, "\t%s\n", pp->name); - return 0; -} - -/* Parse an int, put it into *result; return 0 on failure, else 1. */ -int opt_int(const char *value, int *result) -{ - long l; - - if (!opt_long(value, &l)) - return 0; - *result = (int)l; - if (*result != l) { - BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n", - prog, value); - return 0; - } - return 1; -} - -static void opt_number_error(const char *v) -{ - size_t i = 0; - struct strstr_pair_st { - char *prefix; - char *name; - } b[] = { - {"0x", "a hexadecimal"}, - {"0X", "a hexadecimal"}, - {"0", "an octal"} - }; - - for (i = 0; i < OSSL_NELEM(b); i++) { - if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { - BIO_printf(bio_err, - "%s: Can't parse \"%s\" as %s number\n", - prog, v, b[i].name); - return; - } - } - BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v); - return; -} - -/* Parse a long, put it into *result; return 0 on failure, else 1. */ -int opt_long(const char *value, long *result) -{ - int oerrno = errno; - long l; - char *endp; - - errno = 0; - l = strtol(value, &endp, 0); - if (*endp - || endp == value - || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) - || (l == 0 && errno != 0)) { - opt_number_error(value); - errno = oerrno; - return 0; - } - *result = l; - errno = oerrno; - return 1; -} - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ - defined(INTMAX_MAX) && defined(UINTMAX_MAX) - -/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ -int opt_imax(const char *value, intmax_t *result) -{ - int oerrno = errno; - intmax_t m; - char *endp; - - errno = 0; - m = strtoimax(value, &endp, 0); - if (*endp - || endp == value - || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE) - || (m == 0 && errno != 0)) { - opt_number_error(value); - errno = oerrno; - return 0; - } - *result = m; - errno = oerrno; - return 1; -} - -/* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ -int opt_umax(const char *value, uintmax_t *result) -{ - int oerrno = errno; - uintmax_t m; - char *endp; - - errno = 0; - m = strtoumax(value, &endp, 0); - if (*endp - || endp == value - || (m == UINTMAX_MAX && errno == ERANGE) - || (m == 0 && errno != 0)) { - opt_number_error(value); - errno = oerrno; - return 0; - } - *result = m; - errno = oerrno; - return 1; -} -#endif - -/* - * Parse an unsigned long, put it into *result; return 0 on failure, else 1. - */ -int opt_ulong(const char *value, unsigned long *result) -{ - int oerrno = errno; - char *endptr; - unsigned long l; - - errno = 0; - l = strtoul(value, &endptr, 0); - if (*endptr - || endptr == value - || ((l == ULONG_MAX) && errno == ERANGE) - || (l == 0 && errno != 0)) { - opt_number_error(value); - errno = oerrno; - return 0; - } - *result = l; - errno = oerrno; - return 1; -} - -/* - * We pass opt as an int but cast it to "enum range" so that all the - * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch - * in gcc do the right thing. - */ -enum range { OPT_V_ENUM }; - -int opt_verify(int opt, X509_VERIFY_PARAM *vpm) -{ - int i; - ossl_intmax_t t = 0; - ASN1_OBJECT *otmp; - X509_PURPOSE *xptmp; - const X509_VERIFY_PARAM *vtmp; - - assert(vpm != NULL); - assert(opt > OPT_V__FIRST); - assert(opt < OPT_V__LAST); - - switch ((enum range)opt) { - case OPT_V__FIRST: - case OPT_V__LAST: - return 0; - case OPT_V_POLICY: - otmp = OBJ_txt2obj(opt_arg(), 0); - if (otmp == NULL) { - BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg()); - return 0; - } - X509_VERIFY_PARAM_add0_policy(vpm, otmp); - break; - case OPT_V_PURPOSE: - /* purpose name -> purpose index */ - i = X509_PURPOSE_get_by_sname(opt_arg()); - if (i < 0) { - BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg()); - return 0; - } - - /* purpose index -> purpose object */ - xptmp = X509_PURPOSE_get0(i); - - /* purpose object -> purpose value */ - i = X509_PURPOSE_get_id(xptmp); - - if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { - BIO_printf(bio_err, - "%s: Internal error setting purpose %s\n", - prog, opt_arg()); - return 0; - } - break; - case OPT_V_VERIFY_NAME: - vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); - if (vtmp == NULL) { - BIO_printf(bio_err, "%s: Invalid verify name %s\n", - prog, opt_arg()); - return 0; - } - X509_VERIFY_PARAM_set1(vpm, vtmp); - break; - case OPT_V_VERIFY_DEPTH: - i = atoi(opt_arg()); - if (i >= 0) - X509_VERIFY_PARAM_set_depth(vpm, i); - break; - case OPT_V_VERIFY_AUTH_LEVEL: - i = atoi(opt_arg()); - if (i >= 0) - X509_VERIFY_PARAM_set_auth_level(vpm, i); - break; - case OPT_V_ATTIME: - if (!opt_imax(opt_arg(), &t)) - return 0; - if (t != (time_t)t) { - BIO_printf(bio_err, "%s: epoch time out of range %s\n", - prog, opt_arg()); - return 0; - } - X509_VERIFY_PARAM_set_time(vpm, (time_t)t); - break; - case OPT_V_VERIFY_HOSTNAME: - if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) - return 0; - break; - case OPT_V_VERIFY_EMAIL: - if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) - return 0; - break; - case OPT_V_VERIFY_IP: - if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) - return 0; - break; - case OPT_V_IGNORE_CRITICAL: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); - break; - case OPT_V_ISSUER_CHECKS: - /* NOP, deprecated */ - break; - case OPT_V_CRL_CHECK: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); - break; - case OPT_V_CRL_CHECK_ALL: - X509_VERIFY_PARAM_set_flags(vpm, - X509_V_FLAG_CRL_CHECK | - X509_V_FLAG_CRL_CHECK_ALL); - break; - case OPT_V_POLICY_CHECK: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); - break; - case OPT_V_EXPLICIT_POLICY: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); - break; - case OPT_V_INHIBIT_ANY: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); - break; - case OPT_V_INHIBIT_MAP: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); - break; - case OPT_V_X509_STRICT: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); - break; - case OPT_V_EXTENDED_CRL: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); - break; - case OPT_V_USE_DELTAS: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); - break; - case OPT_V_POLICY_PRINT: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); - break; - case OPT_V_CHECK_SS_SIG: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); - break; - case OPT_V_TRUSTED_FIRST: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); - break; - case OPT_V_SUITEB_128_ONLY: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); - break; - case OPT_V_SUITEB_128: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); - break; - case OPT_V_SUITEB_192: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); - break; - case OPT_V_PARTIAL_CHAIN: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); - break; - case OPT_V_NO_ALT_CHAINS: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); - break; - case OPT_V_NO_CHECK_TIME: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); - break; - case OPT_V_ALLOW_PROXY_CERTS: - X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); - break; - } - return 1; - -} - -/* - * Parse the next flag (and value if specified), return 0 if done, -1 on - * error, otherwise the flag's retval. - */ -int opt_next(void) -{ - char *p; - const OPTIONS *o; - int ival; - long lval; - unsigned long ulval; - ossl_intmax_t imval; - ossl_uintmax_t umval; - - /* Look at current arg; at end of the list? */ - arg = NULL; - p = argv[opt_index]; - if (p == NULL) - return 0; - - /* If word doesn't start with a -, we're done. */ - if (*p != '-') - return 0; - - /* Hit "--" ? We're done. */ - opt_index++; - if (strcmp(p, "--") == 0) - return 0; - - /* Allow -nnn and --nnn */ - if (*++p == '-') - p++; - flag = p - 1; - - /* If we have --flag=foo, snip it off */ - if ((arg = strchr(p, '=')) != NULL) - *arg++ = '\0'; - for (o = opts; o->name; ++o) { - /* If not this option, move on to the next one. */ - if (strcmp(p, o->name) != 0) - continue; - - /* If it doesn't take a value, make sure none was given. */ - if (o->valtype == 0 || o->valtype == '-') { - if (arg) { - BIO_printf(bio_err, - "%s: Option -%s does not take a value\n", prog, p); - return -1; - } - return o->retval; - } - - /* Want a value; get the next param if =foo not used. */ - if (arg == NULL) { - if (argv[opt_index] == NULL) { - BIO_printf(bio_err, - "%s: Option -%s needs a value\n", prog, o->name); - return -1; - } - arg = argv[opt_index++]; - } - - /* Syntax-check value. */ - switch (o->valtype) { - default: - case 's': - /* Just a string. */ - break; - case '/': - if (app_isdir(arg) > 0) - break; - BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg); - return -1; - case '<': - /* Input file. */ - break; - case '>': - /* Output file. */ - break; - case 'p': - case 'n': - if (!opt_int(arg, &ival) - || (o->valtype == 'p' && ival <= 0)) { - BIO_printf(bio_err, - "%s: Non-positive number \"%s\" for -%s\n", - prog, arg, o->name); - return -1; - } - break; - case 'M': - if (!opt_imax(arg, &imval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); - return -1; - } - break; - case 'U': - if (!opt_umax(arg, &umval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); - return -1; - } - break; - case 'l': - if (!opt_long(arg, &lval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); - return -1; - } - break; - case 'u': - if (!opt_ulong(arg, &ulval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); - return -1; - } - break; - case 'c': - case 'E': - case 'F': - case 'f': - if (opt_format(arg, - o->valtype == 'c' ? OPT_FMT_PDS : - o->valtype == 'E' ? OPT_FMT_PDE : - o->valtype == 'F' ? OPT_FMT_PEMDER - : OPT_FMT_ANY, &ival)) - break; - BIO_printf(bio_err, - "%s: Invalid format \"%s\" for -%s\n", - prog, arg, o->name); - return -1; - } - - /* Return the flag value. */ - return o->retval; - } - if (unknown != NULL) { - dunno = p; - return unknown->retval; - } - BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p); - return -1; -} - -/* Return the most recent flag parameter. */ -char *opt_arg(void) -{ - return arg; -} - -/* Return the most recent flag. */ -char *opt_flag(void) -{ - return flag; -} - -/* Return the unknown option. */ -char *opt_unknown(void) -{ - return dunno; -} - -/* Return the rest of the arguments after parsing flags. */ -char **opt_rest(void) -{ - return &argv[opt_index]; -} - -/* How many items in remaining args? */ -int opt_num_rest(void) -{ - int i = 0; - char **pp; - - for (pp = opt_rest(); *pp; pp++, i++) - continue; - return i; -} - -/* Return a string describing the parameter type. */ -static const char *valtype2param(const OPTIONS *o) -{ - switch (o->valtype) { - case 0: - case '-': - return ""; - case 's': - return "val"; - case '/': - return "dir"; - case '<': - return "infile"; - case '>': - return "outfile"; - case 'p': - return "+int"; - case 'n': - return "int"; - case 'l': - return "long"; - case 'u': - return "ulong"; - case 'E': - return "PEM|DER|ENGINE"; - case 'F': - return "PEM|DER"; - case 'f': - return "format"; - case 'M': - return "intmax"; - case 'U': - return "uintmax"; - } - return "parm"; -} - -void opt_help(const OPTIONS *list) -{ - const OPTIONS *o; - int i; - int standard_prolog; - int width = 5; - char start[80 + 1]; - char *p; - const char *help; - - /* Starts with its own help message? */ - standard_prolog = list[0].name != OPT_HELP_STR; - - /* Find the widest help. */ - for (o = list; o->name; o++) { - if (o->name == OPT_MORE_STR) - continue; - i = 2 + (int)strlen(o->name); - if (o->valtype != '-') - i += 1 + strlen(valtype2param(o)); - if (i < MAX_OPT_HELP_WIDTH && i > width) - width = i; - assert(i < (int)sizeof(start)); - } - - if (standard_prolog) - BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n", - prog); - - /* Now let's print. */ - for (o = list; o->name; o++) { - help = o->helpstr ? o->helpstr : "(No additional info)"; - if (o->name == OPT_HELP_STR) { - BIO_printf(bio_err, help, prog); - continue; - } - - /* Pad out prefix */ - memset(start, ' ', sizeof(start) - 1); - start[sizeof(start) - 1] = '\0'; - - if (o->name == OPT_MORE_STR) { - /* Continuation of previous line; pad and print. */ - start[width] = '\0'; - BIO_printf(bio_err, "%s %s\n", start, help); - continue; - } - - /* Build up the "-flag [param]" part. */ - p = start; - *p++ = ' '; - *p++ = '-'; - if (o->name[0]) - p += strlen(strcpy(p, o->name)); - else - *p++ = '*'; - if (o->valtype != '-') { - *p++ = ' '; - p += strlen(strcpy(p, valtype2param(o))); - } - *p = ' '; - if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { - *p = '\0'; - BIO_printf(bio_err, "%s\n", start); - memset(start, ' ', sizeof(start)); - } - start[width] = '\0'; - BIO_printf(bio_err, "%s %s\n", start, help); - } -} diff --git a/apps/passwd.c b/apps/passwd.c --- a/apps/passwd.c +++ b/apps/passwd.c @@ -1,7 +1,7 @@ /* * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -16,13 +16,13 @@ #include #include #include -#ifndef OPENSSL_NO_DES +#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0) # include #endif #include #include -static unsigned const char cov_2char[64] = { +static const unsigned char cov_2char[64] = { /* from crypto/des/fcrypt.c */ 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, @@ -38,7 +38,6 @@ typedef enum { passwd_unset = 0, - passwd_crypt, passwd_md5, passwd_apr1, passwd_sha256, @@ -51,32 +50,43 @@ int reverse, size_t pw_maxlen, passwd_modes mode); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_IN, OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1, - OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN, - OPT_R_ENUM + OPT_1, OPT_5, OPT_6, OPT_AIXMD5, OPT_SALT, OPT_STDIN, + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS passwd_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [password]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Read passwords from file"}, {"noverify", OPT_NOVERIFY, '-', "Never verify when reading password from terminal"}, + {"stdin", OPT_STDIN, '-', "Read passwords from stdin"}, + + OPT_SECTION("Output"), {"quiet", OPT_QUIET, '-', "No warnings"}, {"table", OPT_TABLE, '-', "Format output as table"}, {"reverse", OPT_REVERSE, '-', "Switch table columns"}, + + OPT_SECTION("Cryptographic"), {"salt", OPT_SALT, 's', "Use provided salt"}, - {"stdin", OPT_STDIN, '-', "Read passwords from stdin"}, {"6", OPT_6, '-', "SHA512-based password algorithm"}, {"5", OPT_5, '-', "SHA256-based password algorithm"}, {"apr1", OPT_APR1, '-', "MD5-based password algorithm, Apache variant"}, {"1", OPT_1, '-', "MD5-based password algorithm"}, {"aixmd5", OPT_AIXMD5, '-', "AIX MD5-based password algorithm"}, -#ifndef OPENSSL_NO_DES - {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"}, -#endif + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"password", 0, 0, "Password text to digest (optional)"}, {NULL} }; @@ -154,13 +164,6 @@ goto opthelp; mode = passwd_aixmd5; break; - case OPT_CRYPT: -#ifndef OPENSSL_NO_DES - if (mode != passwd_unset) - goto opthelp; - mode = passwd_crypt; -#endif - break; case OPT_SALT: passed_salt = 1; salt = opt_arg(); @@ -175,11 +178,16 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* All remaining arguments are the password text */ argc = opt_num_rest(); argv = opt_rest(); - if (*argv != NULL) { if (pw_source_defined) goto opthelp; @@ -187,16 +195,14 @@ passwds = argv; } + if (!app_RAND_load()) + goto end; + if (mode == passwd_unset) { /* use default */ - mode = passwd_crypt; + mode = passwd_md5; } -#ifdef OPENSSL_NO_DES - if (mode == passwd_crypt) - goto opthelp; -#endif - if (infile != NULL && in_stdin) { BIO_printf(bio_err, "%s: Can't combine -in and -stdin\n", prog); goto end; @@ -212,9 +218,6 @@ goto end; } - if (mode == passwd_crypt) - pw_maxlen = 8; - if (passwds == NULL) { /* no passwords on the command line */ @@ -413,7 +416,7 @@ if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL)) goto err; if (!EVP_DigestUpdate(md2, - (i & 1) ? (unsigned const char *)passwd : buf, + (i & 1) ? (const unsigned char *)passwd : buf, (i & 1) ? passwd_len : sizeof(buf))) goto err; if (i % 3) { @@ -425,7 +428,7 @@ goto err; } if (!EVP_DigestUpdate(md2, - (i & 1) ? buf : (unsigned const char *)passwd, + (i & 1) ? buf : (const unsigned char *)passwd, (i & 1) ? sizeof(buf) : passwd_len)) goto err; if (!EVP_DigestFinal_ex(md2, buf, NULL)) @@ -515,7 +518,7 @@ EVP_MD_CTX *md = NULL, *md2 = NULL; const EVP_MD *sha = NULL; size_t passwd_len, salt_len, magic_len; - unsigned int rounds = 5000; /* Default */ + unsigned int rounds = ROUNDS_DEFAULT; /* Default */ char rounds_custom = 0; char *p_bytes = NULL; char *s_bytes = NULL; @@ -627,7 +630,7 @@ n = passwd_len; while (n) { if (!EVP_DigestUpdate(md, - (n & 1) ? buf : (unsigned const char *)passwd, + (n & 1) ? buf : (const unsigned char *)passwd, (n & 1) ? buf_size : passwd_len)) goto err; n >>= 1; @@ -673,7 +676,7 @@ if (!EVP_DigestInit_ex(md2, sha, NULL)) goto err; if (!EVP_DigestUpdate(md2, - (n & 1) ? (unsigned const char *)p_bytes : buf, + (n & 1) ? (const unsigned char *)p_bytes : buf, (n & 1) ? passwd_len : buf_size)) goto err; if (n % 3) { @@ -685,7 +688,7 @@ goto err; } if (!EVP_DigestUpdate(md2, - (n & 1) ? buf : (unsigned const char *)p_bytes, + (n & 1) ? buf : (const unsigned char *)p_bytes, (n & 1) ? buf_size : passwd_len)) goto err; if (!EVP_DigestFinal_ex(md2, buf, NULL)) @@ -785,11 +788,6 @@ size_t saltlen = 0; size_t i; -#ifndef OPENSSL_NO_DES - if (mode == passwd_crypt) - saltlen = 2; -#endif /* !OPENSSL_NO_DES */ - if (mode == passwd_md5 || mode == passwd_apr1 || mode == passwd_aixmd5) saltlen = 8; @@ -828,10 +826,6 @@ assert(strlen(passwd) <= pw_maxlen); /* now compute password hash */ -#ifndef OPENSSL_NO_DES - if (mode == passwd_crypt) - hash = DES_crypt(passwd, *salt_p); -#endif if (mode == passwd_md5 || mode == passwd_apr1) hash = md5crypt(passwd, (mode == passwd_md5 ? "1" : "apr1"), *salt_p); if (mode == passwd_aixmd5) diff --git a/apps/pkcs12.c b/apps/pkcs12.c --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -1,13 +1,14 @@ /* - * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include #include #include @@ -17,6 +18,8 @@ #include #include #include +#include +#include #define NOKEYS 0x1 #define NOCERTS 0x2 @@ -26,7 +29,13 @@ #define PASSWD_BUF_SIZE 2048 +#define WARN_EXPORT(opt) \ + BIO_printf(bio_err, "Warning: -%s option ignored with -export\n", opt); +#define WARN_NO_EXPORT(opt) \ + BIO_printf(bio_err, "Warning: -%s option ignored without -export\n", opt); + static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) *untrusted_certs, STACK_OF(X509) **chain); int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, int passlen, int options, @@ -46,100 +55,131 @@ static int set_pbe(int *ppbe, const char *str); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS, OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER, - OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER, - OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE, - OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME, +#ifndef OPENSSL_NO_DES + OPT_DESCERT, +#endif + OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER, + OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE, + OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS, + OPT_NAME, OPT_CSP, OPT_CANAME, OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH, - OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE, - OPT_R_ENUM + OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE, + OPT_R_ENUM, OPT_PROV_ENUM, +#ifndef OPENSSL_NO_DES + OPT_LEGACY_ALG +#endif } OPTION_CHOICE; const OPTIONS pkcs12_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"out", OPT_OUT, '>', "Output file"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"password", OPT_PASSWORD, 's', "Set PKCS#12 import/export password source"}, + {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"}, {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"}, - {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"}, - {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"}, {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"}, - {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"}, - {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"}, - {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"}, - {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"}, - {"chain", OPT_CHAIN, '-', "Add certificate chain"}, - {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"}, - {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"}, -#ifndef OPENSSL_NO_RC2 - {"descert", OPT_DESCERT, '-', - "Encrypt output with 3DES (default RC2-40)"}, - {"certpbe", OPT_CERTPBE, 's', - "Certificate PBE algorithm (default RC2-40)"}, -#else - {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"}, - {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"}, + {"noout", OPT_NOOUT, '-', "Don't output anything, just verify PKCS#12 input"}, +#ifndef OPENSSL_NO_DES + {"legacy", OPT_LEGACY_ALG, '-', +# ifdef OPENSSL_NO_RC2 + "Use legacy encryption algorithm 3DES_CBC for keys and certs" +# else + "Use legacy encryption: 3DES_CBC for keys, RC2_CBC for certs" +# endif + }, #endif - {"export", OPT_EXPORT, '-', "Output PKCS12 file"}, - {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"}, - {"maciter", OPT_MACITER, '-', "Use MAC iteration"}, - {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"}, - {"nomac", OPT_NOMAC, '-', "Don't generate MAC"}, - {"LMK", OPT_LMK, '-', - "Add local machine keyset attribute to private key"}, - {"nodes", OPT_NODES, '-', "Don't encrypt private keys"}, - {"macalg", OPT_MACALG, 's', - "Digest algorithm used in MAC (default SHA1)"}, - {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + OPT_PROV_OPTIONS, OPT_R_OPTIONS, - {"inkey", OPT_INKEY, 's', "Private key if not infile"}, - {"certfile", OPT_CERTFILE, '<', "Load certs from file"}, - {"name", OPT_NAME, 's', "Use name as friendly name"}, - {"CSP", OPT_CSP, 's', "Microsoft CSP name"}, - {"caname", OPT_CANAME, 's', - "Use name as CA friendly name (can be repeated)"}, - {"in", OPT_IN, '<', "Input filename"}, - {"out", OPT_OUT, '>', "Output filename"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, - {"password", OPT_PASSWORD, 's', "Set import/export password source"}, - {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"}, + + OPT_SECTION("PKCS#12 import (parsing PKCS#12)"), + {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"}, + {"nomacver", OPT_NOMACVER, '-', "Don't verify integrity MAC"}, + {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"}, + {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"}, + {"", OPT_CIPHER, '-', "Any supported cipher for output encryption"}, + {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"}, + {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"}, + + OPT_SECTION("PKCS#12 output (export)"), + {"export", OPT_EXPORT, '-', "Create PKCS12 file"}, + {"inkey", OPT_INKEY, 's', "Private key, else read from -in input file"}, + {"certfile", OPT_CERTFILE, '<', "Extra certificates for PKCS12 output"}, + {"passcerts", OPT_PASSCERTS, 's', "Certificate file pass phrase source"}, + {"chain", OPT_CHAIN, '-', "Build and add certificate chain for EE cert,"}, + {OPT_MORE_STR, 0, 0, + "which is the 1st cert from -in matching the private key (if given)"}, + {"untrusted", OPT_UNTRUSTED, '<', "Untrusted certificates for chain building"}, {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"}, + {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"}, + {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"}, {"no-CAfile", OPT_NOCAFILE, '-', "Do not load the default certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', "Do not load certificates from the default certificates directory"}, - {"", OPT_CIPHER, '-', "Any supported cipher"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store"}, + {"name", OPT_NAME, 's', "Use name as friendly name"}, + {"caname", OPT_CANAME, 's', + "Use name as CA friendly name (can be repeated)"}, + {"CSP", OPT_CSP, 's', "Microsoft CSP name"}, + {"LMK", OPT_LMK, '-', + "Add local machine keyset attribute to private key"}, + {"keyex", OPT_KEYEX, '-', "Set key type to MS key exchange"}, + {"keysig", OPT_KEYSIG, '-', "Set key type to MS key signature"}, + {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default AES-256 CBC)"}, + {"certpbe", OPT_CERTPBE, 's', + "Certificate PBE algorithm (default PBES2 with PBKDF2 and AES-256 CBC)"}, +#ifndef OPENSSL_NO_DES + {"descert", OPT_DESCERT, '-', + "Encrypt output with 3DES (default PBES2 with PBKDF2 and AES-256 CBC)"}, #endif + {"macalg", OPT_MACALG, 's', + "Digest algorithm to use in MAC (default SHA256)"}, + {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"}, + {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"}, + {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"}, + {"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"}, + {"nomac", OPT_NOMAC, '-', "Don't generate MAC"}, {NULL} }; int pkcs12_main(int argc, char **argv) { char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL; + char *untrusted = NULL, *ciphername = NULL, *enc_flag = NULL; + char *passcertsarg = NULL, *passcerts = NULL; char *name = NULL, *csp_name = NULL; char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = ""; - int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0; - int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER; -#ifndef OPENSSL_NO_RC2 - int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; -#else - int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0; +#ifndef OPENSSL_NO_DES + int use_legacy = 0; #endif - int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + /* use library defaults for the iter, maciter, cert, and key PBE */ + int iter = 0, maciter = 0; + int cert_pbe = NID_undef; + int key_pbe = NID_undef; int ret = 1, macver = 1, add_lmk = 0, private = 0; int noprompt = 0; char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL, *macalg = NULL; char *cpass = NULL, *mpass = NULL, *badpass = NULL; - const char *CApath = NULL, *CAfile = NULL, *prog; - int noCApath = 0, noCAfile = 0; + const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog; + int noCApath = 0, noCAfile = 0, noCAstore = 0; ENGINE *e = NULL; BIO *in = NULL, *out = NULL; PKCS12 *p12 = NULL; STACK_OF(OPENSSL_STRING) *canames = NULL; - const EVP_CIPHER *enc = EVP_des_ede3_cbc(); + EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc(); + EVP_CIPHER *enc = (EVP_CIPHER *)default_enc; OPTION_CHOICE o; prog = opt_init(argc, argv, pkcs12_options); @@ -187,34 +227,47 @@ case OPT_NOMACVER: macver = 0; break; +#ifndef OPENSSL_NO_DES case OPT_DESCERT: cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; break; +#endif case OPT_EXPORT: - export_cert = 1; + export_pkcs12 = 1; + break; + case OPT_NODES: + case OPT_NOENC: + /* + * |enc_flag| stores the name of the option used so it + * can be printed if an error message is output. + */ + enc_flag = opt_flag() + 1; + enc = NULL; + ciphername = NULL; break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &enc)) - goto opthelp; + ciphername = opt_unknown(); + enc_flag = opt_unknown(); + break; + case OPT_ITER: + maciter = iter = opt_int_arg(); break; case OPT_NOITER: iter = 1; break; case OPT_MACITER: - maciter = PKCS12_DEFAULT_ITER; + /* no-op */ break; case OPT_NOMACITER: maciter = 1; break; case OPT_NOMAC: + cert_pbe = -1; maciter = -1; break; case OPT_MACALG: macalg = opt_arg(); break; - case OPT_NODES: - enc = NULL; - break; case OPT_CERTPBE: if (!set_pbe(&cert_pbe, opt_arg())) goto opthelp; @@ -233,6 +286,12 @@ case OPT_CERTFILE: certfile = opt_arg(); break; + case OPT_UNTRUSTED: + untrusted = opt_arg(); + break; + case OPT_PASSCERTS: + passcertsarg = opt_arg(); + break; case OPT_NAME: name = opt_arg(); break; @@ -266,28 +325,145 @@ case OPT_CAPATH: CApath = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; case OPT_CAFILE: CAfile = opt_arg(); break; case OPT_NOCAPATH: noCApath = 1; break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; +#ifndef OPENSSL_NO_DES + case OPT_LEGACY_ALG: + use_legacy = 1; + break; +#endif + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (!app_RAND_load()) + goto end; + + if (ciphername != NULL) { + if (!opt_cipher_any(ciphername, &enc)) + goto opthelp; + } + if (export_pkcs12) { + if ((options & INFO) != 0) + WARN_EXPORT("info"); + if (macver == 0) + WARN_EXPORT("nomacver"); + if ((options & CLCERTS) != 0) + WARN_EXPORT("clcerts"); + if ((options & CACERTS) != 0) + WARN_EXPORT("cacerts"); + if (enc != default_enc) + BIO_printf(bio_err, + "Warning: output encryption option -%s ignored with -export\n", enc_flag); + } else { + if (keyname != NULL) + WARN_NO_EXPORT("inkey"); + if (certfile != NULL) + WARN_NO_EXPORT("certfile"); + if (passcertsarg != NULL) + WARN_NO_EXPORT("passcerts"); + if (chain) + WARN_NO_EXPORT("chain"); + if (untrusted != NULL) + WARN_NO_EXPORT("untrusted"); + if (CAfile != NULL) + WARN_NO_EXPORT("CAfile"); + if (CApath != NULL) + WARN_NO_EXPORT("CApath"); + if (CAstore != NULL) + WARN_NO_EXPORT("CAstore"); + if (noCAfile) + WARN_NO_EXPORT("no-CAfile"); + if (noCApath) + WARN_NO_EXPORT("no-CApath"); + if (noCAstore) + WARN_NO_EXPORT("no-CAstore"); + if (name != NULL) + WARN_NO_EXPORT("name"); + if (canames != NULL) + WARN_NO_EXPORT("caname"); + if (csp_name != NULL) + WARN_NO_EXPORT("CSP"); + if (add_lmk) + WARN_NO_EXPORT("LMK"); + if (keytype == KEY_EX) + WARN_NO_EXPORT("keyex"); + if (keytype == KEY_SIG) + WARN_NO_EXPORT("keysig"); + if (key_pbe != NID_undef) + WARN_NO_EXPORT("keypbe"); + if (cert_pbe != NID_undef && cert_pbe != -1) + WARN_NO_EXPORT("certpbe and -descert"); + if (macalg != NULL) + WARN_NO_EXPORT("macalg"); + if (iter != 0) + WARN_NO_EXPORT("iter and -noiter"); + if (maciter == 1) + WARN_NO_EXPORT("nomaciter"); + if (cert_pbe == -1 && maciter == -1) + WARN_NO_EXPORT("nomac"); + } +#ifndef OPENSSL_NO_DES + if (use_legacy) { + /* load the legacy provider if not loaded already*/ + if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) { + if (!app_provider_load(app_get0_libctx(), "legacy")) + goto end; + /* load the default provider explicitly */ + if (!app_provider_load(app_get0_libctx(), "default")) + goto end; + } + if (cert_pbe == NID_undef) { + /* Adapt default algorithm */ +# ifndef OPENSSL_NO_RC2 + cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; +# else + cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +# endif + } + + if (key_pbe == NID_undef) + key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + if (enc == default_enc) + enc = (EVP_CIPHER *)EVP_des_ede3_cbc(); + if (macalg == NULL) + macalg = "sha1"; + } +#endif + private = 1; + if (!app_passwd(passcertsarg, NULL, &passcerts, NULL)) { + BIO_printf(bio_err, "Error getting certificate file password\n"); + goto end; + } + if (passarg != NULL) { - if (export_cert) + if (export_pkcs12) passoutarg = passarg; else passinarg = passarg; @@ -299,7 +475,7 @@ } if (cpass == NULL) { - if (export_cert) + if (export_pkcs12) cpass = passout; else cpass = passin; @@ -309,7 +485,7 @@ mpass = cpass; noprompt = 1; if (twopass) { - if (export_cert) + if (export_pkcs12) BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n"); else BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n"); @@ -325,7 +501,7 @@ if (1) { #ifndef OPENSSL_NO_UI_CONSOLE if (EVP_read_pw_string( - macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) { + macpass, sizeof(macpass), "Enter MAC Password:", export_pkcs12)) { BIO_printf(bio_err, "Can't read Password\n"); goto end; } @@ -336,96 +512,126 @@ } } - if (export_cert) { + if (export_pkcs12) { EVP_PKEY *key = NULL; - X509 *ucert = NULL, *x = NULL; + X509 *ee_cert = NULL, *x = NULL; STACK_OF(X509) *certs = NULL; - const EVP_MD *macmd = NULL; + STACK_OF(X509) *untrusted_certs = NULL; + EVP_MD *macmd = NULL; unsigned char *catmp = NULL; int i; if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { - BIO_printf(bio_err, "Nothing to do!\n"); + BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n"); goto export_end; } - if (options & NOCERTS) + if ((options & NOCERTS) != 0) { chain = 0; + BIO_printf(bio_err, "Warning: -chain option ignored with -nocerts\n"); + } if (!(options & NOKEYS)) { key = load_key(keyname ? keyname : infile, - FORMAT_PEM, 1, passin, e, "private key"); + FORMAT_PEM, 1, passin, e, + keyname ? + "private key from -inkey file" : + "private key from -in file"); if (key == NULL) goto export_end; } - /* Load in all certs in input file */ + /* Load all certs in input file */ if (!(options & NOCERTS)) { - if (!load_certs(infile, &certs, FORMAT_PEM, NULL, - "certificates")) + if (!load_certs(infile, 1, &certs, passin, + "certificates from -in file")) goto export_end; + if (sk_X509_num(certs) < 1) { + BIO_printf(bio_err, "No certificate in -in file %s\n", infile); + goto export_end; + } if (key != NULL) { /* Look for matching private key */ for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); if (X509_check_private_key(x, key)) { - ucert = x; + ee_cert = x; /* Zero keyid and alias */ - X509_keyid_set1(ucert, NULL, 0); - X509_alias_set1(ucert, NULL, 0); + X509_keyid_set1(ee_cert, NULL, 0); + X509_alias_set1(ee_cert, NULL, 0); /* Remove from list */ (void)sk_X509_delete(certs, i); break; } } - if (ucert == NULL) { + if (ee_cert == NULL) { BIO_printf(bio_err, - "No certificate matches private key\n"); + "No cert in -in file '%s' matches private key\n", + infile); goto export_end; } } - } - /* Add any more certificates asked for */ - if (certfile != NULL) { - if (!load_certs(certfile, &certs, FORMAT_PEM, NULL, - "certificates from certfile")) + /* Load any untrusted certificates for chain building */ + if (untrusted != NULL) { + if (!load_certs(untrusted, 0, &untrusted_certs, passcerts, + "untrusted certificates")) goto export_end; } - /* If chaining get chain from user cert */ + /* If chaining get chain from end entity cert */ if (chain) { int vret; STACK_OF(X509) *chain2; X509_STORE *store; - if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) + X509 *ee_cert_tmp = ee_cert; + + /* Assume the first cert if we haven't got anything else */ + if (ee_cert_tmp == NULL && certs != NULL) + ee_cert_tmp = sk_X509_value(certs, 0); + + if (ee_cert_tmp == NULL) { + BIO_printf(bio_err, + "No end entity certificate to check with -chain\n"); + goto export_end; + } + + if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) == NULL) goto export_end; - vret = get_cert_chain(ucert, store, &chain2); + vret = get_cert_chain(ee_cert_tmp, store, untrusted_certs, &chain2); X509_STORE_free(store); if (vret == X509_V_OK) { - /* Exclude verified certificate */ - for (i = 1; i < sk_X509_num(chain2); i++) - sk_X509_push(certs, sk_X509_value(chain2, i)); - /* Free first certificate */ - X509_free(sk_X509_value(chain2, 0)); - sk_X509_free(chain2); + int add_certs; + /* Remove from chain2 the first (end entity) certificate */ + X509_free(sk_X509_shift(chain2)); + /* Add the remaining certs (except for duplicates) */ + add_certs = X509_add_certs(certs, chain2, X509_ADD_FLAG_UP_REF + | X509_ADD_FLAG_NO_DUP); + sk_X509_pop_free(chain2, X509_free); + if (!add_certs) + goto export_end; } else { if (vret != X509_V_ERR_UNSPECIFIED) - BIO_printf(bio_err, "Error %s getting chain.\n", + BIO_printf(bio_err, "Error getting chain: %s\n", X509_verify_cert_error_string(vret)); - else - ERR_print_errors(bio_err); goto export_end; } } - /* Add any CA names */ + /* Add any extra certificates asked for */ + if (certfile != NULL) { + if (!load_certs(certfile, 0, &certs, passcerts, + "extra certificates from -certfile")) + goto export_end; + } + /* Add any CA names */ for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) { catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i); X509_alias_set1(sk_X509_value(certs, i), catmp, -1); @@ -439,7 +645,7 @@ if (add_lmk && key != NULL) EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); - if (!noprompt) { + if (!noprompt && !(enc == NULL && maciter == -1)) { /* To avoid bit rot */ if (1) { #ifndef OPENSSL_NO_UI_CONSOLE @@ -458,21 +664,27 @@ if (!twopass) OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); - p12 = PKCS12_create(cpass, name, key, ucert, certs, - key_pbe, cert_pbe, iter, -1, keytype); + p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs, + key_pbe, cert_pbe, iter, -1, keytype, + app_get0_libctx(), app_get0_propq()); - if (!p12) { - ERR_print_errors(bio_err); + if (p12 == NULL) { + BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n", + outfile); goto export_end; } - if (macalg) { + if (macalg != NULL) { if (!opt_md(macalg, &macmd)) goto opthelp; } if (maciter != -1) - PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); + if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) { + BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n"); + BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n"); + goto export_end; + } assert(private); @@ -487,9 +699,12 @@ export_end: EVP_PKEY_free(key); + EVP_MD_free(macmd); sk_X509_pop_free(certs, X509_free); - X509_free(ucert); + sk_X509_pop_free(untrusted_certs, X509_free); + X509_free(ee_cert); + ERR_print_errors(bio_err); goto end; } @@ -501,7 +716,12 @@ if (out == NULL) goto end; - if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) { + p12 = PKCS12_init_ex(NID_pkcs7_data, app_get0_libctx(), app_get0_propq()); + if (p12 == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if ((p12 = d2i_PKCS12_bio(in, &p12)) == NULL) { ERR_print_errors(bio_err); goto end; } @@ -544,6 +764,16 @@ tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L); } if (macver) { + EVP_KDF *pkcs12kdf; + + pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF", + app_get0_propq()); + if (pkcs12kdf == NULL) { + BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n"); + BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n"); + goto end; + } + EVP_KDF_free(pkcs12kdf); /* If we enter empty password try no password first */ if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { /* If mac and crypto pass the same set it to NULL too */ @@ -557,6 +787,14 @@ */ unsigned char *utmp; int utmplen; + unsigned long err = ERR_peek_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 + && ERR_GET_REASON(err) == PKCS12_R_MAC_ABSENT) { + BIO_printf(bio_err, "Warning: MAC is absent!\n"); + goto dump; + } + utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen); if (utmp == NULL) goto end; @@ -574,6 +812,7 @@ } } + dump: assert(private); if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); @@ -588,6 +827,7 @@ BIO_free_all(out); sk_OPENSSL_STRING_free(canames); OPENSSL_free(badpass); + OPENSSL_free(passcerts); OPENSSL_free(passin); OPENSSL_free(passout); return ret; @@ -725,6 +965,16 @@ X509_free(x509); break; + case NID_secretBag: + if (options & INFO) + BIO_printf(bio_err, "Secret bag\n"); + print_attribs(out, attrs, "Bag Attributes"); + BIO_printf(bio_err, "Bag Type: "); + i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_bag_type(bag)); + BIO_printf(bio_err, "\nBag Value: "); + print_attribute(out, PKCS12_SAFEBAG_get0_bag_obj(bag)); + return 1; + case NID_safeContentsBag: if (options & INFO) BIO_printf(bio_err, "Safe Contents bag\n"); @@ -744,18 +994,19 @@ /* Given a single certificate return a verified chain or NULL if error */ static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) *untrusted_certs, STACK_OF(X509) **chain) { X509_STORE_CTX *store_ctx = NULL; STACK_OF(X509) *chn = NULL; int i = 0; - store_ctx = X509_STORE_CTX_new(); + store_ctx = X509_STORE_CTX_new_ex(app_get0_libctx(), app_get0_propq()); if (store_ctx == NULL) { i = X509_V_ERR_UNSPECIFIED; goto end; } - if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) { + if (!X509_STORE_CTX_init(store_ctx, store, cert, untrusted_certs)) { i = X509_V_ERR_UNSPECIFIED; goto end; } @@ -863,12 +1114,13 @@ int cert_load(BIO *in, STACK_OF(X509) *sk) { - int ret; + int ret = 0; X509 *cert; - ret = 0; + while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { ret = 1; - sk_X509_push(sk, cert); + if (!sk_X509_push(sk, cert)) + return 0; } if (ret) ERR_clear_error(); @@ -889,6 +1141,11 @@ OPENSSL_free(value); break; + case V_ASN1_UTF8STRING: + BIO_printf(out, "%.*s\n", av->value.utf8string->length, + av->value.utf8string->data); + break; + case V_ASN1_OCTET_STRING: hex_prin(out, av->value.octet_string->data, av->value.octet_string->length); diff --git a/apps/pkcs7.c b/apps/pkcs7.c --- a/apps/pkcs7.c +++ b/apps/pkcs7.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -21,15 +21,24 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT, - OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE + OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS pkcs7_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + + OPT_SECTION("Output"), {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, {"out", OPT_OUT, '>', "Output file"}, {"noout", OPT_NOOUT, '-', "Don't output encoded data"}, @@ -37,21 +46,21 @@ {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"}, {"print_certs", OPT_PRINT_CERTS, '-', "Print_certs print any certs or crl in the input"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + + OPT_PROV_OPTIONS, {NULL} }; int pkcs7_main(int argc, char **argv) { ENGINE *e = NULL; - PKCS7 *p7 = NULL; + PKCS7 *p7 = NULL, *p7i; BIO *in = NULL, *out = NULL; int informat = FORMAT_PEM, outformat = FORMAT_PEM; char *infile = NULL, *outfile = NULL, *prog; int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1; OPTION_CHOICE o; + OSSL_LIB_CTX *libctx = app_get0_libctx(); prog = opt_init(argc, argv, pkcs7_options); while ((o = opt_next()) != OPT_EOF) { @@ -94,8 +103,14 @@ case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; @@ -104,11 +119,18 @@ if (in == NULL) goto end; + p7 = PKCS7_new_ex(libctx, app_get0_propq()); + if (p7 == NULL) { + BIO_printf(bio_err, "unable to allocate PKCS7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + if (informat == FORMAT_ASN1) - p7 = d2i_PKCS7_bio(in, NULL); + p7i = d2i_PKCS7_bio(in, &p7); else - p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); - if (p7 == NULL) { + p7i = PEM_read_bio_PKCS7(in, &p7, NULL, NULL); + if (p7i == NULL) { BIO_printf(bio_err, "unable to load PKCS7 object\n"); ERR_print_errors(bio_err); goto end; diff --git a/apps/pkcs8.c b/apps/pkcs8.c --- a/apps/pkcs8.c +++ b/apps/pkcs8.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -18,7 +18,7 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT, #ifndef OPENSSL_NO_SCRYPT @@ -26,35 +26,44 @@ #endif OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT, OPT_TRADITIONAL, - OPT_R_ENUM + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS pkcs8_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"}, - {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, - {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, - {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"}, - {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, - {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"}, - OPT_R_OPTIONS, - {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"}, + {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"}, {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"}, - {"iter", OPT_ITER, 'p', "Specify the iteration count"}, + + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, + {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"}, {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + {"iter", OPT_ITER, 'p', "Specify the iteration count"}, + {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, + #ifndef OPENSSL_NO_SCRYPT + OPT_SECTION("Scrypt"), {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"}, {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"}, {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"}, {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"}, #endif + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, {NULL} }; @@ -65,8 +74,8 @@ EVP_PKEY *pkey = NULL; PKCS8_PRIV_KEY_INFO *p8inf = NULL; X509_SIG *p8 = NULL; - const EVP_CIPHER *cipher = NULL; - char *infile = NULL, *outfile = NULL; + EVP_CIPHER *cipher = NULL; + char *infile = NULL, *outfile = NULL, *ciphername = NULL; char *passinarg = NULL, *passoutarg = NULL, *prog; #ifndef OPENSSL_NO_UI_CONSOLE char pass[APP_PASS_LEN]; @@ -74,7 +83,7 @@ char *passin = NULL, *passout = NULL, *p8pass = NULL; OPTION_CHOICE o; int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; int private = 0, traditional = 0; #ifndef OPENSSL_NO_SCRYPT long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0; @@ -119,12 +128,15 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_TRADITIONAL: traditional = 1; break; case OPT_V2: - if (!opt_cipher(opt_arg(), &cipher)) - goto opthelp; + ciphername = opt_arg(); break; case OPT_V1: pbe_nid = OBJ_txt2nid(opt_arg()); @@ -142,11 +154,10 @@ goto opthelp; } if (cipher == NULL) - cipher = EVP_aes_256_cbc(); + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); break; case OPT_ITER: - if (!opt_int(opt_arg(), &iter)) - goto opthelp; + iter = opt_int_arg(); break; case OPT_PASSIN: passinarg = opt_arg(); @@ -163,7 +174,7 @@ scrypt_r = 8; scrypt_p = 1; if (cipher == NULL) - cipher = EVP_aes_256_cbc(); + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); break; case OPT_SCRYPT_N: if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0) @@ -180,11 +191,20 @@ #endif } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; private = 1; + if (!app_RAND_load()) + goto end; + + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &cipher)) + goto opthelp; + } if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); @@ -192,9 +212,10 @@ } if ((pbe_nid == -1) && cipher == NULL) - cipher = EVP_aes_256_cbc(); + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); - in = bio_open_default(infile, 'r', informat); + in = bio_open_default(infile, 'r', + informat == FORMAT_UNDEF ? FORMAT_PEM : informat); if (in == NULL) goto end; out = bio_open_owner(outfile, outformat, private); @@ -278,7 +299,7 @@ } if (nocrypt) { - if (informat == FORMAT_PEM) { + if (informat == FORMAT_PEM || informat == FORMAT_UNDEF) { p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL); } else if (informat == FORMAT_ASN1) { p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); @@ -287,7 +308,7 @@ goto end; } } else { - if (informat == FORMAT_PEM) { + if (informat == FORMAT_PEM || informat == FORMAT_UNDEF) { p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); } else if (informat == FORMAT_ASN1) { p8 = d2i_PKCS8_bio(in, NULL); @@ -349,6 +370,7 @@ X509_SIG_free(p8); PKCS8_PRIV_KEY_INFO_free(p8inf); EVP_PKEY_free(pkey); + EVP_CIPHER_free(cipher); release_engine(e); BIO_free_all(out); BIO_free(in); diff --git a/apps/pkey.c b/apps/pkey.c --- a/apps/pkey.c +++ b/apps/pkey.c @@ -1,7 +1,7 @@ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,54 +11,77 @@ #include #include "apps.h" #include "progs.h" +#include "ec_common.h" #include #include #include +#include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB, - OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK + OPT_TEXT, OPT_NOOUT, OPT_CIPHER, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK, + OPT_EC_PARAM_ENC, OPT_EC_CONV_FORM, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS pkey_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'f', "Input format (DER or PEM)"}, - {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, - {"in", OPT_IN, 's', "Input key"}, - {"out", OPT_OUT, '>', "Output file"}, - {"pubin", OPT_PUBIN, '-', - "Read public key from input (default is private key)"}, - {"pubout", OPT_PUBOUT, '-', "Output public key, not private"}, - {"text_pub", OPT_TEXT_PUB, '-', "Only output public key components"}, - {"text", OPT_TEXT, '-', "Output in plaintext as well"}, - {"noout", OPT_NOOUT, '-', "Don't output the key"}, - {"", OPT_MD, '-', "Any supported cipher"}, - {"traditional", OPT_TRADITIONAL, '-', - "Use traditional format for private keys"}, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif + OPT_PROV_OPTIONS, + {"check", OPT_CHECK, '-', "Check key consistency"}, {"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"}, + + OPT_SECTION("Input"), + {"in", OPT_IN, 's', "Input key"}, + {"inform", OPT_INFORM, 'f', + "Key input format (ENGINE, other values ignored)"}, + {"passin", OPT_PASSIN, 's', "Key input pass phrase source"}, + {"pubin", OPT_PUBIN, '-', + "Read only public components from key input"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file for encoded and/or text output"}, + {"outform", OPT_OUTFORM, 'F', "Output encoding format (DER or PEM)"}, + {"", OPT_CIPHER, '-', "Any supported cipher to be used for encryption"}, + {"passout", OPT_PASSOUT, 's', "Output PEM file pass phrase source"}, + {"traditional", OPT_TRADITIONAL, '-', + "Use traditional format for private key PEM output"}, + {"pubout", OPT_PUBOUT, '-', "Restrict encoded output to public components"}, + {"noout", OPT_NOOUT, '-', "Do not output the key in encoded form"}, + {"text", OPT_TEXT, '-', "Output key components in plaintext"}, + {"text_pub", OPT_TEXT_PUB, '-', + "Output only public key components in text form"}, + {"ec_conv_form", OPT_EC_CONV_FORM, 's', + "Specifies the EC point conversion form in the encoding"}, + {"ec_param_enc", OPT_EC_PARAM_ENC, 's', + "Specifies the way the EC parameters are encoded"}, + {NULL} }; int pkey_main(int argc, char **argv) { - BIO *in = NULL, *out = NULL; + BIO *out = NULL; ENGINE *e = NULL; EVP_PKEY *pkey = NULL; - const EVP_CIPHER *cipher = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL; - char *passinarg = NULL, *passoutarg = NULL, *prog; + char *passinarg = NULL, *passoutarg = NULL, *ciphername = NULL, *prog; OPTION_CHOICE o; - int informat = FORMAT_PEM, outformat = FORMAT_PEM; - int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0, ret = 1; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM; + int pubin = 0, pubout = 0, text_pub = 0, text = 0, noout = 0, ret = 1; int private = 0, traditional = 0, check = 0, pub_check = 0; +#ifndef OPENSSL_NO_EC + char *asn1_encoding = NULL; + char *point_format = NULL; +#endif prog = opt_init(argc, argv, pkey_options); while ((o = opt_next()) != OPT_EOF) { @@ -96,13 +119,13 @@ outfile = opt_arg(); break; case OPT_PUBIN: - pubin = pubout = pubtext = 1; + pubin = pubout = 1; break; case OPT_PUBOUT: pubout = 1; break; case OPT_TEXT_PUB: - pubtext = text = 1; + text_pub = 1; break; case OPT_TEXT: text = 1; @@ -119,19 +142,69 @@ case OPT_PUB_CHECK: pub_check = 1; break; - case OPT_MD: - if (!opt_cipher(opt_unknown(), &cipher)) + case OPT_CIPHER: + ciphername = opt_unknown(); + break; + case OPT_EC_CONV_FORM: +#ifdef OPENSSL_NO_EC + goto opthelp; +#else + point_format = opt_arg(); + if (!opt_string(point_format, point_format_options)) goto opthelp; + break; +#endif + case OPT_EC_PARAM_ENC: +#ifdef OPENSSL_NO_EC + goto opthelp; +#else + asn1_encoding = opt_arg(); + if (!opt_string(asn1_encoding, asn1_encoding_options)) + goto opthelp; + break; +#endif + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; - private = !noout && !pubout ? 1 : 0; - if (text && !pubtext) - private = 1; + if (text && text_pub) + BIO_printf(bio_err, + "Warning: The -text option is ignored with -text_pub\n"); + if (traditional && (noout || outformat != FORMAT_PEM)) + BIO_printf(bio_err, + "Warning: The -traditional is ignored since there is no PEM output\n"); + + /* -pubout and -text is the same as -text_pub */ + if (!text_pub && pubout && text) { + text = 0; + text_pub = 1; + } + + private = (!noout && !pubout) || (text && !text_pub); + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &cipher)) + goto opthelp; + } + if (cipher == NULL) { + if (passoutarg != NULL) + BIO_printf(bio_err, + "Warning: The -passout option is ignored without a cipher option\n"); + } else { + if (noout || outformat != FORMAT_PEM) { + BIO_printf(bio_err, + "Error: Cipher options are supported only for PEM output\n"); + goto end; + } + } if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; @@ -148,9 +221,28 @@ if (pkey == NULL) goto end; +#ifndef OPENSSL_NO_EC + if (asn1_encoding != NULL || point_format != NULL) { + OSSL_PARAM params[3], *p = params; + + if (!EVP_PKEY_is_a(pkey, "EC")) + goto end; + + if (asn1_encoding != NULL) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, + asn1_encoding, 0); + if (point_format != NULL) + *p++ = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + point_format, 0); + *p = OSSL_PARAM_construct_end(); + if (EVP_PKEY_set_params(pkey, params) <= 0) + goto end; + } +#endif + if (check || pub_check) { int r; - EVP_PKEY_CTX *ctx; ctx = EVP_PKEY_CTX_new(pkey, e); if (ctx == NULL) { @@ -158,7 +250,7 @@ goto end; } - if (check) + if (check && !pubin) r = EVP_PKEY_check(ctx); else r = EVP_PKEY_public_check(ctx); @@ -170,17 +262,10 @@ * Note: at least for RSA keys if this function returns * -1, there will be no error reasons. */ - unsigned long err; - - BIO_printf(out, "Key is invalid\n"); - - while ((err = ERR_peek_error()) != 0) { - BIO_printf(out, "Detailed error: %s\n", - ERR_reason_error_string(err)); - ERR_get_error(); /* remove err from error stack */ - } + BIO_printf(bio_err, "Key is invalid\n"); + ERR_print_errors(bio_err); + goto end; } - EVP_PKEY_CTX_free(ctx); } if (!noout) { @@ -202,6 +287,11 @@ } } } else if (outformat == FORMAT_ASN1) { + if (text || text_pub) { + BIO_printf(bio_err, + "Error: Text output cannot be combined with DER output\n"); + goto end; + } if (pubout) { if (!i2d_PUBKEY_bio(out, pkey)) goto end; @@ -216,15 +306,13 @@ } } - if (text) { - if (pubtext) { - if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) - goto end; - } else { - assert(private); - if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0) - goto end; - } + if (text_pub) { + if (EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) + goto end; + } else if (text) { + assert(private); + if (EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0) + goto end; } ret = 0; @@ -232,10 +320,11 @@ end: if (ret != 0) ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); + EVP_CIPHER_free(cipher); release_engine(e); BIO_free_all(out); - BIO_free(in); OPENSSL_free(passin); OPENSSL_free(passout); diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c --- a/apps/pkeyparam.c +++ b/apps/pkeyparam.c @@ -1,7 +1,7 @@ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -9,6 +9,7 @@ #include #include +#include #include "apps.h" #include "progs.h" #include @@ -16,21 +17,29 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT, - OPT_ENGINE, OPT_CHECK + OPT_ENGINE, OPT_CHECK, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS pkeyparam_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, - {"text", OPT_TEXT, '-', "Print parameters as text"}, - {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"}, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif {"check", OPT_CHECK, '-', "Check key param consistency"}, + + OPT_SECTION("Input"), + {"in", OPT_IN, '<', "Input file"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"text", OPT_TEXT, '-', "Print parameters as text"}, + {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"}, + + OPT_PROV_OPTIONS, {NULL} }; @@ -39,7 +48,8 @@ ENGINE *e = NULL; BIO *in = NULL, *out = NULL; EVP_PKEY *pkey = NULL; - int text = 0, noout = 0, ret = 1, check = 0; + EVP_PKEY_CTX *ctx = NULL; + int text = 0, noout = 0, ret = EXIT_FAILURE, check = 0, r; OPTION_CHOICE o; char *infile = NULL, *outfile = NULL, *prog; @@ -73,8 +83,14 @@ case OPT_CHECK: check = 1; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; @@ -85,7 +101,8 @@ out = bio_open_default(outfile, 'w', FORMAT_PEM); if (out == NULL) goto end; - pkey = PEM_read_bio_Parameters(in, NULL); + pkey = PEM_read_bio_Parameters_ex(in, NULL, app_get0_libctx(), + app_get0_propq()); if (pkey == NULL) { BIO_printf(bio_err, "Error reading parameters\n"); ERR_print_errors(bio_err); @@ -93,10 +110,11 @@ } if (check) { - int r; - EVP_PKEY_CTX *ctx; - - ctx = EVP_PKEY_CTX_new(pkey, e); + if (e == NULL) + ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, + app_get0_propq()); + else + ctx = EVP_PKEY_CTX_new(pkey, e); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; @@ -111,17 +129,10 @@ * Note: at least for RSA keys if this function returns * -1, there will be no error reasons. */ - unsigned long err; - - BIO_printf(out, "Parameters are invalid\n"); - - while ((err = ERR_peek_error()) != 0) { - BIO_printf(out, "Detailed error: %s\n", - ERR_reason_error_string(err)); - ERR_get_error(); /* remove err from error stack */ - } + BIO_printf(bio_err, "Parameters are invalid\n"); + ERR_print_errors(bio_err); + goto end; } - EVP_PKEY_CTX_free(ctx); } if (!noout) @@ -130,9 +141,10 @@ if (text) EVP_PKEY_print_params(out, pkey, 0, NULL); - ret = 0; + ret = EXIT_SUCCESS; end: + EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); release_engine(e); BIO_free_all(out); diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c --- a/apps/pkeyutl.c +++ b/apps/pkeyutl.c @@ -1,7 +1,7 @@ /* - * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -13,6 +13,7 @@ #include #include #include +#include #define KEY_NONE 0 #define KEY_PRIVKEY 1 @@ -22,7 +23,9 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, char *passinarg, int pkey_op, ENGINE *e, - const int impl); + const int impl, int rawin, EVP_PKEY **ppkey, + EVP_MD_CTX *mctx, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq); static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, ENGINE *e); @@ -31,69 +34,100 @@ unsigned char *out, size_t *poutlen, const unsigned char *in, size_t inlen); +static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, + EVP_PKEY *pkey, BIO *in, + int filesize, unsigned char *sig, int siglen, + unsigned char **out, size_t *poutlen); + typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT, OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN, OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN, - OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN, - OPT_R_ENUM + OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF, + OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM, + OPT_CONFIG, + OPT_RAWIN, OPT_DIGEST } OPTION_CHOICE; const OPTIONS pkeyutl_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"engine_impl", OPT_ENGINE_IMPL, '-', + "Also use engine given by -engine for crypto operations"}, +#endif + {"sign", OPT_SIGN, '-', "Sign input data with private key"}, + {"verify", OPT_VERIFY, '-', "Verify with public key"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"}, + {"derive", OPT_DERIVE, '-', "Derive shared secret"}, + OPT_CONFIG_OPTION, + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file - default stdin"}, - {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"}, {"pubin", OPT_PUBIN, '-', "Input is a public key"}, + {"inkey", OPT_INKEY, 's', "Input private key file"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"}, + {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"}, {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"}, + {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, + {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"}, + {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file - default stdout"}, {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"}, {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, - {"sign", OPT_SIGN, '-', "Sign input data with private key"}, - {"verify", OPT_VERIFY, '-', "Verify with public key"}, {"verifyrecover", OPT_VERIFYRECOVER, '-', "Verify with public key, recover original data"}, - {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, - {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"}, - {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"}, - {"derive", OPT_DERIVE, '-', "Derive shared secret"}, + + OPT_SECTION("Signing/Derivation"), + {"digest", OPT_DIGEST, 's', + "Specify the digest algorithm when signing the raw input data"}, + {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + {"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's', + "Public key option that is read as a passphrase argument opt:passphrase"}, {"kdf", OPT_KDF, 's', "Use KDF algorithm"}, {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"}, - {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"}, - {"inkey", OPT_INKEY, 's', "Input private key file"}, - {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"}, - {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, - {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, - {"engine_impl", OPT_ENGINE_IMPL, '-', - "Also use engine given by -engine for crypto operations"}, -#endif + OPT_PROV_OPTIONS, {NULL} }; int pkeyutl_main(int argc, char **argv) { + CONF *conf = NULL; BIO *in = NULL, *out = NULL; ENGINE *e = NULL; EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; char hexdump = 0, asn1parse = 0, rev = 0, *prog; unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; OPTION_CHOICE o; - int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM; + int buf_inlen = 0, siglen = -1; + int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF; int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; int engine_impl = 0; int ret = 1, rv = -1; size_t buf_outlen; const char *inkey = NULL; const char *peerkey = NULL; - const char *kdfalg = NULL; + const char *kdfalg = NULL, *digestname = NULL; int kdflen = 0; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; + STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL; + int rawin = 0; + EVP_MD_CTX *mctx = NULL; + EVP_MD *md = NULL; + int filesize = -1; + OSSL_LIB_CTX *libctx = app_get0_libctx(); prog = opt_init(argc, argv, pkeyutl_options); while ((o = opt_next()) != OPT_EOF) { @@ -129,17 +163,26 @@ passinarg = opt_arg(); break; case OPT_PEERFORM: - if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform)) goto opthelp; break; case OPT_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) goto opthelp; break; case OPT_R_CASES: if (!opt_rand(o)) goto end; break; + case OPT_CONFIG: + conf = app_load_config_modules(opt_arg()); + if (conf == NULL) + goto end; + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; @@ -192,12 +235,51 @@ goto end; } break; + case OPT_PKEYOPT_PASSIN: + if ((pkeyopts_passin == NULL && + (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) || + sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) { + BIO_puts(bio_err, "out of memory\n"); + goto end; + } + break; + case OPT_RAWIN: + rawin = 1; + break; + case OPT_DIGEST: + digestname = opt_arg(); + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (!app_RAND_load()) + goto end; + + if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) { + BIO_printf(bio_err, + "%s: -rawin can only be used with -sign or -verify\n", + prog); + goto opthelp; + } + + if (digestname != NULL && !rawin) { + BIO_printf(bio_err, + "%s: -digest can only be used with -rawin\n", + prog); + goto opthelp; + } + + if (rawin && rev) { + BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", + prog); + goto opthelp; + } + if (kdfalg != NULL) { if (kdflen == 0) { BIO_printf(bio_err, @@ -213,16 +295,22 @@ "%s: no peer key given (-peerkey parameter).\n", prog); goto opthelp; } + + if (rawin) { + if ((mctx = EVP_MD_CTX_new()) == NULL) { + BIO_printf(bio_err, "Error: out of memory\n"); + goto end; + } + } ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, - passinarg, pkey_op, e, engine_impl); + passinarg, pkey_op, e, engine_impl, rawin, &pkey, + mctx, digestname, libctx, app_get0_propq()); if (ctx == NULL) { BIO_printf(bio_err, "%s: Error initializing context\n", prog); - ERR_print_errors(bio_err); goto end; } if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) { BIO_printf(bio_err, "%s: Error setting up peer key\n", prog); - ERR_print_errors(bio_err); goto end; } if (pkeyopts != NULL) { @@ -235,11 +323,58 @@ if (pkey_ctrl_string(ctx, opt) <= 0) { BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n", prog, opt); - ERR_print_errors(bio_err); goto end; } } } + if (pkeyopts_passin != NULL) { + int num = sk_OPENSSL_STRING_num(pkeyopts_passin); + int i; + + for (i = 0; i < num; i++) { + char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i); + char *passin = strchr(opt, ':'); + char *passwd; + + if (passin == NULL) { + /* Get password interactively */ + char passwd_buf[4096]; + int r; + + BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt); + r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1, + passwd_buf, 0); + if (r < 0) { + if (r == -2) + BIO_puts(bio_err, "user abort\n"); + else + BIO_puts(bio_err, "entry failed\n"); + goto end; + } + passwd = OPENSSL_strdup(passwd_buf); + if (passwd == NULL) { + BIO_puts(bio_err, "out of memory\n"); + goto end; + } + } else { + /* Get password as a passin argument: First split option name + * and passphrase argument into two strings */ + *passin = 0; + passin++; + if (app_passwd(passin, NULL, &passwd, NULL) == 0) { + BIO_printf(bio_err, "failed to get '%s'\n", opt); + goto end; + } + } + + if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) { + BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n", + prog, opt); + goto end; + } + OPENSSL_free(passwd); + } + } if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) { BIO_printf(bio_err, @@ -255,6 +390,12 @@ if (pkey_op != EVP_PKEY_OP_DERIVE) { in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (infile != NULL) { + struct stat st; + + if (stat(infile, &st) == 0 && st.st_size <= INT_MAX) + filesize = (int)st.st_size; + } if (in == NULL) goto end; } @@ -277,7 +418,8 @@ } } - if (in != NULL) { + /* Raw input data is handled elsewhere */ + if (in != NULL && !rawin) { /* Read the input data */ buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); if (buf_inlen < 0) { @@ -296,8 +438,9 @@ } } - /* Sanity check the input */ - if (buf_inlen > EVP_MAX_MD_SIZE + /* Sanity check the input if the input is not raw */ + if (!rawin + && buf_inlen > EVP_MAX_MD_SIZE && (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY)) { BIO_printf(bio_err, @@ -306,8 +449,13 @@ } if (pkey_op == EVP_PKEY_OP_VERIFY) { - rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, - buf_in, (size_t)buf_inlen); + if (rawin) { + rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen, + NULL, 0); + } else { + rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, + buf_in, (size_t)buf_inlen); + } if (rv == 1) { BIO_puts(out, "Signature Verified Successfully\n"); ret = 0; @@ -316,18 +464,24 @@ } goto end; } - if (kdflen != 0) { - buf_outlen = kdflen; - rv = 1; + if (rawin) { + /* rawin allocates the buffer in do_raw_keyop() */ + rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0, + &buf_out, (size_t *)&buf_outlen); } else { - rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, - buf_in, (size_t)buf_inlen); - } - if (rv > 0 && buf_outlen != 0) { - buf_out = app_malloc(buf_outlen, "buffer output"); - rv = do_keyop(ctx, pkey_op, - buf_out, (size_t *)&buf_outlen, - buf_in, (size_t)buf_inlen); + if (kdflen != 0) { + buf_outlen = kdflen; + rv = 1; + } else { + rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + } + if (rv > 0 && buf_outlen != 0) { + buf_out = app_malloc(buf_outlen, "buffer output"); + rv = do_keyop(ctx, pkey_op, + buf_out, (size_t *)&buf_outlen, + buf_in, (size_t)buf_inlen); + } } if (rv <= 0) { if (pkey_op != EVP_PKEY_OP_DERIVE) { @@ -335,14 +489,13 @@ } else { BIO_puts(bio_err, "Key derivation failed\n"); } - ERR_print_errors(bio_err); goto end; } ret = 0; if (asn1parse) { if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) - ERR_print_errors(bio_err); + ERR_print_errors(bio_err); /* but still return success */ } else if (hexdump) { BIO_dump(out, (char *)buf_out, buf_outlen); } else { @@ -350,7 +503,11 @@ } end: + if (ret != 0) + ERR_print_errors(bio_err); + EVP_MD_CTX_free(mctx); EVP_PKEY_CTX_free(ctx); + EVP_MD_free(md); release_engine(e); BIO_free(in); BIO_free_all(out); @@ -358,13 +515,17 @@ OPENSSL_free(buf_out); OPENSSL_free(sig); sk_OPENSSL_STRING_free(pkeyopts); + sk_OPENSSL_STRING_free(pkeyopts_passin); + NCONF_free(conf); return ret; } static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, char *passinarg, int pkey_op, ENGINE *e, - const int engine_impl) + const int engine_impl, int rawin, + EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -372,6 +533,7 @@ char *passin = NULL; int rv = -1; X509 *x; + if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { @@ -384,11 +546,11 @@ } switch (key_type) { case KEY_PRIVKEY: - pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); + pkey = load_key(keyfile, keyform, 0, passin, e, "private key"); break; case KEY_PUBKEY: - pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); + pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key"); break; case KEY_CERT: @@ -420,42 +582,68 @@ goto end; } } - ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); + if (impl != NULL) + ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); + else + ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq); } else { if (pkey == NULL) goto end; - *pkeysize = EVP_PKEY_size(pkey); - ctx = EVP_PKEY_CTX_new(pkey, impl); + + *pkeysize = EVP_PKEY_get_size(pkey); + if (impl != NULL) + ctx = EVP_PKEY_CTX_new(pkey, impl); + else + ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq); + if (ppkey != NULL) + *ppkey = pkey; EVP_PKEY_free(pkey); } if (ctx == NULL) goto end; - switch (pkey_op) { - case EVP_PKEY_OP_SIGN: - rv = EVP_PKEY_sign_init(ctx); - break; + if (rawin) { + EVP_MD_CTX_set_pkey_ctx(mctx, ctx); - case EVP_PKEY_OP_VERIFY: - rv = EVP_PKEY_verify_init(ctx); - break; + switch (pkey_op) { + case EVP_PKEY_OP_SIGN: + rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq, + pkey, NULL); + break; - case EVP_PKEY_OP_VERIFYRECOVER: - rv = EVP_PKEY_verify_recover_init(ctx); - break; + case EVP_PKEY_OP_VERIFY: + rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq, + pkey, NULL); + break; + } - case EVP_PKEY_OP_ENCRYPT: - rv = EVP_PKEY_encrypt_init(ctx); - break; + } else { + switch (pkey_op) { + case EVP_PKEY_OP_SIGN: + rv = EVP_PKEY_sign_init(ctx); + break; - case EVP_PKEY_OP_DECRYPT: - rv = EVP_PKEY_decrypt_init(ctx); - break; + case EVP_PKEY_OP_VERIFY: + rv = EVP_PKEY_verify_init(ctx); + break; - case EVP_PKEY_OP_DERIVE: - rv = EVP_PKEY_derive_init(ctx); - break; + case EVP_PKEY_OP_VERIFYRECOVER: + rv = EVP_PKEY_verify_recover_init(ctx); + break; + + case EVP_PKEY_OP_ENCRYPT: + rv = EVP_PKEY_encrypt_init(ctx); + break; + + case EVP_PKEY_OP_DECRYPT: + rv = EVP_PKEY_decrypt_init(ctx); + break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive_init(ctx); + break; + } } if (rv <= 0) { @@ -478,18 +666,15 @@ if (peerform == FORMAT_ENGINE) engine = e; - peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key"); + peer = load_pubkey(file, peerform, 0, NULL, engine, "peer key"); if (peer == NULL) { BIO_printf(bio_err, "Error reading peer key %s\n", file); - ERR_print_errors(bio_err); return 0; } - ret = EVP_PKEY_derive_set_peer(ctx, peer); + ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0; EVP_PKEY_free(peer); - if (ret <= 0) - ERR_print_errors(bio_err); return ret; } @@ -522,3 +707,95 @@ } return rv; } + +#define TBUF_MAXSIZE 2048 + +static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, + EVP_PKEY *pkey, BIO *in, + int filesize, unsigned char *sig, int siglen, + unsigned char **out, size_t *poutlen) +{ + int rv = 0; + unsigned char tbuf[TBUF_MAXSIZE]; + unsigned char *mbuf = NULL; + int buf_len = 0; + + /* Some algorithms only support oneshot digests */ + if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519 + || EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) { + if (filesize < 0) { + BIO_printf(bio_err, + "Error: unable to determine file size for oneshot operation\n"); + goto end; + } + mbuf = app_malloc(filesize, "oneshot sign/verify buffer"); + switch(pkey_op) { + case EVP_PKEY_OP_VERIFY: + buf_len = BIO_read(in, mbuf, filesize); + if (buf_len != filesize) { + BIO_printf(bio_err, "Error reading raw input data\n"); + goto end; + } + rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len); + break; + case EVP_PKEY_OP_SIGN: + buf_len = BIO_read(in, mbuf, filesize); + if (buf_len != filesize) { + BIO_printf(bio_err, "Error reading raw input data\n"); + goto end; + } + rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len); + if (rv == 1 && out != NULL) { + *out = app_malloc(*poutlen, "buffer output"); + rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len); + } + break; + } + goto end; + } + + switch(pkey_op) { + case EVP_PKEY_OP_VERIFY: + for (;;) { + buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); + if (buf_len == 0) + break; + if (buf_len < 0) { + BIO_printf(bio_err, "Error reading raw input data\n"); + goto end; + } + rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len); + if (rv != 1) { + BIO_printf(bio_err, "Error verifying raw input data\n"); + goto end; + } + } + rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen); + break; + case EVP_PKEY_OP_SIGN: + for (;;) { + buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); + if (buf_len == 0) + break; + if (buf_len < 0) { + BIO_printf(bio_err, "Error reading raw input data\n"); + goto end; + } + rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len); + if (rv != 1) { + BIO_printf(bio_err, "Error signing raw input data\n"); + goto end; + } + } + rv = EVP_DigestSignFinal(mctx, NULL, poutlen); + if (rv == 1 && out != NULL) { + *out = app_malloc(*poutlen, "buffer output"); + rv = EVP_DigestSignFinal(mctx, *out, poutlen); + } + break; + } + + end: + OPENSSL_free(mbuf); + return rv; +} diff --git a/apps/prime.c b/apps/prime.c --- a/apps/prime.c +++ b/apps/prime.c @@ -1,7 +1,7 @@ /* - * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -14,28 +14,36 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS + OPT_COMMON, + OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS prime_options[] = { {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"}, - {OPT_HELP_STR, 1, '-', - " number Number to check for primality\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"bits", OPT_BITS, 'p', "Size of number in bits"}, + {"checks", OPT_CHECKS, 'p', "Number of checks"}, + + OPT_SECTION("Output"), {"hex", OPT_HEX, '-', "Hex output"}, {"generate", OPT_GENERATE, '-', "Generate a prime"}, - {"bits", OPT_BITS, 'p', "Size of number in bits"}, {"safe", OPT_SAFE, '-', "When used with -generate, generate a safe prime"}, - {"checks", OPT_CHECKS, 'p', "Number of checks"}, + + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"number", 0, 0, "Number(s) to check for primality if not generating"}, {NULL} }; int prime_main(int argc, char **argv) { BIGNUM *bn = NULL; - int hex = 0, checks = 20, generate = 0, bits = 0, safe = 0, ret = 1; + int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1; char *prog; OPTION_CHOICE o; @@ -64,20 +72,23 @@ safe = 1; break; case OPT_CHECKS: - checks = atoi(opt_arg()); + /* ignore parameter and argument */ + opt_arg(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; break; } } + + /* Optional arguments are numbers to check. */ argc = opt_num_rest(); argv = opt_rest(); - if (generate) { - if (argc != 0) { - BIO_printf(bio_err, "Extra arguments given.\n"); + if (argc != 0) goto opthelp; - } } else if (argc == 0) { - BIO_printf(bio_err, "%s: No prime specified\n", prog); goto opthelp; } @@ -121,7 +132,7 @@ BN_print(bio_out, bn); BIO_printf(bio_out, " (%s) %s prime\n", argv[0], - BN_is_prime_ex(bn, checks, NULL, NULL) + BN_check_prime(bn, NULL, NULL) ? "is" : "is not"); } } diff --git a/apps/progs.pl b/apps/progs.pl --- a/apps/progs.pl +++ b/apps/progs.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -14,17 +14,22 @@ use lib '.'; use configdata qw/@disablables %unified_info/; +my $opt = shift @ARGV; +die "Unrecognised option, must be -C or -H\n" + unless ($opt eq '-H' || $opt eq '-C'); + my %commands = (); my $cmdre = qr/^\s*int\s+([a-z_][a-z0-9_]*)_main\(\s*int\s+argc\s*,/; my $apps_openssl = shift @ARGV; -my $YEAR = [localtime()]->[5] + 1900; +my $YEAR = [gmtime($ENV{SOURCE_DATE_EPOCH} || time())]->[5] + 1900; # because the program apps/openssl has object files as sources, and # they then have the corresponding C files as source, we need to chain # the lookups in %unified_info my @openssl_source = map { @{$unified_info{sources}->{$_}} } - grep { /\.o$/ } + grep { /\.o$/ + && !$unified_info{attributes}->{sources}->{$apps_openssl}->{$_}->{nocheck} } @{$unified_info{sources}->{$apps_openssl}}; foreach my $filename (@openssl_source) { @@ -38,144 +43,178 @@ @ARGV = sort keys %commands; -print <<"EOF"; +if ($opt eq '-H') { + print <<"EOF"; /* * WARNING: do not edit! * Generated by apps/progs.pl * * Copyright 1995-$YEAR The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ -typedef enum FUNC_TYPE { - FT_none, FT_general, FT_md, FT_cipher, FT_pkey, - FT_md_alg, FT_cipher_alg -} FUNC_TYPE; - -typedef struct function_st { - FUNC_TYPE type; - const char *name; - int (*func)(int argc, char *argv[]); - const OPTIONS *help; -} FUNCTION; - -DEFINE_LHASH_OF(FUNCTION); +#include "function.h" EOF -foreach (@ARGV) { - printf "extern int %s_main(int argc, char *argv[]);\n", $_; -} -print "\n"; + foreach (@ARGV) { + printf "extern int %s_main(int argc, char *argv[]);\n", $_; + } + print "\n"; -foreach (@ARGV) { - printf "extern const OPTIONS %s_options[];\n", $_; -} -print "\n"; - -my %cmd_disabler = ( - ciphers => "sock", - genrsa => "rsa", - rsautl => "rsa", - gendsa => "dsa", - dsaparam => "dsa", - gendh => "dh", - dhparam => "dh", - ecparam => "ec", - pkcs12 => "des", -); - -print "#ifdef INCLUDE_FUNCTION_TABLE\n"; -print "static FUNCTION functions[] = {\n"; -foreach my $cmd ( @ARGV ) { - my $str = " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options},\n"; - if ($cmd =~ /^s_/) { - print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n"; - } elsif (grep { $cmd eq $_ } @disablables) { - print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; - } elsif (my $disabler = $cmd_disabler{$cmd}) { - print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; - } else { - print $str; + foreach (@ARGV) { + printf "extern const OPTIONS %s_options[];\n", $_; } + print "\n"; + print "extern FUNCTION functions[];\n"; } -my %md_disabler = ( - blake2b512 => "blake2", - blake2s256 => "blake2", -); -foreach my $cmd ( - "md2", "md4", "md5", - "gost", - "sha1", "sha224", "sha256", "sha384", - "sha512", "sha512-224", "sha512-256", - "sha3-224", "sha3-256", "sha3-384", "sha3-512", - "shake128", "shake256", - "mdc2", "rmd160", "blake2b512", "blake2s256", - "sm3" -) { - my $str = " {FT_md, \"$cmd\", dgst_main},\n"; - if (grep { $cmd eq $_ } @disablables) { - print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; - } elsif (my $disabler = $md_disabler{$cmd}) { - print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; - } else { - print $str; +if ($opt eq '-C') { + print <<"EOF"; +/* + * WARNING: do not edit! + * Generated by apps/progs.pl + * + * Copyright 1995-$YEAR 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 + * https://www.openssl.org/source/license.html + */ + +#include "progs.h" + +EOF + + my %cmd_disabler = ( + ciphers => "sock", + genrsa => "rsa", + gendsa => "dsa", + dsaparam => "dsa", + gendh => "dh", + dhparam => "dh", + ecparam => "ec", + ); + my %cmd_deprecated = ( +# The format of this table is: +# [0] = alternative command to use instead +# [1] = deprecented in this version +# [2] = preprocessor conditional for exclusing irrespective of deprecation +# rsa => [ "pkey", "3_0", "rsa" ], +# genrsa => [ "genpkey", "3_0", "rsa" ], + rsautl => [ "pkeyutl", "3_0", "rsa" ], +# dhparam => [ "pkeyparam", "3_0", "dh" ], +# dsaparam => [ "pkeyparam", "3_0", "dsa" ], +# dsa => [ "pkey", "3_0", "dsa" ], +# gendsa => [ "genpkey", "3_0", "dsa" ], +# ec => [ "pkey", "3_0", "ec" ], +# ecparam => [ "pkeyparam", "3_0", "ec" ], + ); + + print "FUNCTION functions[] = {\n"; + foreach my $cmd ( @ARGV ) { + my $str = + " {FT_general, \"$cmd\", ${cmd}_main, ${cmd}_options, NULL, NULL},\n"; + if ($cmd =~ /^s_/) { + print "#ifndef OPENSSL_NO_SOCK\n${str}#endif\n"; + } elsif (my $deprecated = $cmd_deprecated{$cmd}) { + my @dep = @{$deprecated}; + my $daltprg = $dep[0]; + my $dver = $dep[1]; + my $dsys = $dep[2]; + print "#if !defined(OPENSSL_NO_DEPRECATED_" . $dver . ")"; + if ($dsys) { + print " && !defined(OPENSSL_NO_" . uc($dsys) . ")"; + } + $dver =~ s/_/./g; + my $dalt = "\"" . $daltprg . "\", \"" . $dver . "\""; + $str =~ s/NULL, NULL/$dalt/; + print "\n${str}#endif\n"; + } elsif (grep { $cmd eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; + } elsif (my $disabler = $cmd_disabler{$cmd}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } } -} -my %cipher_disabler = ( - des3 => "des", - desx => "des", - cast5 => "cast", -); -foreach my $cmd ( - "aes-128-cbc", "aes-128-ecb", - "aes-192-cbc", "aes-192-ecb", - "aes-256-cbc", "aes-256-ecb", - "aria-128-cbc", "aria-128-cfb", - "aria-128-ctr", "aria-128-ecb", "aria-128-ofb", - "aria-128-cfb1", "aria-128-cfb8", - "aria-192-cbc", "aria-192-cfb", - "aria-192-ctr", "aria-192-ecb", "aria-192-ofb", - "aria-192-cfb1", "aria-192-cfb8", - "aria-256-cbc", "aria-256-cfb", - "aria-256-ctr", "aria-256-ecb", "aria-256-ofb", - "aria-256-cfb1", "aria-256-cfb8", - "camellia-128-cbc", "camellia-128-ecb", - "camellia-192-cbc", "camellia-192-ecb", - "camellia-256-cbc", "camellia-256-ecb", - "base64", "zlib", - "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40", - "rc2", "bf", "cast", "rc5", - "des-ecb", "des-ede", "des-ede3", - "des-cbc", "des-ede-cbc","des-ede3-cbc", - "des-cfb", "des-ede-cfb","des-ede3-cfb", - "des-ofb", "des-ede-ofb","des-ede3-ofb", - "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb", - "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb", - "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc", - "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb", - "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb", - "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb", - "sm4-cbc", "sm4-ecb", "sm4-cfb", "sm4-ofb", "sm4-ctr" -) { - my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options},\n"; - (my $algo = $cmd) =~ s/-.*//g; - if ($cmd eq "zlib") { - print "#ifdef ZLIB\n${str}#endif\n"; - } elsif (grep { $algo eq $_ } @disablables) { - print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n"; - } elsif (my $disabler = $cipher_disabler{$algo}) { - print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; - } else { - print $str; + my %md_disabler = ( + blake2b512 => "blake2", + blake2s256 => "blake2", + ); + foreach my $cmd ( + "md2", "md4", "md5", + "sha1", "sha224", "sha256", "sha384", + "sha512", "sha512-224", "sha512-256", + "sha3-224", "sha3-256", "sha3-384", "sha3-512", + "shake128", "shake256", + "mdc2", "rmd160", "blake2b512", "blake2s256", + "sm3" + ) { + my $str = " {FT_md, \"$cmd\", dgst_main, NULL, NULL},\n"; + if (grep { $cmd eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($cmd) . "\n${str}#endif\n"; + } elsif (my $disabler = $md_disabler{$cmd}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } } -} -print " {0, NULL, NULL}\n};\n"; -print "#endif\n"; + my %cipher_disabler = ( + des3 => "des", + desx => "des", + cast5 => "cast", + ); + foreach my $cmd ( + "aes-128-cbc", "aes-128-ecb", + "aes-192-cbc", "aes-192-ecb", + "aes-256-cbc", "aes-256-ecb", + "aria-128-cbc", "aria-128-cfb", + "aria-128-ctr", "aria-128-ecb", "aria-128-ofb", + "aria-128-cfb1", "aria-128-cfb8", + "aria-192-cbc", "aria-192-cfb", + "aria-192-ctr", "aria-192-ecb", "aria-192-ofb", + "aria-192-cfb1", "aria-192-cfb8", + "aria-256-cbc", "aria-256-cfb", + "aria-256-ctr", "aria-256-ecb", "aria-256-ofb", + "aria-256-cfb1", "aria-256-cfb8", + "camellia-128-cbc", "camellia-128-ecb", + "camellia-192-cbc", "camellia-192-ecb", + "camellia-256-cbc", "camellia-256-ecb", + "base64", "zlib", + "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40", + "rc2", "bf", "cast", "rc5", + "des-ecb", "des-ede", "des-ede3", + "des-cbc", "des-ede-cbc","des-ede3-cbc", + "des-cfb", "des-ede-cfb","des-ede3-cfb", + "des-ofb", "des-ede-ofb","des-ede3-ofb", + "idea-cbc","idea-ecb", "idea-cfb", "idea-ofb", + "seed-cbc","seed-ecb", "seed-cfb", "seed-ofb", + "rc2-cbc", "rc2-ecb", "rc2-cfb","rc2-ofb", "rc2-64-cbc", "rc2-40-cbc", + "bf-cbc", "bf-ecb", "bf-cfb", "bf-ofb", + "cast5-cbc","cast5-ecb", "cast5-cfb","cast5-ofb", + "cast-cbc", "rc5-cbc", "rc5-ecb", "rc5-cfb", "rc5-ofb", + "sm4-cbc", "sm4-ecb", "sm4-cfb", "sm4-ofb", "sm4-ctr" + ) { + my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options, NULL},\n"; + (my $algo = $cmd) =~ s/-.*//g; + if ($cmd eq "zlib") { + print "#ifdef ZLIB\n${str}#endif\n"; + } elsif (grep { $algo eq $_ } @disablables) { + print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n"; + } elsif (my $disabler = $cipher_disabler{$algo}) { + print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; + } else { + print $str; + } + } + + print " {0, NULL, NULL, NULL, NULL}\n};\n"; +} diff --git a/apps/rand.c b/apps/rand.c --- a/apps/rand.c +++ b/apps/rand.c @@ -1,7 +1,7 @@ /* - * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,22 +19,30 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, - OPT_R_ENUM + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS rand_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [flags] num\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] num\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"out", OPT_OUT, '>', "Output file"}, - OPT_R_OPTIONS, - {"base64", OPT_BASE64, '-', "Base64 encode output"}, - {"hex", OPT_HEX, '-', "Hex encode output"}, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"base64", OPT_BASE64, '-', "Base64 encode output"}, + {"hex", OPT_HEX, '-', "Hex encode output"}, + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"num", 0, 0, "Number of bytes to generate"}, {NULL} }; @@ -74,18 +82,26 @@ case OPT_HEX: format = FORMAT_TEXT; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* Optional argument is number of bytes to generate. */ argc = opt_num_rest(); argv = opt_rest(); if (argc == 1) { if (!opt_int(argv[0], &num) || num <= 0) - goto end; - } else if (argc > 0) { - BIO_printf(bio_err, "Extra arguments given.\n"); + goto opthelp; + } else if (argc != 0) { goto opthelp; } + if (!app_RAND_load()) + goto end; + out = bio_open_default(outfile, 'w', format); if (out == NULL) goto end; diff --git a/apps/rehash.c b/apps/rehash.c --- a/apps/rehash.c +++ b/apps/rehash.c @@ -1,8 +1,8 @@ /* - * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2013-2014 Timo Teräs * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -42,7 +42,6 @@ # include # include - # ifndef PATH_MAX # define PATH_MAX 4096 # endif @@ -169,6 +168,12 @@ *ep = nilhentry; ep->old_id = ~0; ep->filename = OPENSSL_strdup(filename); + if (ep->filename == NULL) { + OPENSSL_free(ep); + ep = NULL; + BIO_printf(bio_err, "out of memory\n"); + return 1; + } if (bp->last_entry) bp->last_entry->next = ep; if (bp->first_entry == NULL) @@ -209,7 +214,7 @@ return -1; for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) { const char *suffix = suffixes[type]; - if (strncasecmp(suffix, &filename[i], strlen(suffix)) == 0) + if (OPENSSL_strncasecmp(suffix, &filename[i], strlen(suffix)) == 0) break; } i += strlen(suffixes[type]); @@ -233,7 +238,7 @@ { STACK_OF (X509_INFO) *inf = NULL; X509_INFO *x; - X509_NAME *name = NULL; + const X509_NAME *name = NULL; BIO *b; const char *ext; unsigned char digest[EVP_MAX_MD_SIZE]; @@ -244,7 +249,7 @@ if ((ext = strrchr(filename, '.')) == NULL) goto end; for (i = 0; i < OSSL_NELEM(extensions); i++) { - if (strcasecmp(extensions[i], ext + 1) == 0) + if (OPENSSL_strcasecmp(extensions[i], ext + 1) == 0) break; } if (i >= OSSL_NELEM(extensions)) @@ -292,10 +297,23 @@ goto end; } if (name != NULL) { - if ((h == HASH_NEW) || (h == HASH_BOTH)) - errs += add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0); + if (h == HASH_NEW || h == HASH_BOTH) { + int ok; + unsigned long hash_value = + X509_NAME_hash_ex(name, + app_get0_libctx(), app_get0_propq(), &ok); + + if (ok) { + errs += add_entry(type, hash_value, filename, digest, 1, ~0); + } else { + BIO_printf(bio_err, "%s: error calculating SHA1 hash value\n", + opt_getprog()); + errs++; + } + } if ((h == HASH_OLD) || (h == HASH_BOTH)) - errs += add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0); + errs += add_entry(type, X509_NAME_hash_old(name), + filename, digest, 1, ~0); } end: @@ -454,19 +472,28 @@ } typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE + OPT_COMMON, + OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS rehash_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert-directory...]\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [directory...]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"h", OPT_HELP, '-', "Display this summary"}, {"compat", OPT_COMPAT, '-', "Create both new- and old-style hash links"}, {"old", OPT_OLD, '-', "Use old-style hash to generate links"}, {"n", OPT_N, '-', "Do not remove existing links"}, + + OPT_SECTION("Output"), {"v", OPT_VERBOSE, '-', "Verbose output"}, + + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"directory", 0, 0, "One or more directories to process (optional)"}, {NULL} }; @@ -501,13 +528,19 @@ case OPT_VERBOSE: verbose = 1; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* Optional arguments are directories to scan. */ argc = opt_num_rest(); argv = opt_rest(); evpmd = EVP_sha1(); - evpmdsize = EVP_MD_size(evpmd); + evpmdsize = EVP_MD_get_size(evpmd); if (*argv != NULL) { while (*argv != NULL) diff --git a/apps/req.c b/apps/req.c --- a/apps/req.c +++ b/apps/req.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -14,6 +14,7 @@ #include #include "apps.h" #include "progs.h" +#include #include #include #include @@ -25,32 +26,29 @@ #include #include #include -#ifndef OPENSSL_NO_RSA -# include -#endif +#include #ifndef OPENSSL_NO_DSA # include #endif -#define SECTION "req" - -#define BITS "default_bits" -#define KEYFILE "default_keyfile" -#define PROMPT "prompt" -#define DISTINGUISHED_NAME "distinguished_name" -#define ATTRIBUTES "attributes" -#define V3_EXTENSIONS "x509_extensions" -#define REQ_EXTENSIONS "req_extensions" -#define STRING_MASK "string_mask" -#define UTF8_IN "utf8" - -#define DEFAULT_KEY_LENGTH 2048 -#define MIN_KEY_LENGTH 512 - -static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn, - int attribs, unsigned long chtype); -static int build_subject(X509_REQ *req, const char *subj, unsigned long chtype, - int multirdn); +#define BITS "default_bits" +#define KEYFILE "default_keyfile" +#define PROMPT "prompt" +#define DISTINGUISHED_NAME "distinguished_name" +#define ATTRIBUTES "attributes" +#define V3_EXTENSIONS "x509_extensions" +#define REQ_EXTENSIONS "req_extensions" +#define STRING_MASK "string_mask" +#define UTF8_IN "utf8" + +#define DEFAULT_KEY_LENGTH 2048 +#define MIN_KEY_LENGTH 512 +#define DEFAULT_DAYS 30 /* default cert validity period in days */ +#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */ +#define EXT_COPY_UNSET -1 + +static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj, + int mutlirdn, int attribs, unsigned long chtype); static int prompt_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, @@ -65,91 +63,113 @@ char *value, int nid, int n_min, int n_max, unsigned long chtype, int mval); static int genpkey_cb(EVP_PKEY_CTX *ctx); -static int build_data(char *text, const char *def, - char *value, int n_min, int n_max, - char *buf, const int buf_size, - const char *desc1, const char *desc2 - ); +static int build_data(char *text, const char *def, char *value, + int n_min, int n_max, char *buf, const int buf_size, + const char *desc1, const char *desc2); static int req_check_len(int len, int n_min, int n_max); static int check_end(const char *str, const char *end); static int join(char buf[], size_t buf_size, const char *name, const char *tail, const char *desc); static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, - int *pkey_type, long *pkeylen, - char **palgnam, ENGINE *keygen_engine); + char **pkeytype, long *pkeylen, + ENGINE *keygen_engine); + +static const char *section = "req"; static CONF *req_conf = NULL; static CONF *addext_conf = NULL; static int batch = 0; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, - OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, - OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, + OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, + OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, - OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, + OPT_CA, OPT_CAKEY, + OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, + OPT_COPY_EXTENSIONS, OPT_ADDEXT, OPT_EXTENSIONS, OPT_REQEXTS, OPT_PRECERT, OPT_MD, - OPT_R_ENUM + OPT_SECTION, + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS req_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"keygen_engine", OPT_KEYGEN_ENGINE, 's', + "Specify engine to be used for key generation operations"}, +#endif + {"in", OPT_IN, '<', "X.509 request input file (default stdin)"}, {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, - {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, - {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, - {"key", OPT_KEY, 's', "Private key to use"}, - {"keyform", OPT_KEYFORM, 'f', "Key file format"}, - {"pubkey", OPT_PUBKEY, '-', "Output public key"}, + {"verify", OPT_VERIFY, '-', "Verify self-signature on the request"}, + + OPT_SECTION("Certificate"), {"new", OPT_NEW, '-', "New request"}, {"config", OPT_CONFIG, '<', "Request template file"}, - {"keyout", OPT_KEYOUT, '>', "File to send the key to"}, - {"passin", OPT_PASSIN, 's', "Private key password source"}, - {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, - OPT_R_OPTIONS, - {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"}, - {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, - {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, - {"batch", OPT_BATCH, '-', - "Do not ask anything during request generation"}, - {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"}, - {"modulus", OPT_MODULUS, '-', "RSA modulus"}, - {"verify", OPT_VERIFY, '-', "Verify signature on REQ"}, - {"nodes", OPT_NODES, '-', "Don't encrypt the output key"}, - {"noout", OPT_NOOUT, '-', "Do not output REQ"}, - {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"section", OPT_SECTION, 's', "Config section to use (default \"req\")"}, {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"}, {"reqopt", OPT_REQOPT, 's', "Various request text options"}, {"text", OPT_TEXT, '-', "Text form of request"}, {"x509", OPT_X509, '-', - "Output a x509 structure instead of a cert request"}, + "Output an X.509 certificate structure instead of a cert request"}, + {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"}, + {"CAkey", OPT_CAKEY, 's', + "Issuer private key to use with -CA; default is -CA arg"}, {OPT_MORE_STR, 1, 1, "(Required by some CA's)"}, - {"subj", OPT_SUBJ, 's', "Set or modify request subject"}, - {"subject", OPT_SUBJECT, '-', "Output the request's subject"}, + {"subj", OPT_SUBJ, 's', "Set or modify subject of request or cert"}, + {"subject", OPT_SUBJECT, '-', + "Print the subject of the output request or cert"}, {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', - "Enable support for multivalued RDNs"}, + "Deprecated; multi-valued RDNs support is always on."}, {"days", OPT_DAYS, 'p', "Number of days cert is valid for"}, {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, + {"copy_extensions", OPT_COPY_EXTENSIONS, 's', + "copy extensions from request when using -x509"}, {"addext", OPT_ADDEXT, 's', "Additional cert extension key=value pair (may be given more than once)"}, {"extensions", OPT_EXTENSIONS, 's', "Cert extension section (override value in config file)"}, {"reqexts", OPT_REQEXTS, 's', "Request extension section (override value in config file)"}, - {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"}, + {"precert", OPT_PRECERT, '-', + "Add a poison extension to the generated cert (implies -new)"}, + + OPT_SECTION("Keys and Signing"), + {"key", OPT_KEY, 's', "Key for signing, and to include unless -in given"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"}, + {"pubkey", OPT_PUBKEY, '-', "Output public key"}, + {"keyout", OPT_KEYOUT, '>', "File to write private key to"}, + {"passin", OPT_PASSIN, 's', "Private key and certificate password source"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + {"newkey", OPT_NEWKEY, 's', + "Generate new key with [:] or [:] or param:"}, + {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, + {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"}, {"", OPT_MD, '-', "Any supported digest"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, - {"keygen_engine", OPT_KEYGEN_ENGINE, 's', - "Specify engine to be used for key generation operations"}, -#endif + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, + {"batch", OPT_BATCH, '-', + "Do not ask anything during request generation"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"}, + {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"}, + {"noout", OPT_NOOUT, '-', "Do not output REQ"}, + {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"}, + {"modulus", OPT_MODULUS, '-', "RSA modulus"}, + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, {NULL} }; - /* * An LHASH of strings, where each string is an extension name. */ @@ -169,9 +189,8 @@ } /* - * Is the |kv| key already duplicated? This is remarkably tricky to get - * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax - * error. + * Is the |kv| key already duplicated? This is remarkably tricky to get right. + * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error. */ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) { @@ -200,7 +219,7 @@ *p = '\0'; /* Finally have a clean "key"; see if it's there [by attempt to add it]. */ - p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv); + p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING *)kv); if (p != NULL) { OPENSSL_free(p); return 1; @@ -215,36 +234,39 @@ int req_main(int argc, char **argv) { ASN1_INTEGER *serial = NULL; - BIO *in = NULL, *out = NULL; + BIO *out = NULL; ENGINE *e = NULL, *gen_eng = NULL; - EVP_PKEY *pkey = NULL; + EVP_PKEY *pkey = NULL, *CAkey = NULL; EVP_PKEY_CTX *genctx = NULL; - STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; + STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL, *vfyopts = NULL; LHASH_OF(OPENSSL_STRING) *addexts = NULL; - X509 *x509ss = NULL; + X509 *new_x509 = NULL, *CAcert = NULL; X509_REQ *req = NULL; - const EVP_CIPHER *cipher = NULL; - const EVP_MD *md_alg = NULL, *digest = NULL; + EVP_CIPHER *cipher = NULL; + EVP_MD *md = NULL; + int ext_copy = EXT_COPY_UNSET; BIO *addext_bio = NULL; - char *extensions = NULL, *infile = NULL; - char *outfile = NULL, *keyfile = NULL; + char *extensions = NULL; + const char *infile = NULL, *CAfile = NULL, *CAkeyfile = NULL; + char *outfile = NULL, *keyfile = NULL, *digest = NULL; char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL; char *passin = NULL, *passout = NULL; char *nofree_passin = NULL, *nofree_passout = NULL; char *req_exts = NULL, *subj = NULL; + X509_NAME *fsubj = NULL; char *template = default_config_file, *keyout = NULL; const char *keyalg = NULL; OPTION_CHOICE o; - int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0; - int pkey_type = -1, private = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM; - int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0; - int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; - long newkey = -1; + int days = UNSET_DAYS; + int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF; + int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0; + int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; + long newkey_len = -1; unsigned long chtype = MBSTRING_ASC, reqflag = 0; #ifndef OPENSSL_NO_DES - cipher = EVP_des_ede3_cbc(); + cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); #endif prog = opt_init(argc, argv, req_options); @@ -272,7 +294,7 @@ break; case OPT_KEYGEN_ENGINE: #ifndef OPENSSL_NO_ENGINE - gen_eng = ENGINE_by_id(opt_arg()); + gen_eng = setup_engine(opt_arg(), 0); if (gen_eng == NULL) { BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv); goto opthelp; @@ -291,6 +313,9 @@ case OPT_CONFIG: template = opt_arg(); break; + case OPT_SECTION: + section = opt_arg(); + break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) goto opthelp; @@ -314,14 +339,19 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_NEWKEY: keyalg = opt_arg(); newreq = 1; break; case OPT_PKEYOPT: - if (!pkeyopts) + if (pkeyopts == NULL) pkeyopts = sk_OPENSSL_STRING_new_null(); - if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg())) + if (pkeyopts == NULL + || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg())) goto opthelp; break; case OPT_SIGOPT: @@ -330,6 +360,12 @@ if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; + case OPT_VFYOPT: + if (!vfyopts) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto opthelp; + break; case OPT_BATCH: batch = 1; break; @@ -343,7 +379,8 @@ verify = 1; break; case OPT_NODES: - nodes = 1; + case OPT_NOENC: + noenc = 1; break; case OPT_NOOUT: noout = 1; @@ -366,10 +403,22 @@ text = 1; break; case OPT_X509: - x509 = 1; + gen_x509 = 1; + break; + case OPT_CA: + CAfile = opt_arg(); + gen_x509 = 1; + break; + case OPT_CAKEY: + CAkeyfile = opt_arg(); break; case OPT_DAYS: days = atoi(opt_arg()); + if (days < -1) { + BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n", + prog); + goto end; + } break; case OPT_SET_SERIAL: if (serial != NULL) { @@ -387,7 +436,14 @@ subj = opt_arg(); break; case OPT_MULTIVALUE_RDN: - multirdn = 1; + /* obsolete */ + break; + case OPT_COPY_EXTENSIONS: + if (!set_ext_copy(&ext_copy, opt_arg())) { + BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", + opt_arg()); + goto end; + } break; case OPT_ADDEXT: p = opt_arg(); @@ -398,9 +454,11 @@ goto end; } i = duplicated(addexts, p); - if (i == 1) + if (i == 1) { + BIO_printf(bio_err, "Duplicate extension: %s\n", p); goto opthelp; - if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0) + } + if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0) goto end; break; case OPT_EXTENSIONS: @@ -413,37 +471,39 @@ newreq = precert = 1; break; case OPT_MD: - if (!opt_md(opt_unknown(), &md_alg)) - goto opthelp; - digest = md_alg; + digest = opt_unknown(); break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; - if (days && !x509) - BIO_printf(bio_err, "Ignoring -days; not generating a certificate\n"); - if (x509 && infile == NULL) - newreq = 1; + if (!app_RAND_load()) + goto end; - /* TODO: simplify this as pkey is still always NULL here */ - private = newreq && (pkey == NULL) ? 1 : 0; + if (!gen_x509) { + if (days != UNSET_DAYS) + BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n"); + if (ext_copy == EXT_COPY_NONE) + BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n"); + } + if (gen_x509 && infile == NULL) + newreq = 1; if (!app_passwd(passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } - if (verbose) - BIO_printf(bio_err, "Using configuration from %s\n", template); - if ((req_conf = app_load_config(template)) == NULL) + if ((req_conf = app_load_config_verbose(template, verbose)) == NULL) goto end; - if (addext_bio) { + if (addext_bio != NULL) { if (verbose) BIO_printf(bio_err, - "Using additional configuration from command line\n"); + "Using additional configuration from -addext options\n"); if ((addext_conf = app_load_config_bio(addext_bio, NULL)) == NULL) goto end; } @@ -455,14 +515,12 @@ if (p == NULL) ERR_clear_error(); if (p != NULL) { - BIO *oid_bio; + BIO *oid_bio = BIO_new_file(p, "r"); - oid_bio = BIO_new_file(p, "r"); if (oid_bio == NULL) { - /*- - BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); - ERR_print_errors(bio_err); - */ + if (verbose) + BIO_printf(bio_err, + "Problems opening '%s' for extra OIDs\n", p); } else { OBJ_create_objects(oid_bio); BIO_free(oid_bio); @@ -472,59 +530,67 @@ if (!add_oid_section(req_conf)) goto end; - if (md_alg == NULL) { - p = NCONF_get_string(req_conf, SECTION, "default_md"); - if (p == NULL) { + /* Check that any specified digest is fetchable */ + if (digest != NULL) { + if (!opt_md(digest, &md)) { ERR_clear_error(); - } else { - if (!opt_md(p, &md_alg)) - goto opthelp; - digest = md_alg; + goto opthelp; } + EVP_MD_free(md); + } else { + /* No digest specified, default to configuration */ + p = NCONF_get_string(req_conf, section, "default_md"); + if (p == NULL) + ERR_clear_error(); + else + digest = p; } if (extensions == NULL) { - extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); + extensions = NCONF_get_string(req_conf, section, V3_EXTENSIONS); if (extensions == NULL) ERR_clear_error(); } if (extensions != NULL) { /* Check syntax of file */ X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, req_conf); if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) { BIO_printf(bio_err, - "Error Loading extension section %s\n", extensions); + "Error checking x509 extension section %s\n", + extensions); goto end; } } if (addext_conf != NULL) { /* Check syntax of command line extensions */ X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, addext_conf); if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { - BIO_printf(bio_err, "Error Loading command line extensions\n"); + BIO_printf(bio_err, "Error checking extensions defined using -addext\n"); goto end; } } if (passin == NULL) { passin = nofree_passin = - NCONF_get_string(req_conf, SECTION, "input_password"); + NCONF_get_string(req_conf, section, "input_password"); if (passin == NULL) ERR_clear_error(); } if (passout == NULL) { passout = nofree_passout = - NCONF_get_string(req_conf, SECTION, "output_password"); + NCONF_get_string(req_conf, section, "output_password"); if (passout == NULL) ERR_clear_error(); } - p = NCONF_get_string(req_conf, SECTION, STRING_MASK); + p = NCONF_get_string(req_conf, section, STRING_MASK); if (p == NULL) ERR_clear_error(); @@ -534,7 +600,7 @@ } if (chtype != MBSTRING_UTF8) { - p = NCONF_get_string(req_conf, SECTION, UTF8_IN); + p = NCONF_get_string(req_conf, section, UTF8_IN); if (p == NULL) ERR_clear_error(); else if (strcmp(p, "yes") == 0) @@ -542,134 +608,117 @@ } if (req_exts == NULL) { - req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); + req_exts = NCONF_get_string(req_conf, section, REQ_EXTENSIONS); if (req_exts == NULL) ERR_clear_error(); } if (req_exts != NULL) { /* Check syntax of file */ X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, req_conf); if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) { BIO_printf(bio_err, - "Error Loading request extension section %s\n", + "Error checking request extension section %s\n", req_exts); goto end; } } if (keyfile != NULL) { - pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); - if (pkey == NULL) { - /* load_key() has already printed an appropriate message */ + pkey = load_key(keyfile, keyform, 0, passin, e, "private key"); + if (pkey == NULL) goto end; - } else { - app_RAND_load_conf(req_conf, SECTION); - } + app_RAND_load_conf(req_conf, section); } + if (newreq && pkey == NULL) { + app_RAND_load_conf(req_conf, section); - if (newreq && (pkey == NULL)) { - app_RAND_load_conf(req_conf, SECTION); + if (!NCONF_get_number(req_conf, section, BITS, &newkey_len)) + newkey_len = DEFAULT_KEY_LENGTH; - if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) { - newkey = DEFAULT_KEY_LENGTH; - } - - if (keyalg != NULL) { - genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey, - &keyalgstr, gen_eng); - if (genctx == NULL) - goto end; - } + genctx = set_keygen_ctx(keyalg, &keyalgstr, &newkey_len, gen_eng); + if (genctx == NULL) + goto end; - if (newkey < MIN_KEY_LENGTH - && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) { - BIO_printf(bio_err, "private key length is too short,\n"); - BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", - MIN_KEY_LENGTH, newkey); + if (newkey_len < MIN_KEY_LENGTH + && (EVP_PKEY_CTX_is_a(genctx, "RSA") + || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS") + || EVP_PKEY_CTX_is_a(genctx, "DSA"))) { + BIO_printf(bio_err, "Private key length too short, needs to be at least %d bits, not %ld.\n", + MIN_KEY_LENGTH, newkey_len); goto end; } - if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS) + if (newkey_len > OPENSSL_RSA_MAX_MODULUS_BITS + && (EVP_PKEY_CTX_is_a(genctx, "RSA") + || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS"))) BIO_printf(bio_err, "Warning: It is not recommended to use more than %d bit for RSA keys.\n" " Your key size is %ld! Larger key size may behave not as expected.\n", - OPENSSL_RSA_MAX_MODULUS_BITS, newkey); + OPENSSL_RSA_MAX_MODULUS_BITS, newkey_len); #ifndef OPENSSL_NO_DSA - if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS) + if (EVP_PKEY_CTX_is_a(genctx, "DSA") + && newkey_len > OPENSSL_DSA_MAX_MODULUS_BITS) BIO_printf(bio_err, "Warning: It is not recommended to use more than %d bit for DSA keys.\n" " Your key size is %ld! Larger key size may behave not as expected.\n", - OPENSSL_DSA_MAX_MODULUS_BITS, newkey); + OPENSSL_DSA_MAX_MODULUS_BITS, newkey_len); #endif - if (genctx == NULL) { - genctx = set_keygen_ctx(NULL, &pkey_type, &newkey, - &keyalgstr, gen_eng); - if (!genctx) - goto end; - } - if (pkeyopts != NULL) { char *genopt; for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) { genopt = sk_OPENSSL_STRING_value(pkeyopts, i); if (pkey_ctrl_string(genctx, genopt) <= 0) { - BIO_printf(bio_err, "parameter error \"%s\"\n", genopt); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Key parameter error \"%s\"\n", genopt); goto end; } } } - if (pkey_type == EVP_PKEY_EC) { - BIO_printf(bio_err, "Generating an EC private key\n"); - } else { - BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr); - } - EVP_PKEY_CTX_set_cb(genctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(genctx, bio_err); - if (EVP_PKEY_keygen(genctx, &pkey) <= 0) { - BIO_puts(bio_err, "Error Generating Key\n"); - goto end; - } + pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose); EVP_PKEY_CTX_free(genctx); genctx = NULL; + } + if (keyout == NULL && keyfile == NULL) { + keyout = NCONF_get_string(req_conf, section, KEYFILE); + if (keyout == NULL) + ERR_clear_error(); + } - if (keyout == NULL) { - keyout = NCONF_get_string(req_conf, SECTION, KEYFILE); + if (pkey != NULL && (keyfile == NULL || keyout != NULL)) { + if (verbose) { + BIO_printf(bio_err, "Writing private key to "); if (keyout == NULL) - ERR_clear_error(); + BIO_printf(bio_err, "stdout\n"); + else + BIO_printf(bio_err, "'%s'\n", keyout); } - - if (keyout == NULL) - BIO_printf(bio_err, "writing new private key to stdout\n"); - else - BIO_printf(bio_err, "writing new private key to '%s'\n", keyout); - out = bio_open_owner(keyout, outformat, private); + out = bio_open_owner(keyout, outformat, newreq); if (out == NULL) goto end; - p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key"); + p = NCONF_get_string(req_conf, section, "encrypt_rsa_key"); if (p == NULL) { ERR_clear_error(); - p = NCONF_get_string(req_conf, SECTION, "encrypt_key"); + p = NCONF_get_string(req_conf, section, "encrypt_key"); if (p == NULL) ERR_clear_error(); } if ((p != NULL) && (strcmp(p, "no") == 0)) cipher = NULL; - if (nodes) + if (noenc) cipher = NULL; i = 0; loop: - assert(private); if (!PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, passout)) { if ((ERR_GET_REASON(ERR_peek_error()) == @@ -685,112 +734,151 @@ BIO_printf(bio_err, "-----\n"); } + /* + * subj is expected to be in the format /type0=value0/type1=value1/type2=... + * where characters may be escaped by \ + */ + if (subj != NULL + && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL) + goto end; + if (!newreq) { - in = bio_open_default(infile, 'r', informat); - if (in == NULL) + req = load_csr(infile /* if NULL, reads from stdin */, + informat, "X509 request"); + if (req == NULL) goto end; + } - if (informat == FORMAT_ASN1) - req = d2i_X509_REQ_bio(in, NULL); - else - req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); - if (req == NULL) { - BIO_printf(bio_err, "unable to load X509 request\n"); + if (CAkeyfile == NULL) + CAkeyfile = CAfile; + if (CAkeyfile != NULL) { + if (CAfile == NULL) { + BIO_printf(bio_err, + "Warning: Ignoring -CAkey option since no -CA option is given\n"); + } else { + if ((CAkey = load_key(CAkeyfile, FORMAT_UNDEF, + 0, passin, e, + CAkeyfile != CAfile + ? "issuer private key from -CAkey arg" + : "issuer private key from -CA arg")) == NULL) + goto end; + } + } + if (CAfile != NULL) { + if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin, + "issuer cert from -CA arg")) == NULL) + goto end; + if (!X509_check_private_key(CAcert, CAkey)) { + BIO_printf(bio_err, + "Issuer CA certificate and key do not match\n"); goto end; } } - - if (newreq || x509) { - if (pkey == NULL) { - BIO_printf(bio_err, "you need to specify a private key\n"); + if (newreq || gen_x509) { + if (CAcert == NULL && pkey == NULL) { + BIO_printf(bio_err, "Must provide a signature key using -key or" + " provide -CA / -CAkey\n"); goto end; } if (req == NULL) { - req = X509_REQ_new(); + req = X509_REQ_new_ex(app_get0_libctx(), app_get0_propq()); if (req == NULL) { goto end; } - i = make_REQ(req, pkey, subj, multirdn, !x509, chtype); - subj = NULL; /* done processing '-subj' option */ - if (!i) { - BIO_printf(bio_err, "problems making Certificate Request\n"); + if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){ + BIO_printf(bio_err, "Error making certificate request\n"); goto end; } + /* Note that -x509 can take over -key and -subj option values. */ } - if (x509) { - EVP_PKEY *tmppkey; + if (gen_x509) { + EVP_PKEY *pub_key = X509_REQ_get0_pubkey(req); + EVP_PKEY *issuer_key = CAcert != NULL ? CAkey : pkey; X509V3_CTX ext_ctx; - if ((x509ss = X509_new()) == NULL) - goto end; + X509_NAME *issuer = CAcert != NULL ? X509_get_subject_name(CAcert) : + X509_REQ_get_subject_name(req); + X509_NAME *n_subj = fsubj != NULL ? fsubj : + X509_REQ_get_subject_name(req); - /* Set version to V3 */ - if ((extensions != NULL || addext_conf != NULL) - && !X509_set_version(x509ss, 2)) + if ((new_x509 = X509_new_ex(app_get0_libctx(), + app_get0_propq())) == NULL) goto end; + if (serial != NULL) { - if (!X509_set_serialNumber(x509ss, serial)) + if (!X509_set_serialNumber(new_x509, serial)) goto end; } else { - if (!rand_serial(NULL, X509_get_serialNumber(x509ss))) + if (!rand_serial(NULL, X509_get_serialNumber(new_x509))) goto end; } - if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) + if (!X509_set_issuer_name(new_x509, issuer)) goto end; - if (days == 0) { - /* set default days if it's not specified */ - days = 30; + if (days == UNSET_DAYS) { + days = DEFAULT_DAYS; } - if (!set_cert_times(x509ss, NULL, NULL, days)) + if (!set_cert_times(new_x509, NULL, NULL, days)) + goto end; + if (!X509_set_subject_name(new_x509, n_subj)) goto end; - if (!X509_set_subject_name - (x509ss, X509_REQ_get_subject_name(req))) + if (!pub_key || !X509_set_pubkey(new_x509, pub_key)) goto end; - tmppkey = X509_REQ_get0_pubkey(req); - if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey)) + if (ext_copy == EXT_COPY_UNSET) { + if (infile != NULL) + BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n"); + } else if (!copy_extensions(new_x509, req, ext_copy)) { + BIO_printf(bio_err, "Error copying extensions from request\n"); goto end; + } /* Set up V3 context struct */ - - X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); + X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509, + new_x509, NULL, NULL, X509V3_CTX_REPLACE); + /* prepare fallback for AKID, but only if issuer cert == new_x509 */ + if (CAcert == NULL) { + if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key)) + goto end; + ERR_set_mark(); + if (!X509_check_private_key(new_x509, issuer_key)) + BIO_printf(bio_err, + "Warning: Signature key and public key of cert do not match\n"); + ERR_pop_to_mark(); + } X509V3_set_nconf(&ext_ctx, req_conf); /* Add extensions */ - if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf, - &ext_ctx, extensions, - x509ss)) { - BIO_printf(bio_err, "Error Loading extension section %s\n", + if (extensions != NULL + && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions, + new_x509)) { + BIO_printf(bio_err, "Error adding x509 extensions from section %s\n", extensions); goto end; } if (addext_conf != NULL && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", - x509ss)) { - BIO_printf(bio_err, "Error Loading command line extensions\n"); + new_x509)) { + BIO_printf(bio_err, "Error adding extensions defined via -addext\n"); goto end; } /* If a pre-cert was requested, we need to add a poison extension */ if (precert) { - if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0) - != 1) { + if (X509_add1_ext_i2d(new_x509, NID_ct_precert_poison, + NULL, 1, 0) != 1) { BIO_printf(bio_err, "Error adding poison extension\n"); goto end; } } - i = do_X509_sign(x509ss, pkey, digest, sigopts); - if (!i) { - ERR_print_errors(bio_err); + i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx); + if (!i) goto end; - } } else { X509V3_CTX ext_ctx; /* Set up V3 context struct */ - X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); X509V3_set_nconf(&ext_ctx, req_conf); @@ -798,49 +886,39 @@ if (req_exts != NULL && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, req_exts, req)) { - BIO_printf(bio_err, "Error Loading extension section %s\n", + BIO_printf(bio_err, "Error adding request extensions from section %s\n", req_exts); goto end; } if (addext_conf != NULL && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", req)) { - BIO_printf(bio_err, "Error Loading command line extensions\n"); + BIO_printf(bio_err, "Error adding extensions defined via -addext\n"); goto end; } i = do_X509_REQ_sign(req, pkey, digest, sigopts); - if (!i) { - ERR_print_errors(bio_err); + if (!i) goto end; - } } } - if (subj && x509) { - BIO_printf(bio_err, "Cannot modify certificate subject\n"); - goto end; - } - - if (subj && !x509) { + if (subj != NULL && !newreq && !gen_x509) { if (verbose) { - BIO_printf(bio_err, "Modifying Request's Subject\n"); - print_name(bio_err, "old subject=", - X509_REQ_get_subject_name(req), get_nameopt()); + BIO_printf(out, "Modifying subject of certificate request\n"); + print_name(out, "Old subject=", X509_REQ_get_subject_name(req)); } - if (build_subject(req, subj, chtype, multirdn) == 0) { - BIO_printf(bio_err, "ERROR: cannot modify subject\n"); - ret = 1; + if (!X509_REQ_set_subject_name(req, fsubj)) { + BIO_printf(bio_err, "Error modifying subject of certificate request\n"); goto end; } if (verbose) { - print_name(bio_err, "new subject=", - X509_REQ_get_subject_name(req), get_nameopt()); + print_name(out, "New subject=", X509_REQ_get_subject_name(req)); } } - if (verify && !x509) { + if (verify) { EVP_PKEY *tpubkey = pkey; if (tpubkey == NULL) { @@ -849,16 +927,14 @@ goto end; } - i = X509_REQ_verify(req, tpubkey); + i = do_X509_REQ_verify(req, tpubkey, vfyopts); - if (i < 0) { + if (i < 0) goto end; - } else if (i == 0) { - BIO_printf(bio_err, "verify failure\n"); - ERR_print_errors(bio_err); - } else { /* if (i > 0) */ - BIO_printf(bio_err, "verify OK\n"); - } + if (i == 0) + BIO_printf(bio_err, "Certificate request self-signature verify failure\n"); + else /* i > 0 */ + BIO_printf(bio_err, "Certificate request self-signature verify OK\n"); } if (noout && !text && !modulus && !subject && !pubkey) { @@ -878,62 +954,58 @@ if (tpubkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); - ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(out, tpubkey); } if (text) { - if (x509) - ret = X509_print_ex(out, x509ss, get_nameopt(), reqflag); + if (gen_x509) + ret = X509_print_ex(out, new_x509, get_nameopt(), reqflag); else ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag); if (ret == 0) { - if (x509) - BIO_printf(bio_err, "Error printing certificate\n"); + if (gen_x509) + BIO_printf(bio_err, "Error printing certificate\n"); else - BIO_printf(bio_err, "Error printing certificate request\n"); - - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error printing certificate request\n"); goto end; } } if (subject) { - if (x509) - print_name(out, "subject=", X509_get_subject_name(x509ss), - get_nameopt()); - else - print_name(out, "subject=", X509_REQ_get_subject_name(req), - get_nameopt()); + print_name(out, "subject=", gen_x509 + ? X509_get_subject_name(new_x509) + : X509_REQ_get_subject_name(req)); } if (modulus) { EVP_PKEY *tpubkey; - if (x509) - tpubkey = X509_get0_pubkey(x509ss); + if (gen_x509) + tpubkey = X509_get0_pubkey(new_x509); else tpubkey = X509_REQ_get0_pubkey(req); if (tpubkey == NULL) { - fprintf(stdout, "Modulus=unavailable\n"); + fprintf(stdout, "Modulus is unavailable\n"); goto end; } fprintf(stdout, "Modulus="); -#ifndef OPENSSL_NO_RSA - if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) { - const BIGNUM *n; - RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL); + if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) { + BIGNUM *n = NULL; + + if (!EVP_PKEY_get_bn_param(tpubkey, "n", &n)) + goto end; BN_print(out, n); - } else -#endif + BN_free(n); + } else { fprintf(stdout, "Wrong Algorithm type"); + } fprintf(stdout, "\n"); } - if (!noout && !x509) { + if (!noout && !gen_x509) { if (outformat == FORMAT_ASN1) i = i2d_X509_REQ_bio(out, req); else if (newhdr) @@ -941,17 +1013,17 @@ else i = PEM_write_bio_X509_REQ(out, req); if (!i) { - BIO_printf(bio_err, "unable to write X509 request\n"); + BIO_printf(bio_err, "Unable to write certificate request\n"); goto end; } } - if (!noout && x509 && (x509ss != NULL)) { + if (!noout && gen_x509 && new_x509 != NULL) { if (outformat == FORMAT_ASN1) - i = i2d_X509_bio(out, x509ss); + i = i2d_X509_bio(out, new_x509); else - i = PEM_write_bio_X509(out, x509ss); + i = PEM_write_bio_X509(out, new_x509); if (!i) { - BIO_printf(bio_err, "unable to write X509 certificate\n"); + BIO_printf(bio_err, "Unable to write X509 certificate\n"); goto end; } } @@ -963,20 +1035,23 @@ NCONF_free(req_conf); NCONF_free(addext_conf); BIO_free(addext_bio); - BIO_free(in); BIO_free_all(out); EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(genctx); sk_OPENSSL_STRING_free(pkeyopts); sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(vfyopts); lh_OPENSSL_STRING_doall(addexts, exts_cleanup); lh_OPENSSL_STRING_free(addexts); #ifndef OPENSSL_NO_ENGINE - ENGINE_free(gen_eng); + release_engine(gen_eng); #endif OPENSSL_free(keyalgstr); X509_REQ_free(req); - X509_free(x509ss); + X509_NAME_free(fsubj); + X509_free(new_x509); + X509_free(CAcert); + EVP_PKEY_free(CAkey); ASN1_INTEGER_free(serial); release_engine(e); if (passin != nofree_passin) @@ -986,50 +1061,48 @@ return ret; } -static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, - int attribs, unsigned long chtype) +static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj, + int multirdn, int attribs, unsigned long chtype) { int ret = 0, i; char no_prompt = 0; - STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL; + STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL; char *tmp, *dn_sect, *attr_sect; - tmp = NCONF_get_string(req_conf, SECTION, PROMPT); + tmp = NCONF_get_string(req_conf, section, PROMPT); if (tmp == NULL) ERR_clear_error(); if ((tmp != NULL) && strcmp(tmp, "no") == 0) no_prompt = 1; - dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME); + dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME); if (dn_sect == NULL) { - BIO_printf(bio_err, "unable to find '%s' in config\n", - DISTINGUISHED_NAME); - goto err; - } - dn_sk = NCONF_get_section(req_conf, dn_sect); - if (dn_sk == NULL) { - BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect); - goto err; + ERR_clear_error(); + } else { + dn_sk = NCONF_get_section(req_conf, dn_sect); + if (dn_sk == NULL) { + BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect); + goto err; + } } - attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES); + attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES); if (attr_sect == NULL) { ERR_clear_error(); - attr_sk = NULL; } else { attr_sk = NCONF_get_section(req_conf, attr_sect); if (attr_sk == NULL) { - BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect); + BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect); goto err; } } - /* setup version number */ - if (!X509_REQ_set_version(req, 0L)) - goto err; /* version 1 */ + /* so far there is only version 1 */ + if (!X509_REQ_set_version(req, X509_REQ_VERSION_1)) + goto err; - if (subj) - i = build_subject(req, subj, chtype, multirdn); + if (fsubj != NULL) + i = X509_REQ_set_subject_name(req, fsubj); else if (no_prompt) i = auto_info(req, dn_sk, attr_sk, attribs, chtype); else @@ -1046,26 +1119,6 @@ return ret; } -/* - * subject is expected to be in the format /type0=value0/type1=value1/type2=... - * where characters may be escaped by \ - */ -static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype, - int multirdn) -{ - X509_NAME *n; - - if ((n = parse_name(subject, chtype, multirdn)) == NULL) - return 0; - - if (!X509_REQ_set_subject_name(req, n)) { - X509_NAME_free(n); - return 0; - } - X509_NAME_free(n); - return 1; -} - static int prompt_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, @@ -1079,8 +1132,7 @@ char *type, *value; const char *def; CONF_VALUE *v; - X509_NAME *subj; - subj = X509_REQ_get_subject_name(req); + X509_NAME *subj = X509_REQ_get_subject_name(req); if (!batch) { BIO_printf(bio_err, @@ -1100,7 +1152,7 @@ if (sk_CONF_VALUE_num(dn_sk)) { i = -1; start: - for ( ; ; ) { + for (;;) { i++; if (sk_CONF_VALUE_num(dn_sk) <= i) break; @@ -1152,7 +1204,6 @@ n_min = -1; } - if (!join(buf, sizeof(buf), v->name, "_max", "Name")) return 0; if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { @@ -1165,8 +1216,7 @@ return 0; } if (X509_NAME_entry_count(subj) == 0) { - BIO_printf(bio_err, - "error, no objects specified in config file\n"); + BIO_printf(bio_err, "Error: No objects specified in config file\n"); return 0; } @@ -1181,7 +1231,7 @@ i = -1; start2: - for ( ; ; ) { + for (;;) { i++; if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i)) break; @@ -1207,7 +1257,7 @@ value = NULL; } - if (!join(buf, sizeof(buf), type,"_min", "Name")) + if (!join(buf, sizeof(buf), type, "_min", "Name")) return 0; if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { ERR_clear_error(); @@ -1258,10 +1308,10 @@ */ for (p = v->name; *p; p++) { #ifndef CHARSET_EBCDIC - spec_char = ((*p == ':') || (*p == ',') || (*p == '.')); + spec_char = (*p == ':' || *p == ',' || *p == '.'); #else - spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[',']) - || (*p == os_toascii['.'])); + spec_char = (*p == os_toascii[':'] || *p == os_toascii[','] + || *p == os_toascii['.']); #endif if (spec_char) { p++; @@ -1289,7 +1339,7 @@ } if (!X509_NAME_entry_count(subj)) { - BIO_printf(bio_err, "error, no objects specified in config file\n"); + BIO_printf(bio_err, "Error: No objects specified in config file\n"); return 0; } if (attribs) { @@ -1339,19 +1389,15 @@ if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, (unsigned char *)buf, -1)) { BIO_printf(bio_err, "Error adding attribute\n"); - ERR_print_errors(bio_err); ret = 0; } return ret; } - -static int build_data(char *text, const char *def, - char *value, int n_min, int n_max, - char *buf, const int buf_size, - const char *desc1, const char *desc2 - ) +static int build_data(char *text, const char *def, char *value, + int n_min, int n_max, char *buf, const int buf_size, + const char *desc1, const char *desc2) { int i; start: @@ -1386,7 +1432,7 @@ i = strlen(buf); if (buf[i - 1] != '\n') { - BIO_printf(bio_err, "weird input :-(\n"); + BIO_printf(bio_err, "Missing newline at end of input\n"); return 0; } buf[--i] = '\0'; @@ -1403,16 +1449,14 @@ static int req_check_len(int len, int n_min, int n_max) { - if ((n_min > 0) && (len < n_min)) { + if (n_min > 0 && len < n_min) { BIO_printf(bio_err, - "string is too short, it needs to be at least %d bytes long\n", - n_min); + "String too short, must be at least %d bytes long\n", n_min); return 0; } - if ((n_max >= 0) && (len > n_max)) { + if (n_max >= 0 && len > n_max) { BIO_printf(bio_err, - "string is too long, it needs to be no more than %d bytes long\n", - n_max); + "String too long, must be at most %d bytes long\n", n_max); return 0; } return 1; @@ -1451,66 +1495,71 @@ } static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, - int *pkey_type, long *pkeylen, - char **palgnam, ENGINE *keygen_engine) + char **pkeytype, long *pkeylen, + ENGINE *keygen_engine) { EVP_PKEY_CTX *gctx = NULL; EVP_PKEY *param = NULL; long keylen = -1; BIO *pbio = NULL; + const char *keytype = NULL; + size_t keytypelen = 0; + int expect_paramfile = 0; const char *paramfile = NULL; + /* Treat the first part of gstr, and only that */ if (gstr == NULL) { - *pkey_type = EVP_PKEY_RSA; + /* + * Special case: when no string given, default to RSA and the + * key length given by |*pkeylen|. + */ + keytype = "RSA"; keylen = *pkeylen; } else if (gstr[0] >= '0' && gstr[0] <= '9') { - *pkey_type = EVP_PKEY_RSA; - keylen = atol(gstr); - *pkeylen = keylen; - } else if (strncmp(gstr, "param:", 6) == 0) { - paramfile = gstr + 6; + /* Special case: only keylength given from string, so default to RSA */ + keytype = "RSA"; + /* The second part treatment will do the rest */ } else { const char *p = strchr(gstr, ':'); int len; - ENGINE *tmpeng; - const EVP_PKEY_ASN1_METHOD *ameth; if (p != NULL) len = p - gstr; else len = strlen(gstr); - /* - * The lookup of a the string will cover all engines so keep a note - * of the implementation. - */ - ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len); - - if (ameth == NULL) { - BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr); - return NULL; - } - - EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth); -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(tmpeng); -#endif - if (*pkey_type == EVP_PKEY_RSA) { - if (p != NULL) { - keylen = atol(p + 1); - *pkeylen = keylen; - } else { - keylen = *pkeylen; + if (strncmp(gstr, "param", len) == 0) { + expect_paramfile = 1; + if (p == NULL) { + BIO_printf(bio_err, + "Parameter file requested but no path given: %s\n", + gstr); + return NULL; } - } else if (p != NULL) { - paramfile = p + 1; + } else { + keytype = gstr; + keytypelen = len; } + + if (p != NULL) + gstr = gstr + len + 1; + else + gstr = NULL; + } + + /* Treat the second part of gstr, if there is one */ + if (gstr != NULL) { + /* If the second part starts with a digit, we assume it's a size */ + if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9') + keylen = atol(gstr); + else + paramfile = gstr; } if (paramfile != NULL) { pbio = BIO_new_file(paramfile, "r"); if (pbio == NULL) { - BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile); + BIO_printf(bio_err, "Cannot open parameter file %s\n", paramfile); return NULL; } param = PEM_read_bio_Parameters(pbio, NULL); @@ -1532,62 +1581,83 @@ BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile); return NULL; } - if (*pkey_type == -1) { - *pkey_type = EVP_PKEY_id(param); - } else if (*pkey_type != EVP_PKEY_base_id(param)) { - BIO_printf(bio_err, "Key Type does not match parameters\n"); - EVP_PKEY_free(param); - return NULL; + if (keytype == NULL) { + keytype = EVP_PKEY_get0_type_name(param); + if (keytype == NULL) { + EVP_PKEY_free(param); + BIO_puts(bio_err, "Unable to determine key type\n"); + return NULL; + } } } - if (palgnam != NULL) { - const EVP_PKEY_ASN1_METHOD *ameth; - ENGINE *tmpeng; - const char *anam; + if (keytypelen > 0) + *pkeytype = OPENSSL_strndup(keytype, keytypelen); + else + *pkeytype = OPENSSL_strdup(keytype); - ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type); - if (ameth == NULL) { - BIO_puts(bio_err, "Internal error: can't find key algorithm\n"); - return NULL; - } - EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth); - *palgnam = OPENSSL_strdup(anam); -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(tmpeng); -#endif + if (*pkeytype == NULL) { + BIO_printf(bio_err, "Out of memory\n"); + EVP_PKEY_free(param); + return NULL; } + if (keylen >= 0) + *pkeylen = keylen; + if (param != NULL) { - gctx = EVP_PKEY_CTX_new(param, keygen_engine); - *pkeylen = EVP_PKEY_bits(param); + if (!EVP_PKEY_is_a(param, *pkeytype)) { + BIO_printf(bio_err, "Key type does not match parameters\n"); + EVP_PKEY_free(param); + return NULL; + } + + if (keygen_engine != NULL) + gctx = EVP_PKEY_CTX_new(param, keygen_engine); + else + gctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), + param, app_get0_propq()); + *pkeylen = EVP_PKEY_get_bits(param); EVP_PKEY_free(param); } else { - gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine); + if (keygen_engine != NULL) { + int pkey_id = get_legacy_pkey_id(app_get0_libctx(), *pkeytype, + keygen_engine); + + if (pkey_id != NID_undef) + gctx = EVP_PKEY_CTX_new_id(pkey_id, keygen_engine); + } else { + gctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), + *pkeytype, app_get0_propq()); + } } if (gctx == NULL) { BIO_puts(bio_err, "Error allocating keygen context\n"); - ERR_print_errors(bio_err); return NULL; } if (EVP_PKEY_keygen_init(gctx) <= 0) { BIO_puts(bio_err, "Error initializing keygen context\n"); - ERR_print_errors(bio_err); EVP_PKEY_CTX_free(gctx); return NULL; } -#ifndef OPENSSL_NO_RSA - if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) { - if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) { - BIO_puts(bio_err, "Error setting RSA keysize\n"); - ERR_print_errors(bio_err); + if (keylen == -1 && (EVP_PKEY_CTX_is_a(gctx, "RSA") + || EVP_PKEY_CTX_is_a(gctx, "RSA-PSS"))) + keylen = *pkeylen; + + if (keylen != -1) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t bits = keylen; + + params[0] = + OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &bits); + if (EVP_PKEY_CTX_set_params(gctx, params) <= 0) { + BIO_puts(bio_err, "Error setting keysize\n"); EVP_PKEY_CTX_free(gctx); return NULL; } } -#endif return gctx; } @@ -1610,70 +1680,3 @@ (void)BIO_flush(b); return 1; } - -static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, - const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) -{ - EVP_PKEY_CTX *pkctx = NULL; - int i, def_nid; - - if (ctx == NULL) - return 0; - /* - * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory - * for this algorithm. - */ - if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2 - && def_nid == NID_undef) { - /* The signing algorithm requires there to be no digest */ - md = NULL; - } - if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) - return 0; - for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { - char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); - if (pkey_ctrl_string(pkctx, sigopt) <= 0) { - BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); - ERR_print_errors(bio_err); - return 0; - } - } - return 1; -} - -int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, - STACK_OF(OPENSSL_STRING) *sigopts) -{ - int rv; - EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - - rv = do_sign_init(mctx, pkey, md, sigopts); - if (rv > 0) - rv = X509_sign_ctx(x, mctx); - EVP_MD_CTX_free(mctx); - return rv > 0 ? 1 : 0; -} - -int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, - STACK_OF(OPENSSL_STRING) *sigopts) -{ - int rv; - EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - rv = do_sign_init(mctx, pkey, md, sigopts); - if (rv > 0) - rv = X509_REQ_sign_ctx(x, mctx); - EVP_MD_CTX_free(mctx); - return rv > 0 ? 1 : 0; -} - -int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, - STACK_OF(OPENSSL_STRING) *sigopts) -{ - int rv; - EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - rv = do_sign_init(mctx, pkey, md, sigopts); - if (rv > 0) - rv = X509_CRL_sign_ctx(x, mctx); - EVP_MD_CTX_free(mctx); - return rv > 0 ? 1 : 0; -} diff --git a/apps/rsa.c b/apps/rsa.c --- a/apps/rsa.c +++ b/apps/rsa.c @@ -1,13 +1,17 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* Necessary for legacy RSA public key export */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include + #include #include #include @@ -21,60 +25,119 @@ #include #include #include +#include + +/* + * This include is to get OSSL_KEYMGMT_SELECT_*, which feels a bit + * much just for those macros... they might serve better as EVP macros. + */ +#include + +#ifndef OPENSSL_NO_RC4 +# define DEFAULT_PVK_ENCR_STRENGTH 2 +#else +# define DEFAULT_PVK_ENCR_STRENGTH 0 +#endif typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN, OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT, /* Do not change the order here; see case statements below */ OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG, - OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER + OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER, + OPT_PROV_ENUM, OPT_TRADITIONAL } OPTION_CHOICE; const OPTIONS rsa_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"}, - {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"}, + {"check", OPT_CHECK, '-', "Verify key consistency"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), {"in", OPT_IN, 's', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, + {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"}, {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, - {"pubout", OPT_PUBOUT, '-', "Output a public key"}, - {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"}, + {"pubout", OPT_PUBOUT, '-', "Output a public key"}, {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"}, + {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, {"noout", OPT_NOOUT, '-', "Don't print key out"}, {"text", OPT_TEXT, '-', "Print the key in text"}, {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, - {"check", OPT_CHECK, '-', "Verify key consistency"}, - {"", OPT_CIPHER, '-', "Any supported cipher"}, -#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + {"traditional", OPT_TRADITIONAL, '-', + "Use traditional format for private keys"}, + +#ifndef OPENSSL_NO_RC4 + OPT_SECTION("PVK"), {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"}, {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"}, {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"}, #endif -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + + OPT_PROV_OPTIONS, {NULL} }; +static int try_legacy_encoding(EVP_PKEY *pkey, int outformat, int pubout, + BIO *out) +{ + int ret = 0; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + const RSA *rsa = EVP_PKEY_get0_RSA(pkey); + + if (rsa == NULL) + return 0; + + if (outformat == FORMAT_ASN1) { + if (pubout == 2) + ret = i2d_RSAPublicKey_bio(out, rsa) > 0; + else + ret = i2d_RSA_PUBKEY_bio(out, rsa) > 0; + } else if (outformat == FORMAT_PEM) { + if (pubout == 2) + ret = PEM_write_bio_RSAPublicKey(out, rsa) > 0; + else + ret = PEM_write_bio_RSA_PUBKEY(out, rsa) > 0; +# ifndef OPENSSL_NO_DSA + } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { + ret = i2b_PublicKey_bio(out, pkey) > 0; +# endif + } +#endif + + return ret; +} + int rsa_main(int argc, char **argv) { ENGINE *e = NULL; BIO *out = NULL; - RSA *rsa = NULL; - const EVP_CIPHER *enc = NULL; - char *infile = NULL, *outfile = NULL, *prog; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx; + EVP_CIPHER *enc = NULL; + char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog; char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL; - int i, private = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0; + int private = 0; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, check = 0; int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1; -#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) - int pvk_encr = 2; -#endif + int pvk_encr = DEFAULT_PVK_ENCR_STRENGTH; OPTION_CHOICE o; + int traditional = 0; + const char *output_type = NULL; + const char *output_structure = NULL; + int selection = 0; + OSSL_ENCODER_CTX *ectx = NULL; prog = opt_init(argc, argv, rsa_options); while ((o = opt_next()) != OPT_EOF) { @@ -126,9 +189,7 @@ case OPT_PVK_STRONG: /* pvk_encr:= 2 */ case OPT_PVK_WEAK: /* pvk_encr:= 1 */ case OPT_PVK_NONE: /* pvk_encr:= 0 */ -#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) pvk_encr = (o - OPT_PVK_NONE); -#endif break; case OPT_NOOUT: noout = 1; @@ -143,15 +204,27 @@ check = 1; break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &enc)) - goto opthelp; + ciphername = opt_unknown(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; + case OPT_TRADITIONAL: + traditional = 1; break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (ciphername != NULL) { + if (!opt_cipher(ciphername, &enc)) + goto opthelp; + } private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { @@ -163,34 +236,31 @@ goto end; } - { - EVP_PKEY *pkey; + if (pubin) { + int tmpformat = FORMAT_UNDEF; - if (pubin) { - int tmpformat = -1; - if (pubin == 2) { - if (informat == FORMAT_PEM) - tmpformat = FORMAT_PEMRSA; - else if (informat == FORMAT_ASN1) - tmpformat = FORMAT_ASN1RSA; - } else { - tmpformat = informat; - } - - pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key"); + if (pubin == 2) { + if (informat == FORMAT_PEM) + tmpformat = FORMAT_PEMRSA; + else if (informat == FORMAT_ASN1) + tmpformat = FORMAT_ASN1RSA; } else { - pkey = load_key(infile, informat, 1, passin, e, "Private Key"); + tmpformat = informat; } - if (pkey != NULL) - rsa = EVP_PKEY_get1_RSA(pkey); - EVP_PKEY_free(pkey); + pkey = load_pubkey(infile, tmpformat, 1, passin, e, "public key"); + } else { + pkey = load_key(infile, informat, 1, passin, e, "private key"); } - if (rsa == NULL) { + if (pkey == NULL) { ERR_print_errors(bio_err); goto end; } + if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) { + BIO_printf(bio_err, "Not an RSA key\n"); + goto end; + } out = bio_open_owner(outfile, outformat, private); if (out == NULL) @@ -198,7 +268,8 @@ if (text) { assert(pubin || private); - if (!RSA_print(out, rsa, 0)) { + if ((pubin && EVP_PKEY_print_public(out, pkey, 0, NULL) <= 0) + || (!pubin && EVP_PKEY_print_private(out, pkey, 0, NULL) <= 0)) { perror(outfile); ERR_print_errors(bio_err); goto end; @@ -206,30 +277,34 @@ } if (modulus) { - const BIGNUM *n; - RSA_get0_key(rsa, &n, NULL, NULL); + BIGNUM *n = NULL; + + /* Every RSA key has an 'n' */ + EVP_PKEY_get_bn_param(pkey, "n", &n); BIO_printf(out, "Modulus="); BN_print(out, n); BIO_printf(out, "\n"); + BN_free(n); } if (check) { - int r = RSA_check_key_ex(rsa, NULL); + int r; + + pctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (pctx == NULL) { + BIO_printf(bio_err, "RSA unable to create PKEY context\n"); + ERR_print_errors(bio_err); + goto end; + } + r = EVP_PKEY_check(pctx); + EVP_PKEY_CTX_free(pctx); if (r == 1) { BIO_printf(out, "RSA key ok\n"); } else if (r == 0) { - unsigned long err; - - while ((err = ERR_peek_error()) != 0 && - ERR_GET_LIB(err) == ERR_LIB_RSA && - ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX && - ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) { - BIO_printf(out, "RSA key error: %s\n", - ERR_reason_error_string(err)); - ERR_get_error(); /* remove err from error stack */ - } - } else if (r == -1) { + BIO_printf(bio_err, "RSA key not ok\n"); + ERR_print_errors(bio_err); + } else if (r < 0) { ERR_print_errors(bio_err); goto end; } @@ -240,71 +315,100 @@ goto end; } BIO_printf(bio_err, "writing RSA key\n"); + + /* Choose output type for the format */ if (outformat == FORMAT_ASN1) { - if (pubout || pubin) { - if (pubout == 2) - i = i2d_RSAPublicKey_bio(out, rsa); - else - i = i2d_RSA_PUBKEY_bio(out, rsa); - } else { - assert(private); - i = i2d_RSAPrivateKey_bio(out, rsa); - } + output_type = "DER"; } else if (outformat == FORMAT_PEM) { + output_type = "PEM"; + } else if (outformat == FORMAT_MSBLOB) { + output_type = "MSBLOB"; + } else if (outformat == FORMAT_PVK) { + if (pubin) { + BIO_printf(bio_err, "PVK form impossible with public key input\n"); + goto end; + } + output_type = "PVK"; + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + + /* Select what you want in the output */ + if (pubout || pubin) { + selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + } else { + assert(private); + selection = (OSSL_KEYMGMT_SELECT_KEYPAIR + | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + } + + /* For DER based output, select the desired output structure */ + if (outformat == FORMAT_ASN1 || outformat == FORMAT_PEM) { if (pubout || pubin) { if (pubout == 2) - i = PEM_write_bio_RSAPublicKey(out, rsa); + output_structure = "pkcs1"; /* "type-specific" would work too */ else - i = PEM_write_bio_RSA_PUBKEY(out, rsa); + output_structure = "SubjectPublicKeyInfo"; } else { assert(private); - i = PEM_write_bio_RSAPrivateKey(out, rsa, - enc, NULL, 0, NULL, passout); + if (traditional) + output_structure = "pkcs1"; /* "type-specific" would work too */ + else + output_structure = "PrivateKeyInfo"; } -#ifndef OPENSSL_NO_DSA - } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) { - EVP_PKEY *pk; - pk = EVP_PKEY_new(); - if (pk == NULL) - goto end; + } - EVP_PKEY_set1_RSA(pk, rsa); - if (outformat == FORMAT_PVK) { - if (pubin) { - BIO_printf(bio_err, "PVK form impossible with public key input\n"); - EVP_PKEY_free(pk); - goto end; - } - assert(private); -# ifdef OPENSSL_NO_RC4 - BIO_printf(bio_err, "PVK format not supported\n"); - EVP_PKEY_free(pk); + /* Now, perform the encoding */ + ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, + output_type, output_structure, + NULL); + if (OSSL_ENCODER_CTX_get_num_encoders(ectx) == 0) { + if ((!pubout && !pubin) + || !try_legacy_encoding(pkey, outformat, pubout, out)) + BIO_printf(bio_err, "%s format not supported\n", output_type); + else + ret = 0; + goto end; + } + + /* Passphrase setup */ + if (enc != NULL) + OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL); + + /* Default passphrase prompter */ + if (enc != NULL || outformat == FORMAT_PVK) { + OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL); + if (passout != NULL) + /* When passout given, override the passphrase prompter */ + OSSL_ENCODER_CTX_set_passphrase(ectx, + (const unsigned char *)passout, + strlen(passout)); + } + + /* PVK is a bit special... */ + if (outformat == FORMAT_PVK) { + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = OSSL_PARAM_construct_int("encrypt-level", &pvk_encr); + if (!OSSL_ENCODER_CTX_set_params(ectx, params)) { + BIO_printf(bio_err, "invalid PVK encryption level\n"); goto end; -# else - i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout); -# endif - } else if (pubin || pubout) { - i = i2b_PublicKey_bio(out, pk); - } else { - assert(private); - i = i2b_PrivateKey_bio(out, pk); } - EVP_PKEY_free(pk); -#endif - } else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); - goto end; } - if (i <= 0) { + + if (!OSSL_ENCODER_to_bio(ectx, out)) { BIO_printf(bio_err, "unable to write key\n"); ERR_print_errors(bio_err); - } else { - ret = 0; + goto end; } + ret = 0; end: + OSSL_ENCODER_CTX_free(ectx); release_engine(e); BIO_free_all(out); - RSA_free(rsa); + EVP_PKEY_free(pkey); + EVP_CIPHER_free(enc); OPENSSL_free(passin); OPENSSL_free(passout); return ret; diff --git a/apps/rsautl.c b/apps/rsautl.c --- a/apps/rsautl.c +++ b/apps/rsautl.c @@ -1,13 +1,14 @@ /* - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include + #include "apps.h" #include "progs.h" #include @@ -25,40 +26,46 @@ #define KEY_CERT 3 typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP, - OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931, + OPT_RSA_RAW, OPT_OAEP, OPT_PKCS, OPT_X931, OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM, - OPT_R_ENUM + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS rsautl_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"sign", OPT_SIGN, '-', "Sign with private key"}, + {"verify", OPT_VERIFY, '-', "Verify with public key"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, {"inkey", OPT_INKEY, 's', "Input key"}, - {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, + {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"}, {"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, - {"ssl", OPT_SSL, '-', "Use SSL v2 padding"}, - {"raw", OPT_RAW, '-', "Use no padding"}, + {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"raw", OPT_RSA_RAW, '-', "Use no padding"}, {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"}, + {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"}, {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"}, - {"sign", OPT_SIGN, '-', "Sign with private key"}, - {"verify", OPT_VERIFY, '-', "Verify with public key"}, {"asn1parse", OPT_ASN1PARSE, '-', "Run output through asn1parse; useful with -verify"}, {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, - {"x931", OPT_X931, '-', "Use ANSI X9.31 padding"}, - {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, - {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"}, - {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + OPT_PROV_OPTIONS, {NULL} }; @@ -67,14 +74,15 @@ BIO *in = NULL, *out = NULL; ENGINE *e = NULL; EVP_PKEY *pkey = NULL; - RSA *rsa = NULL; + EVP_PKEY_CTX *ctx = NULL; X509 *x; char *infile = NULL, *outfile = NULL, *keyfile = NULL; char *passinarg = NULL, *passin = NULL, *prog; char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; unsigned char *rsa_in = NULL, *rsa_out = NULL, pad = RSA_PKCS1_PADDING; - int rsa_inlen, keyformat = FORMAT_PEM, keysize, ret = 1; - int rsa_outlen = 0, hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0; + size_t rsa_inlen, rsa_outlen = 0; + int keyformat = FORMAT_UNDEF, keysize, ret = 1, rv; + int hexdump = 0, asn1parse = 0, need_priv = 0, rev = 0; OPTION_CHOICE o; prog = opt_init(argc, argv, rsautl_options); @@ -90,7 +98,7 @@ ret = 0; goto end; case OPT_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) goto opthelp; break; case OPT_IN: @@ -108,15 +116,12 @@ case OPT_HEXDUMP: hexdump = 1; break; - case OPT_RAW: + case OPT_RSA_RAW: pad = RSA_NO_PADDING; break; case OPT_OAEP: pad = RSA_PKCS1_OAEP_PADDING; break; - case OPT_SSL: - pad = RSA_SSLV23_PADDING; - break; case OPT_PKCS: pad = RSA_PKCS1_PADDING; break; @@ -156,12 +161,21 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; + if (!app_RAND_load()) + goto end; + if (need_priv && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; @@ -174,15 +188,15 @@ switch (key_type) { case KEY_PRIVKEY: - pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key"); + pkey = load_key(keyfile, keyformat, 0, passin, e, "private key"); break; case KEY_PUBKEY: - pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "Public Key"); + pkey = load_pubkey(keyfile, keyformat, 0, NULL, e, "public key"); break; case KEY_CERT: - x = load_cert(keyfile, keyformat, "Certificate"); + x = load_cert(keyfile, FORMAT_UNDEF, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); @@ -193,15 +207,6 @@ if (pkey == NULL) return 1; - rsa = EVP_PKEY_get1_RSA(pkey); - EVP_PKEY_free(pkey); - - if (rsa == NULL) { - BIO_printf(bio_err, "Error getting RSA key\n"); - ERR_print_errors(bio_err); - goto end; - } - in = bio_open_default(infile, 'r', FORMAT_BINARY); if (in == NULL) goto end; @@ -209,48 +214,58 @@ if (out == NULL) goto end; - keysize = RSA_size(rsa); + keysize = EVP_PKEY_get_size(pkey); rsa_in = app_malloc(keysize * 2, "hold rsa key"); rsa_out = app_malloc(keysize, "output rsa key"); + rsa_outlen = keysize; /* Read the input data */ - rsa_inlen = BIO_read(in, rsa_in, keysize * 2); - if (rsa_inlen < 0) { + rv = BIO_read(in, rsa_in, keysize * 2); + if (rv < 0) { BIO_printf(bio_err, "Error reading input Data\n"); goto end; } + rsa_inlen = rv; if (rev) { - int i; + size_t i; unsigned char ctmp; + for (i = 0; i < rsa_inlen / 2; i++) { ctmp = rsa_in[i]; rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; rsa_in[rsa_inlen - 1 - i] = ctmp; } } - switch (rsa_mode) { + if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) + goto end; + + switch (rsa_mode) { case RSA_VERIFY: - rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + rv = EVP_PKEY_verify_recover_init(ctx) > 0 + && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 + && EVP_PKEY_verify_recover(ctx, rsa_out, &rsa_outlen, + rsa_in, rsa_inlen) > 0; break; - case RSA_SIGN: - rsa_outlen = - RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + rv = EVP_PKEY_sign_init(ctx) > 0 + && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 + && EVP_PKEY_sign(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0; break; - case RSA_ENCRYPT: - rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + rv = EVP_PKEY_encrypt_init(ctx) > 0 + && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 + && EVP_PKEY_encrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0; break; - case RSA_DECRYPT: - rsa_outlen = - RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); + rv = EVP_PKEY_decrypt_init(ctx) > 0 + && EVP_PKEY_CTX_set_rsa_padding(ctx, pad) > 0 + && EVP_PKEY_decrypt(ctx, rsa_out, &rsa_outlen, rsa_in, rsa_inlen) > 0; break; } - if (rsa_outlen < 0) { + if (!rv) { BIO_printf(bio_err, "RSA operation error\n"); ERR_print_errors(bio_err); goto end; @@ -266,7 +281,8 @@ BIO_write(out, rsa_out, rsa_outlen); } end: - RSA_free(rsa); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); release_engine(e); BIO_free(in); BIO_free_all(out); diff --git a/apps/s_apps.h b/apps/s_apps.h deleted file mode 100644 --- a/apps/s_apps.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include - -#include - -#define PORT "4433" -#define PROTOCOL "tcp" - -typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context); -int do_server(int *accept_sock, const char *host, const char *port, - int family, int type, int protocol, do_server_cb cb, - unsigned char *context, int naccept, BIO *bio_s_out); - -int verify_callback(int ok, X509_STORE_CTX *ctx); - -int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); -int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, - STACK_OF(X509) *chain, int build_chain); -int ssl_print_sigalgs(BIO *out, SSL *s); -int ssl_print_point_formats(BIO *out, SSL *s); -int ssl_print_groups(BIO *out, SSL *s, int noshared); -int ssl_print_tmp_key(BIO *out, SSL *s); -int init_client(int *sock, const char *host, const char *port, - const char *bindhost, const char *bindport, - int family, int type, int protocol); -int should_retry(int i); - -long bio_dump_callback(BIO *bio, int cmd, const char *argp, - int argi, long argl, long ret); - -void apps_ssl_info_callback(const SSL *s, int where, int ret); -void msg_cb(int write_p, int version, int content_type, const void *buf, - size_t len, SSL *ssl, void *arg); -void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data, - int len, void *arg); - -int generate_cookie_callback(SSL *ssl, unsigned char *cookie, - unsigned int *cookie_len); -int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, - unsigned int cookie_len); - -#ifdef __VMS /* 31 char symbol name limit */ -# define generate_stateless_cookie_callback generate_stateless_cookie_cb -# define verify_stateless_cookie_callback verify_stateless_cookie_cb -#endif - -int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, - size_t *cookie_len); -int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, - size_t cookie_len); - -typedef struct ssl_excert_st SSL_EXCERT; - -void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc); -void ssl_excert_free(SSL_EXCERT *exc); -int args_excert(int option, SSL_EXCERT **pexc); -int load_excert(SSL_EXCERT **pexc); -void print_verify_detail(SSL *s, BIO *bio); -void print_ssl_summary(SSL *s); -int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx); -int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, - int crl_download); -int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath, - const char *vfyCAfile, const char *chCApath, - const char *chCAfile, STACK_OF(X509_CRL) *crls, - int crl_download); -void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose); -int set_keylog_file(SSL_CTX *ctx, const char *keylog_file); -void print_ca_names(BIO *bio, SSL *s); diff --git a/apps/s_cb.c b/apps/s_cb.c deleted file mode 100644 --- a/apps/s_cb.c +++ /dev/null @@ -1,1548 +0,0 @@ -/* - * Copyright 1995-2022 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 - */ - -/* callback functions used by s_client, s_server, and s_time */ -#include -#include -#include /* for memcpy() and strcmp() */ -#include "apps.h" -#include -#include -#include -#include -#include -#ifndef OPENSSL_NO_DH -# include -#endif -#include "s_apps.h" - -#define COOKIE_SECRET_LENGTH 16 - -VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 }; - -#ifndef OPENSSL_NO_SOCK -static unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; -static int cookie_initialized = 0; -#endif -static BIO *bio_keylog = NULL; - -static const char *lookup(int val, const STRINT_PAIR* list, const char* def) -{ - for ( ; list->name; ++list) - if (list->retval == val) - return list->name; - return def; -} - -int verify_callback(int ok, X509_STORE_CTX *ctx) -{ - X509 *err_cert; - int err, depth; - - err_cert = X509_STORE_CTX_get_current_cert(ctx); - err = X509_STORE_CTX_get_error(ctx); - depth = X509_STORE_CTX_get_error_depth(ctx); - - if (!verify_args.quiet || !ok) { - BIO_printf(bio_err, "depth=%d ", depth); - if (err_cert != NULL) { - X509_NAME_print_ex(bio_err, - X509_get_subject_name(err_cert), - 0, get_nameopt()); - BIO_puts(bio_err, "\n"); - } else { - BIO_puts(bio_err, "\n"); - } - } - if (!ok) { - BIO_printf(bio_err, "verify error:num=%d:%s\n", err, - X509_verify_cert_error_string(err)); - if (verify_args.depth < 0 || verify_args.depth >= depth) { - if (!verify_args.return_error) - ok = 1; - verify_args.error = err; - } else { - ok = 0; - verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG; - } - } - switch (err) { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - if (err_cert != NULL) { - BIO_puts(bio_err, "issuer= "); - X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), - 0, get_nameopt()); - BIO_puts(bio_err, "\n"); - } - break; - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - if (err_cert != NULL) { - BIO_printf(bio_err, "notBefore="); - ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert)); - BIO_printf(bio_err, "\n"); - } - break; - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - if (err_cert != NULL) { - BIO_printf(bio_err, "notAfter="); - ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert)); - BIO_printf(bio_err, "\n"); - } - break; - case X509_V_ERR_NO_EXPLICIT_POLICY: - if (!verify_args.quiet) - policies_print(ctx); - break; - } - if (err == X509_V_OK && ok == 2 && !verify_args.quiet) - policies_print(ctx); - if (ok && !verify_args.quiet) - BIO_printf(bio_err, "verify return:%d\n", ok); - return ok; -} - -int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) -{ - if (cert_file != NULL) { - if (SSL_CTX_use_certificate_file(ctx, cert_file, - SSL_FILETYPE_PEM) <= 0) { - BIO_printf(bio_err, "unable to get certificate from '%s'\n", - cert_file); - ERR_print_errors(bio_err); - return 0; - } - if (key_file == NULL) - key_file = cert_file; - if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { - BIO_printf(bio_err, "unable to get private key from '%s'\n", - key_file); - ERR_print_errors(bio_err); - return 0; - } - - /* - * If we are using DSA, we can copy the parameters from the private - * key - */ - - /* - * Now we know that a key and cert have been set against the SSL - * context - */ - if (!SSL_CTX_check_private_key(ctx)) { - BIO_printf(bio_err, - "Private key does not match the certificate public key\n"); - return 0; - } - } - return 1; -} - -int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, - STACK_OF(X509) *chain, int build_chain) -{ - int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0; - if (cert == NULL) - return 1; - if (SSL_CTX_use_certificate(ctx, cert) <= 0) { - BIO_printf(bio_err, "error setting certificate\n"); - ERR_print_errors(bio_err); - return 0; - } - - if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) { - BIO_printf(bio_err, "error setting private key\n"); - ERR_print_errors(bio_err); - return 0; - } - - /* - * Now we know that a key and cert have been set against the SSL context - */ - if (!SSL_CTX_check_private_key(ctx)) { - BIO_printf(bio_err, - "Private key does not match the certificate public key\n"); - return 0; - } - if (chain && !SSL_CTX_set1_chain(ctx, chain)) { - BIO_printf(bio_err, "error setting certificate chain\n"); - ERR_print_errors(bio_err); - return 0; - } - if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) { - BIO_printf(bio_err, "error building certificate chain\n"); - ERR_print_errors(bio_err); - return 0; - } - return 1; -} - -static STRINT_PAIR cert_type_list[] = { - {"RSA sign", TLS_CT_RSA_SIGN}, - {"DSA sign", TLS_CT_DSS_SIGN}, - {"RSA fixed DH", TLS_CT_RSA_FIXED_DH}, - {"DSS fixed DH", TLS_CT_DSS_FIXED_DH}, - {"ECDSA sign", TLS_CT_ECDSA_SIGN}, - {"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH}, - {"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH}, - {"GOST01 Sign", TLS_CT_GOST01_SIGN}, - {"GOST12 Sign", TLS_CT_GOST12_SIGN}, - {NULL} -}; - -static void ssl_print_client_cert_types(BIO *bio, SSL *s) -{ - const unsigned char *p; - int i; - int cert_type_num = SSL_get0_certificate_types(s, &p); - if (!cert_type_num) - return; - BIO_puts(bio, "Client Certificate Types: "); - for (i = 0; i < cert_type_num; i++) { - unsigned char cert_type = p[i]; - const char *cname = lookup((int)cert_type, cert_type_list, NULL); - - if (i) - BIO_puts(bio, ", "); - if (cname != NULL) - BIO_puts(bio, cname); - else - BIO_printf(bio, "UNKNOWN (%d),", cert_type); - } - BIO_puts(bio, "\n"); -} - -static const char *get_sigtype(int nid) -{ - switch (nid) { - case EVP_PKEY_RSA: - return "RSA"; - - case EVP_PKEY_RSA_PSS: - return "RSA-PSS"; - - case EVP_PKEY_DSA: - return "DSA"; - - case EVP_PKEY_EC: - return "ECDSA"; - - case NID_ED25519: - return "Ed25519"; - - case NID_ED448: - return "Ed448"; - - case NID_id_GostR3410_2001: - return "gost2001"; - - case NID_id_GostR3410_2012_256: - return "gost2012_256"; - - case NID_id_GostR3410_2012_512: - return "gost2012_512"; - - default: - return NULL; - } -} - -static int do_print_sigalgs(BIO *out, SSL *s, int shared) -{ - int i, nsig, client; - client = SSL_is_server(s) ? 0 : 1; - if (shared) - nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL); - else - nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL); - if (nsig == 0) - return 1; - - if (shared) - BIO_puts(out, "Shared "); - - if (client) - BIO_puts(out, "Requested "); - BIO_puts(out, "Signature Algorithms: "); - for (i = 0; i < nsig; i++) { - int hash_nid, sign_nid; - unsigned char rhash, rsign; - const char *sstr = NULL; - if (shared) - SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL, - &rsign, &rhash); - else - SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash); - if (i) - BIO_puts(out, ":"); - sstr = get_sigtype(sign_nid); - if (sstr) - BIO_printf(out, "%s", sstr); - else - BIO_printf(out, "0x%02X", (int)rsign); - if (hash_nid != NID_undef) - BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid)); - else if (sstr == NULL) - BIO_printf(out, "+0x%02X", (int)rhash); - } - BIO_puts(out, "\n"); - return 1; -} - -int ssl_print_sigalgs(BIO *out, SSL *s) -{ - int nid; - if (!SSL_is_server(s)) - ssl_print_client_cert_types(out, s); - do_print_sigalgs(out, s, 0); - do_print_sigalgs(out, s, 1); - if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef) - BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid)); - if (SSL_get_peer_signature_type_nid(s, &nid)) - BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid)); - return 1; -} - -#ifndef OPENSSL_NO_EC -int ssl_print_point_formats(BIO *out, SSL *s) -{ - int i, nformats; - const char *pformats; - nformats = SSL_get0_ec_point_formats(s, &pformats); - if (nformats <= 0) - return 1; - BIO_puts(out, "Supported Elliptic Curve Point Formats: "); - for (i = 0; i < nformats; i++, pformats++) { - if (i) - BIO_puts(out, ":"); - switch (*pformats) { - case TLSEXT_ECPOINTFORMAT_uncompressed: - BIO_puts(out, "uncompressed"); - break; - - case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime: - BIO_puts(out, "ansiX962_compressed_prime"); - break; - - case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2: - BIO_puts(out, "ansiX962_compressed_char2"); - break; - - default: - BIO_printf(out, "unknown(%d)", (int)*pformats); - break; - - } - } - BIO_puts(out, "\n"); - return 1; -} - -int ssl_print_groups(BIO *out, SSL *s, int noshared) -{ - int i, ngroups, *groups, nid; - const char *gname; - - ngroups = SSL_get1_groups(s, NULL); - if (ngroups <= 0) - return 1; - groups = app_malloc(ngroups * sizeof(int), "groups to print"); - SSL_get1_groups(s, groups); - - BIO_puts(out, "Supported Elliptic Groups: "); - for (i = 0; i < ngroups; i++) { - if (i) - BIO_puts(out, ":"); - nid = groups[i]; - /* If unrecognised print out hex version */ - if (nid & TLSEXT_nid_unknown) { - BIO_printf(out, "0x%04X", nid & 0xFFFF); - } else { - /* TODO(TLS1.3): Get group name here */ - /* Use NIST name for curve if it exists */ - gname = EC_curve_nid2nist(nid); - if (gname == NULL) - gname = OBJ_nid2sn(nid); - BIO_printf(out, "%s", gname); - } - } - OPENSSL_free(groups); - if (noshared) { - BIO_puts(out, "\n"); - return 1; - } - BIO_puts(out, "\nShared Elliptic groups: "); - ngroups = SSL_get_shared_group(s, -1); - for (i = 0; i < ngroups; i++) { - if (i) - BIO_puts(out, ":"); - nid = SSL_get_shared_group(s, i); - /* TODO(TLS1.3): Convert for DH groups */ - gname = EC_curve_nid2nist(nid); - if (gname == NULL) - gname = OBJ_nid2sn(nid); - BIO_printf(out, "%s", gname); - } - if (ngroups == 0) - BIO_puts(out, "NONE"); - BIO_puts(out, "\n"); - return 1; -} -#endif - -int ssl_print_tmp_key(BIO *out, SSL *s) -{ - EVP_PKEY *key; - - if (!SSL_get_peer_tmp_key(s, &key)) - return 1; - BIO_puts(out, "Server Temp Key: "); - switch (EVP_PKEY_id(key)) { - case EVP_PKEY_RSA: - BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key)); - break; - - case EVP_PKEY_DH: - BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key)); - break; -#ifndef OPENSSL_NO_EC - case EVP_PKEY_EC: - { - EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); - int nid; - const char *cname; - nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); - EC_KEY_free(ec); - cname = EC_curve_nid2nist(nid); - if (cname == NULL) - cname = OBJ_nid2sn(nid); - BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key)); - } - break; -#endif - default: - BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)), - EVP_PKEY_bits(key)); - } - EVP_PKEY_free(key); - return 1; -} - -long bio_dump_callback(BIO *bio, int cmd, const char *argp, - int argi, long argl, long ret) -{ - BIO *out; - - out = (BIO *)BIO_get_callback_arg(bio); - if (out == NULL) - return ret; - - if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { - BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n", - (void *)bio, (void *)argp, (unsigned long)argi, ret, ret); - BIO_dump(out, argp, (int)ret); - return ret; - } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { - BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n", - (void *)bio, (void *)argp, (unsigned long)argi, ret, ret); - BIO_dump(out, argp, (int)ret); - } - return ret; -} - -void apps_ssl_info_callback(const SSL *s, int where, int ret) -{ - const char *str; - int w; - - w = where & ~SSL_ST_MASK; - - if (w & SSL_ST_CONNECT) - str = "SSL_connect"; - else if (w & SSL_ST_ACCEPT) - str = "SSL_accept"; - else - str = "undefined"; - - if (where & SSL_CB_LOOP) { - BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s)); - } else if (where & SSL_CB_ALERT) { - str = (where & SSL_CB_READ) ? "read" : "write"; - BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", - str, - SSL_alert_type_string_long(ret), - SSL_alert_desc_string_long(ret)); - } else if (where & SSL_CB_EXIT) { - if (ret == 0) - BIO_printf(bio_err, "%s:failed in %s\n", - str, SSL_state_string_long(s)); - else if (ret < 0) - BIO_printf(bio_err, "%s:error in %s\n", - str, SSL_state_string_long(s)); - } -} - -static STRINT_PAIR ssl_versions[] = { - {"SSL 3.0", SSL3_VERSION}, - {"TLS 1.0", TLS1_VERSION}, - {"TLS 1.1", TLS1_1_VERSION}, - {"TLS 1.2", TLS1_2_VERSION}, - {"TLS 1.3", TLS1_3_VERSION}, - {"DTLS 1.0", DTLS1_VERSION}, - {"DTLS 1.0 (bad)", DTLS1_BAD_VER}, - {NULL} -}; - -static STRINT_PAIR alert_types[] = { - {" close_notify", 0}, - {" end_of_early_data", 1}, - {" unexpected_message", 10}, - {" bad_record_mac", 20}, - {" decryption_failed", 21}, - {" record_overflow", 22}, - {" decompression_failure", 30}, - {" handshake_failure", 40}, - {" bad_certificate", 42}, - {" unsupported_certificate", 43}, - {" certificate_revoked", 44}, - {" certificate_expired", 45}, - {" certificate_unknown", 46}, - {" illegal_parameter", 47}, - {" unknown_ca", 48}, - {" access_denied", 49}, - {" decode_error", 50}, - {" decrypt_error", 51}, - {" export_restriction", 60}, - {" protocol_version", 70}, - {" insufficient_security", 71}, - {" internal_error", 80}, - {" inappropriate_fallback", 86}, - {" user_canceled", 90}, - {" no_renegotiation", 100}, - {" missing_extension", 109}, - {" unsupported_extension", 110}, - {" certificate_unobtainable", 111}, - {" unrecognized_name", 112}, - {" bad_certificate_status_response", 113}, - {" bad_certificate_hash_value", 114}, - {" unknown_psk_identity", 115}, - {" certificate_required", 116}, - {NULL} -}; - -static STRINT_PAIR handshakes[] = { - {", HelloRequest", SSL3_MT_HELLO_REQUEST}, - {", ClientHello", SSL3_MT_CLIENT_HELLO}, - {", ServerHello", SSL3_MT_SERVER_HELLO}, - {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST}, - {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET}, - {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA}, - {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS}, - {", Certificate", SSL3_MT_CERTIFICATE}, - {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE}, - {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST}, - {", ServerHelloDone", SSL3_MT_SERVER_DONE}, - {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY}, - {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE}, - {", Finished", SSL3_MT_FINISHED}, - {", CertificateUrl", SSL3_MT_CERTIFICATE_URL}, - {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS}, - {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA}, - {", KeyUpdate", SSL3_MT_KEY_UPDATE}, -#ifndef OPENSSL_NO_NEXTPROTONEG - {", NextProto", SSL3_MT_NEXT_PROTO}, -#endif - {", MessageHash", SSL3_MT_MESSAGE_HASH}, - {NULL} -}; - -void msg_cb(int write_p, int version, int content_type, const void *buf, - size_t len, SSL *ssl, void *arg) -{ - BIO *bio = arg; - const char *str_write_p = write_p ? ">>>" : "<<<"; - const char *str_version = lookup(version, ssl_versions, "???"); - const char *str_content_type = "", *str_details1 = "", *str_details2 = ""; - const unsigned char* bp = buf; - - if (version == SSL3_VERSION || - version == TLS1_VERSION || - version == TLS1_1_VERSION || - version == TLS1_2_VERSION || - version == TLS1_3_VERSION || - version == DTLS1_VERSION || version == DTLS1_BAD_VER) { - switch (content_type) { - case 20: - str_content_type = ", ChangeCipherSpec"; - break; - case 21: - str_content_type = ", Alert"; - str_details1 = ", ???"; - if (len == 2) { - switch (bp[0]) { - case 1: - str_details1 = ", warning"; - break; - case 2: - str_details1 = ", fatal"; - break; - } - str_details2 = lookup((int)bp[1], alert_types, " ???"); - } - break; - case 22: - str_content_type = ", Handshake"; - str_details1 = "???"; - if (len > 0) - str_details1 = lookup((int)bp[0], handshakes, "???"); - break; - case 23: - str_content_type = ", ApplicationData"; - break; -#ifndef OPENSSL_NO_HEARTBEATS - case 24: - str_details1 = ", Heartbeat"; - - if (len > 0) { - switch (bp[0]) { - case 1: - str_details1 = ", HeartbeatRequest"; - break; - case 2: - str_details1 = ", HeartbeatResponse"; - break; - } - } - break; -#endif - } - } - - BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version, - str_content_type, (unsigned long)len, str_details1, - str_details2); - - if (len > 0) { - size_t num, i; - - BIO_printf(bio, " "); - num = len; - for (i = 0; i < num; i++) { - if (i % 16 == 0 && i > 0) - BIO_printf(bio, "\n "); - BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]); - } - if (i < len) - BIO_printf(bio, " ..."); - BIO_printf(bio, "\n"); - } - (void)BIO_flush(bio); -} - -static STRINT_PAIR tlsext_types[] = { - {"server name", TLSEXT_TYPE_server_name}, - {"max fragment length", TLSEXT_TYPE_max_fragment_length}, - {"client certificate URL", TLSEXT_TYPE_client_certificate_url}, - {"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys}, - {"truncated HMAC", TLSEXT_TYPE_truncated_hmac}, - {"status request", TLSEXT_TYPE_status_request}, - {"user mapping", TLSEXT_TYPE_user_mapping}, - {"client authz", TLSEXT_TYPE_client_authz}, - {"server authz", TLSEXT_TYPE_server_authz}, - {"cert type", TLSEXT_TYPE_cert_type}, - {"supported_groups", TLSEXT_TYPE_supported_groups}, - {"EC point formats", TLSEXT_TYPE_ec_point_formats}, - {"SRP", TLSEXT_TYPE_srp}, - {"signature algorithms", TLSEXT_TYPE_signature_algorithms}, - {"use SRTP", TLSEXT_TYPE_use_srtp}, - {"heartbeat", TLSEXT_TYPE_heartbeat}, - {"session ticket", TLSEXT_TYPE_session_ticket}, - {"renegotiation info", TLSEXT_TYPE_renegotiate}, - {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp}, - {"TLS padding", TLSEXT_TYPE_padding}, -#ifdef TLSEXT_TYPE_next_proto_neg - {"next protocol", TLSEXT_TYPE_next_proto_neg}, -#endif -#ifdef TLSEXT_TYPE_encrypt_then_mac - {"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac}, -#endif -#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation - {"application layer protocol negotiation", - TLSEXT_TYPE_application_layer_protocol_negotiation}, -#endif -#ifdef TLSEXT_TYPE_extended_master_secret - {"extended master secret", TLSEXT_TYPE_extended_master_secret}, -#endif - {"key share", TLSEXT_TYPE_key_share}, - {"supported versions", TLSEXT_TYPE_supported_versions}, - {"psk", TLSEXT_TYPE_psk}, - {"psk kex modes", TLSEXT_TYPE_psk_kex_modes}, - {"certificate authorities", TLSEXT_TYPE_certificate_authorities}, - {"post handshake auth", TLSEXT_TYPE_post_handshake_auth}, - {NULL} -}; - -/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */ -static STRINT_PAIR signature_tls13_scheme_list[] = { - {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */}, - {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */}, -/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */ -/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */ - {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */}, - {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */}, - {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */}, - {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */}, - {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */}, - {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */}, - {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */}, - {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */}, - {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */}, - {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */}, - {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */}, - {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */}, - {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */}, - {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */}, - {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */}, - {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */}, - {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */}, - {NULL} -}; - -/* from rfc5246 7.4.1.4.1. */ -static STRINT_PAIR signature_tls12_alg_list[] = { - {"anonymous", TLSEXT_signature_anonymous /* 0 */}, - {"RSA", TLSEXT_signature_rsa /* 1 */}, - {"DSA", TLSEXT_signature_dsa /* 2 */}, - {"ECDSA", TLSEXT_signature_ecdsa /* 3 */}, - {NULL} -}; - -/* from rfc5246 7.4.1.4.1. */ -static STRINT_PAIR signature_tls12_hash_list[] = { - {"none", TLSEXT_hash_none /* 0 */}, - {"MD5", TLSEXT_hash_md5 /* 1 */}, - {"SHA1", TLSEXT_hash_sha1 /* 2 */}, - {"SHA224", TLSEXT_hash_sha224 /* 3 */}, - {"SHA256", TLSEXT_hash_sha256 /* 4 */}, - {"SHA384", TLSEXT_hash_sha384 /* 5 */}, - {"SHA512", TLSEXT_hash_sha512 /* 6 */}, - {NULL} -}; - -void tlsext_cb(SSL *s, int client_server, int type, - const unsigned char *data, int len, void *arg) -{ - BIO *bio = arg; - const char *extname = lookup(type, tlsext_types, "unknown"); - - BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n", - client_server ? "server" : "client", extname, type, len); - BIO_dump(bio, (const char *)data, len); - (void)BIO_flush(bio); -} - -#ifndef OPENSSL_NO_SOCK -int generate_cookie_callback(SSL *ssl, unsigned char *cookie, - unsigned int *cookie_len) -{ - unsigned char *buffer; - size_t length = 0; - unsigned short port; - BIO_ADDR *lpeer = NULL, *peer = NULL; - - /* Initialize a random secret */ - if (!cookie_initialized) { - if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) { - BIO_printf(bio_err, "error setting random cookie secret\n"); - return 0; - } - cookie_initialized = 1; - } - - if (SSL_is_dtls(ssl)) { - lpeer = peer = BIO_ADDR_new(); - if (peer == NULL) { - BIO_printf(bio_err, "memory full\n"); - return 0; - } - - /* Read peer information */ - (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); - } else { - peer = ourpeer; - } - - /* Create buffer with peer's address and port */ - if (!BIO_ADDR_rawaddress(peer, NULL, &length)) { - BIO_printf(bio_err, "Failed getting peer address\n"); - return 0; - } - OPENSSL_assert(length != 0); - port = BIO_ADDR_rawport(peer); - length += sizeof(port); - buffer = app_malloc(length, "cookie generate buffer"); - - memcpy(buffer, &port, sizeof(port)); - BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL); - - /* Calculate HMAC of buffer using the secret */ - HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, - buffer, length, cookie, cookie_len); - - OPENSSL_free(buffer); - BIO_ADDR_free(lpeer); - - return 1; -} - -int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, - unsigned int cookie_len) -{ - unsigned char result[EVP_MAX_MD_SIZE]; - unsigned int resultlength; - - /* Note: we check cookie_initialized because if it's not, - * it cannot be valid */ - if (cookie_initialized - && generate_cookie_callback(ssl, result, &resultlength) - && cookie_len == resultlength - && memcmp(result, cookie, resultlength) == 0) - return 1; - - return 0; -} - -int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie, - size_t *cookie_len) -{ - unsigned int temp; - int res = generate_cookie_callback(ssl, cookie, &temp); - - if (res != 0) - *cookie_len = temp; - return res; -} - -int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie, - size_t cookie_len) -{ - return verify_cookie_callback(ssl, cookie, cookie_len); -} - -#endif - -/* - * Example of extended certificate handling. Where the standard support of - * one certificate per algorithm is not sufficient an application can decide - * which certificate(s) to use at runtime based on whatever criteria it deems - * appropriate. - */ - -/* Linked list of certificates, keys and chains */ -struct ssl_excert_st { - int certform; - const char *certfile; - int keyform; - const char *keyfile; - const char *chainfile; - X509 *cert; - EVP_PKEY *key; - STACK_OF(X509) *chain; - int build_chain; - struct ssl_excert_st *next, *prev; -}; - -static STRINT_PAIR chain_flags[] = { - {"Overall Validity", CERT_PKEY_VALID}, - {"Sign with EE key", CERT_PKEY_SIGN}, - {"EE signature", CERT_PKEY_EE_SIGNATURE}, - {"CA signature", CERT_PKEY_CA_SIGNATURE}, - {"EE key parameters", CERT_PKEY_EE_PARAM}, - {"CA key parameters", CERT_PKEY_CA_PARAM}, - {"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN}, - {"Issuer Name", CERT_PKEY_ISSUER_NAME}, - {"Certificate Type", CERT_PKEY_CERT_TYPE}, - {NULL} -}; - -static void print_chain_flags(SSL *s, int flags) -{ - STRINT_PAIR *pp; - - for (pp = chain_flags; pp->name; ++pp) - BIO_printf(bio_err, "\t%s: %s\n", - pp->name, - (flags & pp->retval) ? "OK" : "NOT OK"); - BIO_printf(bio_err, "\tSuite B: "); - if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS) - BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n"); - else - BIO_printf(bio_err, "not tested\n"); -} - -/* - * Very basic selection callback: just use any certificate chain reported as - * valid. More sophisticated could prioritise according to local policy. - */ -static int set_cert_cb(SSL *ssl, void *arg) -{ - int i, rv; - SSL_EXCERT *exc = arg; -#ifdef CERT_CB_TEST_RETRY - static int retry_cnt; - if (retry_cnt < 5) { - retry_cnt++; - BIO_printf(bio_err, - "Certificate callback retry test: count %d\n", - retry_cnt); - return -1; - } -#endif - SSL_certs_clear(ssl); - - if (exc == NULL) - return 1; - - /* - * Go to end of list and traverse backwards since we prepend newer - * entries this retains the original order. - */ - while (exc->next != NULL) - exc = exc->next; - - i = 0; - - while (exc != NULL) { - i++; - rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain); - BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i); - X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0, - get_nameopt()); - BIO_puts(bio_err, "\n"); - print_chain_flags(ssl, rv); - if (rv & CERT_PKEY_VALID) { - if (!SSL_use_certificate(ssl, exc->cert) - || !SSL_use_PrivateKey(ssl, exc->key)) { - return 0; - } - /* - * NB: we wouldn't normally do this as it is not efficient - * building chains on each connection better to cache the chain - * in advance. - */ - if (exc->build_chain) { - if (!SSL_build_cert_chain(ssl, 0)) - return 0; - } else if (exc->chain != NULL) { - if (!SSL_set1_chain(ssl, exc->chain)) - return 0; - } - } - exc = exc->prev; - } - return 1; -} - -void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc) -{ - SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc); -} - -static int ssl_excert_prepend(SSL_EXCERT **pexc) -{ - SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert"); - - memset(exc, 0, sizeof(*exc)); - - exc->next = *pexc; - *pexc = exc; - - if (exc->next) { - exc->certform = exc->next->certform; - exc->keyform = exc->next->keyform; - exc->next->prev = exc; - } else { - exc->certform = FORMAT_PEM; - exc->keyform = FORMAT_PEM; - } - return 1; - -} - -void ssl_excert_free(SSL_EXCERT *exc) -{ - SSL_EXCERT *curr; - - if (exc == NULL) - return; - while (exc) { - X509_free(exc->cert); - EVP_PKEY_free(exc->key); - sk_X509_pop_free(exc->chain, X509_free); - curr = exc; - exc = exc->next; - OPENSSL_free(curr); - } -} - -int load_excert(SSL_EXCERT **pexc) -{ - SSL_EXCERT *exc = *pexc; - if (exc == NULL) - return 1; - /* If nothing in list, free and set to NULL */ - if (exc->certfile == NULL && exc->next == NULL) { - ssl_excert_free(exc); - *pexc = NULL; - return 1; - } - for (; exc; exc = exc->next) { - if (exc->certfile == NULL) { - BIO_printf(bio_err, "Missing filename\n"); - return 0; - } - exc->cert = load_cert(exc->certfile, exc->certform, - "Server Certificate"); - if (exc->cert == NULL) - return 0; - if (exc->keyfile != NULL) { - exc->key = load_key(exc->keyfile, exc->keyform, - 0, NULL, NULL, "Server Key"); - } else { - exc->key = load_key(exc->certfile, exc->certform, - 0, NULL, NULL, "Server Key"); - } - if (exc->key == NULL) - return 0; - if (exc->chainfile != NULL) { - if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL, - "Server Chain")) - return 0; - } - } - return 1; -} - -enum range { OPT_X_ENUM }; - -int args_excert(int opt, SSL_EXCERT **pexc) -{ - SSL_EXCERT *exc = *pexc; - - assert(opt > OPT_X__FIRST); - assert(opt < OPT_X__LAST); - - if (exc == NULL) { - if (!ssl_excert_prepend(&exc)) { - BIO_printf(bio_err, " %s: Error initialising xcert\n", - opt_getprog()); - goto err; - } - *pexc = exc; - } - - switch ((enum range)opt) { - case OPT_X__FIRST: - case OPT_X__LAST: - return 0; - case OPT_X_CERT: - if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) { - BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog()); - goto err; - } - *pexc = exc; - exc->certfile = opt_arg(); - break; - case OPT_X_KEY: - if (exc->keyfile != NULL) { - BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog()); - goto err; - } - exc->keyfile = opt_arg(); - break; - case OPT_X_CHAIN: - if (exc->chainfile != NULL) { - BIO_printf(bio_err, "%s: Chain already specified\n", - opt_getprog()); - goto err; - } - exc->chainfile = opt_arg(); - break; - case OPT_X_CHAIN_BUILD: - exc->build_chain = 1; - break; - case OPT_X_CERTFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform)) - return 0; - break; - case OPT_X_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform)) - return 0; - break; - } - return 1; - - err: - ERR_print_errors(bio_err); - ssl_excert_free(exc); - *pexc = NULL; - return 0; -} - -static void print_raw_cipherlist(SSL *s) -{ - const unsigned char *rlist; - static const unsigned char scsv_id[] = { 0, 0xFF }; - size_t i, rlistlen, num; - if (!SSL_is_server(s)) - return; - num = SSL_get0_raw_cipherlist(s, NULL); - OPENSSL_assert(num == 2); - rlistlen = SSL_get0_raw_cipherlist(s, &rlist); - BIO_puts(bio_err, "Client cipher list: "); - for (i = 0; i < rlistlen; i += num, rlist += num) { - const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist); - if (i) - BIO_puts(bio_err, ":"); - if (c != NULL) { - BIO_puts(bio_err, SSL_CIPHER_get_name(c)); - } else if (memcmp(rlist, scsv_id, num) == 0) { - BIO_puts(bio_err, "SCSV"); - } else { - size_t j; - BIO_puts(bio_err, "0x"); - for (j = 0; j < num; j++) - BIO_printf(bio_err, "%02X", rlist[j]); - } - } - BIO_puts(bio_err, "\n"); -} - -/* - * Hex encoder for TLSA RRdata, not ':' delimited. - */ -static char *hexencode(const unsigned char *data, size_t len) -{ - static const char *hex = "0123456789abcdef"; - char *out; - char *cp; - size_t outlen = 2 * len + 1; - int ilen = (int) outlen; - - if (outlen < len || ilen < 0 || outlen != (size_t)ilen) { - BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n", - opt_getprog(), len); - exit(1); - } - cp = out = app_malloc(ilen, "TLSA hex data buffer"); - - while (len-- > 0) { - *cp++ = hex[(*data >> 4) & 0x0f]; - *cp++ = hex[*data++ & 0x0f]; - } - *cp = '\0'; - return out; -} - -void print_verify_detail(SSL *s, BIO *bio) -{ - int mdpth; - EVP_PKEY *mspki; - long verify_err = SSL_get_verify_result(s); - - if (verify_err == X509_V_OK) { - const char *peername = SSL_get0_peername(s); - - BIO_printf(bio, "Verification: OK\n"); - if (peername != NULL) - BIO_printf(bio, "Verified peername: %s\n", peername); - } else { - const char *reason = X509_verify_cert_error_string(verify_err); - - BIO_printf(bio, "Verification error: %s\n", reason); - } - - if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) { - uint8_t usage, selector, mtype; - const unsigned char *data = NULL; - size_t dlen = 0; - char *hexdata; - - mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen); - - /* - * The TLSA data field can be quite long when it is a certificate, - * public key or even a SHA2-512 digest. Because the initial octets of - * ASN.1 certificates and public keys contain mostly boilerplate OIDs - * and lengths, we show the last 12 bytes of the data instead, as these - * are more likely to distinguish distinct TLSA records. - */ -#define TLSA_TAIL_SIZE 12 - if (dlen > TLSA_TAIL_SIZE) - hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); - else - hexdata = hexencode(data, dlen); - BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", - usage, selector, mtype, - (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, - (mspki != NULL) ? "signed the certificate" : - mdpth ? "matched TA certificate" : "matched EE certificate", - mdpth); - OPENSSL_free(hexdata); - } -} - -void print_ssl_summary(SSL *s) -{ - const SSL_CIPHER *c; - X509 *peer; - - BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s)); - print_raw_cipherlist(s); - c = SSL_get_current_cipher(s); - BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); - do_print_sigalgs(bio_err, s, 0); - peer = SSL_get_peer_certificate(s); - if (peer != NULL) { - int nid; - - BIO_puts(bio_err, "Peer certificate: "); - X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), - 0, get_nameopt()); - BIO_puts(bio_err, "\n"); - if (SSL_get_peer_signature_nid(s, &nid)) - BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid)); - if (SSL_get_peer_signature_type_nid(s, &nid)) - BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); - print_verify_detail(s, bio_err); - } else { - BIO_puts(bio_err, "No peer certificate\n"); - } - X509_free(peer); -#ifndef OPENSSL_NO_EC - ssl_print_point_formats(bio_err, s); - if (SSL_is_server(s)) - ssl_print_groups(bio_err, s, 1); - else - ssl_print_tmp_key(bio_err, s); -#else - if (!SSL_is_server(s)) - ssl_print_tmp_key(bio_err, s); -#endif -} - -int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, - SSL_CTX *ctx) -{ - int i; - - SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); - for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) { - const char *flag = sk_OPENSSL_STRING_value(str, i); - const char *arg = sk_OPENSSL_STRING_value(str, i + 1); - if (SSL_CONF_cmd(cctx, flag, arg) <= 0) { - if (arg != NULL) - BIO_printf(bio_err, "Error with command: \"%s %s\"\n", - flag, arg); - else - BIO_printf(bio_err, "Error with command: \"%s\"\n", flag); - ERR_print_errors(bio_err); - return 0; - } - } - if (!SSL_CONF_CTX_finish(cctx)) { - BIO_puts(bio_err, "Error finishing context\n"); - ERR_print_errors(bio_err); - return 0; - } - return 1; -} - -static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls) -{ - X509_CRL *crl; - int i; - for (i = 0; i < sk_X509_CRL_num(crls); i++) { - crl = sk_X509_CRL_value(crls, i); - X509_STORE_add_crl(st, crl); - } - return 1; -} - -int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download) -{ - X509_STORE *st; - st = SSL_CTX_get_cert_store(ctx); - add_crls_store(st, crls); - if (crl_download) - store_setup_crl_download(st); - return 1; -} - -int ssl_load_stores(SSL_CTX *ctx, - const char *vfyCApath, const char *vfyCAfile, - const char *chCApath, const char *chCAfile, - STACK_OF(X509_CRL) *crls, int crl_download) -{ - X509_STORE *vfy = NULL, *ch = NULL; - int rv = 0; - if (vfyCApath != NULL || vfyCAfile != NULL) { - vfy = X509_STORE_new(); - if (vfy == NULL) - goto err; - if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath)) - goto err; - add_crls_store(vfy, crls); - SSL_CTX_set1_verify_cert_store(ctx, vfy); - if (crl_download) - store_setup_crl_download(vfy); - } - if (chCApath != NULL || chCAfile != NULL) { - ch = X509_STORE_new(); - if (ch == NULL) - goto err; - if (!X509_STORE_load_locations(ch, chCAfile, chCApath)) - goto err; - SSL_CTX_set1_chain_cert_store(ctx, ch); - } - rv = 1; - err: - X509_STORE_free(vfy); - X509_STORE_free(ch); - return rv; -} - -/* Verbose print out of security callback */ - -typedef struct { - BIO *out; - int verbose; - int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid, - void *other, void *ex); -} security_debug_ex; - -static STRINT_PAIR callback_types[] = { - {"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED}, - {"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED}, - {"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK}, -#ifndef OPENSSL_NO_DH - {"Temp DH key bits", SSL_SECOP_TMP_DH}, -#endif - {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED}, - {"Shared Curve", SSL_SECOP_CURVE_SHARED}, - {"Check Curve", SSL_SECOP_CURVE_CHECK}, - {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED}, - {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED}, - {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK}, - {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK}, - {"Certificate chain EE key", SSL_SECOP_EE_KEY}, - {"Certificate chain CA key", SSL_SECOP_CA_KEY}, - {"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY}, - {"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY}, - {"Certificate chain CA digest", SSL_SECOP_CA_MD}, - {"Peer chain CA digest", SSL_SECOP_PEER_CA_MD}, - {"SSL compression", SSL_SECOP_COMPRESSION}, - {"Session ticket", SSL_SECOP_TICKET}, - {NULL} -}; - -static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, - int op, int bits, int nid, - void *other, void *ex) -{ - security_debug_ex *sdb = ex; - int rv, show_bits = 1, cert_md = 0; - const char *nm; - int show_nm; - rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex); - if (rv == 1 && sdb->verbose < 2) - return 1; - BIO_puts(sdb->out, "Security callback: "); - - nm = lookup(op, callback_types, NULL); - show_nm = nm != NULL; - switch (op) { - case SSL_SECOP_TICKET: - case SSL_SECOP_COMPRESSION: - show_bits = 0; - show_nm = 0; - break; - case SSL_SECOP_VERSION: - BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???")); - show_bits = 0; - show_nm = 0; - break; - case SSL_SECOP_CA_MD: - case SSL_SECOP_PEER_CA_MD: - cert_md = 1; - break; - case SSL_SECOP_SIGALG_SUPPORTED: - case SSL_SECOP_SIGALG_SHARED: - case SSL_SECOP_SIGALG_CHECK: - case SSL_SECOP_SIGALG_MASK: - show_nm = 0; - break; - } - if (show_nm) - BIO_printf(sdb->out, "%s=", nm); - - switch (op & SSL_SECOP_OTHER_TYPE) { - - case SSL_SECOP_OTHER_CIPHER: - BIO_puts(sdb->out, SSL_CIPHER_get_name(other)); - break; - -#ifndef OPENSSL_NO_EC - case SSL_SECOP_OTHER_CURVE: - { - const char *cname; - cname = EC_curve_nid2nist(nid); - if (cname == NULL) - cname = OBJ_nid2sn(nid); - BIO_puts(sdb->out, cname); - } - break; -#endif -#ifndef OPENSSL_NO_DH - case SSL_SECOP_OTHER_DH: - { - DH *dh = other; - BIO_printf(sdb->out, "%d", DH_bits(dh)); - break; - } -#endif - case SSL_SECOP_OTHER_CERT: - { - if (cert_md) { - int sig_nid = X509_get_signature_nid(other); - BIO_puts(sdb->out, OBJ_nid2sn(sig_nid)); - } else { - EVP_PKEY *pkey = X509_get0_pubkey(other); - const char *algname = ""; - EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, - &algname, EVP_PKEY_get0_asn1(pkey)); - BIO_printf(sdb->out, "%s, bits=%d", - algname, EVP_PKEY_bits(pkey)); - } - break; - } - case SSL_SECOP_OTHER_SIGALG: - { - const unsigned char *salg = other; - const char *sname = NULL; - int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */ - /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */ - - if (nm != NULL) - BIO_printf(sdb->out, "%s", nm); - else - BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op); - - sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL); - if (sname != NULL) { - BIO_printf(sdb->out, " scheme=%s", sname); - } else { - int alg_code = salg[1]; - int hash_code = salg[0]; - const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL); - const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL); - - if (alg_str != NULL && hash_str != NULL) - BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str); - else - BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code); - } - } - - } - - if (show_bits) - BIO_printf(sdb->out, ", security bits=%d", bits); - BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no"); - return rv; -} - -void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose) -{ - static security_debug_ex sdb; - - sdb.out = bio_err; - sdb.verbose = verbose; - sdb.old_cb = SSL_CTX_get_security_callback(ctx); - SSL_CTX_set_security_callback(ctx, security_callback_debug); - SSL_CTX_set0_security_ex_data(ctx, &sdb); -} - -static void keylog_callback(const SSL *ssl, const char *line) -{ - if (bio_keylog == NULL) { - BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n"); - return; - } - - /* - * There might be concurrent writers to the keylog file, so we must ensure - * that the given line is written at once. - */ - BIO_printf(bio_keylog, "%s\n", line); - (void)BIO_flush(bio_keylog); -} - -int set_keylog_file(SSL_CTX *ctx, const char *keylog_file) -{ - /* Close any open files */ - BIO_free_all(bio_keylog); - bio_keylog = NULL; - - if (ctx == NULL || keylog_file == NULL) { - /* Keylogging is disabled, OK. */ - return 0; - } - - /* - * Append rather than write in order to allow concurrent modification. - * Furthermore, this preserves existing keylog files which is useful when - * the tool is run multiple times. - */ - bio_keylog = BIO_new_file(keylog_file, "a"); - if (bio_keylog == NULL) { - BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file); - return 1; - } - - /* Write a header for seekable, empty files (this excludes pipes). */ - if (BIO_tell(bio_keylog) == 0) { - BIO_puts(bio_keylog, - "# SSL/TLS secrets log file, generated by OpenSSL\n"); - (void)BIO_flush(bio_keylog); - } - SSL_CTX_set_keylog_callback(ctx, keylog_callback); - return 0; -} - -void print_ca_names(BIO *bio, SSL *s) -{ - const char *cs = SSL_is_server(s) ? "server" : "client"; - const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s); - int i; - - if (sk == NULL || sk_X509_NAME_num(sk) == 0) { - if (!SSL_is_server(s)) - BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs); - return; - } - - BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs); - for (i = 0; i < sk_X509_NAME_num(sk); i++) { - X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt()); - BIO_write(bio, "\n", 1); - } -} diff --git a/apps/s_client.c b/apps/s_client.c --- a/apps/s_client.c +++ b/apps/s_client.c @@ -1,8 +1,8 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2005 Nokia. All rights reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -38,10 +38,8 @@ #include #include #include +#include #include -#ifndef OPENSSL_NO_SRP -# include -#endif #ifndef OPENSSL_NO_CT # include #endif @@ -91,27 +89,6 @@ return ret; } -static void do_ssl_shutdown(SSL *ssl) -{ - int ret; - - do { - /* We only do unidirectional shutdown */ - ret = SSL_shutdown(ssl); - if (ret < 0) { - switch (SSL_get_error(ssl, ret)) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_WANT_ASYNC: - case SSL_ERROR_WANT_ASYNC_JOB: - /* We just do busy waiting. Nothing clever */ - continue; - } - ret = 0; - } - } while (ret < 0); -} - /* Default PSK identity and key */ static char *psk_identity = "Client_identity"; @@ -258,117 +235,6 @@ return SSL_TLSEXT_ERR_OK; } -#ifndef OPENSSL_NO_SRP - -/* This is a context that we pass to all callbacks */ -typedef struct srp_arg_st { - char *srppassin; - char *srplogin; - int msg; /* copy from c_msg */ - int debug; /* copy from c_debug */ - int amp; /* allow more groups */ - int strength; /* minimal size for N */ -} SRP_ARG; - -# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64 - -static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g) -{ - BN_CTX *bn_ctx = BN_CTX_new(); - BIGNUM *p = BN_new(); - BIGNUM *r = BN_new(); - int ret = - g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) && - BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && - p != NULL && BN_rshift1(p, N) && - /* p = (N-1)/2 */ - BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 && - r != NULL && - /* verify g^((N-1)/2) == -1 (mod N) */ - BN_mod_exp(r, g, p, N, bn_ctx) && - BN_add_word(r, 1) && BN_cmp(r, N) == 0; - - BN_free(r); - BN_free(p); - BN_CTX_free(bn_ctx); - return ret; -} - -/*- - * This callback is used here for two purposes: - * - extended debugging - * - making some primality tests for unknown groups - * The callback is only called for a non default group. - * - * An application does not need the call back at all if - * only the standard groups are used. In real life situations, - * client and server already share well known groups, - * thus there is no need to verify them. - * Furthermore, in case that a server actually proposes a group that - * is not one of those defined in RFC 5054, it is more appropriate - * to add the group to a static list and then compare since - * primality tests are rather cpu consuming. - */ - -static int ssl_srp_verify_param_cb(SSL *s, void *arg) -{ - SRP_ARG *srp_arg = (SRP_ARG *)arg; - BIGNUM *N = NULL, *g = NULL; - - if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL)) - return 0; - if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) { - BIO_printf(bio_err, "SRP parameters:\n"); - BIO_printf(bio_err, "\tN="); - BN_print(bio_err, N); - BIO_printf(bio_err, "\n\tg="); - BN_print(bio_err, g); - BIO_printf(bio_err, "\n"); - } - - if (SRP_check_known_gN_param(g, N)) - return 1; - - if (srp_arg->amp == 1) { - if (srp_arg->debug) - BIO_printf(bio_err, - "SRP param N and g are not known params, going to check deeper.\n"); - - /* - * The srp_moregroups is a real debugging feature. Implementors - * should rather add the value to the known ones. The minimal size - * has already been tested. - */ - if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g)) - return 1; - } - BIO_printf(bio_err, "SRP param N and g rejected.\n"); - return 0; -} - -# define PWD_STRLEN 1024 - -static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) -{ - SRP_ARG *srp_arg = (SRP_ARG *)arg; - char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer"); - PW_CB_DATA cb_tmp; - int l; - - cb_tmp.password = (char *)srp_arg->srppassin; - cb_tmp.prompt_info = "SRP user"; - if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) { - BIO_printf(bio_err, "Can't read Password\n"); - OPENSSL_free(pass); - return NULL; - } - *(pass + l) = '\0'; - - return pass; -} - -#endif - #ifndef OPENSSL_NO_NEXTPROTONEG /* This the context that we pass to next_proto_cb */ typedef struct tlsextnextprotoctx_st { @@ -563,7 +429,7 @@ } typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX, OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT, OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN, @@ -581,35 +447,56 @@ OPT_SSL3, OPT_SSL_CONFIG, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, - OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, - OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, - OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_CERT_CHAIN, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, + OPT_NEXTPROTONEG, OPT_ALPN, + OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, + OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, OPT_VERIFYCAFILE, + OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE, OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC, OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST, OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE, OPT_V_ENUM, OPT_X_ENUM, - OPT_S_ENUM, - OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN, + OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF, + OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS, + OPT_DANE_TLSA_DOMAIN, #ifndef OPENSSL_NO_CT OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, #endif OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, OPT_ENABLE_PHA, OPT_SCTP_LABEL_BUG, - OPT_R_ENUM + OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS s_client_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [host:port]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's', + "Specify engine to be used for client certificate operations"}, +#endif + {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified section for SSL_CTX configuration"}, +#ifndef OPENSSL_NO_CT + {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"}, + {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"}, + {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"}, +#endif + + OPT_SECTION("Network"), {"host", OPT_HOST, 's', "Use -connect instead"}, {"port", OPT_PORT, 'p', "Use -connect instead"}, {"connect", OPT_CONNECT, 's', - "TCP/IP where to connect (default is :" PORT ")"}, + "TCP/IP where to connect; default: " PORT ")"}, {"bind", OPT_BIND, 's', "bind local address for connection"}, {"proxy", OPT_PROXY, 's', "Connect to via specified proxy to the real server"}, + {"proxy_user", OPT_PROXY_USER, 's', "UserID for proxy authentication"}, + {"proxy_pass", OPT_PROXY_PASS, 's', "Proxy authentication password source"}, #ifdef AF_UNIX {"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"}, #endif @@ -617,20 +504,38 @@ #ifdef AF_INET6 {"6", OPT_6, '-', "Use IPv6 only"}, #endif - {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"}, - {"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"}, + {"maxfraglen", OPT_MAXFRAGLEN, 'p', + "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"}, + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', + "Size used to split data for encrypt pipelines"}, + {"max_pipelines", OPT_MAX_PIPELINES, 'p', + "Maximum number of encrypt/decrypt pipelines to be used"}, + {"read_buf", OPT_READ_BUF, 'p', + "Default read buffer size to be used for connections"}, + {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"}, + + OPT_SECTION("Identity"), + {"cert", OPT_CERT, '<', "Client certificate file to use"}, {"certform", OPT_CERTFORM, 'F', - "Certificate format (PEM or DER) PEM default"}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, - {"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"}, - {"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"}, - {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, + "Client certificate file format (PEM/DER/P12); has no effect"}, + {"cert_chain", OPT_CERT_CHAIN, '<', + "Client certificate chain file (in PEM format)"}, + {"build_chain", OPT_BUILD_CHAIN, '-', "Build client certificate chain"}, + {"key", OPT_KEY, 's', "Private key file to use; default: -cert file"}, + {"keyform", OPT_KEYFORM, 'E', "Key format (ENGINE, other values ignored)"}, + {"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"}, + {"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"}, + {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"}, {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"}, {"no-CAfile", OPT_NOCAFILE, '-', "Do not load the default certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', "Do not load certificates from the default certificates directory"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store"}, {"requestCAfile", OPT_REQCAFILE, '<', "PEM format file of CA names to send to the server"}, {"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"}, @@ -638,16 +543,19 @@ "DANE TLSA rrdata presentation form"}, {"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-', "Disable name checks when matching DANE-EE(3) TLSA records"}, + {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"}, + {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, + {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, + {"name", OPT_PROTOHOST, 's', + "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""}, + + OPT_SECTION("Session"), {"reconnect", OPT_RECONNECT, '-', "Drop and re-make the connection with the same Session-ID"}, - {"showcerts", OPT_SHOWCERTS, '-', - "Show all certificates sent by the server"}, - {"debug", OPT_DEBUG, '-', "Extra output"}, - {"msg", OPT_MSG, '-', "Show protocol messages"}, - {"msgfile", OPT_MSGFILE, '>', - "File to send output of -msg or -trace, instead of stdout"}, - {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"}, - {"state", OPT_STATE, '-', "Print the ssl states"}, + {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"}, + {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"}, + + OPT_SECTION("Input/Output"), {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, {"quiet", OPT_QUIET, '-', "No s_client output"}, {"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"}, @@ -656,47 +564,35 @@ "Use the appropriate STARTTLS command before starting TLS"}, {"xmpphost", OPT_XMPPHOST, 's', "Alias of -name option for \"-starttls xmpp[-server]\""}, - OPT_R_OPTIONS, - {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"}, - {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"}, -#ifndef OPENSSL_NO_SRTP - {"use_srtp", OPT_USE_SRTP, 's', - "Offer SRTP key management with a colon-separated profile list"}, -#endif - {"keymatexport", OPT_KEYMATEXPORT, 's', - "Export keying material using label"}, - {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', - "Export len bytes of keying material (default 20)"}, - {"maxfraglen", OPT_MAXFRAGLEN, 'p', - "Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"}, - {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"}, - {"name", OPT_PROTOHOST, 's', - "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""}, - {"CRL", OPT_CRL, '<', "CRL file to use"}, - {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"}, - {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, - {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', - "Close connection on verification error"}, - {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"}, {"brief", OPT_BRIEF, '-', "Restrict output to brief summary of connection parameters"}, {"prexit", OPT_PREXIT, '-', "Print session information when the program exits"}, + + OPT_SECTION("Debug"), + {"showcerts", OPT_SHOWCERTS, '-', + "Show all certificates sent by the server"}, + {"debug", OPT_DEBUG, '-', "Extra output"}, + {"msg", OPT_MSG, '-', "Show protocol messages"}, + {"msgfile", OPT_MSGFILE, '>', + "File to send output of -msg or -trace, instead of stdout"}, + {"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"}, + {"state", OPT_STATE, '-', "Print the ssl states"}, + {"keymatexport", OPT_KEYMATEXPORT, 's', + "Export keying material using label"}, + {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', + "Export len bytes of keying material; default 20"}, {"security_debug", OPT_SECURITY_DEBUG, '-', "Enable security debug messages"}, {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', "Output more security debug output"}, - {"cert_chain", OPT_CERT_CHAIN, '<', - "Certificate chain file (in PEM format)"}, - {"chainCApath", OPT_CHAINCAPATH, '/', - "Use dir as certificate store path to build CA certificate chain"}, - {"verifyCApath", OPT_VERIFYCAPATH, '/', - "Use dir as certificate store path to verify CA certificate"}, - {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, - {"chainCAfile", OPT_CHAINCAFILE, '<', - "CA file for certificate chain (PEM format)"}, - {"verifyCAfile", OPT_VERIFYCAFILE, '<', - "CA file for certificate verification (PEM format)"}, +#ifndef OPENSSL_NO_SSL_TRACE + {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"}, +#endif +#ifdef WATT32 + {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"}, +#endif + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, {"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"}, {"servername", OPT_SERVERNAME, 's', "Set TLS extension servername (SNI) in ClientHello (default)"}, @@ -704,6 +600,8 @@ "Do not send the server name (SNI) extension in the ClientHello"}, {"tlsextdebug", OPT_TLSEXTDEBUG, '-', "Hex dump of all TLS extensions received"}, + {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-', + "Do not treat lack of close_notify from a peer as an error"}, #ifndef OPENSSL_NO_OCSP {"status", OPT_STATUS, '-', "Request certificate status from server"}, #endif @@ -712,17 +610,9 @@ {"alpn", OPT_ALPN, 's', "Enable ALPN extension, considering named protocols supported (comma-separated list)"}, {"async", OPT_ASYNC, '-', "Support asynchronous operation"}, - {"ssl_config", OPT_SSL_CONFIG, 's', "Use specified configuration file"}, - {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, - {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', - "Size used to split data for encrypt pipelines"}, - {"max_pipelines", OPT_MAX_PIPELINES, 'p', - "Maximum number of encrypt/decrypt pipelines to be used"}, - {"read_buf", OPT_READ_BUF, 'p', - "Default read buffer size to be used for connections"}, - OPT_S_OPTIONS, - OPT_V_OPTIONS, - OPT_X_OPTIONS, + {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + + OPT_SECTION("Protocol and version"), #ifndef OPENSSL_NO_SSL3 {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, #endif @@ -754,43 +644,54 @@ {"sctp", OPT_SCTP, '-', "Use SCTP"}, {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"}, #endif -#ifndef OPENSSL_NO_SSL_TRACE - {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"}, -#endif -#ifdef WATT32 - {"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"}, -#endif - {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, - {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"}, - {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, - {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, -#ifndef OPENSSL_NO_SRP - {"srpuser", OPT_SRPUSER, 's', "SRP authentication for 'user'"}, - {"srppass", OPT_SRPPASS, 's', "Password for 'user'"}, - {"srp_lateuser", OPT_SRP_LATEUSER, '-', - "SRP username into second ClientHello message"}, - {"srp_moregroups", OPT_SRP_MOREGROUPS, '-', - "Tolerate other than the known g N values."}, - {"srp_strength", OPT_SRP_STRENGTH, 'p', "Minimal length in bits for N"}, -#endif #ifndef OPENSSL_NO_NEXTPROTONEG {"nextprotoneg", OPT_NEXTPROTONEG, 's', "Enable NPN extension, considering named protocols supported (comma-separated list)"}, #endif -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, - {"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's', - "Specify engine to be used for client certificate operations"}, -#endif -#ifndef OPENSSL_NO_CT - {"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"}, - {"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"}, - {"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"}, -#endif - {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"}, - {NULL, OPT_EOF, 0x00, NULL} +#ifndef OPENSSL_NO_SRTP + {"use_srtp", OPT_USE_SRTP, 's', + "Offer SRTP key management with a colon-separated profile list"}, +#endif +#ifndef OPENSSL_NO_SRP + {"srpuser", OPT_SRPUSER, 's', "(deprecated) SRP authentication for 'user'"}, + {"srppass", OPT_SRPPASS, 's', "(deprecated) Password for 'user'"}, + {"srp_lateuser", OPT_SRP_LATEUSER, '-', + "(deprecated) SRP username into second ClientHello message"}, + {"srp_moregroups", OPT_SRP_MOREGROUPS, '-', + "(deprecated) Tolerate other than the known g N values."}, + {"srp_strength", OPT_SRP_STRENGTH, 'p', + "(deprecated) Minimal length in bits for N"}, +#endif + + OPT_R_OPTIONS, + OPT_S_OPTIONS, + OPT_V_OPTIONS, + {"CRL", OPT_CRL, '<', "CRL file to use"}, + {"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"}, + {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER); default PEM"}, + {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', + "Close connection on verification error"}, + {"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"}, + {"chainCAfile", OPT_CHAINCAFILE, '<', + "CA file for certificate chain (PEM format)"}, + {"chainCApath", OPT_CHAINCAPATH, '/', + "Use dir as certificate store path to build CA certificate chain"}, + {"chainCAstore", OPT_CHAINCASTORE, ':', + "CA store URI for certificate chain"}, + {"verifyCAfile", OPT_VERIFYCAFILE, '<', + "CA file for certificate verification (PEM format)"}, + {"verifyCApath", OPT_VERIFYCAPATH, '/', + "Use dir as certificate store path to verify CA certificate"}, + {"verifyCAstore", OPT_VERIFYCASTORE, ':', + "CA store URI for certificate verification"}, + OPT_X_OPTIONS, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"host:port", 0, 0, "Where to connect; same as -connect option"}, + {NULL} }; typedef enum PROTOCOL_choice { @@ -802,7 +703,6 @@ PROTO_TELNET, PROTO_XMPP, PROTO_XMPP_SERVER, - PROTO_CONNECT, PROTO_IRC, PROTO_MYSQL, PROTO_POSTGRES, @@ -896,29 +796,33 @@ int dane_ee_no_name = 0; STACK_OF(X509_CRL) *crls = NULL; const SSL_METHOD *meth = TLS_client_method(); - const char *CApath = NULL, *CAfile = NULL; - char *cbuf = NULL, *sbuf = NULL; - char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL; + const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL; + char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; + char *proxystr = NULL, *proxyuser = NULL; + char *proxypassarg = NULL, *proxypass = NULL; + char *connectstr = NULL, *bindstr = NULL; char *cert_file = NULL, *key_file = NULL, *chain_file = NULL; - char *chCApath = NULL, *chCAfile = NULL, *host = NULL; - char *port = OPENSSL_strdup(PORT); + char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL, *host = NULL; + char *thost = NULL, *tport = NULL; + char *port = NULL; char *bindhost = NULL, *bindport = NULL; - char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; + char *passarg = NULL, *pass = NULL; + char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = NULL; char *ReqCAfile = NULL; char *sess_in = NULL, *crl_file = NULL, *p; const char *protohost = NULL; struct timeval timeout, *timeoutp; fd_set readfds, writefds; - int noCApath = 0, noCAfile = 0; - int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_PEM; - int key_format = FORMAT_PEM, crlf = 0, full_log = 1, mbuf_len = 0; + int noCApath = 0, noCAfile = 0, noCAstore = 0; + int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_UNDEF; + int key_format = FORMAT_UNDEF, crlf = 0, full_log = 1, mbuf_len = 0; int prexit = 0; int sdebug = 0; int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0; - int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0; + int ret = 1, in_init = 1, i, nbio_test = 0, sock = -1, k, width, state = 0; int sbuf_len, sbuf_off, cmdletters = 1; int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; - int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0; + int starttls_proto = PROTO_OFF, crl_format = FORMAT_UNDEF, crl_download = 0; int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) int at_eof = 0; @@ -983,6 +887,7 @@ #ifndef OPENSSL_NO_SCTP int sctp_label_bug = 0; #endif + int ignore_unexpected_eof = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -994,16 +899,16 @@ # endif #endif - prog = opt_progname(argv[0]); c_quiet = 0; c_debug = 0; c_showcerts = 0; c_nbio = 0; + port = OPENSSL_strdup(PORT); vpm = X509_VERIFY_PARAM_new(); cctx = SSL_CONF_CTX_new(); - if (vpm == NULL || cctx == NULL) { - BIO_printf(bio_err, "%s: out of memory\n", prog); + if (port == NULL || vpm == NULL || cctx == NULL) { + BIO_printf(bio_err, "%s: out of memory\n", opt_getprog()); goto end; } @@ -1080,7 +985,12 @@ break; case OPT_PROXY: proxystr = opt_arg(); - starttls_proto = PROTO_CONNECT; + break; + case OPT_PROXY_USER: + proxyuser = opt_arg(); + break; + case OPT_PROXY_PASS: + proxypassarg = opt_arg(); break; #ifdef AF_UNIX case OPT_UNIX: @@ -1120,7 +1030,7 @@ sess_in = opt_arg(); break; case OPT_CERTFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &cert_format)) goto opthelp; break; case OPT_CRLFORM: @@ -1156,6 +1066,9 @@ if (!args_excert(o, &exc)) goto end; break; + case OPT_IGNORE_UNEXPECTED_EOF: + ignore_unexpected_eof = 1; + break; case OPT_PREXIT: prexit = 1; break; @@ -1176,7 +1089,7 @@ break; case OPT_SSL_CLIENT_ENGINE: #ifndef OPENSSL_NO_ENGINE - ssl_client_engine = ENGINE_by_id(opt_arg()); + ssl_client_engine = setup_engine(opt_arg(), 0); if (ssl_client_engine == NULL) { BIO_printf(bio_err, "Error getting client auth engine\n"); goto opthelp; @@ -1187,6 +1100,10 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_IGN_EOF: c_ign_eof = 1; break; @@ -1214,6 +1131,10 @@ break; case OPT_MSGFILE: bio_c_msg = BIO_new_file(opt_arg(), "w"); + if (bio_c_msg == NULL) { + BIO_printf(bio_err, "Error writing file %s\n", opt_arg()); + goto end; + } break; case OPT_TRACE: #ifndef OPENSSL_NO_SSL_TRACE @@ -1370,7 +1291,7 @@ fallback_scsv = 1; break; case OPT_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &key_format)) goto opthelp; break; case OPT_PASS: @@ -1426,6 +1347,18 @@ case OPT_VERIFYCAFILE: vfyCAfile = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; + case OPT_NOCASTORE: + noCAstore = 1; + break; + case OPT_CHAINCASTORE: + chCAstore = opt_arg(); + break; + case OPT_VERIFYCASTORE: + vfyCAstore = opt_arg(); + break; case OPT_DANE_TLSA_DOMAIN: dane_tlsa_domain = opt_arg(); break; @@ -1530,6 +1463,25 @@ break; } } + + /* Optional argument is connect string if -connect not used. */ + argc = opt_num_rest(); + if (argc == 1) { + /* Don't allow -connect and a separate argument. */ + if (connectstr != NULL) { + BIO_printf(bio_err, + "%s: cannot provide both -connect option and target parameter\n", + prog); + goto opthelp; + } + connect_type = use_inet; + freeandcopy(&connectstr, *opt_rest()); + } else if (argc != 0) { + goto opthelp; + } + if (!app_RAND_load()) + goto end; + if (count4or6 >= 2) { BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog); goto opthelp; @@ -1548,23 +1500,6 @@ goto opthelp; } } - argc = opt_num_rest(); - if (argc == 1) { - /* If there's a positional argument, it's the equivalent of - * OPT_CONNECT. - * Don't allow -connect and a separate argument. - */ - if (connectstr != NULL) { - BIO_printf(bio_err, - "%s: must not provide both -connect option and target parameter\n", - prog); - goto opthelp; - } - connect_type = use_inet; - freeandcopy(&connectstr, *opt_rest()); - } else if (argc != 0) { - goto opthelp; - } #ifndef OPENSSL_NO_NEXTPROTONEG if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { @@ -1572,46 +1507,57 @@ goto opthelp; } #endif - if (proxystr != NULL) { + + if (connectstr != NULL) { int res; char *tmp_host = host, *tmp_port = port; - if (connectstr == NULL) { - BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog); - goto opthelp; - } - res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST); + + res = BIO_parse_hostserv(connectstr, &host, &port, BIO_PARSE_PRIO_HOST); if (tmp_host != host) OPENSSL_free(tmp_host); if (tmp_port != port) OPENSSL_free(tmp_port); if (!res) { BIO_printf(bio_err, - "%s: -proxy argument malformed or ambiguous\n", prog); + "%s: -connect argument or target parameter malformed or ambiguous\n", + prog); goto end; } + } + + if (proxystr != NULL) { + int res; + char *tmp_host = host, *tmp_port = port; + + if (host == NULL || port == NULL) { + BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog); + goto opthelp; + } + if (servername == NULL && !noservername) { - res = BIO_parse_hostserv(connectstr, &sname_alloc, NULL, BIO_PARSE_PRIO_HOST); - if (!res) { - BIO_printf(bio_err, - "%s: -connect argument malformed or ambiguous\n", prog); + servername = sname_alloc = OPENSSL_strdup(host); + if (sname_alloc == NULL) { + BIO_printf(bio_err, "%s: out of memory\n", prog); goto end; } - servername = sname_alloc; } - } else { - int res = 1; - char *tmp_host = host, *tmp_port = port; - if (connectstr != NULL) - res = BIO_parse_hostserv(connectstr, &host, &port, - BIO_PARSE_PRIO_HOST); + + /* Retain the original target host:port for use in the HTTP proxy connect string */ + thost = OPENSSL_strdup(host); + tport = OPENSSL_strdup(port); + if (thost == NULL || tport == NULL) { + BIO_printf(bio_err, "%s: out of memory\n", prog); + goto end; + } + + res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST); if (tmp_host != host) OPENSSL_free(tmp_host); if (tmp_port != port) OPENSSL_free(tmp_port); if (!res) { BIO_printf(bio_err, - "%s: -connect argument or target parameter malformed or ambiguous\n", - prog); + "%s: -proxy argument malformed or ambiguous\n", prog); goto end; } } @@ -1661,7 +1607,17 @@ #endif if (!app_passwd(passarg, NULL, &pass, NULL)) { - BIO_printf(bio_err, "Error getting password\n"); + BIO_printf(bio_err, "Error getting private key password\n"); + goto end; + } + + if (!app_passwd(proxypassarg, NULL, &proxypass, NULL)) { + BIO_printf(bio_err, "Error getting proxy password\n"); + goto end; + } + + if (proxypass != NULL && proxyuser == NULL) { + BIO_printf(bio_err, "Error: Must specify proxy_user with proxy_pass\n"); goto end; } @@ -1670,35 +1626,28 @@ if (key_file != NULL) { key = load_key(key_file, key_format, 0, pass, e, - "client certificate private key file"); - if (key == NULL) { - ERR_print_errors(bio_err); + "client certificate private key"); + if (key == NULL) goto end; - } } if (cert_file != NULL) { - cert = load_cert(cert_file, cert_format, "client certificate file"); - if (cert == NULL) { - ERR_print_errors(bio_err); + cert = load_cert_pass(cert_file, cert_format, 1, pass, + "client certificate"); + if (cert == NULL) goto end; - } } if (chain_file != NULL) { - if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL, - "client certificate chain")) + if (!load_certs(chain_file, 0, &chain, pass, "client certificate chain")) goto end; } if (crl_file != NULL) { X509_CRL *crl; - crl = load_crl(crl_file, crl_format); - if (crl == NULL) { - BIO_puts(bio_err, "Error loading CRL\n"); - ERR_print_errors(bio_err); + crl = load_crl(crl_file, crl_format, 0, "CRL"); + if (crl == NULL) goto end; - } crls = sk_X509_CRL_new_null(); if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { BIO_puts(bio_err, "Error adding CRL\n"); @@ -1714,10 +1663,21 @@ if (bio_c_out == NULL) { if (c_quiet && !c_debug) { bio_c_out = BIO_new(BIO_s_null()); - if (c_msg && bio_c_msg == NULL) + if (c_msg && bio_c_msg == NULL) { bio_c_msg = dup_bio_out(FORMAT_TEXT); - } else if (bio_c_out == NULL) + if (bio_c_msg == NULL) { + BIO_printf(bio_err, "Out of memory\n"); + goto end; + } + } + } else { bio_c_out = dup_bio_out(FORMAT_TEXT); + } + + if (bio_c_out == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto end; + } } #ifndef OPENSSL_NO_SRP if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) { @@ -1726,7 +1686,7 @@ } #endif - ctx = SSL_CTX_new(meth); + ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; @@ -1761,6 +1721,9 @@ && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) goto end; + if (ignore_unexpected_eof) + SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); + if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { BIO_printf(bio_err, "Error setting verify params\n"); ERR_print_errors(bio_err); @@ -1804,7 +1767,9 @@ goto end; } - if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, + if (!ssl_load_stores(ctx, + vfyCApath, vfyCAfile, vfyCAstore, + chCApath, chCAfile, chCAstore, crls, crl_download)) { BIO_printf(bio_err, "Error loading store locations\n"); ERR_print_errors(bio_err); @@ -1826,10 +1791,10 @@ if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { BIO_puts(bio_err, "Error setting client auth engine\n"); ERR_print_errors(bio_err); - ENGINE_free(ssl_client_engine); + release_engine(ssl_client_engine); goto end; } - ENGINE_free(ssl_client_engine); + release_engine(ssl_client_engine); } #endif @@ -1933,7 +1898,8 @@ SSL_CTX_set_verify(ctx, verify, verify_callback); - if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { + if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) { ERR_print_errors(bio_err); goto end; } @@ -1948,21 +1914,10 @@ SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); } -# ifndef OPENSSL_NO_SRP - if (srp_arg.srplogin) { - if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) { - BIO_printf(bio_err, "Unable to set SRP username\n"); - goto end; - } - srp_arg.msg = c_msg; - srp_arg.debug = c_debug; - SSL_CTX_set_srp_cb_arg(ctx, &srp_arg); - SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb); - SSL_CTX_set_srp_strength(ctx, srp_arg.strength); - if (c_msg || c_debug || srp_arg.amp == 0) - SSL_CTX_set_srp_verify_param_callback(ctx, - ssl_srp_verify_param_cb); - } +#ifndef OPENSSL_NO_SRP + if (srp_arg.srplogin != NULL + && !set_up_srp_arg(ctx, &srp_arg, srp_lateuser, c_msg, c_debug)) + goto end; # endif if (dane_tlsa_domain != NULL) { @@ -2023,7 +1978,7 @@ if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) { if (servername == NULL) { - if(host == NULL || is_dNS_name(host)) + if(host == NULL || is_dNS_name(host)) servername = (host == NULL) ? "localhost" : host; } if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) { @@ -2059,16 +2014,16 @@ } re_start: - if (init_client(&s, host, port, bindhost, bindport, socket_family, + if (init_client(&sock, host, port, bindhost, bindport, socket_family, socket_type, protocol) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); - BIO_closesocket(s); + BIO_closesocket(sock); goto end; } - BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); + BIO_printf(bio_c_out, "CONNECTED(%08X)\n", sock); if (c_nbio) { - if (!BIO_socket_nbio(s, 1)) { + if (!BIO_socket_nbio(sock, 1)) { ERR_print_errors(bio_err); goto end; } @@ -2080,21 +2035,23 @@ #ifndef OPENSSL_NO_SCTP if (protocol == IPPROTO_SCTP) - sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); + sbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE); else #endif - sbio = BIO_new_dgram(s, BIO_NOCLOSE); + sbio = BIO_new_dgram(sock, BIO_NOCLOSE); - if ((peer_info.addr = BIO_ADDR_new()) == NULL) { + if (sbio == NULL || (peer_info.addr = BIO_ADDR_new()) == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); - BIO_closesocket(s); + BIO_free(sbio); + BIO_closesocket(sock); goto end; } - if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) { + if (!BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &peer_info)) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); + BIO_free(sbio); BIO_ADDR_free(peer_info.addr); - BIO_closesocket(s); + BIO_closesocket(sock); goto end; } @@ -2131,17 +2088,29 @@ } } else #endif /* OPENSSL_NO_DTLS */ - sbio = BIO_new_socket(s, BIO_NOCLOSE); + sbio = BIO_new_socket(sock, BIO_NOCLOSE); + + if (sbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + ERR_print_errors(bio_err); + BIO_closesocket(sock); + goto end; + } if (nbio_test) { BIO *test; test = BIO_new(BIO_f_nbio_test()); + if (test == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + BIO_free(sbio); + goto shut; + } sbio = BIO_push(test, sbio); } if (c_debug) { - BIO_set_callback(sbio, bio_dump_callback); + BIO_set_callback_ex(sbio, bio_dump_callback); BIO_set_callback_arg(sbio, (char *)bio_c_out); } if (c_msg) { @@ -2186,6 +2155,13 @@ sbuf_len = 0; sbuf_off = 0; + if (proxystr != NULL) { + /* Here we must use the connect string target host & port */ + if (!OSSL_HTTP_proxy_connect(sbio, thost, tport, proxyuser, proxypass, + 0 /* no timeout */, bio_err, prog)) + goto shut; + } + switch ((PROTOCOL_CHOICE) starttls_proto) { case PROTO_OFF: break; @@ -2203,6 +2179,10 @@ int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); + if (fbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto shut; + } BIO_push(fbio, sbio); /* Wait for multi-line response to end from LMTP or SMTP */ do { @@ -2251,6 +2231,10 @@ int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); + if (fbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto shut; + } BIO_push(fbio, sbio); BIO_gets(fbio, mbuf, BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ @@ -2278,6 +2262,10 @@ { BIO *fbio = BIO_new(BIO_f_buffer()); + if (fbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto shut; + } BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { @@ -2361,64 +2349,15 @@ goto shut; } break; - case PROTO_CONNECT: - { - enum { - error_proto, /* Wrong protocol, not even HTTP */ - error_connect, /* CONNECT failed */ - success - } foundit = error_connect; - BIO *fbio = BIO_new(BIO_f_buffer()); - - BIO_push(fbio, sbio); - BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr); - (void)BIO_flush(fbio); - /* - * The first line is the HTTP response. According to RFC 7230, - * it's formatted exactly like this: - * - * HTTP/d.d ddd Reason text\r\n - */ - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); - if (mbuf_len < (int)strlen("HTTP/1.0 200")) { - BIO_printf(bio_err, - "%s: HTTP CONNECT failed, insufficient response " - "from proxy (got %d octets)\n", prog, mbuf_len); - (void)BIO_flush(fbio); - BIO_pop(fbio); - BIO_free(fbio); - goto shut; - } - if (mbuf[8] != ' ') { - BIO_printf(bio_err, - "%s: HTTP CONNECT failed, incorrect response " - "from proxy\n", prog); - foundit = error_proto; - } else if (mbuf[9] != '2') { - BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog, - &mbuf[9]); - } else { - foundit = success; - } - if (foundit != error_proto) { - /* Read past all following headers */ - do { - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); - } while (mbuf_len > 2); - } - (void)BIO_flush(fbio); - BIO_pop(fbio); - BIO_free(fbio); - if (foundit != success) { - goto shut; - } - } - break; case PROTO_IRC: { int numeric; BIO *fbio = BIO_new(BIO_f_buffer()); + if (fbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto end; + } BIO_push(fbio, sbio); BIO_printf(fbio, "STARTTLS\r\n"); (void)BIO_flush(fbio); @@ -2579,17 +2518,25 @@ int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); + if (fbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto end; + } BIO_push(fbio, sbio); BIO_gets(fbio, mbuf, BUFSIZZ); /* STARTTLS command requires CAPABILITIES... */ BIO_printf(fbio, "CAPABILITIES\r\n"); (void)BIO_flush(fbio); - /* wait for multi-line CAPABILITIES response */ - do { - mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); - if (strstr(mbuf, "STARTTLS")) - foundit = 1; - } while (mbuf_len > 1 && mbuf[0] != '.'); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* no point in trying to parse the CAPABILITIES response if there is none */ + if (strstr(mbuf, "101") != NULL) { + /* wait for multi-line CAPABILITIES response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } while (mbuf_len > 1 && mbuf[0] != '.'); + } (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); @@ -2615,6 +2562,10 @@ int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); + if (fbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + goto end; + } BIO_push(fbio, sbio); /* wait for multi-line response to end from Sieve */ do { @@ -2674,8 +2625,9 @@ BIO *ldapbio = BIO_new(BIO_s_mem()); CONF *cnf = NCONF_new(NULL); - if (cnf == NULL) { + if (ldapbio == NULL || cnf == NULL) { BIO_free(ldapbio); + NCONF_free(cnf); goto end; } BIO_puts(ldapbio, ldap_tls_genconf); @@ -2784,7 +2736,6 @@ tty_on = 1; if (in_init) { in_init = 0; - if (c_brief) { BIO_puts(bio_err, "CONNECTION ESTABLISHED\n"); print_ssl_summary(con); @@ -3080,22 +3031,14 @@ BIO_printf(bio_err, "RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len = 0; - } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) + } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) && cmdletters) { BIO_printf(bio_err, "KEYUPDATE\n"); SSL_key_update(con, cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED : SSL_KEY_UPDATE_NOT_REQUESTED); cbuf_len = 0; - } -#ifndef OPENSSL_NO_HEARTBEATS - else if ((!c_ign_eof) && (cbuf[0] == 'B' && cmdletters)) { - BIO_printf(bio_err, "HEARTBEATING\n"); - SSL_heartbeat(con); - cbuf_len = 0; - } -#endif - else { + } else { cbuf_len = i; cbuf_off = 0; #ifdef CHARSET_EBCDIC @@ -3108,7 +3051,6 @@ } } - ret = 0; shut: if (in_init) print_stuff(bio_c_out, con, full_log); @@ -3134,8 +3076,8 @@ timeout.tv_usec = 500000; /* some extreme round-trip */ do { FD_ZERO(&readfds); - openssl_fdset(s, &readfds); - } while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0 + openssl_fdset(sock, &readfds); + } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 && BIO_read(sbio, sbuf, BUFSIZZ) > 0); BIO_closesocket(SSL_get_fd(con)); @@ -3166,6 +3108,8 @@ OPENSSL_free(bindport); OPENSSL_free(host); OPENSSL_free(port); + OPENSSL_free(thost); + OPENSSL_free(tport); X509_VERIFY_PARAM_free(vpm); ssl_excert_free(exc); sk_OPENSSL_STRING_free(ssl_args); @@ -3174,6 +3118,7 @@ OPENSSL_clear_free(cbuf, BUFSIZZ); OPENSSL_clear_free(sbuf, BUFSIZZ); OPENSSL_clear_free(mbuf, BUFSIZZ); + clear_free(proxypass); release_engine(e); BIO_free(bio_c_out); bio_c_out = NULL; @@ -3187,6 +3132,7 @@ X509 *peer = NULL; STACK_OF(X509) *sk; const SSL_CIPHER *c; + EVP_PKEY *public_key; int i, istls13 = (SSL_version(s) == TLS1_3_VERSION); long verify_result; #ifndef OPENSSL_NO_COMP @@ -3212,13 +3158,26 @@ BIO_printf(bio, " i:"); X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt()); BIO_puts(bio, "\n"); + public_key = X509_get_pubkey(sk_X509_value(sk, i)); + if (public_key != NULL) { + BIO_printf(bio, " a:PKEY: %s, %d (bit); sigalg: %s\n", + OBJ_nid2sn(EVP_PKEY_get_base_id(public_key)), + EVP_PKEY_get_bits(public_key), + OBJ_nid2sn(X509_get_signature_nid(sk_X509_value(sk, i)))); + EVP_PKEY_free(public_key); + } + BIO_printf(bio, " v:NotBefore: "); + ASN1_TIME_print(bio, X509_get0_notBefore(sk_X509_value(sk, i))); + BIO_printf(bio, "; NotAfter: "); + ASN1_TIME_print(bio, X509_get0_notAfter(sk_X509_value(sk, i))); + BIO_puts(bio, "\n"); if (c_showcerts) PEM_write_bio_X509(bio, sk_X509_value(sk, i)); } } BIO_printf(bio, "---\n"); - peer = SSL_get_peer_certificate(s); + peer = SSL_get0_peer_certificate(s); if (peer != NULL) { BIO_printf(bio, "Server certificate\n"); @@ -3283,7 +3242,7 @@ pktmp = X509_get0_pubkey(peer); BIO_printf(bio, "Server public key is %d bit\n", - EVP_PKEY_bits(pktmp)); + EVP_PKEY_get_bits(pktmp)); } BIO_printf(bio, "Secure Renegotiation IS%s supported\n", SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); @@ -3295,9 +3254,14 @@ BIO_printf(bio, "Expansion: %s\n", expansion ? SSL_COMP_get_name(expansion) : "NONE"); #endif +#ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_send(SSL_get_wbio(s))) + BIO_printf(bio_err, "Using Kernel TLS for sending\n"); + if (BIO_get_ktls_recv(SSL_get_rbio(s))) + BIO_printf(bio_err, "Using Kernel TLS for receiving\n"); +#endif -#ifdef SSL_DEBUG - { + if (OSSL_TRACE_ENABLED(TLS)) { /* Print out local port of connection: useful for debugging */ int sock; union BIO_sock_info_u info; @@ -3310,7 +3274,6 @@ } BIO_ADDR_free(info.addr); } -#endif #if !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto.status != -1) { @@ -3379,11 +3342,11 @@ BIO_printf(bio, " Label: '%s'\n", keymatexportlabel); BIO_printf(bio, " Length: %i bytes\n", keymatexportlen); exportedkeymat = app_malloc(keymatexportlen, "export key"); - if (!SSL_export_keying_material(s, exportedkeymat, + if (SSL_export_keying_material(s, exportedkeymat, keymatexportlen, keymatexportlabel, strlen(keymatexportlabel), - NULL, 0, 0)) { + NULL, 0, 0) <= 0) { BIO_printf(bio, " Error\n"); } else { BIO_printf(bio, " Keying material: "); @@ -3394,7 +3357,6 @@ OPENSSL_free(exportedkeymat); } BIO_printf(bio, "---\n"); - X509_free(peer); /* flush, or debugging output gets mixed with http response */ (void)BIO_flush(bio); } @@ -3510,7 +3472,7 @@ } /* - * Host dNS Name verifier: used for checking that the hostname is in dNS format + * Host dNS Name verifier: used for checking that the hostname is in dNS format * before setting it as SNI */ static int is_dNS_name(const char *host) diff --git a/apps/s_server.c b/apps/s_server.c --- a/apps/s_server.c +++ b/apps/s_server.c @@ -3,7 +3,7 @@ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -21,6 +21,7 @@ #include #include #include +#include #ifndef OPENSSL_NO_SOCK @@ -47,12 +48,7 @@ #ifndef OPENSSL_NO_DH # include #endif -#ifndef OPENSSL_NO_RSA -# include -#endif -#ifndef OPENSSL_NO_SRP -# include -#endif +#include #include "s_apps.h" #include "timeouts.h" #ifdef CHARSET_EBCDIC @@ -71,9 +67,6 @@ unsigned int *id_len); static void init_session_cache_ctx(SSL_CTX *sctx); static void free_sessions(void); -#ifndef OPENSSL_NO_DH -static DH *load_dh_param(const char *dhfile); -#endif static void print_connection_info(SSL *con); static const int bufsize = 16 * 1024; @@ -103,6 +96,8 @@ static int async = 0; +static int use_sendfile = 0; + static const char *session_id_prefix = NULL; #ifndef OPENSSL_NO_DTLS @@ -123,6 +118,8 @@ static char *psk_identity = "Client_identity"; char *psk_key = NULL; /* by default PSK is not used */ +static char http_server_binmode = 0; /* for now: 0/1 = default/binary */ + #ifndef OPENSSL_NO_PSK static unsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk, @@ -241,56 +238,7 @@ } #ifndef OPENSSL_NO_SRP -/* This is a context that we pass to callbacks */ -typedef struct srpsrvparm_st { - char *login; - SRP_VBASE *vb; - SRP_user_pwd *user; -} srpsrvparm; static srpsrvparm srp_callback_parm; - -/* - * This callback pretends to require some asynchronous logic in order to - * obtain a verifier. When the callback is called for a new connection we - * return with a negative value. This will provoke the accept etc to return - * with an LOOKUP_X509. The main logic of the reinvokes the suspended call - * (which would normally occur after a worker has finished) and we set the - * user parameters. - */ -static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) -{ - srpsrvparm *p = (srpsrvparm *) arg; - int ret = SSL3_AL_FATAL; - - if (p->login == NULL && p->user == NULL) { - p->login = SSL_get_srp_username(s); - BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); - return -1; - } - - if (p->user == NULL) { - BIO_printf(bio_err, "User %s doesn't exist\n", p->login); - goto err; - } - - if (SSL_set_srp_server_param - (s, p->user->N, p->user->g, p->user->s, p->user->v, - p->user->info) < 0) { - *ad = SSL_AD_INTERNAL_ERROR; - goto err; - } - BIO_printf(bio_err, - "SRP parameters set: username = \"%s\" info=\"%s\" \n", - p->login, p->user->info); - ret = SSL_ERROR_NONE; - - err: - SRP_user_pwd_free(p->user); - p->user = NULL; - p->login = NULL; - return ret; -} - #endif static int local_argc = 0; @@ -476,7 +424,7 @@ BIO_printf(p->biodebug, "Hostname in TLS extension: \""); while ((uc = *cp++) != 0) BIO_printf(p->biodebug, - isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc); + (((uc) & ~127) == 0) && isprint(uc) ? "%c" : "\\x%02x", uc); BIO_printf(p->biodebug, "\"\n"); } @@ -484,7 +432,7 @@ return SSL_TLSEXT_ERR_NOACK; if (servername != NULL) { - if (strcasecmp(servername, p->servername)) + if (OPENSSL_strcasecmp(servername, p->servername)) return p->extension_error; if (ctx2 != NULL) { BIO_printf(p->biodebug, "Switching server context.\n"); @@ -501,6 +449,7 @@ char *respin; /* Default responder to use */ char *host, *path, *port; + char *proxy, *no_proxy; int use_ssl; int verbose; } tlsextstatusctx; @@ -520,6 +469,7 @@ OCSP_RESPONSE **resp) { char *host = NULL, *port = NULL, *path = NULL; + char *proxy = NULL, *no_proxy = NULL; int use_ssl; STACK_OF(OPENSSL_STRING) *aia = NULL; X509 *x = NULL; @@ -535,8 +485,8 @@ x = SSL_get_certificate(s); aia = X509_get1_ocsp(x); if (aia != NULL) { - if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), - &host, &port, &path, &use_ssl)) { + if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &use_ssl, + NULL, &host, &port, NULL, &path, NULL, NULL)) { BIO_puts(bio_err, "cert_status: can't parse AIA URL\n"); goto err; } @@ -554,6 +504,8 @@ port = srctx->port; use_ssl = srctx->use_ssl; } + proxy = srctx->proxy; + no_proxy = srctx->no_proxy; inctx = X509_STORE_CTX_new(); if (inctx == NULL) @@ -585,8 +537,8 @@ if (!OCSP_REQUEST_add_ext(req, ext, -1)) goto err; } - *resp = process_responder(req, host, path, port, use_ssl, NULL, - srctx->timeout); + *resp = process_responder(req, host, port, path, proxy, no_proxy, + use_ssl, NULL /* headers */, srctx->timeout); if (*resp == NULL) { BIO_puts(bio_err, "cert_status: error querying responder\n"); goto done; @@ -716,7 +668,7 @@ if (SSL_select_next_proto ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_ALERT_FATAL; } if (!s_quiet) { @@ -735,7 +687,8 @@ } typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, + OPT_COMMON, + OPT_ENGINE, OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT, OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM, @@ -744,9 +697,12 @@ OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE, OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, - OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF, + OPT_VERIFYCAFILE, + OPT_CASTORE, OPT_NOCASTORE, OPT_CHAINCASTORE, OPT_VERIFYCASTORE, + OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF, OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE, - OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE, + OPT_STATUS_TIMEOUT, OPT_PROXY, OPT_NO_PROXY, OPT_STATUS_URL, + OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE, OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE, OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK, @@ -756,132 +712,154 @@ OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS, OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, - OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, + OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, OPT_SENDFILE, OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA, OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG, + OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF, OPT_R_ENUM, OPT_S_ENUM, OPT_V_ENUM, - OPT_X_ENUM + OPT_X_ENUM, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS s_server_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"ssl_config", OPT_SSL_CONFIG, 's', + "Configure SSL_CTX using the given configuration value"}, +#ifndef OPENSSL_NO_SSL_TRACE + {"trace", OPT_TRACE, '-', "trace protocol messages"}, +#endif +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Network"), {"port", OPT_PORT, 'p', "TCP/IP port to listen on for connections (default is " PORT ")"}, {"accept", OPT_ACCEPT, 's', "TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"}, #ifdef AF_UNIX {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"}, + {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"}, #endif {"4", OPT_4, '-', "Use IPv4 only"}, {"6", OPT_6, '-', "Use IPv6 only"}, -#ifdef AF_UNIX - {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"}, -#endif + + OPT_SECTION("Identity"), {"context", OPT_CONTEXT, 's', "Set session ID context"}, + {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"}, + {"no-CAfile", OPT_NOCAFILE, '-', + "Do not load the default certificates file"}, + {"no-CApath", OPT_NOCAPATH, '-', + "Do not load certificates from the default certificates directory"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store URI"}, + {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"}, {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"}, {"Verify", OPT_UPPER_V_VERIFY, 'n', "Turn on peer certificate verification, must have a cert"}, - {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, - {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"}, + {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"}, + {"cert", OPT_CERT, '<', "Server certificate file to use; default " TEST_CERT}, + {"cert2", OPT_CERT2, '<', + "Certificate file to use for servername; default " TEST_CERT2}, + {"certform", OPT_CERTFORM, 'F', + "Server certificate file format (PEM/DER/P12); has no effect"}, + {"cert_chain", OPT_CERT_CHAIN, '<', + "Server certificate chain file in PEM format"}, + {"build_chain", OPT_BUILD_CHAIN, '-', "Build server certificate chain"}, {"serverinfo", OPT_SERVERINFO, 's', "PEM serverinfo file for certificate"}, - {"certform", OPT_CERTFORM, 'F', - "Certificate format (PEM or DER) PEM default"}, {"key", OPT_KEY, 's', - "Private Key if not in -cert; default is " TEST_CERT}, - {"keyform", OPT_KEYFORM, 'f', - "Key format (PEM, DER or ENGINE) PEM default"}, - {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, + "Private key file to use; default is -cert file or else" TEST_CERT}, + {"key2", OPT_KEY2, '<', + "-Private Key file to use for servername if not in -cert2"}, + {"keyform", OPT_KEYFORM, 'f', "Key format (ENGINE, other values ignored)"}, + {"pass", OPT_PASS, 's', "Private key and cert file pass phrase source"}, {"dcert", OPT_DCERT, '<', - "Second certificate file to use (usually for DSA)"}, - {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"}, + "Second server certificate file to use (usually for DSA)"}, {"dcertform", OPT_DCERTFORM, 'F', - "Second certificate format (PEM or DER) PEM default"}, + "Second server certificate file format (PEM/DER/P12); has no effect"}, + {"dcert_chain", OPT_DCERT_CHAIN, '<', + "second server certificate chain file in PEM format"}, {"dkey", OPT_DKEY, '<', "Second private key file to use (usually for DSA)"}, {"dkeyform", OPT_DKEYFORM, 'F', - "Second key format (PEM, DER or ENGINE) PEM default"}, - {"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"}, + "Second key file format (ENGINE, other values ignored)"}, + {"dpass", OPT_DPASS, 's', + "Second private key and cert file pass phrase source"}, + {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"}, + {"servername", OPT_SERVERNAME, 's', + "Servername for HostName TLS extension"}, + {"servername_fatal", OPT_SERVERNAME_FATAL, '-', + "On servername mismatch send fatal alert (default warning alert)"}, {"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"}, {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, - {"debug", OPT_DEBUG, '-', "Print more output"}, - {"msg", OPT_MSG, '-', "Show protocol messages"}, - {"msgfile", OPT_MSGFILE, '>', - "File to send output of -msg or -trace, instead of stdout"}, - {"state", OPT_STATE, '-', "Print the SSL states"}, - {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, - {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, - {"no-CAfile", OPT_NOCAFILE, '-', - "Do not load the default certificates file"}, - {"no-CApath", OPT_NOCAPATH, '-', - "Do not load certificates from the default certificates directory"}, - {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"}, {"quiet", OPT_QUIET, '-', "No server output"}, {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-', "Disable caching and tickets if ephemeral (EC)DH is used"}, {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"}, {"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"}, - {"servername", OPT_SERVERNAME, 's', - "Servername for HostName TLS extension"}, - {"servername_fatal", OPT_SERVERNAME_FATAL, '-', - "mismatch send fatal alert (default warning alert)"}, - {"cert2", OPT_CERT2, '<', - "Certificate file to use for servername; default is" TEST_CERT2}, - {"key2", OPT_KEY2, '<', - "-Private Key file to use for servername if not in -cert2"}, + {"ignore_unexpected_eof", OPT_IGNORE_UNEXPECTED_EOF, '-', + "Do not treat lack of close_notify from a peer as an error"}, {"tlsextdebug", OPT_TLSEXTDEBUG, '-', "Hex dump of all TLS extensions received"}, {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"}, {"id_prefix", OPT_ID_PREFIX, 's', "Generate SSL/TLS session IDs prefixed by arg"}, - OPT_R_OPTIONS, {"keymatexport", OPT_KEYMATEXPORT, 's', "Export keying material using label"}, {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', - "Export len bytes of keying material (default 20)"}, + "Export len bytes of keying material; default 20"}, {"CRL", OPT_CRL, '<', "CRL file to use"}, + {"CRLform", OPT_CRLFORM, 'F', "CRL file format (PEM or DER); default PEM"}, {"crl_download", OPT_CRL_DOWNLOAD, '-', - "Download CRL from distribution points"}, - {"cert_chain", OPT_CERT_CHAIN, '<', - "certificate chain file in PEM format"}, - {"dcert_chain", OPT_DCERT_CHAIN, '<', - "second certificate chain file in PEM format"}, + "Download CRLs from distribution points in certificate CDP entries"}, + {"chainCAfile", OPT_CHAINCAFILE, '<', + "CA file for certificate chain (PEM format)"}, {"chainCApath", OPT_CHAINCAPATH, '/', "use dir as certificate store path to build CA certificate chain"}, + {"chainCAstore", OPT_CHAINCASTORE, ':', + "use URI as certificate store to build CA certificate chain"}, + {"verifyCAfile", OPT_VERIFYCAFILE, '<', + "CA file for certificate verification (PEM format)"}, {"verifyCApath", OPT_VERIFYCAPATH, '/', "use dir as certificate store path to verify CA certificate"}, + {"verifyCAstore", OPT_VERIFYCASTORE, ':', + "use URI as certificate store to verify CA certificate"}, {"no_cache", OPT_NO_CACHE, '-', "Disable session cache"}, {"ext_cache", OPT_EXT_CACHE, '-', - "Disable internal cache, setup and use external cache"}, - {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, + "Disable internal cache, set up and use external cache"}, {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', "Close connection on verification error"}, {"verify_quiet", OPT_VERIFY_QUIET, '-', "No verify output except verify errors"}, - {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, - {"chainCAfile", OPT_CHAINCAFILE, '<', - "CA file for certificate chain (PEM format)"}, - {"verifyCAfile", OPT_VERIFYCAFILE, '<', - "CA file for certificate verification (PEM format)"}, - {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"}, - {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"}, + {"ign_eof", OPT_IGN_EOF, '-', "Ignore input EOF (default when -quiet)"}, + {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input EOF"}, + #ifndef OPENSSL_NO_OCSP + OPT_SECTION("OCSP"), {"status", OPT_STATUS, '-', "Request certificate status from server"}, {"status_verbose", OPT_STATUS_VERBOSE, '-', "Print more output in certificate status callback"}, {"status_timeout", OPT_STATUS_TIMEOUT, 'n', "Status request responder timeout"}, {"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"}, + {"proxy", OPT_PROXY, 's', + "[http[s]://]host[:port][/path] of HTTP(S) proxy to use; path is ignored"}, + {"no_proxy", OPT_NO_PROXY, 's', + "List of addresses of servers not to use HTTP(S) proxy for"}, + {OPT_MORE_STR, 0, 0, + "Default from environment variable 'no_proxy', else 'NO_PROXY', else none"}, {"status_file", OPT_STATUS_FILE, '<', "File containing DER encoded OCSP Response"}, #endif -#ifndef OPENSSL_NO_SSL_TRACE - {"trace", OPT_TRACE, '-', "trace protocol messages"}, -#endif + + OPT_SECTION("Debug"), {"security_debug", OPT_SECURITY_DEBUG, '-', "Print output from SSL/TLS security framework"}, {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', @@ -889,21 +867,29 @@ {"brief", OPT_BRIEF, '-', "Restrict output to brief summary of connection parameters"}, {"rev", OPT_REV, '-', - "act as a simple test server which just sends back with the received text reversed"}, + "act as an echo server that sends back received text reversed"}, + {"debug", OPT_DEBUG, '-', "Print more output"}, + {"msg", OPT_MSG, '-', "Show protocol messages"}, + {"msgfile", OPT_MSGFILE, '>', + "File to send output of -msg or -trace, instead of stdout"}, + {"state", OPT_STATE, '-', "Print the SSL states"}, {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"}, - {"ssl_config", OPT_SSL_CONFIG, 's', - "Configure SSL_CTX using the configuration 'val'"}, - {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, - {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', - "Size used to split data for encrypt pipelines"}, {"max_pipelines", OPT_MAX_PIPELINES, 'p', "Maximum number of encrypt/decrypt pipelines to be used"}, + {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"}, + {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, + + OPT_SECTION("Network"), + {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, + {"mtu", OPT_MTU, 'p', "Set link-layer MTU"}, {"read_buf", OPT_READ_BUF, 'p', "Default read buffer size to be used for connections"}, - OPT_S_OPTIONS, - OPT_V_OPTIONS, - OPT_X_OPTIONS, - {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, + {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', + "Size used to split data for encrypt pipelines"}, + {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, + + OPT_SECTION("Server identity"), {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"}, #ifndef OPENSSL_NO_PSK {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"}, @@ -911,10 +897,25 @@ {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, #ifndef OPENSSL_NO_SRP - {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"}, + {"srpvfile", OPT_SRPVFILE, '<', "(deprecated) The verifier file for SRP"}, {"srpuserseed", OPT_SRPUSERSEED, 's', - "A seed string for a default user salt"}, + "(deprecated) A seed string for a default user salt"}, #endif + + OPT_SECTION("Protocol and version"), + {"max_early_data", OPT_MAX_EARLY, 'n', + "The maximum number of bytes of early data as advertised in tickets"}, + {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n', + "The maximum number of bytes of early data (hard limit)"}, + {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, + {"num_tickets", OPT_S_NUM_TICKETS, 'n', + "The number of TLSv1.3 session tickets that a server will automatically issue" }, + {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"}, + {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"}, + {"http_server_binmode", OPT_HTTP_SERVER_BINMODE, '-', "opening files in binary mode when acting as http server (-WWW and -HTTP)"}, + {"no_ca_names", OPT_NOCANAMES, '-', + "Disable TLS Extension CA Names"}, + {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"}, #ifndef OPENSSL_NO_SSL3 {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"}, #endif @@ -932,12 +933,9 @@ #endif #ifndef OPENSSL_NO_DTLS {"dtls", OPT_DTLS, '-', "Use any DTLS version"}, - {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, - {"mtu", OPT_MTU, 'p', "Set link layer MTU"}, {"listen", OPT_LISTEN, '-', "Listen for a DTLS ClientHello with a cookie and then connect"}, #endif - {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"}, #ifndef OPENSSL_NO_DTLS1 {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"}, #endif @@ -948,33 +946,27 @@ {"sctp", OPT_SCTP, '-', "Use SCTP"}, {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"}, #endif -#ifndef OPENSSL_NO_DH - {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, +#ifndef OPENSSL_NO_SRTP + {"use_srtp", OPT_SRTP_PROFILES, 's', + "Offer SRTP key management with a colon-separated profile list"}, #endif + {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, #ifndef OPENSSL_NO_NEXTPROTONEG {"nextprotoneg", OPT_NEXTPROTONEG, 's', "Set the advertised protocols for the NPN extension (comma-separated list)"}, -#endif -#ifndef OPENSSL_NO_SRTP - {"use_srtp", OPT_SRTP_PROFILES, 's', - "Offer SRTP key management with a colon-separated profile list"}, #endif {"alpn", OPT_ALPN, 's', "Set the advertised protocols for the ALPN extension (comma-separated list)"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#ifndef OPENSSL_NO_KTLS + {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"}, #endif - {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, - {"max_early_data", OPT_MAX_EARLY, 'n', - "The maximum number of bytes of early data as advertised in tickets"}, - {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n', - "The maximum number of bytes of early data (hard limit)"}, - {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, - {"num_tickets", OPT_S_NUM_TICKETS, 'n', - "The number of TLSv1.3 session tickets that a server will automatically issue" }, - {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"}, - {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"}, - {NULL, OPT_EOF, 0, NULL} + + OPT_R_OPTIONS, + OPT_S_OPTIONS, + OPT_V_OPTIONS, + OPT_X_OPTIONS, + OPT_PROV_OPTIONS, + {NULL} }; #define IS_PROT_FLAG(o) \ @@ -993,28 +985,28 @@ STACK_OF(X509_CRL) *crls = NULL; X509 *s_cert = NULL, *s_dcert = NULL; X509_VERIFY_PARAM *vpm = NULL; - const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL; + const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL; + const char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL; char *dpassarg = NULL, *dpass = NULL; - char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; + char *passarg = NULL, *pass = NULL; + char *vfyCApath = NULL, *vfyCAfile = NULL, *vfyCAstore = NULL; char *crl_file = NULL, *prog; #ifdef AF_UNIX int unlink_unix_path = 0; #endif do_server_cb server_cb; int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0; -#ifndef OPENSSL_NO_DH char *dhfile = NULL; int no_dhe = 0; -#endif int nocert = 0, ret = 1; - int noCApath = 0, noCAfile = 0; - int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM; - int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; + int noCApath = 0, noCAfile = 0, noCAstore = 0; + int s_cert_format = FORMAT_UNDEF, s_key_format = FORMAT_UNDEF; + int s_dcert_format = FORMAT_UNDEF, s_dkey_format = FORMAT_UNDEF; int rev = 0, naccept = -1, sdebug = 0; int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; - int state = 0, crl_format = FORMAT_PEM, crl_download = 0; + int state = 0, crl_format = FORMAT_UNDEF, crl_download = 0; char *host = NULL; - char *port = BUF_strdup(PORT); + char *port = NULL; unsigned char *context = NULL; OPTION_CHOICE o; EVP_PKEY *s_key2 = NULL; @@ -1056,9 +1048,11 @@ const char *keylog_file = NULL; int max_early_data = -1, recv_max_early_data = -1; char *psksessf = NULL; + int no_ca_names = 0; #ifndef OPENSSL_NO_SCTP int sctp_label_bug = 0; #endif + int ignore_unexpected_eof = 0; /* Init of few remaining global variables */ local_argc = argc; @@ -1073,10 +1067,12 @@ s_quiet = 0; s_brief = 0; async = 0; + use_sendfile = 0; + port = OPENSSL_strdup(PORT); cctx = SSL_CONF_CTX_new(); vpm = X509_VERIFY_PARAM_new(); - if (cctx == NULL || vpm == NULL) + if (port == NULL || cctx == NULL || vpm == NULL) goto end; SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE); @@ -1163,7 +1159,9 @@ #ifdef AF_UNIX case OPT_UNIX: socket_family = AF_UNIX; - OPENSSL_free(host); host = BUF_strdup(opt_arg()); + OPENSSL_free(host); host = OPENSSL_strdup(opt_arg()); + if (host == NULL) + goto end; OPENSSL_free(port); port = NULL; break; case OPT_UNLINK: @@ -1209,7 +1207,7 @@ s_serverinfo_file = opt_arg(); break; case OPT_CERTFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_cert_format)) goto opthelp; break; case OPT_KEY: @@ -1226,19 +1224,17 @@ s_chain_file = opt_arg(); break; case OPT_DHPARAM: -#ifndef OPENSSL_NO_DH dhfile = opt_arg(); -#endif break; case OPT_DCERTFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dcert_format)) goto opthelp; break; case OPT_DCERT: s_dcert_file = opt_arg(); break; case OPT_DKEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dkey_format)) goto opthelp; break; case OPT_DPASS: @@ -1265,6 +1261,18 @@ case OPT_VERIFYCAPATH: vfyCApath = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; + case OPT_NOCASTORE: + noCAstore = 1; + break; + case OPT_CHAINCASTORE: + chCAstore = opt_arg(); + break; + case OPT_VERIFYCASTORE: + vfyCAstore = opt_arg(); + break; case OPT_NO_CACHE: no_cache = 1; break; @@ -1350,16 +1358,25 @@ #ifndef OPENSSL_NO_OCSP s_tlsextstatus = 1; tlscstatp.timeout = atoi(opt_arg()); +#endif + break; + case OPT_PROXY: +#ifndef OPENSSL_NO_OCSP + tlscstatp.proxy = opt_arg(); +#endif + break; + case OPT_NO_PROXY: +#ifndef OPENSSL_NO_OCSP + tlscstatp.no_proxy = opt_arg(); #endif break; case OPT_STATUS_URL: #ifndef OPENSSL_NO_OCSP s_tlsextstatus = 1; - if (!OCSP_parse_url(opt_arg(), - &tlscstatp.host, - &tlscstatp.port, - &tlscstatp.path, &tlscstatp.use_ssl)) { - BIO_printf(bio_err, "Error parsing URL\n"); + if (!OSSL_HTTP_parse_url(opt_arg(), &tlscstatp.use_ssl, NULL, + &tlscstatp.host, &tlscstatp.port, NULL, + &tlscstatp.path, NULL, NULL)) { + BIO_printf(bio_err, "Error parsing -status_url argument\n"); goto end; } #endif @@ -1375,6 +1392,10 @@ break; case OPT_MSGFILE: bio_s_msg = BIO_new_file(opt_arg(), "w"); + if (bio_s_msg == NULL) { + BIO_printf(bio_err, "Error writing file %s\n", opt_arg()); + goto end; + } break; case OPT_TRACE: #ifndef OPENSSL_NO_SSL_TRACE @@ -1400,9 +1421,7 @@ s_quiet = s_brief = verify_args.quiet = 1; break; case OPT_NO_DHE: -#ifndef OPENSSL_NO_DH no_dhe = 1; -#endif break; case OPT_NO_RESUME_EPHEMERAL: no_resume_ephemeral = 1; @@ -1529,12 +1548,18 @@ session_id_prefix = opt_arg(); break; case OPT_ENGINE: - engine = setup_engine(opt_arg(), 1); +#ifndef OPENSSL_NO_ENGINE + engine = setup_engine(opt_arg(), s_debug); +#endif break; case OPT_R_CASES: if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_SERVERNAME: tlsextcbp.servername = opt_arg(); break; @@ -1603,10 +1628,30 @@ if (max_early_data == -1) max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; break; + case OPT_HTTP_SERVER_BINMODE: + http_server_binmode = 1; + break; + case OPT_NOCANAMES: + no_ca_names = 1; + break; + case OPT_SENDFILE: +#ifndef OPENSSL_NO_KTLS + use_sendfile = 1; +#endif + break; + case OPT_IGNORE_UNEXPECTED_EOF: + ignore_unexpected_eof = 1; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); - argv = opt_rest(); + if (argc != 0) + goto opthelp; + + if (!app_RAND_load()) + goto end; #ifndef OPENSSL_NO_NEXTPROTONEG if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { @@ -1655,6 +1700,13 @@ } #endif +#ifndef OPENSSL_NO_KTLS + if (use_sendfile && www <= 1) { + BIO_printf(bio_err, "Can't use -sendfile without -WWW or -HTTP\n"); + goto end; + } +#endif + if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { BIO_printf(bio_err, "Error getting password\n"); goto end; @@ -1671,40 +1723,32 @@ if (nocert == 0) { s_key = load_key(s_key_file, s_key_format, 0, pass, engine, - "server certificate private key file"); - if (s_key == NULL) { - ERR_print_errors(bio_err); + "server certificate private key"); + if (s_key == NULL) goto end; - } - s_cert = load_cert(s_cert_file, s_cert_format, - "server certificate file"); + s_cert = load_cert_pass(s_cert_file, s_cert_format, 1, pass, + "server certificate"); - if (s_cert == NULL) { - ERR_print_errors(bio_err); + if (s_cert == NULL) goto end; - } if (s_chain_file != NULL) { - if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, + if (!load_certs(s_chain_file, 0, &s_chain, NULL, "server certificate chain")) goto end; } if (tlsextcbp.servername != NULL) { s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine, - "second server certificate private key file"); - if (s_key2 == NULL) { - ERR_print_errors(bio_err); + "second server certificate private key"); + if (s_key2 == NULL) goto end; - } - s_cert2 = load_cert(s_cert_file2, s_cert_format, - "second server certificate file"); + s_cert2 = load_cert_pass(s_cert_file2, s_cert_format, 1, pass, + "second server certificate"); - if (s_cert2 == NULL) { - ERR_print_errors(bio_err); + if (s_cert2 == NULL) goto end; - } } } #if !defined(OPENSSL_NO_NEXTPROTONEG) @@ -1723,12 +1767,9 @@ if (crl_file != NULL) { X509_CRL *crl; - crl = load_crl(crl_file, crl_format); - if (crl == NULL) { - BIO_puts(bio_err, "Error loading CRL\n"); - ERR_print_errors(bio_err); + crl = load_crl(crl_file, crl_format, 0, "CRL"); + if (crl == NULL) goto end; - } crls = sk_X509_CRL_new_null(); if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { BIO_puts(bio_err, "Error adding CRL\n"); @@ -1744,21 +1785,19 @@ s_dkey_file = s_dcert_file; s_dkey = load_key(s_dkey_file, s_dkey_format, - 0, dpass, engine, "second certificate private key file"); - if (s_dkey == NULL) { - ERR_print_errors(bio_err); + 0, dpass, engine, "second certificate private key"); + if (s_dkey == NULL) goto end; - } - s_dcert = load_cert(s_dcert_file, s_dcert_format, - "second server certificate file"); + s_dcert = load_cert_pass(s_dcert_file, s_dcert_format, 1, dpass, + "second server certificate"); if (s_dcert == NULL) { ERR_print_errors(bio_err); goto end; } if (s_dchain_file != NULL) { - if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL, + if (!load_certs(s_dchain_file, 0, &s_dchain, NULL, "second server certificate chain")) goto end; } @@ -1768,17 +1807,22 @@ if (bio_s_out == NULL) { if (s_quiet && !s_debug) { bio_s_out = BIO_new(BIO_s_null()); - if (s_msg && bio_s_msg == NULL) + if (s_msg && bio_s_msg == NULL) { bio_s_msg = dup_bio_out(FORMAT_TEXT); + if (bio_s_msg == NULL) { + BIO_printf(bio_err, "Out of memory\n"); + goto end; + } + } } else { - if (bio_s_out == NULL) - bio_s_out = dup_bio_out(FORMAT_TEXT); + bio_s_out = dup_bio_out(FORMAT_TEXT); } } -#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) - if (nocert) -#endif - { + + if (bio_s_out == NULL) + goto end; + + if (nocert) { s_cert_file = NULL; s_key_file = NULL; s_dcert_file = NULL; @@ -1787,7 +1831,7 @@ s_key_file2 = NULL; } - ctx = SSL_CTX_new(meth); + ctx = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; @@ -1809,7 +1853,6 @@ goto end; } } - #ifndef OPENSSL_NO_SCTP if (protocol == IPPROTO_SCTP && sctp_label_bug == 1) SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG); @@ -1833,7 +1876,6 @@ } BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); } - SSL_CTX_set_quiet_shutdown(ctx, 1); if (exc != NULL) ssl_ctx_set_excert(ctx, exc); @@ -1850,6 +1892,13 @@ SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); } + if (no_ca_names) { + SSL_CTX_set_options(ctx, SSL_OP_DISABLE_TLSEXT_CA_NAMES); + } + + if (ignore_unexpected_eof) + SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); + if (max_send_fragment > 0 && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", @@ -1884,7 +1933,8 @@ } #endif - if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { + if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) { ERR_print_errors(bio_err); goto end; } @@ -1896,7 +1946,9 @@ ssl_ctx_add_crls(ctx, crls, 0); - if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, + if (!ssl_load_stores(ctx, + vfyCApath, vfyCAfile, vfyCAstore, + chCApath, chCAfile, chCAstore, crls, crl_download)) { BIO_printf(bio_err, "Error loading store locations\n"); ERR_print_errors(bio_err); @@ -1904,7 +1956,7 @@ } if (s_cert2) { - ctx2 = SSL_CTX_new(meth); + ctx2 = SSL_CTX_new_ex(app_get0_libctx(), app_get0_propq(), meth); if (ctx2 == NULL) { ERR_print_errors(bio_err); goto end; @@ -1928,7 +1980,6 @@ } BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); } - SSL_CTX_set_quiet_shutdown(ctx2, 1); if (exc != NULL) ssl_ctx_set_excert(ctx2, exc); @@ -1945,8 +1996,8 @@ if (async) SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC); - if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile, - noCApath)) { + if (!ctx_set_verify_locations(ctx2, CAfile, noCAfile, CApath, + noCApath, CAstore, noCAstore)) { ERR_print_errors(bio_err); goto end; } @@ -1968,54 +2019,70 @@ if (alpn_ctx.data) SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); -#ifndef OPENSSL_NO_DH if (!no_dhe) { - DH *dh = NULL; + EVP_PKEY *dhpkey = NULL; if (dhfile != NULL) - dh = load_dh_param(dhfile); + dhpkey = load_keyparams(dhfile, FORMAT_UNDEF, 0, "DH", "DH parameters"); else if (s_cert_file != NULL) - dh = load_dh_param(s_cert_file); + dhpkey = load_keyparams_suppress(s_cert_file, FORMAT_UNDEF, 0, "DH", + "DH parameters", 1); - if (dh != NULL) { + if (dhpkey != NULL) { BIO_printf(bio_s_out, "Setting temp DH parameters\n"); } else { BIO_printf(bio_s_out, "Using default temp DH parameters\n"); } (void)BIO_flush(bio_s_out); - if (dh == NULL) { + if (dhpkey == NULL) { SSL_CTX_set_dh_auto(ctx, 1); - } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { - BIO_puts(bio_err, "Error setting temp DH parameters\n"); - ERR_print_errors(bio_err); - DH_free(dh); - goto end; + } else { + /* + * We need 2 references: one for use by ctx and one for use by + * ctx2 + */ + if (!EVP_PKEY_up_ref(dhpkey)) { + EVP_PKEY_free(dhpkey); + goto end; + } + if (!SSL_CTX_set0_tmp_dh_pkey(ctx, dhpkey)) { + BIO_puts(bio_err, "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + /* Free 2 references */ + EVP_PKEY_free(dhpkey); + EVP_PKEY_free(dhpkey); + goto end; + } } if (ctx2 != NULL) { - if (!dhfile) { - DH *dh2 = load_dh_param(s_cert_file2); - if (dh2 != NULL) { + if (dhfile != NULL) { + EVP_PKEY *dhpkey2 = load_keyparams_suppress(s_cert_file2, + FORMAT_UNDEF, + 0, "DH", + "DH parameters", 1); + + if (dhpkey2 != NULL) { BIO_printf(bio_s_out, "Setting temp DH parameters\n"); (void)BIO_flush(bio_s_out); - DH_free(dh); - dh = dh2; + EVP_PKEY_free(dhpkey); + dhpkey = dhpkey2; } } - if (dh == NULL) { + if (dhpkey == NULL) { SSL_CTX_set_dh_auto(ctx2, 1); - } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { + } else if (!SSL_CTX_set0_tmp_dh_pkey(ctx2, dhpkey)) { BIO_puts(bio_err, "Error setting temp DH parameters\n"); ERR_print_errors(bio_err); - DH_free(dh); + EVP_PKEY_free(dhpkey); goto end; } + dhpkey = NULL; } - DH_free(dh); + EVP_PKEY_free(dhpkey); } -#endif if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain)) goto end; @@ -2050,10 +2117,16 @@ SSL_CTX_set_psk_server_callback(ctx, psk_server_cb); } - if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { - BIO_printf(bio_err, "error setting PSK identity hint to context\n"); - ERR_print_errors(bio_err); - goto end; + if (psk_identity_hint != NULL) { + if (min_version == TLS1_3_VERSION) { + BIO_printf(bio_s_out, "PSK warning: there is NO identity hint in TLSv1.3\n"); + } else { + if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { + BIO_printf(bio_err, "error setting PSK identity hint to context\n"); + ERR_print_errors(bio_err); + goto end; + } + } } #endif if (psksessf != NULL) { @@ -2112,20 +2185,9 @@ #ifndef OPENSSL_NO_SRP if (srp_verifier_file != NULL) { - srp_callback_parm.vb = SRP_VBASE_new(srpuserseed); - srp_callback_parm.user = NULL; - srp_callback_parm.login = NULL; - if ((ret = - SRP_VBASE_init(srp_callback_parm.vb, - srp_verifier_file)) != SRP_NO_ERROR) { - BIO_printf(bio_err, - "Cannot initialize SRP verifier file \"%s\":ret=%d\n", - srp_verifier_file, ret); + if (!set_up_srp_verifier_file(ctx, &srp_callback_parm, srpuserseed, + srp_verifier_file)) goto end; - } - SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); - SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); - SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); } else #endif if (CAfile != NULL) { @@ -2236,8 +2298,8 @@ SSL_CTX_sess_get_cache_size(ssl_ctx)); } -static long int count_reads_callback(BIO *bio, int cmd, const char *argp, - int argi, long int argl, long int ret) +static long int count_reads_callback(BIO *bio, int cmd, const char *argp, size_t len, + int argi, long argl, int ret, size_t *processed) { unsigned int *p_counter = (unsigned int *)BIO_get_callback_arg(bio); @@ -2253,7 +2315,7 @@ if (s_debug) { BIO_set_callback_arg(bio, (char *)bio_s_out); - ret = bio_dump_callback(bio, cmd, argp, argi, argl, ret); + ret = (int)bio_dump_callback(bio, cmd, argp, len, argi, argl, ret, processed); BIO_set_callback_arg(bio, (char *)p_counter); } @@ -2321,6 +2383,11 @@ else # endif sbio = BIO_new_dgram(s, BIO_NOCLOSE); + if (sbio == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + ERR_print_errors(bio_err); + goto err; + } if (enable_timeouts) { timeout.tv_sec = 0; @@ -2370,6 +2437,13 @@ BIO *test; test = BIO_new(BIO_f_nbio_test()); + if (test == NULL) { + BIO_printf(bio_err, "Unable to create BIO\n"); + ret = -1; + BIO_free(sbio); + goto err; + } + sbio = BIO_push(test, sbio); } @@ -2377,7 +2451,7 @@ SSL_set_accept_state(con); /* SSL_set_fd(con,s); */ - BIO_set_callback(SSL_get_rbio(con), count_reads_callback); + BIO_set_callback_ex(SSL_get_rbio(con), count_reads_callback); if (s_msg) { #ifndef OPENSSL_NO_SSL_TRACE if (s_msg == 2) @@ -2536,14 +2610,6 @@ */ goto err; } -#ifndef OPENSSL_NO_HEARTBEATS - if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) { - BIO_printf(bio_err, "HEARTBEATING\n"); - SSL_heartbeat(con); - i = 0; - continue; - } -#endif if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) { SSL_renegotiate(con); i = SSL_do_handshake(con); @@ -2585,8 +2651,8 @@ continue; } if (buf[0] == 'P') { - static const char *str = "Lets print some clear text\n"; - BIO_write(SSL_get_wbio(con), str, strlen(str)); + static const char str[] = "Lets print some clear text\n"; + BIO_write(SSL_get_wbio(con), str, sizeof(str) -1); } if (buf[0] == 'S') { print_stats(bio_s_out, SSL_get_SSL_CTX(con)); @@ -2609,15 +2675,9 @@ #ifndef OPENSSL_NO_SRP while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP renego during write\n"); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); + + lookup_srp_user(&srp_callback_parm, bio_s_out); + k = SSL_write(con, &(buf[l]), (unsigned int)i); } #endif @@ -2688,7 +2748,6 @@ ret = -1; goto err; } - if (i < 0) { ret = 0; goto err; @@ -2702,15 +2761,9 @@ #ifndef OPENSSL_NO_SRP while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP renego during read\n"); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); + + lookup_srp_user(&srp_callback_parm, bio_s_out); + i = SSL_read(con, (char *)buf, bufsize); } #endif @@ -2757,7 +2810,7 @@ err: if (con != NULL) { BIO_printf(bio_s_out, "shutting down SSL\n"); - SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + do_ssl_shutdown(con); SSL_free(con); } BIO_printf(bio_s_out, "CONNECTION CLOSED\n"); @@ -2852,15 +2905,9 @@ && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP during accept %s\n", srp_callback_parm.login); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); + + lookup_srp_user(&srp_callback_parm, bio_s_out); + i = SSL_accept(con); if (i <= 0) retry = is_retryable(con, i); @@ -2909,12 +2956,11 @@ PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); - peer = SSL_get_peer_certificate(con); + peer = SSL_get0_peer_certificate(con); if (peer != NULL) { BIO_printf(bio_s_out, "Client certificate\n"); PEM_write_bio_X509(bio_s_out, peer); dump_cert_text(bio_s_out, peer); - X509_free(peer); peer = NULL; } @@ -2959,11 +3005,11 @@ BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel); BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen); exportedkeymat = app_malloc(keymatexportlen, "export key"); - if (!SSL_export_keying_material(con, exportedkeymat, + if (SSL_export_keying_material(con, exportedkeymat, keymatexportlen, keymatexportlabel, strlen(keymatexportlabel), - NULL, 0, 0)) { + NULL, 0, 0) <= 0) { BIO_printf(bio_s_out, " Error\n"); } else { BIO_printf(bio_s_out, " Keying material: "); @@ -2973,25 +3019,16 @@ } OPENSSL_free(exportedkeymat); } +#ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_send(SSL_get_wbio(con))) + BIO_printf(bio_err, "Using Kernel TLS for sending\n"); + if (BIO_get_ktls_recv(SSL_get_rbio(con))) + BIO_printf(bio_err, "Using Kernel TLS for receiving\n"); +#endif (void)BIO_flush(bio_s_out); } -#ifndef OPENSSL_NO_DH -static DH *load_dh_param(const char *dhfile) -{ - DH *ret = NULL; - BIO *bio; - - if ((bio = BIO_new_file(dhfile, "r")) == NULL) - goto err; - ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - err: - BIO_free(bio); - return ret; -} -#endif - static int www_body(int s, int stype, int prot, unsigned char *context) { char *buf = NULL; @@ -3004,12 +3041,21 @@ int total_bytes = 0; #endif int width; +#ifndef OPENSSL_NO_KTLS + int use_sendfile_for_req = use_sendfile; +#endif fd_set readfds; + const char *opmode; +#ifdef CHARSET_EBCDIC + BIO *filter; +#endif /* Set width for a select call if needed */ width = s + 1; - buf = app_malloc(bufsize, "server www buffer"); + /* as we use BIO_gets(), and it always null terminates data, we need + * to allocate 1 byte longer buffer to fit the full 2^14 byte record */ + buf = app_malloc(bufsize + 1, "server www buffer"); io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); if ((io == NULL) || (ssl_bio == NULL)) @@ -3023,7 +3069,7 @@ } /* lets make the output buffer a reasonable size */ - if (!BIO_set_write_buffer_size(io, bufsize)) + if (BIO_set_write_buffer_size(io, bufsize) <= 0) goto err; if ((con = SSL_new(ctx)) == NULL) @@ -3042,10 +3088,21 @@ } sbio = BIO_new_socket(s, BIO_NOCLOSE); + if (sbio == NULL) { + SSL_free(con); + goto err; + } + if (s_nbio_test) { BIO *test; test = BIO_new(BIO_f_nbio_test()); + if (test == NULL) { + SSL_free(con); + BIO_free(sbio); + goto err; + } + sbio = BIO_push(test, sbio); } SSL_set_bio(con, sbio, sbio); @@ -3054,12 +3111,17 @@ /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ BIO_set_ssl(ssl_bio, con, BIO_CLOSE); BIO_push(io, ssl_bio); + ssl_bio = NULL; #ifdef CHARSET_EBCDIC - io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); + filter = BIO_new(BIO_f_ebcdic_filter()); + if (filter == NULL) + goto err; + + io = BIO_push(filter, io); #endif if (s_debug) { - BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } if (s_msg) { @@ -3073,7 +3135,7 @@ } for (;;) { - i = BIO_gets(io, buf, bufsize - 1); + i = BIO_gets(io, buf, bufsize + 1); if (i < 0) { /* error */ if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) { if (!s_quiet) @@ -3085,21 +3147,13 @@ if (BIO_should_io_special(io) && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP renego during read\n"); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); + + lookup_srp_user(&srp_callback_parm, bio_s_out); + continue; } #endif -#if !defined(OPENSSL_SYS_MSDOS) - sleep(1); -#endif + ossl_sleep(1000); continue; } } else if (i == 0) { /* end of input */ @@ -3146,7 +3200,7 @@ * we're expecting to come from the client. If they haven't * sent one there's not much we can do. */ - BIO_gets(io, buf, bufsize - 1); + BIO_gets(io, buf, bufsize + 1); } BIO_puts(io, @@ -3228,12 +3282,11 @@ BIO_printf(io, "---\n"); print_stats(io, SSL_get_SSL_CTX(con)); BIO_printf(io, "---\n"); - peer = SSL_get_peer_certificate(con); + peer = SSL_get0_peer_certificate(con); if (peer != NULL) { BIO_printf(io, "Client certificate\n"); X509_print(io, peer); PEM_write_bio_X509(io, peer); - X509_free(peer); peer = NULL; } else { BIO_puts(io, "no client certificate available\n"); @@ -3304,9 +3357,10 @@ break; } - if ((file = BIO_new_file(p, "r")) == NULL) { + opmode = (http_server_binmode == 1) ? "rb" : "r"; + if ((file = BIO_new_file(p, opmode)) == NULL) { BIO_puts(io, text); - BIO_printf(io, "Error opening '%s'\r\n", p); + BIO_printf(io, "Error opening '%s' mode='%s'\r\n", p, opmode); ERR_print_errors(io); break; } @@ -3326,38 +3380,83 @@ "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); } /* send the file */ - for (;;) { - i = BIO_read(file, buf, bufsize); - if (i <= 0) - break; +#ifndef OPENSSL_NO_KTLS + if (use_sendfile_for_req && !BIO_get_ktls_send(SSL_get_wbio(con))) { + BIO_printf(bio_err, "Warning: sendfile requested but KTLS is not available\n"); + use_sendfile_for_req = 0; + } + if (use_sendfile_for_req) { + FILE *fp = NULL; + int fd; + struct stat st; + off_t offset = 0; + size_t filesize; + + BIO_get_fp(file, &fp); + fd = fileno(fp); + if (fstat(fd, &st) < 0) { + BIO_printf(io, "Error fstat '%s'\r\n", p); + ERR_print_errors(io); + goto write_error; + } -#ifdef RENEG - total_bytes += i; - BIO_printf(bio_err, "%d\n", i); - if (total_bytes > 3 * 1024) { - total_bytes = 0; - BIO_printf(bio_err, "RENEGOTIATE\n"); - SSL_renegotiate(con); + filesize = st.st_size; + if (((int)BIO_flush(io)) < 0) + goto write_error; + + for (;;) { + i = SSL_sendfile(con, fd, offset, filesize, 0); + if (i < 0) { + BIO_printf(io, "Error SSL_sendfile '%s'\r\n", p); + ERR_print_errors(io); + break; + } else { + offset += i; + filesize -= i; + } + + if (filesize <= 0) { + if (!s_quiet) + BIO_printf(bio_err, "KTLS SENDFILE '%s' OK\n", p); + + break; + } } + } else #endif + { + for (;;) { + i = BIO_read(file, buf, bufsize); + if (i <= 0) + break; - for (j = 0; j < i;) { #ifdef RENEG - static count = 0; - if (++count == 13) { + total_bytes += i; + BIO_printf(bio_err, "%d\n", i); + if (total_bytes > 3 * 1024) { + total_bytes = 0; + BIO_printf(bio_err, "RENEGOTIATE\n"); SSL_renegotiate(con); } #endif - k = BIO_write(io, &(buf[j]), i - j); - if (k <= 0) { - if (!BIO_should_retry(io) - && !SSL_waiting_for_async(con)) - goto write_error; - else { - BIO_printf(bio_s_out, "rwrite W BLOCK\n"); + + for (j = 0; j < i;) { +#ifdef RENEG + static count = 0; + if (++count == 13) + SSL_renegotiate(con); +#endif + k = BIO_write(io, &(buf[j]), i - j); + if (k <= 0) { + if (!BIO_should_retry(io) + && !SSL_waiting_for_async(con)) { + goto write_error; + } else { + BIO_printf(bio_s_out, "rwrite W BLOCK\n"); + } + } else { + j += k; } - } else { - j += k; } } } @@ -3377,10 +3476,11 @@ } end: /* make sure we re-use sessions */ - SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + do_ssl_shutdown(con); err: OPENSSL_free(buf); + BIO_free(ssl_bio); BIO_free_all(io); return ret; } @@ -3392,15 +3492,20 @@ int ret = 1; SSL *con; BIO *io, *ssl_bio, *sbio; +#ifdef CHARSET_EBCDIC + BIO *filter; +#endif - buf = app_malloc(bufsize, "server rev buffer"); + /* as we use BIO_gets(), and it always null terminates data, we need + * to allocate 1 byte longer buffer to fit the full 2^14 byte record */ + buf = app_malloc(bufsize + 1, "server rev buffer"); io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); if ((io == NULL) || (ssl_bio == NULL)) goto err; /* lets make the output buffer a reasonable size */ - if (!BIO_set_write_buffer_size(io, bufsize)) + if (BIO_set_write_buffer_size(io, bufsize) <= 0) goto err; if ((con = SSL_new(ctx)) == NULL) @@ -3419,18 +3524,29 @@ } sbio = BIO_new_socket(s, BIO_NOCLOSE); + if (sbio == NULL) { + SSL_free(con); + ERR_print_errors(bio_err); + goto err; + } + SSL_set_bio(con, sbio, sbio); SSL_set_accept_state(con); /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ BIO_set_ssl(ssl_bio, con, BIO_CLOSE); BIO_push(io, ssl_bio); + ssl_bio = NULL; #ifdef CHARSET_EBCDIC - io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); + filter = BIO_new(BIO_f_ebcdic_filter()); + if (filter == NULL) + goto err; + + io = BIO_push(filter, io); #endif if (s_debug) { - BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback); BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); } if (s_msg) { @@ -3456,15 +3572,9 @@ if (BIO_should_io_special(io) && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP renego during accept\n"); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); + + lookup_srp_user(&srp_callback_parm, bio_s_out); + continue; } #endif @@ -3473,7 +3583,7 @@ print_ssl_summary(con); for (;;) { - i = BIO_gets(io, buf, bufsize - 1); + i = BIO_gets(io, buf, bufsize + 1); if (i < 0) { /* error */ if (!BIO_should_retry(io)) { if (!s_quiet) @@ -3485,21 +3595,13 @@ if (BIO_should_io_special(io) && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { BIO_printf(bio_s_out, "LOOKUP renego during read\n"); - SRP_user_pwd_free(srp_callback_parm.user); - srp_callback_parm.user = - SRP_VBASE_get1_by_user(srp_callback_parm.vb, - srp_callback_parm.login); - if (srp_callback_parm.user) - BIO_printf(bio_s_out, "LOOKUP done %s\n", - srp_callback_parm.user->info); - else - BIO_printf(bio_s_out, "LOOKUP not successful\n"); + + lookup_srp_user(&srp_callback_parm, bio_s_out); + continue; } #endif -#if !defined(OPENSSL_SYS_MSDOS) - sleep(1); -#endif + ossl_sleep(1000); continue; } } else if (i == 0) { /* end of input */ @@ -3531,11 +3633,12 @@ } end: /* make sure we re-use sessions */ - SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + do_ssl_shutdown(con); err: OPENSSL_free(buf); + BIO_free(ssl_bio); BIO_free_all(io); return ret; } @@ -3545,6 +3648,8 @@ unsigned int *id_len) { unsigned int count = 0; + unsigned int session_id_prefix_len = strlen(session_id_prefix); + do { if (RAND_bytes(id, *id_len) <= 0) return 0; @@ -3556,8 +3661,8 @@ * conflicts. */ memcpy(id, session_id_prefix, - (strlen(session_id_prefix) < *id_len) ? - strlen(session_id_prefix) : *id_len); + (session_id_prefix_len < *id_len) ? + session_id_prefix_len : *id_len); } while (SSL_has_matching_session_id(ssl, id, *id_len) && (++count < MAX_SESSION_ID_ATTEMPTS)); @@ -3568,7 +3673,7 @@ /* * By default s_server uses an in-memory cache which caches SSL_SESSION - * structures without any serialisation. This hides some bugs which only + * structures without any serialization. This hides some bugs which only * become apparent in deployed servers. By implementing a basic external * session cache some issues can be debugged using s_server. */ diff --git a/apps/s_socket.c b/apps/s_socket.c deleted file mode 100644 --- a/apps/s_socket.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright 1995-2022 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 - */ - -/* socket-related functions used by s_client and s_server */ -#include -#include -#include -#include -#include -#include - -/* - * With IPv6, it looks like Digital has mixed up the proper order of - * recursive header file inclusion, resulting in the compiler complaining - * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is - * needed to have fileno() declared correctly... So let's define u_int - */ -#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) -# define __U_INT -typedef unsigned int u_int; -#endif - -#ifndef OPENSSL_NO_SOCK - -# include "apps.h" -# include "s_apps.h" -# include "internal/sockets.h" - -# include -# include - -/* Keep track of our peer's address for the cookie callback */ -BIO_ADDR *ourpeer = NULL; - -/* - * init_client - helper routine to set up socket communication - * @sock: pointer to storage of resulting socket. - * @host: the host name or path (for AF_UNIX) to connect to. - * @port: the port to connect to (ignored for AF_UNIX). - * @bindhost: source host or path (for AF_UNIX). - * @bindport: source port (ignored for AF_UNIX). - * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or - * AF_UNSPEC - * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM - * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any) - * - * This will create a socket and use it to connect to a host:port, or if - * family == AF_UNIX, to the path found in host. - * - * If the host has more than one address, it will try them one by one until - * a successful connection is established. The resulting socket will be - * found in *sock on success, it will be given INVALID_SOCKET otherwise. - * - * Returns 1 on success, 0 on failure. - */ -int init_client(int *sock, const char *host, const char *port, - const char *bindhost, const char *bindport, - int family, int type, int protocol) -{ - BIO_ADDRINFO *res = NULL; - BIO_ADDRINFO *bindaddr = NULL; - const BIO_ADDRINFO *ai = NULL; - const BIO_ADDRINFO *bi = NULL; - int found = 0; - int ret; - - if (BIO_sock_init() != 1) - return 0; - - ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol, - &res); - if (ret == 0) { - ERR_print_errors(bio_err); - return 0; - } - - if (bindhost != NULL || bindport != NULL) { - ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT, - family, type, protocol, &bindaddr); - if (ret == 0) { - ERR_print_errors (bio_err); - goto out; - } - } - - ret = 0; - for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { - /* Admittedly, these checks are quite paranoid, we should not get - * anything in the BIO_ADDRINFO chain that we haven't - * asked for. */ - OPENSSL_assert((family == AF_UNSPEC - || family == BIO_ADDRINFO_family(ai)) - && (type == 0 || type == BIO_ADDRINFO_socktype(ai)) - && (protocol == 0 - || protocol == BIO_ADDRINFO_protocol(ai))); - - if (bindaddr != NULL) { - for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) { - if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai)) - break; - } - if (bi == NULL) - continue; - ++found; - } - - *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai), - BIO_ADDRINFO_protocol(ai), 0); - if (*sock == INVALID_SOCKET) { - /* Maybe the kernel doesn't support the socket family, even if - * BIO_lookup() added it in the returned result... - */ - continue; - } - - if (bi != NULL) { - if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi), - BIO_SOCK_REUSEADDR)) { - BIO_closesocket(*sock); - *sock = INVALID_SOCKET; - break; - } - } - -#ifndef OPENSSL_NO_SCTP - if (protocol == IPPROTO_SCTP) { - /* - * For SCTP we have to set various options on the socket prior to - * connecting. This is done automatically by BIO_new_dgram_sctp(). - * We don't actually need the created BIO though so we free it again - * immediately. - */ - BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE); - - if (tmpbio == NULL) { - ERR_print_errors(bio_err); - return 0; - } - BIO_free(tmpbio); - } -#endif - - if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), - BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) { - BIO_closesocket(*sock); - *sock = INVALID_SOCKET; - continue; - } - - /* Success, don't try any more addresses */ - break; - } - - if (*sock == INVALID_SOCKET) { - if (bindaddr != NULL && !found) { - BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n", - BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " : - BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " : - BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "", - bindhost != NULL ? bindhost : "", - bindport != NULL ? ":" : "", - bindport != NULL ? bindport : ""); - ERR_clear_error(); - ret = 0; - } - ERR_print_errors(bio_err); - } else { - /* Remove any stale errors from previous connection attempts */ - ERR_clear_error(); - ret = 1; - } -out: - if (bindaddr != NULL) { - BIO_ADDRINFO_free (bindaddr); - } - BIO_ADDRINFO_free(res); - return ret; -} - -/* - * do_server - helper routine to perform a server operation - * @accept_sock: pointer to storage of resulting socket. - * @host: the host name or path (for AF_UNIX) to connect to. - * @port: the port to connect to (ignored for AF_UNIX). - * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or - * AF_UNSPEC - * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM - * @cb: pointer to a function that receives the accepted socket and - * should perform the communication with the connecting client. - * @context: pointer to memory that's passed verbatim to the cb function. - * @naccept: number of times an incoming connect should be accepted. If -1, - * unlimited number. - * - * This will create a socket and use it to listen to a host:port, or if - * family == AF_UNIX, to the path found in host, then start accepting - * incoming connections and run cb on the resulting socket. - * - * 0 on failure, something other on success. - */ -int do_server(int *accept_sock, const char *host, const char *port, - int family, int type, int protocol, do_server_cb cb, - unsigned char *context, int naccept, BIO *bio_s_out) -{ - int asock = 0; - int sock; - int i; - BIO_ADDRINFO *res = NULL; - const BIO_ADDRINFO *next; - int sock_family, sock_type, sock_protocol, sock_port; - const BIO_ADDR *sock_address; - int sock_family_fallback = AF_UNSPEC; - const BIO_ADDR *sock_address_fallback = NULL; - int sock_options = BIO_SOCK_REUSEADDR; - int ret = 0; - - if (BIO_sock_init() != 1) - return 0; - - if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol, - &res)) { - ERR_print_errors(bio_err); - return 0; - } - - /* Admittedly, these checks are quite paranoid, we should not get - * anything in the BIO_ADDRINFO chain that we haven't asked for */ - OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res)) - && (type == 0 || type == BIO_ADDRINFO_socktype(res)) - && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res))); - - sock_family = BIO_ADDRINFO_family(res); - sock_type = BIO_ADDRINFO_socktype(res); - sock_protocol = BIO_ADDRINFO_protocol(res); - sock_address = BIO_ADDRINFO_address(res); - next = BIO_ADDRINFO_next(res); - if (sock_family == AF_INET6) - sock_options |= BIO_SOCK_V6_ONLY; - if (next != NULL - && BIO_ADDRINFO_socktype(next) == sock_type - && BIO_ADDRINFO_protocol(next) == sock_protocol) { - if (sock_family == AF_INET - && BIO_ADDRINFO_family(next) == AF_INET6) { - /* In case AF_INET6 is returned but not supported by the - * kernel, retry with the first detected address family */ - sock_family_fallback = sock_family; - sock_address_fallback = sock_address; - sock_family = AF_INET6; - sock_address = BIO_ADDRINFO_address(next); - } else if (sock_family == AF_INET6 - && BIO_ADDRINFO_family(next) == AF_INET) { - sock_options &= ~BIO_SOCK_V6_ONLY; - } - } - - asock = BIO_socket(sock_family, sock_type, sock_protocol, 0); - if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) { - asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0); - sock_address = sock_address_fallback; - } - if (asock == INVALID_SOCKET - || !BIO_listen(asock, sock_address, sock_options)) { - BIO_ADDRINFO_free(res); - ERR_print_errors(bio_err); - if (asock != INVALID_SOCKET) - BIO_closesocket(asock); - goto end; - } - -#ifndef OPENSSL_NO_SCTP - if (protocol == IPPROTO_SCTP) { - /* - * For SCTP we have to set various options on the socket prior to - * accepting. This is done automatically by BIO_new_dgram_sctp(). - * We don't actually need the created BIO though so we free it again - * immediately. - */ - BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE); - - if (tmpbio == NULL) { - BIO_closesocket(asock); - ERR_print_errors(bio_err); - goto end; - } - BIO_free(tmpbio); - } -#endif - - sock_port = BIO_ADDR_rawport(sock_address); - - BIO_ADDRINFO_free(res); - res = NULL; - - if (sock_port == 0) { - /* dynamically allocated port, report which one */ - union BIO_sock_info_u info; - char *hostname = NULL; - char *service = NULL; - int success = 0; - - if ((info.addr = BIO_ADDR_new()) != NULL - && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info) - && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL - && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL - && BIO_printf(bio_s_out, - strchr(hostname, ':') == NULL - ? /* IPv4 */ "ACCEPT %s:%s\n" - : /* IPv6 */ "ACCEPT [%s]:%s\n", - hostname, service) > 0) - success = 1; - - (void)BIO_flush(bio_s_out); - OPENSSL_free(hostname); - OPENSSL_free(service); - BIO_ADDR_free(info.addr); - if (!success) { - BIO_closesocket(asock); - ERR_print_errors(bio_err); - goto end; - } - } else { - (void)BIO_printf(bio_s_out, "ACCEPT\n"); - (void)BIO_flush(bio_s_out); - } - - if (accept_sock != NULL) - *accept_sock = asock; - for (;;) { - char sink[64]; - struct timeval timeout; - fd_set readfds; - - if (type == SOCK_STREAM) { - BIO_ADDR_free(ourpeer); - ourpeer = BIO_ADDR_new(); - if (ourpeer == NULL) { - BIO_closesocket(asock); - ERR_print_errors(bio_err); - goto end; - } - do { - sock = BIO_accept_ex(asock, ourpeer, 0); - } while (sock < 0 && BIO_sock_should_retry(sock)); - if (sock < 0) { - ERR_print_errors(bio_err); - BIO_closesocket(asock); - break; - } - BIO_set_tcp_ndelay(sock, 1); - i = (*cb)(sock, type, protocol, context); - - /* - * If we ended with an alert being sent, but still with data in the - * network buffer to be read, then calling BIO_closesocket() will - * result in a TCP-RST being sent. On some platforms (notably - * Windows) then this will result in the peer immediately abandoning - * the connection including any buffered alert data before it has - * had a chance to be read. Shutting down the sending side first, - * and then closing the socket sends TCP-FIN first followed by - * TCP-RST. This seems to allow the peer to read the alert data. - */ - shutdown(sock, 1); /* SHUT_WR */ - /* - * We just said we have nothing else to say, but it doesn't mean - * that the other side has nothing. It's even recommended to - * consume incoming data. [In testing context this ensures that - * alerts are passed on...] - */ - timeout.tv_sec = 0; - timeout.tv_usec = 500000; /* some extreme round-trip */ - do { - FD_ZERO(&readfds); - openssl_fdset(sock, &readfds); - } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 - && readsocket(sock, sink, sizeof(sink)) > 0); - - BIO_closesocket(sock); - } else { - i = (*cb)(asock, type, protocol, context); - } - - if (naccept != -1) - naccept--; - if (i < 0 || naccept == 0) { - BIO_closesocket(asock); - ret = i; - break; - } - } - end: -# ifdef AF_UNIX - if (family == AF_UNIX) - unlink(host); -# endif - BIO_ADDR_free(ourpeer); - ourpeer = NULL; - return ret; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/apps/s_time.c b/apps/s_time.c --- a/apps/s_time.c +++ b/apps/s_time.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -22,9 +22,9 @@ #include #include "s_apps.h" #include -#include +#include "internal/sockets.h" #if !defined(OPENSSL_SYS_MSDOS) -# include OPENSSL_UNISTD +# include #endif #define SSL_CONNECT_NAME "localhost:4433" @@ -43,40 +43,64 @@ static const size_t fmt_http_get_cmd_size = sizeof(fmt_http_get_cmd) - 2; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_CONNECT, OPT_CIPHER, OPT_CIPHERSUITES, OPT_CERT, OPT_NAMEOPT, OPT_KEY, - OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NEW, OPT_REUSE, - OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3, - OPT_WWW + OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, + OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, + OPT_NEW, OPT_REUSE, OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3, + OPT_WWW, OPT_TLS1, OPT_TLS1_1, OPT_TLS1_2, OPT_TLS1_3, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS s_time_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Connection"), {"connect", OPT_CONNECT, 's', "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"}, + {"new", OPT_NEW, '-', "Just time new connections"}, + {"reuse", OPT_REUSE, '-', "Just time connection reuse"}, + {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"}, {"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"}, {"ciphersuites", OPT_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, +#ifndef OPENSSL_NO_SSL3 + {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, +#endif +#ifndef OPENSSL_NO_TLS1 + {"tls1", OPT_TLS1, '-', "Just use TLSv1.0"}, +#endif +#ifndef OPENSSL_NO_TLS1_1 + {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"}, +#endif +#ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"}, +#endif +#ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"}, +#endif + {"verify", OPT_VERIFY, 'p', + "Turn on peer certificate verification, set depth"}, + {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR}, + {"www", OPT_WWW, 's', "Fetch specified page from the site"}, + + OPT_SECTION("Certificate"), + {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"}, {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"}, - {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"}, {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, + {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, + {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"}, {"no-CAfile", OPT_NOCAFILE, '-', "Do not load the default certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', "Do not load certificates from the default certificates directory"}, - {"new", OPT_NEW, '-', "Just time new connections"}, - {"reuse", OPT_REUSE, '-', "Just time connection reuse"}, - {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"}, - {"verify", OPT_VERIFY, 'p', - "Turn on peer certificate verification, set depth"}, - {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR}, - {"www", OPT_WWW, 's', "Fetch specified page from the site"}, -#ifndef OPENSSL_NO_SSL3 - {"ssl3", OPT_SSL3, '-', "Just use SSLv3"}, -#endif + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store URI"}, + + OPT_PROV_OPTIONS, {NULL} }; @@ -94,15 +118,16 @@ SSL *scon = NULL; SSL_CTX *ctx = NULL; const SSL_METHOD *meth = NULL; - char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *ciphersuites = NULL; + char *CApath = NULL, *CAfile = NULL, *CAstore = NULL; + char *cipher = NULL, *ciphersuites = NULL; char *www_path = NULL; char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog; double totalTime = 0.0; - int noCApath = 0, noCAfile = 0; + int noCApath = 0, noCAfile = 0, noCAstore = 0; int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0; long bytes_read = 0, finishtime = 0; OPTION_CHOICE o; - int max_version = 0, ver, buf_len; + int min_version = 0, max_version = 0, ver, buf_len, fd; size_t buf_size; meth = TLS_client_method(); @@ -129,8 +154,7 @@ perform = 1; break; case OPT_VERIFY: - if (!opt_int(opt_arg(), &verify_args.depth)) - goto opthelp; + verify_args.depth = opt_int_arg(); BIO_printf(bio_err, "%s: verify depth is %d\n", prog, verify_args.depth); break; @@ -156,6 +180,12 @@ case OPT_NOCAFILE: noCAfile = 1; break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_CIPHER: cipher = opt_arg(); break; @@ -166,8 +196,7 @@ st_bugs = 1; break; case OPT_TIME: - if (!opt_int(opt_arg(), &maxtime)) - goto opthelp; + maxtime = opt_int_arg(); break; case OPT_WWW: www_path = opt_arg(); @@ -178,10 +207,33 @@ } break; case OPT_SSL3: + min_version = SSL3_VERSION; max_version = SSL3_VERSION; break; + case OPT_TLS1: + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + break; + case OPT_TLS1_1: + min_version = TLS1_1_VERSION; + max_version = TLS1_1_VERSION; + break; + case OPT_TLS1_2: + min_version = TLS1_2_VERSION; + max_version = TLS1_2_VERSION; + break; + case OPT_TLS1_3: + min_version = TLS1_3_VERSION; + max_version = TLS1_3_VERSION; + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; @@ -192,8 +244,9 @@ if ((ctx = SSL_CTX_new(meth)) == NULL) goto end; - SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_quiet_shutdown(ctx, 1); + if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0) + goto end; if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) goto end; @@ -206,7 +259,8 @@ if (!set_cert_stuff(ctx, certfile, keyfile)) goto end; - if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { + if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) { ERR_print_errors(bio_err); goto end; } @@ -289,7 +343,8 @@ continue; } SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); - BIO_closesocket(SSL_get_fd(scon)); + if ((fd = SSL_get_fd(scon)) >= 0) + BIO_closesocket(fd); nConn = 0; totalTime = 0.0; @@ -316,7 +371,8 @@ bytes_read += i; } SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); - BIO_closesocket(SSL_get_fd(scon)); + if ((fd = SSL_get_fd(scon)) >= 0) + BIO_closesocket(fd); nConn += 1; if (SSL_session_reused(scon)) { @@ -338,10 +394,13 @@ printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); - printf - ("%d connections in %ld real seconds, %ld bytes read per connection\n", - nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); - + if (nConn > 0) + printf + ("%d connections in %ld real seconds, %ld bytes read per connection\n", + nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); + else + printf("0 connections in %ld real seconds\n", + (long)time(NULL) - finishtime + maxtime); ret = 0; end: @@ -362,12 +421,19 @@ if ((conn = BIO_new(BIO_s_connect())) == NULL) return NULL; - BIO_set_conn_hostname(conn, host); - BIO_set_conn_mode(conn, BIO_SOCK_NODELAY); + if (BIO_set_conn_hostname(conn, host) <= 0 + || BIO_set_conn_mode(conn, BIO_SOCK_NODELAY) <= 0) { + BIO_free(conn); + return NULL; + } - if (scon == NULL) + if (scon == NULL) { serverCon = SSL_new(ctx); - else { + if (serverCon == NULL) { + BIO_free(conn); + return NULL; + } + } else { serverCon = scon; SSL_set_connect_state(serverCon); } diff --git a/apps/sess_id.c b/apps/sess_id.c --- a/apps/sess_id.c +++ b/apps/sess_id.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,22 +19,27 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_CERT, OPT_NOOUT, OPT_CONTEXT } OPTION_CHOICE; const OPTIONS sess_id_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"context", OPT_CONTEXT, 's', "Set the session ID context"}, + + OPT_SECTION("Input"), + {"in", OPT_IN, 's', "Input file - default stdin"}, {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file - default stdout"}, {"outform", OPT_OUTFORM, 'f', "Output format - default PEM (PEM, DER or NSS)"}, - {"in", OPT_IN, 's', "Input file - default stdin"}, - {"out", OPT_OUT, '>', "Output file - default stdout"}, {"text", OPT_TEXT, '-', "Print ssl session id details"}, {"cert", OPT_CERT, '-', "Output certificate "}, {"noout", OPT_NOOUT, '-', "Don't output the encoded session info"}, - {"context", OPT_CONTEXT, 's', "Set the session ID context"}, {NULL} }; @@ -91,6 +96,8 @@ break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; diff --git a/apps/smime.c b/apps/smime.c --- a/apps/smime.c +++ b/apps/smime.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -33,7 +33,7 @@ #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY, OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN, OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, @@ -41,76 +41,97 @@ OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD, OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE, - OPT_R_ENUM, + OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE, + OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG, OPT_V_ENUM, - OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT, + OPT_IN, OPT_INFORM, OPT_OUT, OPT_OUTFORM, OPT_CONTENT } OPTION_CHOICE; const OPTIONS smime_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, - {OPT_HELP_STR, 1, '-', - " cert.pem... recipient certs for encryption\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file"}, + {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, + {"out", OPT_OUT, '>', "Output file"}, + {"outform", OPT_OUTFORM, 'c', + "Output format SMIME (default), PEM or DER"}, + {"inkey", OPT_INKEY, 's', + "Input private key (if not signer or recipient)"}, + {"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, + {"indef", OPT_INDEF, '-', "Same as -stream" }, + {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, + OPT_CONFIG_OPTION, + + OPT_SECTION("Action"), {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, {"sign", OPT_SIGN, '-', "Sign message"}, + {"resign", OPT_RESIGN, '-', "Resign a signed message"}, {"verify", OPT_VERIFY, '-', "Verify signed message"}, + + OPT_SECTION("Signing/Encryption"), + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, + {"", OPT_CIPHER, '-', "Any supported cipher"}, {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, {"nointern", OPT_NOINTERN, '-', "Don't search certificates in message for signer"}, - {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, - {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, - {"nocerts", OPT_NOCERTS, '-', - "Don't include signers certificate when signing"}, {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, {"binary", OPT_BINARY, '-', "Don't translate message to text"}, - {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, {"signer", OPT_SIGNER, 's', "Signer certificate file"}, - {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, - {"in", OPT_IN, '<', "Input file"}, - {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, - {"inkey", OPT_INKEY, 's', - "Input private key (if not signer or recipient)"}, - {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"}, - {"out", OPT_OUT, '>', "Output file"}, - {"outform", OPT_OUTFORM, 'c', - "Output format SMIME (default), PEM or DER"}, {"content", OPT_CONTENT, '<', "Supply or override content for detached signature"}, + {"nocerts", OPT_NOCERTS, '-', + "Don't include signers certificate when signing"}, + + OPT_SECTION("Verification/Decryption"), + {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, + {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, + + {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, + + OPT_SECTION("Email"), {"to", OPT_TO, 's', "To address"}, {"from", OPT_FROM, 's', "From address"}, {"subject", OPT_SUBJECT, 's', "Subject"}, {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, + {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + + OPT_SECTION("Certificate chain"), {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, + {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"}, {"no-CAfile", OPT_NOCAFILE, '-', "Do not load the default certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', "Do not load certificates from the default certificates directory"}, - {"resign", OPT_RESIGN, '-', "Resign a signed message"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load certificates from the default certificates store"}, {"nochain", OPT_NOCHAIN, '-', "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" }, - {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, - {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, - {"indef", OPT_INDEF, '-', "Same as -stream" }, - {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only"}, + OPT_R_OPTIONS, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, - {"", OPT_CIPHER, '-', "Any supported cipher"}, OPT_V_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"cert", 0, 0, "Recipient certs, used when encrypting"}, {NULL} }; int smime_main(int argc, char **argv) { + CONF *conf = NULL; BIO *in = NULL, *out = NULL, *indata = NULL; EVP_PKEY *key = NULL; PKCS7 *p7 = NULL; @@ -119,20 +140,22 @@ X509 *cert = NULL, *recip = NULL, *signer = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; - const EVP_CIPHER *cipher = NULL; - const EVP_MD *sign_md = NULL; - const char *CAfile = NULL, *CApath = NULL, *prog = NULL; + EVP_CIPHER *cipher = NULL; + EVP_MD *sign_md = NULL; + const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog = NULL; char *certfile = NULL, *keyfile = NULL, *contfile = NULL; char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; - char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL; + char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL; + char *subject = NULL, *digestname = NULL, *ciphername = NULL; OPTION_CHOICE o; - int noCApath = 0, noCAfile = 0; + int noCApath = 0, noCAfile = 0, noCAstore = 0; int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = - FORMAT_PEM; + FORMAT_UNDEF; int vpmtouched = 0, rv = 0; ENGINE *e = NULL; const char *mime_eol = "\n"; + OSSL_LIB_CTX *libctx = app_get0_libctx(); if ((vpm = X509_VERIFY_PARAM_new()) == NULL) return 1; @@ -226,6 +249,15 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; + case OPT_CONFIG: + conf = app_load_config_modules(opt_arg()); + if (conf == NULL) + goto end; + break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; @@ -262,12 +294,10 @@ recipfile = opt_arg(); break; case OPT_MD: - if (!opt_md(opt_arg(), &sign_md)) - goto opthelp; + digestname = opt_arg(); break; case OPT_CIPHER: - if (!opt_cipher(opt_unknown(), &cipher)) - goto opthelp; + ciphername = opt_unknown(); break; case OPT_INKEY: /* If previous -inkey argument add signer to list */ @@ -302,12 +332,18 @@ case OPT_CAPATH: CApath = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_NOCAPATH: noCApath = 1; break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_CONTENT: contfile = opt_arg(); break; @@ -318,13 +354,31 @@ break; } } + + /* Extra arguments are files with recipient keys. */ argc = opt_num_rest(); argv = opt_rest(); + if (!app_RAND_load()) + goto end; + + if (digestname != NULL) { + if (!opt_md(digestname, &sign_md)) + goto opthelp; + } + if (ciphername != NULL) { + if (!opt_cipher_any(ciphername, &cipher)) + goto opthelp; + } if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); goto opthelp; } + if (!operation) { + BIO_puts(bio_err, + "No operation (-encrypt|-sign|...) specified\n"); + goto opthelp; + } if (operation & SMIME_SIGNERS) { /* Check to see if any final signer needs to be appended */ @@ -360,8 +414,6 @@ BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); goto opthelp; } - } else if (!operation) { - goto opthelp; } if (!app_passwd(passinarg, NULL, &passin, NULL)) { @@ -387,7 +439,7 @@ if (operation == SMIME_ENCRYPT) { if (cipher == NULL) { #ifndef OPENSSL_NO_DES - cipher = EVP_des_ede3_cbc(); + cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); #else BIO_printf(bio_err, "No cipher selected\n"); goto end; @@ -397,7 +449,7 @@ if (encerts == NULL) goto end; while (*argv != NULL) { - cert = load_cert(*argv, FORMAT_PEM, + cert = load_cert(*argv, FORMAT_UNDEF, "recipient certificate file"); if (cert == NULL) goto end; @@ -408,15 +460,14 @@ } if (certfile != NULL) { - if (!load_certs(certfile, &other, FORMAT_PEM, NULL, - "certificate file")) { + if (!load_certs(certfile, 0, &other, NULL, "certificates")) { ERR_print_errors(bio_err); goto end; } } if (recipfile != NULL && (operation == SMIME_DECRYPT)) { - if ((recip = load_cert(recipfile, FORMAT_PEM, + if ((recip = load_cert(recipfile, FORMAT_UNDEF, "recipient certificate file")) == NULL) { ERR_print_errors(bio_err); goto end; @@ -434,7 +485,7 @@ } if (keyfile != NULL) { - key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + key = load_key(keyfile, keyform, 0, passin, e, "signing key"); if (key == NULL) goto end; } @@ -444,18 +495,25 @@ goto end; if (operation & SMIME_IP) { + PKCS7 *p7_in = NULL; + + p7 = PKCS7_new_ex(libctx, app_get0_propq()); + if (p7 == NULL) { + BIO_printf(bio_err, "Error allocating PKCS7 object\n"); + goto end; + } if (informat == FORMAT_SMIME) { - p7 = SMIME_read_PKCS7(in, &indata); + p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7); } else if (informat == FORMAT_PEM) { - p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); + p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL); } else if (informat == FORMAT_ASN1) { - p7 = d2i_PKCS7_bio(in, NULL); + p7_in = d2i_PKCS7_bio(in, &p7); } else { BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); goto end; } - if (p7 == NULL) { + if (p7_in == NULL) { BIO_printf(bio_err, "Error reading S/MIME message\n"); goto end; } @@ -473,7 +531,8 @@ goto end; if (operation == SMIME_VERIFY) { - if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) == NULL) goto end; X509_STORE_set_verify_cb(store, smime_cb); if (vpmtouched) @@ -485,7 +544,7 @@ if (operation == SMIME_ENCRYPT) { if (indef) flags |= PKCS7_STREAM; - p7 = PKCS7_encrypt(encerts, in, cipher, flags); + p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq()); } else if (operation & SMIME_SIGNERS) { int i; /* @@ -500,7 +559,7 @@ flags |= PKCS7_STREAM; } flags |= PKCS7_PARTIAL; - p7 = PKCS7_sign(NULL, NULL, other, in, flags); + p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq()); if (p7 == NULL) goto end; if (flags & PKCS7_NOCERTS) { @@ -515,13 +574,13 @@ for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); - signer = load_cert(signerfile, FORMAT_PEM, - "signer certificate"); + signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate"); if (signer == NULL) goto end; - key = load_key(keyfile, keyform, 0, passin, e, "signing key file"); + key = load_key(keyfile, keyform, 0, passin, e, "signing key"); if (key == NULL) goto end; + if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) goto end; X509_free(signer); @@ -604,12 +663,15 @@ X509_free(recip); X509_free(signer); EVP_PKEY_free(key); + EVP_MD_free(sign_md); + EVP_CIPHER_free(cipher); PKCS7_free(p7); release_engine(e); BIO_free(in); BIO_free(indata); BIO_free_all(out); OPENSSL_free(passin); + NCONF_free(conf); return ret; } diff --git a/apps/speed.c b/apps/speed.c --- a/apps/speed.c +++ b/apps/speed.c @@ -1,20 +1,27 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #undef SECONDS -#define SECONDS 3 -#define RSA_SECONDS 10 -#define DSA_SECONDS 10 -#define ECDSA_SECONDS 10 -#define ECDH_SECONDS 10 -#define EdDSA_SECONDS 10 +#define SECONDS 3 +#define PKEY_SECONDS 10 + +#define RSA_SECONDS PKEY_SECONDS +#define DSA_SECONDS PKEY_SECONDS +#define ECDSA_SECONDS PKEY_SECONDS +#define ECDH_SECONDS PKEY_SECONDS +#define EdDSA_SECONDS PKEY_SECONDS +#define SM2_SECONDS PKEY_SECONDS +#define FFDH_SECONDS PKEY_SECONDS + +/* We need to use some deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED #include #include @@ -22,14 +29,22 @@ #include #include "apps.h" #include "progs.h" +#include "internal/numbers.h" #include #include #include #include #include +#include #include #if !defined(OPENSSL_SYS_MSDOS) -# include OPENSSL_UNISTD +# include +#endif + +#if defined(__TANDEM) +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif #endif #if defined(_WIN32) @@ -37,66 +52,14 @@ #endif #include -#ifndef OPENSSL_NO_DES -# include -#endif -#include -#ifndef OPENSSL_NO_CAMELLIA -# include -#endif -#ifndef OPENSSL_NO_MD2 -# include -#endif -#ifndef OPENSSL_NO_MDC2 -# include -#endif -#ifndef OPENSSL_NO_MD4 -# include -#endif -#ifndef OPENSSL_NO_MD5 -# include -#endif -#include -#include -#ifndef OPENSSL_NO_RMD160 -# include -#endif -#ifndef OPENSSL_NO_WHIRLPOOL -# include -#endif -#ifndef OPENSSL_NO_RC4 -# include -#endif -#ifndef OPENSSL_NO_RC5 -# include -#endif -#ifndef OPENSSL_NO_RC2 -# include -#endif -#ifndef OPENSSL_NO_IDEA -# include -#endif -#ifndef OPENSSL_NO_SEED -# include -#endif -#ifndef OPENSSL_NO_BF -# include -#endif -#ifndef OPENSSL_NO_CAST -# include -#endif -#ifndef OPENSSL_NO_RSA -# include -# include "./testrsa.h" +#include +#include "./testrsa.h" +#ifndef OPENSSL_NO_DH +# include #endif #include -#ifndef OPENSSL_NO_DSA -# include -# include "./testdsa.h" -#endif -#ifndef OPENSSL_NO_EC -# include -#endif +#include +#include "./testdsa.h" #include #ifndef HAVE_FORK @@ -104,6 +67,7 @@ # define HAVE_FORK 0 # else # define HAVE_FORK 1 +# include # endif #endif @@ -116,6 +80,11 @@ #define MAX_MISALIGNMENT 63 #define MAX_ECDH_SIZE 256 #define MISALIGN 64 +#define MAX_FFDH_SIZE 1024 + +#ifndef RSA_DEFAULT_PRIME_NUM +# define RSA_DEFAULT_PRIME_NUM 2 +#endif typedef struct openssl_speed_sec_st { int sym; @@ -124,70 +93,15 @@ int ecdsa; int ecdh; int eddsa; + int sm2; + int ffdh; } openssl_speed_sec_t; static volatile int run = 0; -static int mr = 0; +static int mr = 0; /* machine-readeable output format to merge fork results */ static int usertime = 1; -#ifndef OPENSSL_NO_MD2 -static int EVP_Digest_MD2_loop(void *args); -#endif - -#ifndef OPENSSL_NO_MDC2 -static int EVP_Digest_MDC2_loop(void *args); -#endif -#ifndef OPENSSL_NO_MD4 -static int EVP_Digest_MD4_loop(void *args); -#endif -#ifndef OPENSSL_NO_MD5 -static int MD5_loop(void *args); -static int HMAC_loop(void *args); -#endif -static int SHA1_loop(void *args); -static int SHA256_loop(void *args); -static int SHA512_loop(void *args); -#ifndef OPENSSL_NO_WHIRLPOOL -static int WHIRLPOOL_loop(void *args); -#endif -#ifndef OPENSSL_NO_RMD160 -static int EVP_Digest_RMD160_loop(void *args); -#endif -#ifndef OPENSSL_NO_RC4 -static int RC4_loop(void *args); -#endif -#ifndef OPENSSL_NO_DES -static int DES_ncbc_encrypt_loop(void *args); -static int DES_ede3_cbc_encrypt_loop(void *args); -#endif -static int AES_cbc_128_encrypt_loop(void *args); -static int AES_cbc_192_encrypt_loop(void *args); -static int AES_ige_128_encrypt_loop(void *args); -static int AES_cbc_256_encrypt_loop(void *args); -static int AES_ige_192_encrypt_loop(void *args); -static int AES_ige_256_encrypt_loop(void *args); -static int CRYPTO_gcm128_aad_loop(void *args); -static int RAND_bytes_loop(void *args); -static int EVP_Update_loop(void *args); -static int EVP_Update_loop_ccm(void *args); -static int EVP_Update_loop_aead(void *args); -static int EVP_Digest_loop(void *args); -#ifndef OPENSSL_NO_RSA -static int RSA_sign_loop(void *args); -static int RSA_verify_loop(void *args); -#endif -#ifndef OPENSSL_NO_DSA -static int DSA_sign_loop(void *args); -static int DSA_verify_loop(void *args); -#endif -#ifndef OPENSSL_NO_EC -static int ECDSA_sign_loop(void *args); -static int ECDSA_verify_loop(void *args); -static int EdDSA_sign_loop(void *args); -static int EdDSA_verify_loop(void *args); -#endif - static double Time_F(int s); static void print_message(const char *s, long num, int length, int tm); static void pkey_print_message(const char *str, const char *str2, @@ -200,6 +114,7 @@ static const int lengths_list[] = { 16, 64, 256, 1024, 8 * 1024, 16 * 1024 }; +#define SIZE_NUM OSSL_NELEM(lengths_list) static const int *lengths = lengths_list; static const int aead_lengths_list[] = { @@ -272,17 +187,12 @@ return ret; } #else -static double Time_F(int s) -{ - return app_tminterval(s, usertime); -} +# error "SIGALRM not defined and the platform is not Windows" #endif static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, const openssl_speed_sec_t *seconds); -#define found(value, pairs, result)\ - opt_found(value, result, pairs, OSSL_NELEM(pairs)) static int opt_found(const char *name, unsigned int *result, const OPT_PAIR pairs[], unsigned int nbelem) { @@ -295,23 +205,21 @@ } return 0; } +#define opt_found(value, pairs, result)\ + opt_found(value, result, pairs, OSSL_NELEM(pairs)) typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, - OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, - OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD + OPT_COMMON, + OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, + OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM, + OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC } OPTION_CHOICE; const OPTIONS speed_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [algorithm...]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"}, - {"decrypt", OPT_DECRYPT, '-', - "Time decryption instead of encryption (only EVP)"}, - {"aead", OPT_AEAD, '-', - "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, {"mb", OPT_MB, '-', "Enable (tls1>=1) multi-block mode on EVP-named cipher"}, {"mr", OPT_MR, '-', "Produce machine readable output"}, @@ -322,160 +230,114 @@ {"async_jobs", OPT_ASYNCJOBS, 'p', "Enable async mode and start specified number of jobs"}, #endif - OPT_R_OPTIONS, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif + {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"}, + + OPT_SECTION("Selection"), + {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"}, + {"hmac", OPT_HMAC, 's', "HMAC using EVP-named digest"}, + {"cmac", OPT_CMAC, 's', "CMAC using EVP-named cipher"}, + {"decrypt", OPT_DECRYPT, '-', + "Time decryption instead of encryption (only EVP)"}, + {"aead", OPT_AEAD, '-', + "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, + + OPT_SECTION("Timing"), {"elapsed", OPT_ELAPSED, '-', "Use wall-clock time instead of CPU user time as divisor"}, - {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"}, {"seconds", OPT_SECONDS, 'p', "Run benchmarks for specified amount of seconds"}, {"bytes", OPT_BYTES, 'p', "Run [non-PKI] benchmarks on custom-sized buffer"}, {"misalign", OPT_MISALIGN, 'p', "Use specified offset to mis-align buffers"}, + + OPT_R_OPTIONS, + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"algorithm", 0, 0, "Algorithm(s) to test (optional; otherwise tests all)"}, {NULL} }; -#define D_MD2 0 -#define D_MDC2 1 -#define D_MD4 2 -#define D_MD5 3 -#define D_HMAC 4 -#define D_SHA1 5 -#define D_RMD160 6 -#define D_RC4 7 -#define D_CBC_DES 8 -#define D_EDE3_DES 9 -#define D_CBC_IDEA 10 -#define D_CBC_SEED 11 -#define D_CBC_RC2 12 -#define D_CBC_RC5 13 -#define D_CBC_BF 14 -#define D_CBC_CAST 15 -#define D_CBC_128_AES 16 -#define D_CBC_192_AES 17 -#define D_CBC_256_AES 18 -#define D_CBC_128_CML 19 -#define D_CBC_192_CML 20 -#define D_CBC_256_CML 21 -#define D_EVP 22 -#define D_SHA256 23 -#define D_SHA512 24 -#define D_WHIRLPOOL 25 -#define D_IGE_128_AES 26 -#define D_IGE_192_AES 27 -#define D_IGE_256_AES 28 -#define D_GHASH 29 -#define D_RAND 30 -/* name of algorithms to test */ -static const char *names[] = { - "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4", - "des cbc", "des ede3", "idea cbc", "seed cbc", - "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc", - "aes-128 cbc", "aes-192 cbc", "aes-256 cbc", - "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc", - "evp", "sha256", "sha512", "whirlpool", - "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash", - "rand" +enum { + D_MD2, D_MDC2, D_MD4, D_MD5, D_SHA1, D_RMD160, + D_SHA256, D_SHA512, D_WHIRLPOOL, D_HMAC, + D_CBC_DES, D_EDE3_DES, D_RC4, D_CBC_IDEA, D_CBC_SEED, + D_CBC_RC2, D_CBC_RC5, D_CBC_BF, D_CBC_CAST, + D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES, + D_CBC_128_CML, D_CBC_192_CML, D_CBC_256_CML, + D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, ALGOR_NUM +}; +/* name of algorithms to test. MUST BE KEEP IN SYNC with above enum ! */ +static const char *names[ALGOR_NUM] = { + "md2", "mdc2", "md4", "md5", "sha1", "rmd160", + "sha256", "sha512", "whirlpool", "hmac(md5)", + "des-cbc", "des-ede3", "rc4", "idea-cbc", "seed-cbc", + "rc2-cbc", "rc5-cbc", "blowfish", "cast-cbc", + "aes-128-cbc", "aes-192-cbc", "aes-256-cbc", + "camellia-128-cbc", "camellia-192-cbc", "camellia-256-cbc", + "evp", "ghash", "rand", "cmac" }; -#define ALGOR_NUM OSSL_NELEM(names) -/* list of configured algorithm (remaining) */ +/* list of configured algorithm (remaining), with some few alias */ static const OPT_PAIR doit_choices[] = { -#ifndef OPENSSL_NO_MD2 {"md2", D_MD2}, -#endif -#ifndef OPENSSL_NO_MDC2 {"mdc2", D_MDC2}, -#endif -#ifndef OPENSSL_NO_MD4 {"md4", D_MD4}, -#endif -#ifndef OPENSSL_NO_MD5 {"md5", D_MD5}, {"hmac", D_HMAC}, -#endif {"sha1", D_SHA1}, {"sha256", D_SHA256}, {"sha512", D_SHA512}, -#ifndef OPENSSL_NO_WHIRLPOOL {"whirlpool", D_WHIRLPOOL}, -#endif -#ifndef OPENSSL_NO_RMD160 {"ripemd", D_RMD160}, {"rmd160", D_RMD160}, {"ripemd160", D_RMD160}, -#endif -#ifndef OPENSSL_NO_RC4 {"rc4", D_RC4}, -#endif -#ifndef OPENSSL_NO_DES {"des-cbc", D_CBC_DES}, {"des-ede3", D_EDE3_DES}, -#endif {"aes-128-cbc", D_CBC_128_AES}, {"aes-192-cbc", D_CBC_192_AES}, {"aes-256-cbc", D_CBC_256_AES}, - {"aes-128-ige", D_IGE_128_AES}, - {"aes-192-ige", D_IGE_192_AES}, - {"aes-256-ige", D_IGE_256_AES}, -#ifndef OPENSSL_NO_RC2 + {"camellia-128-cbc", D_CBC_128_CML}, + {"camellia-192-cbc", D_CBC_192_CML}, + {"camellia-256-cbc", D_CBC_256_CML}, {"rc2-cbc", D_CBC_RC2}, {"rc2", D_CBC_RC2}, -#endif -#ifndef OPENSSL_NO_RC5 {"rc5-cbc", D_CBC_RC5}, {"rc5", D_CBC_RC5}, -#endif -#ifndef OPENSSL_NO_IDEA {"idea-cbc", D_CBC_IDEA}, {"idea", D_CBC_IDEA}, -#endif -#ifndef OPENSSL_NO_SEED {"seed-cbc", D_CBC_SEED}, {"seed", D_CBC_SEED}, -#endif -#ifndef OPENSSL_NO_BF {"bf-cbc", D_CBC_BF}, {"blowfish", D_CBC_BF}, {"bf", D_CBC_BF}, -#endif -#ifndef OPENSSL_NO_CAST {"cast-cbc", D_CBC_CAST}, {"cast", D_CBC_CAST}, {"cast5", D_CBC_CAST}, -#endif {"ghash", D_GHASH}, {"rand", D_RAND} }; -static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)]; +static double results[ALGOR_NUM][SIZE_NUM]; -#ifndef OPENSSL_NO_DSA -# define R_DSA_512 0 -# define R_DSA_1024 1 -# define R_DSA_2048 2 -static const OPT_PAIR dsa_choices[] = { +enum { R_DSA_512, R_DSA_1024, R_DSA_2048, DSA_NUM }; +static const OPT_PAIR dsa_choices[DSA_NUM] = { {"dsa512", R_DSA_512}, {"dsa1024", R_DSA_1024}, {"dsa2048", R_DSA_2048} }; -# define DSA_NUM OSSL_NELEM(dsa_choices) - static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */ -#endif /* OPENSSL_NO_DSA */ - -#define R_RSA_512 0 -#define R_RSA_1024 1 -#define R_RSA_2048 2 -#define R_RSA_3072 3 -#define R_RSA_4096 4 -#define R_RSA_7680 5 -#define R_RSA_15360 6 -#ifndef OPENSSL_NO_RSA -static const OPT_PAIR rsa_choices[] = { + +enum { + R_RSA_512, R_RSA_1024, R_RSA_2048, R_RSA_3072, R_RSA_4096, R_RSA_7680, + R_RSA_15360, RSA_NUM +}; +static const OPT_PAIR rsa_choices[RSA_NUM] = { {"rsa512", R_RSA_512}, {"rsa1024", R_RSA_1024}, {"rsa2048", R_RSA_2048}, @@ -484,49 +346,43 @@ {"rsa7680", R_RSA_7680}, {"rsa15360", R_RSA_15360} }; -# define RSA_NUM OSSL_NELEM(rsa_choices) static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */ -#endif /* OPENSSL_NO_RSA */ -enum { - R_EC_P160, - R_EC_P192, - R_EC_P224, - R_EC_P256, - R_EC_P384, - R_EC_P521, +#ifndef OPENSSL_NO_DH +enum ff_params_t { + R_FFDH_2048, R_FFDH_3072, R_FFDH_4096, R_FFDH_6144, R_FFDH_8192, FFDH_NUM +}; + +static const OPT_PAIR ffdh_choices[FFDH_NUM] = { + {"ffdh2048", R_FFDH_2048}, + {"ffdh3072", R_FFDH_3072}, + {"ffdh4096", R_FFDH_4096}, + {"ffdh6144", R_FFDH_6144}, + {"ffdh8192", R_FFDH_8192}, +}; + +static double ffdh_results[FFDH_NUM][1]; /* 1 op: derivation */ +#endif /* OPENSSL_NO_DH */ + +enum ec_curves_t { + R_EC_P160, R_EC_P192, R_EC_P224, R_EC_P256, R_EC_P384, R_EC_P521, #ifndef OPENSSL_NO_EC2M - R_EC_K163, - R_EC_K233, - R_EC_K283, - R_EC_K409, - R_EC_K571, - R_EC_B163, - R_EC_B233, - R_EC_B283, - R_EC_B409, - R_EC_B571, + R_EC_K163, R_EC_K233, R_EC_K283, R_EC_K409, R_EC_K571, + R_EC_B163, R_EC_B233, R_EC_B283, R_EC_B409, R_EC_B571, #endif - R_EC_BRP256R1, - R_EC_BRP256T1, - R_EC_BRP384R1, - R_EC_BRP384T1, - R_EC_BRP512R1, - R_EC_BRP512T1, - R_EC_X25519, - R_EC_X448 + R_EC_BRP256R1, R_EC_BRP256T1, R_EC_BRP384R1, R_EC_BRP384T1, + R_EC_BRP512R1, R_EC_BRP512T1, ECDSA_NUM }; - -#ifndef OPENSSL_NO_EC -static OPT_PAIR ecdsa_choices[] = { +/* list of ecdsa curves */ +static const OPT_PAIR ecdsa_choices[ECDSA_NUM] = { {"ecdsap160", R_EC_P160}, {"ecdsap192", R_EC_P192}, {"ecdsap224", R_EC_P224}, {"ecdsap256", R_EC_P256}, {"ecdsap384", R_EC_P384}, {"ecdsap521", R_EC_P521}, -# ifndef OPENSSL_NO_EC2M +#ifndef OPENSSL_NO_EC2M {"ecdsak163", R_EC_K163}, {"ecdsak233", R_EC_K233}, {"ecdsak283", R_EC_K283}, @@ -537,7 +393,7 @@ {"ecdsab283", R_EC_B283}, {"ecdsab409", R_EC_B409}, {"ecdsab571", R_EC_B571}, -# endif +#endif {"ecdsabrp256r1", R_EC_BRP256R1}, {"ecdsabrp256t1", R_EC_BRP256T1}, {"ecdsabrp384r1", R_EC_BRP384R1}, @@ -545,18 +401,16 @@ {"ecdsabrp512r1", R_EC_BRP512R1}, {"ecdsabrp512t1", R_EC_BRP512T1} }; -# define ECDSA_NUM OSSL_NELEM(ecdsa_choices) - -static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */ - -static const OPT_PAIR ecdh_choices[] = { +enum { R_EC_X25519 = ECDSA_NUM, R_EC_X448, EC_NUM }; +/* list of ecdh curves, extension of |ecdsa_choices| list above */ +static const OPT_PAIR ecdh_choices[EC_NUM] = { {"ecdhp160", R_EC_P160}, {"ecdhp192", R_EC_P192}, {"ecdhp224", R_EC_P224}, {"ecdhp256", R_EC_P256}, {"ecdhp384", R_EC_P384}, {"ecdhp521", R_EC_P521}, -# ifndef OPENSSL_NO_EC2M +#ifndef OPENSSL_NO_EC2M {"ecdhk163", R_EC_K163}, {"ecdhk233", R_EC_K233}, {"ecdhk283", R_EC_K283}, @@ -567,7 +421,7 @@ {"ecdhb283", R_EC_B283}, {"ecdhb409", R_EC_B409}, {"ecdhb571", R_EC_B571}, -# endif +#endif {"ecdhbrp256r1", R_EC_BRP256R1}, {"ecdhbrp256t1", R_EC_BRP256T1}, {"ecdhbrp384r1", R_EC_BRP384R1}, @@ -577,28 +431,30 @@ {"ecdhx25519", R_EC_X25519}, {"ecdhx448", R_EC_X448} }; -# define EC_NUM OSSL_NELEM(ecdh_choices) -static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */ +static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */ +static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */ -#define R_EC_Ed25519 0 -#define R_EC_Ed448 1 -static OPT_PAIR eddsa_choices[] = { +enum { R_EC_Ed25519, R_EC_Ed448, EdDSA_NUM }; +static const OPT_PAIR eddsa_choices[EdDSA_NUM] = { {"ed25519", R_EC_Ed25519}, {"ed448", R_EC_Ed448} -}; -# define EdDSA_NUM OSSL_NELEM(eddsa_choices) +}; static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */ -#endif /* OPENSSL_NO_EC */ -#ifndef SIGALRM -# define COND(d) (count < (d)) -# define COUNT(d) (d) -#else -# define COND(unused_cond) (run && count<0x7fffffff) -# define COUNT(d) (count) -#endif /* SIGALRM */ +#ifndef OPENSSL_NO_SM2 +enum { R_EC_CURVESM2, SM2_NUM }; +static const OPT_PAIR sm2_choices[SM2_NUM] = { + {"curveSM2", R_EC_CURVESM2} +}; +# define SM2_ID "TLSv1.3+GM+Cipher+Suite" +# define SM2_ID_LEN sizeof("TLSv1.3+GM+Cipher+Suite") - 1 +static double sm2_results[SM2_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_SM2 */ + +#define COND(unused_cond) (run && count < INT_MAX) +#define COUNT(d) (count) typedef struct loopargs_st { ASYNC_JOB *inprogress_job; @@ -608,25 +464,32 @@ unsigned char *buf_malloc; unsigned char *buf2_malloc; unsigned char *key; - unsigned int siglen; + size_t buflen; size_t sigsize; -#ifndef OPENSSL_NO_RSA - RSA *rsa_key[RSA_NUM]; -#endif -#ifndef OPENSSL_NO_DSA - DSA *dsa_key[DSA_NUM]; -#endif -#ifndef OPENSSL_NO_EC - EC_KEY *ecdsa[ECDSA_NUM]; + EVP_PKEY_CTX *rsa_sign_ctx[RSA_NUM]; + EVP_PKEY_CTX *rsa_verify_ctx[RSA_NUM]; + EVP_PKEY_CTX *dsa_sign_ctx[DSA_NUM]; + EVP_PKEY_CTX *dsa_verify_ctx[DSA_NUM]; + EVP_PKEY_CTX *ecdsa_sign_ctx[ECDSA_NUM]; + EVP_PKEY_CTX *ecdsa_verify_ctx[ECDSA_NUM]; EVP_PKEY_CTX *ecdh_ctx[EC_NUM]; EVP_MD_CTX *eddsa_ctx[EdDSA_NUM]; + EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM]; +#ifndef OPENSSL_NO_SM2 + EVP_MD_CTX *sm2_ctx[SM2_NUM]; + EVP_MD_CTX *sm2_vfy_ctx[SM2_NUM]; + EVP_PKEY *sm2_pkey[SM2_NUM]; +#endif unsigned char *secret_a; unsigned char *secret_b; size_t outlen[EC_NUM]; +#ifndef OPENSSL_NO_DH + EVP_PKEY_CTX *ffdh_ctx[FFDH_NUM]; + unsigned char *secret_ff_a; + unsigned char *secret_ff_b; #endif EVP_CIPHER_CTX *ctx; - HMAC_CTX *hctx; - GCM128_CONTEXT *gcm_ctx; + EVP_MAC_CTX *mctx; } loopargs_t; static int run_benchmark(int async_jobs, int (*loop_function) (void *), loopargs_t * loopargs); @@ -634,273 +497,216 @@ static unsigned int testnum; /* Nb of iterations to do per algorithm and key-size */ -static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)]; +static long c[ALGOR_NUM][SIZE_NUM]; -#ifndef OPENSSL_NO_MD2 -static int EVP_Digest_MD2_loop(void *args) +static char *evp_mac_mdname = "md5"; +static char *evp_hmac_name = NULL; +static const char *evp_md_name = NULL; +static char *evp_mac_ciphername = "aes-128-cbc"; +static char *evp_cmac_name = NULL; + +static int have_md(const char *name) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char md2[MD2_DIGEST_LENGTH]; - int count; + int ret = 0; + EVP_MD *md = NULL; - for (count = 0; COND(c[D_MD2][testnum]); count++) { - if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(), - NULL)) - return -1; + if (opt_md_silent(name, &md)) { + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + + if (ctx != NULL && EVP_DigestInit(ctx, md) > 0) + ret = 1; + EVP_MD_CTX_free(ctx); + EVP_MD_free(md); } - return count; + return ret; } -#endif -#ifndef OPENSSL_NO_MDC2 -static int EVP_Digest_MDC2_loop(void *args) +static int have_cipher(const char *name) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char mdc2[MDC2_DIGEST_LENGTH]; - int count; + int ret = 0; + EVP_CIPHER *cipher = NULL; - for (count = 0; COND(c[D_MDC2][testnum]); count++) { - if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(), - NULL)) - return -1; + if (opt_cipher_silent(name, &cipher)) { + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + + if (ctx != NULL + && EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1) > 0) + ret = 1; + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cipher); } - return count; + return ret; } -#endif -#ifndef OPENSSL_NO_MD4 -static int EVP_Digest_MD4_loop(void *args) +static int EVP_Digest_loop(const char *mdname, int algindex, void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - unsigned char md4[MD4_DIGEST_LENGTH]; + unsigned char digest[EVP_MAX_MD_SIZE]; int count; + EVP_MD *md = NULL; - for (count = 0; COND(c[D_MD4][testnum]); count++) { - if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(), - NULL)) - return -1; + if (!opt_md_silent(mdname, &md)) + return -1; + for (count = 0; COND(c[algindex][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md, + NULL)) { + count = -1; + break; + } } + EVP_MD_free(md); return count; } -#endif -#ifndef OPENSSL_NO_MD5 -static int MD5_loop(void *args) +static int EVP_Digest_md_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char md5[MD5_DIGEST_LENGTH]; - int count; - for (count = 0; COND(c[D_MD5][testnum]); count++) - MD5(buf, lengths[testnum], md5); - return count; + return EVP_Digest_loop(evp_md_name, D_EVP, args); } -static int HMAC_loop(void *args) +static int EVP_Digest_MD2_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - HMAC_CTX *hctx = tempargs->hctx; - unsigned char hmac[MD5_DIGEST_LENGTH]; - int count; - - for (count = 0; COND(c[D_HMAC][testnum]); count++) { - HMAC_Init_ex(hctx, NULL, 0, NULL, NULL); - HMAC_Update(hctx, buf, lengths[testnum]); - HMAC_Final(hctx, hmac, NULL); - } - return count; + return EVP_Digest_loop("md2", D_MD2, args); } -#endif -static int SHA1_loop(void *args) +static int EVP_Digest_MDC2_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char sha[SHA_DIGEST_LENGTH]; - int count; - for (count = 0; COND(c[D_SHA1][testnum]); count++) - SHA1(buf, lengths[testnum], sha); - return count; + return EVP_Digest_loop("mdc2", D_MDC2, args); } -static int SHA256_loop(void *args) +static int EVP_Digest_MD4_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char sha256[SHA256_DIGEST_LENGTH]; - int count; - for (count = 0; COND(c[D_SHA256][testnum]); count++) - SHA256(buf, lengths[testnum], sha256); - return count; + return EVP_Digest_loop("md4", D_MD4, args); } -static int SHA512_loop(void *args) +static int MD5_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char sha512[SHA512_DIGEST_LENGTH]; - int count; - for (count = 0; COND(c[D_SHA512][testnum]); count++) - SHA512(buf, lengths[testnum], sha512); - return count; + return EVP_Digest_loop("md5", D_MD5, args); } -#ifndef OPENSSL_NO_WHIRLPOOL -static int WHIRLPOOL_loop(void *args) +static int EVP_MAC_loop(int algindex, void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH]; + EVP_MAC_CTX *mctx = tempargs->mctx; + unsigned char mac[EVP_MAX_MD_SIZE]; int count; - for (count = 0; COND(c[D_WHIRLPOOL][testnum]); count++) - WHIRLPOOL(buf, lengths[testnum], whirlpool); - return count; -} -#endif -#ifndef OPENSSL_NO_RMD160 -static int EVP_Digest_RMD160_loop(void *args) -{ - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char rmd160[RIPEMD160_DIGEST_LENGTH]; - int count; - for (count = 0; COND(c[D_RMD160][testnum]); count++) { - if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]), - NULL, EVP_ripemd160(), NULL)) + for (count = 0; COND(c[algindex][testnum]); count++) { + size_t outl; + + if (!EVP_MAC_init(mctx, NULL, 0, NULL) + || !EVP_MAC_update(mctx, buf, lengths[testnum]) + || !EVP_MAC_final(mctx, mac, &outl, sizeof(mac))) return -1; } return count; } -#endif -#ifndef OPENSSL_NO_RC4 -static RC4_KEY rc4_ks; -static int RC4_loop(void *args) +static int HMAC_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - int count; - for (count = 0; COND(c[D_RC4][testnum]); count++) - RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf); - return count; + return EVP_MAC_loop(D_HMAC, args); } -#endif -#ifndef OPENSSL_NO_DES -static unsigned char DES_iv[8]; -static DES_key_schedule sch; -static DES_key_schedule sch2; -static DES_key_schedule sch3; -static int DES_ncbc_encrypt_loop(void *args) +static int CMAC_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - int count; - for (count = 0; COND(c[D_CBC_DES][testnum]); count++) - DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch, - &DES_iv, DES_ENCRYPT); - return count; + return EVP_MAC_loop(D_EVP_CMAC, args); } -static int DES_ede3_cbc_encrypt_loop(void *args) +static int SHA1_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - int count; - for (count = 0; COND(c[D_EDE3_DES][testnum]); count++) - DES_ede3_cbc_encrypt(buf, buf, lengths[testnum], - &sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT); - return count; + return EVP_Digest_loop("sha1", D_SHA1, args); } -#endif -#define MAX_BLOCK_SIZE 128 - -static unsigned char iv[2 * MAX_BLOCK_SIZE / 8]; -static AES_KEY aes_ks1, aes_ks2, aes_ks3; -static int AES_cbc_128_encrypt_loop(void *args) +static int SHA256_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - int count; - for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++) - AES_cbc_encrypt(buf, buf, - (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT); - return count; + return EVP_Digest_loop("sha256", D_SHA256, args); } -static int AES_cbc_192_encrypt_loop(void *args) +static int SHA512_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - int count; - for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++) - AES_cbc_encrypt(buf, buf, - (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT); - return count; + return EVP_Digest_loop("sha512", D_SHA512, args); } -static int AES_cbc_256_encrypt_loop(void *args) +static int WHIRLPOOL_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - int count; - for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++) - AES_cbc_encrypt(buf, buf, - (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT); - return count; + return EVP_Digest_loop("whirlpool", D_WHIRLPOOL, args); } -static int AES_ige_128_encrypt_loop(void *args) +static int EVP_Digest_RMD160_loop(void *args) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char *buf2 = tempargs->buf2; - int count; - for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++) - AES_ige_encrypt(buf, buf2, - (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT); - return count; + return EVP_Digest_loop("ripemd160", D_RMD160, args); } -static int AES_ige_192_encrypt_loop(void *args) +static int algindex; + +static int EVP_Cipher_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - unsigned char *buf2 = tempargs->buf2; int count; - for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++) - AES_ige_encrypt(buf, buf2, - (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT); + + if (tempargs->ctx == NULL) + return -1; + for (count = 0; COND(c[algindex][testnum]); count++) + if (EVP_Cipher(tempargs->ctx, buf, buf, (size_t)lengths[testnum]) <= 0) + return -1; return count; } -static int AES_ige_256_encrypt_loop(void *args) +static int GHASH_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - unsigned char *buf2 = tempargs->buf2; + EVP_MAC_CTX *mctx = tempargs->mctx; int count; - for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++) - AES_ige_encrypt(buf, buf2, - (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT); + + /* just do the update in the loop to be comparable with 1.1.1 */ + for (count = 0; COND(c[D_GHASH][testnum]); count++) { + if (!EVP_MAC_update(mctx, buf, lengths[testnum])) + return -1; + } return count; } -static int CRYPTO_gcm128_aad_loop(void *args) +#define MAX_BLOCK_SIZE 128 + +static unsigned char iv[2 * MAX_BLOCK_SIZE / 8]; + +static EVP_CIPHER_CTX *init_evp_cipher_ctx(const char *ciphername, + const unsigned char *key, + int keylen) { - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx; - int count; - for (count = 0; COND(c[D_GHASH][testnum]); count++) - CRYPTO_gcm128_aad(gcm_ctx, buf, lengths[testnum]); - return count; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; + + if (!opt_cipher_silent(ciphername, &cipher)) + return NULL; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto end; + + if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 1)) { + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; + goto end; + } + + if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0) { + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; + goto end; + } + + if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1)) { + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; + goto end; + } + +end: + EVP_CIPHER_free(cipher); + return ctx; } static int RAND_bytes_loop(void *args) @@ -914,7 +720,6 @@ return count; } -static long save_count = 0; static int decrypt = 0; static int EVP_Update_loop(void *args) { @@ -922,11 +727,9 @@ unsigned char *buf = tempargs->buf; EVP_CIPHER_CTX *ctx = tempargs->ctx; int outl, count, rc; -#ifndef SIGALRM - int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; -#endif + if (decrypt) { - for (count = 0; COND(nb_iter); count++) { + for (count = 0; COND(c[D_EVP][testnum]); count++) { rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); if (rc != 1) { /* reset iv in case of counter overflow */ @@ -934,7 +737,7 @@ } } } else { - for (count = 0; COND(nb_iter); count++) { + for (count = 0; COND(c[D_EVP][testnum]); count++) { rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); if (rc != 1) { /* reset iv in case of counter overflow */ @@ -961,29 +764,28 @@ EVP_CIPHER_CTX *ctx = tempargs->ctx; int outl, count; unsigned char tag[12]; -#ifndef SIGALRM - int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; -#endif + if (decrypt) { - for (count = 0; COND(nb_iter); count++) { - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag); + for (count = 0; COND(c[D_EVP][testnum]); count++) { + (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), + tag); /* reset iv */ - EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); + (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); /* counter is reset on every update */ - EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); } } else { - for (count = 0; COND(nb_iter); count++) { + for (count = 0; COND(c[D_EVP][testnum]); count++) { /* restore iv length field */ - EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]); + (void)EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]); /* counter is reset on every update */ - EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); } } if (decrypt) - EVP_DecryptFinal_ex(ctx, buf, &outl); + (void)EVP_DecryptFinal_ex(ctx, buf, &outl); else - EVP_EncryptFinal_ex(ctx, buf, &outl); + (void)EVP_EncryptFinal_ex(ctx, buf, &outl); return count; } @@ -1000,61 +802,42 @@ int outl, count; unsigned char aad[13] = { 0xcc }; unsigned char faketag[16] = { 0xcc }; -#ifndef SIGALRM - int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; -#endif + if (decrypt) { - for (count = 0; COND(nb_iter); count++) { - EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, - sizeof(faketag), faketag); - EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); - EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); - EVP_DecryptFinal_ex(ctx, buf + outl, &outl); + for (count = 0; COND(c[D_EVP][testnum]); count++) { + (void)EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv); + (void)EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + sizeof(faketag), faketag); + (void)EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + (void)EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + (void)EVP_DecryptFinal_ex(ctx, buf + outl, &outl); } } else { - for (count = 0; COND(nb_iter); count++) { - EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv); - EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); - EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); - EVP_EncryptFinal_ex(ctx, buf + outl, &outl); + for (count = 0; COND(c[D_EVP][testnum]); count++) { + (void)EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv); + (void)EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad)); + (void)EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); + (void)EVP_EncryptFinal_ex(ctx, buf + outl, &outl); } } return count; } -static const EVP_MD *evp_md = NULL; -static int EVP_Digest_loop(void *args) -{ - loopargs_t *tempargs = *(loopargs_t **) args; - unsigned char *buf = tempargs->buf; - unsigned char md[EVP_MAX_MD_SIZE]; - int count; -#ifndef SIGALRM - int nb_iter = save_count * 4 * lengths[0] / lengths[testnum]; -#endif - - for (count = 0; COND(nb_iter); count++) { - if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL)) - return -1; - } - return count; -} - -#ifndef OPENSSL_NO_RSA -static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */ - -static int RSA_sign_loop(void *args) +static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */ + +static int RSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; unsigned char *buf2 = tempargs->buf2; - unsigned int *rsa_num = &tempargs->siglen; - RSA **rsa_key = tempargs->rsa_key; + size_t *rsa_num = &tempargs->sigsize; + EVP_PKEY_CTX **rsa_sign_ctx = tempargs->rsa_sign_ctx; int ret, count; + for (count = 0; COND(rsa_c[testnum][0]); count++) { - ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]); - if (ret == 0) { + *rsa_num = tempargs->buflen; + ret = EVP_PKEY_sign(rsa_sign_ctx[testnum], buf2, rsa_num, buf, 36); + if (ret <= 0) { BIO_printf(bio_err, "RSA sign failure\n"); ERR_print_errors(bio_err); count = -1; @@ -1069,12 +852,12 @@ loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; unsigned char *buf2 = tempargs->buf2; - unsigned int rsa_num = tempargs->siglen; - RSA **rsa_key = tempargs->rsa_key; + size_t rsa_num = tempargs->sigsize; + EVP_PKEY_CTX **rsa_verify_ctx = tempargs->rsa_verify_ctx; int ret, count; + for (count = 0; COND(rsa_c[testnum][1]); count++) { - ret = - RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]); + ret = EVP_PKEY_verify(rsa_verify_ctx[testnum], buf2, rsa_num, buf, 36); if (ret <= 0) { BIO_printf(bio_err, "RSA verify failure\n"); ERR_print_errors(bio_err); @@ -1084,21 +867,41 @@ } return count; } -#endif -#ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DH +static long ffdh_c[FFDH_NUM][1]; + +static int FFDH_derive_key_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ffdh_ctx = tempargs->ffdh_ctx[testnum]; + unsigned char *derived_secret = tempargs->secret_ff_a; + int count; + + for (count = 0; COND(ffdh_c[testnum][0]); count++) { + /* outlen can be overwritten with a too small value (no padding used) */ + size_t outlen = MAX_FFDH_SIZE; + + EVP_PKEY_derive(ffdh_ctx, derived_secret, &outlen); + } + return count; +} +#endif /* OPENSSL_NO_DH */ + static long dsa_c[DSA_NUM][2]; static int DSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; unsigned char *buf2 = tempargs->buf2; - DSA **dsa_key = tempargs->dsa_key; - unsigned int *siglen = &tempargs->siglen; + size_t *dsa_num = &tempargs->sigsize; + EVP_PKEY_CTX **dsa_sign_ctx = tempargs->dsa_sign_ctx; int ret, count; + for (count = 0; COND(dsa_c[testnum][0]); count++) { - ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]); - if (ret == 0) { + *dsa_num = tempargs->buflen; + ret = EVP_PKEY_sign(dsa_sign_ctx[testnum], buf2, dsa_num, buf, 20); + if (ret <= 0) { BIO_printf(bio_err, "DSA sign failure\n"); ERR_print_errors(bio_err); count = -1; @@ -1113,11 +916,12 @@ loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; unsigned char *buf2 = tempargs->buf2; - DSA **dsa_key = tempargs->dsa_key; - unsigned int siglen = tempargs->siglen; + size_t dsa_num = tempargs->sigsize; + EVP_PKEY_CTX **dsa_verify_ctx = tempargs->dsa_verify_ctx; int ret, count; + for (count = 0; COND(dsa_c[testnum][1]); count++) { - ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]); + ret = EVP_PKEY_verify(dsa_verify_ctx[testnum], buf2, dsa_num, buf, 20); if (ret <= 0) { BIO_printf(bio_err, "DSA verify failure\n"); ERR_print_errors(bio_err); @@ -1127,21 +931,21 @@ } return count; } -#endif -#ifndef OPENSSL_NO_EC static long ecdsa_c[ECDSA_NUM][2]; static int ECDSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - EC_KEY **ecdsa = tempargs->ecdsa; - unsigned char *ecdsasig = tempargs->buf2; - unsigned int *ecdsasiglen = &tempargs->siglen; + unsigned char *buf2 = tempargs->buf2; + size_t *ecdsa_num = &tempargs->sigsize; + EVP_PKEY_CTX **ecdsa_sign_ctx = tempargs->ecdsa_sign_ctx; int ret, count; + for (count = 0; COND(ecdsa_c[testnum][0]); count++) { - ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]); - if (ret == 0) { + *ecdsa_num = tempargs->buflen; + ret = EVP_PKEY_sign(ecdsa_sign_ctx[testnum], buf2, ecdsa_num, buf, 20); + if (ret <= 0) { BIO_printf(bio_err, "ECDSA sign failure\n"); ERR_print_errors(bio_err); count = -1; @@ -1155,13 +959,15 @@ { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - EC_KEY **ecdsa = tempargs->ecdsa; - unsigned char *ecdsasig = tempargs->buf2; - unsigned int ecdsasiglen = tempargs->siglen; + unsigned char *buf2 = tempargs->buf2; + size_t ecdsa_num = tempargs->sigsize; + EVP_PKEY_CTX **ecdsa_verify_ctx = tempargs->ecdsa_verify_ctx; int ret, count; + for (count = 0; COND(ecdsa_c[testnum][1]); count++) { - ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]); - if (ret != 1) { + ret = EVP_PKEY_verify(ecdsa_verify_ctx[testnum], buf2, ecdsa_num, + buf, 20); + if (ret <= 0) { BIO_printf(bio_err, "ECDSA verify failure\n"); ERR_print_errors(bio_err); count = -1; @@ -1214,7 +1020,7 @@ { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; - EVP_MD_CTX **edctx = tempargs->eddsa_ctx; + EVP_MD_CTX **edctx = tempargs->eddsa_ctx2; unsigned char *eddsasig = tempargs->buf2; size_t eddsasigsize = tempargs->sigsize; int ret, count; @@ -1230,7 +1036,75 @@ } return count; } -#endif /* OPENSSL_NO_EC */ + +#ifndef OPENSSL_NO_SM2 +static long sm2_c[SM2_NUM][2]; +static int SM2_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_MD_CTX **sm2ctx = tempargs->sm2_ctx; + unsigned char *sm2sig = tempargs->buf2; + size_t sm2sigsize; + int ret, count; + EVP_PKEY **sm2_pkey = tempargs->sm2_pkey; + const size_t max_size = EVP_PKEY_get_size(sm2_pkey[testnum]); + + for (count = 0; COND(sm2_c[testnum][0]); count++) { + sm2sigsize = max_size; + + if (!EVP_DigestSignInit(sm2ctx[testnum], NULL, EVP_sm3(), + NULL, sm2_pkey[testnum])) { + BIO_printf(bio_err, "SM2 init sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + ret = EVP_DigestSign(sm2ctx[testnum], sm2sig, &sm2sigsize, + buf, 20); + if (ret == 0) { + BIO_printf(bio_err, "SM2 sign failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + /* update the latest returned size and always use the fixed buffer size */ + tempargs->sigsize = sm2sigsize; + } + + return count; +} + +static int SM2_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + EVP_MD_CTX **sm2ctx = tempargs->sm2_vfy_ctx; + unsigned char *sm2sig = tempargs->buf2; + size_t sm2sigsize = tempargs->sigsize; + int ret, count; + EVP_PKEY **sm2_pkey = tempargs->sm2_pkey; + + for (count = 0; COND(sm2_c[testnum][1]); count++) { + if (!EVP_DigestVerifyInit(sm2ctx[testnum], NULL, EVP_sm3(), + NULL, sm2_pkey[testnum])) { + BIO_printf(bio_err, "SM2 verify init failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + ret = EVP_DigestVerify(sm2ctx[testnum], sm2sig, sm2sigsize, + buf, 20); + if (ret != 1) { + BIO_printf(bio_err, "SM2 verify failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + return count; +} +#endif /* OPENSSL_NO_SM2 */ static int run_benchmark(int async_jobs, int (*loop_function) (void *), loopargs_t * loopargs) @@ -1383,124 +1257,170 @@ return error ? -1 : total_op_count; } +typedef struct ec_curve_st { + const char *name; + unsigned int nid; + unsigned int bits; + size_t sigsize; /* only used for EdDSA curves */ +} EC_CURVE; + +static EVP_PKEY *get_ecdsa(const EC_CURVE *curve) +{ + EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY *key = NULL; + + /* Ensure that the error queue is empty */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); + ERR_print_errors(bio_err); + } + + /* + * Let's try to create a ctx directly from the NID: this works for + * curves like Curve25519 that are not implemented through the low + * level EC interface. + * If this fails we try creating a EVP_PKEY_EC generic param ctx, + * then we set the curve by NID before deriving the actual keygen + * ctx for that specific curve. + */ + kctx = EVP_PKEY_CTX_new_id(curve->nid, NULL); + if (kctx == NULL) { + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *params = NULL; + /* + * If we reach this code EVP_PKEY_CTX_new_id() failed and a + * "int_ctx_new:unsupported algorithm" error was added to the + * error queue. + * We remove it from the error queue as we are handling it. + */ + unsigned long error = ERR_peek_error(); + + if (error == ERR_peek_last_error() /* oldest and latest errors match */ + /* check that the error origin matches */ + && ERR_GET_LIB(error) == ERR_LIB_EVP + && (ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM + || ERR_GET_REASON(error) == ERR_R_UNSUPPORTED)) + ERR_get_error(); /* pop error from queue */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "Unhandled error in the error queue during EC key setup.\n"); + ERR_print_errors(bio_err); + return NULL; + } + + /* Create the context for parameter generation */ + if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL + || EVP_PKEY_paramgen_init(pctx) <= 0 + || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, + curve->nid) <= 0 + || EVP_PKEY_paramgen(pctx, ¶ms) <= 0) { + BIO_printf(bio_err, "EC params init failure.\n"); + ERR_print_errors(bio_err); + EVP_PKEY_CTX_free(pctx); + return NULL; + } + EVP_PKEY_CTX_free(pctx); + + /* Create the context for the key generation */ + kctx = EVP_PKEY_CTX_new(params, NULL); + EVP_PKEY_free(params); + } + if (kctx == NULL + || EVP_PKEY_keygen_init(kctx) <= 0 + || EVP_PKEY_keygen(kctx, &key) <= 0) { + BIO_printf(bio_err, "EC key generation failure.\n"); + ERR_print_errors(bio_err); + key = NULL; + } + EVP_PKEY_CTX_free(kctx); + return key; +} + +#define stop_it(do_it, test_num)\ + memset(do_it + test_num, 0, OSSL_NELEM(do_it) - test_num); + int speed_main(int argc, char **argv) { ENGINE *e = NULL; loopargs_t *loopargs = NULL; const char *prog; const char *engine_id = NULL; - const EVP_CIPHER *evp_cipher = NULL; + EVP_CIPHER *evp_cipher = NULL; + EVP_MAC *mac = NULL; double d = 0.0; OPTION_CHOICE o; int async_init = 0, multiblock = 0, pr_header = 0; - int doit[ALGOR_NUM] = { 0 }; + uint8_t doit[ALGOR_NUM] = { 0 }; int ret = 1, misalign = 0, lengths_single = 0, aead = 0; long count = 0; - unsigned int size_num = OSSL_NELEM(lengths_list); - unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0; + unsigned int size_num = SIZE_NUM; + unsigned int i, k, loopargs_len = 0, async_jobs = 0; int keylen; int buflen; + BIGNUM *bn = NULL; + EVP_PKEY_CTX *genctx = NULL; #ifndef NO_FORK int multi = 0; #endif -#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \ - || !defined(OPENSSL_NO_EC) - long rsa_count = 1; -#endif + long op_count = 1; openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS, ECDSA_SECONDS, ECDH_SECONDS, - EdDSA_SECONDS }; + EdDSA_SECONDS, SM2_SECONDS, + FFDH_SECONDS }; - /* What follows are the buffers and key material. */ -#ifndef OPENSSL_NO_RC5 - RC5_32_KEY rc5_ks; -#endif -#ifndef OPENSSL_NO_RC2 - RC2_KEY rc2_ks; -#endif -#ifndef OPENSSL_NO_IDEA - IDEA_KEY_SCHEDULE idea_ks; -#endif -#ifndef OPENSSL_NO_SEED - SEED_KEY_SCHEDULE seed_ks; -#endif -#ifndef OPENSSL_NO_BF - BF_KEY bf_ks; -#endif -#ifndef OPENSSL_NO_CAST - CAST_KEY cast_ks; -#endif - static const unsigned char key16[16] = { - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, - 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 - }; - static const unsigned char key24[24] = { - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, - 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, - 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 - }; static const unsigned char key32[32] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56 }; -#ifndef OPENSSL_NO_CAMELLIA - static const unsigned char ckey24[24] = { - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, - 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, - 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 - }; - static const unsigned char ckey32[32] = { - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, - 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, - 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, - 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56 - }; - CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3; -#endif -#ifndef OPENSSL_NO_DES - static DES_cblock key = { - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 - }; - static DES_cblock key2 = { - 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12 + static const unsigned char deskey[] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, /* key1 */ + 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, /* key2 */ + 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 /* key3 */ }; - static DES_cblock key3 = { - 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34 - }; -#endif -#ifndef OPENSSL_NO_RSA - static const unsigned int rsa_bits[RSA_NUM] = { - 512, 1024, 2048, 3072, 4096, 7680, 15360 - }; - static const unsigned char *rsa_data[RSA_NUM] = { - test512, test1024, test2048, test3072, test4096, test7680, test15360 - }; - static const int rsa_data_length[RSA_NUM] = { - sizeof(test512), sizeof(test1024), - sizeof(test2048), sizeof(test3072), - sizeof(test4096), sizeof(test7680), - sizeof(test15360) + static const struct { + const unsigned char *data; + unsigned int length; + unsigned int bits; + } rsa_keys[] = { + { test512, sizeof(test512), 512 }, + { test1024, sizeof(test1024), 1024 }, + { test2048, sizeof(test2048), 2048 }, + { test3072, sizeof(test3072), 3072 }, + { test4096, sizeof(test4096), 4096 }, + { test7680, sizeof(test7680), 7680 }, + { test15360, sizeof(test15360), 15360 } }; - int rsa_doit[RSA_NUM] = { 0 }; + uint8_t rsa_doit[RSA_NUM] = { 0 }; int primes = RSA_DEFAULT_PRIME_NUM; -#endif -#ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_DH + typedef struct ffdh_params_st { + const char *name; + unsigned int nid; + unsigned int bits; + } FFDH_PARAMS; + + static const FFDH_PARAMS ffdh_params[FFDH_NUM] = { + {"ffdh2048", NID_ffdhe2048, 2048}, + {"ffdh3072", NID_ffdhe3072, 3072}, + {"ffdh4096", NID_ffdhe4096, 4096}, + {"ffdh6144", NID_ffdhe6144, 6144}, + {"ffdh8192", NID_ffdhe8192, 8192} + }; + uint8_t ffdh_doit[FFDH_NUM] = { 0 }; + +#endif /* OPENSSL_NO_DH */ static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 }; - int dsa_doit[DSA_NUM] = { 0 }; -#endif -#ifndef OPENSSL_NO_EC + uint8_t dsa_doit[DSA_NUM] = { 0 }; /* * We only test over the following curves as they are representative, To * add tests over more curves, simply add the curve NID and curve name to - * the following arrays and increase the |ecdh_choices| list accordingly. + * the following arrays and increase the |ecdh_choices| and |ecdsa_choices| + * lists accordingly. */ - static const struct { - const char *name; - unsigned int nid; - unsigned int bits; - } test_curves[] = { + static const EC_CURVE ec_curves[EC_NUM] = { /* Prime Curves */ {"secp160r1", NID_secp160r1, 160}, {"nistp192", NID_X9_62_prime192v1, 192}, @@ -1508,7 +1428,7 @@ {"nistp256", NID_X9_62_prime256v1, 256}, {"nistp384", NID_secp384r1, 384}, {"nistp521", NID_secp521r1, 521}, -# ifndef OPENSSL_NO_EC2M +#ifndef OPENSSL_NO_EC2M /* Binary Curves */ {"nistk163", NID_sect163k1, 163}, {"nistk233", NID_sect233k1, 233}, @@ -1520,7 +1440,7 @@ {"nistb283", NID_sect283r1, 283}, {"nistb409", NID_sect409r1, 409}, {"nistb571", NID_sect571r1, 571}, -# endif +#endif {"brainpoolP256r1", NID_brainpoolP256r1, 256}, {"brainpoolP256t1", NID_brainpoolP256t1, 256}, {"brainpoolP384r1", NID_brainpoolP384r1, 384}, @@ -1531,22 +1451,36 @@ {"X25519", NID_X25519, 253}, {"X448", NID_X448, 448} }; - static const struct { - const char *name; - unsigned int nid; - unsigned int bits; - size_t sigsize; - } test_ed_curves[] = { + static const EC_CURVE ed_curves[EdDSA_NUM] = { /* EdDSA */ {"Ed25519", NID_ED25519, 253, 64}, {"Ed448", NID_ED448, 456, 114} }; - int ecdsa_doit[ECDSA_NUM] = { 0 }; - int ecdh_doit[EC_NUM] = { 0 }; - int eddsa_doit[EdDSA_NUM] = { 0 }; - OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM); - OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM); -#endif /* ndef OPENSSL_NO_EC */ +#ifndef OPENSSL_NO_SM2 + static const EC_CURVE sm2_curves[SM2_NUM] = { + /* SM2 */ + {"CurveSM2", NID_sm2, 256} + }; + uint8_t sm2_doit[SM2_NUM] = { 0 }; +#endif + uint8_t ecdsa_doit[ECDSA_NUM] = { 0 }; + uint8_t ecdh_doit[EC_NUM] = { 0 }; + uint8_t eddsa_doit[EdDSA_NUM] = { 0 }; + + /* checks declarated curves against choices list. */ + OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448); + OPENSSL_assert(strcmp(eddsa_choices[EdDSA_NUM - 1].name, "ed448") == 0); + + OPENSSL_assert(ec_curves[EC_NUM - 1].nid == NID_X448); + OPENSSL_assert(strcmp(ecdh_choices[EC_NUM - 1].name, "ecdhx448") == 0); + + OPENSSL_assert(ec_curves[ECDSA_NUM - 1].nid == NID_brainpoolP512t1); + OPENSSL_assert(strcmp(ecdsa_choices[ECDSA_NUM - 1].name, "ecdsabrp512t1") == 0); + +#ifndef OPENSSL_NO_SM2 + OPENSSL_assert(sm2_curves[SM2_NUM - 1].nid == NID_sm2); + OPENSSL_assert(strcmp(sm2_choices[SM2_NUM - 1].name, "curveSM2") == 0); +#endif prog = opt_init(argc, argv, speed_options); while ((o = opt_next()) != OPT_EOF) { @@ -1564,18 +1498,43 @@ usertime = 0; break; case OPT_EVP: - evp_md = NULL; - evp_cipher = EVP_get_cipherbyname(opt_arg()); - if (evp_cipher == NULL) - evp_md = EVP_get_digestbyname(opt_arg()); - if (evp_cipher == NULL && evp_md == NULL) { + if (doit[D_EVP]) { + BIO_printf(bio_err, "%s: -evp option cannot be used more than once\n", prog); + goto opterr; + } + ERR_set_mark(); + if (!opt_cipher_silent(opt_arg(), &evp_cipher)) { + if (have_md(opt_arg())) + evp_md_name = opt_arg(); + } + if (evp_cipher == NULL && evp_md_name == NULL) { + ERR_clear_last_mark(); BIO_printf(bio_err, "%s: %s is an unknown cipher or digest\n", prog, opt_arg()); goto end; } + ERR_pop_to_mark(); doit[D_EVP] = 1; break; + case OPT_HMAC: + if (!have_md(opt_arg())) { + BIO_printf(bio_err, "%s: %s is an unknown digest\n", + prog, opt_arg()); + goto end; + } + evp_mac_mdname = opt_arg(); + doit[D_HMAC] = 1; + break; + case OPT_CMAC: + if (!have_cipher(opt_arg())) { + BIO_printf(bio_err, "%s: %s is an unknown cipher\n", + prog, opt_arg()); + goto end; + } + evp_mac_ciphername = opt_arg(); + doit[D_EVP_CMAC] = 1; + break; case OPT_DECRYPT: decrypt = 1; break; @@ -1590,7 +1549,7 @@ case OPT_MULTI: #ifndef NO_FORK multi = atoi(opt_arg()); - if (multi >= INT_MAX / (int)sizeof(int)) { + if ((size_t)multi >= SIZE_MAX / sizeof(int)) { BIO_printf(bio_err, "%s: multi argument too large\n", prog); return 0; } @@ -1612,8 +1571,7 @@ #endif break; case OPT_MISALIGN: - if (!opt_int(opt_arg(), &misalign)) - goto end; + misalign = opt_int_arg(); if (misalign > MISALIGN) { BIO_printf(bio_err, "%s: Maximum offset is %d\n", prog, MISALIGN); @@ -1636,13 +1594,17 @@ if (!opt_rand(o)) goto end; break; - case OPT_PRIMES: - if (!opt_int(opt_arg(), &primes)) + case OPT_PROV_CASES: + if (!opt_provider(o)) goto end; break; + case OPT_PRIMES: + primes = opt_int_arg(); + break; case OPT_SECONDS: seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa - = seconds.ecdh = seconds.eddsa = atoi(opt_arg()); + = seconds.ecdh = seconds.eddsa + = seconds.sm2 = seconds.ffdh = atoi(opt_arg()); break; case OPT_BYTES: lengths_single = atoi(opt_arg()); @@ -1654,89 +1616,112 @@ break; } } + + /* Remaining arguments are algorithms. */ argc = opt_num_rest(); argv = opt_rest(); - /* Remaining arguments are algorithms. */ + if (!app_RAND_load()) + goto end; + for (; *argv; argv++) { - if (found(*argv, doit_choices, &i)) { + const char *algo = *argv; + + if (opt_found(algo, doit_choices, &i)) { doit[i] = 1; continue; } -#ifndef OPENSSL_NO_DES - if (strcmp(*argv, "des") == 0) { + if (strcmp(algo, "des") == 0) { doit[D_CBC_DES] = doit[D_EDE3_DES] = 1; continue; } -#endif - if (strcmp(*argv, "sha") == 0) { + if (strcmp(algo, "sha") == 0) { doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1; continue; } -#ifndef OPENSSL_NO_RSA - if (strcmp(*argv, "openssl") == 0) - continue; - if (strcmp(*argv, "rsa") == 0) { - for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++) - rsa_doit[loop] = 1; - continue; - } - if (found(*argv, rsa_choices, &i)) { - rsa_doit[i] = 1; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (strcmp(algo, "openssl") == 0) /* just for compatibility */ continue; - } #endif -#ifndef OPENSSL_NO_DSA - if (strcmp(*argv, "dsa") == 0) { - dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] = - dsa_doit[R_DSA_2048] = 1; - continue; + if (strncmp(algo, "rsa", 3) == 0) { + if (algo[3] == '\0') { + memset(rsa_doit, 1, sizeof(rsa_doit)); + continue; + } + if (opt_found(algo, rsa_choices, &i)) { + rsa_doit[i] = 1; + continue; + } } - if (found(*argv, dsa_choices, &i)) { - dsa_doit[i] = 2; - continue; +#ifndef OPENSSL_NO_DH + if (strncmp(algo, "ffdh", 4) == 0) { + if (algo[4] == '\0') { + memset(ffdh_doit, 1, sizeof(ffdh_doit)); + continue; + } + if (opt_found(algo, ffdh_choices, &i)) { + ffdh_doit[i] = 2; + continue; + } } #endif - if (strcmp(*argv, "aes") == 0) { + if (strncmp(algo, "dsa", 3) == 0) { + if (algo[3] == '\0') { + memset(dsa_doit, 1, sizeof(dsa_doit)); + continue; + } + if (opt_found(algo, dsa_choices, &i)) { + dsa_doit[i] = 2; + continue; + } + } + if (strcmp(algo, "aes") == 0) { doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1; continue; } -#ifndef OPENSSL_NO_CAMELLIA - if (strcmp(*argv, "camellia") == 0) { + if (strcmp(algo, "camellia") == 0) { doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1; continue; } -#endif -#ifndef OPENSSL_NO_EC - if (strcmp(*argv, "ecdsa") == 0) { - for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) - ecdsa_doit[loop] = 1; - continue; + if (strncmp(algo, "ecdsa", 5) == 0) { + if (algo[5] == '\0') { + memset(ecdsa_doit, 1, sizeof(ecdsa_doit)); + continue; + } + if (opt_found(algo, ecdsa_choices, &i)) { + ecdsa_doit[i] = 2; + continue; + } } - if (found(*argv, ecdsa_choices, &i)) { - ecdsa_doit[i] = 2; - continue; + if (strncmp(algo, "ecdh", 4) == 0) { + if (algo[4] == '\0') { + memset(ecdh_doit, 1, sizeof(ecdh_doit)); + continue; + } + if (opt_found(algo, ecdh_choices, &i)) { + ecdh_doit[i] = 2; + continue; + } } - if (strcmp(*argv, "ecdh") == 0) { - for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) - ecdh_doit[loop] = 1; + if (strcmp(algo, "eddsa") == 0) { + memset(eddsa_doit, 1, sizeof(eddsa_doit)); continue; } - if (found(*argv, ecdh_choices, &i)) { - ecdh_doit[i] = 2; + if (opt_found(algo, eddsa_choices, &i)) { + eddsa_doit[i] = 2; continue; } - if (strcmp(*argv, "eddsa") == 0) { - for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) - eddsa_doit[loop] = 1; +#ifndef OPENSSL_NO_SM2 + if (strcmp(algo, "sm2") == 0) { + memset(sm2_doit, 1, sizeof(sm2_doit)); continue; } - if (found(*argv, eddsa_choices, &i)) { - eddsa_doit[i] = 2; + if (opt_found(algo, sm2_choices, &i)) { + sm2_doit[i] = 2; continue; } #endif - BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv); + BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo); goto end; } @@ -1745,22 +1730,22 @@ if (evp_cipher == NULL) { BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n"); goto end; - } else if (!(EVP_CIPHER_flags(evp_cipher) & + } else if (!(EVP_CIPHER_get_flags(evp_cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { BIO_printf(bio_err, "%s is not an AEAD cipher\n", - OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher))); + EVP_CIPHER_get0_name(evp_cipher)); goto end; } } if (multiblock) { if (evp_cipher == NULL) { - BIO_printf(bio_err,"-mb can be used only with a multi-block" - " capable cipher\n"); + BIO_printf(bio_err, "-mb can be used only with a multi-block" + " capable cipher\n"); goto end; - } else if (!(EVP_CIPHER_flags(evp_cipher) & + } else if (!(EVP_CIPHER_get_flags(evp_cipher) & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { BIO_printf(bio_err, "%s is not a multi-block capable\n", - OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher))); + EVP_CIPHER_get0_name(evp_cipher)); goto end; } else if (async_jobs > 0) { BIO_printf(bio_err, "Async mode is not supported with -mb"); @@ -1794,6 +1779,10 @@ buflen = lengths[size_num - 1]; if (buflen < 36) /* size of random vector in RSA benchmark */ buflen = 36; + if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) { + BIO_printf(bio_err, "Error: buffer size too large\n"); + goto end; + } buflen += MAX_MISALIGNMENT + 1; loopargs[i].buf_malloc = app_malloc(buflen, "input buffer"); loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer"); @@ -1803,9 +1792,13 @@ /* Align the start of buffers on a 64 byte boundary */ loopargs[i].buf = loopargs[i].buf_malloc + misalign; loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign; -#ifndef OPENSSL_NO_EC + loopargs[i].buflen = buflen - misalign; + loopargs[i].sigsize = buflen - misalign; loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a"); loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b"); +#ifndef OPENSSL_NO_DH + loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a"); + loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH secret b"); #endif } @@ -1818,25 +1811,43 @@ e = setup_engine(engine_id, 0); /* No parameters; turn on everything. */ - if ((argc == 0) && !doit[D_EVP]) { - for (i = 0; i < ALGOR_NUM; i++) - if (i != D_EVP) - doit[i] = 1; -#ifndef OPENSSL_NO_RSA - for (i = 0; i < RSA_NUM; i++) - rsa_doit[i] = 1; -#endif -#ifndef OPENSSL_NO_DSA - for (i = 0; i < DSA_NUM; i++) - dsa_doit[i] = 1; + if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) { + memset(doit, 1, sizeof(doit)); + doit[D_EVP] = doit[D_EVP_CMAC] = 0; + ERR_set_mark(); + for (i = D_MD2; i <= D_WHIRLPOOL; i++) { + if (!have_md(names[i])) + doit[i] = 0; + } + for (i = D_CBC_DES; i <= D_CBC_256_CML; i++) { + if (!have_cipher(names[i])) + doit[i] = 0; + } + if ((mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", + app_get0_propq())) != NULL) { + EVP_MAC_free(mac); + mac = NULL; + } else { + doit[D_GHASH] = 0; + } + if ((mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", + app_get0_propq())) != NULL) { + EVP_MAC_free(mac); + mac = NULL; + } else { + doit[D_HMAC] = 0; + } + ERR_pop_to_mark(); + memset(rsa_doit, 1, sizeof(rsa_doit)); +#ifndef OPENSSL_NO_DH + memset(ffdh_doit, 1, sizeof(ffdh_doit)); #endif -#ifndef OPENSSL_NO_EC - for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) - ecdsa_doit[loop] = 1; - for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) - ecdh_doit[loop] = 1; - for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) - eddsa_doit[loop] = 1; + memset(dsa_doit, 1, sizeof(dsa_doit)); + memset(ecdsa_doit, 1, sizeof(ecdsa_doit)); + memset(ecdh_doit, 1, sizeof(ecdh_doit)); + memset(eddsa_doit, 1, sizeof(eddsa_doit)); +#ifndef OPENSSL_NO_SM2 + memset(sm2_doit, 1, sizeof(sm2_doit)); #endif } for (i = 0; i < ALGOR_NUM; i++) @@ -1848,308 +1859,10 @@ "You have chosen to measure elapsed time " "instead of user CPU time.\n"); -#ifndef OPENSSL_NO_RSA - for (i = 0; i < loopargs_len; i++) { - if (primes > RSA_DEFAULT_PRIME_NUM) { - /* for multi-prime RSA, skip this */ - break; - } - for (k = 0; k < RSA_NUM; k++) { - const unsigned char *p; - - p = rsa_data[k]; - loopargs[i].rsa_key[k] = - d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]); - if (loopargs[i].rsa_key[k] == NULL) { - BIO_printf(bio_err, - "internal error loading RSA key number %d\n", k); - goto end; - } - } - } -#endif -#ifndef OPENSSL_NO_DSA - for (i = 0; i < loopargs_len; i++) { - loopargs[i].dsa_key[0] = get_dsa(512); - loopargs[i].dsa_key[1] = get_dsa(1024); - loopargs[i].dsa_key[2] = get_dsa(2048); - } -#endif -#ifndef OPENSSL_NO_DES - DES_set_key_unchecked(&key, &sch); - DES_set_key_unchecked(&key2, &sch2); - DES_set_key_unchecked(&key3, &sch3); -#endif - AES_set_encrypt_key(key16, 128, &aes_ks1); - AES_set_encrypt_key(key24, 192, &aes_ks2); - AES_set_encrypt_key(key32, 256, &aes_ks3); -#ifndef OPENSSL_NO_CAMELLIA - Camellia_set_key(key16, 128, &camellia_ks1); - Camellia_set_key(ckey24, 192, &camellia_ks2); - Camellia_set_key(ckey32, 256, &camellia_ks3); -#endif -#ifndef OPENSSL_NO_IDEA - IDEA_set_encrypt_key(key16, &idea_ks); -#endif -#ifndef OPENSSL_NO_SEED - SEED_set_key(key16, &seed_ks); -#endif -#ifndef OPENSSL_NO_RC4 - RC4_set_key(&rc4_ks, 16, key16); -#endif -#ifndef OPENSSL_NO_RC2 - RC2_set_key(&rc2_ks, 16, key16, 128); -#endif -#ifndef OPENSSL_NO_RC5 - RC5_32_set_key(&rc5_ks, 16, key16, 12); -#endif -#ifndef OPENSSL_NO_BF - BF_set_key(&bf_ks, 16, key16); -#endif -#ifndef OPENSSL_NO_CAST - CAST_set_key(&cast_ks, 16, key16); -#endif -#ifndef SIGALRM -# ifndef OPENSSL_NO_DES - BIO_printf(bio_err, "First we calculate the approximate speed ...\n"); - count = 10; - do { - long it; - count *= 2; - Time_F(START); - for (it = count; it; it--) - DES_ecb_encrypt((DES_cblock *)loopargs[0].buf, - (DES_cblock *)loopargs[0].buf, &sch, DES_ENCRYPT); - d = Time_F(STOP); - } while (d < 3); - save_count = count; - c[D_MD2][0] = count / 10; - c[D_MDC2][0] = count / 10; - c[D_MD4][0] = count; - c[D_MD5][0] = count; - c[D_HMAC][0] = count; - c[D_SHA1][0] = count; - c[D_RMD160][0] = count; - c[D_RC4][0] = count * 5; - c[D_CBC_DES][0] = count; - c[D_EDE3_DES][0] = count / 3; - c[D_CBC_IDEA][0] = count; - c[D_CBC_SEED][0] = count; - c[D_CBC_RC2][0] = count; - c[D_CBC_RC5][0] = count; - c[D_CBC_BF][0] = count; - c[D_CBC_CAST][0] = count; - c[D_CBC_128_AES][0] = count; - c[D_CBC_192_AES][0] = count; - c[D_CBC_256_AES][0] = count; - c[D_CBC_128_CML][0] = count; - c[D_CBC_192_CML][0] = count; - c[D_CBC_256_CML][0] = count; - c[D_SHA256][0] = count; - c[D_SHA512][0] = count; - c[D_WHIRLPOOL][0] = count; - c[D_IGE_128_AES][0] = count; - c[D_IGE_192_AES][0] = count; - c[D_IGE_256_AES][0] = count; - c[D_GHASH][0] = count; - c[D_RAND][0] = count; - - for (i = 1; i < size_num; i++) { - long l0, l1; - - l0 = (long)lengths[0]; - l1 = (long)lengths[i]; - - c[D_MD2][i] = c[D_MD2][0] * 4 * l0 / l1; - c[D_MDC2][i] = c[D_MDC2][0] * 4 * l0 / l1; - c[D_MD4][i] = c[D_MD4][0] * 4 * l0 / l1; - c[D_MD5][i] = c[D_MD5][0] * 4 * l0 / l1; - c[D_HMAC][i] = c[D_HMAC][0] * 4 * l0 / l1; - c[D_SHA1][i] = c[D_SHA1][0] * 4 * l0 / l1; - c[D_RMD160][i] = c[D_RMD160][0] * 4 * l0 / l1; - c[D_SHA256][i] = c[D_SHA256][0] * 4 * l0 / l1; - c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1; - c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1; - c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1; - c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1; - - l0 = (long)lengths[i - 1]; - - c[D_RC4][i] = c[D_RC4][i - 1] * l0 / l1; - c[D_CBC_DES][i] = c[D_CBC_DES][i - 1] * l0 / l1; - c[D_EDE3_DES][i] = c[D_EDE3_DES][i - 1] * l0 / l1; - c[D_CBC_IDEA][i] = c[D_CBC_IDEA][i - 1] * l0 / l1; - c[D_CBC_SEED][i] = c[D_CBC_SEED][i - 1] * l0 / l1; - c[D_CBC_RC2][i] = c[D_CBC_RC2][i - 1] * l0 / l1; - c[D_CBC_RC5][i] = c[D_CBC_RC5][i - 1] * l0 / l1; - c[D_CBC_BF][i] = c[D_CBC_BF][i - 1] * l0 / l1; - c[D_CBC_CAST][i] = c[D_CBC_CAST][i - 1] * l0 / l1; - c[D_CBC_128_AES][i] = c[D_CBC_128_AES][i - 1] * l0 / l1; - c[D_CBC_192_AES][i] = c[D_CBC_192_AES][i - 1] * l0 / l1; - c[D_CBC_256_AES][i] = c[D_CBC_256_AES][i - 1] * l0 / l1; - c[D_CBC_128_CML][i] = c[D_CBC_128_CML][i - 1] * l0 / l1; - c[D_CBC_192_CML][i] = c[D_CBC_192_CML][i - 1] * l0 / l1; - c[D_CBC_256_CML][i] = c[D_CBC_256_CML][i - 1] * l0 / l1; - c[D_IGE_128_AES][i] = c[D_IGE_128_AES][i - 1] * l0 / l1; - c[D_IGE_192_AES][i] = c[D_IGE_192_AES][i - 1] * l0 / l1; - c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1; - } - -# ifndef OPENSSL_NO_RSA - rsa_c[R_RSA_512][0] = count / 2000; - rsa_c[R_RSA_512][1] = count / 400; - for (i = 1; i < RSA_NUM; i++) { - rsa_c[i][0] = rsa_c[i - 1][0] / 8; - rsa_c[i][1] = rsa_c[i - 1][1] / 4; - if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0) - rsa_doit[i] = 0; - else { - if (rsa_c[i][0] == 0) { - rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */ - rsa_c[i][1] = 20; - } - } - } -# endif - -# ifndef OPENSSL_NO_DSA - dsa_c[R_DSA_512][0] = count / 1000; - dsa_c[R_DSA_512][1] = count / 1000 / 2; - for (i = 1; i < DSA_NUM; i++) { - dsa_c[i][0] = dsa_c[i - 1][0] / 4; - dsa_c[i][1] = dsa_c[i - 1][1] / 4; - if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0) - dsa_doit[i] = 0; - else { - if (dsa_c[i][0] == 0) { - dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */ - dsa_c[i][1] = 1; - } - } - } -# endif - -# ifndef OPENSSL_NO_EC - ecdsa_c[R_EC_P160][0] = count / 1000; - ecdsa_c[R_EC_P160][1] = count / 1000 / 2; - for (i = R_EC_P192; i <= R_EC_P521; i++) { - ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; - ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; - if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) - ecdsa_doit[i] = 0; - else { - if (ecdsa_c[i][0] == 0) { - ecdsa_c[i][0] = 1; - ecdsa_c[i][1] = 1; - } - } - } -# ifndef OPENSSL_NO_EC2M - ecdsa_c[R_EC_K163][0] = count / 1000; - ecdsa_c[R_EC_K163][1] = count / 1000 / 2; - for (i = R_EC_K233; i <= R_EC_K571; i++) { - ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; - ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; - if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) - ecdsa_doit[i] = 0; - else { - if (ecdsa_c[i][0] == 0) { - ecdsa_c[i][0] = 1; - ecdsa_c[i][1] = 1; - } - } - } - ecdsa_c[R_EC_B163][0] = count / 1000; - ecdsa_c[R_EC_B163][1] = count / 1000 / 2; - for (i = R_EC_B233; i <= R_EC_B571; i++) { - ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2; - ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2; - if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0) - ecdsa_doit[i] = 0; - else { - if (ecdsa_c[i][0] == 0) { - ecdsa_c[i][0] = 1; - ecdsa_c[i][1] = 1; - } - } - } -# endif - - ecdh_c[R_EC_P160][0] = count / 1000; - for (i = R_EC_P192; i <= R_EC_P521; i++) { - ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; - if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) - ecdh_doit[i] = 0; - else { - if (ecdh_c[i][0] == 0) { - ecdh_c[i][0] = 1; - } - } - } -# ifndef OPENSSL_NO_EC2M - ecdh_c[R_EC_K163][0] = count / 1000; - for (i = R_EC_K233; i <= R_EC_K571; i++) { - ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; - if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) - ecdh_doit[i] = 0; - else { - if (ecdh_c[i][0] == 0) { - ecdh_c[i][0] = 1; - } - } - } - ecdh_c[R_EC_B163][0] = count / 1000; - for (i = R_EC_B233; i <= R_EC_B571; i++) { - ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; - if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) - ecdh_doit[i] = 0; - else { - if (ecdh_c[i][0] == 0) { - ecdh_c[i][0] = 1; - } - } - } -# endif - /* repeated code good to factorize */ - ecdh_c[R_EC_BRP256R1][0] = count / 1000; - for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) { - ecdh_c[i][0] = ecdh_c[i - 2][0] / 2; - if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) - ecdh_doit[i] = 0; - else { - if (ecdh_c[i][0] == 0) { - ecdh_c[i][0] = 1; - } - } - } - ecdh_c[R_EC_BRP256T1][0] = count / 1000; - for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) { - ecdh_c[i][0] = ecdh_c[i - 2][0] / 2; - if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0) - ecdh_doit[i] = 0; - else { - if (ecdh_c[i][0] == 0) { - ecdh_c[i][0] = 1; - } - } - } - /* default iteration count for the last two EC Curves */ - ecdh_c[R_EC_X25519][0] = count / 1800; - ecdh_c[R_EC_X448][0] = count / 7200; - - eddsa_c[R_EC_Ed25519][0] = count / 1800; - eddsa_c[R_EC_Ed448][0] = count / 7200; -# endif - -# else -/* not worth fixing */ -# error "You cannot disable DES on systems without SIGALRM." -# endif /* OPENSSL_NO_DES */ -#elif SIGALRM > 0 +#if SIGALRM > 0 signal(SIGALRM, alarmed); -#endif /* SIGALRM */ +#endif -#ifndef OPENSSL_NO_MD2 if (doit[D_MD2]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum], @@ -2158,10 +1871,11 @@ count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs); d = Time_F(STOP); print_result(D_MD2, testnum, count, d); + if (count < 0) + break; } } -#endif -#ifndef OPENSSL_NO_MDC2 + if (doit[D_MDC2]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum], @@ -2170,11 +1884,11 @@ count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs); d = Time_F(STOP); print_result(D_MDC2, testnum, count, d); + if (count < 0) + break; } } -#endif -#ifndef OPENSSL_NO_MD4 if (doit[D_MD4]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum], @@ -2183,11 +1897,11 @@ count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs); d = Time_F(STOP); print_result(D_MD4, testnum, count, d); + if (count < 0) + break; } } -#endif -#ifndef OPENSSL_NO_MD5 if (doit[D_MD5]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum], @@ -2196,35 +1910,11 @@ count = run_benchmark(async_jobs, MD5_loop, loopargs); d = Time_F(STOP); print_result(D_MD5, testnum, count, d); + if (count < 0) + break; } } - if (doit[D_HMAC]) { - static const char hmac_key[] = "This is a key..."; - int len = strlen(hmac_key); - - for (i = 0; i < loopargs_len; i++) { - loopargs[i].hctx = HMAC_CTX_new(); - if (loopargs[i].hctx == NULL) { - BIO_printf(bio_err, "HMAC malloc failure, exiting..."); - exit(1); - } - - HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL); - } - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum], - seconds.sym); - Time_F(START); - count = run_benchmark(async_jobs, HMAC_loop, loopargs); - d = Time_F(STOP); - print_result(D_HMAC, testnum, count, d); - } - for (i = 0; i < loopargs_len; i++) { - HMAC_CTX_free(loopargs[i].hctx); - } - } -#endif if (doit[D_SHA1]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum], @@ -2233,8 +1923,11 @@ count = run_benchmark(async_jobs, SHA1_loop, loopargs); d = Time_F(STOP); print_result(D_SHA1, testnum, count, d); + if (count < 0) + break; } } + if (doit[D_SHA256]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_SHA256], c[D_SHA256][testnum], @@ -2243,8 +1936,11 @@ count = run_benchmark(async_jobs, SHA256_loop, loopargs); d = Time_F(STOP); print_result(D_SHA256, testnum, count, d); + if (count < 0) + break; } } + if (doit[D_SHA512]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_SHA512], c[D_SHA512][testnum], @@ -2253,9 +1949,11 @@ count = run_benchmark(async_jobs, SHA512_loop, loopargs); d = Time_F(STOP); print_result(D_SHA512, testnum, count, d); + if (count < 0) + break; } } -#ifndef OPENSSL_NO_WHIRLPOOL + if (doit[D_WHIRLPOOL]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum], @@ -2264,11 +1962,11 @@ count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs); d = Time_F(STOP); print_result(D_WHIRLPOOL, testnum, count, d); + if (count < 0) + break; } } -#endif -#ifndef OPENSSL_NO_RMD160 if (doit[D_RMD160]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_RMD160], c[D_RMD160][testnum], @@ -2277,319 +1975,215 @@ count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs); d = Time_F(STOP); print_result(D_RMD160, testnum, count, d); + if (count < 0) + break; } } -#endif -#ifndef OPENSSL_NO_RC4 - if (doit[D_RC4]) { + + if (doit[D_HMAC]) { + static const char hmac_key[] = "This is a key..."; + int len = strlen(hmac_key); + OSSL_PARAM params[3]; + + mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", app_get0_propq()); + if (mac == NULL || evp_mac_mdname == NULL) + goto end; + + evp_hmac_name = app_malloc(sizeof("hmac()") + strlen(evp_mac_mdname), + "HMAC name"); + sprintf(evp_hmac_name, "hmac(%s)", evp_mac_mdname); + names[D_HMAC] = evp_hmac_name; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + evp_mac_mdname, 0); + params[1] = + OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (char *)hmac_key, len); + params[2] = OSSL_PARAM_construct_end(); + + for (i = 0; i < loopargs_len; i++) { + loopargs[i].mctx = EVP_MAC_CTX_new(mac); + if (loopargs[i].mctx == NULL) + goto end; + + if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params)) + goto skip_hmac; /* Digest not found */ + } for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum], + print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum], seconds.sym); Time_F(START); - count = run_benchmark(async_jobs, RC4_loop, loopargs); + count = run_benchmark(async_jobs, HMAC_loop, loopargs); d = Time_F(STOP); - print_result(D_RC4, testnum, count, d); + print_result(D_HMAC, testnum, count, d); + if (count < 0) + break; } + for (i = 0; i < loopargs_len; i++) + EVP_MAC_CTX_free(loopargs[i].mctx); + EVP_MAC_free(mac); + mac = NULL; } -#endif -#ifndef OPENSSL_NO_DES +skip_hmac: if (doit[D_CBC_DES]) { - for (testnum = 0; testnum < size_num; testnum++) { + int st = 1; + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx("des-cbc", deskey, + sizeof(deskey) / 3); + st = loopargs[i].ctx != NULL; + } + algindex = D_CBC_DES; + for (testnum = 0; st && testnum < size_num; testnum++) { print_message(names[D_CBC_DES], c[D_CBC_DES][testnum], lengths[testnum], seconds.sym); Time_F(START); - count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs); + count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); d = Time_F(STOP); print_result(D_CBC_DES, testnum, count, d); } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } if (doit[D_EDE3_DES]) { - for (testnum = 0; testnum < size_num; testnum++) { + int st = 1; + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx("des-ede3-cbc", deskey, + sizeof(deskey)); + st = loopargs[i].ctx != NULL; + } + algindex = D_EDE3_DES; + for (testnum = 0; st && testnum < size_num; testnum++) { print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum], lengths[testnum], seconds.sym); Time_F(START); count = - run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs); + run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); d = Time_F(STOP); print_result(D_EDE3_DES, testnum, count, d); } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } -#endif - if (doit[D_CBC_128_AES]) { - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs); - d = Time_F(STOP); - print_result(D_CBC_128_AES, testnum, count, d); - } - } - if (doit[D_CBC_192_AES]) { - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs); - d = Time_F(STOP); - print_result(D_CBC_192_AES, testnum, count, d); - } - } - if (doit[D_CBC_256_AES]) { - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs); - d = Time_F(STOP); - print_result(D_CBC_256_AES, testnum, count, d); - } - } + for (k = 0; k < 3; k++) { + algindex = D_CBC_128_AES + k; + if (doit[algindex]) { + int st = 1; - if (doit[D_IGE_128_AES]) { - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs); - d = Time_F(STOP); - print_result(D_IGE_128_AES, testnum, count, d); + keylen = 16 + k * 8; + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx(names[algindex], + key32, keylen); + st = loopargs[i].ctx != NULL; + } + + for (testnum = 0; st && testnum < size_num; testnum++) { + print_message(names[algindex], c[algindex][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); + d = Time_F(STOP); + print_result(algindex, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } } - if (doit[D_IGE_192_AES]) { - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs); - d = Time_F(STOP); - print_result(D_IGE_192_AES, testnum, count, d); + + for (k = 0; k < 3; k++) { + algindex = D_CBC_128_CML + k; + if (doit[algindex]) { + int st = 1; + + keylen = 16 + k * 8; + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx(names[algindex], + key32, keylen); + st = loopargs[i].ctx != NULL; + } + + for (testnum = 0; st && testnum < size_num; testnum++) { + print_message(names[algindex], c[algindex][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); + d = Time_F(STOP); + print_result(algindex, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } } - if (doit[D_IGE_256_AES]) { - for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs); - d = Time_F(STOP); - print_result(D_IGE_256_AES, testnum, count, d); + + for (algindex = D_RC4; algindex <= D_CBC_CAST; algindex++) { + if (doit[algindex]) { + int st = 1; + + keylen = 16; + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx(names[algindex], + key32, keylen); + st = loopargs[i].ctx != NULL; + } + + for (testnum = 0; st && testnum < size_num; testnum++) { + print_message(names[algindex], c[algindex][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); + d = Time_F(STOP); + print_result(algindex, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } } if (doit[D_GHASH]) { + static const char gmac_iv[] = "0123456789ab"; + OSSL_PARAM params[3]; + + mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", app_get0_propq()); + if (mac == NULL) + goto end; + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER, + "aes-128-gcm", 0); + params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV, + (char *)gmac_iv, + sizeof(gmac_iv) - 1); + params[2] = OSSL_PARAM_construct_end(); + for (i = 0; i < loopargs_len; i++) { - loopargs[i].gcm_ctx = - CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt); - CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx, - (unsigned char *)"0123456789ab", 12); - } + loopargs[i].mctx = EVP_MAC_CTX_new(mac); + if (loopargs[i].mctx == NULL) + goto end; + if (!EVP_MAC_init(loopargs[i].mctx, key32, 16, params)) + goto end; + } for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_GHASH], c[D_GHASH][testnum], - lengths[testnum], seconds.sym); + print_message(names[D_GHASH], c[D_GHASH][testnum], lengths[testnum], + seconds.sym); Time_F(START); - count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs); + count = run_benchmark(async_jobs, GHASH_loop, loopargs); d = Time_F(STOP); print_result(D_GHASH, testnum, count, d); + if (count < 0) + break; } for (i = 0; i < loopargs_len; i++) - CRYPTO_gcm128_release(loopargs[i].gcm_ctx); - } -#ifndef OPENSSL_NO_CAMELLIA - if (doit[D_CBC_128_CML]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_128_CML]); - doit[D_CBC_128_CML] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - for (count = 0; COND(c[D_CBC_128_CML][testnum]); count++) - Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &camellia_ks1, - iv, CAMELLIA_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_128_CML, testnum, count, d); - } - } - if (doit[D_CBC_192_CML]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_192_CML]); - doit[D_CBC_192_CML] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum], - lengths[testnum], seconds.sym); - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported, exiting..."); - exit(1); - } - Time_F(START); - for (count = 0; COND(c[D_CBC_192_CML][testnum]); count++) - Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &camellia_ks2, - iv, CAMELLIA_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_192_CML, testnum, count, d); - } - } - if (doit[D_CBC_256_CML]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_256_CML]); - doit[D_CBC_256_CML] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - for (count = 0; COND(c[D_CBC_256_CML][testnum]); count++) - Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &camellia_ks3, - iv, CAMELLIA_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_256_CML, testnum, count, d); - } - } -#endif -#ifndef OPENSSL_NO_IDEA - if (doit[D_CBC_IDEA]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_IDEA]); - doit[D_CBC_IDEA] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - for (count = 0; COND(c[D_CBC_IDEA][testnum]); count++) - IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &idea_ks, - iv, IDEA_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_IDEA, testnum, count, d); - } - } -#endif -#ifndef OPENSSL_NO_SEED - if (doit[D_CBC_SEED]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_SEED]); - doit[D_CBC_SEED] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - for (count = 0; COND(c[D_CBC_SEED][testnum]); count++) - SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &seed_ks, iv, 1); - d = Time_F(STOP); - print_result(D_CBC_SEED, testnum, count, d); - } - } -#endif -#ifndef OPENSSL_NO_RC2 - if (doit[D_CBC_RC2]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_RC2]); - doit[D_CBC_RC2] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum], - lengths[testnum], seconds.sym); - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported, exiting..."); - exit(1); - } - Time_F(START); - for (count = 0; COND(c[D_CBC_RC2][testnum]); count++) - RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &rc2_ks, - iv, RC2_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_RC2, testnum, count, d); - } - } -#endif -#ifndef OPENSSL_NO_RC5 - if (doit[D_CBC_RC5]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_RC5]); - doit[D_CBC_RC5] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum], - lengths[testnum], seconds.sym); - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported, exiting..."); - exit(1); - } - Time_F(START); - for (count = 0; COND(c[D_CBC_RC5][testnum]); count++) - RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &rc5_ks, - iv, RC5_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_RC5, testnum, count, d); - } + EVP_MAC_CTX_free(loopargs[i].mctx); + EVP_MAC_free(mac); + mac = NULL; } -#endif -#ifndef OPENSSL_NO_BF - if (doit[D_CBC_BF]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_BF]); - doit[D_CBC_BF] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_BF], c[D_CBC_BF][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - for (count = 0; COND(c[D_CBC_BF][testnum]); count++) - BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &bf_ks, - iv, BF_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_BF, testnum, count, d); - } - } -#endif -#ifndef OPENSSL_NO_CAST - if (doit[D_CBC_CAST]) { - if (async_jobs > 0) { - BIO_printf(bio_err, "Async mode is not supported with %s\n", - names[D_CBC_CAST]); - doit[D_CBC_CAST] = 0; - } - for (testnum = 0; testnum < size_num && async_init == 0; testnum++) { - print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - for (count = 0; COND(c[D_CBC_CAST][testnum]); count++) - CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf, - (size_t)lengths[testnum], &cast_ks, - iv, CAST_ENCRYPT); - d = Time_F(STOP); - print_result(D_CBC_CAST, testnum, count, d); - } - } -#endif + if (doit[D_RAND]) { for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum], @@ -2603,20 +2197,20 @@ if (doit[D_EVP]) { if (evp_cipher != NULL) { - int (*loopfunc)(void *args) = EVP_Update_loop; + int (*loopfunc) (void *) = EVP_Update_loop; - if (multiblock && (EVP_CIPHER_flags(evp_cipher) & + if (multiblock && (EVP_CIPHER_get_flags(evp_cipher) & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) { multiblock_speed(evp_cipher, lengths_single, &seconds); ret = 0; goto end; } - names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)); + names[D_EVP] = EVP_CIPHER_get0_name(evp_cipher); - if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) { + if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_CCM_MODE) { loopfunc = EVP_Update_loop_ccm; - } else if (aead && (EVP_CIPHER_flags(evp_cipher) & + } else if (aead && (EVP_CIPHER_get_flags(evp_cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { loopfunc = EVP_Update_loop_aead; if (lengths == lengths_list) { @@ -2626,7 +2220,7 @@ } for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_EVP], save_count, lengths[testnum], + print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum], seconds.sym); for (k = 0; k < loopargs_len; k++) { @@ -2644,7 +2238,7 @@ EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0); - keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx); + keylen = EVP_CIPHER_CTX_get_key_length(loopargs[k].ctx); loopargs[k].key = app_malloc(keylen, "evp_cipher key"); EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key); if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, @@ -2654,81 +2248,139 @@ exit(1); } OPENSSL_clear_free(loopargs[k].key, keylen); + + /* SIV mode only allows for a single Update operation */ + if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_SIV_MODE) + (void)EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, + EVP_CTRL_SET_SPEED, 1, NULL); } Time_F(START); count = run_benchmark(async_jobs, loopfunc, loopargs); d = Time_F(STOP); - for (k = 0; k < loopargs_len; k++) { + for (k = 0; k < loopargs_len; k++) EVP_CIPHER_CTX_free(loopargs[k].ctx); - } print_result(D_EVP, testnum, count, d); } - } else if (evp_md != NULL) { - names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md)); + } else if (evp_md_name != NULL) { + names[D_EVP] = evp_md_name; for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_EVP], save_count, lengths[testnum], + print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum], seconds.sym); Time_F(START); - count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs); + count = run_benchmark(async_jobs, EVP_Digest_md_loop, loopargs); d = Time_F(STOP); print_result(D_EVP, testnum, count, d); + if (count < 0) + break; } } } + if (doit[D_EVP_CMAC]) { + OSSL_PARAM params[3]; + EVP_CIPHER *cipher = NULL; + + mac = EVP_MAC_fetch(app_get0_libctx(), "CMAC", app_get0_propq()); + if (mac == NULL || evp_mac_ciphername == NULL) + goto end; + if (!opt_cipher(evp_mac_ciphername, &cipher)) + goto end; + + keylen = EVP_CIPHER_get_key_length(cipher); + EVP_CIPHER_free(cipher); + if (keylen <= 0 || keylen > (int)sizeof(key32)) { + BIO_printf(bio_err, "\nRequested CMAC cipher with unsupported key length.\n"); + goto end; + } + evp_cmac_name = app_malloc(sizeof("cmac()") + + strlen(evp_mac_ciphername), "CMAC name"); + sprintf(evp_cmac_name, "cmac(%s)", evp_mac_ciphername); + names[D_EVP_CMAC] = evp_cmac_name; + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER, + evp_mac_ciphername, 0); + params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (char *)key32, keylen); + params[2] = OSSL_PARAM_construct_end(); + + for (i = 0; i < loopargs_len; i++) { + loopargs[i].mctx = EVP_MAC_CTX_new(mac); + if (loopargs[i].mctx == NULL) + goto end; + + if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params)) + goto end; + } + + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_EVP_CMAC], c[D_EVP_CMAC][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, CMAC_loop, loopargs); + d = Time_F(STOP); + print_result(D_EVP_CMAC, testnum, count, d); + if (count < 0) + break; + } + for (i = 0; i < loopargs_len; i++) + EVP_MAC_CTX_free(loopargs[i].mctx); + EVP_MAC_free(mac); + mac = NULL; + } + for (i = 0; i < loopargs_len; i++) if (RAND_bytes(loopargs[i].buf, 36) <= 0) goto end; -#ifndef OPENSSL_NO_RSA for (testnum = 0; testnum < RSA_NUM; testnum++) { + EVP_PKEY *rsa_key = NULL; int st = 0; + if (!rsa_doit[testnum]) continue; - for (i = 0; i < loopargs_len; i++) { - if (primes > 2) { - /* we haven't set keys yet, generate multi-prime RSA keys */ - BIGNUM *bn = BN_new(); - - if (bn == NULL) - goto end; - if (!BN_set_word(bn, RSA_F4)) { - BN_free(bn); - goto end; - } - BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n", - rsa_choices[testnum].name); + if (primes > RSA_DEFAULT_PRIME_NUM) { + /* we haven't set keys yet, generate multi-prime RSA keys */ + bn = BN_new(); + st = bn != NULL + && BN_set_word(bn, RSA_F4) + && init_gen_str(&genctx, "RSA", NULL, 0, NULL, NULL) + && EVP_PKEY_CTX_set_rsa_keygen_bits(genctx, rsa_keys[testnum].bits) > 0 + && EVP_PKEY_CTX_set1_rsa_keygen_pubexp(genctx, bn) > 0 + && EVP_PKEY_CTX_set_rsa_keygen_primes(genctx, primes) > 0 + && EVP_PKEY_keygen(genctx, &rsa_key); + BN_free(bn); + bn = NULL; + EVP_PKEY_CTX_free(genctx); + genctx = NULL; + } else { + const unsigned char *p = rsa_keys[testnum].data; - loopargs[i].rsa_key[testnum] = RSA_new(); - if (loopargs[i].rsa_key[testnum] == NULL) { - BN_free(bn); - goto end; - } + st = (rsa_key = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p, + rsa_keys[testnum].length)) != NULL; + } - if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum], - rsa_bits[testnum], - primes, bn, NULL)) { - BN_free(bn); - goto end; - } - BN_free(bn); - } - st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2, - &loopargs[i].siglen, loopargs[i].rsa_key[testnum]); - if (st == 0) - break; + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].rsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, NULL); + loopargs[i].sigsize = loopargs[i].buflen; + if (loopargs[i].rsa_sign_ctx[testnum] == NULL + || EVP_PKEY_sign_init(loopargs[i].rsa_sign_ctx[testnum]) <= 0 + || EVP_PKEY_sign(loopargs[i].rsa_sign_ctx[testnum], + loopargs[i].buf2, + &loopargs[i].sigsize, + loopargs[i].buf, 36) <= 0) + st = 0; } - if (st == 0) { + if (!st) { BIO_printf(bio_err, - "RSA sign failure. No RSA sign will be done.\n"); + "RSA sign setup failure. No RSA sign will be done.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; } else { pkey_print_message("private", "rsa", - rsa_c[testnum][0], rsa_bits[testnum], + rsa_c[testnum][0], rsa_keys[testnum].bits, seconds.rsa); /* RSA_blinding_on(rsa_key[testnum],NULL); */ Time_F(START); @@ -2737,25 +2389,30 @@ BIO_printf(bio_err, mr ? "+R1:%ld:%d:%.2f\n" : "%ld %u bits private RSA's in %.2fs\n", - count, rsa_bits[testnum], d); + count, rsa_keys[testnum].bits, d); rsa_results[testnum][0] = (double)count / d; - rsa_count = count; - } - - for (i = 0; i < loopargs_len; i++) { - st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2, - loopargs[i].siglen, loopargs[i].rsa_key[testnum]); - if (st <= 0) - break; + op_count = count; + } + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].rsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, + NULL); + if (loopargs[i].rsa_verify_ctx[testnum] == NULL + || EVP_PKEY_verify_init(loopargs[i].rsa_verify_ctx[testnum]) <= 0 + || EVP_PKEY_verify(loopargs[i].rsa_verify_ctx[testnum], + loopargs[i].buf2, + loopargs[i].sigsize, + loopargs[i].buf, 36) <= 0) + st = 0; } - if (st <= 0) { + if (!st) { BIO_printf(bio_err, - "RSA verify failure. No RSA verify will be done.\n"); + "RSA verify setup failure. No RSA verify will be done.\n"); ERR_print_errors(bio_err); rsa_doit[testnum] = 0; } else { pkey_print_message("public", "rsa", - rsa_c[testnum][1], rsa_bits[testnum], + rsa_c[testnum][1], rsa_keys[testnum].bits, seconds.rsa); Time_F(START); count = run_benchmark(async_jobs, RSA_verify_loop, loopargs); @@ -2763,41 +2420,44 @@ BIO_printf(bio_err, mr ? "+R2:%ld:%d:%.2f\n" : "%ld %u bits public RSA's in %.2fs\n", - count, rsa_bits[testnum], d); + count, rsa_keys[testnum].bits, d); rsa_results[testnum][1] = (double)count / d; } - if (rsa_count <= 1) { + if (op_count <= 1) { /* if longer than 10s, don't do any more */ - for (testnum++; testnum < RSA_NUM; testnum++) - rsa_doit[testnum] = 0; + stop_it(rsa_doit, testnum); } + EVP_PKEY_free(rsa_key); } -#endif /* OPENSSL_NO_RSA */ - - for (i = 0; i < loopargs_len; i++) - if (RAND_bytes(loopargs[i].buf, 36) <= 0) - goto end; -#ifndef OPENSSL_NO_DSA for (testnum = 0; testnum < DSA_NUM; testnum++) { - int st = 0; + EVP_PKEY *dsa_key = NULL; + int st; + if (!dsa_doit[testnum]) continue; - /* DSA_generate_key(dsa_key[testnum]); */ - /* DSA_sign_setup(dsa_key[testnum],NULL); */ - for (i = 0; i < loopargs_len; i++) { - st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2, - &loopargs[i].siglen, loopargs[i].dsa_key[testnum]); - if (st == 0) - break; + st = (dsa_key = get_dsa(dsa_bits[testnum])) != NULL; + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].dsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key, + NULL); + loopargs[i].sigsize = loopargs[i].buflen; + if (loopargs[i].dsa_sign_ctx[testnum] == NULL + || EVP_PKEY_sign_init(loopargs[i].dsa_sign_ctx[testnum]) <= 0 + + || EVP_PKEY_sign(loopargs[i].dsa_sign_ctx[testnum], + loopargs[i].buf2, + &loopargs[i].sigsize, + loopargs[i].buf, 20) <= 0) + st = 0; } - if (st == 0) { + if (!st) { BIO_printf(bio_err, - "DSA sign failure. No DSA sign will be done.\n"); + "DSA sign setup failure. No DSA sign will be done.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; } else { pkey_print_message("sign", "dsa", dsa_c[testnum][0], dsa_bits[testnum], @@ -2810,18 +2470,23 @@ : "%ld %u bits DSA signs in %.2fs\n", count, dsa_bits[testnum], d); dsa_results[testnum][0] = (double)count / d; - rsa_count = count; - } - - for (i = 0; i < loopargs_len; i++) { - st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2, - loopargs[i].siglen, loopargs[i].dsa_key[testnum]); - if (st <= 0) - break; + op_count = count; + } + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].dsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(dsa_key, + NULL); + if (loopargs[i].dsa_verify_ctx[testnum] == NULL + || EVP_PKEY_verify_init(loopargs[i].dsa_verify_ctx[testnum]) <= 0 + || EVP_PKEY_verify(loopargs[i].dsa_verify_ctx[testnum], + loopargs[i].buf2, + loopargs[i].sigsize, + loopargs[i].buf, 36) <= 0) + st = 0; } - if (st <= 0) { + if (!st) { BIO_printf(bio_err, - "DSA verify failure. No DSA verify will be done.\n"); + "DSA verify setup failure. No DSA verify will be done.\n"); ERR_print_errors(bio_err); dsa_doit[testnum] = 0; } else { @@ -2838,214 +2503,137 @@ dsa_results[testnum][1] = (double)count / d; } - if (rsa_count <= 1) { + if (op_count <= 1) { /* if longer than 10s, don't do any more */ - for (testnum++; testnum < DSA_NUM; testnum++) - dsa_doit[testnum] = 0; + stop_it(dsa_doit, testnum); } + EVP_PKEY_free(dsa_key); } -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_EC for (testnum = 0; testnum < ECDSA_NUM; testnum++) { - int st = 1; + EVP_PKEY *ecdsa_key = NULL; + int st; if (!ecdsa_doit[testnum]) - continue; /* Ignore Curve */ - for (i = 0; i < loopargs_len; i++) { - loopargs[i].ecdsa[testnum] = - EC_KEY_new_by_curve_name(test_curves[testnum].nid); - if (loopargs[i].ecdsa[testnum] == NULL) { + continue; + + st = (ecdsa_key = get_ecdsa(&ec_curves[testnum])) != NULL; + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ecdsa_sign_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key, + NULL); + loopargs[i].sigsize = loopargs[i].buflen; + if (loopargs[i].ecdsa_sign_ctx[testnum] == NULL + || EVP_PKEY_sign_init(loopargs[i].ecdsa_sign_ctx[testnum]) <= 0 + + || EVP_PKEY_sign(loopargs[i].ecdsa_sign_ctx[testnum], + loopargs[i].buf2, + &loopargs[i].sigsize, + loopargs[i].buf, 20) <= 0) st = 0; - break; - } } - if (st == 0) { - BIO_printf(bio_err, "ECDSA failure.\n"); + if (!st) { + BIO_printf(bio_err, + "ECDSA sign setup failure. No ECDSA sign will be done.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; } else { - for (i = 0; i < loopargs_len; i++) { - EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL); - /* Perform ECDSA signature test */ - EC_KEY_generate_key(loopargs[i].ecdsa[testnum]); - st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2, - &loopargs[i].siglen, - loopargs[i].ecdsa[testnum]); - if (st == 0) - break; - } - if (st == 0) { - BIO_printf(bio_err, - "ECDSA sign failure. No ECDSA sign will be done.\n"); - ERR_print_errors(bio_err); - rsa_count = 1; - } else { - pkey_print_message("sign", "ecdsa", - ecdsa_c[testnum][0], - test_curves[testnum].bits, seconds.ecdsa); - Time_F(START); - count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs); - d = Time_F(STOP); - - BIO_printf(bio_err, - mr ? "+R5:%ld:%u:%.2f\n" : - "%ld %u bits ECDSA signs in %.2fs \n", - count, test_curves[testnum].bits, d); - ecdsa_results[testnum][0] = (double)count / d; - rsa_count = count; - } - - /* Perform ECDSA verification test */ - for (i = 0; i < loopargs_len; i++) { - st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2, - loopargs[i].siglen, - loopargs[i].ecdsa[testnum]); - if (st != 1) - break; - } - if (st != 1) { - BIO_printf(bio_err, - "ECDSA verify failure. No ECDSA verify will be done.\n"); - ERR_print_errors(bio_err); - ecdsa_doit[testnum] = 0; - } else { - pkey_print_message("verify", "ecdsa", - ecdsa_c[testnum][1], - test_curves[testnum].bits, seconds.ecdsa); - Time_F(START); - count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs); - d = Time_F(STOP); - BIO_printf(bio_err, - mr ? "+R6:%ld:%u:%.2f\n" - : "%ld %u bits ECDSA verify in %.2fs\n", - count, test_curves[testnum].bits, d); - ecdsa_results[testnum][1] = (double)count / d; - } + pkey_print_message("sign", "ecdsa", + ecdsa_c[testnum][0], ec_curves[testnum].bits, + seconds.ecdsa); + Time_F(START); + count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R5:%ld:%u:%.2f\n" + : "%ld %u bits ECDSA signs in %.2fs\n", + count, ec_curves[testnum].bits, d); + ecdsa_results[testnum][0] = (double)count / d; + op_count = count; + } + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ecdsa_verify_ctx[testnum] = EVP_PKEY_CTX_new(ecdsa_key, + NULL); + if (loopargs[i].ecdsa_verify_ctx[testnum] == NULL + || EVP_PKEY_verify_init(loopargs[i].ecdsa_verify_ctx[testnum]) <= 0 + || EVP_PKEY_verify(loopargs[i].ecdsa_verify_ctx[testnum], + loopargs[i].buf2, + loopargs[i].sigsize, + loopargs[i].buf, 20) <= 0) + st = 0; + } + if (!st) { + BIO_printf(bio_err, + "ECDSA verify setup failure. No ECDSA verify will be done.\n"); + ERR_print_errors(bio_err); + ecdsa_doit[testnum] = 0; + } else { + pkey_print_message("verify", "ecdsa", + ecdsa_c[testnum][1], ec_curves[testnum].bits, + seconds.ecdsa); + Time_F(START); + count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R6:%ld:%u:%.2f\n" + : "%ld %u bits ECDSA verify in %.2fs\n", + count, ec_curves[testnum].bits, d); + ecdsa_results[testnum][1] = (double)count / d; + } - if (rsa_count <= 1) { - /* if longer than 10s, don't do any more */ - for (testnum++; testnum < ECDSA_NUM; testnum++) - ecdsa_doit[testnum] = 0; - } + if (op_count <= 1) { + /* if longer than 10s, don't do any more */ + stop_it(ecdsa_doit, testnum); } } for (testnum = 0; testnum < EC_NUM; testnum++) { - int ecdh_checks = 1; - - if (!ecdh_doit[testnum]) - continue; - - for (i = 0; i < loopargs_len; i++) { - EVP_PKEY_CTX *kctx = NULL; - EVP_PKEY_CTX *test_ctx = NULL; - EVP_PKEY_CTX *ctx = NULL; - EVP_PKEY *key_A = NULL; - EVP_PKEY *key_B = NULL; - size_t outlen; - size_t test_outlen; - - /* Ensure that the error queue is empty */ - if (ERR_peek_error()) { - BIO_printf(bio_err, - "WARNING: the error queue contains previous unhandled errors.\n"); - ERR_print_errors(bio_err); - } - - /* Let's try to create a ctx directly from the NID: this works for - * curves like Curve25519 that are not implemented through the low - * level EC interface. - * If this fails we try creating a EVP_PKEY_EC generic param ctx, - * then we set the curve by NID before deriving the actual keygen - * ctx for that specific curve. */ - kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */ - if (!kctx) { - EVP_PKEY_CTX *pctx = NULL; - EVP_PKEY *params = NULL; - - /* If we reach this code EVP_PKEY_CTX_new_id() failed and a - * "int_ctx_new:unsupported algorithm" error was added to the - * error queue. - * We remove it from the error queue as we are handling it. */ - unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */ - if (error == ERR_peek_last_error() && /* oldest and latest errors match */ - /* check that the error origin matches */ - ERR_GET_LIB(error) == ERR_LIB_EVP && - ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW && - ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM) - ERR_get_error(); /* pop error from queue */ - if (ERR_peek_error()) { - BIO_printf(bio_err, - "Unhandled error in the error queue during ECDH init.\n"); - ERR_print_errors(bio_err); - rsa_count = 1; - break; - } + int ecdh_checks = 1; - if ( /* Create the context for parameter generation */ - !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) || - /* Initialise the parameter generation */ - !EVP_PKEY_paramgen_init(pctx) || - /* Set the curve by NID */ - !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, - test_curves - [testnum].nid) || - /* Create the parameter object params */ - !EVP_PKEY_paramgen(pctx, ¶ms)) { - ecdh_checks = 0; - BIO_printf(bio_err, "ECDH EC params init failure.\n"); - ERR_print_errors(bio_err); - rsa_count = 1; - break; - } - /* Create the context for the key generation */ - kctx = EVP_PKEY_CTX_new(params, NULL); + if (!ecdh_doit[testnum]) + continue; - EVP_PKEY_free(params); - params = NULL; - EVP_PKEY_CTX_free(pctx); - pctx = NULL; - } - if (kctx == NULL || /* keygen ctx is not null */ - EVP_PKEY_keygen_init(kctx) <= 0/* init keygen ctx */ ) { - ecdh_checks = 0; - BIO_printf(bio_err, "ECDH keygen failure.\n"); - ERR_print_errors(bio_err); - rsa_count = 1; - break; - } + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY_CTX *test_ctx = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *key_A = NULL; + EVP_PKEY *key_B = NULL; + size_t outlen; + size_t test_outlen; - if (EVP_PKEY_keygen(kctx, &key_A) <= 0 || /* generate secret key A */ - EVP_PKEY_keygen(kctx, &key_B) <= 0 || /* generate secret key B */ - !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */ - EVP_PKEY_derive_init(ctx) <= 0 || /* init derivation ctx */ - EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 || /* set peer pubkey in ctx */ - EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 || /* determine max length */ - outlen == 0 || /* ensure outlen is a valid size */ - outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) { + if ((key_A = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key A */ + || (key_B = get_ecdsa(&ec_curves[testnum])) == NULL /* generate secret key B */ + || (ctx = EVP_PKEY_CTX_new(key_A, NULL)) == NULL /* derivation ctx from skeyA */ + || EVP_PKEY_derive_init(ctx) <= 0 /* init derivation ctx */ + || EVP_PKEY_derive_set_peer(ctx, key_B) <= 0 /* set peer pubkey in ctx */ + || EVP_PKEY_derive(ctx, NULL, &outlen) <= 0 /* determine max length */ + || outlen == 0 /* ensure outlen is a valid size */ + || outlen > MAX_ECDH_SIZE /* avoid buffer overflow */) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH key generation failure.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; break; } - /* Here we perform a test run, comparing the output of a*B and b*A; + /* + * Here we perform a test run, comparing the output of a*B and b*A; * we try this here and assume that further EVP_PKEY_derive calls * never fail, so we can skip checks in the actually benchmarked - * code, for maximum performance. */ - if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */ - !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */ - !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */ - !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */ - !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */ - !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */ - test_outlen != outlen /* compare output length */ ) { + * code, for maximum performance. + */ + if ((test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) == NULL /* test ctx from skeyB */ + || EVP_PKEY_derive_init(test_ctx) <= 0 /* init derivation test_ctx */ + || EVP_PKEY_derive_set_peer(test_ctx, key_A) <= 0 /* set peer pubkey in test_ctx */ + || EVP_PKEY_derive(test_ctx, NULL, &test_outlen) <= 0 /* determine max length */ + || EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) <= 0 /* compute a*B */ + || EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) <= 0 /* compute b*A */ + || test_outlen != outlen /* compare output length */) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH computation failure.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; break; } @@ -3055,7 +2643,7 @@ ecdh_checks = 0; BIO_printf(bio_err, "ECDH computations don't match.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; break; } @@ -3064,15 +2652,13 @@ EVP_PKEY_free(key_A); EVP_PKEY_free(key_B); - EVP_PKEY_CTX_free(kctx); - kctx = NULL; EVP_PKEY_CTX_free(test_ctx); test_ctx = NULL; } if (ecdh_checks != 0) { pkey_print_message("", "ecdh", ecdh_c[testnum][0], - test_curves[testnum].bits, seconds.ecdh); + ec_curves[testnum].bits, seconds.ecdh); Time_F(START); count = run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs); @@ -3080,15 +2666,14 @@ BIO_printf(bio_err, mr ? "+R7:%ld:%d:%.2f\n" : "%ld %u-bits ECDH ops in %.2fs\n", count, - test_curves[testnum].bits, d); + ec_curves[testnum].bits, d); ecdh_results[testnum][0] = (double)count / d; - rsa_count = count; + op_count = count; } - if (rsa_count <= 1) { + if (op_count <= 1) { /* if longer than 10s, don't do any more */ - for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++) - ecdh_doit[testnum] = 0; + stop_it(ecdh_doit, testnum); } } @@ -3105,9 +2690,14 @@ st = 0; break; } + loopargs[i].eddsa_ctx2[testnum] = EVP_MD_CTX_new(); + if (loopargs[i].eddsa_ctx2[testnum] == NULL) { + st = 0; + break; + } - if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL)) - == NULL + if ((ed_pctx = EVP_PKEY_CTX_new_id(ed_curves[testnum].nid, + NULL)) == NULL || EVP_PKEY_keygen_init(ed_pctx) <= 0 || EVP_PKEY_keygen(ed_pctx, &ed_pkey) <= 0) { st = 0; @@ -3122,16 +2712,24 @@ EVP_PKEY_free(ed_pkey); break; } + if (!EVP_DigestVerifyInit(loopargs[i].eddsa_ctx2[testnum], NULL, + NULL, NULL, ed_pkey)) { + st = 0; + EVP_PKEY_free(ed_pkey); + break; + } + EVP_PKEY_free(ed_pkey); + ed_pkey = NULL; } if (st == 0) { BIO_printf(bio_err, "EdDSA failure.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; } else { for (i = 0; i < loopargs_len; i++) { /* Perform EdDSA signature test */ - loopargs[i].sigsize = test_ed_curves[testnum].sigsize; + loopargs[i].sigsize = ed_curves[testnum].sigsize; st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum], loopargs[i].buf2, &loopargs[i].sigsize, loopargs[i].buf, 20); @@ -3142,11 +2740,11 @@ BIO_printf(bio_err, "EdDSA sign failure. No EdDSA sign will be done.\n"); ERR_print_errors(bio_err); - rsa_count = 1; + op_count = 1; } else { - pkey_print_message("sign", test_ed_curves[testnum].name, + pkey_print_message("sign", ed_curves[testnum].name, eddsa_c[testnum][0], - test_ed_curves[testnum].bits, seconds.eddsa); + ed_curves[testnum].bits, seconds.eddsa); Time_F(START); count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs); d = Time_F(STOP); @@ -3154,15 +2752,14 @@ BIO_printf(bio_err, mr ? "+R8:%ld:%u:%s:%.2f\n" : "%ld %u bits %s signs in %.2fs \n", - count, test_ed_curves[testnum].bits, - test_ed_curves[testnum].name, d); + count, ed_curves[testnum].bits, + ed_curves[testnum].name, d); eddsa_results[testnum][0] = (double)count / d; - rsa_count = count; + op_count = count; } - /* Perform EdDSA verification test */ for (i = 0; i < loopargs_len; i++) { - st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum], + st = EVP_DigestVerify(loopargs[i].eddsa_ctx2[testnum], loopargs[i].buf2, loopargs[i].sigsize, loopargs[i].buf, 20); if (st != 1) @@ -3174,62 +2771,360 @@ ERR_print_errors(bio_err); eddsa_doit[testnum] = 0; } else { - pkey_print_message("verify", test_ed_curves[testnum].name, + pkey_print_message("verify", ed_curves[testnum].name, eddsa_c[testnum][1], - test_ed_curves[testnum].bits, seconds.eddsa); + ed_curves[testnum].bits, seconds.eddsa); Time_F(START); count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, mr ? "+R9:%ld:%u:%s:%.2f\n" : "%ld %u bits %s verify in %.2fs\n", - count, test_ed_curves[testnum].bits, - test_ed_curves[testnum].name, d); + count, ed_curves[testnum].bits, + ed_curves[testnum].name, d); eddsa_results[testnum][1] = (double)count / d; } - if (rsa_count <= 1) { + if (op_count <= 1) { + /* if longer than 10s, don't do any more */ + stop_it(eddsa_doit, testnum); + } + } + } + +#ifndef OPENSSL_NO_SM2 + for (testnum = 0; testnum < SM2_NUM; testnum++) { + int st = 1; + EVP_PKEY *sm2_pkey = NULL; + + if (!sm2_doit[testnum]) + continue; /* Ignore Curve */ + /* Init signing and verification */ + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY_CTX *sm2_pctx = NULL; + EVP_PKEY_CTX *sm2_vfy_pctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + st = 0; + + loopargs[i].sm2_ctx[testnum] = EVP_MD_CTX_new(); + loopargs[i].sm2_vfy_ctx[testnum] = EVP_MD_CTX_new(); + if (loopargs[i].sm2_ctx[testnum] == NULL + || loopargs[i].sm2_vfy_ctx[testnum] == NULL) + break; + + sm2_pkey = NULL; + + st = !((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL)) == NULL + || EVP_PKEY_keygen_init(pctx) <= 0 + || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, + sm2_curves[testnum].nid) <= 0 + || EVP_PKEY_keygen(pctx, &sm2_pkey) <= 0); + EVP_PKEY_CTX_free(pctx); + if (st == 0) + break; + + st = 0; /* set back to zero */ + /* attach it sooner to rely on main final cleanup */ + loopargs[i].sm2_pkey[testnum] = sm2_pkey; + loopargs[i].sigsize = EVP_PKEY_get_size(sm2_pkey); + + sm2_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL); + sm2_vfy_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL); + if (sm2_pctx == NULL || sm2_vfy_pctx == NULL) { + EVP_PKEY_CTX_free(sm2_vfy_pctx); + break; + } + + /* attach them directly to respective ctx */ + EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_ctx[testnum], sm2_pctx); + EVP_MD_CTX_set_pkey_ctx(loopargs[i].sm2_vfy_ctx[testnum], sm2_vfy_pctx); + + /* + * No need to allow user to set an explicit ID here, just use + * the one defined in the 'draft-yang-tls-tl13-sm-suites' I-D. + */ + if (EVP_PKEY_CTX_set1_id(sm2_pctx, SM2_ID, SM2_ID_LEN) != 1 + || EVP_PKEY_CTX_set1_id(sm2_vfy_pctx, SM2_ID, SM2_ID_LEN) != 1) + break; + + if (!EVP_DigestSignInit(loopargs[i].sm2_ctx[testnum], NULL, + EVP_sm3(), NULL, sm2_pkey)) + break; + if (!EVP_DigestVerifyInit(loopargs[i].sm2_vfy_ctx[testnum], NULL, + EVP_sm3(), NULL, sm2_pkey)) + break; + st = 1; /* mark loop as succeeded */ + } + if (st == 0) { + BIO_printf(bio_err, "SM2 init failure.\n"); + ERR_print_errors(bio_err); + op_count = 1; + } else { + for (i = 0; i < loopargs_len; i++) { + /* Perform SM2 signature test */ + st = EVP_DigestSign(loopargs[i].sm2_ctx[testnum], + loopargs[i].buf2, &loopargs[i].sigsize, + loopargs[i].buf, 20); + if (st == 0) + break; + } + if (st == 0) { + BIO_printf(bio_err, + "SM2 sign failure. No SM2 sign will be done.\n"); + ERR_print_errors(bio_err); + op_count = 1; + } else { + pkey_print_message("sign", sm2_curves[testnum].name, + sm2_c[testnum][0], + sm2_curves[testnum].bits, seconds.sm2); + Time_F(START); + count = run_benchmark(async_jobs, SM2_sign_loop, loopargs); + d = Time_F(STOP); + + BIO_printf(bio_err, + mr ? "+R10:%ld:%u:%s:%.2f\n" : + "%ld %u bits %s signs in %.2fs \n", + count, sm2_curves[testnum].bits, + sm2_curves[testnum].name, d); + sm2_results[testnum][0] = (double)count / d; + op_count = count; + } + + /* Perform SM2 verification test */ + for (i = 0; i < loopargs_len; i++) { + st = EVP_DigestVerify(loopargs[i].sm2_vfy_ctx[testnum], + loopargs[i].buf2, loopargs[i].sigsize, + loopargs[i].buf, 20); + if (st != 1) + break; + } + if (st != 1) { + BIO_printf(bio_err, + "SM2 verify failure. No SM2 verify will be done.\n"); + ERR_print_errors(bio_err); + sm2_doit[testnum] = 0; + } else { + pkey_print_message("verify", sm2_curves[testnum].name, + sm2_c[testnum][1], + sm2_curves[testnum].bits, seconds.sm2); + Time_F(START); + count = run_benchmark(async_jobs, SM2_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R11:%ld:%u:%s:%.2f\n" + : "%ld %u bits %s verify in %.2fs\n", + count, sm2_curves[testnum].bits, + sm2_curves[testnum].name, d); + sm2_results[testnum][1] = (double)count / d; + } + + if (op_count <= 1) { /* if longer than 10s, don't do any more */ - for (testnum++; testnum < EdDSA_NUM; testnum++) - eddsa_doit[testnum] = 0; + for (testnum++; testnum < SM2_NUM; testnum++) + sm2_doit[testnum] = 0; } } } +#endif /* OPENSSL_NO_SM2 */ + +#ifndef OPENSSL_NO_DH + for (testnum = 0; testnum < FFDH_NUM; testnum++) { + int ffdh_checks = 1; + + if (!ffdh_doit[testnum]) + continue; + + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY *pkey_A = NULL; + EVP_PKEY *pkey_B = NULL; + EVP_PKEY_CTX *ffdh_ctx = NULL; + EVP_PKEY_CTX *test_ctx = NULL; + size_t secret_size; + size_t test_out; + + /* Ensure that the error queue is empty */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); + ERR_print_errors(bio_err); + } + + pkey_A = EVP_PKEY_new(); + if (!pkey_A) { + BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + pkey_B = EVP_PKEY_new(); + if (!pkey_B) { + BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + + ffdh_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); + if (!ffdh_ctx) { + BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + + if (EVP_PKEY_keygen_init(ffdh_ctx) <= 0) { + BIO_printf(bio_err, "Error while initialising EVP_PKEY_CTX.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + if (EVP_PKEY_CTX_set_dh_nid(ffdh_ctx, ffdh_params[testnum].nid) <= 0) { + BIO_printf(bio_err, "Error setting DH key size for keygen.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + + if (EVP_PKEY_keygen(ffdh_ctx, &pkey_A) <= 0 || + EVP_PKEY_keygen(ffdh_ctx, &pkey_B) <= 0) { + BIO_printf(bio_err, "FFDH key generation failure.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + + EVP_PKEY_CTX_free(ffdh_ctx); -#endif /* OPENSSL_NO_EC */ + /* + * check if the derivation works correctly both ways so that + * we know if future derive calls will fail, and we can skip + * error checking in benchmarked code + */ + ffdh_ctx = EVP_PKEY_CTX_new(pkey_A, NULL); + if (ffdh_ctx == NULL) { + BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + if (EVP_PKEY_derive_init(ffdh_ctx) <= 0) { + BIO_printf(bio_err, "FFDH derivation context init failure.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + if (EVP_PKEY_derive_set_peer(ffdh_ctx, pkey_B) <= 0) { + BIO_printf(bio_err, "Assigning peer key for derivation failed.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + if (EVP_PKEY_derive(ffdh_ctx, NULL, &secret_size) <= 0) { + BIO_printf(bio_err, "Checking size of shared secret failed.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + if (secret_size > MAX_FFDH_SIZE) { + BIO_printf(bio_err, "Assertion failure: shared secret too large.\n"); + op_count = 1; + ffdh_checks = 0; + break; + } + if (EVP_PKEY_derive(ffdh_ctx, + loopargs[i].secret_ff_a, + &secret_size) <= 0) { + BIO_printf(bio_err, "Shared secret derive failure.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + /* Now check from side B */ + test_ctx = EVP_PKEY_CTX_new(pkey_B, NULL); + if (!test_ctx) { + BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + if (EVP_PKEY_derive_init(test_ctx) <= 0 || + EVP_PKEY_derive_set_peer(test_ctx, pkey_A) <= 0 || + EVP_PKEY_derive(test_ctx, NULL, &test_out) <= 0 || + EVP_PKEY_derive(test_ctx, loopargs[i].secret_ff_b, &test_out) <= 0 || + test_out != secret_size) { + BIO_printf(bio_err, "FFDH computation failure.\n"); + op_count = 1; + ffdh_checks = 0; + break; + } + + /* compare the computed secrets */ + if (CRYPTO_memcmp(loopargs[i].secret_ff_a, + loopargs[i].secret_ff_b, secret_size)) { + BIO_printf(bio_err, "FFDH computations don't match.\n"); + ERR_print_errors(bio_err); + op_count = 1; + ffdh_checks = 0; + break; + } + + loopargs[i].ffdh_ctx[testnum] = ffdh_ctx; + + EVP_PKEY_free(pkey_A); + pkey_A = NULL; + EVP_PKEY_free(pkey_B); + pkey_B = NULL; + EVP_PKEY_CTX_free(test_ctx); + test_ctx = NULL; + } + if (ffdh_checks != 0) { + pkey_print_message("", "ffdh", ffdh_c[testnum][0], + ffdh_params[testnum].bits, seconds.ffdh); + Time_F(START); + count = + run_benchmark(async_jobs, FFDH_derive_key_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R12:%ld:%d:%.2f\n" : + "%ld %u-bits FFDH ops in %.2fs\n", count, + ffdh_params[testnum].bits, d); + ffdh_results[testnum][0] = (double)count / d; + op_count = count; + } + if (op_count <= 1) { + /* if longer than 10s, don't do any more */ + stop_it(ffdh_doit, testnum); + } + } +#endif /* OPENSSL_NO_DH */ #ifndef NO_FORK show_res: #endif if (!mr) { - printf("%s\n", OpenSSL_version(OPENSSL_VERSION)); + printf("version: %s\n", OpenSSL_version(OPENSSL_FULL_VERSION_STRING)); printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON)); - printf("options:"); - printf("%s ", BN_options()); -#ifndef OPENSSL_NO_MD2 - printf("%s ", MD2_options()); -#endif -#ifndef OPENSSL_NO_RC4 - printf("%s ", RC4_options()); -#endif -#ifndef OPENSSL_NO_DES - printf("%s ", DES_options()); -#endif - printf("%s ", AES_options()); -#ifndef OPENSSL_NO_IDEA - printf("%s ", IDEA_options()); -#endif -#ifndef OPENSSL_NO_BF - printf("%s ", BF_options()); -#endif - printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS)); + printf("options: %s\n", BN_options()); + printf("%s\n", OpenSSL_version(OPENSSL_CFLAGS)); + printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO)); } if (pr_header) { - if (mr) + if (mr) { printf("+H"); - else { - printf - ("The 'numbers' are in 1000s of bytes per second processed.\n"); + } else { + printf("The 'numbers' are in 1000s of bytes per second processed.\n"); printf("type "); } for (testnum = 0; testnum < size_num; testnum++) @@ -3252,7 +3147,6 @@ } printf("\n"); } -#ifndef OPENSSL_NO_RSA testnum = 1; for (k = 0; k < RSA_NUM; k++) { if (!rsa_doit[k]) @@ -3263,14 +3157,12 @@ } if (mr) printf("+F2:%u:%u:%f:%f\n", - k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]); + k, rsa_keys[k].bits, rsa_results[k][0], rsa_results[k][1]); else printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", - rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1], + rsa_keys[k].bits, 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1], rsa_results[k][0], rsa_results[k][1]); } -#endif -#ifndef OPENSSL_NO_DSA testnum = 1; for (k = 0; k < DSA_NUM; k++) { if (!dsa_doit[k]) @@ -3287,8 +3179,6 @@ dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1], dsa_results[k][0], dsa_results[k][1]); } -#endif -#ifndef OPENSSL_NO_EC testnum = 1; for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) { if (!ecdsa_doit[k]) @@ -3300,11 +3190,11 @@ if (mr) printf("+F4:%u:%u:%f:%f\n", - k, test_curves[k].bits, + k, ec_curves[k].bits, ecdsa_results[k][0], ecdsa_results[k][1]); else printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n", - test_curves[k].bits, test_curves[k].name, + ec_curves[k].bits, ec_curves[k].name, 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1], ecdsa_results[k][0], ecdsa_results[k][1]); } @@ -3319,12 +3209,12 @@ } if (mr) printf("+F5:%u:%u:%f:%f\n", - k, test_curves[k].bits, + k, ec_curves[k].bits, ecdh_results[k][0], 1.0 / ecdh_results[k][0]); else printf("%4u bits ecdh (%s) %8.4fs %8.1f\n", - test_curves[k].bits, test_curves[k].name, + ec_curves[k].bits, ec_curves[k].name, 1.0 / ecdh_results[k][0], ecdh_results[k][0]); } @@ -3339,15 +3229,56 @@ if (mr) printf("+F6:%u:%u:%s:%f:%f\n", - k, test_ed_curves[k].bits, test_ed_curves[k].name, + k, ed_curves[k].bits, ed_curves[k].name, eddsa_results[k][0], eddsa_results[k][1]); else printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n", - test_ed_curves[k].bits, test_ed_curves[k].name, + ed_curves[k].bits, ed_curves[k].name, 1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1], eddsa_results[k][0], eddsa_results[k][1]); } + +#ifndef OPENSSL_NO_SM2 + testnum = 1; + for (k = 0; k < OSSL_NELEM(sm2_doit); k++) { + if (!sm2_doit[k]) + continue; + if (testnum && !mr) { + printf("%30ssign verify sign/s verify/s\n", " "); + testnum = 0; + } + + if (mr) + printf("+F7:%u:%u:%s:%f:%f\n", + k, sm2_curves[k].bits, sm2_curves[k].name, + sm2_results[k][0], sm2_results[k][1]); + else + printf("%4u bits SM2 (%s) %8.4fs %8.4fs %8.1f %8.1f\n", + sm2_curves[k].bits, sm2_curves[k].name, + 1.0 / sm2_results[k][0], 1.0 / sm2_results[k][1], + sm2_results[k][0], sm2_results[k][1]); + } #endif +#ifndef OPENSSL_NO_DH + testnum = 1; + for (k = 0; k < FFDH_NUM; k++) { + if (!ffdh_doit[k]) + continue; + if (testnum && !mr) { + printf("%23sop op/s\n", " "); + testnum = 0; + } + if (mr) + printf("+F8:%u:%u:%f:%f\n", + k, ffdh_params[k].bits, + ffdh_results[k][0], 1.0 / ffdh_results[k][0]); + + else + printf("%4u bits ffdh %8.4fs %8.1f\n", + ffdh_params[k].bits, + 1.0 / ffdh_results[k][0], ffdh_results[k][0]); + } +#endif /* OPENSSL_NO_DH */ ret = 0; @@ -3357,25 +3288,55 @@ OPENSSL_free(loopargs[i].buf_malloc); OPENSSL_free(loopargs[i].buf2_malloc); -#ifndef OPENSSL_NO_RSA - for (k = 0; k < RSA_NUM; k++) - RSA_free(loopargs[i].rsa_key[k]); -#endif -#ifndef OPENSSL_NO_DSA - for (k = 0; k < DSA_NUM; k++) - DSA_free(loopargs[i].dsa_key[k]); + BN_free(bn); + EVP_PKEY_CTX_free(genctx); + for (k = 0; k < RSA_NUM; k++) { + EVP_PKEY_CTX_free(loopargs[i].rsa_sign_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].rsa_verify_ctx[k]); + } +#ifndef OPENSSL_NO_DH + OPENSSL_free(loopargs[i].secret_ff_a); + OPENSSL_free(loopargs[i].secret_ff_b); + for (k = 0; k < FFDH_NUM; k++) + EVP_PKEY_CTX_free(loopargs[i].ffdh_ctx[k]); #endif -#ifndef OPENSSL_NO_EC - for (k = 0; k < ECDSA_NUM; k++) - EC_KEY_free(loopargs[i].ecdsa[k]); + for (k = 0; k < DSA_NUM; k++) { + EVP_PKEY_CTX_free(loopargs[i].dsa_sign_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].dsa_verify_ctx[k]); + } + for (k = 0; k < ECDSA_NUM; k++) { + EVP_PKEY_CTX_free(loopargs[i].ecdsa_sign_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].ecdsa_verify_ctx[k]); + } for (k = 0; k < EC_NUM; k++) EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]); - for (k = 0; k < EdDSA_NUM; k++) + for (k = 0; k < EdDSA_NUM; k++) { EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]); + EVP_MD_CTX_free(loopargs[i].eddsa_ctx2[k]); + } +#ifndef OPENSSL_NO_SM2 + for (k = 0; k < SM2_NUM; k++) { + EVP_PKEY_CTX *pctx = NULL; + + /* free signing ctx */ + if (loopargs[i].sm2_ctx[k] != NULL + && (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_ctx[k])) != NULL) + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(loopargs[i].sm2_ctx[k]); + /* free verification ctx */ + if (loopargs[i].sm2_vfy_ctx[k] != NULL + && (pctx = EVP_MD_CTX_get_pkey_ctx(loopargs[i].sm2_vfy_ctx[k])) != NULL) + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(loopargs[i].sm2_vfy_ctx[k]); + /* free pkey */ + EVP_PKEY_free(loopargs[i].sm2_pkey[k]); + } +#endif OPENSSL_free(loopargs[i].secret_a); OPENSSL_free(loopargs[i].secret_b); -#endif } + OPENSSL_free(evp_hmac_name); + OPENSSL_free(evp_cmac_name); if (async_jobs > 0) { for (i = 0; i < loopargs_len; i++) @@ -3387,49 +3348,38 @@ } OPENSSL_free(loopargs); release_engine(e); + EVP_CIPHER_free(evp_cipher); + EVP_MAC_free(mac); return ret; } static void print_message(const char *s, long num, int length, int tm) { -#ifdef SIGALRM BIO_printf(bio_err, mr ? "+DT:%s:%d:%d\n" : "Doing %s for %ds on %d size blocks: ", s, tm, length); (void)BIO_flush(bio_err); run = 1; alarm(tm); -#else - BIO_printf(bio_err, - mr ? "+DN:%s:%ld:%d\n" - : "Doing %s %ld times on %d size blocks: ", s, num, length); - (void)BIO_flush(bio_err); -#endif } static void pkey_print_message(const char *str, const char *str2, long num, unsigned int bits, int tm) { -#ifdef SIGALRM BIO_printf(bio_err, mr ? "+DTP:%d:%s:%s:%d\n" : "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm); (void)BIO_flush(bio_err); run = 1; alarm(tm); -#else - BIO_printf(bio_err, - mr ? "+DNP:%ld:%d:%s:%s\n" - : "Doing %ld %u bits %s %s's: ", num, bits, str, str2); - (void)BIO_flush(bio_err); -#endif } static void print_result(int alg, int run_no, int count, double time_used) { if (count == -1) { - BIO_puts(bio_err, "EVP error!\n"); - exit(1); + BIO_printf(bio_err, "%s error!\n", names[alg]); + ERR_print_errors(bio_err); + return; } BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n" @@ -3454,9 +3404,8 @@ delim++; } - while (!isdelim[(unsigned char)(**string)]) { + while (!isdelim[(unsigned char)(**string)]) (*string)++; - } if (**string) { **string = 0; @@ -3471,6 +3420,7 @@ int n; int fd[2]; int *fds; + int status; static char sep[] = ":"; fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi"); @@ -3506,7 +3456,12 @@ char buf[1024]; char *p; - f = fdopen(fds[n], "r"); + if ((f = fdopen(fds[n], "r")) == NULL) { + BIO_printf(bio_err, "fdopen failure with 0x%x\n", + errno); + OPENSSL_free(fds); + return 1; + } while (fgets(buf, sizeof(buf), f)) { p = strchr(buf, '\n'); if (p) @@ -3540,9 +3495,7 @@ d = atof(sstrsep(&p, sep)); rsa_results[k][1] += d; - } -# ifndef OPENSSL_NO_DSA - else if (strncmp(buf, "+F3:", 4) == 0) { + } else if (strncmp(buf, "+F3:", 4) == 0) { int k; double d; @@ -3555,10 +3508,7 @@ d = atof(sstrsep(&p, sep)); dsa_results[k][1] += d; - } -# endif -# ifndef OPENSSL_NO_EC - else if (strncmp(buf, "+F4:", 4) == 0) { + } else if (strncmp(buf, "+F4:", 4) == 0) { int k; double d; @@ -3595,19 +3545,59 @@ d = atof(sstrsep(&p, sep)); eddsa_results[k][1] += d; - } -# endif +# ifndef OPENSSL_NO_SM2 + } else if (strncmp(buf, "+F7:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); + sstrsep(&p, sep); + + d = atof(sstrsep(&p, sep)); + sm2_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + sm2_results[k][1] += d; +# endif /* OPENSSL_NO_SM2 */ +# ifndef OPENSSL_NO_DH + } else if (strncmp(buf, "+F8:", 4) == 0) { + int k; + double d; + + p = buf + 4; + k = atoi(sstrsep(&p, sep)); + sstrsep(&p, sep); - else if (strncmp(buf, "+H:", 3) == 0) { + d = atof(sstrsep(&p, sep)); + ffdh_results[k][0] += d; +# endif /* OPENSSL_NO_DH */ + } else if (strncmp(buf, "+H:", 3) == 0) { ; - } else + } else { BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf, n); + } } fclose(f); } OPENSSL_free(fds); + for (n = 0; n < multi; ++n) { + while (wait(&status) == -1) + if (errno != EINTR) { + BIO_printf(bio_err, "Waitng for child failed with 0x%x\n", + errno); + return 1; + } + if (WIFEXITED(status) && WEXITSTATUS(status)) { + BIO_printf(bio_err, "Child exited with %d\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + BIO_printf(bio_err, "Child terminated by signal %d\n", + WTERMSIG(status)); + } + } return 1; } #endif @@ -3620,8 +3610,8 @@ const int *mblengths = mblengths_list; int j, count, keylen, num = OSSL_NELEM(mblengths_list); const char *alg_name; - unsigned char *inp, *out, *key, no_key[32], no_iv[16]; - EVP_CIPHER_CTX *ctx; + unsigned char *inp = NULL, *out = NULL, *key, no_key[32], no_iv[16]; + EVP_CIPHER_CTX *ctx = NULL; double d = 0.0; if (lengths_single) { @@ -3631,22 +3621,32 @@ inp = app_malloc(mblengths[num - 1], "multiblock input buffer"); out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer"); - ctx = EVP_CIPHER_CTX_new(); - EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv); + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + app_bail_out("failed to allocate cipher context\n"); + if (!EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv)) + app_bail_out("failed to initialise cipher context\n"); - keylen = EVP_CIPHER_CTX_key_length(ctx); + if ((keylen = EVP_CIPHER_CTX_get_key_length(ctx)) < 0) { + BIO_printf(bio_err, "Impossible negative key length: %d\n", keylen); + goto err; + } key = app_malloc(keylen, "evp_cipher key"); - EVP_CIPHER_CTX_rand_key(ctx, key); - EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL); + if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) + app_bail_out("failed to generate random cipher key\n"); + if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL)) + app_bail_out("failed to set cipher key\n"); OPENSSL_clear_free(key, keylen); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key); - alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)); + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, + sizeof(no_key), no_key) <= 0) + app_bail_out("failed to set AEAD key\n"); + if ((alg_name = EVP_CIPHER_get0_name(evp_cipher)) == NULL) + app_bail_out("failed to get cipher name\n"); for (j = 0; j < num; j++) { print_message(alg_name, 0, mblengths[j], seconds->sym); Time_F(START); - for (count = 0; run && count < 0x7fffffff; count++) { + for (count = 0; run && count < INT_MAX; count++) { unsigned char aad[EVP_AEAD_TLS1_AAD_LEN]; EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; size_t len = mblengths[j]; @@ -3670,8 +3670,9 @@ mb_param.out = out; mb_param.inp = inp; mb_param.len = len; - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, - sizeof(mb_param), &mb_param); + (void)EVP_CIPHER_CTX_ctrl(ctx, + EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT, + sizeof(mb_param), &mb_param); } else { int pad; @@ -3717,6 +3718,7 @@ fprintf(stdout, "\n"); } + err: OPENSSL_free(inp); OPENSSL_free(out); EVP_CIPHER_CTX_free(ctx); diff --git a/apps/spkac.c b/apps/spkac.c --- a/apps/spkac.c +++ b/apps/spkac.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -21,29 +21,38 @@ #include typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT, OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC, - OPT_SPKSECT, OPT_KEYFORM + OPT_SPKSECT, OPT_KEYFORM, OPT_DIGEST, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS spkac_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"spksect", OPT_SPKSECT, 's', + "Specify the name of an SPKAC-dedicated section of configuration"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, - {"out", OPT_OUT, '>', "Output file"}, {"key", OPT_KEY, '<', "Create SPKAC using private key"}, - {"keyform", OPT_KEYFORM, 'f', "Private key file format - default PEM (PEM, DER, or ENGINE)"}, + {"keyform", OPT_KEYFORM, 'f', "Private key file format (ENGINE, other values ignored)"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"challenge", OPT_CHALLENGE, 's', "Challenge string"}, {"spkac", OPT_SPKAC, 's', "Alternative SPKAC name"}, + + OPT_SECTION("Output"), + {"digest", OPT_DIGEST, 's', "Sign new SPKAC with the specified digest (default: MD5)" }, + {"out", OPT_OUT, '>', "Output file"}, {"noout", OPT_NOOUT, '-', "Don't print SPKAC"}, {"pubkey", OPT_PUBKEY, '-', "Output public key"}, {"verify", OPT_VERIFY, '-', "Verify SPKAC signature"}, - {"spksect", OPT_SPKSECT, 's', - "Specify the name of an SPKAC-dedicated section of configuration"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + + OPT_PROV_OPTIONS, {NULL} }; @@ -58,8 +67,10 @@ char *infile = NULL, *outfile = NULL, *passinarg = NULL, *passin = NULL; char *spkstr = NULL, *prog; const char *spkac = "SPKAC", *spksect = "default"; + const char *digest = "MD5"; + EVP_MD *md = NULL; int i, ret = 1, verify = 0, noout = 0, pubkey = 0; - int keyformat = FORMAT_PEM; + int keyformat = FORMAT_UNDEF; OPTION_CHOICE o; prog = opt_init(argc, argv, spkac_options); @@ -108,11 +119,20 @@ case OPT_SPKSECT: spksect = opt_arg(); break; + case OPT_DIGEST: + digest = opt_arg(); + break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); if (argc != 0) goto opthelp; @@ -123,6 +143,9 @@ } if (keyfile != NULL) { + if (!opt_md(digest, &md)) + goto end; + pkey = load_key(strcmp(keyfile, "-") ? keyfile : NULL, keyformat, 1, passin, e, "private key"); if (pkey == NULL) @@ -133,8 +156,15 @@ if (challenge != NULL) ASN1_STRING_set(spki->spkac->challenge, challenge, (int)strlen(challenge)); - NETSCAPE_SPKI_set_pubkey(spki, pkey); - NETSCAPE_SPKI_sign(spki, pkey, EVP_md5()); + if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) { + BIO_printf(bio_err, "Error setting public key\n"); + goto end; + } + i = NETSCAPE_SPKI_sign(spki, pkey, md); + if (i <= 0) { + BIO_printf(bio_err, "Error signing SPKAC\n"); + goto end; + } spkstr = NETSCAPE_SPKI_b64_encode(spki); if (spkstr == NULL) goto end; @@ -192,6 +222,7 @@ ret = 0; end: + EVP_MD_free(md); NCONF_free(conf); NETSCAPE_SPKI_free(spki); BIO_free_all(out); diff --git a/apps/srp.c b/apps/srp.c --- a/apps/srp.c +++ b/apps/srp.c @@ -1,8 +1,8 @@ /* - * Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2004, EdelKey Project. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,7 +11,11 @@ * for the EdelKey project. */ +/* SRP is deprecated, so we're going to have to use some deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include + #include #include #include @@ -186,31 +190,42 @@ } typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD, OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO, - OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM + OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS srp_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [user...]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"verbose", OPT_VERBOSE, '-', "Talk a lot while doing things"}, {"config", OPT_CONFIG, '<', "A config file"}, {"name", OPT_NAME, 's', "The particular srp definition to use"}, - {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"}, - {"add", OPT_ADD, '-', "Add a user and srp verifier"}, - {"modify", OPT_MODIFY, '-', - "Modify the srp verifier of an existing user"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Action"), + {"add", OPT_ADD, '-', "Add a user and SRP verifier"}, + {"modify", OPT_MODIFY, '-', "Modify the SRP verifier of an existing user"}, {"delete", OPT_DELETE, '-', "Delete user from verifier file"}, {"list", OPT_LIST, '-', "List users"}, + + OPT_SECTION("Configuration"), + {"srpvfile", OPT_SRPVFILE, '<', "The srp verifier file name"}, {"gn", OPT_GN, 's', "Set g and N values to be used for new verifier"}, {"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, + OPT_R_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"user", 0, 0, "Username(s) to process (optional)"}, {NULL} }; @@ -283,11 +298,20 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* Optional parameters are usernames. */ argc = opt_num_rest(); argv = opt_rest(); + if (!app_RAND_load()) + goto end; + if (srpvfile != NULL && configfile != NULL) { BIO_printf(bio_err, "-srpvfile and -configfile cannot be specified together.\n"); @@ -320,10 +344,7 @@ if (configfile == NULL) configfile = default_config_file; - if (verbose) - BIO_printf(bio_err, "Using configuration from %s\n", - configfile); - conf = app_load_config(configfile); + conf = app_load_config_verbose(configfile, verbose); if (conf == NULL) goto end; if (configfile != default_config_file && !app_load_modules(conf)) @@ -358,8 +379,10 @@ srpvfile); db = load_index(srpvfile, NULL); - if (db == NULL) + if (db == NULL) { + BIO_printf(bio_err, "Problem with index file: %s (could not load/parse file)\n", srpvfile); goto end; + } /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { diff --git a/apps/storeutl.c b/apps/storeutl.c --- a/apps/storeutl.c +++ b/apps/storeutl.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,24 +19,29 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, int expected, int criterion, OSSL_STORE_SEARCH *search, int text, int noout, int recursive, int indent, BIO *out, - const char *prog); + const char *prog, OSSL_LIB_CTX *libctx); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN, + OPT_COMMON, + OPT_ENGINE, OPT_OUT, OPT_PASSIN, OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE, OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS, OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL, OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS, - OPT_MD + OPT_MD, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS storeutl_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, - {"out", OPT_OUT, '>', "Output file - default stdout"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"text", OPT_TEXT, '-', "Print a text form of the objects"}, - {"noout", OPT_NOOUT, '-', "No PEM output, just status"}, + {"", OPT_MD, '-', "Any supported digest"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + + OPT_SECTION("Search"), {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"}, {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"}, {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"}, @@ -45,11 +50,20 @@ {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"}, {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"}, {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"}, - {"", OPT_MD, '-', "Any supported digest"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif {"r", OPT_RECURSIVE, '-', "Recurse through names"}, + + OPT_SECTION("Input"), + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"text", OPT_TEXT, '-', "Print a text form of the objects"}, + {"noout", OPT_NOOUT, '-', "No PEM output, just status"}, + + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"uri", 0, 0, "URI of the store object"}, {NULL} }; @@ -68,9 +82,10 @@ ASN1_INTEGER *serial = NULL; unsigned char *fingerprint = NULL; size_t fingerprintlen = 0; - char *alias = NULL; + char *alias = NULL, *digestname = NULL; OSSL_STORE_SEARCH *search = NULL; - const EVP_MD *digest = NULL; + EVP_MD *digest = NULL; + OSSL_LIB_CTX *libctx = app_get0_libctx(); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -142,16 +157,13 @@ prog); goto end; } - if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { - BIO_printf(bio_err, "%s: can't parse subject argument.\n", - prog); + subject = parse_name(opt_arg(), MBSTRING_UTF8, 1, "subject"); + if (subject == NULL) goto end; - } break; case OPT_CRITERION_ISSUER: if (criterion != 0 - || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL - && issuer != NULL)) { + && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) { BIO_printf(bio_err, "%s: criterion already given.\n", prog); goto end; @@ -162,16 +174,13 @@ prog); goto end; } - if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { - BIO_printf(bio_err, "%s: can't parse issuer argument.\n", - prog); + issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1, "issuer"); + if (issuer == NULL) goto end; - } break; case OPT_CRITERION_SERIAL: if (criterion != 0 - || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL - && serial != NULL)) { + && criterion != OSSL_STORE_SEARCH_BY_ISSUER_SERIAL) { BIO_printf(bio_err, "%s: criterion already given.\n", prog); goto end; @@ -237,20 +246,24 @@ e = setup_engine(opt_arg(), 0); break; case OPT_MD: - if (!opt_md(opt_unknown(), &digest)) - goto opthelp; + digestname = opt_unknown(); + break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* One argument, the URI */ argc = opt_num_rest(); argv = opt_rest(); - - if (argc == 0) { - BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog); - goto opthelp; - } - if (argc > 1) { - BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog); + if (argc != 1) goto opthelp; + + if (digestname != NULL) { + if (!opt_md(digestname, &digest)) + goto opthelp; } if (criterion != 0) { @@ -305,9 +318,10 @@ ret = process(argv[0], get_ui_method(), &pw_cb_data, expected, criterion, search, - text, noout, recursive, 0, out, prog); + text, noout, recursive, 0, out, prog, libctx); end: + EVP_MD_free(digest); OPENSSL_free(fingerprint); OPENSSL_free(alias); ASN1_INTEGER_free(serial); @@ -336,12 +350,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, int expected, int criterion, OSSL_STORE_SEARCH *search, int text, int noout, int recursive, int indent, BIO *out, - const char *prog) + const char *prog, OSSL_LIB_CTX *libctx) { OSSL_STORE_CTX *store_ctx = NULL; int ret = 1, items = 0; - if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL)) + if ((store_ctx = OSSL_STORE_open_ex(uri, libctx, app_get0_propq(), uimeth, uidata, + NULL, NULL, NULL)) == NULL) { BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri); ERR_print_errors(bio_err); @@ -379,18 +394,20 @@ info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); if (info == NULL) { - if (OSSL_STORE_eof(store_ctx)) - break; - if (OSSL_STORE_error(store_ctx)) { if (recursive) ERR_clear_error(); else ERR_print_errors(bio_err); + if (OSSL_STORE_eof(store_ctx)) + break; ret++; continue; } + if (OSSL_STORE_eof(store_ctx)) + break; + BIO_printf(bio_err, "ERROR: OSSL_STORE_load() returned NULL without " "eof or error indications\n"); @@ -422,7 +439,8 @@ const char *suburi = OSSL_STORE_INFO_get0_NAME(info); ret += process(suburi, uimeth, uidata, expected, criterion, search, - text, noout, recursive, indent + 2, out, prog); + text, noout, recursive, indent + 2, out, prog, + libctx); } break; case OSSL_STORE_INFO_PARAMS: @@ -433,6 +451,13 @@ PEM_write_bio_Parameters(out, OSSL_STORE_INFO_get0_PARAMS(info)); break; + case OSSL_STORE_INFO_PUBKEY: + if (text) + EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info), + 0, NULL); + if (!noout) + PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info)); + break; case OSSL_STORE_INFO_PKEY: if (text) EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info), diff --git a/apps/testdsa.h b/apps/testdsa.h --- a/apps/testdsa.h +++ b/apps/testdsa.h @@ -1,14 +1,16 @@ /* - * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +#include + /* used by speed.c */ -DSA *get_dsa(int); +EVP_PKEY *get_dsa(int); static unsigned char dsa512_priv[] = { 0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c, @@ -211,11 +213,14 @@ st.q_l = sizeof(dsa##bits##_q); \ } while (0) -DSA *get_dsa(int dsa_bits) +EVP_PKEY *get_dsa(int dsa_bits) { - DSA *dsa; + EVP_PKEY *pkey = NULL; BIGNUM *priv_key, *pub_key, *p, *q, *g; + EVP_PKEY_CTX *pctx; testdsa dsa_t; + OSSL_PARAM_BLD *tmpl = NULL; + OSSL_PARAM *params = NULL; switch (dsa_bits) { case 512: @@ -231,30 +236,44 @@ return NULL; } - if ((dsa = DSA_new()) == NULL) + if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL) return NULL; + priv_key = BN_bin2bn(dsa_t.priv, dsa_t.priv_l, NULL); pub_key = BN_bin2bn(dsa_t.pub, dsa_t.pub_l, NULL); p = BN_bin2bn(dsa_t.p, dsa_t.p_l, NULL); q = BN_bin2bn(dsa_t.q, dsa_t.q_l, NULL); g = BN_bin2bn(dsa_t.g, dsa_t.g_l, NULL); - if ((priv_key == NULL) || (pub_key == NULL) || (p == NULL) || (q == NULL) - || (g == NULL)) { + if (priv_key == NULL || pub_key == NULL || p == NULL || q == NULL + || g == NULL) { goto err; } - if (!DSA_set0_pqg(dsa, p, q, g)) - goto err; - - if (!DSA_set0_key(dsa, pub_key, priv_key)) + if ((tmpl = OSSL_PARAM_BLD_new()) == NULL + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, + p) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, + q) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, + g) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, + priv_key) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, + pub_key) + || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) goto err; - return dsa; - err: - DSA_free(dsa); + if (EVP_PKEY_fromdata_init(pctx) <= 0 + || EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR, + params) <= 0) + pkey = NULL; +err: + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(tmpl); BN_free(priv_key); BN_free(pub_key); BN_free(p); BN_free(q); BN_free(g); - return NULL; + EVP_PKEY_CTX_free(pctx); + return pkey; } diff --git a/apps/testrsa.h b/apps/testrsa.h --- a/apps/testrsa.h +++ b/apps/testrsa.h @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/apps/timeouts.h b/apps/timeouts.h --- a/apps/timeouts.h +++ b/apps/timeouts.h @@ -1,7 +1,7 @@ /* * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/apps/ts.c b/apps/ts.c --- a/apps/ts.c +++ b/apps/ts.c @@ -1,7 +1,7 @@ /* - * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -63,60 +63,68 @@ /* Verify related functions. */ static int verify_command(const char *data, const char *digest, const char *queryfile, const char *in, int token_in, - const char *CApath, const char *CAfile, const char *untrusted, - X509_VERIFY_PARAM *vpm); + const char *CApath, const char *CAfile, + const char *CAstore, + char *untrusted, X509_VERIFY_PARAM *vpm); static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, const char *queryfile, const char *CApath, const char *CAfile, - const char *untrusted, + const char *CAstore, + char *untrusted, X509_VERIFY_PARAM *vpm); static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, - X509_VERIFY_PARAM *vpm); + const char *CAstore, X509_VERIFY_PARAM *vpm); static int verify_cb(int ok, X509_STORE_CTX *ctx); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA, OPT_DIGEST, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT, OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT, OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER, - OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED, - OPT_MD, OPT_V_ENUM, OPT_R_ENUM + OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, OPT_UNTRUSTED, + OPT_MD, OPT_V_ENUM, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS ts_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"config", OPT_CONFIG, '<', "Configuration file"}, {"section", OPT_SECTION, 's', "Section to use within config file"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif + {"inkey", OPT_INKEY, 's', "File with private key for reply"}, + {"signer", OPT_SIGNER, 's', "Signer certificate file"}, + {"chain", OPT_CHAIN, '<', "File with signer CA chain"}, + {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"}, + {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"}, + {"CAstore", OPT_CASTORE, ':', "URI to trusted CA store"}, + {"untrusted", OPT_UNTRUSTED, '<', "Extra untrusted certs"}, + {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"}, + {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"}, + {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, + {"", OPT_MD, '-', "Any supported digest"}, + + OPT_SECTION("Query"), {"query", OPT_QUERY, '-', "Generate a TS query"}, {"data", OPT_DATA, '<', "File to hash"}, {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"}, - OPT_R_OPTIONS, - {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"}, - {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"}, + {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"}, {"cert", OPT_CERT, '-', "Put cert request into query"}, {"in", OPT_IN, '<', "Input file"}, - {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"}, + + OPT_SECTION("Verify"), + {"verify", OPT_VERIFY, '-', "Verify a TS response"}, + {"reply", OPT_REPLY, '-', "Generate a TS reply"}, + {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"}, + {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"}, {"out", OPT_OUT, '>', "Output file"}, - {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"}, {"text", OPT_TEXT, '-', "Output text (not DER)"}, - {"reply", OPT_REPLY, '-', "Generate a TS reply"}, - {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"}, - {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, - {"inkey", OPT_INKEY, 's', "File with private key for reply"}, - {"signer", OPT_SIGNER, 's', "Signer certificate file"}, - {"chain", OPT_CHAIN, '<', "File with signer CA chain"}, - {"verify", OPT_VERIFY, '-', "Verify a TS response"}, - {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"}, - {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"}, - {"untrusted", OPT_UNTRUSTED, '<', "File with untrusted certs"}, - {"", OPT_MD, '-', "Any supported digest"}, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif - {OPT_HELP_STR, 1, '-', "\nOptions specific to 'ts -verify': \n"}, + + OPT_R_OPTIONS, OPT_V_OPTIONS, - {OPT_HELP_STR, 1, '-', "\n"}, + OPT_PROV_OPTIONS, {NULL} }; @@ -124,41 +132,43 @@ * This command is so complex, special help is needed. */ static char* opt_helplist[] = { + "", "Typical uses:", - "ts -query [-rand file...] [-config file] [-data file]", - " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]", - " [-in file] [-out file] [-text]", - " or", - "ts -reply [-config file] [-section tsa_section]", - " [-queryfile file] [-passin password]", - " [-signer tsa_cert.pem] [-inkey private_key.pem]", - " [-chain certs_file.pem] [-tspolicy oid]", - " [-in file] [-token_in] [-out file] [-token_out]", + " openssl ts -query [-rand file...] [-config file] [-data file]", + " [-digest hexstring] [-tspolicy oid] [-no_nonce] [-cert]", + " [-in file] [-out file] [-text]", + "", + " openssl ts -reply [-config file] [-section tsa_section]", + " [-queryfile file] [-passin password]", + " [-signer tsa_cert.pem] [-inkey private_key.pem]", + " [-chain certs_file.pem] [-tspolicy oid]", + " [-in file] [-token_in] [-out file] [-token_out]", #ifndef OPENSSL_NO_ENGINE - " [-text] [-engine id]", + " [-text] [-engine id]", #else - " [-text]", + " [-text]", #endif - " or", - "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem", - " [-data file] [-digest hexstring]", - " [-queryfile file] -in file [-token_in]", - " [[options specific to 'ts -verify']]", + "", + " openssl ts -verify -CApath dir -CAfile root-cert.pem -CAstore uri", + " -untrusted extra-certs.pem [-data file] [-digest hexstring]", + " [-queryfile request.tsq] -in response.tsr [-token_in] ...", NULL, }; int ts_main(int argc, char **argv) { CONF *conf = NULL; - const char *CAfile = NULL, *untrusted = NULL, *prog; + const char *CAfile = NULL, *prog; + char *untrusted = NULL; const char *configfile = default_config_file, *engine = NULL; - const char *section = NULL; + const char *section = NULL, *digestname = NULL; char **helpp; char *password = NULL; char *data = NULL, *digest = NULL, *policy = NULL; char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL; char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL; - const EVP_MD *md = NULL; + char *CAstore = NULL; + EVP_MD *md = NULL; OPTION_CHOICE o, mode = OPT_ERR; int ret = 1, no_nonce = 0, cert = 0, text = 0; int vpmtouched = 0; @@ -208,6 +218,10 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_TSPOLICY: policy = opt_arg(); break; @@ -253,6 +267,9 @@ case OPT_CAFILE: CAfile = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; case OPT_UNTRUSTED: untrusted = opt_arg(); break; @@ -260,8 +277,7 @@ engine = opt_arg(); break; case OPT_MD: - if (!opt_md(opt_unknown(), &md)) - goto opthelp; + digestname = opt_unknown(); break; case OPT_V_CASES: if (!opt_verify(o, vpm)) @@ -270,9 +286,19 @@ break; } } - if (mode == OPT_ERR || opt_num_rest() != 0) + + /* No extra arguments. */ + argc = opt_num_rest(); + if (argc != 0 || mode == OPT_ERR) goto opthelp; + if (!app_RAND_load()) + goto end; + + if (digestname != NULL) { + if (!opt_md(digestname, &md)) + goto opthelp; + } if (mode == OPT_REPLY && passin && !app_passwd(passin, NULL, &password, NULL)) { BIO_printf(bio_err, "Error getting password.\n"); @@ -309,7 +335,7 @@ if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest)) goto opthelp; ret = !verify_command(data, digest, queryfile, in, token_in, - CApath, CAfile, untrusted, + CApath, CAfile, CAstore, untrusted, vpmtouched ? vpm : NULL); } else { goto opthelp; @@ -317,6 +343,7 @@ end: X509_VERIFY_PARAM_free(vpm); + EVP_MD_free(md); NCONF_free(conf); OPENSSL_free(password); return ret; @@ -423,7 +450,7 @@ ASN1_OBJECT *policy_obj = NULL; ASN1_INTEGER *nonce_asn1 = NULL; - if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL) + if (md == NULL && (md = EVP_get_digestbyname("sha256")) == NULL) goto err; if ((ts_req = TS_REQ_new()) == NULL) goto err; @@ -433,7 +460,7 @@ goto err; if ((algo = X509_ALGOR_new()) == NULL) goto err; - if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL) + if ((algo->algorithm = OBJ_nid2obj(EVP_MD_get_type(md))) == NULL) goto err; if ((algo->parameter = ASN1_TYPE_new()) == NULL) goto err; @@ -482,7 +509,7 @@ int rv = 0; EVP_MD_CTX *md_ctx = NULL; - md_value_len = EVP_MD_size(md); + md_value_len = EVP_MD_get_size(md); if (md_value_len < 0) return 0; @@ -502,11 +529,12 @@ } if (!EVP_DigestFinal(md_ctx, *md_value, NULL)) goto err; - md_value_len = EVP_MD_size(md); + md_value_len = EVP_MD_get_size(md); } else { long digest_len; + *md_value = OPENSSL_hexstr2buf(digest, &digest_len); - if (!*md_value || md_value_len != digest_len) { + if (*md_value == NULL || md_value_len != digest_len) { OPENSSL_free(*md_value); *md_value = NULL; BIO_printf(bio_err, "bad digest, %d bytes " @@ -817,7 +845,8 @@ static int verify_command(const char *data, const char *digest, const char *queryfile, const char *in, int token_in, - const char *CApath, const char *CAfile, const char *untrusted, + const char *CApath, const char *CAfile, + const char *CAstore, char *untrusted, X509_VERIFY_PARAM *vpm) { BIO *in_bio = NULL; @@ -837,7 +866,7 @@ } if ((verify_ctx = create_verify_ctx(data, digest, queryfile, - CApath, CAfile, untrusted, + CApath, CAfile, CAstore, untrusted, vpm)) == NULL) goto end; @@ -864,10 +893,12 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, const char *queryfile, const char *CApath, const char *CAfile, - const char *untrusted, + const char *CAstore, + char *untrusted, X509_VERIFY_PARAM *vpm) { TS_VERIFY_CTX *ctx = NULL; + STACK_OF(X509) *certs; BIO *input = NULL; TS_REQ *request = NULL; int ret = 0; @@ -912,14 +943,18 @@ TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE); /* Initialising the X509_STORE object. */ - if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile, vpm)) + if (TS_VERIFY_CTX_set_store(ctx, + create_cert_store(CApath, CAfile, CAstore, vpm)) == NULL) goto err; - /* Loading untrusted certificates. */ - if (untrusted - && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL) - goto err; + /* Loading any extra untrusted certificates. */ + if (untrusted != NULL) { + certs = load_certs_multifile(untrusted, NULL, "extra untrusted certs", + vpm); + if (certs == NULL || TS_VERIFY_CTX_set_certs(ctx, certs) == NULL) + goto err; + } ret = 1; err: @@ -933,13 +968,18 @@ } static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, - X509_VERIFY_PARAM *vpm) + const char *CAstore, X509_VERIFY_PARAM *vpm) { X509_STORE *cert_ctx = NULL; X509_LOOKUP *lookup = NULL; - int i; + OSSL_LIB_CTX *libctx = app_get0_libctx(); + const char *propq = app_get0_propq(); cert_ctx = X509_STORE_new(); + if (cert_ctx == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + return NULL; + } X509_STORE_set_verify_cb(cert_ctx, verify_cb); if (CApath != NULL) { lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); @@ -947,8 +987,7 @@ BIO_printf(bio_err, "memory allocation failure\n"); goto err; } - i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); - if (!i) { + if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) { BIO_printf(bio_err, "Error loading directory %s\n", CApath); goto err; } @@ -960,13 +999,25 @@ BIO_printf(bio_err, "memory allocation failure\n"); goto err; } - i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); - if (!i) { + if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM, libctx, + propq) <= 0) { BIO_printf(bio_err, "Error loading file %s\n", CAfile); goto err; } } + if (CAstore != NULL) { + lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_store()); + if (lookup == NULL) { + BIO_printf(bio_err, "memory allocation failure\n"); + goto err; + } + if (X509_LOOKUP_load_store_ex(lookup, CAstore, libctx, propq) <= 0) { + BIO_printf(bio_err, "Error loading store URI %s\n", CAstore); + goto err; + } + } + if (vpm != NULL) X509_STORE_set1_param(cert_ctx, vpm); diff --git a/apps/tsget.in b/apps/tsget.in --- a/apps/tsget.in +++ b/apps/tsget.in @@ -1,8 +1,8 @@ #!{- $config{HASHBANGPERL} -} -# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2002 The OpenTSA Project. All rights reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -21,10 +21,10 @@ my $return_data = ""; my $data_len = length ${$state->{data}}; if ($state->{bytes} < $data_len) { - $data_len = $data_len - $state->{bytes}; - $data_len = $maxlength if $data_len > $maxlength; - $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len; - $state->{bytes} += $data_len; + $data_len = $data_len - $state->{bytes}; + $data_len = $maxlength if $data_len > $maxlength; + $return_data = substr ${$state->{data}}, $state->{bytes}, $data_len; + $state->{bytes} += $data_len; } return $return_data; } @@ -47,14 +47,14 @@ $curl->setopt(CURLOPT_VERBOSE, 1) if $options{d}; $curl->setopt(CURLOPT_FAILONERROR, 1); $curl->setopt(CURLOPT_USERAGENT, - "OpenTSA tsget.pl/openssl-{- $config{version} -}"); + "OpenTSA tsget.pl/openssl-{- $config{full_version} -}"); # Options for POST method. $curl->setopt(CURLOPT_UPLOAD, 1); $curl->setopt(CURLOPT_CUSTOMREQUEST, "POST"); $curl->setopt(CURLOPT_HTTPHEADER, - ["Content-Type: application/timestamp-query", - "Accept: application/timestamp-reply,application/timestamp-response"]); + ["Content-Type: application/timestamp-query", + "Accept: application/timestamp-reply,application/timestamp-response"]); $curl->setopt(CURLOPT_READFUNCTION, \&read_body); $curl->setopt(CURLOPT_HEADERFUNCTION, sub { return length($_[0]); }); @@ -63,8 +63,8 @@ # SSL related options. $curl->setopt(CURLOPT_SSLKEYTYPE, "PEM"); - $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate. - $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN. + $curl->setopt(CURLOPT_SSL_VERIFYPEER, 1); # Verify server's certificate. + $curl->setopt(CURLOPT_SSL_VERIFYHOST, 2); # Check server's CN. $curl->setopt(CURLOPT_SSLKEY, $options{k}) if defined($options{k}); $curl->setopt(CURLOPT_SSLKEYPASSWD, $options{p}) if defined($options{p}); $curl->setopt(CURLOPT_SSLCERT, $options{c}) if defined($options{c}); @@ -101,15 +101,15 @@ my $error_string; if ($error_code != 0) { my $http_code = $curl->getinfo(CURLINFO_HTTP_CODE); - $error_string = "could not get timestamp"; - $error_string .= ", http code: $http_code" unless $http_code == 0; - $error_string .= ", curl code: $error_code"; - $error_string .= " ($::error_buf)" if defined($::error_buf); + $error_string = "could not get timestamp"; + $error_string .= ", http code: $http_code" unless $http_code == 0; + $error_string .= ", curl code: $error_code"; + $error_string .= " ($::error_buf)" if defined($::error_buf); } else { my $ct = $curl->getinfo(CURLINFO_CONTENT_TYPE); - if (lc($ct) ne "application/timestamp-reply" - && lc($ct) ne "application/timestamp-response") { - $error_string = "unexpected content type returned: $ct"; + if (lc($ct) ne "application/timestamp-reply" + && lc($ct) ne "application/timestamp-response") { + $error_string = "unexpected content type returned: $ct"; } } return ($ts_body, $error_string); @@ -163,15 +163,15 @@ # Read request. my $body; if ($input eq "-") { - # Read the request from STDIN; - $body = ; + # Read the request from STDIN; + $body = ; } else { - # Read the request from file. + # Read the request from file. open INPUT, "<" . $input - or warn("$input: could not open input file: $!\n"), next REQUEST; + or warn("$input: could not open input file: $!\n"), next REQUEST; $body = ; close INPUT - or warn("$input: could not close input file: $!\n"), next REQUEST; + or warn("$input: could not close input file: $!\n"), next REQUEST; } # Send request. @@ -179,21 +179,21 @@ my ($ts_body, $error) = get_timestamp $curl, \$body; if (defined($error)) { - die "$input: fatal error: $error\n"; + die "$input: fatal error: $error\n"; } STDERR->printflush(", reply received") if $options{v}; # Write response. if ($output eq "-") { - # Write to STDOUT. + # Write to STDOUT. print $ts_body; } else { - # Write to file. + # Write to file. open OUTPUT, ">", $output - or warn("$output: could not open output file: $!\n"), next REQUEST; + or warn("$output: could not open output file: $!\n"), next REQUEST; print OUTPUT $ts_body; close OUTPUT - or warn("$output: could not close output file: $!\n"), next REQUEST; + or warn("$output: could not close output file: $!\n"), next REQUEST; } STDERR->printflush(", $output written.\n") if $options{v}; } diff --git a/apps/verify.c b/apps/verify.c --- a/apps/verify.c +++ b/apps/verify.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -21,42 +21,58 @@ static int cb(int ok, X509_STORE_CTX *ctx); static int check(X509_STORE *ctx, const char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, - STACK_OF(X509_CRL) *crls, int show_chain); + STACK_OF(X509_CRL) *crls, int show_chain, + STACK_OF(OPENSSL_STRING) *opts); static int v_verbose = 0, vflags = 0; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, + OPT_COMMON, + OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, + OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, - OPT_V_ENUM, OPT_NAMEOPT, - OPT_VERBOSE + OPT_V_ENUM, OPT_NAMEOPT, OPT_VFYOPT, + OPT_VERBOSE, + OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS verify_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"}, - {OPT_HELP_STR, 1, '-', "Valid options are:\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"}, + + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, +#ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, +#endif {"verbose", OPT_VERBOSE, '-', "Print extra information about the operations being performed."}, - {"CApath", OPT_CAPATH, '/', "A directory of trusted certificates"}, + {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"}, + + OPT_SECTION("Certificate chain"), + {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"}, {"CAfile", OPT_CAFILE, '<', "A file of trusted certificates"}, + {"CApath", OPT_CAPATH, '/', "A directory of files with trusted certificates"}, + {"CAstore", OPT_CASTORE, ':', "URI to a store of trusted certificates"}, {"no-CAfile", OPT_NOCAFILE, '-', - "Do not load the default certificates file"}, + "Do not load the default trusted certificates file"}, {"no-CApath", OPT_NOCAPATH, '-', - "Do not load certificates from the default certificates directory"}, + "Do not load trusted certificates from the default directory"}, + {"no-CAstore", OPT_NOCASTORE, '-', + "Do not load trusted certificates from the default certificates store"}, {"untrusted", OPT_UNTRUSTED, '<', "A file of untrusted certificates"}, - {"trusted", OPT_TRUSTED, '<', "A file of trusted certificates"}, {"CRLfile", OPT_CRLFILE, '<', "File containing one or more CRL's (in PEM format) to load"}, {"crl_download", OPT_CRL_DOWNLOAD, '-', - "Attempt to download CRL information for this certificate"}, + "Try downloading CRL information for certificates via their CDP entries"}, {"show_chain", OPT_SHOW_CHAIN, '-', "Display information about the certificate chain"}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, + OPT_V_OPTIONS, -#ifndef OPENSSL_NO_ENGINE - {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, -#endif + {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"}, + + OPT_PROV_OPTIONS, + + OPT_PARAMETERS(), + {"cert", 0, 0, "Certificate(s) to verify (optional; stdin used otherwise)"}, {NULL} }; @@ -65,10 +81,11 @@ ENGINE *e = NULL; STACK_OF(X509) *untrusted = NULL, *trusted = NULL; STACK_OF(X509_CRL) *crls = NULL; + STACK_OF(OPENSSL_STRING) *vfyopts = NULL; X509_STORE *store = NULL; X509_VERIFY_PARAM *vpm = NULL; - const char *prog, *CApath = NULL, *CAfile = NULL; - int noCApath = 0, noCAfile = 0; + const char *prog, *CApath = NULL, *CAfile = NULL, *CAstore = NULL; + int noCApath = 0, noCAfile = 0, noCAstore = 0; int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; OPTION_CHOICE o; @@ -80,24 +97,25 @@ switch (o) { case OPT_EOF: case OPT_ERR: + opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(verify_options); - BIO_printf(bio_err, "Recognized usages:\n"); + BIO_printf(bio_err, "\nRecognized certificate chain purposes:\n"); for (i = 0; i < X509_PURPOSE_get_count(); i++) { - X509_PURPOSE *ptmp; - ptmp = X509_PURPOSE_get0(i); - BIO_printf(bio_err, "\t%-10s\t%s\n", + X509_PURPOSE *ptmp = X509_PURPOSE_get0(i); + + BIO_printf(bio_err, " %-15s %s\n", X509_PURPOSE_get0_sname(ptmp), X509_PURPOSE_get0_name(ptmp)); } - BIO_printf(bio_err, "Recognized verify names:\n"); + BIO_printf(bio_err, "Recognized certificate policy names:\n"); for (i = 0; i < X509_VERIFY_PARAM_get_count(); i++) { - const X509_VERIFY_PARAM *vptmp; - vptmp = X509_VERIFY_PARAM_get0(i); - BIO_printf(bio_err, "\t%-10s\n", + const X509_VERIFY_PARAM *vptmp = X509_VERIFY_PARAM_get0(i); + + BIO_printf(bio_err, " %s\n", X509_VERIFY_PARAM_get0_name(vptmp)); } ret = 0; @@ -113,15 +131,21 @@ case OPT_CAFILE: CAfile = opt_arg(); break; + case OPT_CASTORE: + CAstore = opt_arg(); + break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; + case OPT_NOCASTORE: + noCAstore = 1; + break; case OPT_UNTRUSTED: /* Zero or more times */ - if (!load_certs(opt_arg(), &untrusted, FORMAT_PEM, NULL, + if (!load_certs(opt_arg(), 0, &untrusted, NULL, "untrusted certificates")) goto end; break; @@ -129,14 +153,13 @@ /* Zero or more times */ noCAfile = 1; noCApath = 1; - if (!load_certs(opt_arg(), &trusted, FORMAT_PEM, NULL, - "trusted certificates")) + noCAstore = 1; + if (!load_certs(opt_arg(), 0, &trusted, NULL, "trusted certificates")) goto end; break; case OPT_CRLFILE: /* Zero or more times */ - if (!load_crls(opt_arg(), &crls, FORMAT_PEM, NULL, - "other CRLs")) + if (!load_crls(opt_arg(), &crls, NULL, "other CRLs")) goto end; break; case OPT_CRL_DOWNLOAD: @@ -155,21 +178,36 @@ if (!set_nameopt(opt_arg())) goto end; break; + case OPT_VFYOPT: + if (!vfyopts) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) + goto opthelp; + break; case OPT_VERBOSE: v_verbose = 1; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; } } + + /* Extra arguments are certificates to verify. */ argc = opt_num_rest(); argv = opt_rest(); - if (trusted != NULL && (CAfile || CApath)) { + + if (trusted != NULL + && (CAfile != NULL || CApath != NULL || CAstore != NULL)) { BIO_printf(bio_err, - "%s: Cannot use -trusted with -CAfile or -CApath\n", + "%s: Cannot use -trusted with -CAfile, -CApath or -CAstore\n", prog); goto end; } - if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) + if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, + CAstore, noCAstore)) == NULL) goto end; X509_STORE_set_verify_cb(store, cb); @@ -183,12 +221,13 @@ ret = 0; if (argc < 1) { - if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1) + if (check(store, NULL, untrusted, trusted, crls, show_chain, + vfyopts) != 1) ret = -1; } else { for (i = 0; i < argc; i++) - if (check(store, argv[i], untrusted, trusted, crls, - show_chain) != 1) + if (check(store, argv[i], untrusted, trusted, crls, show_chain, + vfyopts) != 1) ret = -1; } @@ -198,13 +237,15 @@ sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); + sk_OPENSSL_STRING_free(vfyopts); release_engine(e); return (ret < 0 ? 2 : ret); } static int check(X509_STORE *ctx, const char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, - STACK_OF(X509_CRL) *crls, int show_chain) + STACK_OF(X509_CRL) *crls, int show_chain, + STACK_OF(OPENSSL_STRING) *opts) { X509 *x = NULL; int i = 0, ret = 0; @@ -212,22 +253,35 @@ STACK_OF(X509) *chain = NULL; int num_untrusted; - x = load_cert(file, FORMAT_PEM, "certificate file"); + x = load_cert(file, FORMAT_UNDEF, "certificate file"); if (x == NULL) goto end; + if (opts != NULL) { + for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { + char *opt = sk_OPENSSL_STRING_value(opts, i); + if (x509_ctrl_string(x, opt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", opt); + ERR_print_errors(bio_err); + X509_free(x); + return 0; + } + } + } + csc = X509_STORE_CTX_new(); if (csc == NULL) { - printf("error %s: X.509 store context allocation failed\n", - (file == NULL) ? "stdin" : file); + BIO_printf(bio_err, "error %s: X.509 store context allocation failed\n", + (file == NULL) ? "stdin" : file); goto end; } X509_STORE_set_flags(ctx, vflags); if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { X509_STORE_CTX_free(csc); - printf("error %s: X.509 store context initialization failed\n", - (file == NULL) ? "stdin" : file); + BIO_printf(bio_err, + "error %s: X.509 store context initialization failed\n", + (file == NULL) ? "stdin" : file); goto end; } if (tchain != NULL) @@ -236,28 +290,30 @@ X509_STORE_CTX_set0_crls(csc, crls); i = X509_verify_cert(csc); if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) { - printf("%s: OK\n", (file == NULL) ? "stdin" : file); + BIO_printf(bio_out, "%s: OK\n", (file == NULL) ? "stdin" : file); ret = 1; if (show_chain) { int j; chain = X509_STORE_CTX_get1_chain(csc); num_untrusted = X509_STORE_CTX_get_num_untrusted(csc); - printf("Chain:\n"); + BIO_printf(bio_out, "Chain:\n"); for (j = 0; j < sk_X509_num(chain); j++) { X509 *cert = sk_X509_value(chain, j); - printf("depth=%d: ", j); + BIO_printf(bio_out, "depth=%d: ", j); X509_NAME_print_ex_fp(stdout, X509_get_subject_name(cert), 0, get_nameopt()); if (j < num_untrusted) - printf(" (untrusted)"); - printf("\n"); + BIO_printf(bio_out, " (untrusted)"); + BIO_printf(bio_out, "\n"); } sk_X509_pop_free(chain, X509_free); } } else { - printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file); + BIO_printf(bio_err, + "error %s: verification failed\n", + (file == NULL) ? "stdin" : file); } X509_STORE_CTX_free(csc); @@ -298,19 +354,34 @@ policies_print(ctx); /* fall thru */ case X509_V_ERR_CERT_HAS_EXPIRED: - /* Continue even if the leaf is a self signed cert */ + /* 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: case X509_V_ERR_INVALID_NON_CA: case X509_V_ERR_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_INVALID_PURPOSE: case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + /* errors due to strict conformance checking (-x509_strict) */ + case X509_V_ERR_INVALID_PURPOSE: + case X509_V_ERR_PATHLEN_INVALID_FOR_NON_CA: + case X509_V_ERR_PATHLEN_WITHOUT_KU_KEY_CERT_SIGN: + case X509_V_ERR_CA_BCONS_NOT_CRITICAL: + case X509_V_ERR_CA_CERT_MISSING_KEY_USAGE: + case X509_V_ERR_KU_KEY_CERT_SIGN_INVALID_FOR_NON_CA: + case X509_V_ERR_ISSUER_NAME_EMPTY: + case X509_V_ERR_SUBJECT_NAME_EMPTY: + case X509_V_ERR_EMPTY_SUBJECT_SAN_NOT_CRITICAL: + case X509_V_ERR_EMPTY_SUBJECT_ALT_NAME: + case X509_V_ERR_SIGNATURE_ALGORITHM_INCONSISTENCY: + case X509_V_ERR_AUTHORITY_KEY_IDENTIFIER_CRITICAL: + case X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL: + case X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER: + case X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER: + case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3: ok = 1; } - return ok; } diff --git a/apps/version.c b/apps/version.c --- a/apps/version.c +++ b/apps/version.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -15,56 +15,36 @@ #include #include #include -#ifndef OPENSSL_NO_MD2 -# include -#endif -#ifndef OPENSSL_NO_RC4 -# include -#endif -#ifndef OPENSSL_NO_DES -# include -#endif -#ifndef OPENSSL_NO_IDEA -# include -#endif -#ifndef OPENSSL_NO_BF -# include -#endif typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R + OPT_COMMON, + OPT_B, OPT_D, OPT_E, OPT_M, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R, OPT_C } OPTION_CHOICE; const OPTIONS version_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + + OPT_SECTION("Output"), {"a", OPT_A, '-', "Show all data"}, {"b", OPT_B, '-', "Show build date"}, {"d", OPT_D, '-', "Show configuration directory"}, {"e", OPT_E, '-', "Show engines directory"}, + {"m", OPT_M, '-', "Show modules directory"}, {"f", OPT_F, '-', "Show compiler flags used"}, {"o", OPT_O, '-', "Show some internal datatype options"}, {"p", OPT_P, '-', "Show target build platform"}, {"r", OPT_R, '-', "Show random seeding options"}, {"v", OPT_V, '-', "Show library version"}, + {"c", OPT_C, '-', "Show CPU settings info"}, {NULL} }; -#if defined(OPENSSL_RAND_SEED_DEVRANDOM) || defined(OPENSSL_RAND_SEED_EGD) -static void printlist(const char *prefix, const char **dev) -{ - printf("%s (", prefix); - for ( ; *dev != NULL; dev++) - printf(" \"%s\"", *dev); - printf(" )"); -} -#endif - int version_main(int argc, char **argv) { int ret = 1, dirty = 0, seed = 0; int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0; - int engdir = 0; + int engdir = 0, moddir = 0, cpuinfo = 0; char *prog; OPTION_CHOICE o; @@ -89,6 +69,9 @@ case OPT_E: dirty = engdir = 1; break; + case OPT_M: + dirty = moddir = 1; + break; case OPT_F: dirty = cflags = 1; break; @@ -104,48 +87,35 @@ case OPT_V: dirty = version = 1; break; + case OPT_C: + dirty = cpuinfo = 1; + break; case OPT_A: - seed = options = cflags = version = date = platform = dir = engdir + seed = options = cflags = version = date = platform + = dir = engdir = moddir = cpuinfo = 1; break; } } - if (opt_num_rest() != 0) { - BIO_printf(bio_err, "Extra parameters given.\n"); + + /* No extra arguments. */ + argc = opt_num_rest(); + if (argc != 0) goto opthelp; - } + if (!dirty) version = 1; - if (version) { - if (OpenSSL_version_num() == OPENSSL_VERSION_NUMBER) - printf("%s\n", OpenSSL_version(OPENSSL_VERSION)); - else - printf("%s (Library: %s)\n", - OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION)); - } + if (version) + printf("%s (Library: %s)\n", + OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION)); if (date) printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON)); if (platform) printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM)); if (options) { - printf("options: "); - printf("%s ", BN_options()); -#ifndef OPENSSL_NO_MD2 - printf("%s ", MD2_options()); -#endif -#ifndef OPENSSL_NO_RC4 - printf("%s ", RC4_options()); -#endif -#ifndef OPENSSL_NO_DES - printf("%s ", DES_options()); -#endif -#ifndef OPENSSL_NO_IDEA - printf("%s ", IDEA_options()); -#endif -#ifndef OPENSSL_NO_BF - printf("%s ", BF_options()); -#endif + printf("options: "); + printf(" %s", BN_options()); printf("\n"); } if (cflags) @@ -154,41 +124,28 @@ printf("%s\n", OpenSSL_version(OPENSSL_DIR)); if (engdir) printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR)); + if (moddir) + printf("%s\n", OpenSSL_version(OPENSSL_MODULES_DIR)); if (seed) { - printf("Seeding source:"); -#ifdef OPENSSL_RAND_SEED_RTDSC - printf(" rtdsc"); -#endif -#ifdef OPENSSL_RAND_SEED_RDCPU - printf(" rdrand ( rdseed rdrand )"); -#endif -#ifdef OPENSSL_RAND_SEED_LIBRANDOM - printf(" C-library-random"); -#endif -#ifdef OPENSSL_RAND_SEED_GETRANDOM - printf(" getrandom-syscall"); -#endif -#ifdef OPENSSL_RAND_SEED_DEVRANDOM - { - static const char *dev[] = { DEVRANDOM, NULL }; - printlist(" random-device", dev); - } -#endif -#ifdef OPENSSL_RAND_SEED_EGD - { - static const char *dev[] = { DEVRANDOM_EGD, NULL }; - printlist(" EGD", dev); - } -#endif -#ifdef OPENSSL_RAND_SEED_NONE - printf(" none"); -#endif -#ifdef OPENSSL_RAND_SEED_OS - printf(" os-specific"); -#endif - printf("\n"); + const char *src = OPENSSL_info(OPENSSL_INFO_SEED_SOURCE); + printf("Seeding source: %s\n", src ? src : "N/A"); } + if (cpuinfo) + printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO)); ret = 0; end: return ret; } + + +#if defined(__TANDEM) && defined(OPENSSL_VPROC) +/* + * Define a VPROC function for the openssl program. + * This is used by platform version identification tools. + * Do not inline this procedure or make it static. + */ +# define OPENSSL_VPROC_STRING_(x) x##_OPENSSL +# define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x) +# define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC) +void OPENSSL_VPROC_FUNC(void) {} +#endif diff --git a/apps/x509.c b/apps/x509.c --- a/apps/x509.c +++ b/apps/x509.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -21,162 +21,271 @@ #include #include #include -#ifndef OPENSSL_NO_RSA -# include -#endif +#include #ifndef OPENSSL_NO_DSA # include #endif #undef POSTFIX #define POSTFIX ".srl" -#define DEF_DAYS 30 +#define DEFAULT_DAYS 30 /* default cert validity period in days */ +#define UNSET_DAYS -2 /* -1 is used for testing expiration checks */ +#define EXT_COPY_UNSET -1 static int callb(int ok, X509_STORE_CTX *ctx); -static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, - const EVP_MD *digest, CONF *conf, const char *section, - int preserve_dates); -static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, - X509 *x, X509 *xca, EVP_PKEY *pkey, - STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile, - int create, int days, int clrext, CONF *conf, - const char *section, ASN1_INTEGER *sno, int reqfile, - int preserve_dates); +static ASN1_INTEGER *x509_load_serial(const char *CAfile, + const char *serialfile, int create); static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); -static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts); +static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, - OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, - OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, - OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY, - OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, - OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, + OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, + OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY, + OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ, + OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT, + OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST, OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST, OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, - OPT_SUBJECT_HASH_OLD, - OPT_ISSUER_HASH_OLD, + OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS, OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, - OPT_R_ENUM, OPT_EXT + OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT } OPTION_CHOICE; const OPTIONS x509_options[] = { + OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + + {"in", OPT_IN, '<', + "Certificate input, or CSR input file with -req (default stdin)"}, + {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"}, + {"new", OPT_NEW, '-', "Generate a certificate from scratch"}, + {"x509toreq", OPT_X509TOREQ, '-', + "Output a certification request (rather than a certificate)"}, + {"req", OPT_REQ, '-', "Input is a CSR file (rather than a certificate)"}, + {"copy_extensions", OPT_COPY_EXTENSIONS, 's', + "copy extensions when converting from CSR to x509 or vice versa"}, {"inform", OPT_INFORM, 'f', - "Input format - default PEM (one of DER or PEM)"}, - {"in", OPT_IN, '<', "Input file - default stdin"}, - {"outform", OPT_OUTFORM, 'f', - "Output format - default PEM (one of DER or PEM)"}, + "CSR input file format (DER or PEM) - default PEM"}, + {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"}, + {"key", OPT_KEY, 's', + "Key for signing, and to include unless using -force_pubkey"}, + {"signkey", OPT_SIGNKEY, 's', + "Same as -key"}, + {"keyform", OPT_KEYFORM, 'E', + "Key input format (ENGINE, other values ignored)"}, {"out", OPT_OUT, '>', "Output file - default stdout"}, - {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, - {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"}, + {"outform", OPT_OUTFORM, 'f', + "Output format (DER or PEM) - default PEM"}, + {"nocert", OPT_NOCERT, '-', + "No cert output (except for requested printing)"}, + {"noout", OPT_NOOUT, '-', "No output (except for requested printing)"}, + + OPT_SECTION("Certificate printing"), + {"text", OPT_TEXT, '-', "Print the certificate in text form"}, + {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, + {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"}, + {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"}, + {"alias", OPT_ALIAS, '-', "Print certificate alias"}, {"serial", OPT_SERIAL, '-', "Print serial number value"}, - {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, - {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, - {"hash", OPT_HASH, '-', "Synonym for -subject_hash"}, + {"startdate", OPT_STARTDATE, '-', "Print the notBefore field"}, + {"enddate", OPT_ENDDATE, '-', "Print the notAfter field"}, + {"dates", OPT_DATES, '-', "Print both notBefore and notAfter fields"}, {"subject", OPT_SUBJECT, '-', "Print subject DN"}, {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, + {"nameopt", OPT_NAMEOPT, 's', + "Certificate subject/issuer name printing options"}, {"email", OPT_EMAIL, '-', "Print email address(es)"}, - {"startdate", OPT_STARTDATE, '-', "Set notBefore field"}, - {"enddate", OPT_ENDDATE, '-', "Set notAfter field"}, - {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, - {"dates", OPT_DATES, '-', "Both Before and After dates"}, - {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, - {"pubkey", OPT_PUBKEY, '-', "Output the public key"}, - {"fingerprint", OPT_FINGERPRINT, '-', - "Print the certificate fingerprint"}, - {"alias", OPT_ALIAS, '-', "Output certificate alias"}, - {"noout", OPT_NOOUT, '-', "No output, just status"}, - {"nocert", OPT_NOCERT, '-', "No certificate output"}, + {"hash", OPT_HASH, '-', "Synonym for -subject_hash (for backward compat)"}, + {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, +#ifndef OPENSSL_NO_MD5 + {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', + "Print old-style (MD5) subject hash value"}, +#endif + {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, +#ifndef OPENSSL_NO_MD5 + {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', + "Print old-style (MD5) issuer hash value"}, +#endif + {"ext", OPT_EXT, 's', + "Restrict which X.509 extensions to print and/or copy"}, {"ocspid", OPT_OCSPID, '-', "Print OCSP hash values for the subject name and public key"}, {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"}, - {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"}, - {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, - {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"}, - {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, - {"addreject", OPT_ADDREJECT, 's', - "Reject certificate for a given purpose"}, - {"setalias", OPT_SETALIAS, 's', "Set certificate alias"}, - {"days", OPT_DAYS, 'n', - "How long till expiry of a signed certificate - def 30 days"}, + {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, + {"pubkey", OPT_PUBKEY, '-', "Print the public key in PEM format"}, + {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, + + OPT_SECTION("Certificate checking"), {"checkend", OPT_CHECKEND, 'M', - "Check whether the cert expires in the next arg seconds"}, - {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"}, - {"signkey", OPT_SIGNKEY, 's', "Self sign cert with arg"}, - {"x509toreq", OPT_X509TOREQ, '-', - "Output a certification request object"}, - {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"}, - {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"}, - {"CAkey", OPT_CAKEY, 's', - "The CA key, must be PEM format; if not in CAfile"}, - {"CAcreateserial", OPT_CACREATESERIAL, '-', - "Create serial number file if it does not exist"}, - {"CAserial", OPT_CASERIAL, 's', "Serial file"}, - {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, - {"text", OPT_TEXT, '-', "Print the certificate in text form"}, - {"ext", OPT_EXT, 's', "Print various X509V3 extensions"}, - {"C", OPT_C, '-', "Print out C code forms"}, - {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"}, - OPT_R_OPTIONS, - {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"}, - {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, - {"certopt", OPT_CERTOPT, 's', "Various certificate text options"}, + "Check whether cert expires in the next arg seconds"}, + {OPT_MORE_STR, 1, 1, "Exit 1 (failure) if so, 0 if not"}, {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"}, {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"}, {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"}, - {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"}, - {"CAkeyform", OPT_CAKEYFORM, 'E', "CA key format - default PEM"}, - {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, - {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"}, - {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"}, + + OPT_SECTION("Certificate output"), + {"set_serial", OPT_SET_SERIAL, 's', + "Serial number to use, overrides -CAserial"}, + {"next_serial", OPT_NEXT_SERIAL, '-', + "Increment current certificate serial number"}, + {"days", OPT_DAYS, 'n', + "Number of days until newly generated certificate expires - default 30"}, + {"preserve_dates", OPT_PRESERVE_DATES, '-', + "Preserve existing validity dates"}, + {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"}, + {"force_pubkey", OPT_FORCE_PUBKEY, '<', + "Place the given key in new certificate"}, + {"clrext", OPT_CLREXT, '-', + "Do not take over any extensions from the source certificate or request"}, + {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"}, + {"extensions", OPT_EXTENSIONS, 's', + "Section of extfile to use - default: unnamed section"}, + {"sigopt", OPT_SIGOPT, 's', "Signature parameter, in n:v form"}, + {"badsig", OPT_BADSIG, '-', + "Corrupt last byte of certificate signature (for test)"}, + {"", OPT_MD, '-', "Any supported digest, used for signing and printing"}, + + OPT_SECTION("Micro-CA"), + {"CA", OPT_CA, '<', + "Use the given CA certificate, conflicts with -key"}, + {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"}, + {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"}, + {"CAkeyform", OPT_CAKEYFORM, 'E', + "CA key format (ENGINE, other values ignored)"}, + {"CAserial", OPT_CASERIAL, 's', + "File that keeps track of CA-generated serial number"}, + {"CAcreateserial", OPT_CACREATESERIAL, '-', + "Create CA serial number file if it does not exist"}, + + OPT_SECTION("Certificate trust output"), + {"trustout", OPT_TRUSTOUT, '-', "Mark certificate PEM output as trusted"}, + {"setalias", OPT_SETALIAS, 's', "Set certificate alias (nickname)"}, + {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, + {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, {"clrreject", OPT_CLRREJECT, '-', "Clears all the prohibited or rejected uses of the certificate"}, - {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"}, - {"", OPT_MD, '-', "Any supported digest"}, -#ifndef OPENSSL_NO_MD5 - {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', - "Print old-style (MD5) subject hash value"}, - {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', - "Print old-style (MD5) issuer hash value"}, -#endif + {"addreject", OPT_ADDREJECT, 's', + "Reject certificate for a given purpose"}, + + OPT_R_OPTIONS, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif - {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"}, + OPT_PROV_OPTIONS, {NULL} }; +static void warn_copying(ASN1_OBJECT *excluded, const char *names) +{ + const char *sn = OBJ_nid2sn(OBJ_obj2nid(excluded)); + + if (names != NULL && strstr(names, sn) != NULL) + BIO_printf(bio_err, + "Warning: -ext should not specify copying %s extension to CSR; ignoring this\n", + sn); +} + +static X509_REQ *x509_to_req(X509 *cert, int ext_copy, const char *names) +{ + const STACK_OF(X509_EXTENSION) *cert_exts = X509_get0_extensions(cert); + int i, n = sk_X509_EXTENSION_num(cert_exts /* may be NULL */); + ASN1_OBJECT *skid = OBJ_nid2obj(NID_subject_key_identifier); + ASN1_OBJECT *akid = OBJ_nid2obj(NID_authority_key_identifier); + STACK_OF(X509_EXTENSION) *exts; + X509_REQ *req = X509_to_X509_REQ(cert, NULL, NULL); + + if (req == NULL) + return NULL; + + /* + * Filter out SKID and AKID extensions, which make no sense in a CSR. + * If names is not NULL, copy only those extensions listed there. + */ + warn_copying(skid, names); + warn_copying(akid, names); + if ((exts = sk_X509_EXTENSION_new_reserve(NULL, n)) == NULL) + goto err; + for (i = 0; i < n; i++) { + X509_EXTENSION *ex = sk_X509_EXTENSION_value(cert_exts, i); + ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); + + if (OBJ_cmp(obj, skid) != 0 && OBJ_cmp(obj, akid) != 0 + && !sk_X509_EXTENSION_push(exts, ex)) + goto err; + } + + if (sk_X509_EXTENSION_num(exts) > 0) { + if (ext_copy != EXT_COPY_UNSET && ext_copy != EXT_COPY_NONE + && !X509_REQ_add_extensions(req, exts)) { + BIO_printf(bio_err, "Error copying extensions from certificate\n"); + goto err; + } + } + sk_X509_EXTENSION_free(exts); + return req; + + err: + sk_X509_EXTENSION_free(exts); + X509_REQ_free(req); + return NULL; +} + +static int self_signed(X509_STORE *ctx, X509 *cert) +{ + X509_STORE_CTX *xsc = X509_STORE_CTX_new(); + int ret = 0; + + if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, cert, NULL)) { + BIO_printf(bio_err, "Error initialising X509 store\n"); + } else { + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); + ret = X509_verify_cert(xsc) > 0; + } + X509_STORE_CTX_free(xsc); + return ret; +} + int x509_main(int argc, char **argv) { ASN1_INTEGER *sno = NULL; ASN1_OBJECT *objtmp = NULL; BIO *out = NULL; CONF *extconf = NULL; - EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; + int ext_copy = EXT_COPY_UNSET; + X509V3_CTX ext_ctx; + EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL; + EVP_PKEY *pkey; + int newcert = 0; + char *subj = NULL, *digest = NULL; + X509_NAME *fsubj = NULL; + const unsigned long chtype = MBSTRING_ASC; + const int multirdn = 1; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; - STACK_OF(OPENSSL_STRING) *sigopts = NULL; - X509 *x = NULL, *xca = NULL; + STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL; + X509 *x = NULL, *xca = NULL, *issuer_cert; X509_REQ *req = NULL, *rq = NULL; X509_STORE *ctx = NULL; - const EVP_MD *digest = NULL; - char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; - char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL; + char *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL; + char *checkhost = NULL, *checkemail = NULL, *checkip = NULL; + char *ext_names = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; - char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; + char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL; char *prog; - int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; - int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; + int days = UNSET_DAYS; /* not explicitly set */ + int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0; + int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF; + unsigned long dateopt = ASN1_DTFLGS_RFC822; int fingerprint = 0, reqfile = 0, checkend = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF; int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; - int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; + int noout = 0, CA_createserial = 0, email = 0; int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; - int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; + int ret = 1, i, j, num = 0, badsig = 0, clrext = 0, nocert = 0; int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; int enddate = 0; time_t checkoffset = 0; @@ -206,7 +315,7 @@ ret = 0; goto end; case OPT_INFORM: - if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) + if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_IN: @@ -217,15 +326,15 @@ goto opthelp; break; case OPT_KEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) goto opthelp; break; case OPT_CAFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAformat)) goto opthelp; break; case OPT_CAKEYFORM: - if (!opt_format(opt_arg(), OPT_FMT_PDE, &CAkeyformat)) + if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat)) goto opthelp; break; case OPT_OUT: @@ -235,16 +344,40 @@ reqfile = 1; break; + case OPT_DATEOPT: + if (!set_dateopt(&dateopt, opt_arg())) { + BIO_printf(bio_err, + "Invalid date format: %s\n", opt_arg()); + goto end; + } + break; + case OPT_COPY_EXTENSIONS: + if (!set_ext_copy(&ext_copy, opt_arg())) { + BIO_printf(bio_err, + "Invalid extension copy option: %s\n", opt_arg()); + goto end; + } + break; + case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; - case OPT_DAYS: - if (preserve_dates) + case OPT_VFYOPT: + if (!vfyopts) + vfyopts = sk_OPENSSL_STRING_new_null(); + if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) goto opthelp; + break; + case OPT_DAYS: days = atoi(opt_arg()); + if (days < -1) { + BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n", + prog); + goto end; + } break; case OPT_PASSIN: passinarg = opt_arg(); @@ -256,16 +389,19 @@ if (!opt_rand(o)) goto end; break; + case OPT_PROV_CASES: + if (!opt_provider(o)) + goto end; + break; case OPT_EXTENSIONS: extsect = opt_arg(); break; + case OPT_KEY: case OPT_SIGNKEY: - keyfile = opt_arg(); - sign_flag = ++num; + privkeyfile = opt_arg(); break; case OPT_CA: CAfile = opt_arg(); - CA_flag = ++num; break; case OPT_CAKEY: CAkeyfile = opt_arg(); @@ -281,34 +417,35 @@ if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) goto opthelp; break; + case OPT_NEW: + newcert = 1; + break; case OPT_FORCE_PUBKEY: - fkeyfile = opt_arg(); + pubkeyfile = opt_arg(); + break; + case OPT_SUBJ: + subj = opt_arg(); break; case OPT_ADDTRUST: + if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { - BIO_printf(bio_err, - "%s: Invalid trust object value %s\n", + BIO_printf(bio_err, "%s: Invalid trust object value %s\n", prog, opt_arg()); goto opthelp; } - if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) - goto end; sk_ASN1_OBJECT_push(trust, objtmp); - objtmp = NULL; trustout = 1; break; case OPT_ADDREJECT: + if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { - BIO_printf(bio_err, - "%s: Invalid reject object value %s\n", + BIO_printf(bio_err, "%s: Invalid reject object value %s\n", prog, opt_arg()); goto opthelp; } - if (reject == NULL - && (reject = sk_ASN1_OBJECT_new_null()) == NULL) - goto end; sk_ASN1_OBJECT_push(reject, objtmp); - objtmp = NULL; trustout = 1; break; case OPT_SETALIAS: @@ -326,9 +463,6 @@ case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; - case OPT_C: - C = ++num; - break; case OPT_EMAIL: email = ++num; break; @@ -345,10 +479,10 @@ modulus = ++num; break; case OPT_PUBKEY: - pubkey = ++num; + print_pubkey = ++num; break; case OPT_X509TOREQ: - x509req = ++num; + x509toreq = 1; break; case OPT_TEXT: text = ++num; @@ -382,7 +516,7 @@ break; case OPT_EXT: ext = ++num; - exts = opt_arg(); + ext_names = opt_arg(); break; case OPT_NOCERT: nocert = 1; @@ -430,12 +564,12 @@ case OPT_CHECKEND: checkend = 1; { - intmax_t temp = 0; - if (!opt_imax(opt_arg(), &temp)) + ossl_intmax_t temp = 0; + if (!opt_intmax(opt_arg(), &temp)) goto opthelp; checkoffset = (time_t)temp; - if ((intmax_t)checkoffset != temp) { - BIO_printf(bio_err, "%s: checkend time out of range %s\n", + if ((ossl_intmax_t)checkoffset != temp) { + BIO_printf(bio_err, "%s: Checkend time out of range %s\n", prog, opt_arg()); goto opthelp; } @@ -451,48 +585,103 @@ checkip = opt_arg(); break; case OPT_PRESERVE_DATES: - if (days != DEF_DAYS) - goto opthelp; preserve_dates = 1; break; case OPT_MD: - if (!opt_md(opt_unknown(), &digest)) - goto opthelp; + digest = opt_unknown(); + break; } } + + /* No extra arguments. */ argc = opt_num_rest(); - argv = opt_rest(); - if (argc != 0) { - BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); + if (argc != 0) goto opthelp; + + if (!app_RAND_load()) + goto end; + + if (preserve_dates && days != UNSET_DAYS) { + BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n"); + goto end; } + if (days == UNSET_DAYS) + days = DEFAULT_DAYS; if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } - if (!X509_STORE_set_default_paths(ctx)) { - ERR_print_errors(bio_err); + if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(), + app_get0_propq())) + goto end; + + if (newcert && infile != NULL) { + BIO_printf(bio_err, "The -in option cannot be used with -new\n"); + goto end; + } + if (newcert && reqfile) { + BIO_printf(bio_err, + "The -req option cannot be used with -new\n"); goto end; } + if (privkeyfile != NULL) { + privkey = load_key(privkeyfile, keyformat, 0, passin, e, "private key"); + if (privkey == NULL) + goto end; + } + if (pubkeyfile != NULL) { + if ((pubkey = load_pubkey(pubkeyfile, keyformat, 0, NULL, e, + "explicitly set public key")) == NULL) + goto end; + } - if (fkeyfile != NULL) { - fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key"); - if (fkey == NULL) + if (newcert) { + if (subj == NULL) { + BIO_printf(bio_err, + "The -new option requires a subject to be set using -subj\n"); goto end; + } + if (privkeyfile == NULL && pubkeyfile == NULL) { + BIO_printf(bio_err, + "The -new option requires using the -key or -force_pubkey option\n"); + goto end; + } } + if (subj != NULL + && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL) + goto end; - if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { + if (CAkeyfile == NULL) CAkeyfile = CAfile; - } else if ((CA_flag) && (CAkeyfile == NULL)) { - BIO_printf(bio_err, - "need to specify a CAkey if using the CA command\n"); - goto end; + if (CAfile != NULL) { + if (privkeyfile != NULL) { + BIO_printf(bio_err, "Cannot use both -key/-signkey and -CA option\n"); + goto end; + } + } else { +#define WARN_NO_CA(opt) BIO_printf(bio_err, \ + "Warning: ignoring " opt " option since -CA option is not given\n"); + if (CAkeyfile != NULL) + WARN_NO_CA("-CAkey"); + if (CAkeyformat != FORMAT_UNDEF) + WARN_NO_CA("-CAkeyform"); + if (CAformat != FORMAT_UNDEF) + WARN_NO_CA("-CAform"); + if (CAserial != NULL) + WARN_NO_CA("-CAserial"); + if (CA_createserial) + WARN_NO_CA("-CAcreateserial"); } - if (extfile != NULL) { + if (extfile == NULL) { + if (extsect != NULL) + BIO_printf(bio_err, + "Warning: ignoring -extensions option without -extfile\n"); + } else { X509V3_CTX ctx2; + if ((extconf = app_load_config(extfile)) == NULL) goto end; if (extsect == NULL) { @@ -506,92 +695,79 @@ X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, - "Error Loading extension section %s\n", extsect); - ERR_print_errors(bio_err); + "Error checking extension section %s\n", extsect); goto end; } } if (reqfile) { - EVP_PKEY *pkey; - BIO *in; - - if (!sign_flag && !CA_flag) { - BIO_printf(bio_err, "We need a private key to sign with\n"); + req = load_csr(infile, informat, "certificate request input"); + if (req == NULL) goto end; - } - in = bio_open_default(infile, 'r', informat); - if (in == NULL) - goto end; - req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); - BIO_free(in); - - if (req == NULL) { - ERR_print_errors(bio_err); - goto end; - } if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { - BIO_printf(bio_err, "error unpacking public key\n"); + BIO_printf(bio_err, "Error unpacking public key from CSR\n"); goto end; } - i = X509_REQ_verify(req, pkey); - if (i < 0) { - BIO_printf(bio_err, "Signature verification error\n"); - ERR_print_errors(bio_err); + i = do_X509_REQ_verify(req, pkey, vfyopts); + if (i <= 0) { + BIO_printf(bio_err, i < 0 + ? "Error while verifying certificate request self-signature\n" + : "Certificate request self-signature did not match the contents\n"); goto end; } - if (i == 0) { + BIO_printf(bio_err, "Certificate request self-signature ok\n"); + + print_name(bio_err, "subject=", X509_REQ_get_subject_name(req)); + } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) { + BIO_printf(bio_err, "Warning: ignoring -copy_extensions since neither -x509toreq nor -req is given\n"); + } + + if (reqfile || newcert) { + if (preserve_dates) BIO_printf(bio_err, - "Signature did not match the certificate request\n"); + "Warning: ignoring -preserve_dates option with -req or -new\n"); + preserve_dates = 0; + if (privkeyfile == NULL && CAkeyfile == NULL) { + BIO_printf(bio_err, + "We need a private key to sign with, use -key or -CAkey or -CA with private key\n"); goto end; - } else { - BIO_printf(bio_err, "Signature ok\n"); } - - print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), - get_nameopt()); - - if ((x = X509_new()) == NULL) + if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) goto end; - - if (sno == NULL) { + if (CAfile == NULL && sno == NULL) { sno = ASN1_INTEGER_new(); if (sno == NULL || !rand_serial(NULL, sno)) goto end; - if (!X509_set_serialNumber(x, sno)) - goto end; - ASN1_INTEGER_free(sno); - sno = NULL; - } else if (!X509_set_serialNumber(x, sno)) { - goto end; } - - if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req))) - goto end; - if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) - goto end; - if (!set_cert_times(x, NULL, NULL, days)) - goto end; - - if (fkey != NULL) { - X509_set_pubkey(x, fkey); - } else { - pkey = X509_REQ_get0_pubkey(req); - X509_set_pubkey(x, pkey); + if (req != NULL && ext_copy != EXT_COPY_UNSET) { + if (clrext && ext_copy != EXT_COPY_NONE) { + BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); + goto end; + } else if (!copy_extensions(x, req, ext_copy)) { + BIO_printf(bio_err, "Error copying extensions from request\n"); + goto end; + } } } else { - x = load_cert(infile, informat, "Certificate"); + x = load_cert_pass(infile, informat, 1, passin, "certificate"); + if (x == NULL) + goto end; } - - if (x == NULL) + if ((fsubj != NULL || req != NULL) + && !X509_set_subject_name(x, fsubj != NULL ? fsubj : + X509_REQ_get_subject_name(req))) goto end; - if (CA_flag) { - xca = load_cert(CAfile, CAformat, "CA Certificate"); + if ((pubkey != NULL || privkey != NULL || req != NULL) + && !X509_set_pubkey(x, pubkey != NULL ? pubkey : + privkey != NULL ? privkey : + X509_REQ_get0_pubkey(req))) + goto end; + + if (CAfile != NULL) { + xca = load_cert_pass(CAfile, CAformat, 1, passin, "CA certificate"); if (xca == NULL) goto end; - if (reqfile && !X509_set_issuer_name(x, X509_get_subject_name(xca))) - goto end; } out = bio_open_default(outfile, 'w', outformat); @@ -610,21 +786,120 @@ X509_reject_clear(x); if (trust != NULL) { - for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { - objtmp = sk_ASN1_OBJECT_value(trust, i); - X509_add1_trust_object(x, objtmp); - } - objtmp = NULL; + for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) + X509_add1_trust_object(x, sk_ASN1_OBJECT_value(trust, i)); } if (reject != NULL) { - for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { - objtmp = sk_ASN1_OBJECT_value(reject, i); - X509_add1_reject_object(x, objtmp); + for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) + X509_add1_reject_object(x, sk_ASN1_OBJECT_value(reject, i)); + } + + if (clrext && ext_names != NULL) + BIO_printf(bio_err, "Warning: Ignoring -ext since -clrext is given\n"); + for (i = X509_get_ext_count(x) - 1; i >= 0; i--) { + X509_EXTENSION *ex = X509_get_ext(x, i); + const char *sn = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ex))); + + if (clrext || (ext_names != NULL && strstr(ext_names, sn) == NULL)) + X509_EXTENSION_free(X509_delete_ext(x, i)); + } + + issuer_cert = x; + if (CAfile != NULL) { + issuer_cert = xca; + if (sno == NULL) + sno = x509_load_serial(CAfile, CAserial, CA_createserial); + if (sno == NULL) + goto end; + if (!x509toreq && !reqfile && !newcert && !self_signed(ctx, x)) + goto end; + } + + if (sno != NULL && !X509_set_serialNumber(x, sno)) + goto end; + + if (reqfile || newcert || privkey != NULL || CAfile != NULL) { + if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) + goto end; + if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert))) + goto end; + } + + X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE); + /* prepare fallback for AKID, but only if issuer cert equals subject cert */ + if (CAfile == NULL) { + if (!X509V3_set_issuer_pkey(&ext_ctx, privkey)) + goto end; + } + if (extconf != NULL && !x509toreq) { + X509V3_set_nconf(&ext_ctx, extconf); + if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) { + BIO_printf(bio_err, + "Error adding extensions from section %s\n", extsect); + goto end; } - objtmp = NULL; } + /* At this point the contents of the certificate x have been finished. */ + + pkey = X509_get0_pubkey(x); + if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) { + BIO_printf(bio_err, "Error getting public key\n"); + goto end; + } + + if (x509toreq) { /* also works in conjunction with -req */ + if (privkey == NULL) { + BIO_printf(bio_err, "Must specify request signing key using -key\n"); + goto end; + } + if (clrext && ext_copy != EXT_COPY_NONE) { + BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); + goto end; + } + if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL) + goto end; + if (extconf != NULL) { + X509V3_set_nconf(&ext_ctx, extconf); + if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) { + BIO_printf(bio_err, + "Error adding request extensions from section %s\n", extsect); + goto end; + } + } + if (!do_X509_REQ_sign(rq, privkey, digest, sigopts)) + goto end; + if (!noout) { + if (outformat == FORMAT_ASN1) { + X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT); + i = i2d_X509_bio(out, x); + } else { + i = PEM_write_bio_X509_REQ(out, rq); + } + if (!i) { + BIO_printf(bio_err, + "Unable to write certificate request\n"); + goto end; + } + } + noout = 1; + } else if (privkey != NULL) { + if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx)) + goto end; + } else if (CAfile != NULL) { + if ((CAkey = load_key(CAkeyfile, CAkeyformat, + 0, passin, e, "CA private key")) == NULL) + goto end; + if (!X509_check_private_key(xca, CAkey)) { + BIO_printf(bio_err, + "CA certificate and CA private key do not match\n"); + goto end; + } + + if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx)) + goto end; + } if (badsig) { const ASN1_BIT_STRING *signature; @@ -632,236 +907,133 @@ corrupt_signature(signature); } - if (num) { - for (i = 1; i <= num; i++) { - if (issuer == i) { - print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); - } else if (subject == i) { - print_name(out, "subject=", - X509_get_subject_name(x), get_nameopt()); - } else if (serial == i) { - BIO_printf(out, "serial="); - i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); - BIO_printf(out, "\n"); - } else if (next_serial == i) { - ASN1_INTEGER *ser = X509_get_serialNumber(x); - BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL); - - if (!bnser) - goto end; - if (!BN_add_word(bnser, 1)) - goto end; - ser = BN_to_ASN1_INTEGER(bnser, NULL); - if (!ser) - goto end; + /* Process print options in the given order, as indicated by index i */ + for (i = 1; i <= num; i++) { + if (i == issuer) { + print_name(out, "issuer=", X509_get_issuer_name(x)); + } else if (i == subject) { + print_name(out, "subject=", X509_get_subject_name(x)); + } else if (i == serial) { + BIO_printf(out, "serial="); + i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x)); + BIO_printf(out, "\n"); + } else if (i == next_serial) { + ASN1_INTEGER *ser; + BIGNUM *bnser = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x), NULL); + + if (bnser == NULL) + goto end; + if (!BN_add_word(bnser, 1) + || (ser = BN_to_ASN1_INTEGER(bnser, NULL)) == NULL) { BN_free(bnser); - i2a_ASN1_INTEGER(out, ser); - ASN1_INTEGER_free(ser); - BIO_puts(out, "\n"); - } else if ((email == i) || (ocsp_uri == i)) { - int j; - STACK_OF(OPENSSL_STRING) *emlst; - if (email == i) - emlst = X509_get1_email(x); - else - emlst = X509_get1_ocsp(x); - for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) - BIO_printf(out, "%s\n", - sk_OPENSSL_STRING_value(emlst, j)); - X509_email_free(emlst); - } else if (aliasout == i) { - unsigned char *alstr; - alstr = X509_alias_get0(x, NULL); - if (alstr) - BIO_printf(out, "%s\n", alstr); - else - BIO_puts(out, "\n"); - } else if (subject_hash == i) { - BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); + goto end; } + BN_free(bnser); + i2a_ASN1_INTEGER(out, ser); + ASN1_INTEGER_free(ser); + BIO_puts(out, "\n"); + } else if (i == email || i == ocsp_uri) { + STACK_OF(OPENSSL_STRING) *emlst = + i == email ? X509_get1_email(x) : X509_get1_ocsp(x); + + for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) + BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); + X509_email_free(emlst); + } else if (i == aliasout) { + unsigned char *alstr = X509_alias_get0(x, NULL); + + if (alstr) + BIO_printf(out, "%s\n", alstr); + else + BIO_puts(out, "\n"); + } else if (i == subject_hash) { + BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); #ifndef OPENSSL_NO_MD5 - else if (subject_hash_old == i) { - BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); - } + } else if (i == subject_hash_old) { + BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); #endif - else if (issuer_hash == i) { - BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); - } + } else if (i == issuer_hash) { + BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); #ifndef OPENSSL_NO_MD5 - else if (issuer_hash_old == i) { - BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); - } + } else if (i == issuer_hash_old) { + BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); #endif - else if (pprint == i) { - X509_PURPOSE *ptmp; - int j; - BIO_printf(out, "Certificate purposes:\n"); - for (j = 0; j < X509_PURPOSE_get_count(); j++) { - ptmp = X509_PURPOSE_get0(j); - purpose_print(out, x, ptmp); - } - } else if (modulus == i) { - EVP_PKEY *pkey; - - pkey = X509_get0_pubkey(x); - if (pkey == NULL) { - BIO_printf(bio_err, "Modulus=unavailable\n"); - ERR_print_errors(bio_err); - goto end; - } - BIO_printf(out, "Modulus="); -#ifndef OPENSSL_NO_RSA - if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { - const BIGNUM *n; - RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL); - BN_print(out, n); - } else -#endif -#ifndef OPENSSL_NO_DSA - if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { - const BIGNUM *dsapub = NULL; - DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL); - BN_print(out, dsapub); - } else -#endif - { - BIO_printf(out, "Wrong Algorithm type"); - } - BIO_printf(out, "\n"); - } else if (pubkey == i) { - EVP_PKEY *pkey; - - pkey = X509_get0_pubkey(x); - if (pkey == NULL) { - BIO_printf(bio_err, "Error getting public key\n"); - ERR_print_errors(bio_err); - goto end; - } - PEM_write_bio_PUBKEY(out, pkey); - } else if (C == i) { - unsigned char *d; - char *m; - int len; - - print_name(out, "/*\n" - " * Subject: ", X509_get_subject_name(x), get_nameopt()); - print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt()); - BIO_puts(out, " */\n"); - - len = i2d_X509(x, NULL); - m = app_malloc(len, "x509 name buffer"); - d = (unsigned char *)m; - len = i2d_X509_NAME(X509_get_subject_name(x), &d); - print_array(out, "the_subject_name", len, (unsigned char *)m); - d = (unsigned char *)m; - len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); - print_array(out, "the_public_key", len, (unsigned char *)m); - d = (unsigned char *)m; - len = i2d_X509(x, &d); - print_array(out, "the_certificate", len, (unsigned char *)m); - OPENSSL_free(m); - } else if (text == i) { - X509_print_ex(out, x, get_nameopt(), certflag); - } else if (startdate == i) { - BIO_puts(out, "notBefore="); - ASN1_TIME_print(out, X509_get0_notBefore(x)); - BIO_puts(out, "\n"); - } else if (enddate == i) { - BIO_puts(out, "notAfter="); - ASN1_TIME_print(out, X509_get0_notAfter(x)); - BIO_puts(out, "\n"); - } else if (fingerprint == i) { - int j; - unsigned int n; - unsigned char md[EVP_MAX_MD_SIZE]; - const EVP_MD *fdig = digest; - - if (fdig == NULL) - fdig = EVP_sha1(); - - if (!X509_digest(x, fdig, md, &n)) { - BIO_printf(bio_err, "out of memory\n"); - goto end; - } - BIO_printf(out, "%s Fingerprint=", - OBJ_nid2sn(EVP_MD_type(fdig))); - for (j = 0; j < (int)n; j++) { - BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) - ? '\n' : ':'); - } + } else if (i == pprint) { + BIO_printf(out, "Certificate purposes:\n"); + for (j = 0; j < X509_PURPOSE_get_count(); j++) + purpose_print(out, x, X509_PURPOSE_get0(j)); + } else if (i == modulus) { + BIO_printf(out, "Modulus="); + if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) { + BIGNUM *n = NULL; + + /* Every RSA key has an 'n' */ + EVP_PKEY_get_bn_param(pkey, "n", &n); + BN_print(out, n); + BN_free(n); + } else if (EVP_PKEY_is_a(pkey, "DSA")) { + BIGNUM *dsapub = NULL; + + /* Every DSA key has a 'pub' */ + EVP_PKEY_get_bn_param(pkey, "pub", &dsapub); + BN_print(out, dsapub); + BN_free(dsapub); + } else { + BIO_printf(out, "No modulus for this public key type"); } - - /* should be in the library */ - else if ((sign_flag == i) && (x509req == 0)) { - BIO_printf(bio_err, "Getting Private key\n"); - if (Upkey == NULL) { - Upkey = load_key(keyfile, keyformat, 0, - passin, e, "Private key"); - if (Upkey == NULL) - goto end; - } - - if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates)) - goto end; - } else if (CA_flag == i) { - BIO_printf(bio_err, "Getting CA Private Key\n"); - if (CAkeyfile != NULL) { - CApkey = load_key(CAkeyfile, CAkeyformat, - 0, passin, e, "CA Private Key"); - if (CApkey == NULL) - goto end; - } - - if (!x509_certify(ctx, CAfile, digest, x, xca, - CApkey, sigopts, - CAserial, CA_createserial, days, clrext, - extconf, extsect, sno, reqfile, preserve_dates)) - goto end; - } else if (x509req == i) { - EVP_PKEY *pk; - - BIO_printf(bio_err, "Getting request Private Key\n"); - if (keyfile == NULL) { - BIO_printf(bio_err, "no request key file specified\n"); - goto end; - } else { - pk = load_key(keyfile, keyformat, 0, - passin, e, "request key"); - if (pk == NULL) - goto end; - } - - BIO_printf(bio_err, "Generating certificate request\n"); - - rq = X509_to_X509_REQ(x, pk, digest); - EVP_PKEY_free(pk); - if (rq == NULL) { - ERR_print_errors(bio_err); - goto end; - } - if (!noout) { - X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT); - PEM_write_bio_X509_REQ(out, rq); - } - noout = 1; - } else if (ocspid == i) { - X509_ocspid_print(out, x); - } else if (ext == i) { - print_x509v3_exts(out, x, exts); + BIO_printf(out, "\n"); + } else if (i == print_pubkey) { + PEM_write_bio_PUBKEY(out, pkey); + } else if (i == text) { + X509_print_ex(out, x, get_nameopt(), certflag); + } else if (i == startdate) { + BIO_puts(out, "notBefore="); + ASN1_TIME_print_ex(out, X509_get0_notBefore(x), dateopt); + BIO_puts(out, "\n"); + } else if (i == enddate) { + BIO_puts(out, "notAfter="); + ASN1_TIME_print_ex(out, X509_get0_notAfter(x), dateopt); + BIO_puts(out, "\n"); + } else if (i == fingerprint) { + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + const char *fdigname = digest; + EVP_MD *fdig; + int digres; + + if (fdigname == NULL) + fdigname = "SHA1"; + + if ((fdig = EVP_MD_fetch(app_get0_libctx(), fdigname, + app_get0_propq())) == NULL) { + BIO_printf(bio_err, "Unknown digest\n"); + goto end; + } + digres = X509_digest(x, fdig, md, &n); + EVP_MD_free(fdig); + if (!digres) { + BIO_printf(bio_err, "Out of memory\n"); + goto end; } + + BIO_printf(out, "%s Fingerprint=", fdigname); + for (j = 0; j < (int)n; j++) + BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); + } else if (i == ocspid) { + X509_ocspid_print(out, x); + } else if (i == ext) { + print_x509v3_exts(out, x, ext_names); } } if (checkend) { time_t tcheck = time(NULL) + checkoffset; - if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) { + ret = X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0; + if (ret) BIO_printf(out, "Certificate will expire\n"); - ret = 1; - } else { + else BIO_printf(out, "Certificate will not expire\n"); - ret = 0; - } goto end; } @@ -880,33 +1052,36 @@ else i = PEM_write_bio_X509(out, x); } else { - BIO_printf(bio_err, "bad output format specified for outfile\n"); + BIO_printf(bio_err, "Bad output format specified for outfile\n"); goto end; } if (!i) { - BIO_printf(bio_err, "unable to write certificate\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Unable to write certificate\n"); goto end; } ret = 0; + end: + if (ret != 0) + ERR_print_errors(bio_err); NCONF_free(extconf); BIO_free_all(out); X509_STORE_free(ctx); + X509_NAME_free(fsubj); X509_REQ_free(req); X509_free(x); X509_free(xca); - EVP_PKEY_free(Upkey); - EVP_PKEY_free(CApkey); - EVP_PKEY_free(fkey); + EVP_PKEY_free(privkey); + EVP_PKEY_free(CAkey); + EVP_PKEY_free(pubkey); sk_OPENSSL_STRING_free(sigopts); + sk_OPENSSL_STRING_free(vfyopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); - ASN1_OBJECT_free(objtmp); release_engine(e); - OPENSSL_free(passin); + clear_free(passin); return ret; } @@ -934,7 +1109,7 @@ goto end; if (!BN_add_word(serial, 1)) { - BIO_printf(bio_err, "add_word failure\n"); + BIO_printf(bio_err, "Serial number increment failure\n"); goto end; } @@ -949,92 +1124,14 @@ return bs; } -static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, - X509 *x, X509 *xca, EVP_PKEY *pkey, - STACK_OF(OPENSSL_STRING) *sigopts, - const char *serialfile, int create, - int days, int clrext, CONF *conf, const char *section, - ASN1_INTEGER *sno, int reqfile, int preserve_dates) -{ - int ret = 0; - ASN1_INTEGER *bs = NULL; - X509_STORE_CTX *xsc = NULL; - EVP_PKEY *upkey; - - upkey = X509_get0_pubkey(xca); - if (upkey == NULL) { - BIO_printf(bio_err, "Error obtaining CA X509 public key\n"); - goto end; - } - EVP_PKEY_copy_parameters(upkey, pkey); - - xsc = X509_STORE_CTX_new(); - if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) { - BIO_printf(bio_err, "Error initialising X509 store\n"); - goto end; - } - if (sno) - bs = sno; - else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL) - goto end; - - /* - * NOTE: this certificate can/should be self signed, unless it was a - * certificate request in which case it is not. - */ - X509_STORE_CTX_set_cert(xsc, x); - X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); - if (!reqfile && X509_verify_cert(xsc) <= 0) - goto end; - - if (!X509_check_private_key(xca, pkey)) { - BIO_printf(bio_err, - "CA certificate and CA private key do not match\n"); - goto end; - } - - if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) - goto end; - if (!X509_set_serialNumber(x, bs)) - goto end; - - if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) - goto end; - - if (clrext) { - while (X509_get_ext_count(x) > 0) - X509_delete_ext(x, 0); - } - - if (conf != NULL) { - X509V3_CTX ctx2; - X509_set_version(x, 2); /* version 3 certificate */ - X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); - X509V3_set_nconf(&ctx2, conf); - if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) - goto end; - } - - if (!do_X509_sign(x, pkey, digest, sigopts)) - goto end; - ret = 1; - end: - X509_STORE_CTX_free(xsc); - if (!ret) - ERR_print_errors(bio_err); - if (!sno) - ASN1_INTEGER_free(bs); - return ret; -} - static int callb(int ok, X509_STORE_CTX *ctx) { int err; X509 *err_cert; /* - * it is ok to use a self signed certificate This case will catch both - * the initial ok == 0 and the final ok == 1 calls to this function + * It is ok to use a self-signed certificate. This case will catch both + * the initial ok == 0 and the final ok == 1 calls to this function. */ err = X509_STORE_CTX_get_error(ctx); if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) @@ -1047,51 +1144,19 @@ */ if (ok) { BIO_printf(bio_err, - "error with certificate to be certified - should be self signed\n"); + "Error with certificate to be certified - should be self-signed\n"); return 0; } else { err_cert = X509_STORE_CTX_get_current_cert(ctx); - print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); + print_name(bio_err, "subject=", X509_get_subject_name(err_cert)); BIO_printf(bio_err, - "error with certificate - error %d at depth %d\n%s\n", err, + "Error with certificate - error %d at depth %d\n%s\n", err, X509_STORE_CTX_get_error_depth(ctx), X509_verify_cert_error_string(err)); return 1; } } -/* self sign */ -static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, - const EVP_MD *digest, CONF *conf, const char *section, - int preserve_dates) -{ - - if (!X509_set_issuer_name(x, X509_get_subject_name(x))) - goto err; - if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) - goto err; - if (!X509_set_pubkey(x, pkey)) - goto err; - if (clrext) { - while (X509_get_ext_count(x) > 0) - X509_delete_ext(x, 0); - } - if (conf != NULL) { - X509V3_CTX ctx; - X509_set_version(x, 2); /* version 3 certificate */ - X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); - X509V3_set_nconf(&ctx, conf); - if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) - goto err; - } - if (!X509_sign(x, pkey, digest)) - goto err; - return 1; - err: - ERR_print_errors(bio_err); - return 0; -} - static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) { int id, i, idret; @@ -1150,7 +1215,7 @@ exts = X509_get0_extensions(x); if ((num = sk_X509_EXTENSION_num(exts)) <= 0) { - BIO_printf(bio, "No extensions in certificate\n"); + BIO_printf(bio_err, "No extensions in certificate\n"); ret = 1; goto end; } diff --git a/appveyor.yml b/appveyor.yml --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ image: - - Visual Studio 2017 + - Visual Studio 2017 platform: - x64 @@ -12,16 +12,23 @@ configuration: - shared - - plain - minimal +for: + - + branches: + only: + - master + configuration: + - shared + - plain + - minimal + before_build: - ps: >- Install-Module VSSetup -Scope CurrentUser - ps: >- Get-VSSetupInstance -All - - ps: >- - gci env:* | sort-object name - ps: >- If ($env:Platform -Match "x86") { $env:VCVARS_PLATFORM="x86" @@ -32,47 +39,44 @@ } - ps: >- If ($env:Configuration -Match "shared") { - $env:SHARED="no-makedepend" + $env:CONFIG_OPTS="enable-fips" } ElseIf ($env:Configuration -Match "minimal") { - $env:SHARED="no-shared no-dso no-makedepend no-aria no-async no-autoload-config no-blake2 no-bf no-camellia no-cast no-chacha no-cmac no-cms no-comp no-ct no-des no-dgram no-dh no-dsa no-dtls no-ec2m no-engine no-filenames no-gost no-idea no-mdc2 no-md4 no-multiblock no-nextprotoneg no-ocsp no-ocb no-poly1305 no-psk no-rc2 no-rc4 no-rmd160 no-seed no-siphash no-sm2 no-sm3 no-sm4 no-srp no-srtp no-ssl3 no-ssl3-method no-ts no-ui-console no-whirlpool no-asm -DOPENSSL_SMALL_FOOTPRINT" + $env:CONFIG_OPTS="no-bulk no-asm -DOPENSSL_SMALL_FOOTPRINT" } Else { - $env:SHARED="no-shared no-makedepend" + $env:CONFIG_OPTS="no-fips no-shared" } - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" %VCVARS_PLATFORM% - mkdir _build - cd _build - - perl ..\Configure %TARGET% %SHARED% + - perl ..\Configure %TARGET% no-makedepend %CONFIG_OPTS% - perl configdata.pm --dump - cd .. - ps: >- - if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER` - -or (&git log -1 $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT | - Select-String "\[extended tests\]") ) { - $env:EXTENDED_TESTS="yes" + If ($env:BUILDONLY -or $env:MAKEVERBOSE) { + $env:NMAKE="nmake" + } Else { + $env:NMAKE="nmake /S" } + - ps: >- + gci env:* | sort-object name build_script: - cd _build - - ps: >- - If ($env:Configuration -Match "shared" -or $env:EXTENDED_TESTS) { - cmd /c "nmake build_all_generated 2>&1" - cmd /c "nmake PERL=no-perl 2>&1" - } + - "%NMAKE% build_all_generated" + - "%NMAKE% PERL=no-perl" - cd .. test_script: - cd _build - ps: >- - If ($env:Configuration -Match "shared" -or $env:EXTENDED_TESTS) { - if ($env:EXTENDED_TESTS) { - cmd /c "nmake test V=1 2>&1" - } Else { - cmd /c "nmake test V=1 TESTS=-test_fuzz 2>&1" - } + if ($env:Configuration -Match "plain") { + cmd /c "%NMAKE% test VERBOSE_FAILURE=yes 2>&1" + } Else { + cmd /c "%NMAKE% test VERBOSE_FAILURE=yes TESTS=-test_fuzz 2>&1" } - ps: >- - if ($env:EXTENDED_TESTS) { + if ($env:Configuration -Match "shared") { mkdir ..\_install - cmd /c "nmake install DESTDIR=..\_install 2>&1" + cmd /c "%NMAKE% install DESTDIR=..\_install 2>&1" } - cd .. diff --git a/build.info b/build.info --- a/build.info +++ b/build.info @@ -1,13 +1,14 @@ -{- - our $sover = $config{shlib_version_number}; - our $sover_filename = $sover; - $sover_filename =~ s|\.|_|g - if $config{target} =~ /^mingw/ || $config{target} =~ /^VC-/; - $sover_filename = - sprintf "%02d%02d", split m|\.|, $config{shlib_version_number} - if $config{target} =~ /^vms/; - ""; --} +# Note that some of these directories are filtered in Configure. Look for +# %skipdir there for further explanations. + +SUBDIRS=crypto ssl apps util tools fuzz providers doc +IF[{- !$disabled{tests} -}] + SUBDIRS=test +ENDIF +IF[{- !$disabled{'deprecated-3.0'} -}] + SUBDIRS=engines +ENDIF + LIBS=libcrypto libssl INCLUDE[libcrypto]=. include INCLUDE[libssl]=. include @@ -15,89 +16,77 @@ # Empty DEPEND "indices" means the dependencies are expected to be built # unconditionally before anything else. -DEPEND[]=include/openssl/opensslconf.h include/crypto/bn_conf.h \ - include/crypto/dso_conf.h -DEPEND[include/openssl/opensslconf.h]=configdata.pm -GENERATE[include/openssl/opensslconf.h]=include/openssl/opensslconf.h.in -DEPEND[include/crypto/bn_conf.h]=configdata.pm +DEPEND[]=include/openssl/asn1.h \ + include/openssl/asn1t.h \ + include/openssl/bio.h \ + include/openssl/cmp.h \ + include/openssl/cms.h \ + include/openssl/conf.h \ + include/openssl/crmf.h \ + include/openssl/crypto.h \ + include/openssl/ct.h \ + include/openssl/err.h \ + include/openssl/ess.h \ + include/openssl/fipskey.h \ + include/openssl/lhash.h \ + include/openssl/opensslv.h \ + include/openssl/ocsp.h \ + include/openssl/pkcs12.h \ + include/openssl/pkcs7.h \ + include/openssl/safestack.h \ + include/openssl/srp.h \ + include/openssl/ssl.h \ + include/openssl/ui.h \ + include/openssl/x509.h \ + include/openssl/x509v3.h \ + include/openssl/x509_vfy.h \ + include/crypto/bn_conf.h include/crypto/dso_conf.h + +GENERATE[include/openssl/asn1.h]=include/openssl/asn1.h.in +GENERATE[include/openssl/asn1t.h]=include/openssl/asn1t.h.in +GENERATE[include/openssl/bio.h]=include/openssl/bio.h.in +GENERATE[include/openssl/cmp.h]=include/openssl/cmp.h.in +GENERATE[include/openssl/cms.h]=include/openssl/cms.h.in +GENERATE[include/openssl/conf.h]=include/openssl/conf.h.in +# include/openssl/configuration.h is generated by configdata.pm +# We still need this information for the FIPS module checksum, but the attribute +# 'skip' ensures that nothing is actually done with it. +GENERATE[include/openssl/configuration.h]{skip}=include/openssl/configuration.h.in +GENERATE[include/openssl/crmf.h]=include/openssl/crmf.h.in +GENERATE[include/openssl/crypto.h]=include/openssl/crypto.h.in +GENERATE[include/openssl/ct.h]=include/openssl/ct.h.in +GENERATE[include/openssl/err.h]=include/openssl/err.h.in +GENERATE[include/openssl/ess.h]=include/openssl/ess.h.in +GENERATE[include/openssl/fipskey.h]=include/openssl/fipskey.h.in +GENERATE[include/openssl/lhash.h]=include/openssl/lhash.h.in +GENERATE[include/openssl/ocsp.h]=include/openssl/ocsp.h.in +GENERATE[include/openssl/opensslv.h]=include/openssl/opensslv.h.in +GENERATE[include/openssl/pkcs12.h]=include/openssl/pkcs12.h.in +GENERATE[include/openssl/pkcs7.h]=include/openssl/pkcs7.h.in +GENERATE[include/openssl/safestack.h]=include/openssl/safestack.h.in +GENERATE[include/openssl/srp.h]=include/openssl/srp.h.in +GENERATE[include/openssl/ssl.h]=include/openssl/ssl.h.in +GENERATE[include/openssl/ui.h]=include/openssl/ui.h.in +GENERATE[include/openssl/x509.h]=include/openssl/x509.h.in +GENERATE[include/openssl/x509v3.h]=include/openssl/x509v3.h.in +GENERATE[include/openssl/x509_vfy.h]=include/openssl/x509_vfy.h.in GENERATE[include/crypto/bn_conf.h]=include/crypto/bn_conf.h.in -DEPEND[include/crypto/dso_conf.h]=configdata.pm GENERATE[include/crypto/dso_conf.h]=include/crypto/dso_conf.h.in IF[{- defined $target{shared_defflag} -}] - IF[{- $config{target} =~ /^mingw/ -}] - GENERATE[libcrypto.def]=util/mkdef.pl crypto 32 - DEPEND[libcrypto.def]=util/libcrypto.num - GENERATE[libssl.def]=util/mkdef.pl ssl 32 - DEPEND[libssl.def]=util/libssl.num - - SHARED_SOURCE[libcrypto]=libcrypto.def - SHARED_SOURCE[libssl]=libssl.def - ELSIF[{- $config{target} =~ /^aix/ -}] - GENERATE[libcrypto.map]=util/mkdef.pl crypto aix - DEPEND[libcrypto.map]=util/libcrypto.num - GENERATE[libssl.map]=util/mkdef.pl ssl aix - DEPEND[libssl.map]=util/libssl.num - - SHARED_SOURCE[libcrypto]=libcrypto.map - SHARED_SOURCE[libssl]=libssl.map - ELSE - GENERATE[libcrypto.map]=util/mkdef.pl crypto linux - DEPEND[libcrypto.map]=util/libcrypto.num - GENERATE[libssl.map]=util/mkdef.pl ssl linux - DEPEND[libssl.map]=util/libssl.num + SHARED_SOURCE[libcrypto]=libcrypto.ld + SHARED_SOURCE[libssl]=libssl.ld - SHARED_SOURCE[libcrypto]=libcrypto.map - SHARED_SOURCE[libssl]=libssl.map - ENDIF + GENERATE[libcrypto.ld]=util/libcrypto.num libcrypto + GENERATE[libssl.ld]=util/libssl.num libssl + DEPEND[libcrypto.ld libssl.ld]=configdata.pm util/perl/OpenSSL/Ordinals.pm ENDIF -# VMS and VC don't have parametrised .def / .symvec generation, so they get -# special treatment, since we know they do use these files -IF[{- $config{target} =~ /^VC-/ -}] - GENERATE[libcrypto.def]=util/mkdef.pl crypto 32 - DEPEND[libcrypto.def]=util/libcrypto.num - GENERATE[libssl.def]=util/mkdef.pl ssl 32 - DEPEND[libssl.def]=util/libssl.num - SHARED_SOURCE[libcrypto]=libcrypto.def - SHARED_SOURCE[libssl]=libssl.def -ELSIF[{- $config{target} =~ /^vms/ -}] - GENERATE[libcrypto.opt]=util/mkdef.pl crypto "VMS" - DEPEND[libcrypto.opt]=util/libcrypto.num - GENERATE[libssl.opt]=util/mkdef.pl ssl "VMS" - DEPEND[libssl.opt]=util/libssl.num - - SHARED_SOURCE[libcrypto]=libcrypto.opt - SHARED_SOURCE[libssl]=libssl.opt -ENDIF - -IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}] +IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] GENERATE[libcrypto.rc]=util/mkrc.pl libcrypto GENERATE[libssl.rc]=util/mkrc.pl libssl + DEPEND[libcrypto.rc libssl.rc]=configdata.pm SHARED_SOURCE[libcrypto]=libcrypto.rc SHARED_SOURCE[libssl]=libssl.rc ENDIF - -IF[{- $config{target} =~ /^Cygwin/ -}] - SHARED_NAME[libcrypto]=cygcrypto-{- $sover_filename -} - SHARED_NAME[libssl]=cygssl-{- $sover_filename -} -ELSIF[{- $config{target} =~ /^mingw/ -}] - SHARED_NAME[libcrypto]=libcrypto-{- $sover_filename -}{- $config{target} eq "mingw64" ? "-x64" : "" -} - SHARED_NAME[libssl]=libssl-{- $sover_filename -}{- $config{target} eq "mingw64" ? "-x64" : "" -} -ELSIF[{- $config{target} =~ /^VC-/ -}] - SHARED_NAME[libcrypto]=libcrypto-{- $sover_filename -}{- $target{multilib} -} - SHARED_NAME[libssl]=libssl-{- $sover_filename -}{- $target{multilib} -} -ENDIF - -# VMS has a cultural standard where all libraries are prefixed. -# For OpenSSL, the choice is 'ossl$' (this prefix was claimed in a -# conversation with VSI, Tuesday January 26 2016) -# Also, it seems it's usual to have the pointer size the libraries -# were built for as part of the name. -IF[{- $config{target} =~ /^vms/ -}] - RENAME[libcrypto]=ossl$libcrypto{- $target{pointer_size} -} - RENAME[libssl]=ossl$libssl{- $target{pointer_size} -} - SHARED_NAME[libcrypto]=ossl$libcrypto{- $sover_filename -}_shr{- $target{pointer_size} -} - SHARED_NAME[libssl]=ossl$libssl{- $sover_filename -}_shr{- $target{pointer_size} -} -ENDIF diff --git a/config b/config --- a/config +++ b/config @@ -1,946 +1,10 @@ -#!/bin/sh -# Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. +#! /bin/sh +# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html -# OpenSSL config: determine the operating system and run ./Configure -# Derived from minarch and GuessOS from Apache. -# -# Do "config -h" for usage information. -SUFFIX="" -DRYRUN="false" -VERBOSE="false" -EXE="" THERE=`dirname $0` - -# pick up any command line args to config -for i -do -case "$i" in --d*) options=$options" --debug";; --t*) DRYRUN="true" VERBOSE="true";; --v*) VERBOSE="true";; --h*) DRYRUN="true"; cat </dev/null` || MACHINE="unknown" -[ "$RELEASE" ] || RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown" -[ "$SYSTEM" ] || SYSTEM=`(uname -s) 2>/dev/null` || SYSTEM="unknown" -[ "$BUILD" ] || VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown" - - -# Now test for ISC and SCO, since it is has a braindamaged uname. -# -# We need to work around FreeBSD 1.1.5.1 -( -XREL=`uname -X 2>/dev/null | grep "^Release" | awk '{print $3}'` -if [ "x$XREL" != "x" ]; then - if [ -f /etc/kconfig ]; then - case "$XREL" in - 4.0|4.1) - echo "${MACHINE}-whatever-isc4"; exit 0 - ;; - esac - else - case "$XREL" in - 3.2v4.2) - echo "whatever-whatever-sco3"; exit 0 - ;; - 3.2v5.0*) - echo "whatever-whatever-sco5"; exit 0 - ;; - 4.2MP) - case "x${VERSION}" in - x2.0*) echo "whatever-whatever-unixware20"; exit 0 ;; - x2.1*) echo "whatever-whatever-unixware21"; exit 0 ;; - x2*) echo "whatever-whatever-unixware2"; exit 0 ;; - esac - ;; - 4.2) - echo "whatever-whatever-unixware1"; exit 0 - ;; - 5*) - case "x${VERSION}" in - # We hardcode i586 in place of ${MACHINE} for the - # following reason. The catch is that even though Pentium - # is minimum requirement for platforms in question, - # ${MACHINE} gets always assigned to i386. Now, problem - # with i386 is that it makes ./config pass 386 to - # ./Configure, which in turn makes make generate - # inefficient SHA-1 (for this moment) code. - x[678]*) echo "i586-sco-unixware7"; exit 0 ;; - esac - ;; - esac - fi -fi -# Now we simply scan though... In most cases, the SYSTEM info is enough -# -case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in - A/UX:*) - echo "m68k-apple-aux3"; exit 0 - ;; - - AIX:[3-9]:4:*) - echo "${MACHINE}-ibm-aix"; exit 0 - ;; - - AIX:*:[5-9]:*) - echo "${MACHINE}-ibm-aix"; exit 0 - ;; - - AIX:*) - echo "${MACHINE}-ibm-aix3"; exit 0 - ;; - - HI-UX:*) - echo "${MACHINE}-hi-hiux"; exit 0 - ;; - - HP-UX:*) - HPUXVER=`echo ${RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "$HPUXVER" in - 1[0-9].*) # HPUX 10 and 11 targets are unified - echo "${MACHINE}-hp-hpux1x"; exit 0 - ;; - *) - echo "${MACHINE}-hp-hpux"; exit 0 - ;; - esac - ;; - - IRIX:6.*) - echo "mips3-sgi-irix"; exit 0 - ;; - - IRIX64:*) - echo "mips4-sgi-irix64"; exit 0 - ;; - - Linux:[2-9].*) - echo "${MACHINE}-whatever-linux2"; exit 0 - ;; - - Linux:1.*) - echo "${MACHINE}-whatever-linux1"; exit 0 - ;; - - GNU*) - echo "hurd-x86"; exit 0; - ;; - - LynxOS:*) - echo "${MACHINE}-lynx-lynxos"; exit 0 - ;; - - BSD/OS:4.*) # BSD/OS always says 386 - echo "i486-whatever-bsdi4"; exit 0 - ;; - - BSD/386:*:*:*486*|BSD/OS:*:*:*:*486*) - case `/sbin/sysctl -n hw.model` in - Pentium*) - echo "i586-whatever-bsdi"; exit 0 - ;; - *) - echo "i386-whatever-bsdi"; exit 0 - ;; - esac; - ;; - - BSD/386:*|BSD/OS:*) - echo "${MACHINE}-whatever-bsdi"; exit 0 - ;; - - FreeBSD:*:*:*386*) - VERS=`echo ${RELEASE} | sed -e 's/[-(].*//'` - MACH=`sysctl -n hw.model` - ARCH='whatever' - case ${MACH} in - *386* ) MACH="i386" ;; - *486* ) MACH="i486" ;; - Pentium\ II*) MACH="i686" ;; - Pentium* ) MACH="i586" ;; - * ) MACH="$MACHINE" ;; - esac - case ${MACH} in - i[0-9]86 ) ARCH="pc" ;; - esac - echo "${MACH}-${ARCH}-freebsd${VERS}"; exit 0 - ;; - - DragonFly:*) - echo "${MACHINE}-whatever-dragonfly"; exit 0 - ;; - - FreeBSD:*) - echo "${MACHINE}-whatever-freebsd"; exit 0 - ;; - - Haiku:*) - echo "${MACHINE}-whatever-haiku"; exit 0 - ;; - - NetBSD:*:*:*386*) - echo "`(/usr/sbin/sysctl -n hw.model || /sbin/sysctl -n hw.model) | sed 's,.*\(.\)86-class.*,i\186,'`-whatever-netbsd"; exit 0 - ;; - - NetBSD:*) - echo "${MACHINE}-whatever-netbsd"; exit 0 - ;; - - OpenBSD:*) - echo "${MACHINE}-whatever-openbsd"; exit 0 - ;; - - OpenUNIX:*) - echo "${MACHINE}-unknown-OpenUNIX${VERSION}"; exit 0 - ;; - - OSF1:*:*:*alpha*) - OSFMAJOR=`echo ${RELEASE}| sed -e 's/^V\([0-9]*\)\..*$/\1/'` - case "$OSFMAJOR" in - 4|5) - echo "${MACHINE}-dec-tru64"; exit 0 - ;; - 1|2|3) - echo "${MACHINE}-dec-osf"; exit 0 - ;; - *) - echo "${MACHINE}-dec-osf"; exit 0 - ;; - esac - ;; - - Paragon*:*:*:*) - echo "i860-intel-osf1"; exit 0 - ;; - - Rhapsody:*) - echo "ppc-apple-rhapsody"; exit 0 - ;; - - Darwin:*) - case "$MACHINE" in - Power*) - echo "ppc-apple-darwin${VERSION}" - ;; - *) - echo "${MACHINE}-apple-darwin${VERSION}" - ;; - esac - exit 0 - ;; - - SunOS:5.*) - echo "${MACHINE}-whatever-solaris2"; exit 0 - ;; - - SunOS:*) - echo "${MACHINE}-sun-sunos4"; exit 0 - ;; - - UNIX_System_V:4.*:*) - echo "${MACHINE}-whatever-sysv4"; exit 0 - ;; - - VOS:*:*:i786) - echo "i386-stratus-vos"; exit 0 - ;; - - VOS:*:*:*) - echo "hppa1.1-stratus-vos"; exit 0 - ;; - - *:4*:R4*:m88k) - echo "${MACHINE}-whatever-sysv4"; exit 0 - ;; - - DYNIX/ptx:4*:*) - echo "${MACHINE}-whatever-sysv4"; exit 0 - ;; - - *:4.0:3.0:3[34]?? | *:4.0:3.0:3[34]??,*) - echo "i486-ncr-sysv4"; exit 0 - ;; - - ULTRIX:*) - echo "${MACHINE}-unknown-ultrix"; exit 0 - ;; - - POSIX-BC*) - echo "${MACHINE}-siemens-sysv4"; exit 0 # Here, $MACHINE == "BS2000" - ;; - - machten:*) - echo "${MACHINE}-tenon-${SYSTEM}"; exit 0; - ;; - - library:*) - echo "${MACHINE}-ncr-sysv4"; exit 0 - ;; - - ConvexOS:*:11.0:*) - echo "${MACHINE}-v11-${SYSTEM}"; exit 0; - ;; - - # The following combinations are supported - # MINGW64* on x86_64 => mingw64 - # MINGW32* on x86_64 => mingw - # MINGW32* on i?86 => mingw - # - # MINGW64* on i?86 isn't expected to work... - MINGW64*:*:*:x86_64) - echo "${MACHINE}-whatever-mingw64"; exit 0; - ;; - MINGW*) - echo "${MACHINE}-whatever-mingw"; exit 0; - ;; - CYGWIN*) - echo "${MACHINE}-pc-cygwin"; exit 0 - ;; - - vxworks*) - echo "${MACHINE}-whatever-vxworks"; exit 0; - ;; -esac - -# -# Ugg. These are all we can determine by what we know about -# the output of uname. Be more creative: -# - -# Do the Apollo stuff first. Here, we just simply assume -# that the existence of the /usr/apollo directory is proof -# enough -if [ -d /usr/apollo ]; then - echo "whatever-apollo-whatever" - exit 0 -fi - -# Now NeXT -ISNEXT=`hostinfo 2>/dev/null` -case "$ISNEXT" in - *'NeXT Mach 3.3'*) - echo "whatever-next-nextstep3.3"; exit 0 - ;; - *NeXT*) - echo "whatever-next-nextstep"; exit 0 - ;; -esac - -# At this point we gone through all the one's -# we know of: Punt - -echo "${MACHINE}-whatever-${SYSTEM}" -exit 0 -) 2>/dev/null | ( - -# --------------------------------------------------------------------------- -# this is where the translation occurs into SSLeay terms -# --------------------------------------------------------------------------- - -# Only set CC if not supplied already -if [ -z "$CROSS_COMPILE$CC" ]; then - GCCVER=`sh -c "gcc -dumpversion" 2>/dev/null` - if [ "$GCCVER" != "" ]; then - # then strip off whatever prefix egcs prepends the number with... - # Hopefully, this will work for any future prefixes as well. - GCCVER=`echo $GCCVER | LC_ALL=C sed 's/^[a-zA-Z]*\-//'` - # Since gcc 3.1 gcc --version behaviour has changed. gcc -dumpversion - # does give us what we want though, so we use that. We just just the - # major and minor version numbers. - # peak single digit before and after first dot, e.g. 2.95.1 gives 29 - GCCVER=`echo $GCCVER | sed 's/\([0-9]\)\.\([0-9]\).*/\1\2/'` - CC=gcc - else - CC=cc - fi -fi -GCCVER=${GCCVER:-0} -if [ "$SYSTEM" = "HP-UX" ];then - # By default gcc is a ILP32 compiler (with long long == 64). - GCC_BITS="32" - if [ $GCCVER -ge 30 ]; then - # PA64 support only came in with gcc 3.0.x. - # We check if the preprocessor symbol __LP64__ is defined... - if echo "__LP64__" | gcc -v -E -x c - 2>/dev/null | grep "^__LP64__" 2>&1 > /dev/null; then - : # __LP64__ has slipped through, it therefore is not defined - else - GCC_BITS="64" - fi - fi -fi -if [ "$SYSTEM" = "SunOS" ]; then - if [ $GCCVER -ge 30 ]; then - # 64-bit ABI isn't officially supported in gcc 3.0, but it appears - # to be working, at the very least 'make test' passes... - if gcc -v -E -x c /dev/null 2>&1 | grep __arch64__ > /dev/null; then - GCC_ARCH="-m64" - else - GCC_ARCH="-m32" - fi - fi - # check for WorkShop C, expected output is "cc: blah-blah C x.x" - CCVER=`(cc -V 2>&1) 2>/dev/null | \ - egrep -e '^cc: .* C [0-9]\.[0-9]' | \ - sed 's/.* C \([0-9]\)\.\([0-9]\).*/\1\2/'` - CCVER=${CCVER:-0} - if [ $MACHINE != i86pc -a $CCVER -gt 40 ]; then - CC=cc # overrides gcc!!! - if [ $CCVER -eq 50 ]; then - echo "WARNING! Detected WorkShop C 5.0. Do make sure you have" - echo " patch #107357-01 or later applied." - sleep 5 - fi - fi -fi - -if [ "${SYSTEM}" = "AIX" ]; then # favor vendor cc over gcc - (cc) 2>&1 | grep -iv "not found" > /dev/null && CC=cc -fi - -CCVER=${CCVER:-0} - -# read the output of the embedded GuessOS -read GUESSOS - -echo Operating system: $GUESSOS - -# now map the output into SSLeay terms ... really should hack into the -# script above so we end up with values in vars but that would take -# more time that I want to waste at the moment -case "$GUESSOS" in - uClinux*64*) - OUT=uClinux-dist64 - ;; - uClinux*) - OUT=uClinux-dist - ;; - mips3-sgi-irix) - OUT="irix-mips3-$CC" - ;; - mips4-sgi-irix64) - echo "WARNING! If you wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure irix64-mips4-$CC' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - OUT="irix-mips3-$CC" - ;; - ppc-apple-rhapsody) OUT="rhapsody-ppc-cc" ;; - ppc-apple-darwin*) - ISA64=`(sysctl -n hw.optional.64bitops) 2>/dev/null` - if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then - echo "WARNING! If you wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure darwin64-ppc-cc' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - fi - if [ "$ISA64" = "1" -a "$KERNEL_BITS" = "64" ]; then - OUT="darwin64-ppc-cc" - else - OUT="darwin-ppc-cc" - fi ;; - i?86-apple-darwin*) - ISA64=`(sysctl -n hw.optional.x86_64) 2>/dev/null` - if [ "$ISA64" = "1" -a -z "$KERNEL_BITS" ]; then - echo "WARNING! If you wish to build 64-bit library, then you have to" - echo " invoke 'KERNEL_BITS=64 $THERE/config $options'." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 1" 2; stty -icanon min 0 time 50; read waste; exit 0) <&1 || exit - fi - fi - if [ "$ISA64" = "1" -a "$KERNEL_BITS" = "64" ]; then - OUT="darwin64-x86_64-cc" - else - OUT="darwin-i386-cc" - fi ;; - x86_64-apple-darwin*) - if [ "$KERNEL_BITS" = "32" ]; then - OUT="darwin-i386-cc" - else - OUT="darwin64-x86_64-cc" - fi ;; - $MACHINE-apple-darwin*) - OUT="darwin64-$MACHINE-cc" - ;; - armv6+7-*-iphoneos) - __CNF_CFLAGS="$__CNF_CFLAGS -arch armv6 -arch armv7" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch armv6 -arch armv7" - OUT="iphoneos-cross" ;; - *-*-iphoneos) - __CNF_CFLAGS="$__CNF_CFLAGS -arch ${MACHINE}" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch ${MACHINE}" - OUT="iphoneos-cross" ;; - arm64-*-iphoneos|*-*-ios64) - OUT="ios64-cross" ;; - alpha-*-linux2) - ISA=`awk '/cpu model/{print$4;exit(0);}' /proc/cpuinfo` - OUT="linux-alpha-$CC" - if [ "$CC" = "gcc" ]; then - case ${ISA:-generic} in - EV5|EV45) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev5" - __CNF_CXXFLAGS="$__CNF_CFLAGS -mcpu=ev5";; - EV56|PCA56) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev56" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mcpu=ev56";; - *) __CNF_CFLAGS="$__CNF_CFLAGS -mcpu=ev6" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mcpu=ev6";; - esac - fi - ;; - ppc64-*-linux2) - if [ -z "$KERNEL_BITS" ]; then - echo "WARNING! If you wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure linux-ppc64' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - fi - if [ "$KERNEL_BITS" = "64" ]; then - OUT="linux-ppc64" - else - OUT="linux-ppc" - if (echo "__LP64__" | gcc -E -x c - 2>/dev/null | grep "^__LP64__" 2>&1 > /dev/null); then - :; - else - __CNF_CFLAGS="$__CNF_CFLAGS -m32" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -m32" - fi - fi - ;; - ppc64le-*-linux2) OUT="linux-ppc64le" ;; - ppc-*-linux2) OUT="linux-ppc" ;; - mips64*-*-linux2) - echo "WARNING! If you wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure linux64-mips64' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - OUT="linux-mips64" - ;; - mips*-*-linux2) OUT="linux-mips32" ;; - ppc60x-*-vxworks*) OUT="vxworks-ppc60x" ;; - ppcgen-*-vxworks*) OUT="vxworks-ppcgen" ;; - pentium-*-vxworks*) OUT="vxworks-pentium" ;; - simlinux-*-vxworks*) OUT="vxworks-simlinux" ;; - mips-*-vxworks*) OUT="vxworks-mips";; - ia64-*-linux?) OUT="linux-ia64" ;; - sparc64-*-linux2) - echo "WARNING! If you *know* that your GNU C supports 64-bit/V9 ABI" - echo " and wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure linux64-sparcv9' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - OUT="linux-sparcv9" ;; - sparc-*-linux2) - KARCH=`awk '/^type/{print$3;exit(0);}' /proc/cpuinfo` - case ${KARCH:-sun4} in - sun4u*) OUT="linux-sparcv9" ;; - sun4m) OUT="linux-sparcv8" ;; - sun4d) OUT="linux-sparcv8" ;; - *) OUT="linux-generic32"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; - esac ;; - parisc*-*-linux2) - # 64-bit builds under parisc64 linux are not supported and - # compiler is expected to generate 32-bit objects... - CPUARCH=`awk '/cpu family/{print substr($5,1,3); exit(0);}' /proc/cpuinfo` - CPUSCHEDULE=`awk '/^cpu.[ ]*: PA/{print substr($3,3); exit(0);}' /proc/cpuinfo` - - # ??TODO ?? Model transformations - # 0. CPU Architecture for the 1.1 processor has letter suffixes. We strip that off - # assuming no further arch. identification will ever be used by GCC. - # 1. I'm most concerned about whether is a 7300LC is closer to a 7100 versus a 7100LC. - # 2. The variant 64-bit processors cause concern should GCC support explicit schedulers - # for these chips in the future. - # PA7300LC -> 7100LC (1.1) - # PA8200 -> 8000 (2.0) - # PA8500 -> 8000 (2.0) - # PA8600 -> 8000 (2.0) - - CPUSCHEDULE=`echo $CPUSCHEDULE|sed -e 's/7300LC/7100LC/' -e 's/8.00/8000/'` - # Finish Model transformations - - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" - __CNF_CFLAGS="$__CNF_CFLAGS -mschedule=$CPUSCHEDULE -march=$CPUARCH" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -mschedule=$CPUSCHEDULE -march=$CPUARCH" - OUT="linux-generic32" ;; - armv[1-3]*-*-linux2) OUT="linux-generic32" ;; - armv[7-9]*-*-linux2) OUT="linux-armv4" - __CNF_CFLAGS="$__CNF_CFLAGS -march=armv7-a" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -march=armv7-a" - ;; - arm*-*-linux2) OUT="linux-armv4" ;; - aarch64-*-linux2) OUT="linux-aarch64" ;; - sh*b-*-linux2) OUT="linux-generic32"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; - sh*-*-linux2) OUT="linux-generic32"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DL_ENDIAN" ;; - m68k*-*-linux2) OUT="linux-generic32"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; - s390-*-linux2) OUT="linux-generic32"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; - s390x-*-linux2) - # To be uncommented when glibc bug is fixed, see Configure... - #if egrep -e '^features.* highgprs' /proc/cpuinfo >/dev/null ; then - # echo "WARNING! If you wish to build \"highgprs\" 32-bit library, then you" - # echo " have to invoke './Configure linux32-s390x' *manually*." - # if [ "$DRYRUN" = "false" -a -t -1 ]; then - # echo " You have about 5 seconds to press Ctrl-C to abort." - # (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - # fi - #fi - OUT="linux64-s390x" - ;; - x86_64-*-linux?) - if $CC -dM -E -x c /dev/null 2>&1 | grep -q ILP32 > /dev/null; then - OUT="linux-x32" - else - OUT="linux-x86_64" - fi ;; - *86-*-linux2) - # On machines where the compiler understands -m32, prefer a - # config target that uses it - if $CC -m32 -E -x c /dev/null > /dev/null 2>&1; then - OUT="linux-x86" - else - OUT="linux-elf" - fi ;; - *86-*-linux1) OUT="linux-aout" ;; - *-*-linux?) OUT="linux-generic32" ;; - sun4[uv]*-*-solaris2) - OUT="solaris-sparcv9-$CC" - ISA64=`(isainfo) 2>/dev/null | grep sparcv9` - if [ "$ISA64" != "" -a "$KERNEL_BITS" = "" ]; then - if [ "$CC" = "cc" -a $CCVER -ge 50 ]; then - echo "WARNING! If you wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure solaris64-sparcv9-cc' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - elif [ "$CC" = "gcc" -a "$GCC_ARCH" = "-m64" ]; then - # $GCC_ARCH denotes default ABI chosen by compiler driver - # (first one found on the $PATH). I assume that user - # expects certain consistency with the rest of his builds - # and therefore switch over to 64-bit. - OUT="solaris64-sparcv9-gcc" - echo "WARNING! If you wish to build 32-bit library, then you have to" - echo " invoke '$THERE/Configure solaris-sparcv9-gcc' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - elif [ "$GCC_ARCH" = "-m32" ]; then - echo "NOTICE! If you *know* that your GNU C supports 64-bit/V9 ABI" - echo " and wish to build 64-bit library, then you have to" - echo " invoke '$THERE/Configure solaris64-sparcv9-gcc' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - fi - fi - if [ "$ISA64" != "" -a "$KERNEL_BITS" = "64" ]; then - OUT="solaris64-sparcv9-$CC" - fi - ;; - sun4m-*-solaris2) OUT="solaris-sparcv8-$CC" ;; - sun4d-*-solaris2) OUT="solaris-sparcv8-$CC" ;; - sun4*-*-solaris2) OUT="solaris-sparcv7-$CC" ;; - *86*-*-solaris2) - ISA64=`(isainfo) 2>/dev/null | grep amd64` - if [ "$ISA64" != "" -a ${KERNEL_BITS:-64} -eq 64 ]; then - OUT="solaris64-x86_64-$CC" - else - OUT="solaris-x86-$CC" - if [ `uname -r | sed -e 's/5\.//'` -lt 10 ]; then - options="$options no-sse2" - fi - fi - ;; - *-*-sunos4) OUT="sunos-$CC" ;; - - *86*-*-bsdi4) OUT="BSD-x86-elf"; options="$options no-sse2"; - __CNF_LDFLAGS="$__CNF_LDFLAGS -ldl" ;; - alpha*-*-*bsd*) OUT="BSD-generic64"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DL_ENDIAN" ;; - powerpc64-*-*bsd*) OUT="BSD-generic64"; - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DB_ENDIAN" ;; - riscv64-*-*bsd*) OUT="BSD-riscv64" ;; - sparc64-*-*bsd*) OUT="BSD-sparc64" ;; - ia64-*-*bsd*) OUT="BSD-ia64" ;; - x86_64-*-dragonfly*) OUT="BSD-x86_64" ;; - amd64-*-*bsd*) OUT="BSD-x86_64" ;; - arm64-*-*bsd*) OUT="BSD-aarch64" ;; - *86*-*-*bsd*) # mimic ld behaviour when it's looking for libc... - if [ -L /usr/lib/libc.so ]; then # [Free|Net]BSD - libc=/usr/lib/libc.so - else # OpenBSD - # ld searches for highest libc.so.* and so do we - libc=`(ls /usr/lib/libc.so.* /lib/libc.so.* | tail -1) 2>/dev/null` - fi - case "`(file -L $libc) 2>/dev/null`" in - *ELF*) OUT="BSD-x86-elf" ;; - *) OUT="BSD-x86"; options="$options no-sse2" ;; - esac ;; - *-*-*bsd*) OUT="BSD-generic32" ;; - - x86_64-*-haiku) OUT="haiku-x86_64" ;; - *-*-haiku) OUT="haiku-x86" ;; - - *-*-osf) OUT="osf1-alpha-cc" ;; - *-*-tru64) OUT="tru64-alpha-cc" ;; - *-*-[Uu]nix[Ww]are7) - if [ "$CC" = "gcc" ]; then - OUT="unixware-7-gcc" ; options="$options no-sse2" - else - OUT="unixware-7" ; options="$options no-sse2" - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -D__i386__" - fi - ;; - *-*-[Uu]nix[Ww]are20*) OUT="unixware-2.0"; options="$options no-sse2 no-sha512" ;; - *-*-[Uu]nix[Ww]are21*) OUT="unixware-2.1"; options="$options no-sse2 no-sha512" ;; - *-*-vos) - options="$options no-threads no-shared no-asm no-dso" - EXE=".pm" - OUT="vos-$CC" ;; - BS2000-siemens-sysv4) OUT="BS2000-OSD" ;; - *-hpux1*) - if [ $CC = "gcc" -a $GCC_BITS = "64" ]; then - OUT="hpux64-parisc2-gcc" - fi - [ "$KERNEL_BITS" ] || KERNEL_BITS=`(getconf KERNEL_BITS) 2>/dev/null` - KERNEL_BITS=${KERNEL_BITS:-32} - CPU_VERSION=`(getconf CPU_VERSION) 2>/dev/null` - CPU_VERSION=${CPU_VERSION:-0} - # See for further info on CPU_VERSION. - if [ $CPU_VERSION -ge 768 ]; then # IA-64 CPU - if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then - OUT="hpux64-ia64-cc" - else - OUT="hpux-ia64-cc" - fi - elif [ $CPU_VERSION -ge 532 ]; then # PA-RISC 2.x CPU - # PA-RISC 2.0 is no longer supported as separate 32-bit - # target. This is compensated for by run-time detection - # in most critical assembly modules and taking advantage - # of 2.0 architecture in PA-RISC 1.1 build. - OUT=${OUT:-"hpux-parisc1_1-${CC}"} - if [ $KERNEL_BITS -eq 64 -a "$CC" = "cc" ]; then - echo "WARNING! If you wish to build 64-bit library then you have to" - echo " invoke '$THERE/Configure hpux64-parisc2-cc' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have about 5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - fi - elif [ $CPU_VERSION -ge 528 ]; then # PA-RISC 1.1+ CPU - OUT="hpux-parisc1_1-${CC}" - elif [ $CPU_VERSION -ge 523 ]; then # PA-RISC 1.0 CPU - OUT="hpux-parisc-${CC}" - else # Motorola(?) CPU - OUT="hpux-$CC" - fi - __CNF_CPPFLAGS="$__CNF_CPPFLAGS -D_REENTRANT" ;; - *-hpux) OUT="hpux-parisc-$CC" ;; - *-aix) - [ "$KERNEL_BITS" ] || KERNEL_BITS=`(getconf KERNEL_BITMODE) 2>/dev/null` - KERNEL_BITS=${KERNEL_BITS:-32} - OBJECT_MODE=${OBJECT_MODE:-32} - if [ "$CC" = "gcc" ]; then - OUT="aix-gcc" - if [ $OBJECT_MODE -eq 64 ]; then - echo 'Your $OBJECT_MODE was found to be set to 64' - OUT="aix64-gcc" - fi - elif [ $OBJECT_MODE -eq 64 ]; then - echo 'Your $OBJECT_MODE was found to be set to 64' - OUT="aix64-cc" - else - OUT="aix-cc" - if [ $KERNEL_BITS -eq 64 ]; then - echo "WARNING! If you wish to build 64-bit kit, then you have to" - echo " invoke '$THERE/Configure aix64-cc' *manually*." - if [ "$DRYRUN" = "false" -a -t 1 ]; then - echo " You have ~5 seconds to press Ctrl-C to abort." - (trap "stty `stty -g`; exit 0" 2 0; stty -icanon min 0 time 50; read waste) <&1 - fi - fi - fi - if (lsattr -E -O -l `lsdev -c processor|awk '{print$1;exit}'` | grep -i powerpc) >/dev/null 2>&1; then - : # this applies even to Power3 and later, as they return PowerPC_POWER[345] - else - options="$options no-asm" - fi - ;; - # these are all covered by the catchall below - i[3456]86-*-cygwin) OUT="Cygwin-x86" ;; - *-*-cygwin) OUT="Cygwin-${MACHINE}" ;; - x86-*-android|i?86-*-android) OUT="android-x86" ;; - armv[7-9]*-*-android) - OUT="android-armeabi" - __CNF_CFLAGS="$__CNF_CFLAGS -march=armv7-a" - __CNF_CXXFLAGS="$__CNF_CXXFLAGS -march=armv7-a";; - arm*-*-android) OUT="android-armeabi" ;; - *) OUT=`echo $GUESSOS | awk -F- '{print $3}'`;; -esac - -# NB: This atalla support has been superseded by the ENGINE support -# That contains its own header and definitions anyway. Support can -# be enabled or disabled on any supported platform without external -# headers, eg. by adding the "hw-atalla" switch to ./config or -# perl Configure -# -# See whether we can compile Atalla support -#if [ -f /usr/include/atasi.h ] -#then -# __CNF_CPPFLAGS="$__CNF_CPPFLAGS -DATALLA" -#fi - -if [ -n "$CONFIG_OPTIONS" ]; then - options="$options $CONFIG_OPTIONS" -fi - -# gcc < 2.8 does not support -march=ultrasparc -if [ "$OUT" = solaris-sparcv9-gcc -a $GCCVER -lt 28 ] -then - echo "WARNING! Falling down to 'solaris-sparcv8-gcc'." - echo " Upgrade to gcc-2.8 or later." - sleep 5 - OUT=solaris-sparcv8-gcc -fi -if [ "$OUT" = "linux-sparcv9" -a $GCCVER -lt 28 ] -then - echo "WARNING! Falling down to 'linux-sparcv8'." - echo " Upgrade to gcc-2.8 or later." - sleep 5 - OUT=linux-sparcv8 -fi - -case "$GUESSOS" in - i386-*) options="$options 386" ;; -esac - -for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha sm2 sm3 sm4 -do - if [ ! -d $THERE/crypto/$i ] - then - options="$options no-$i" - fi -done - -if [ -z "$OUT" ]; then - OUT="$CC" -fi - -if [ ".$PERL" = . ] ; then - for i in . `echo $PATH | sed 's/:/ /g'`; do - if [ -f "$i/perl5$EXE" ] ; then - PERL="$i/perl5$EXE" - break; - fi; - done -fi - -if [ ".$PERL" = . ] ; then - for i in . `echo $PATH | sed 's/:/ /g'`; do - if [ -f "$i/perl$EXE" ] ; then - if "$i/perl$EXE" -e 'exit($]<5.0)'; then - PERL="$i/perl$EXE" - break; - fi; - fi; - done -fi - -if [ ".$PERL" = . ] ; then - echo "You need Perl 5." - exit 1 -fi - -# run Configure to check to see if we need to specify the -# compiler for the platform ... in which case we add it on -# the end ... otherwise we leave it off - -$PERL $THERE/Configure LIST | grep "$OUT-$CC" > /dev/null -if [ $? = "0" ]; then - OUT="$OUT-$CC" -fi - -OUT="$OUT" - -if [ "$OUT" = "darwin64-x86_64-cc" ]; then - echo "WARNING! If you wish to build 32-bit libraries, then you have to" - echo " invoke 'KERNEL_BITS=32 $THERE/config $options'." -fi - -if $PERL $THERE/Configure LIST | grep "$OUT" > /dev/null; then - if [ "$VERBOSE" = "true" ]; then - echo /usr/bin/env \ - __CNF_CPPDEFINES="'$__CNF_CPPDEFINES'" \ - __CNF_CPPINCLUDES="'$__CNF_CPPINCLUDES'" \ - __CNF_CPPFLAGS="'$__CNF_CPPFLAGS'" \ - __CNF_CFLAGS="'$__CNF_CFLAGS'" \ - __CNF_CXXFLAGS="'$__CNF_CXXFLAGS'" \ - __CNF_LDFLAGS="'$__CNF_LDFLAGS'" \ - __CNF_LDLIBS="'$__CNF_LDLIBS'" \ - $PERL $THERE/Configure $OUT $options - fi - if [ "$DRYRUN" = "false" ]; then - # eval to make sure quoted options, possibly with spaces inside, - # are treated right - eval /usr/bin/env \ - __CNF_CPPDEFINES="'$__CNF_CPPDEFINES'" \ - __CNF_CPPINCLUDES="'$__CNF_CPPINCLUDES'" \ - __CNF_CPPFLAGS="'$__CNF_CPPFLAGS'" \ - __CNF_CFLAGS="'$__CNF_CFLAGS'" \ - __CNF_CXXFLAGS="'$__CNF_CXXFLAGS'" \ - __CNF_LDFLAGS="'$__CNF_LDFLAGS'" \ - __CNF_LDLIBS="'$__CNF_LDLIBS'" \ - $PERL $THERE/Configure $OUT $options - fi -else - echo "This system ($OUT) is not supported. See file INSTALL for details." - exit 1 -fi - -# Do not add anothing from here on, so we don't lose the Configure exit code -) +exec "$THERE/Configure" "$@" diff --git a/configdata.pm.in b/configdata.pm.in new file mode 100644 --- /dev/null +++ b/configdata.pm.in @@ -0,0 +1,487 @@ +#! {- $config{HASHBANGPERL} -} +# -*- mode: perl -*- +{- + # We must make sourcedir() return an absolute path, because configdata.pm + # may be loaded as a module from any script in any directory, making + # relative paths untrustable. Because the result is used with 'use lib', + # we must ensure that it returns a Unix style path. Mixing File::Spec + # and File::Spec::Unix does just that. + use File::Spec::Unix; + use File::Spec; + use Cwd qw(abs_path); + sub _fixup_path { + my $path = shift; + + # Make the path absolute at all times + $path = abs_path($path); + + if ($^O eq 'VMS') { + # Convert any path of the VMS form VOLUME:[DIR1.DIR2]FILE to the + # Unix form /VOLUME/DIR1/DIR2/FILE, which is what VMS perl supports + # for 'use lib'. + + # Start with spliting the native path + (my $vol, my $dirs, my $file) = File::Spec->splitpath($path); + my @dirs = File::Spec->splitdir($dirs); + + # Reassemble it as a Unix path + $vol =~ s|:$||; + $dirs = File::Spec::Unix->catdir('', $vol, @dirs); + $path = File::Spec::Unix->catpath('', $dirs, $file); + } + + return $path; + } + sub sourcedir { + return _fixup_path(File::Spec->catdir($config{sourcedir}, @_)) + } + sub sourcefile { + return _fixup_path(File::Spec->catfile($config{sourcedir}, @_)) + } + use lib sourcedir('util', 'perl'); + use OpenSSL::Util; +-} +package configdata; + +use strict; +use warnings; + +use Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw( + %config %target %disabled %withargs %unified_info + @disablables @disablables_int +); + +our %config = ({- dump_data(\%config, indent => 0); -}); +our %target = ({- dump_data(\%target, indent => 0); -}); +our @disablables = ({- dump_data(\@disablables, indent => 0) -}); +our @disablables_int = ({- dump_data(\@disablables_int, indent => 0) -}); +our %disabled = ({- dump_data(\%disabled, indent => 0); -}); +our %withargs = ({- dump_data(\%withargs, indent => 0); -}); +our %unified_info = ({- dump_data(\%unified_info, indent => 0); -}); + +# Unexported, only used by OpenSSL::Test::Utils::available_protocols() +our %available_protocols = ( + tls => [{- dump_data(\@tls, indent => 0) -}], + dtls => [{- dump_data(\@dtls, indent => 0) -}], +); + +# The following data is only used when this files is use as a script +my @makevars = ({- dump_data(\@makevars, indent => 0); -}); +my %disabled_info = ({- dump_data(\%disabled_info, indent => 0); -}); +my @user_crossable = qw( {- join (' ', @user_crossable) -} ); + +# If run directly, we can give some answers, and even reconfigure +unless (caller) { + use Getopt::Long; + use File::Spec::Functions; + use File::Basename; + use File::Compare qw(compare_text); + use File::Copy; + use Pod::Usage; + + use lib '{- sourcedir('util', 'perl') -}'; + use OpenSSL::fallback '{- sourcefile('external', 'perl', 'MODULES.txt') -}'; + + my $here = dirname($0); + + if (scalar @ARGV == 0) { + # With no arguments, re-create the build file + # We do that in two steps, where the first step emits perl + # snipets. + + my $buildfile = $config{build_file}; + my $buildfile_template = "$buildfile.in"; + my @autowarntext = ( + 'WARNING: do not edit!', + "Generated by configdata.pm from " + .join(", ", @{$config{build_file_templates}}), + "via $buildfile_template" + ); + my %gendata = ( + config => \%config, + target => \%target, + disabled => \%disabled, + withargs => \%withargs, + unified_info => \%unified_info, + autowarntext => \@autowarntext, + ); + + use lib '.'; + use lib '{- sourcedir('Configurations') -}'; + use gentemplate; + + open my $buildfile_template_fh, ">$buildfile_template" + or die "Trying to create $buildfile_template: $!"; + foreach (@{$config{build_file_templates}}) { + copy($_, $buildfile_template_fh) + or die "Trying to copy $_ into $buildfile_template: $!"; + } + gentemplate(output => $buildfile_template_fh, %gendata); + close $buildfile_template_fh; + print 'Created ',$buildfile_template,"\n"; + + use OpenSSL::Template; + + my $prepend = <<'_____'; +use File::Spec::Functions; +use lib '{- sourcedir('util', 'perl') -}'; +use lib '{- sourcedir('Configurations') -}'; +use lib '{- $config{builddir} -}'; +use platform; +_____ + + my $tmpl; + open BUILDFILE, ">$buildfile.new" + or die "Trying to create $buildfile.new: $!"; + $tmpl = OpenSSL::Template->new(TYPE => 'FILE', + SOURCE => $buildfile_template); + $tmpl->fill_in(FILENAME => $_, + OUTPUT => \*BUILDFILE, + HASH => \%gendata, + PREPEND => $prepend, + # To ensure that global variables and functions + # defined in one template stick around for the + # next, making them combinable + PACKAGE => 'OpenSSL::safe') + or die $Text::Template::ERROR; + close BUILDFILE; + rename("$buildfile.new", $buildfile) + or die "Trying to rename $buildfile.new to $buildfile: $!"; + print 'Created ',$buildfile,"\n"; + + my $configuration_h = + catfile('include', 'openssl', 'configuration.h'); + my $configuration_h_in = + catfile($config{sourcedir}, 'include', 'openssl', 'configuration.h.in'); + open CONFIGURATION_H, ">${configuration_h}.new" + or die "Trying to create ${configuration_h}.new: $!"; + $tmpl = OpenSSL::Template->new(TYPE => 'FILE', + SOURCE => $configuration_h_in); + $tmpl->fill_in(FILENAME => $_, + OUTPUT => \*CONFIGURATION_H, + HASH => \%gendata, + PREPEND => $prepend, + # To ensure that global variables and functions + # defined in one template stick around for the + # next, making them combinable + PACKAGE => 'OpenSSL::safe') + or die $Text::Template::ERROR; + close CONFIGURATION_H; + + # When using stat() on Windows, we can get it to perform better by + # avoid some data. This doesn't affect the mtime field, so we're not + # losing anything... + ${^WIN32_SLOPPY_STAT} = 1; + + my $update_configuration_h = 0; + if (-f $configuration_h) { + my $configuration_h_mtime = (stat($configuration_h))[9]; + my $configuration_h_in_mtime = (stat($configuration_h_in))[9]; + + # If configuration.h.in was updated after the last configuration.h, + # or if configuration.h.new differs configuration.h, we update + # configuration.h + if ($configuration_h_mtime < $configuration_h_in_mtime + || compare_text("${configuration_h}.new", $configuration_h) != 0) { + $update_configuration_h = 1; + } else { + # If nothing has changed, let's just drop the new one and + # pretend like nothing happened + unlink "${configuration_h}.new" + } + } else { + $update_configuration_h = 1; + } + + if ($update_configuration_h) { + rename("${configuration_h}.new", $configuration_h) + or die "Trying to rename ${configuration_h}.new to $configuration_h: $!"; + print 'Created ',$configuration_h,"\n"; + } + + exit(0); + } + + my $dump = undef; + my $cmdline = undef; + my $options = undef; + my $target = undef; + my $envvars = undef; + my $makevars = undef; + my $buildparams = undef; + my $reconf = undef; + my $verbose = undef; + my $query = undef; + my $help = undef; + my $man = undef; + GetOptions('dump|d' => \$dump, + 'command-line|c' => \$cmdline, + 'options|o' => \$options, + 'target|t' => \$target, + 'environment|e' => \$envvars, + 'make-variables|m' => \$makevars, + 'build-parameters|b' => \$buildparams, + 'reconfigure|reconf|r' => \$reconf, + 'verbose|v' => \$verbose, + 'query|q=s' => \$query, + 'help' => \$help, + 'man' => \$man) + or die "Errors in command line arguments\n"; + + # We allow extra arguments with --query. That allows constructs like + # this: + # ./configdata.pm --query 'get_sources(@ARGV)' file1 file2 file3 + if (!$query && scalar @ARGV > 0) { + print STDERR <<"_____"; +Unrecognised arguments. +For more information, do '$0 --help' +_____ + exit(2); + } + + if ($help) { + pod2usage(-exitval => 0, + -verbose => 1); + } + if ($man) { + pod2usage(-exitval => 0, + -verbose => 2); + } + if ($dump || $cmdline) { + print "\nCommand line (with current working directory = $here):\n\n"; + print ' ',join(' ', + $config{PERL}, + catfile($config{sourcedir}, 'Configure'), + @{$config{perlargv}}), "\n"; + print "\nPerl information:\n\n"; + print ' ',$config{perl_cmd},"\n"; + print ' ',$config{perl_version},' for ',$config{perl_archname},"\n"; + } + if ($dump || $options) { + my $longest = 0; + my $longest2 = 0; + foreach my $what (@disablables) { + $longest = length($what) if $longest < length($what); + $longest2 = length($disabled{$what}) + if $disabled{$what} && $longest2 < length($disabled{$what}); + } + print "\nEnabled features:\n\n"; + foreach my $what (@disablables) { + print " $what\n" unless $disabled{$what}; + } + print "\nDisabled features:\n\n"; + foreach my $what (@disablables) { + if ($disabled{$what}) { + print " $what", ' ' x ($longest - length($what) + 1), + "[$disabled{$what}]", ' ' x ($longest2 - length($disabled{$what}) + 1); + print $disabled_info{$what}->{macro} + if $disabled_info{$what}->{macro}; + print ' (skip ', + join(', ', @{$disabled_info{$what}->{skipped}}), + ')' + if $disabled_info{$what}->{skipped}; + print "\n"; + } + } + } + if ($dump || $target) { + print "\nConfig target attributes:\n\n"; + foreach (sort keys %target) { + next if $_ =~ m|^_| || $_ eq 'template'; + my $quotify = sub { + map { + if (defined $_) { + (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\"" + } else { + "undef"; + } + } @_; + }; + print ' ', $_, ' => '; + if (ref($target{$_}) eq "ARRAY") { + print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n"; + } else { + print $quotify->($target{$_}), ",\n" + } + } + } + if ($dump || $envvars) { + print "\nRecorded environment:\n\n"; + foreach (sort keys %{$config{perlenv}}) { + print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n"; + } + } + if ($dump || $makevars) { + print "\nMakevars:\n\n"; + foreach my $var (@makevars) { + my $prefix = ''; + $prefix = $config{CROSS_COMPILE} + if grep { $var eq $_ } @user_crossable; + $prefix //= ''; + print ' ',$var,' ' x (16 - length $var),'= ', + (ref $config{$var} eq 'ARRAY' + ? join(' ', @{$config{$var}}) + : $prefix.$config{$var}), + "\n" + if defined $config{$var}; + } + + my @buildfile = ($config{builddir}, $config{build_file}); + unshift @buildfile, $here + unless file_name_is_absolute($config{builddir}); + my $buildfile = canonpath(catdir(@buildfile)); + print <<"_____"; + +NOTE: These variables only represent the configuration view. The build file +template may have processed these variables further, please have a look at the +build file for more exact data: + $buildfile +_____ + } + if ($dump || $buildparams) { + my @buildfile = ($config{builddir}, $config{build_file}); + unshift @buildfile, $here + unless file_name_is_absolute($config{builddir}); + print "\nbuild file:\n\n"; + print " ", canonpath(catfile(@buildfile)),"\n"; + + print "\nbuild file templates:\n\n"; + foreach (@{$config{build_file_templates}}) { + my @tmpl = ($_); + unshift @tmpl, $here + unless file_name_is_absolute($config{sourcedir}); + print ' ',canonpath(catfile(@tmpl)),"\n"; + } + } + if ($reconf) { + if ($verbose) { + print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n"; + foreach (sort keys %{$config{perlenv}}) { + print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n"; + } + } + + chdir $here; + exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf'; + } + if ($query) { + use OpenSSL::Config::Query; + + my $confquery = OpenSSL::Config::Query->new(info => \%unified_info, + config => \%config); + my $result = eval "\$confquery->$query"; + + # We may need a result class with a printing function at some point. + # Until then, we assume that we get a scalar, or a list or a hash table + # with scalar values and simply print them in some orderly fashion. + if (ref $result eq 'ARRAY') { + print "$_\n" foreach @$result; + } elsif (ref $result eq 'HASH') { + print "$_ : \\\n ", join(" \\\n ", @{$result->{$_}}), "\n" + foreach sort keys %$result; + } elsif (ref $result eq 'SCALAR') { + print "$$result\n"; + } + } +} + +1; + +__END__ + +=head1 NAME + +configdata.pm - configuration data for OpenSSL builds + +=head1 SYNOPSIS + +Interactive: + + perl configdata.pm [options] + +As data bank module: + + use configdata; + +=head1 DESCRIPTION + +This module can be used in two modes, interactively and as a module containing +all the data recorded by OpenSSL's Configure script. + +When used interactively, simply run it as any perl script. +If run with no arguments, it will rebuild the build file (Makefile or +corresponding). +With at least one option, it will instead get the information you ask for, or +re-run the configuration process. +See L below for more information. + +When loaded as a module, you get a few databanks with useful information to +perform build related tasks. The databanks are: + + %config Configured things. + %target The OpenSSL config target with all inheritances + resolved. + %disabled The features that are disabled. + @disablables The list of features that can be disabled. + %withargs All data given through --with-THING options. + %unified_info All information that was computed from the build.info + files. + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Print a brief help message and exit. + +=item B<--man> + +Print the manual page and exit. + +=item B<--dump> | B<-d> + +Print all relevant configuration data. This is equivalent to B<--command-line> +B<--options> B<--target> B<--environment> B<--make-variables> +B<--build-parameters>. + +=item B<--command-line> | B<-c> + +Print the current configuration command line. + +=item B<--options> | B<-o> + +Print the features, both enabled and disabled, and display defined macro and +skipped directories where applicable. + +=item B<--target> | B<-t> + +Print the config attributes for this config target. + +=item B<--environment> | B<-e> + +Print the environment variables and their values at the time of configuration. + +=item B<--make-variables> | B<-m> + +Print the main make variables generated in the current configuration + +=item B<--build-parameters> | B<-b> + +Print the build parameters, i.e. build file and build file templates. + +=item B<--reconfigure> | B<--reconf> | B<-r> + +Re-run the configuration process. + +=item B<--verbose> | B<-v> + +Verbose output. + +=back + +=cut + +EOF diff --git a/crypto/LPdir_unix.c b/crypto/LPdir_unix.c --- a/crypto/LPdir_unix.c +++ b/crypto/LPdir_unix.c @@ -1,7 +1,7 @@ /* - * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -141,7 +141,8 @@ p--; if (p > (*ctx)->entry_name && p[-1] == ';') p[-1] = '\0'; - if (strcasecmp((*ctx)->entry_name, (*ctx)->previous_entry_name) == 0) + if (OPENSSL_strcasecmp((*ctx)->entry_name, + (*ctx)->previous_entry_name) == 0) goto again; } #endif diff --git a/crypto/README-sparse_array.md b/crypto/README-sparse_array.md new file mode 100644 --- /dev/null +++ b/crypto/README-sparse_array.md @@ -0,0 +1,156 @@ +Sparse Arrays +============= + +The `sparse_array.c` file contains an implementation of a sparse array that +attempts to be both space and time efficient. + +The sparse array is represented using a tree structure. Each node in the +tree contains a block of pointers to either the user supplied leaf values or +to another node. + +There are a number of parameters used to define the block size: + + OPENSSL_SA_BLOCK_BITS Specifies the number of bits covered by each block + SA_BLOCK_MAX Specifies the number of pointers in each block + SA_BLOCK_MASK Specifies a bit mask to perform modulo block size + SA_BLOCK_MAX_LEVELS Indicates the maximum possible height of the tree + +These constants are inter-related: + + SA_BLOCK_MAX = 2 ^ OPENSSL_SA_BLOCK_BITS + SA_BLOCK_MASK = SA_BLOCK_MAX - 1 + SA_BLOCK_MAX_LEVELS = number of bits in size_t divided by + OPENSSL_SA_BLOCK_BITS rounded up to the next multiple + of OPENSSL_SA_BLOCK_BITS + +`OPENSSL_SA_BLOCK_BITS` can be defined at compile time and this overrides the +built in setting. + +As a space and performance optimisation, the height of the tree is usually +less than the maximum possible height. Only sufficient height is allocated to +accommodate the largest index added to the data structure. + +The largest index used to add a value to the array determines the tree height: + + +----------------------+---------------------+ + | Largest Added Index | Height of Tree | + +----------------------+---------------------+ + | SA_BLOCK_MAX - 1 | 1 | + | SA_BLOCK_MAX ^ 2 - 1 | 2 | + | SA_BLOCK_MAX ^ 3 - 1 | 3 | + | ... | ... | + | size_t max | SA_BLOCK_MAX_LEVELS | + +----------------------+---------------------+ + +The tree height is dynamically increased as needed based on additions. + +An empty tree is represented by a NULL root pointer. Inserting a value at +index 0 results in the allocation of a top level node full of null pointers +except for the single pointer to the user's data (N = SA_BLOCK_MAX for +brevity): + + +----+ + |Root| + |Node| + +-+--+ + | + | + | + v + +-+-+---+---+---+---+ + | 0 | 1 | 2 |...|N-1| + | |nil|nil|...|nil| + +-+-+---+---+---+---+ + | + | + | + v + +-+--+ + |User| + |Data| + +----+ + Index 0 + +Inserting at element 2N+1 creates a new root node and pushes down the old root +node. It then creates a second second level node to hold the pointer to the +user's new data: + + +----+ + |Root| + |Node| + +-+--+ + | + | + | + v + +-+-+---+---+---+---+ + | 0 | 1 | 2 |...|N-1| + | |nil| |...|nil| + +-+-+---+-+-+---+---+ + | | + | +------------------+ + | | + v v + +-+-+---+---+---+---+ +-+-+---+---+---+---+ + | 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1| + |nil| |nil|...|nil| |nil| |nil|...|nil| + +-+-+---+---+---+---+ +---+-+-+---+---+---+ + | | + | | + | | + v v + +-+--+ +-+--+ + |User| |User| + |Data| |Data| + +----+ +----+ + Index 0 Index 2N+1 + +The nodes themselves are allocated in a sparse manner. Only nodes which exist +along a path from the root of the tree to an added leaf will be allocated. +The complexity is hidden and nodes are allocated on an as needed basis. +Because the data is expected to be sparse this doesn't result in a large waste +of space. + +Values can be removed from the sparse array by setting their index position to +NULL. The data structure does not attempt to reclaim nodes or reduce the +height of the tree on removal. For example, now setting index 0 to NULL would +result in: + + +----+ + |Root| + |Node| + +-+--+ + | + | + | + v + +-+-+---+---+---+---+ + | 0 | 1 | 2 |...|N-1| + | |nil| |...|nil| + +-+-+---+-+-+---+---+ + | | + | +------------------+ + | | + v v + +-+-+---+---+---+---+ +-+-+---+---+---+---+ + | 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1| + |nil|nil|nil|...|nil| |nil| |nil|...|nil| + +---+---+---+---+---+ +---+-+-+---+---+---+ + | + | + | + v + +-+--+ + |User| + |Data| + +----+ + Index 2N+1 + +Accesses to elements in the sparse array take O(log n) time where n is the +largest element. The base of the logarithm is `SA_BLOCK_MAX`, so for moderately +small indices (e.g. NIDs), single level (constant time) access is achievable. +Space usage is O(minimum(m, n log(n)) where m is the number of elements in the +array. + +Note: sparse arrays only include pointers to types. +Thus, `SPARSE_ARRAY_OF(char)` can be used to store a string. diff --git a/crypto/aes/aes_cbc.c b/crypto/aes/aes_cbc.c --- a/crypto/aes/aes_cbc.c +++ b/crypto/aes/aes_cbc.c @@ -1,12 +1,19 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * AES low level APIs are deprecated for public use, but still ok for internal + * use where we're using them to implement the higher level EVP interface, as is + * the case here. + */ +#include "internal/deprecated.h" + #include #include diff --git a/crypto/aes/aes_cfb.c b/crypto/aes/aes_cfb.c --- a/crypto/aes/aes_cfb.c +++ b/crypto/aes/aes_cfb.c @@ -1,12 +1,18 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * AES_encrypt is deprecated - but we need to use it to implement these other + * deprecated APIs. + */ +#include "internal/deprecated.h" + #include #include diff --git a/crypto/aes/aes_core.c b/crypto/aes/aes_core.c --- a/crypto/aes/aes_core.c +++ b/crypto/aes/aes_core.c @@ -1,7 +1,7 @@ /* - * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -36,6 +36,13 @@ /* Note: rewritten a little bit to provide error control and an OpenSSL- compatible API */ +/* + * AES low level APIs are deprecated for public use, but still ok for internal + * use where we're using them to implement the higher level EVP interface, as is + * the case here. + */ +#include "internal/deprecated.h" + #include #include @@ -44,6 +51,15 @@ #include "aes_local.h" #if defined(OPENSSL_AES_CONST_TIME) && !defined(AES_ASM) + +# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +# define U64(C) C##UI64 +# elif defined(__arch64__) +# define U64(C) C##UL +# else +# define U64(C) C##ULL +# endif + typedef union { unsigned char b[8]; u32 w[2]; @@ -72,10 +88,10 @@ u64 a, b; a = *w; - b = a & 0x8080808080808080uLL; + b = a & U64(0x8080808080808080); a ^= b; b -= b >> 7; - b &= 0x1B1B1B1B1B1B1B1BuLL; + b &= U64(0x1B1B1B1B1B1B1B1B); b ^= a << 1; *w = b; } @@ -222,89 +238,89 @@ u64 x, y, a1, a2, a3, a4, a5, a6; x = *w; - y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7); - x &= 0xDDDDDDDDDDDDDDDDuLL; - x ^= y & 0x5757575757575757uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x1C1C1C1C1C1C1C1CuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x4A4A4A4A4A4A4A4AuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x4242424242424242uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x6464646464646464uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xE0E0E0E0E0E0E0E0uLL; + y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7); + x &= U64(0xDDDDDDDDDDDDDDDD); + x ^= y & U64(0x5757575757575757); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x1C1C1C1C1C1C1C1C); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x4A4A4A4A4A4A4A4A); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x4242424242424242); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x6464646464646464); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xE0E0E0E0E0E0E0E0); a1 = x; - a1 ^= (x & 0xF0F0F0F0F0F0F0F0uLL) >> 4; - a2 = ((x & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((x & 0x3333333333333333uLL) << 2); + a1 ^= (x & U64(0xF0F0F0F0F0F0F0F0)) >> 4; + a2 = ((x & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((x & U64(0x3333333333333333)) << 2); a3 = x & a1; - a3 ^= (a3 & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & 0xAAAAAAAAAAAAAAAAuLL; + a3 ^= (a3 & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & U64(0xAAAAAAAAAAAAAAAA); a4 = a2 & a1; - a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL; - a5 = (a3 & 0xCCCCCCCCCCCCCCCCuLL) >> 2; - a3 ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL; - a4 = a5 & 0x2222222222222222uLL; + a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA); + a5 = (a3 & U64(0xCCCCCCCCCCCCCCCC)) >> 2; + a3 ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC); + a4 = a5 & U64(0x2222222222222222); a4 |= a4 >> 1; - a4 ^= (a5 << 1) & 0x2222222222222222uLL; + a4 ^= (a5 << 1) & U64(0x2222222222222222); a3 ^= a4; - a5 = a3 & 0xA0A0A0A0A0A0A0A0uLL; + a5 = a3 & U64(0xA0A0A0A0A0A0A0A0); a5 |= a5 >> 1; - a5 ^= (a3 << 1) & 0xA0A0A0A0A0A0A0A0uLL; - a4 = a5 & 0xC0C0C0C0C0C0C0C0uLL; + a5 ^= (a3 << 1) & U64(0xA0A0A0A0A0A0A0A0); + a4 = a5 & U64(0xC0C0C0C0C0C0C0C0); a6 = a4 >> 2; - a4 ^= (a5 << 2) & 0xC0C0C0C0C0C0C0C0uLL; - a5 = a6 & 0x2020202020202020uLL; + a4 ^= (a5 << 2) & U64(0xC0C0C0C0C0C0C0C0); + a5 = a6 & U64(0x2020202020202020); a5 |= a5 >> 1; - a5 ^= (a6 << 1) & 0x2020202020202020uLL; + a5 ^= (a6 << 1) & U64(0x2020202020202020); a4 |= a5; a3 ^= a4 >> 4; - a3 &= 0x0F0F0F0F0F0F0F0FuLL; + a3 &= U64(0x0F0F0F0F0F0F0F0F); a2 = a3; - a2 ^= (a3 & 0x0C0C0C0C0C0C0C0CuLL) >> 2; + a2 ^= (a3 & U64(0x0C0C0C0C0C0C0C0C)) >> 2; a4 = a3 & a2; - a4 ^= (a4 & 0x0A0A0A0A0A0A0A0AuLL) >> 1; - a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & 0x0A0A0A0A0A0A0A0AuLL; - a5 = a4 & 0x0808080808080808uLL; + a4 ^= (a4 & U64(0x0A0A0A0A0A0A0A0A)) >> 1; + a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & U64(0x0A0A0A0A0A0A0A0A); + a5 = a4 & U64(0x0808080808080808); a5 |= a5 >> 1; - a5 ^= (a4 << 1) & 0x0808080808080808uLL; + a5 ^= (a4 << 1) & U64(0x0808080808080808); a4 ^= a5 >> 2; - a4 &= 0x0303030303030303uLL; - a4 ^= (a4 & 0x0202020202020202uLL) >> 1; + a4 &= U64(0x0303030303030303); + a4 ^= (a4 & U64(0x0202020202020202)) >> 1; a4 |= a4 << 2; a3 = a2 & a4; - a3 ^= (a3 & 0x0A0A0A0A0A0A0A0AuLL) >> 1; - a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & 0x0A0A0A0A0A0A0A0AuLL; + a3 ^= (a3 & U64(0x0A0A0A0A0A0A0A0A)) >> 1; + a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & U64(0x0A0A0A0A0A0A0A0A); a3 |= a3 << 4; - a2 = ((a1 & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((a1 & 0x3333333333333333uLL) << 2); + a2 = ((a1 & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((a1 & U64(0x3333333333333333)) << 2); x = a1 & a3; - x ^= (x & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & 0xAAAAAAAAAAAAAAAAuLL; + x ^= (x & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & U64(0xAAAAAAAAAAAAAAAA); a4 = a2 & a3; - a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL; - a5 = (x & 0xCCCCCCCCCCCCCCCCuLL) >> 2; - x ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL; - a4 = a5 & 0x2222222222222222uLL; + a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA); + a5 = (x & U64(0xCCCCCCCCCCCCCCCC)) >> 2; + x ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC); + a4 = a5 & U64(0x2222222222222222); a4 |= a4 >> 1; - a4 ^= (a5 << 1) & 0x2222222222222222uLL; + a4 ^= (a5 << 1) & U64(0x2222222222222222); x ^= a4; - y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7); - x &= 0x3939393939393939uLL; - x ^= y & 0x3F3F3F3F3F3F3F3FuLL; - y = ((y & 0xFCFCFCFCFCFCFCFCuLL) >> 2) | ((y & 0x0303030303030303uLL) << 6); - x ^= y & 0x9797979797979797uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x9B9B9B9B9B9B9B9BuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x3C3C3C3C3C3C3C3CuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xDDDDDDDDDDDDDDDDuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x7272727272727272uLL; - x ^= 0x6363636363636363uLL; + y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7); + x &= U64(0x3939393939393939); + x ^= y & U64(0x3F3F3F3F3F3F3F3F); + y = ((y & U64(0xFCFCFCFCFCFCFCFC)) >> 2) | ((y & U64(0x0303030303030303)) << 6); + x ^= y & U64(0x9797979797979797); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x9B9B9B9B9B9B9B9B); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x3C3C3C3C3C3C3C3C); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xDDDDDDDDDDDDDDDD); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x7272727272727272); + x ^= U64(0x6363636363636363); *w = x; } @@ -316,93 +332,93 @@ u64 x, y, a1, a2, a3, a4, a5, a6; x = *w; - x ^= 0x6363636363636363uLL; - y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7); - x &= 0xFDFDFDFDFDFDFDFDuLL; - x ^= y & 0x5E5E5E5E5E5E5E5EuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xF3F3F3F3F3F3F3F3uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xF5F5F5F5F5F5F5F5uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x7878787878787878uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x7777777777777777uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x1515151515151515uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xA5A5A5A5A5A5A5A5uLL; + x ^= U64(0x6363636363636363); + y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7); + x &= U64(0xFDFDFDFDFDFDFDFD); + x ^= y & U64(0x5E5E5E5E5E5E5E5E); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xF3F3F3F3F3F3F3F3); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xF5F5F5F5F5F5F5F5); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x7878787878787878); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x7777777777777777); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x1515151515151515); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xA5A5A5A5A5A5A5A5); a1 = x; - a1 ^= (x & 0xF0F0F0F0F0F0F0F0uLL) >> 4; - a2 = ((x & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((x & 0x3333333333333333uLL) << 2); + a1 ^= (x & U64(0xF0F0F0F0F0F0F0F0)) >> 4; + a2 = ((x & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((x & U64(0x3333333333333333)) << 2); a3 = x & a1; - a3 ^= (a3 & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & 0xAAAAAAAAAAAAAAAAuLL; + a3 ^= (a3 & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & U64(0xAAAAAAAAAAAAAAAA); a4 = a2 & a1; - a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL; - a5 = (a3 & 0xCCCCCCCCCCCCCCCCuLL) >> 2; - a3 ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL; - a4 = a5 & 0x2222222222222222uLL; + a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA); + a5 = (a3 & U64(0xCCCCCCCCCCCCCCCC)) >> 2; + a3 ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC); + a4 = a5 & U64(0x2222222222222222); a4 |= a4 >> 1; - a4 ^= (a5 << 1) & 0x2222222222222222uLL; + a4 ^= (a5 << 1) & U64(0x2222222222222222); a3 ^= a4; - a5 = a3 & 0xA0A0A0A0A0A0A0A0uLL; + a5 = a3 & U64(0xA0A0A0A0A0A0A0A0); a5 |= a5 >> 1; - a5 ^= (a3 << 1) & 0xA0A0A0A0A0A0A0A0uLL; - a4 = a5 & 0xC0C0C0C0C0C0C0C0uLL; + a5 ^= (a3 << 1) & U64(0xA0A0A0A0A0A0A0A0); + a4 = a5 & U64(0xC0C0C0C0C0C0C0C0); a6 = a4 >> 2; - a4 ^= (a5 << 2) & 0xC0C0C0C0C0C0C0C0uLL; - a5 = a6 & 0x2020202020202020uLL; + a4 ^= (a5 << 2) & U64(0xC0C0C0C0C0C0C0C0); + a5 = a6 & U64(0x2020202020202020); a5 |= a5 >> 1; - a5 ^= (a6 << 1) & 0x2020202020202020uLL; + a5 ^= (a6 << 1) & U64(0x2020202020202020); a4 |= a5; a3 ^= a4 >> 4; - a3 &= 0x0F0F0F0F0F0F0F0FuLL; + a3 &= U64(0x0F0F0F0F0F0F0F0F); a2 = a3; - a2 ^= (a3 & 0x0C0C0C0C0C0C0C0CuLL) >> 2; + a2 ^= (a3 & U64(0x0C0C0C0C0C0C0C0C)) >> 2; a4 = a3 & a2; - a4 ^= (a4 & 0x0A0A0A0A0A0A0A0AuLL) >> 1; - a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & 0x0A0A0A0A0A0A0A0AuLL; - a5 = a4 & 0x0808080808080808uLL; + a4 ^= (a4 & U64(0x0A0A0A0A0A0A0A0A)) >> 1; + a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & U64(0x0A0A0A0A0A0A0A0A); + a5 = a4 & U64(0x0808080808080808); a5 |= a5 >> 1; - a5 ^= (a4 << 1) & 0x0808080808080808uLL; + a5 ^= (a4 << 1) & U64(0x0808080808080808); a4 ^= a5 >> 2; - a4 &= 0x0303030303030303uLL; - a4 ^= (a4 & 0x0202020202020202uLL) >> 1; + a4 &= U64(0x0303030303030303); + a4 ^= (a4 & U64(0x0202020202020202)) >> 1; a4 |= a4 << 2; a3 = a2 & a4; - a3 ^= (a3 & 0x0A0A0A0A0A0A0A0AuLL) >> 1; - a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & 0x0A0A0A0A0A0A0A0AuLL; + a3 ^= (a3 & U64(0x0A0A0A0A0A0A0A0A)) >> 1; + a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & U64(0x0A0A0A0A0A0A0A0A); a3 |= a3 << 4; - a2 = ((a1 & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((a1 & 0x3333333333333333uLL) << 2); + a2 = ((a1 & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((a1 & U64(0x3333333333333333)) << 2); x = a1 & a3; - x ^= (x & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & 0xAAAAAAAAAAAAAAAAuLL; + x ^= (x & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & U64(0xAAAAAAAAAAAAAAAA); a4 = a2 & a3; - a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1; - a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL; - a5 = (x & 0xCCCCCCCCCCCCCCCCuLL) >> 2; - x ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL; - a4 = a5 & 0x2222222222222222uLL; + a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1; + a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA); + a5 = (x & U64(0xCCCCCCCCCCCCCCCC)) >> 2; + x ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC); + a4 = a5 & U64(0x2222222222222222); a4 |= a4 >> 1; - a4 ^= (a5 << 1) & 0x2222222222222222uLL; + a4 ^= (a5 << 1) & U64(0x2222222222222222); x ^= a4; - y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7); - x &= 0xB5B5B5B5B5B5B5B5uLL; - x ^= y & 0x4040404040404040uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x8080808080808080uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x1616161616161616uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xEBEBEBEBEBEBEBEBuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x9797979797979797uLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0xFBFBFBFBFBFBFBFBuLL; - y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7); - x ^= y & 0x7D7D7D7D7D7D7D7DuLL; + y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7); + x &= U64(0xB5B5B5B5B5B5B5B5); + x ^= y & U64(0x4040404040404040); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x8080808080808080); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x1616161616161616); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xEBEBEBEBEBEBEBEB); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x9797979797979797); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0xFBFBFBFBFBFBFBFB); + y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7); + x ^= y & U64(0x7D7D7D7D7D7D7D7D); *w = x; } @@ -453,10 +469,10 @@ for (c = 0; c < 2; c++) { s1.d = state[c]; s.d = s1.d; - s.d ^= ((s.d & 0xFFFF0000FFFF0000uLL) >> 16) - | ((s.d & 0x0000FFFF0000FFFFuLL) << 16); - s.d ^= ((s.d & 0xFF00FF00FF00FF00uLL) >> 8) - | ((s.d & 0x00FF00FF00FF00FFuLL) << 8); + s.d ^= ((s.d & U64(0xFFFF0000FFFF0000)) >> 16) + | ((s.d & U64(0x0000FFFF0000FFFF)) << 16); + s.d ^= ((s.d & U64(0xFF00FF00FF00FF00)) >> 8) + | ((s.d & U64(0x00FF00FF00FF00FF)) << 8); s.d ^= s1.d; XtimeLong(&s1.d); s.d ^= s1.d; @@ -481,10 +497,10 @@ for (c = 0; c < 2; c++) { s1.d = state[c]; s.d = s1.d; - s.d ^= ((s.d & 0xFFFF0000FFFF0000uLL) >> 16) - | ((s.d & 0x0000FFFF0000FFFFuLL) << 16); - s.d ^= ((s.d & 0xFF00FF00FF00FF00uLL) >> 8) - | ((s.d & 0x00FF00FF00FF00FFuLL) << 8); + s.d ^= ((s.d & U64(0xFFFF0000FFFF0000)) >> 16) + | ((s.d & U64(0x0000FFFF0000FFFF)) << 16); + s.d ^= ((s.d & U64(0xFF00FF00FF00FF00)) >> 8) + | ((s.d & U64(0x00FF00FF00FF00FF)) << 8); s.d ^= s1.d; XtimeLong(&s1.d); s.d ^= s1.d; @@ -497,12 +513,12 @@ s.b[6] ^= s1.b[7]; s.b[7] ^= s1.b[4]; XtimeLong(&s1.d); - s1.d ^= ((s1.d & 0xFFFF0000FFFF0000uLL) >> 16) - | ((s1.d & 0x0000FFFF0000FFFFuLL) << 16); + s1.d ^= ((s1.d & U64(0xFFFF0000FFFF0000)) >> 16) + | ((s1.d & U64(0x0000FFFF0000FFFF)) << 16); s.d ^= s1.d; XtimeLong(&s1.d); - s1.d ^= ((s1.d & 0xFF00FF00FF00FF00uLL) >> 8) - | ((s1.d & 0x00FF00FF00FF00FFuLL) << 8); + s1.d ^= ((s1.d & U64(0xFF00FF00FF00FF00)) >> 8) + | ((s1.d & U64(0x00FF00FF00FF00FF)) << 8); s.d ^= s1.d; state[c] = s.d; } diff --git a/crypto/aes/aes_ecb.c b/crypto/aes/aes_ecb.c --- a/crypto/aes/aes_ecb.c +++ b/crypto/aes/aes_ecb.c @@ -1,7 +1,7 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -9,6 +9,12 @@ #include +/* + * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement + * AES_ecb_encrypt + */ +#include "internal/deprecated.h" + #include #include "aes_local.h" diff --git a/crypto/aes/aes_ige.c b/crypto/aes/aes_ige.c --- a/crypto/aes/aes_ige.c +++ b/crypto/aes/aes_ige.c @@ -1,12 +1,18 @@ /* * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement + * these functions + */ +#include "internal/deprecated.h" + #include "internal/cryptlib.h" #include @@ -38,12 +44,13 @@ /* N.B. The IV for this mode is _twice_ the block size */ +/* Use of this function is deprecated. */ void AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc) { size_t n; - size_t len = length; + size_t len = length / AES_BLOCK_SIZE; if (length == 0) return; @@ -52,8 +59,6 @@ OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); - len = length / AES_BLOCK_SIZE; - if (AES_ENCRYPT == enc) { if (in != out && (UNALIGNED_MEMOPS_ARE_FAST @@ -166,6 +171,14 @@ /* * Note that its effectively impossible to do biIGE in anything other * than a single pass, so no provision is made for chaining. + * + * NB: The implementation of AES_bi_ige_encrypt has a bug. It is supposed to use + * 2 AES keys, but in fact only one is ever used. This bug has been present + * since this code was first implemented. It is believed to have minimal + * security impact in practice and has therefore not been fixed for backwards + * compatibility reasons. + * + * Use of this function is deprecated. */ /* N.B. The IV for this mode is _four times_ the block size */ diff --git a/crypto/aes/aes_local.h b/crypto/aes/aes_local.h --- a/crypto/aes/aes_local.h +++ b/crypto/aes/aes_local.h @@ -1,7 +1,7 @@ /* - * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -24,7 +24,7 @@ # define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } # endif -typedef unsigned long long u64; +typedef uint64_t u64; # ifdef AES_LONG typedef unsigned long u32; # else diff --git a/crypto/aes/aes_misc.c b/crypto/aes/aes_misc.c --- a/crypto/aes/aes_misc.c +++ b/crypto/aes/aes_misc.c @@ -1,7 +1,7 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,11 +11,13 @@ #include #include "aes_local.h" +#ifndef OPENSSL_NO_DEPRECATED_3_0 const char *AES_options(void) { -#ifdef FULL_UNROLL +# ifdef FULL_UNROLL return "aes(full)"; -#else +# else return "aes(partial)"; -#endif +# endif } +#endif diff --git a/crypto/aes/aes_ofb.c b/crypto/aes/aes_ofb.c --- a/crypto/aes/aes_ofb.c +++ b/crypto/aes/aes_ofb.c @@ -1,12 +1,18 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * AES_encrypt is deprecated - but we need to use it to implement + * AES_ofb128_encrypt + */ +#include "internal/deprecated.h" + #include #include diff --git a/crypto/aes/aes_wrap.c b/crypto/aes/aes_wrap.c --- a/crypto/aes/aes_wrap.c +++ b/crypto/aes/aes_wrap.c @@ -1,12 +1,18 @@ /* - * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement + * these functions + */ +#include "internal/deprecated.h" + #include "internal/cryptlib.h" #include #include diff --git a/crypto/aes/aes_x86core.c b/crypto/aes/aes_x86core.c --- a/crypto/aes/aes_x86core.c +++ b/crypto/aes/aes_x86core.c @@ -1,7 +1,7 @@ /* * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/aes/asm/aes-586.pl b/crypto/aes/asm/aes-586.pl new file mode 100755 --- /dev/null +++ b/crypto/aes/asm/aes-586.pl @@ -0,0 +1,2998 @@ +#! /usr/bin/env perl +# Copyright 2004-2020 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 +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Version 4.3. +# +# You might fail to appreciate this module performance from the first +# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered +# to be *the* best Intel C compiler without -KPIC, performance appears +# to be virtually identical... But try to re-configure with shared +# library support... Aha! Intel compiler "suddenly" lags behind by 30% +# [on P4, more on others]:-) And if compared to position-independent +# code generated by GNU C, this code performs *more* than *twice* as +# fast! Yes, all this buzz about PIC means that unlike other hand- +# coded implementations, this one was explicitly designed to be safe +# to use even in shared library context... This also means that this +# code isn't necessarily absolutely fastest "ever," because in order +# to achieve position independence an extra register has to be +# off-loaded to stack, which affects the benchmark result. +# +# Special note about instruction choice. Do you recall RC4_INT code +# performing poorly on P4? It might be the time to figure out why. +# RC4_INT code implies effective address calculations in base+offset*4 +# form. Trouble is that it seems that offset scaling turned to be +# critical path... At least eliminating scaling resulted in 2.8x RC4 +# performance improvement [as you might recall]. As AES code is hungry +# for scaling too, I [try to] avoid the latter by favoring off-by-2 +# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF. +# +# As was shown by Dean Gaudet, the above note turned out to be +# void. Performance improvement with off-by-2 shifts was observed on +# intermediate implementation, which was spilling yet another register +# to stack... Final offset*4 code below runs just a tad faster on P4, +# but exhibits up to 10% improvement on other cores. +# +# Second version is "monolithic" replacement for aes_core.c, which in +# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key. +# This made it possible to implement little-endian variant of the +# algorithm without modifying the base C code. Motivating factor for +# the undertaken effort was that it appeared that in tight IA-32 +# register window little-endian flavor could achieve slightly higher +# Instruction Level Parallelism, and it indeed resulted in up to 15% +# better performance on most recent µ-archs... +# +# Third version adds AES_cbc_encrypt implementation, which resulted in +# up to 40% performance improvement of CBC benchmark results. 40% was +# observed on P4 core, where "overall" improvement coefficient, i.e. if +# compared to PIC generated by GCC and in CBC mode, was observed to be +# as large as 4x:-) CBC performance is virtually identical to ECB now +# and on some platforms even better, e.g. 17.6 "small" cycles/byte on +# Opteron, because certain function prologues and epilogues are +# effectively taken out of the loop... +# +# Version 3.2 implements compressed tables and prefetch of these tables +# in CBC[!] mode. Former means that 3/4 of table references are now +# misaligned, which unfortunately has negative impact on elder IA-32 +# implementations, Pentium suffered 30% penalty, PIII - 10%. +# +# Version 3.3 avoids L1 cache aliasing between stack frame and +# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The +# latter is achieved by copying the key schedule to controlled place in +# stack. This unfortunately has rather strong impact on small block CBC +# performance, ~2x deterioration on 16-byte block if compared to 3.3. +# +# Version 3.5 checks if there is L1 cache aliasing between user-supplied +# key schedule and S-boxes and abstains from copying the former if +# there is no. This allows end-user to consciously retain small block +# performance by aligning key schedule in specific manner. +# +# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB. +# +# Current ECB performance numbers for 128-bit key in CPU cycles per +# processed byte [measure commonly used by AES benchmarkers] are: +# +# small footprint fully unrolled +# P4 24 22 +# AMD K8 20 19 +# PIII 25 23 +# Pentium 81 78 +# +# Version 3.7 reimplements outer rounds as "compact." Meaning that +# first and last rounds reference compact 256 bytes S-box. This means +# that first round consumes a lot more CPU cycles and that encrypt +# and decrypt performance becomes asymmetric. Encrypt performance +# drops by 10-12%, while decrypt - by 20-25%:-( 256 bytes S-box is +# aggressively pre-fetched. +# +# Version 4.0 effectively rolls back to 3.6 and instead implements +# additional set of functions, _[x86|sse]_AES_[en|de]crypt_compact, +# which use exclusively 256 byte S-box. These functions are to be +# called in modes not concealing plain text, such as ECB, or when +# we're asked to process smaller amount of data [or unconditionally +# on hyper-threading CPU]. Currently it's called unconditionally from +# AES_[en|de]crypt, which affects all modes, but CBC. CBC routine +# still needs to be modified to switch between slower and faster +# mode when appropriate... But in either case benchmark landscape +# changes dramatically and below numbers are CPU cycles per processed +# byte for 128-bit key. +# +# ECB encrypt ECB decrypt CBC large chunk +# P4 52[54] 83[95] 23 +# AMD K8 46[41] 66[70] 18 +# PIII 41[50] 60[77] 24 +# Core 2 31[36] 45[64] 18.5 +# Atom 76[100] 96[138] 60 +# Pentium 115 150 77 +# +# Version 4.1 switches to compact S-box even in key schedule setup. +# +# Version 4.2 prefetches compact S-box in every SSE round or in other +# words every cache-line is *guaranteed* to be accessed within ~50 +# cycles window. Why just SSE? Because it's needed on hyper-threading +# CPU! Which is also why it's prefetched with 64 byte stride. Best +# part is that it has no negative effect on performance:-) +# +# Version 4.3 implements switch between compact and non-compact block +# functions in AES_cbc_encrypt depending on how much data was asked +# to be processed in one stroke. +# +###################################################################### +# Timing attacks are classified in two classes: synchronous when +# attacker consciously initiates cryptographic operation and collects +# timing data of various character afterwards, and asynchronous when +# malicious code is executed on same CPU simultaneously with AES, +# instruments itself and performs statistical analysis of this data. +# +# As far as synchronous attacks go the root to the AES timing +# vulnerability is twofold. Firstly, of 256 S-box elements at most 160 +# are referred to in single 128-bit block operation. Well, in C +# implementation with 4 distinct tables it's actually as little as 40 +# references per 256 elements table, but anyway... Secondly, even +# though S-box elements are clustered into smaller amount of cache- +# lines, smaller than 160 and even 40, it turned out that for certain +# plain-text pattern[s] or simply put chosen plain-text and given key +# few cache-lines remain unaccessed during block operation. Now, if +# attacker can figure out this access pattern, he can deduct the key +# [or at least part of it]. The natural way to mitigate this kind of +# attacks is to minimize the amount of cache-lines in S-box and/or +# prefetch them to ensure that every one is accessed for more uniform +# timing. But note that *if* plain-text was concealed in such way that +# input to block function is distributed *uniformly*, then attack +# wouldn't apply. Now note that some encryption modes, most notably +# CBC, do mask the plain-text in this exact way [secure cipher output +# is distributed uniformly]. Yes, one still might find input that +# would reveal the information about given key, but if amount of +# candidate inputs to be tried is larger than amount of possible key +# combinations then attack becomes infeasible. This is why revised +# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk +# of data is to be processed in one stroke. The current size limit of +# 512 bytes is chosen to provide same [diminishingly low] probability +# for cache-line to remain untouched in large chunk operation with +# large S-box as for single block operation with compact S-box and +# surely needs more careful consideration... +# +# As for asynchronous attacks. There are two flavours: attacker code +# being interleaved with AES on hyper-threading CPU at *instruction* +# level, and two processes time sharing single core. As for latter. +# Two vectors. 1. Given that attacker process has higher priority, +# yield execution to process performing AES just before timer fires +# off the scheduler, immediately regain control of CPU and analyze the +# cache state. For this attack to be efficient attacker would have to +# effectively slow down the operation by several *orders* of magnitude, +# by ratio of time slice to duration of handful of AES rounds, which +# unlikely to remain unnoticed. Not to mention that this also means +# that he would spend correspondingly more time to collect enough +# statistical data to mount the attack. It's probably appropriate to +# say that if adversary reckons that this attack is beneficial and +# risks to be noticed, you probably have larger problems having him +# mere opportunity. In other words suggested code design expects you +# to preclude/mitigate this attack by overall system security design. +# 2. Attacker manages to make his code interrupt driven. In order for +# this kind of attack to be feasible, interrupt rate has to be high +# enough, again comparable to duration of handful of AES rounds. But +# is there interrupt source of such rate? Hardly, not even 1Gbps NIC +# generates interrupts at such raging rate... +# +# And now back to the former, hyper-threading CPU or more specifically +# Intel P4. Recall that asynchronous attack implies that malicious +# code instruments itself. And naturally instrumentation granularity +# has be noticeably lower than duration of codepath accessing S-box. +# Given that all cache-lines are accessed during that time that is. +# Current implementation accesses *all* cache-lines within ~50 cycles +# window, which is actually *less* than RDTSC latency on Intel P4! + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86asm.pl"; + +$output = pop and open STDOUT,">$output"; + +&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); +&static_label("AES_Te"); +&static_label("AES_Td"); + +$s0="eax"; +$s1="ebx"; +$s2="ecx"; +$s3="edx"; +$key="edi"; +$acc="esi"; +$tbl="ebp"; + +# stack frame layout in _[x86|sse]_AES_* routines, frame is allocated +# by caller +$__ra=&DWP(0,"esp"); # return address +$__s0=&DWP(4,"esp"); # s0 backing store +$__s1=&DWP(8,"esp"); # s1 backing store +$__s2=&DWP(12,"esp"); # s2 backing store +$__s3=&DWP(16,"esp"); # s3 backing store +$__key=&DWP(20,"esp"); # pointer to key schedule +$__end=&DWP(24,"esp"); # pointer to end of key schedule +$__tbl=&DWP(28,"esp"); # %ebp backing store + +# stack frame layout in AES_[en|crypt] routines, which differs from +# above by 4 and overlaps by %ebp backing store +$_tbl=&DWP(24,"esp"); +$_esp=&DWP(28,"esp"); + +sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } } + +$speed_limit=512; # chunks smaller than $speed_limit are + # processed with compact routine in CBC mode +$small_footprint=1; # $small_footprint=1 code is ~5% slower [on + # recent µ-archs], but ~5 times smaller! + # I favor compact code to minimize cache + # contention and in hope to "collect" 5% back + # in real-life applications... + +$vertical_spin=0; # shift "vertically" defaults to 0, because of + # its proof-of-concept status... +# Note that there is no decvert(), as well as last encryption round is +# performed with "horizontal" shifts. This is because this "vertical" +# implementation [one which groups shifts on a given $s[i] to form a +# "column," unlike "horizontal" one, which groups shifts on different +# $s[i] to form a "row"] is work in progress. It was observed to run +# few percents faster on Intel cores, but not AMD. On AMD K8 core it's +# whole 12% slower:-( So we face a trade-off... Shall it be resolved +# some day? Till then the code is considered experimental and by +# default remains dormant... + +sub encvert() +{ my ($te,@s) = @_; + my ($v0,$v1) = ($acc,$key); + + &mov ($v0,$s[3]); # copy s3 + &mov (&DWP(4,"esp"),$s[2]); # save s2 + &mov ($v1,$s[0]); # copy s0 + &mov (&DWP(8,"esp"),$s[1]); # save s1 + + &movz ($s[2],&HB($s[0])); + &and ($s[0],0xFF); + &mov ($s[0],&DWP(0,$te,$s[0],8)); # s0>>0 + &shr ($v1,16); + &mov ($s[3],&DWP(3,$te,$s[2],8)); # s0>>8 + &movz ($s[1],&HB($v1)); + &and ($v1,0xFF); + &mov ($s[2],&DWP(2,$te,$v1,8)); # s0>>16 + &mov ($v1,$v0); + &mov ($s[1],&DWP(1,$te,$s[1],8)); # s0>>24 + + &and ($v0,0xFF); + &xor ($s[3],&DWP(0,$te,$v0,8)); # s3>>0 + &movz ($v0,&HB($v1)); + &shr ($v1,16); + &xor ($s[2],&DWP(3,$te,$v0,8)); # s3>>8 + &movz ($v0,&HB($v1)); + &and ($v1,0xFF); + &xor ($s[1],&DWP(2,$te,$v1,8)); # s3>>16 + &mov ($v1,&DWP(4,"esp")); # restore s2 + &xor ($s[0],&DWP(1,$te,$v0,8)); # s3>>24 + + &mov ($v0,$v1); + &and ($v1,0xFF); + &xor ($s[2],&DWP(0,$te,$v1,8)); # s2>>0 + &movz ($v1,&HB($v0)); + &shr ($v0,16); + &xor ($s[1],&DWP(3,$te,$v1,8)); # s2>>8 + &movz ($v1,&HB($v0)); + &and ($v0,0xFF); + &xor ($s[0],&DWP(2,$te,$v0,8)); # s2>>16 + &mov ($v0,&DWP(8,"esp")); # restore s1 + &xor ($s[3],&DWP(1,$te,$v1,8)); # s2>>24 + + &mov ($v1,$v0); + &and ($v0,0xFF); + &xor ($s[1],&DWP(0,$te,$v0,8)); # s1>>0 + &movz ($v0,&HB($v1)); + &shr ($v1,16); + &xor ($s[0],&DWP(3,$te,$v0,8)); # s1>>8 + &movz ($v0,&HB($v1)); + &and ($v1,0xFF); + &xor ($s[3],&DWP(2,$te,$v1,8)); # s1>>16 + &mov ($key,$__key); # reincarnate v1 as key + &xor ($s[2],&DWP(1,$te,$v0,8)); # s1>>24 +} + +# Another experimental routine, which features "horizontal spin," but +# eliminates one reference to stack. Strangely enough runs slower... +sub enchoriz() +{ my ($v0,$v1) = ($key,$acc); + + &movz ($v0,&LB($s0)); # 3, 2, 1, 0* + &rotr ($s2,8); # 8,11,10, 9 + &mov ($v1,&DWP(0,$te,$v0,8)); # 0 + &movz ($v0,&HB($s1)); # 7, 6, 5*, 4 + &rotr ($s3,16); # 13,12,15,14 + &xor ($v1,&DWP(3,$te,$v0,8)); # 5 + &movz ($v0,&HB($s2)); # 8,11,10*, 9 + &rotr ($s0,16); # 1, 0, 3, 2 + &xor ($v1,&DWP(2,$te,$v0,8)); # 10 + &movz ($v0,&HB($s3)); # 13,12,15*,14 + &xor ($v1,&DWP(1,$te,$v0,8)); # 15, t[0] collected + &mov ($__s0,$v1); # t[0] saved + + &movz ($v0,&LB($s1)); # 7, 6, 5, 4* + &shr ($s1,16); # -, -, 7, 6 + &mov ($v1,&DWP(0,$te,$v0,8)); # 4 + &movz ($v0,&LB($s3)); # 13,12,15,14* + &xor ($v1,&DWP(2,$te,$v0,8)); # 14 + &movz ($v0,&HB($s0)); # 1, 0, 3*, 2 + &and ($s3,0xffff0000); # 13,12, -, - + &xor ($v1,&DWP(1,$te,$v0,8)); # 3 + &movz ($v0,&LB($s2)); # 8,11,10, 9* + &or ($s3,$s1); # 13,12, 7, 6 + &xor ($v1,&DWP(3,$te,$v0,8)); # 9, t[1] collected + &mov ($s1,$v1); # s[1]=t[1] + + &movz ($v0,&LB($s0)); # 1, 0, 3, 2* + &shr ($s2,16); # -, -, 8,11 + &mov ($v1,&DWP(2,$te,$v0,8)); # 2 + &movz ($v0,&HB($s3)); # 13,12, 7*, 6 + &xor ($v1,&DWP(1,$te,$v0,8)); # 7 + &movz ($v0,&HB($s2)); # -, -, 8*,11 + &xor ($v1,&DWP(0,$te,$v0,8)); # 8 + &mov ($v0,$s3); + &shr ($v0,24); # 13 + &xor ($v1,&DWP(3,$te,$v0,8)); # 13, t[2] collected + + &movz ($v0,&LB($s2)); # -, -, 8,11* + &shr ($s0,24); # 1* + &mov ($s2,&DWP(1,$te,$v0,8)); # 11 + &xor ($s2,&DWP(3,$te,$s0,8)); # 1 + &mov ($s0,$__s0); # s[0]=t[0] + &movz ($v0,&LB($s3)); # 13,12, 7, 6* + &shr ($s3,16); # , ,13,12 + &xor ($s2,&DWP(2,$te,$v0,8)); # 6 + &mov ($key,$__key); # reincarnate v0 as key + &and ($s3,0xff); # , ,13,12* + &mov ($s3,&DWP(0,$te,$s3,8)); # 12 + &xor ($s3,$s2); # s[2]=t[3] collected + &mov ($s2,$v1); # s[2]=t[2] +} + +# More experimental code... SSE one... Even though this one eliminates +# *all* references to stack, it's not faster... +sub sse_encbody() +{ + &movz ($acc,&LB("eax")); # 0 + &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 0 + &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2 + &movz ("edx",&HB("eax")); # 1 + &mov ("edx",&DWP(3,$tbl,"edx",8)); # 1 + &shr ("eax",16); # 5, 4 + + &movz ($acc,&LB("ebx")); # 10 + &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 10 + &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8 + &movz ($acc,&HB("ebx")); # 11 + &xor ("edx",&DWP(1,$tbl,$acc,8)); # 11 + &shr ("ebx",16); # 15,14 + + &movz ($acc,&HB("eax")); # 5 + &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 5 + &movq ("mm3",QWP(16,$key)); + &movz ($acc,&HB("ebx")); # 15 + &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 15 + &movd ("mm0","ecx"); # t[0] collected + + &movz ($acc,&LB("eax")); # 4 + &mov ("ecx",&DWP(0,$tbl,$acc,8)); # 4 + &movd ("eax","mm2"); # 7, 6, 3, 2 + &movz ($acc,&LB("ebx")); # 14 + &xor ("ecx",&DWP(2,$tbl,$acc,8)); # 14 + &movd ("ebx","mm6"); # 13,12, 9, 8 + + &movz ($acc,&HB("eax")); # 3 + &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 3 + &movz ($acc,&HB("ebx")); # 9 + &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 9 + &movd ("mm1","ecx"); # t[1] collected + + &movz ($acc,&LB("eax")); # 2 + &mov ("ecx",&DWP(2,$tbl,$acc,8)); # 2 + &shr ("eax",16); # 7, 6 + &punpckldq ("mm0","mm1"); # t[0,1] collected + &movz ($acc,&LB("ebx")); # 8 + &xor ("ecx",&DWP(0,$tbl,$acc,8)); # 8 + &shr ("ebx",16); # 13,12 + + &movz ($acc,&HB("eax")); # 7 + &xor ("ecx",&DWP(1,$tbl,$acc,8)); # 7 + &pxor ("mm0","mm3"); + &movz ("eax",&LB("eax")); # 6 + &xor ("edx",&DWP(2,$tbl,"eax",8)); # 6 + &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0 + &movz ($acc,&HB("ebx")); # 13 + &xor ("ecx",&DWP(3,$tbl,$acc,8)); # 13 + &xor ("ecx",&DWP(24,$key)); # t[2] + &movd ("mm4","ecx"); # t[2] collected + &movz ("ebx",&LB("ebx")); # 12 + &xor ("edx",&DWP(0,$tbl,"ebx",8)); # 12 + &shr ("ecx",16); + &movd ("eax","mm1"); # 5, 4, 1, 0 + &mov ("ebx",&DWP(28,$key)); # t[3] + &xor ("ebx","edx"); + &movd ("mm5","ebx"); # t[3] collected + &and ("ebx",0xffff0000); + &or ("ebx","ecx"); + + &punpckldq ("mm4","mm5"); # t[2,3] collected +} + +###################################################################### +# "Compact" block function +###################################################################### + +sub enccompact() +{ my $Fn = \&mov; + while ($#_>5) { pop(@_); $Fn=sub{}; } + my ($i,$te,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # $Fn is used in first compact round and its purpose is to + # void restoration of some values from stack, so that after + # 4xenccompact with extra argument $key value is left there... + if ($i==3) { &$Fn ($key,$__key); }##%edx + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + if ($i==1) { &shr ($s[0],16); }#%ebx[1] + if ($i==2) { &shr ($s[0],24); }#%ecx[2] + &movz ($out,&BP(-128,$te,$out,1)); + + if ($i==3) { $tmp=$s[1]; }##%eax + &movz ($tmp,&HB($s[1])); + &movz ($tmp,&BP(-128,$te,$tmp,1)); + &shl ($tmp,8); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx + else { &mov ($tmp,$s[2]); + &shr ($tmp,16); } + if ($i==2) { &and ($s[1],0xFF); }#%edx[2] + &and ($tmp,0xFF); + &movz ($tmp,&BP(-128,$te,$tmp,1)); + &shl ($tmp,16); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx + elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2] + else { &mov ($tmp,$s[3]); + &shr ($tmp,24); } + &movz ($tmp,&BP(-128,$te,$tmp,1)); + &shl ($tmp,24); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$acc); } + &comment(); +} + +sub enctransform() +{ my @s = ($s0,$s1,$s2,$s3); + my $i = shift; + my $tmp = $tbl; + my $r2 = $key ; + + &and ($tmp,$s[$i]); + &lea ($r2,&DWP(0,$s[$i],$s[$i])); + &mov ($acc,$tmp); + &shr ($tmp,7); + &and ($r2,0xfefefefe); + &sub ($acc,$tmp); + &mov ($tmp,$s[$i]); + &and ($acc,0x1b1b1b1b); + &rotr ($tmp,16); + &xor ($acc,$r2); # r2 + &mov ($r2,$s[$i]); + + &xor ($s[$i],$acc); # r0 ^ r2 + &rotr ($r2,16+8); + &xor ($acc,$tmp); + &rotl ($s[$i],24); + &xor ($acc,$r2); + &mov ($tmp,0x80808080) if ($i!=1); + &xor ($s[$i],$acc); # ROTATE(r2^r0,24) ^ r2 +} + +&function_begin_B("_x86_AES_encrypt_compact"); + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + # prefetch Te4 + &mov ($key,&DWP(0-128,$tbl)); + &mov ($acc,&DWP(32-128,$tbl)); + &mov ($key,&DWP(64-128,$tbl)); + &mov ($acc,&DWP(96-128,$tbl)); + &mov ($key,&DWP(128-128,$tbl)); + &mov ($acc,&DWP(160-128,$tbl)); + &mov ($key,&DWP(192-128,$tbl)); + &mov ($acc,&DWP(224-128,$tbl)); + + &set_label("loop",16); + + &enccompact(0,$tbl,$s0,$s1,$s2,$s3,1); + &enccompact(1,$tbl,$s1,$s2,$s3,$s0,1); + &enccompact(2,$tbl,$s2,$s3,$s0,$s1,1); + &enccompact(3,$tbl,$s3,$s0,$s1,$s2,1); + &mov ($tbl,0x80808080); + &enctransform(2); + &enctransform(3); + &enctransform(0); + &enctransform(1); + &mov ($key,$__key); + &mov ($tbl,$__tbl); + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + + &enccompact(0,$tbl,$s0,$s1,$s2,$s3); + &enccompact(1,$tbl,$s1,$s2,$s3,$s0); + &enccompact(2,$tbl,$s2,$s3,$s0,$s1); + &enccompact(3,$tbl,$s3,$s0,$s1,$s2); + + &xor ($s0,&DWP(16,$key)); + &xor ($s1,&DWP(20,$key)); + &xor ($s2,&DWP(24,$key)); + &xor ($s3,&DWP(28,$key)); + + &ret (); +&function_end_B("_x86_AES_encrypt_compact"); + +###################################################################### +# "Compact" SSE block function. +###################################################################### +# +# Performance is not actually extraordinary in comparison to pure +# x86 code. In particular encrypt performance is virtually the same. +# Decrypt performance on the other hand is 15-20% better on newer +# µ-archs [but we're thankful for *any* improvement here], and ~50% +# better on PIII:-) And additionally on the pros side this code +# eliminates redundant references to stack and thus relieves/ +# minimizes the pressure on the memory bus. +# +# MMX register layout lsb +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# | mm4 | mm0 | +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# | s3 | s2 | s1 | s0 | +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| +# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +# +# Indexes translate as s[N/4]>>(8*(N%4)), e.g. 5 means s1>>8. +# In this terms encryption and decryption "compact" permutation +# matrices can be depicted as following: +# +# encryption lsb # decryption lsb +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t0 || 15 | 10 | 5 | 0 | # | t0 || 7 | 10 | 13 | 0 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t1 || 3 | 14 | 9 | 4 | # | t1 || 11 | 14 | 1 | 4 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t2 || 7 | 2 | 13 | 8 | # | t2 || 15 | 2 | 5 | 8 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# | t3 || 11 | 6 | 1 | 12 | # | t3 || 3 | 6 | 9 | 12 | +# +----++----+----+----+----+ # +----++----+----+----+----+ +# +###################################################################### +# Why not xmm registers? Short answer. It was actually tested and +# was not any faster, but *contrary*, most notably on Intel CPUs. +# Longer answer. Main advantage of using mm registers is that movd +# latency is lower, especially on Intel P4. While arithmetic +# instructions are twice as many, they can be scheduled every cycle +# and not every second one when they are operating on xmm register, +# so that "arithmetic throughput" remains virtually the same. And +# finally the code can be executed even on elder SSE-only CPUs:-) + +sub sse_enccompact() +{ + &pshufw ("mm1","mm0",0x08); # 5, 4, 1, 0 + &pshufw ("mm5","mm4",0x0d); # 15,14,11,10 + &movd ("eax","mm1"); # 5, 4, 1, 0 + &movd ("ebx","mm5"); # 15,14,11,10 + &mov ($__key,$key); + + &movz ($acc,&LB("eax")); # 0 + &movz ("edx",&HB("eax")); # 1 + &pshufw ("mm2","mm0",0x0d); # 7, 6, 3, 2 + &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0 + &movz ($key,&LB("ebx")); # 10 + &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1 + &shr ("eax",16); # 5, 4 + &shl ("edx",8); # 1 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 10 + &movz ($key,&HB("ebx")); # 11 + &shl ($acc,16); # 10 + &pshufw ("mm6","mm4",0x08); # 13,12, 9, 8 + &or ("ecx",$acc); # 10 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 11 + &movz ($key,&HB("eax")); # 5 + &shl ($acc,24); # 11 + &shr ("ebx",16); # 15,14 + &or ("edx",$acc); # 11 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 5 + &movz ($key,&HB("ebx")); # 15 + &shl ($acc,8); # 5 + &or ("ecx",$acc); # 5 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 15 + &movz ($key,&LB("eax")); # 4 + &shl ($acc,24); # 15 + &or ("ecx",$acc); # 15 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 4 + &movz ($key,&LB("ebx")); # 14 + &movd ("eax","mm2"); # 7, 6, 3, 2 + &movd ("mm0","ecx"); # t[0] collected + &movz ("ecx",&BP(-128,$tbl,$key,1)); # 14 + &movz ($key,&HB("eax")); # 3 + &shl ("ecx",16); # 14 + &movd ("ebx","mm6"); # 13,12, 9, 8 + &or ("ecx",$acc); # 14 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 3 + &movz ($key,&HB("ebx")); # 9 + &shl ($acc,24); # 3 + &or ("ecx",$acc); # 3 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 9 + &movz ($key,&LB("ebx")); # 8 + &shl ($acc,8); # 9 + &shr ("ebx",16); # 13,12 + &or ("ecx",$acc); # 9 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 8 + &movz ($key,&LB("eax")); # 2 + &shr ("eax",16); # 7, 6 + &movd ("mm1","ecx"); # t[1] collected + &movz ("ecx",&BP(-128,$tbl,$key,1)); # 2 + &movz ($key,&HB("eax")); # 7 + &shl ("ecx",16); # 2 + &and ("eax",0xff); # 6 + &or ("ecx",$acc); # 2 + + &punpckldq ("mm0","mm1"); # t[0,1] collected + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 7 + &movz ($key,&HB("ebx")); # 13 + &shl ($acc,24); # 7 + &and ("ebx",0xff); # 12 + &movz ("eax",&BP(-128,$tbl,"eax",1)); # 6 + &or ("ecx",$acc); # 7 + &shl ("eax",16); # 6 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 13 + &or ("edx","eax"); # 6 + &shl ($acc,8); # 13 + &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 12 + &or ("ecx",$acc); # 13 + &or ("edx","ebx"); # 12 + &mov ($key,$__key); + &movd ("mm4","ecx"); # t[2] collected + &movd ("mm5","edx"); # t[3] collected + + &punpckldq ("mm4","mm5"); # t[2,3] collected +} + + if (!$x86only) { +&function_begin_B("_sse_AES_encrypt_compact"); + &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0 + &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8 + + # note that caller is expected to allocate stack frame for me! + &mov ($acc,&DWP(240,$key)); # load key->rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + &mov ($s0,0x1b1b1b1b); # magic constant + &mov (&DWP(8,"esp"),$s0); + &mov (&DWP(12,"esp"),$s0); + + # prefetch Te4 + &mov ($s0,&DWP(0-128,$tbl)); + &mov ($s1,&DWP(32-128,$tbl)); + &mov ($s2,&DWP(64-128,$tbl)); + &mov ($s3,&DWP(96-128,$tbl)); + &mov ($s0,&DWP(128-128,$tbl)); + &mov ($s1,&DWP(160-128,$tbl)); + &mov ($s2,&DWP(192-128,$tbl)); + &mov ($s3,&DWP(224-128,$tbl)); + + &set_label("loop",16); + &sse_enccompact(); + &add ($key,16); + &cmp ($key,$__end); + &ja (&label("out")); + + &movq ("mm2",&QWP(8,"esp")); + &pxor ("mm3","mm3"); &pxor ("mm7","mm7"); + &movq ("mm1","mm0"); &movq ("mm5","mm4"); # r0 + &pcmpgtb("mm3","mm0"); &pcmpgtb("mm7","mm4"); + &pand ("mm3","mm2"); &pand ("mm7","mm2"); + &pshufw ("mm2","mm0",0xb1); &pshufw ("mm6","mm4",0xb1);# ROTATE(r0,16) + &paddb ("mm0","mm0"); &paddb ("mm4","mm4"); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # = r2 + &pshufw ("mm3","mm2",0xb1); &pshufw ("mm7","mm6",0xb1);# r0 + &pxor ("mm1","mm0"); &pxor ("mm5","mm4"); # r0^r2 + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(r0,16) + + &movq ("mm2","mm3"); &movq ("mm6","mm7"); + &pslld ("mm3",8); &pslld ("mm7",8); + &psrld ("mm2",24); &psrld ("mm6",24); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= r0<<8 + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= r0>>24 + + &movq ("mm3","mm1"); &movq ("mm7","mm5"); + &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key)); + &psrld ("mm1",8); &psrld ("mm5",8); + &mov ($s0,&DWP(0-128,$tbl)); + &pslld ("mm3",24); &pslld ("mm7",24); + &mov ($s1,&DWP(64-128,$tbl)); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= (r2^r0)<<8 + &mov ($s2,&DWP(128-128,$tbl)); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= (r2^r0)>>24 + &mov ($s3,&DWP(192-128,$tbl)); + + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); + &jmp (&label("loop")); + + &set_label("out",16); + &pxor ("mm0",&QWP(0,$key)); + &pxor ("mm4",&QWP(8,$key)); + + &ret (); +&function_end_B("_sse_AES_encrypt_compact"); + } + +###################################################################### +# Vanilla block function. +###################################################################### + +sub encstep() +{ my ($i,$te,@s) = @_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # lines marked with #%e?x[i] denote "reordered" instructions... + if ($i==3) { &mov ($key,$__key); }##%edx + else { &mov ($out,$s[0]); + &and ($out,0xFF); } + if ($i==1) { &shr ($s[0],16); }#%ebx[1] + if ($i==2) { &shr ($s[0],24); }#%ecx[2] + &mov ($out,&DWP(0,$te,$out,8)); + + if ($i==3) { $tmp=$s[1]; }##%eax + &movz ($tmp,&HB($s[1])); + &xor ($out,&DWP(3,$te,$tmp,8)); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx + else { &mov ($tmp,$s[2]); + &shr ($tmp,16); } + if ($i==2) { &and ($s[1],0xFF); }#%edx[2] + &and ($tmp,0xFF); + &xor ($out,&DWP(2,$te,$tmp,8)); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx + elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2] + else { &mov ($tmp,$s[3]); + &shr ($tmp,24) } + &xor ($out,&DWP(1,$te,$tmp,8)); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$acc); } + &comment(); +} + +sub enclast() +{ my ($i,$te,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + if ($i==3) { &mov ($key,$__key); }##%edx + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + if ($i==1) { &shr ($s[0],16); }#%ebx[1] + if ($i==2) { &shr ($s[0],24); }#%ecx[2] + &mov ($out,&DWP(2,$te,$out,8)); + &and ($out,0x000000ff); + + if ($i==3) { $tmp=$s[1]; }##%eax + &movz ($tmp,&HB($s[1])); + &mov ($tmp,&DWP(0,$te,$tmp,8)); + &and ($tmp,0x0000ff00); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$__s0); }##%ebx + else { &mov ($tmp,$s[2]); + &shr ($tmp,16); } + if ($i==2) { &and ($s[1],0xFF); }#%edx[2] + &and ($tmp,0xFF); + &mov ($tmp,&DWP(0,$te,$tmp,8)); + &and ($tmp,0x00ff0000); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx + elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2] + else { &mov ($tmp,$s[3]); + &shr ($tmp,24); } + &mov ($tmp,&DWP(2,$te,$tmp,8)); + &and ($tmp,0xff000000); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$acc); } +} + +&function_begin_B("_x86_AES_encrypt"); + if ($vertical_spin) { + # I need high parts of volatile registers to be accessible... + &exch ($s1="edi",$key="ebx"); + &mov ($s2="esi",$acc="ecx"); + } + + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + + if ($small_footprint) { + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + &set_label("loop",16); + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + } + else { + &cmp ($acc,10); + &jle (&label("10rounds")); + &cmp ($acc,12); + &jle (&label("12rounds")); + + &set_label("14rounds",4); + for ($i=1;$i<3;$i++) { + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("12rounds",4); + for ($i=1;$i<3;$i++) { + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("10rounds",4); + for ($i=1;$i<10;$i++) { + if ($vertical_spin) { + &encvert($tbl,$s0,$s1,$s2,$s3); + } else { + &encstep(0,$tbl,$s0,$s1,$s2,$s3); + &encstep(1,$tbl,$s1,$s2,$s3,$s0); + &encstep(2,$tbl,$s2,$s3,$s0,$s1); + &encstep(3,$tbl,$s3,$s0,$s1,$s2); + } + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + } + + if ($vertical_spin) { + # "reincarnate" some registers for "horizontal" spin... + &mov ($s1="ebx",$key="edi"); + &mov ($s2="ecx",$acc="esi"); + } + &enclast(0,$tbl,$s0,$s1,$s2,$s3); + &enclast(1,$tbl,$s1,$s2,$s3,$s0); + &enclast(2,$tbl,$s2,$s3,$s0,$s1); + &enclast(3,$tbl,$s3,$s0,$s1,$s2); + + &add ($key,$small_footprint?16:160); + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &ret (); + +&set_label("AES_Te",64); # Yes! I keep it in the code segment! + &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6); + &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591); + &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56); + &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec); + &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa); + &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb); + &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45); + &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b); + &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c); + &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83); + &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9); + &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a); + &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d); + &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f); + &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df); + &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea); + &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34); + &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b); + &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d); + &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413); + &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1); + &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6); + &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972); + &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85); + &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed); + &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511); + &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe); + &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b); + &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05); + &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1); + &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142); + &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf); + &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3); + &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e); + &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a); + &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6); + &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3); + &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b); + &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428); + &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad); + &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14); + &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8); + &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4); + &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2); + &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda); + &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949); + &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf); + &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810); + &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c); + &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697); + &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e); + &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f); + &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc); + &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c); + &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969); + &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27); + &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122); + &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433); + &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9); + &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5); + &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a); + &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0); + &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e); + &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c); + +#Te4 # four copies of Te4 to choose from to avoid L1 aliasing + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); +#rcon: + &data_word(0x00000001, 0x00000002, 0x00000004, 0x00000008); + &data_word(0x00000010, 0x00000020, 0x00000040, 0x00000080); + &data_word(0x0000001b, 0x00000036, 0x00000000, 0x00000000); + &data_word(0x00000000, 0x00000000, 0x00000000, 0x00000000); +&function_end_B("_x86_AES_encrypt"); + +# void AES_encrypt (const void *inp,void *out,const AES_KEY *key); +&function_begin("AES_encrypt"); + &mov ($acc,&wparam(0)); # load inp + &mov ($key,&wparam(2)); # load key + + &mov ($s0,"esp"); + &sub ("esp",36); + &and ("esp",-64); # align to cache-line + + # place stack frame just "above" the key schedule + &lea ($s1,&DWP(-64-63,$key)); + &sub ($s1,"esp"); + &neg ($s1); + &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp",$s1); + &add ("esp",4); # 4 is reserved for caller's return address + &mov ($_esp,$s0); # save stack pointer + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tbl); + &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if (!$x86only); + &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl)); + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + &lea ($s1,&DWP(768-4,"esp")); + &sub ($s1,$tbl); + &and ($s1,0x300); + &lea ($tbl,&DWP(2048+128,$tbl,$s1)); + + if (!$x86only) { + &bt (&DWP(0,$s0),25); # check for SSE bit + &jnc (&label("x86")); + + &movq ("mm0",&QWP(0,$acc)); + &movq ("mm4",&QWP(8,$acc)); + &call ("_sse_AES_encrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &movq (&QWP(0,$acc),"mm0"); # write output data + &movq (&QWP(8,$acc),"mm4"); + &emms (); + &function_end_A(); + } + &set_label("x86",16); + &mov ($_tbl,$tbl); + &mov ($s0,&DWP(0,$acc)); # load input data + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + &call ("_x86_AES_encrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &mov (&DWP(0,$acc),$s0); # write output data + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); +&function_end("AES_encrypt"); + +#--------------------------------------------------------------------# + +###################################################################### +# "Compact" block function +###################################################################### + +sub deccompact() +{ my $Fn = \&mov; + while ($#_>5) { pop(@_); $Fn=sub{}; } + my ($i,$td,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # $Fn is used in first compact round and its purpose is to + # void restoration of some values from stack, so that after + # 4xdeccompact with extra argument $key, $s0 and $s1 values + # are left there... + if($i==3) { &$Fn ($key,$__key); } + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + &movz ($out,&BP(-128,$td,$out,1)); + + if ($i==3) { $tmp=$s[1]; } + &movz ($tmp,&HB($s[1])); + &movz ($tmp,&BP(-128,$td,$tmp,1)); + &shl ($tmp,8); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); } + else { mov ($tmp,$s[2]); } + &shr ($tmp,16); + &and ($tmp,0xFF); + &movz ($tmp,&BP(-128,$td,$tmp,1)); + &shl ($tmp,16); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &$Fn ($s[2],$__s1); } + else { &mov ($tmp,$s[3]); } + &shr ($tmp,24); + &movz ($tmp,&BP(-128,$td,$tmp,1)); + &shl ($tmp,24); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &$Fn ($s[3],$__s0); } +} + +# must be called with 2,3,0,1 as argument sequence!!! +sub dectransform() +{ my @s = ($s0,$s1,$s2,$s3); + my $i = shift; + my $tmp = $key; + my $tp2 = @s[($i+2)%4]; $tp2 = @s[2] if ($i==1); + my $tp4 = @s[($i+3)%4]; $tp4 = @s[3] if ($i==1); + my $tp8 = $tbl; + + &mov ($tmp,0x80808080); + &and ($tmp,$s[$i]); + &mov ($acc,$tmp); + &shr ($tmp,7); + &lea ($tp2,&DWP(0,$s[$i],$s[$i])); + &sub ($acc,$tmp); + &and ($tp2,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp2); + &mov ($acc,$tmp); + &shr ($tmp,7); + &lea ($tp4,&DWP(0,$tp2,$tp2)); + &sub ($acc,$tmp); + &and ($tp4,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$s[$i]); # tp2^tp1 + &xor ($tp4,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp4); + &mov ($acc,$tmp); + &shr ($tmp,7); + &lea ($tp8,&DWP(0,$tp4,$tp4)); + &sub ($acc,$tmp); + &and ($tp8,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp4,$s[$i]); # tp4^tp1 + &rotl ($s[$i],8); # = ROTATE(tp1,8) + &xor ($tp8,$acc); + + &xor ($s[$i],$tp2); + &xor ($tp2,$tp8); + &xor ($s[$i],$tp4); + &xor ($tp4,$tp8); + &rotl ($tp2,24); + &xor ($s[$i],$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1) + &rotl ($tp4,16); + &xor ($s[$i],$tp2); # ^= ROTATE(tp8^tp2^tp1,24) + &rotl ($tp8,8); + &xor ($s[$i],$tp4); # ^= ROTATE(tp8^tp4^tp1,16) + &mov ($s[0],$__s0) if($i==2); #prefetch $s0 + &mov ($s[1],$__s1) if($i==3); #prefetch $s1 + &mov ($s[2],$__s2) if($i==1); + &xor ($s[$i],$tp8); # ^= ROTATE(tp8,8) + + &mov ($s[3],$__s3) if($i==1); + &mov (&DWP(4+4*$i,"esp"),$s[$i]) if($i>=2); +} + +&function_begin_B("_x86_AES_decrypt_compact"); + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + # prefetch Td4 + &mov ($key,&DWP(0-128,$tbl)); + &mov ($acc,&DWP(32-128,$tbl)); + &mov ($key,&DWP(64-128,$tbl)); + &mov ($acc,&DWP(96-128,$tbl)); + &mov ($key,&DWP(128-128,$tbl)); + &mov ($acc,&DWP(160-128,$tbl)); + &mov ($key,&DWP(192-128,$tbl)); + &mov ($acc,&DWP(224-128,$tbl)); + + &set_label("loop",16); + + &deccompact(0,$tbl,$s0,$s3,$s2,$s1,1); + &deccompact(1,$tbl,$s1,$s0,$s3,$s2,1); + &deccompact(2,$tbl,$s2,$s1,$s0,$s3,1); + &deccompact(3,$tbl,$s3,$s2,$s1,$s0,1); + &dectransform(2); + &dectransform(3); + &dectransform(0); + &dectransform(1); + &mov ($key,$__key); + &mov ($tbl,$__tbl); + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + + &deccompact(0,$tbl,$s0,$s3,$s2,$s1); + &deccompact(1,$tbl,$s1,$s0,$s3,$s2); + &deccompact(2,$tbl,$s2,$s1,$s0,$s3); + &deccompact(3,$tbl,$s3,$s2,$s1,$s0); + + &xor ($s0,&DWP(16,$key)); + &xor ($s1,&DWP(20,$key)); + &xor ($s2,&DWP(24,$key)); + &xor ($s3,&DWP(28,$key)); + + &ret (); +&function_end_B("_x86_AES_decrypt_compact"); + +###################################################################### +# "Compact" SSE block function. +###################################################################### + +sub sse_deccompact() +{ + &pshufw ("mm1","mm0",0x0c); # 7, 6, 1, 0 + &pshufw ("mm5","mm4",0x09); # 13,12,11,10 + &movd ("eax","mm1"); # 7, 6, 1, 0 + &movd ("ebx","mm5"); # 13,12,11,10 + &mov ($__key,$key); + + &movz ($acc,&LB("eax")); # 0 + &movz ("edx",&HB("eax")); # 1 + &pshufw ("mm2","mm0",0x06); # 3, 2, 5, 4 + &movz ("ecx",&BP(-128,$tbl,$acc,1)); # 0 + &movz ($key,&LB("ebx")); # 10 + &movz ("edx",&BP(-128,$tbl,"edx",1)); # 1 + &shr ("eax",16); # 7, 6 + &shl ("edx",8); # 1 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 10 + &movz ($key,&HB("ebx")); # 11 + &shl ($acc,16); # 10 + &pshufw ("mm6","mm4",0x03); # 9, 8,15,14 + &or ("ecx",$acc); # 10 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 11 + &movz ($key,&HB("eax")); # 7 + &shl ($acc,24); # 11 + &shr ("ebx",16); # 13,12 + &or ("edx",$acc); # 11 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 7 + &movz ($key,&HB("ebx")); # 13 + &shl ($acc,24); # 7 + &or ("ecx",$acc); # 7 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 13 + &movz ($key,&LB("eax")); # 6 + &shl ($acc,8); # 13 + &movd ("eax","mm2"); # 3, 2, 5, 4 + &or ("ecx",$acc); # 13 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 6 + &movz ($key,&LB("ebx")); # 12 + &shl ($acc,16); # 6 + &movd ("ebx","mm6"); # 9, 8,15,14 + &movd ("mm0","ecx"); # t[0] collected + &movz ("ecx",&BP(-128,$tbl,$key,1)); # 12 + &movz ($key,&LB("eax")); # 4 + &or ("ecx",$acc); # 12 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 4 + &movz ($key,&LB("ebx")); # 14 + &or ("edx",$acc); # 4 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 14 + &movz ($key,&HB("eax")); # 5 + &shl ($acc,16); # 14 + &shr ("eax",16); # 3, 2 + &or ("edx",$acc); # 14 + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 5 + &movz ($key,&HB("ebx")); # 15 + &shr ("ebx",16); # 9, 8 + &shl ($acc,8); # 5 + &movd ("mm1","edx"); # t[1] collected + &movz ("edx",&BP(-128,$tbl,$key,1)); # 15 + &movz ($key,&HB("ebx")); # 9 + &shl ("edx",24); # 15 + &and ("ebx",0xff); # 8 + &or ("edx",$acc); # 15 + + &punpckldq ("mm0","mm1"); # t[0,1] collected + + &movz ($acc,&BP(-128,$tbl,$key,1)); # 9 + &movz ($key,&LB("eax")); # 2 + &shl ($acc,8); # 9 + &movz ("eax",&HB("eax")); # 3 + &movz ("ebx",&BP(-128,$tbl,"ebx",1)); # 8 + &or ("ecx",$acc); # 9 + &movz ($acc,&BP(-128,$tbl,$key,1)); # 2 + &or ("edx","ebx"); # 8 + &shl ($acc,16); # 2 + &movz ("eax",&BP(-128,$tbl,"eax",1)); # 3 + &or ("edx",$acc); # 2 + &shl ("eax",24); # 3 + &or ("ecx","eax"); # 3 + &mov ($key,$__key); + &movd ("mm4","edx"); # t[2] collected + &movd ("mm5","ecx"); # t[3] collected + + &punpckldq ("mm4","mm5"); # t[2,3] collected +} + + if (!$x86only) { +&function_begin_B("_sse_AES_decrypt_compact"); + &pxor ("mm0",&QWP(0,$key)); # 7, 6, 5, 4, 3, 2, 1, 0 + &pxor ("mm4",&QWP(8,$key)); # 15,14,13,12,11,10, 9, 8 + + # note that caller is expected to allocate stack frame for me! + &mov ($acc,&DWP(240,$key)); # load key->rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + + &mov ($s0,0x1b1b1b1b); # magic constant + &mov (&DWP(8,"esp"),$s0); + &mov (&DWP(12,"esp"),$s0); + + # prefetch Td4 + &mov ($s0,&DWP(0-128,$tbl)); + &mov ($s1,&DWP(32-128,$tbl)); + &mov ($s2,&DWP(64-128,$tbl)); + &mov ($s3,&DWP(96-128,$tbl)); + &mov ($s0,&DWP(128-128,$tbl)); + &mov ($s1,&DWP(160-128,$tbl)); + &mov ($s2,&DWP(192-128,$tbl)); + &mov ($s3,&DWP(224-128,$tbl)); + + &set_label("loop",16); + &sse_deccompact(); + &add ($key,16); + &cmp ($key,$__end); + &ja (&label("out")); + + # ROTATE(x^y,N) == ROTATE(x,N)^ROTATE(y,N) + &movq ("mm3","mm0"); &movq ("mm7","mm4"); + &movq ("mm2","mm0",1); &movq ("mm6","mm4",1); + &movq ("mm1","mm0"); &movq ("mm5","mm4"); + &pshufw ("mm0","mm0",0xb1); &pshufw ("mm4","mm4",0xb1);# = ROTATE(tp0,16) + &pslld ("mm2",8); &pslld ("mm6",8); + &psrld ("mm3",8); &psrld ("mm7",8); + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<8 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>8 + &pslld ("mm2",16); &pslld ("mm6",16); + &psrld ("mm3",16); &psrld ("mm7",16); + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp0<<24 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp0>>24 + + &movq ("mm3",&QWP(8,"esp")); + &pxor ("mm2","mm2"); &pxor ("mm6","mm6"); + &pcmpgtb("mm2","mm1"); &pcmpgtb("mm6","mm5"); + &pand ("mm2","mm3"); &pand ("mm6","mm3"); + &paddb ("mm1","mm1"); &paddb ("mm5","mm5"); + &pxor ("mm1","mm2"); &pxor ("mm5","mm6"); # tp2 + &movq ("mm3","mm1"); &movq ("mm7","mm5"); + &movq ("mm2","mm1"); &movq ("mm6","mm5"); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp2 + &pslld ("mm3",24); &pslld ("mm7",24); + &psrld ("mm2",8); &psrld ("mm6",8); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp2<<24 + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= tp2>>8 + + &movq ("mm2",&QWP(8,"esp")); + &pxor ("mm3","mm3"); &pxor ("mm7","mm7"); + &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5"); + &pand ("mm3","mm2"); &pand ("mm7","mm2"); + &paddb ("mm1","mm1"); &paddb ("mm5","mm5"); + &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp4 + &pshufw ("mm3","mm1",0xb1); &pshufw ("mm7","mm5",0xb1); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp4 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16) + + &pxor ("mm3","mm3"); &pxor ("mm7","mm7"); + &pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5"); + &pand ("mm3","mm2"); &pand ("mm7","mm2"); + &paddb ("mm1","mm1"); &paddb ("mm5","mm5"); + &pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp8 + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8 + &movq ("mm3","mm1"); &movq ("mm7","mm5"); + &pshufw ("mm2","mm1",0xb1); &pshufw ("mm6","mm5",0xb1); + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); # ^= ROTATE(tp8,16) + &pslld ("mm1",8); &pslld ("mm5",8); + &psrld ("mm3",8); &psrld ("mm7",8); + &movq ("mm2",&QWP(0,$key)); &movq ("mm6",&QWP(8,$key)); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<8 + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>8 + &mov ($s0,&DWP(0-128,$tbl)); + &pslld ("mm1",16); &pslld ("mm5",16); + &mov ($s1,&DWP(64-128,$tbl)); + &psrld ("mm3",16); &psrld ("mm7",16); + &mov ($s2,&DWP(128-128,$tbl)); + &pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp8<<24 + &mov ($s3,&DWP(192-128,$tbl)); + &pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= tp8>>24 + + &pxor ("mm0","mm2"); &pxor ("mm4","mm6"); + &jmp (&label("loop")); + + &set_label("out",16); + &pxor ("mm0",&QWP(0,$key)); + &pxor ("mm4",&QWP(8,$key)); + + &ret (); +&function_end_B("_sse_AES_decrypt_compact"); + } + +###################################################################### +# Vanilla block function. +###################################################################### + +sub decstep() +{ my ($i,$td,@s) = @_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + # no instructions are reordered, as performance appears + # optimal... or rather that all attempts to reorder didn't + # result in better performance [which by the way is not a + # bit lower than encryption]. + if($i==3) { &mov ($key,$__key); } + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + &mov ($out,&DWP(0,$td,$out,8)); + + if ($i==3) { $tmp=$s[1]; } + &movz ($tmp,&HB($s[1])); + &xor ($out,&DWP(3,$td,$tmp,8)); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); } + else { &mov ($tmp,$s[2]); } + &shr ($tmp,16); + &and ($tmp,0xFF); + &xor ($out,&DWP(2,$td,$tmp,8)); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); } + else { &mov ($tmp,$s[3]); } + &shr ($tmp,24); + &xor ($out,&DWP(1,$td,$tmp,8)); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$__s0); } + &comment(); +} + +sub declast() +{ my ($i,$td,@s)=@_; + my $tmp = $key; + my $out = $i==3?$s[0]:$acc; + + if($i==0) { &lea ($td,&DWP(2048+128,$td)); + &mov ($tmp,&DWP(0-128,$td)); + &mov ($acc,&DWP(32-128,$td)); + &mov ($tmp,&DWP(64-128,$td)); + &mov ($acc,&DWP(96-128,$td)); + &mov ($tmp,&DWP(128-128,$td)); + &mov ($acc,&DWP(160-128,$td)); + &mov ($tmp,&DWP(192-128,$td)); + &mov ($acc,&DWP(224-128,$td)); + &lea ($td,&DWP(-128,$td)); } + if($i==3) { &mov ($key,$__key); } + else { &mov ($out,$s[0]); } + &and ($out,0xFF); + &movz ($out,&BP(0,$td,$out,1)); + + if ($i==3) { $tmp=$s[1]; } + &movz ($tmp,&HB($s[1])); + &movz ($tmp,&BP(0,$td,$tmp,1)); + &shl ($tmp,8); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[2]; &mov ($s[1],$acc); } + else { mov ($tmp,$s[2]); } + &shr ($tmp,16); + &and ($tmp,0xFF); + &movz ($tmp,&BP(0,$td,$tmp,1)); + &shl ($tmp,16); + &xor ($out,$tmp); + + if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); } + else { &mov ($tmp,$s[3]); } + &shr ($tmp,24); + &movz ($tmp,&BP(0,$td,$tmp,1)); + &shl ($tmp,24); + &xor ($out,$tmp); + if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); } + if ($i==3) { &mov ($s[3],$__s0); + &lea ($td,&DWP(-2048,$td)); } +} + +&function_begin_B("_x86_AES_decrypt"); + # note that caller is expected to allocate stack frame for me! + &mov ($__key,$key); # save key + + &xor ($s0,&DWP(0,$key)); # xor with key + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($acc,&DWP(240,$key)); # load key->rounds + + if ($small_footprint) { + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov ($__end,$acc); # end of key schedule + &set_label("loop",16); + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &add ($key,16); # advance rd_key + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + &cmp ($key,$__end); + &mov ($__key,$key); + &jb (&label("loop")); + } + else { + &cmp ($acc,10); + &jle (&label("10rounds")); + &cmp ($acc,12); + &jle (&label("12rounds")); + + &set_label("14rounds",4); + for ($i=1;$i<3;$i++) { + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("12rounds",4); + for ($i=1;$i<3;$i++) { + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + &add ($key,32); + &mov ($__key,$key); # advance rd_key + &set_label("10rounds",4); + for ($i=1;$i<10;$i++) { + &decstep(0,$tbl,$s0,$s3,$s2,$s1); + &decstep(1,$tbl,$s1,$s0,$s3,$s2); + &decstep(2,$tbl,$s2,$s1,$s0,$s3); + &decstep(3,$tbl,$s3,$s2,$s1,$s0); + &xor ($s0,&DWP(16*$i+0,$key)); + &xor ($s1,&DWP(16*$i+4,$key)); + &xor ($s2,&DWP(16*$i+8,$key)); + &xor ($s3,&DWP(16*$i+12,$key)); + } + } + + &declast(0,$tbl,$s0,$s3,$s2,$s1); + &declast(1,$tbl,$s1,$s0,$s3,$s2); + &declast(2,$tbl,$s2,$s1,$s0,$s3); + &declast(3,$tbl,$s3,$s2,$s1,$s0); + + &add ($key,$small_footprint?16:160); + &xor ($s0,&DWP(0,$key)); + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &ret (); + +&set_label("AES_Td",64); # Yes! I keep it in the code segment! + &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a); + &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b); + &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5); + &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5); + &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d); + &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b); + &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295); + &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e); + &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927); + &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d); + &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362); + &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9); + &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52); + &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566); + &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3); + &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed); + &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e); + &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4); + &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4); + &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd); + &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d); + &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060); + &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967); + &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879); + &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000); + &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c); + &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36); + &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624); + &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b); + &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c); + &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12); + &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14); + &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3); + &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b); + &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8); + &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684); + &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7); + &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177); + &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947); + &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322); + &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498); + &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f); + &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54); + &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382); + &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf); + &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb); + &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83); + &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef); + &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029); + &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235); + &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733); + &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117); + &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4); + &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546); + &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb); + &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d); + &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb); + &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a); + &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773); + &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478); + &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2); + &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff); + &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664); + &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0); + +#Td4: # four copies of Td4 to choose from to avoid L1 aliasing + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); + + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +&function_end_B("_x86_AES_decrypt"); + +# void AES_decrypt (const void *inp,void *out,const AES_KEY *key); +&function_begin("AES_decrypt"); + &mov ($acc,&wparam(0)); # load inp + &mov ($key,&wparam(2)); # load key + + &mov ($s0,"esp"); + &sub ("esp",36); + &and ("esp",-64); # align to cache-line + + # place stack frame just "above" the key schedule + &lea ($s1,&DWP(-64-63,$key)); + &sub ($s1,"esp"); + &neg ($s1); + &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line + &sub ("esp",$s1); + &add ("esp",4); # 4 is reserved for caller's return address + &mov ($_esp,$s0); # save stack pointer + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tbl); + &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only); + &lea ($tbl,&DWP(&label("AES_Td")."-".&label("pic_point"),$tbl)); + + # pick Td4 copy which can't "overlap" with stack frame or key schedule + &lea ($s1,&DWP(768-4,"esp")); + &sub ($s1,$tbl); + &and ($s1,0x300); + &lea ($tbl,&DWP(2048+128,$tbl,$s1)); + + if (!$x86only) { + &bt (&DWP(0,$s0),25); # check for SSE bit + &jnc (&label("x86")); + + &movq ("mm0",&QWP(0,$acc)); + &movq ("mm4",&QWP(8,$acc)); + &call ("_sse_AES_decrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &movq (&QWP(0,$acc),"mm0"); # write output data + &movq (&QWP(8,$acc),"mm4"); + &emms (); + &function_end_A(); + } + &set_label("x86",16); + &mov ($_tbl,$tbl); + &mov ($s0,&DWP(0,$acc)); # load input data + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + &call ("_x86_AES_decrypt_compact"); + &mov ("esp",$_esp); # restore stack pointer + &mov ($acc,&wparam(1)); # load out + &mov (&DWP(0,$acc),$s0); # write output data + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); +&function_end("AES_decrypt"); + +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -4(%esp) # return address 0(%esp) +# 0(%esp) # s0 backing store 4(%esp) +# 4(%esp) # s1 backing store 8(%esp) +# 8(%esp) # s2 backing store 12(%esp) +# 12(%esp) # s3 backing store 16(%esp) +# 16(%esp) # key backup 20(%esp) +# 20(%esp) # end of key schedule 24(%esp) +# 24(%esp) # %ebp backup 28(%esp) +# 28(%esp) # %esp backup +my $_inp=&DWP(32,"esp"); # copy of wparam(0) +my $_out=&DWP(36,"esp"); # copy of wparam(1) +my $_len=&DWP(40,"esp"); # copy of wparam(2) +my $_key=&DWP(44,"esp"); # copy of wparam(3) +my $_ivp=&DWP(48,"esp"); # copy of wparam(4) +my $_tmp=&DWP(52,"esp"); # volatile variable +# +my $ivec=&DWP(60,"esp"); # ivec[16] +my $aes_key=&DWP(76,"esp"); # copy of aes_key +my $mark=&DWP(76+240,"esp"); # copy of aes_key->rounds + +&function_begin("AES_cbc_encrypt"); + &mov ($s2 eq "ecx"? $s2 : "",&wparam(2)); # load len + &cmp ($s2,0); + &je (&label("drop_out")); + + &call (&label("pic_point")); # make it PIC! + &set_label("pic_point"); + &blindpop($tbl); + &picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only); + + &cmp (&wparam(5),0); + &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl)); + &jne (&label("picked_te")); + &lea ($tbl,&DWP(&label("AES_Td")."-".&label("AES_Te"),$tbl)); + &set_label("picked_te"); + + # one can argue if this is required + &pushf (); + &cld (); + + &cmp ($s2,$speed_limit); + &jb (&label("slow_way")); + &test ($s2,15); + &jnz (&label("slow_way")); + if (!$x86only) { + &bt (&DWP(0,$s0),28); # check for hyper-threading bit + &jc (&label("slow_way")); + } + # pre-allocate aligned stack frame... + &lea ($acc,&DWP(-80-244,"esp")); + &and ($acc,-64); + + # ... and make sure it doesn't alias with $tbl modulo 4096 + &mov ($s0,$tbl); + &lea ($s1,&DWP(2048+256,$tbl)); + &mov ($s3,$acc); + &and ($s0,0xfff); # s = %ebp&0xfff + &and ($s1,0xfff); # e = (%ebp+2048+256)&0xfff + &and ($s3,0xfff); # p = %esp&0xfff + + &cmp ($s3,$s1); # if (p>=e) %esp =- (p-e); + &jb (&label("tbl_break_out")); + &sub ($s3,$s1); + &sub ($acc,$s3); + &jmp (&label("tbl_ok")); + &set_label("tbl_break_out",4); # else %esp -= (p-s)&0xfff + framesz; + &sub ($s3,$s0); + &and ($s3,0xfff); + &add ($s3,384); + &sub ($acc,$s3); + &set_label("tbl_ok",4); + + &lea ($s3,&wparam(0)); # obtain pointer to parameter block + &exch ("esp",$acc); # allocate stack frame + &add ("esp",4); # reserve for return address! + &mov ($_tbl,$tbl); # save %ebp + &mov ($_esp,$acc); # save %esp + + &mov ($s0,&DWP(0,$s3)); # load inp + &mov ($s1,&DWP(4,$s3)); # load out + #&mov ($s2,&DWP(8,$s3)); # load len + &mov ($key,&DWP(12,$s3)); # load key + &mov ($acc,&DWP(16,$s3)); # load ivp + &mov ($s3,&DWP(20,$s3)); # load enc flag + + &mov ($_inp,$s0); # save copy of inp + &mov ($_out,$s1); # save copy of out + &mov ($_len,$s2); # save copy of len + &mov ($_key,$key); # save copy of key + &mov ($_ivp,$acc); # save copy of ivp + + &mov ($mark,0); # copy of aes_key->rounds = 0; + # do we copy key schedule to stack? + &mov ($s1 eq "ebx" ? $s1 : "",$key); + &mov ($s2 eq "ecx" ? $s2 : "",244/4); + &sub ($s1,$tbl); + &mov ("esi",$key); + &and ($s1,0xfff); + &lea ("edi",$aes_key); + &cmp ($s1,2048+256); + &jb (&label("do_copy")); + &cmp ($s1,4096-244); + &jb (&label("skip_copy")); + &set_label("do_copy",4); + &mov ($_key,"edi"); + &data_word(0xA5F3F689); # rep movsd + &set_label("skip_copy"); + + &mov ($key,16); + &set_label("prefetch_tbl",4); + &mov ($s0,&DWP(0,$tbl)); + &mov ($s1,&DWP(32,$tbl)); + &mov ($s2,&DWP(64,$tbl)); + &mov ($acc,&DWP(96,$tbl)); + &lea ($tbl,&DWP(128,$tbl)); + &sub ($key,1); + &jnz (&label("prefetch_tbl")); + &sub ($tbl,2048); + + &mov ($acc,$_inp); + &mov ($key,$_ivp); + + &cmp ($s3,0); + &je (&label("fast_decrypt")); + +#----------------------------- ENCRYPT -----------------------------# + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + + &set_label("fast_enc_loop",16); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + + &xor ($s0,&DWP(0,$acc)); # xor input data + &xor ($s1,&DWP(4,$acc)); + &xor ($s2,&DWP(8,$acc)); + &xor ($s3,&DWP(12,$acc)); + + &mov ($key,$_key); # load key + &call ("_x86_AES_encrypt"); + + &mov ($acc,$_inp); # load inp + &mov ($key,$_out); # load out + + &mov (&DWP(0,$key),$s0); # save output data + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($s2,$_len); # load len + &mov ($_inp,$acc); # save inp + &lea ($s3,&DWP(16,$key)); # advance out + &mov ($_out,$s3); # save out + &sub ($s2,16); # decrease len + &mov ($_len,$s2); # save len + &jnz (&label("fast_enc_loop")); + &mov ($acc,$_ivp); # load ivp + &mov ($s2,&DWP(8,$key)); # restore last 2 dwords + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$acc),$s0); # save ivec + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &cmp ($mark,0); # was the key schedule copied? + &mov ("edi",$_key); + &je (&label("skip_ezero")); + # zero copy of key schedule + &mov ("ecx",240/4); + &xor ("eax","eax"); + &align (4); + &data_word(0xABF3F689); # rep stosd + &set_label("skip_ezero"); + &mov ("esp",$_esp); + &popf (); + &set_label("drop_out"); + &function_end_A(); + &pushf (); # kludge, never executed + +#----------------------------- DECRYPT -----------------------------# +&set_label("fast_decrypt",16); + + &cmp ($acc,$_out); + &je (&label("fast_dec_in_place")); # in-place processing... + + &mov ($_tmp,$key); + + &align (4); + &set_label("fast_dec_loop",16); + &mov ($s0,&DWP(0,$acc)); # read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov ($key,$_key); # load key + &call ("_x86_AES_decrypt"); + + &mov ($key,$_tmp); # load ivp + &mov ($acc,$_len); # load len + &xor ($s0,&DWP(0,$key)); # xor iv + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov ($key,$_out); # load out + &mov ($acc,$_inp); # load inp + + &mov (&DWP(0,$key),$s0); # write output + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($s2,$_len); # load len + &mov ($_tmp,$acc); # save ivp + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &lea ($key,&DWP(16,$key)); # advance out + &mov ($_out,$key); # save out + &sub ($s2,16); # decrease len + &mov ($_len,$s2); # save len + &jnz (&label("fast_dec_loop")); + &mov ($key,$_tmp); # load temp ivp + &mov ($acc,$_ivp); # load user ivp + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$acc),$s0); # copy back to user + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + &jmp (&label("fast_dec_out")); + + &set_label("fast_dec_in_place",16); + &set_label("fast_dec_in_place_loop"); + &mov ($s0,&DWP(0,$acc)); # read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &lea ($key,$ivec); + &mov (&DWP(0,$key),$s0); # copy to temp + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($key,$_key); # load key + &call ("_x86_AES_decrypt"); + + &mov ($key,$_ivp); # load ivp + &mov ($acc,$_out); # load out + &xor ($s0,&DWP(0,$key)); # xor iv + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &mov (&DWP(0,$acc),$s0); # write output + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &lea ($acc,&DWP(16,$acc)); # advance out + &mov ($_out,$acc); # save out + + &lea ($acc,$ivec); + &mov ($s0,&DWP(0,$acc)); # read temp + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov (&DWP(0,$key),$s0); # copy iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($acc,$_inp); # load inp + &mov ($s2,$_len); # load len + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &sub ($s2,16); # decrease len + &mov ($_len,$s2); # save len + &jnz (&label("fast_dec_in_place_loop")); + + &set_label("fast_dec_out",4); + &cmp ($mark,0); # was the key schedule copied? + &mov ("edi",$_key); + &je (&label("skip_dzero")); + # zero copy of key schedule + &mov ("ecx",240/4); + &xor ("eax","eax"); + &align (4); + &data_word(0xABF3F689); # rep stosd + &set_label("skip_dzero"); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + +#--------------------------- SLOW ROUTINE ---------------------------# +&set_label("slow_way",16); + + &mov ($s0,&DWP(0,$s0)) if (!$x86only);# load OPENSSL_ia32cap + &mov ($key,&wparam(3)); # load key + + # pre-allocate aligned stack frame... + &lea ($acc,&DWP(-80,"esp")); + &and ($acc,-64); + + # ... and make sure it doesn't alias with $key modulo 1024 + &lea ($s1,&DWP(-80-63,$key)); + &sub ($s1,$acc); + &neg ($s1); + &and ($s1,0x3C0); # modulo 1024, but aligned to cache-line + &sub ($acc,$s1); + + # pick S-box copy which can't overlap with stack frame or $key + &lea ($s1,&DWP(768,$acc)); + &sub ($s1,$tbl); + &and ($s1,0x300); + &lea ($tbl,&DWP(2048+128,$tbl,$s1)); + + &lea ($s3,&wparam(0)); # pointer to parameter block + + &exch ("esp",$acc); + &add ("esp",4); # reserve for return address! + &mov ($_tbl,$tbl); # save %ebp + &mov ($_esp,$acc); # save %esp + &mov ($_tmp,$s0); # save OPENSSL_ia32cap + + &mov ($s0,&DWP(0,$s3)); # load inp + &mov ($s1,&DWP(4,$s3)); # load out + #&mov ($s2,&DWP(8,$s3)); # load len + #&mov ($key,&DWP(12,$s3)); # load key + &mov ($acc,&DWP(16,$s3)); # load ivp + &mov ($s3,&DWP(20,$s3)); # load enc flag + + &mov ($_inp,$s0); # save copy of inp + &mov ($_out,$s1); # save copy of out + &mov ($_len,$s2); # save copy of len + &mov ($_key,$key); # save copy of key + &mov ($_ivp,$acc); # save copy of ivp + + &mov ($key,$acc); + &mov ($acc,$s0); + + &cmp ($s3,0); + &je (&label("slow_decrypt")); + +#--------------------------- SLOW ENCRYPT ---------------------------# + &cmp ($s2,16); + &mov ($s3,$s1); + &jb (&label("slow_enc_tail")); + + if (!$x86only) { + &bt ($_tmp,25); # check for SSE bit + &jnc (&label("slow_enc_x86")); + + &movq ("mm0",&QWP(0,$key)); # load iv + &movq ("mm4",&QWP(8,$key)); + + &set_label("slow_enc_loop_sse",16); + &pxor ("mm0",&QWP(0,$acc)); # xor input data + &pxor ("mm4",&QWP(8,$acc)); + + &mov ($key,$_key); + &call ("_sse_AES_encrypt_compact"); + + &mov ($acc,$_inp); # load inp + &mov ($key,$_out); # load out + &mov ($s2,$_len); # load len + + &movq (&QWP(0,$key),"mm0"); # save output data + &movq (&QWP(8,$key),"mm4"); + + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &lea ($s3,&DWP(16,$key)); # advance out + &mov ($_out,$s3); # save out + &sub ($s2,16); # decrease len + &cmp ($s2,16); + &mov ($_len,$s2); # save len + &jae (&label("slow_enc_loop_sse")); + &test ($s2,15); + &jnz (&label("slow_enc_tail")); + &mov ($acc,$_ivp); # load ivp + &movq (&QWP(0,$acc),"mm0"); # save ivec + &movq (&QWP(8,$acc),"mm4"); + &emms (); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + } + &set_label("slow_enc_x86",16); + &mov ($s0,&DWP(0,$key)); # load iv + &mov ($s1,&DWP(4,$key)); + + &set_label("slow_enc_loop_x86",4); + &mov ($s2,&DWP(8,$key)); + &mov ($s3,&DWP(12,$key)); + + &xor ($s0,&DWP(0,$acc)); # xor input data + &xor ($s1,&DWP(4,$acc)); + &xor ($s2,&DWP(8,$acc)); + &xor ($s3,&DWP(12,$acc)); + + &mov ($key,$_key); # load key + &call ("_x86_AES_encrypt_compact"); + + &mov ($acc,$_inp); # load inp + &mov ($key,$_out); # load out + + &mov (&DWP(0,$key),$s0); # save output data + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($s2,$_len); # load len + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &lea ($s3,&DWP(16,$key)); # advance out + &mov ($_out,$s3); # save out + &sub ($s2,16); # decrease len + &cmp ($s2,16); + &mov ($_len,$s2); # save len + &jae (&label("slow_enc_loop_x86")); + &test ($s2,15); + &jnz (&label("slow_enc_tail")); + &mov ($acc,$_ivp); # load ivp + &mov ($s2,&DWP(8,$key)); # restore last dwords + &mov ($s3,&DWP(12,$key)); + &mov (&DWP(0,$acc),$s0); # save ivec + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("slow_enc_tail",16); + &emms () if (!$x86only); + &mov ($key eq "edi"? $key:"",$s3); # load out to edi + &mov ($s1,16); + &sub ($s1,$s2); + &cmp ($key,$acc eq "esi"? $acc:""); # compare with inp + &je (&label("enc_in_place")); + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy input + &jmp (&label("enc_skip_in_place")); + &set_label("enc_in_place"); + &lea ($key,&DWP(0,$key,$s2)); + &set_label("enc_skip_in_place"); + &mov ($s2,$s1); + &xor ($s0,$s0); + &align (4); + &data_word(0xAAF3F689); # rep stosb # zero tail + + &mov ($key,$_ivp); # restore ivp + &mov ($acc,$s3); # output as input + &mov ($s0,&DWP(0,$key)); + &mov ($s1,&DWP(4,$key)); + &mov ($_len,16); # len=16 + &jmp (&label("slow_enc_loop_x86")); # one more spin... + +#--------------------------- SLOW DECRYPT ---------------------------# +&set_label("slow_decrypt",16); + if (!$x86only) { + &bt ($_tmp,25); # check for SSE bit + &jnc (&label("slow_dec_loop_x86")); + + &set_label("slow_dec_loop_sse",4); + &movq ("mm0",&QWP(0,$acc)); # read input + &movq ("mm4",&QWP(8,$acc)); + + &mov ($key,$_key); + &call ("_sse_AES_decrypt_compact"); + + &mov ($acc,$_inp); # load inp + &lea ($s0,$ivec); + &mov ($s1,$_out); # load out + &mov ($s2,$_len); # load len + &mov ($key,$_ivp); # load ivp + + &movq ("mm1",&QWP(0,$acc)); # re-read input + &movq ("mm5",&QWP(8,$acc)); + + &pxor ("mm0",&QWP(0,$key)); # xor iv + &pxor ("mm4",&QWP(8,$key)); + + &movq (&QWP(0,$key),"mm1"); # copy input to iv + &movq (&QWP(8,$key),"mm5"); + + &sub ($s2,16); # decrease len + &jc (&label("slow_dec_partial_sse")); + + &movq (&QWP(0,$s1),"mm0"); # write output + &movq (&QWP(8,$s1),"mm4"); + + &lea ($s1,&DWP(16,$s1)); # advance out + &mov ($_out,$s1); # save out + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &mov ($_len,$s2); # save len + &jnz (&label("slow_dec_loop_sse")); + &emms (); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("slow_dec_partial_sse",16); + &movq (&QWP(0,$s0),"mm0"); # save output to temp + &movq (&QWP(8,$s0),"mm4"); + &emms (); + + &add ($s2 eq "ecx" ? "ecx":"",16); + &mov ("edi",$s1); # out + &mov ("esi",$s0); # temp + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy partial output + + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + } + &set_label("slow_dec_loop_x86",16); + &mov ($s0,&DWP(0,$acc)); # read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &lea ($key,$ivec); + &mov (&DWP(0,$key),$s0); # copy to temp + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($key,$_key); # load key + &call ("_x86_AES_decrypt_compact"); + + &mov ($key,$_ivp); # load ivp + &mov ($acc,$_len); # load len + &xor ($s0,&DWP(0,$key)); # xor iv + &xor ($s1,&DWP(4,$key)); + &xor ($s2,&DWP(8,$key)); + &xor ($s3,&DWP(12,$key)); + + &sub ($acc,16); + &jc (&label("slow_dec_partial_x86")); + + &mov ($_len,$acc); # save len + &mov ($acc,$_out); # load out + + &mov (&DWP(0,$acc),$s0); # write output + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &lea ($acc,&DWP(16,$acc)); # advance out + &mov ($_out,$acc); # save out + + &lea ($acc,$ivec); + &mov ($s0,&DWP(0,$acc)); # read temp + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov (&DWP(0,$key),$s0); # copy it to iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ($acc,$_inp); # load inp + &lea ($acc,&DWP(16,$acc)); # advance inp + &mov ($_inp,$acc); # save inp + &jnz (&label("slow_dec_loop_x86")); + &mov ("esp",$_esp); + &popf (); + &function_end_A(); + &pushf (); # kludge, never executed + + &set_label("slow_dec_partial_x86",16); + &lea ($acc,$ivec); + &mov (&DWP(0,$acc),$s0); # save output to temp + &mov (&DWP(4,$acc),$s1); + &mov (&DWP(8,$acc),$s2); + &mov (&DWP(12,$acc),$s3); + + &mov ($acc,$_inp); + &mov ($s0,&DWP(0,$acc)); # re-read input + &mov ($s1,&DWP(4,$acc)); + &mov ($s2,&DWP(8,$acc)); + &mov ($s3,&DWP(12,$acc)); + + &mov (&DWP(0,$key),$s0); # copy it to iv + &mov (&DWP(4,$key),$s1); + &mov (&DWP(8,$key),$s2); + &mov (&DWP(12,$key),$s3); + + &mov ("ecx",$_len); + &mov ("edi",$_out); + &lea ("esi",$ivec); + &align (4); + &data_word(0xA4F3F689); # rep movsb # copy partial output + + &mov ("esp",$_esp); + &popf (); +&function_end("AES_cbc_encrypt"); +} + +#------------------------------------------------------------------# + +sub enckey() +{ + &movz ("esi",&LB("edx")); # rk[i]>>0 + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[i]>>8 + &shl ("ebx",24); + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shr ("edx",16); + &movz ("esi",&LB("edx")); # rk[i]>>16 + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[i]>>24 + &shl ("ebx",8); + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shl ("ebx",16); + &xor ("eax","ebx"); + + &xor ("eax",&DWP(1024-128,$tbl,"ecx",4)); # rcon +} + +&function_begin("_x86_AES_set_encrypt_key"); + &mov ("esi",&wparam(1)); # user supplied key + &mov ("edi",&wparam(3)); # private key schedule + + &test ("esi",-1); + &jz (&label("badpointer")); + &test ("edi",-1); + &jz (&label("badpointer")); + + &call (&label("pic_point")); + &set_label("pic_point"); + &blindpop($tbl); + &lea ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl)); + &lea ($tbl,&DWP(2048+128,$tbl)); + + # prefetch Te4 + &mov ("eax",&DWP(0-128,$tbl)); + &mov ("ebx",&DWP(32-128,$tbl)); + &mov ("ecx",&DWP(64-128,$tbl)); + &mov ("edx",&DWP(96-128,$tbl)); + &mov ("eax",&DWP(128-128,$tbl)); + &mov ("ebx",&DWP(160-128,$tbl)); + &mov ("ecx",&DWP(192-128,$tbl)); + &mov ("edx",&DWP(224-128,$tbl)); + + &mov ("ecx",&wparam(2)); # number of bits in key + &cmp ("ecx",128); + &je (&label("10rounds")); + &cmp ("ecx",192); + &je (&label("12rounds")); + &cmp ("ecx",256); + &je (&label("14rounds")); + &mov ("eax",-2); # invalid number of bits + &jmp (&label("exit")); + + &set_label("10rounds"); + &mov ("eax",&DWP(0,"esi")); # copy first 4 dwords + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + + &xor ("ecx","ecx"); + &jmp (&label("10shortcut")); + + &align (4); + &set_label("10loop"); + &mov ("eax",&DWP(0,"edi")); # rk[0] + &mov ("edx",&DWP(12,"edi")); # rk[3] + &set_label("10shortcut"); + &enckey (); + + &mov (&DWP(16,"edi"),"eax"); # rk[4] + &xor ("eax",&DWP(4,"edi")); + &mov (&DWP(20,"edi"),"eax"); # rk[5] + &xor ("eax",&DWP(8,"edi")); + &mov (&DWP(24,"edi"),"eax"); # rk[6] + &xor ("eax",&DWP(12,"edi")); + &mov (&DWP(28,"edi"),"eax"); # rk[7] + &inc ("ecx"); + &add ("edi",16); + &cmp ("ecx",10); + &jl (&label("10loop")); + + &mov (&DWP(80,"edi"),10); # setup number of rounds + &xor ("eax","eax"); + &jmp (&label("exit")); + + &set_label("12rounds"); + &mov ("eax",&DWP(0,"esi")); # copy first 6 dwords + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + &mov ("ecx",&DWP(16,"esi")); + &mov ("edx",&DWP(20,"esi")); + &mov (&DWP(16,"edi"),"ecx"); + &mov (&DWP(20,"edi"),"edx"); + + &xor ("ecx","ecx"); + &jmp (&label("12shortcut")); + + &align (4); + &set_label("12loop"); + &mov ("eax",&DWP(0,"edi")); # rk[0] + &mov ("edx",&DWP(20,"edi")); # rk[5] + &set_label("12shortcut"); + &enckey (); + + &mov (&DWP(24,"edi"),"eax"); # rk[6] + &xor ("eax",&DWP(4,"edi")); + &mov (&DWP(28,"edi"),"eax"); # rk[7] + &xor ("eax",&DWP(8,"edi")); + &mov (&DWP(32,"edi"),"eax"); # rk[8] + &xor ("eax",&DWP(12,"edi")); + &mov (&DWP(36,"edi"),"eax"); # rk[9] + + &cmp ("ecx",7); + &je (&label("12break")); + &inc ("ecx"); + + &xor ("eax",&DWP(16,"edi")); + &mov (&DWP(40,"edi"),"eax"); # rk[10] + &xor ("eax",&DWP(20,"edi")); + &mov (&DWP(44,"edi"),"eax"); # rk[11] + + &add ("edi",24); + &jmp (&label("12loop")); + + &set_label("12break"); + &mov (&DWP(72,"edi"),12); # setup number of rounds + &xor ("eax","eax"); + &jmp (&label("exit")); + + &set_label("14rounds"); + &mov ("eax",&DWP(0,"esi")); # copy first 8 dwords + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(8,"esi")); + &mov ("edx",&DWP(12,"esi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(8,"edi"),"ecx"); + &mov (&DWP(12,"edi"),"edx"); + &mov ("eax",&DWP(16,"esi")); + &mov ("ebx",&DWP(20,"esi")); + &mov ("ecx",&DWP(24,"esi")); + &mov ("edx",&DWP(28,"esi")); + &mov (&DWP(16,"edi"),"eax"); + &mov (&DWP(20,"edi"),"ebx"); + &mov (&DWP(24,"edi"),"ecx"); + &mov (&DWP(28,"edi"),"edx"); + + &xor ("ecx","ecx"); + &jmp (&label("14shortcut")); + + &align (4); + &set_label("14loop"); + &mov ("edx",&DWP(28,"edi")); # rk[7] + &set_label("14shortcut"); + &mov ("eax",&DWP(0,"edi")); # rk[0] + + &enckey (); + + &mov (&DWP(32,"edi"),"eax"); # rk[8] + &xor ("eax",&DWP(4,"edi")); + &mov (&DWP(36,"edi"),"eax"); # rk[9] + &xor ("eax",&DWP(8,"edi")); + &mov (&DWP(40,"edi"),"eax"); # rk[10] + &xor ("eax",&DWP(12,"edi")); + &mov (&DWP(44,"edi"),"eax"); # rk[11] + + &cmp ("ecx",6); + &je (&label("14break")); + &inc ("ecx"); + + &mov ("edx","eax"); + &mov ("eax",&DWP(16,"edi")); # rk[4] + &movz ("esi",&LB("edx")); # rk[11]>>0 + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[11]>>8 + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shr ("edx",16); + &shl ("ebx",8); + &movz ("esi",&LB("edx")); # rk[11]>>16 + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &movz ("esi",&HB("edx")); # rk[11]>>24 + &shl ("ebx",16); + &xor ("eax","ebx"); + + &movz ("ebx",&BP(-128,$tbl,"esi",1)); + &shl ("ebx",24); + &xor ("eax","ebx"); + + &mov (&DWP(48,"edi"),"eax"); # rk[12] + &xor ("eax",&DWP(20,"edi")); + &mov (&DWP(52,"edi"),"eax"); # rk[13] + &xor ("eax",&DWP(24,"edi")); + &mov (&DWP(56,"edi"),"eax"); # rk[14] + &xor ("eax",&DWP(28,"edi")); + &mov (&DWP(60,"edi"),"eax"); # rk[15] + + &add ("edi",32); + &jmp (&label("14loop")); + + &set_label("14break"); + &mov (&DWP(48,"edi"),14); # setup number of rounds + &xor ("eax","eax"); + &jmp (&label("exit")); + + &set_label("badpointer"); + &mov ("eax",-1); + &set_label("exit"); +&function_end("_x86_AES_set_encrypt_key"); + +# int AES_set_encrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +&function_begin_B("AES_set_encrypt_key"); + &call ("_x86_AES_set_encrypt_key"); + &ret (); +&function_end_B("AES_set_encrypt_key"); + +sub deckey() +{ my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_; + my $tmp = $tbl; + + &mov ($tmp,0x80808080); + &and ($tmp,$tp1); + &lea ($tp2,&DWP(0,$tp1,$tp1)); + &mov ($acc,$tmp); + &shr ($tmp,7); + &sub ($acc,$tmp); + &and ($tp2,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp2); + &lea ($tp4,&DWP(0,$tp2,$tp2)); + &mov ($acc,$tmp); + &shr ($tmp,7); + &sub ($acc,$tmp); + &and ($tp4,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &xor ($tp2,$tp1); # tp2^tp1 + &xor ($tp4,$acc); + &mov ($tmp,0x80808080); + + &and ($tmp,$tp4); + &lea ($tp8,&DWP(0,$tp4,$tp4)); + &mov ($acc,$tmp); + &shr ($tmp,7); + &xor ($tp4,$tp1); # tp4^tp1 + &sub ($acc,$tmp); + &and ($tp8,0xfefefefe); + &and ($acc,0x1b1b1b1b); + &rotl ($tp1,8); # = ROTATE(tp1,8) + &xor ($tp8,$acc); + + &mov ($tmp,&DWP(4*($i+1),$key)); # modulo-scheduled load + + &xor ($tp1,$tp2); + &xor ($tp2,$tp8); + &xor ($tp1,$tp4); + &rotl ($tp2,24); + &xor ($tp4,$tp8); + &xor ($tp1,$tp8); # ^= tp8^(tp4^tp1)^(tp2^tp1) + &rotl ($tp4,16); + &xor ($tp1,$tp2); # ^= ROTATE(tp8^tp2^tp1,24) + &rotl ($tp8,8); + &xor ($tp1,$tp4); # ^= ROTATE(tp8^tp4^tp1,16) + &mov ($tp2,$tmp); + &xor ($tp1,$tp8); # ^= ROTATE(tp8,8) + + &mov (&DWP(4*$i,$key),$tp1); +} + +# int AES_set_decrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +&function_begin_B("AES_set_decrypt_key"); + &call ("_x86_AES_set_encrypt_key"); + &cmp ("eax",0); + &je (&label("proceed")); + &ret (); + + &set_label("proceed"); + &push ("ebp"); + &push ("ebx"); + &push ("esi"); + &push ("edi"); + + &mov ("esi",&wparam(2)); + &mov ("ecx",&DWP(240,"esi")); # pull number of rounds + &lea ("ecx",&DWP(0,"","ecx",4)); + &lea ("edi",&DWP(0,"esi","ecx",4)); # pointer to last chunk + + &set_label("invert",4); # invert order of chunks + &mov ("eax",&DWP(0,"esi")); + &mov ("ebx",&DWP(4,"esi")); + &mov ("ecx",&DWP(0,"edi")); + &mov ("edx",&DWP(4,"edi")); + &mov (&DWP(0,"edi"),"eax"); + &mov (&DWP(4,"edi"),"ebx"); + &mov (&DWP(0,"esi"),"ecx"); + &mov (&DWP(4,"esi"),"edx"); + &mov ("eax",&DWP(8,"esi")); + &mov ("ebx",&DWP(12,"esi")); + &mov ("ecx",&DWP(8,"edi")); + &mov ("edx",&DWP(12,"edi")); + &mov (&DWP(8,"edi"),"eax"); + &mov (&DWP(12,"edi"),"ebx"); + &mov (&DWP(8,"esi"),"ecx"); + &mov (&DWP(12,"esi"),"edx"); + &add ("esi",16); + &sub ("edi",16); + &cmp ("esi","edi"); + &jne (&label("invert")); + + &mov ($key,&wparam(2)); + &mov ($acc,&DWP(240,$key)); # pull number of rounds + &lea ($acc,&DWP(-2,$acc,$acc)); + &lea ($acc,&DWP(0,$key,$acc,8)); + &mov (&wparam(2),$acc); + + &mov ($s0,&DWP(16,$key)); # modulo-scheduled load + &set_label("permute",4); # permute the key schedule + &add ($key,16); + &deckey (0,$key,$s0,$s1,$s2,$s3); + &deckey (1,$key,$s1,$s2,$s3,$s0); + &deckey (2,$key,$s2,$s3,$s0,$s1); + &deckey (3,$key,$s3,$s0,$s1,$s2); + &cmp ($key,&wparam(2)); + &jb (&label("permute")); + + &xor ("eax","eax"); # return success +&function_end("AES_set_decrypt_key"); +&asciz("AES for x86, CRYPTOGAMS by "); + +&asm_finish(); + +close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/aes/asm/aes-armv4.pl b/crypto/aes/asm/aes-armv4.pl --- a/crypto/aes/asm/aes-armv4.pl +++ b/crypto/aes/asm/aes-armv4.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -39,9 +39,10 @@ # Profiler-assisted and platform-specific optimization resulted in 16% # improvement on Cortex A8 core and ~21.5 cycles per byte. -$flavour = shift; -if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } -else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour && $flavour ne "void") { $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; @@ -49,9 +50,10 @@ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; - open STDOUT,"| \"$^X\" $xlate $flavour $output"; + open STDOUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; } else { - open STDOUT,">$output"; + $output and open STDOUT,">$output"; } $s0="r0"; @@ -76,7 +78,6 @@ # define __ARM_ARCH__ __LINUX_ARM_ARCH__ #endif -.text #if defined(__thumb2__) && !defined(__APPLE__) .syntax unified .thumb @@ -85,6 +86,8 @@ #undef __thumb2__ #endif +.text + .type AES_Te,%object .align 5 AES_Te: diff --git a/crypto/aes/asm/aes-c64xplus.pl b/crypto/aes/asm/aes-c64xplus.pl --- a/crypto/aes/asm/aes-c64xplus.pl +++ b/crypto/aes/asm/aes-c64xplus.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -37,8 +37,7 @@ # cost of 8x increased pressure on L1D. 8x because you'd have # to interleave both Te and Td tables... -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; ($TEA,$TEB)=("A5","B5"); ($KPA,$KPB)=("A3","B1"); diff --git a/crypto/aes/asm/aes-ia64.S b/crypto/aes/asm/aes-ia64.S --- a/crypto/aes/asm/aes-ia64.S +++ b/crypto/aes/asm/aes-ia64.S @@ -1,6 +1,6 @@ // Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. // -// Licensed under the OpenSSL license (the "License"). You may not use +// 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 // https://www.openssl.org/source/license.html @@ -8,7 +8,7 @@ // ==================================================================== // Written by Andy Polyakov for the OpenSSL // project. Rights for redistribution and usage in source and binary -// forms are granted according to the OpenSSL license. +// forms are granted according to the License. // ==================================================================== // // What's wrong with compiler generated code? Compiler never uses diff --git a/crypto/aes/asm/aes-mips.pl b/crypto/aes/asm/aes-mips.pl --- a/crypto/aes/asm/aes-mips.pl +++ b/crypto/aes/asm/aes-mips.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -34,6 +34,11 @@ # instead, code path is chosen upon pre-process time, pass -mips32r2 # or/and -msmartmips. +# February 2019 +# +# Normalize MIPS32R2 AES table address calculation by always using EXT +# instruction. This reduces the standard codebase by another 10%. + ###################################################################### # There is a number of MIPS ABI in use, O32 and N32/64 are most # widely used. Then there is a new contender: NUBI. It appears that if @@ -60,8 +65,12 @@ # ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); # ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); # ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); -# -$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; +$flavour ||= "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 if ($flavour =~ /64|n32/i) { $PTR_LA="dla"; @@ -90,17 +99,13 @@ $big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC}); -for (@ARGV) { $output=$_ if (/\w[\w\-]*\.\w+$/); } -open STDOUT,">$output"; - if (!defined($big_endian)) { $big_endian=(unpack('L',pack('N',1))==1); } -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; - my ($MSB,$LSB)=(0,3); # automatically converted to little-endian +$output and open STDOUT,">$output"; + $code.=<<___; #include "mips_arch.h" @@ -223,6 +228,33 @@ ext $i0,$s1,16,8 _xtr $i0,$s1,16-2 +#else +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + move $i0,$Tbl + move $i1,$Tbl + move $i2,$Tbl + move $i3,$Tbl + ext $t0,$s1,16,8 +.Loop_enc: + ext $t1,$s2,16,8 + ext $t2,$s3,16,8 + ext $t3,$s0,16,8 + $PTR_INS $i0,$t0,2,8 + $PTR_INS $i1,$t1,2,8 + $PTR_INS $i2,$t2,2,8 + $PTR_INS $i3,$t3,2,8 + lw $t0,0($i0) # Te1[s1>>16] + ext $t4,$s2,8,8 + lw $t1,0($i1) # Te1[s2>>16] + ext $t5,$s3,8,8 + lw $t2,0($i2) # Te1[s3>>16] + ext $t6,$s0,8,8 + lw $t3,0($i3) # Te1[s0>>16] + ext $t7,$s1,8,8 + $PTR_INS $i0,$t4,2,8 + $PTR_INS $i1,$t5,2,8 + $PTR_INS $i2,$t6,2,8 + $PTR_INS $i3,$t7,2,8 #else _xtr $i0,$s1,16-2 .Loop_enc: @@ -237,16 +269,6 @@ $PTR_ADD $i1,$Tbl $PTR_ADD $i2,$Tbl $PTR_ADD $i3,$Tbl -#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) - lw $t0,0($i0) # Te1[s1>>16] - _xtr $i0,$s2,8-2 - lw $t1,0($i1) # Te1[s2>>16] - _xtr $i1,$s3,8-2 - lw $t2,0($i2) # Te1[s3>>16] - _xtr $i2,$s0,8-2 - lw $t3,0($i3) # Te1[s0>>16] - _xtr $i3,$s1,8-2 -#else lwl $t0,3($i0) # Te1[s1>>16] lwl $t1,3($i1) # Te1[s2>>16] lwl $t2,3($i2) # Te1[s3>>16] @@ -259,7 +281,6 @@ _xtr $i2,$s0,8-2 lwr $t3,2($i3) # Te1[s0>>16] _xtr $i3,$s1,8-2 -#endif and $i0,0x3fc and $i1,0x3fc and $i2,0x3fc @@ -268,6 +289,7 @@ $PTR_ADD $i1,$Tbl $PTR_ADD $i2,$Tbl $PTR_ADD $i3,$Tbl +#endif #if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) rotr $t0,$t0,8 rotr $t1,$t1,8 @@ -275,22 +297,18 @@ rotr $t3,$t3,8 # if defined(_MIPSEL) lw $t4,0($i0) # Te2[s2>>8] - _xtr $i0,$s3,0-2 + ext $t8,$s3,0,8 lw $t5,0($i1) # Te2[s3>>8] - _xtr $i1,$s0,0-2 + ext $t9,$s0,0,8 lw $t6,0($i2) # Te2[s0>>8] - _xtr $i2,$s1,0-2 + ext $t10,$s1,0,8 lw $t7,0($i3) # Te2[s1>>8] - _xtr $i3,$s2,0-2 + ext $t11,$s2,0,8 + $PTR_INS $i0,$t8,2,8 + $PTR_INS $i1,$t9,2,8 + $PTR_INS $i2,$t10,2,8 + $PTR_INS $i3,$t11,2,8 - and $i0,0x3fc - and $i1,0x3fc - and $i2,0x3fc - and $i3,0x3fc - $PTR_ADD $i0,$Tbl - $PTR_ADD $i1,$Tbl - $PTR_ADD $i2,$Tbl - $PTR_ADD $i3,$Tbl lw $t8,0($i0) # Te3[s3] $PTR_INS $i0,$s0,2,8 lw $t9,0($i1) # Te3[s0] @@ -411,6 +429,9 @@ xor $s3,$t3 .set noreorder bnez $cnt,.Loop_enc +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + ext $t0,$s1,16,8 +#endif _xtr $i0,$s1,16-2 #endif @@ -811,6 +832,33 @@ ext $i0,$s3,16,8 _xtr $i0,$s3,16-2 +#else +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + move $i0,$Tbl + move $i1,$Tbl + move $i2,$Tbl + move $i3,$Tbl + ext $t0,$s3,16,8 +.Loop_dec: + ext $t1,$s0,16,8 + ext $t2,$s1,16,8 + ext $t3,$s2,16,8 + $PTR_INS $i0,$t0,2,8 + $PTR_INS $i1,$t1,2,8 + $PTR_INS $i2,$t2,2,8 + $PTR_INS $i3,$t3,2,8 + lw $t0,0($i0) # Td1[s3>>16] + ext $t4,$s2,8,8 + lw $t1,0($i1) # Td1[s0>>16] + ext $t5,$s3,8,8 + lw $t2,0($i2) # Td1[s1>>16] + ext $t6,$s0,8,8 + lw $t3,0($i3) # Td1[s2>>16] + ext $t7,$s1,8,8 + $PTR_INS $i0,$t4,2,8 + $PTR_INS $i1,$t5,2,8 + $PTR_INS $i2,$t6,2,8 + $PTR_INS $i3,$t7,2,8 #else _xtr $i0,$s3,16-2 .Loop_dec: @@ -825,16 +873,6 @@ $PTR_ADD $i1,$Tbl $PTR_ADD $i2,$Tbl $PTR_ADD $i3,$Tbl -#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) - lw $t0,0($i0) # Td1[s3>>16] - _xtr $i0,$s2,8-2 - lw $t1,0($i1) # Td1[s0>>16] - _xtr $i1,$s3,8-2 - lw $t2,0($i2) # Td1[s1>>16] - _xtr $i2,$s0,8-2 - lw $t3,0($i3) # Td1[s2>>16] - _xtr $i3,$s1,8-2 -#else lwl $t0,3($i0) # Td1[s3>>16] lwl $t1,3($i1) # Td1[s0>>16] lwl $t2,3($i2) # Td1[s1>>16] @@ -847,8 +885,6 @@ _xtr $i2,$s0,8-2 lwr $t3,2($i3) # Td1[s2>>16] _xtr $i3,$s1,8-2 -#endif - and $i0,0x3fc and $i1,0x3fc and $i2,0x3fc @@ -857,6 +893,7 @@ $PTR_ADD $i1,$Tbl $PTR_ADD $i2,$Tbl $PTR_ADD $i3,$Tbl +#endif #if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) rotr $t0,$t0,8 rotr $t1,$t1,8 @@ -864,22 +901,17 @@ rotr $t3,$t3,8 # if defined(_MIPSEL) lw $t4,0($i0) # Td2[s2>>8] - _xtr $i0,$s1,0-2 + ext $t8,$s1,0,8 lw $t5,0($i1) # Td2[s3>>8] - _xtr $i1,$s2,0-2 + ext $t9,$s2,0,8 lw $t6,0($i2) # Td2[s0>>8] - _xtr $i2,$s3,0-2 + ext $t10,$s3,0,8 lw $t7,0($i3) # Td2[s1>>8] - _xtr $i3,$s0,0-2 - - and $i0,0x3fc - and $i1,0x3fc - and $i2,0x3fc - and $i3,0x3fc - $PTR_ADD $i0,$Tbl - $PTR_ADD $i1,$Tbl - $PTR_ADD $i2,$Tbl - $PTR_ADD $i3,$Tbl + ext $t11,$s0,0,8 + $PTR_INS $i0,$t8,2,8 + $PTR_INS $i1,$t9,2,8 + $PTR_INS $i2,$t10,2,8 + $PTR_INS $i3,$t11,2,8 lw $t8,0($i0) # Td3[s1] $PTR_INS $i0,$s0,2,8 lw $t9,0($i1) # Td3[s2] @@ -1001,6 +1033,10 @@ xor $s3,$t3 .set noreorder bnez $cnt,.Loop_dec +#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2) + ext $t0,$s3,16,8 +#endif + _xtr $i0,$s3,16-2 #endif diff --git a/crypto/aes/asm/aes-parisc.pl b/crypto/aes/asm/aes-parisc.pl --- a/crypto/aes/asm/aes-parisc.pl +++ b/crypto/aes/asm/aes-parisc.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -28,9 +28,12 @@ # # Special thanks to polarhome.com for providing HP-UX account. -$flavour = shift; -$output = shift; -open STDOUT,">$output"; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; + +$output and open STDOUT,">$output"; if ($flavour =~ /64/) { $LEVEL ="2.0W"; diff --git a/crypto/aes/asm/aes-ppc.pl b/crypto/aes/asm/aes-ppc.pl --- a/crypto/aes/asm/aes-ppc.pl +++ b/crypto/aes/asm/aes-ppc.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -36,7 +36,10 @@ # ppc_AES_encrypt_compact operates at 42 cycles per byte, while # ppc_AES_decrypt_compact - at 55 (in 64-bit build). -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /64/) { $SIZE_T =8; @@ -59,7 +62,8 @@ ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; +open STDOUT,"| $^X $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; $FRAME=32*$SIZE_T; diff --git a/crypto/aes/asm/aes-s390x.pl b/crypto/aes/asm/aes-s390x.pl --- a/crypto/aes/asm/aes-s390x.pl +++ b/crypto/aes/asm/aes-s390x.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -89,7 +89,10 @@ # instructions, which deliver ~70% improvement at 8KB block size over # vanilla km-based code, 37% - at most like 512-bytes block size. -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /3[12]/) { $SIZE_T=4; @@ -99,8 +102,7 @@ $g="g"; } -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +$output and open STDOUT,">$output"; $softonly=0; # allow hardware support diff --git a/crypto/aes/asm/aes-sparcv9.pl b/crypto/aes/asm/aes-sparcv9.pl --- a/crypto/aes/asm/aes-sparcv9.pl +++ b/crypto/aes/asm/aes-sparcv9.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -10,7 +10,7 @@ # ==================================================================== # Written by Andy Polyakov for the OpenSSL # project. Rights for redistribution and usage in source and binary -# forms are granted according to the OpenSSL license. +# forms are granted according to the License. # ==================================================================== # # Version 1.1 @@ -37,8 +37,7 @@ # optimal decrypt procedure]. Compared to GNU C generated code both # procedures are more than 60% faster:-) -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; $frame="STACK_FRAME"; $bias="STACK_BIAS"; @@ -83,7 +82,10 @@ } $code.=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #ifdef __arch64__ .register %g2,#scratch diff --git a/crypto/aes/asm/aes-x86_64.pl b/crypto/aes/asm/aes-x86_64.pl new file mode 100755 --- /dev/null +++ b/crypto/aes/asm/aes-x86_64.pl @@ -0,0 +1,2927 @@ +#! /usr/bin/env perl +# Copyright 2005-2020 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 +# https://www.openssl.org/source/license.html + +# +# ==================================================================== +# Written by Andy Polyakov for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# ==================================================================== +# +# Version 2.1. +# +# aes-*-cbc benchmarks are improved by >70% [compared to gcc 3.3.2 on +# Opteron 240 CPU] plus all the bells-n-whistles from 32-bit version +# [you'll notice a lot of resemblance], such as compressed S-boxes +# in little-endian byte order, prefetch of these tables in CBC mode, +# as well as avoiding L1 cache aliasing between stack frame and key +# schedule and already mentioned tables, compressed Td4... +# +# Performance in number of cycles per processed byte for 128-bit key: +# +# ECB encrypt ECB decrypt CBC large chunk +# AMD64 33 43 13.0 +# EM64T 38 56 18.6(*) +# Core 2 30 42 14.5(*) +# Atom 65 86 32.1(*) +# +# (*) with hyper-threading off + +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; +*STDOUT=*OUT; + +$verticalspin=1; # unlike 32-bit version $verticalspin performs + # ~15% better on both AMD and Intel cores +$speed_limit=512; # see aes-586.pl for details + +$code=".text\n"; + +$s0="%eax"; +$s1="%ebx"; +$s2="%ecx"; +$s3="%edx"; +$acc0="%esi"; $mask80="%rsi"; +$acc1="%edi"; $maskfe="%rdi"; +$acc2="%ebp"; $mask1b="%rbp"; +$inp="%r8"; +$out="%r9"; +$t0="%r10d"; +$t1="%r11d"; +$t2="%r12d"; +$rnds="%r13d"; +$sbox="%r14"; +$key="%r15"; + +sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; } +sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/; + $r =~ s/%[er]([sd]i)/%\1l/; + $r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; } +sub LO() { my $r=shift; $r =~ s/%r([a-z]+)/%e\1/; + $r =~ s/%r([0-9]+)/%r\1d/; $r; } +sub _data_word() +{ my $i; + while(defined($i=shift)) { $code.=sprintf".long\t0x%08x,0x%08x\n",$i,$i; } +} +sub data_word() +{ my $i; + my $last=pop(@_); + $code.=".long\t"; + while(defined($i=shift)) { $code.=sprintf"0x%08x,",$i; } + $code.=sprintf"0x%08x\n",$last; +} + +sub data_byte() +{ my $i; + my $last=pop(@_); + $code.=".byte\t"; + while(defined($i=shift)) { $code.=sprintf"0x%02x,",$i&0xff; } + $code.=sprintf"0x%02x\n",$last&0xff; +} + +sub encvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + shr \$16,$s2 + movzb `&hi("$s0")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + mov 12($key),$s3 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + mov 0($key),$s0 + xor 1($sbox,$acc1,8),$t2 + xor 1($sbox,$acc2,8),$t3 + + mov 4($key),$s1 + mov 8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enclastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb 2($sbox,$acc0,8),$t0 + movzb 2($sbox,$acc1,8),$t1 + movzb 2($sbox,$acc2,8),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb 2($sbox,$acc0,8),$t3 + mov 0($sbox,$acc1,8),$acc1 #$t0 + mov 0($sbox,$acc2,8),$acc2 #$t1 + + and \$0x0000ff00,$acc1 + and \$0x0000ff00,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + mov 0($sbox,$acc0,8),$acc0 #$t2 + mov 0($sbox,$acc1,8),$acc1 #$t3 + + and \$0x0000ff00,$acc0 + and \$0x0000ff00,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s0 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t0 + mov 0($sbox,$acc1,8),$acc1 #$t1 + mov 0($sbox,$acc2,8),$acc2 #$t2 + + and \$0x00ff0000,$acc0 + and \$0x00ff0000,$acc1 + and \$0x00ff0000,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + mov 0($sbox,$acc0,8),$acc0 #$t3 + mov 2($sbox,$acc1,8),$acc1 #$t0 + mov 2($sbox,$acc2,8),$acc2 #$t1 + + and \$0x00ff0000,$acc0 + and \$0xff000000,$acc1 + and \$0xff000000,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + mov 16+12($key),$s3 + mov 2($sbox,$acc0,8),$acc0 #$t2 + mov 2($sbox,$acc1,8),$acc1 #$t3 + mov 16+0($key),$s0 + + and \$0xff000000,$acc0 + and \$0xff000000,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub encstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" lea 16($key),$key\n" if ($i==0); + + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" mov 0($sbox,$out,8),$out\n"; + + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + $code.=" xor 4*$i($key),$out\n"; + + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub enclast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + if ($i==3) { + $tmp0=$s[1]; + $tmp1=$s[2]; + $tmp2=$s[3]; + } + $code.=" movzb ".&lo($s[0]).",$out\n"; + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + + $code.=" mov 2($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $code.=" and \$0x000000ff,$out\n"; + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" movzb ".&lo($tmp1).",$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" mov 0($sbox,$tmp0,8),$tmp0\n"; + $code.=" mov 0($sbox,$tmp1,8),$tmp1\n"; + $code.=" mov 2($sbox,$tmp2,8),$tmp2\n"; + + $code.=" and \$0x0000ff00,$tmp0\n"; + $code.=" and \$0x00ff0000,$tmp1\n"; + $code.=" and \$0xff000000,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t0,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t2,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_encrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt: +.cfi_startproc + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Lenc_loop +.align 16 +.Lenc_loop: +___ + if ($verticalspin) { &encvert(); } + else { &encstep(0,$s0,$s1,$s2,$s3); + &encstep(1,$s1,$s2,$s3,$s0); + &encstep(2,$s2,$s3,$s0,$s1); + &encstep(3,$s3,$s0,$s1,$s2); + } +$code.=<<___; + sub \$1,$rnds + jnz .Lenc_loop +___ + if ($verticalspin) { &enclastvert(); } + else { &enclast(0,$s0,$s1,$s2,$s3); + &enclast(1,$s1,$s2,$s3,$s0); + &enclast(2,$s2,$s3,$s0,$s1); + &enclast(3,$s3,$s0,$s1,$s2); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_encrypt,.-_x86_64_AES_encrypt +___ + +# it's possible to implement this by shifting tN by 8, filling least +# significant byte with byte load and finally bswap-ing at the end, +# but such partial register load kills Core 2... +sub enccompactvert() +{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + movzb `&lo("$s0")`,$t0 + movzb `&lo("$s1")`,$t1 + movzb `&lo("$s2")`,$t2 + movzb `&lo("$s3")`,$t3 + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s2 + movzb `&hi("$s3")`,$acc2 + movzb ($sbox,$t0,1),$t0 + movzb ($sbox,$t1,1),$t1 + movzb ($sbox,$t2,1),$t2 + movzb ($sbox,$t3,1),$t3 + + movzb ($sbox,$acc0,1),$t4 #$t0 + movzb `&hi("$s0")`,$acc0 + movzb ($sbox,$acc1,1),$t5 #$t1 + movzb `&lo("$s2")`,$acc1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + + shl \$8,$t4 + shr \$16,$s3 + shl \$8,$t5 + xor $t4,$t0 + shr \$16,$s0 + movzb `&lo("$s3")`,$t4 + shr \$16,$s1 + xor $t5,$t1 + shl \$8,$acc2 + movzb `&lo("$s0")`,$t5 + movzb ($sbox,$acc1,1),$acc1 #$t0 + xor $acc2,$t2 + + shl \$8,$acc0 + movzb `&lo("$s1")`,$acc2 + shl \$16,$acc1 + xor $acc0,$t3 + movzb ($sbox,$t4,1),$t4 #$t1 + movzb `&hi("$s3")`,$acc0 + movzb ($sbox,$t5,1),$t5 #$t2 + xor $acc1,$t0 + + shr \$8,$s2 + movzb `&hi("$s0")`,$acc1 + shl \$16,$t4 + shr \$8,$s1 + shl \$16,$t5 + xor $t4,$t1 + movzb ($sbox,$acc2,1),$acc2 #$t3 + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$acc1 #$t1 + movzb ($sbox,$s2,1),$s3 #$t3 + movzb ($sbox,$s1,1),$s2 #$t2 + + shl \$16,$acc2 + xor $t5,$t2 + shl \$24,$acc0 + xor $acc2,$t3 + shl \$24,$acc1 + xor $acc0,$t0 + shl \$24,$s3 + xor $acc1,$t1 + shl \$24,$s2 + mov $t0,$s0 + mov $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub enctransform_ref() +{ my $sn = shift; + my ($acc,$r2,$tmp)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + mov $sn,$acc + and \$0x80808080,$acc + mov $acc,$tmp + shr \$7,$tmp + lea ($sn,$sn),$r2 + sub $tmp,$acc + and \$0xfefefefe,$r2 + and \$0x1b1b1b1b,$acc + mov $sn,$tmp + xor $acc,$r2 + + xor $r2,$sn + rol \$24,$sn + xor $r2,$sn + ror \$16,$tmp + xor $tmp,$sn + ror \$8,$tmp + xor $tmp,$sn +___ +} + +# unlike decrypt case it does not pay off to parallelize enctransform +sub enctransform() +{ my ($t3,$r20,$r21)=($acc2,"%r8d","%r9d"); + +$code.=<<___; + mov \$0x80808080,$t0 + mov \$0x80808080,$t1 + and $s0,$t0 + and $s1,$t1 + mov $t0,$acc0 + mov $t1,$acc1 + shr \$7,$t0 + lea ($s0,$s0),$r20 + shr \$7,$t1 + lea ($s1,$s1),$r21 + sub $t0,$acc0 + sub $t1,$acc1 + and \$0xfefefefe,$r20 + and \$0xfefefefe,$r21 + and \$0x1b1b1b1b,$acc0 + and \$0x1b1b1b1b,$acc1 + mov $s0,$t0 + mov $s1,$t1 + xor $acc0,$r20 + xor $acc1,$r21 + + xor $r20,$s0 + xor $r21,$s1 + mov \$0x80808080,$t2 + rol \$24,$s0 + mov \$0x80808080,$t3 + rol \$24,$s1 + and $s2,$t2 + and $s3,$t3 + xor $r20,$s0 + xor $r21,$s1 + mov $t2,$acc0 + ror \$16,$t0 + mov $t3,$acc1 + ror \$16,$t1 + lea ($s2,$s2),$r20 + shr \$7,$t2 + xor $t0,$s0 + shr \$7,$t3 + xor $t1,$s1 + ror \$8,$t0 + lea ($s3,$s3),$r21 + ror \$8,$t1 + sub $t2,$acc0 + sub $t3,$acc1 + xor $t0,$s0 + xor $t1,$s1 + + and \$0xfefefefe,$r20 + and \$0xfefefefe,$r21 + and \$0x1b1b1b1b,$acc0 + and \$0x1b1b1b1b,$acc1 + mov $s2,$t2 + mov $s3,$t3 + xor $acc0,$r20 + xor $acc1,$r21 + + ror \$16,$t2 + xor $r20,$s2 + ror \$16,$t3 + xor $r21,$s3 + rol \$24,$s2 + mov 0($sbox),$acc0 # prefetch Te4 + rol \$24,$s3 + xor $r20,$s2 + mov 64($sbox),$acc1 + xor $r21,$s3 + mov 128($sbox),$r20 + xor $t2,$s2 + ror \$8,$t2 + xor $t3,$s3 + ror \$8,$t3 + xor $t2,$s2 + mov 192($sbox),$r21 + xor $t3,$s3 +___ +} + +$code.=<<___; +.type _x86_64_AES_encrypt_compact,\@abi-omnipotent +.align 16 +_x86_64_AES_encrypt_compact: +.cfi_startproc + lea 128($sbox),$inp # size optimization + mov 0-128($inp),$acc1 # prefetch Te4 + mov 32-128($inp),$acc2 + mov 64-128($inp),$t0 + mov 96-128($inp),$t1 + mov 128-128($inp),$acc1 + mov 160-128($inp),$acc2 + mov 192-128($inp),$t0 + mov 224-128($inp),$t1 + jmp .Lenc_loop_compact +.align 16 +.Lenc_loop_compact: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + lea 16($key),$key +___ + &enccompactvert(); +$code.=<<___; + cmp 16(%rsp),$key + je .Lenc_compact_done +___ + &enctransform(); +$code.=<<___; + jmp .Lenc_loop_compact +.align 16 +.Lenc_compact_done: + xor 0($key),$s0 + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact +___ + +# void AES_encrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.globl AES_encrypt +.type AES_encrypt,\@function,3 +.align 16 +.globl asm_AES_encrypt +.hidden asm_AES_encrypt +asm_AES_encrypt: +AES_encrypt: +.cfi_startproc + endbranch + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + # allocate frame "above" key schedule + lea -63(%rdx),%rcx # %rdx is key argument + and \$-64,%rsp + sub %rsp,%rcx + neg %rcx + and \$0x3c0,%rcx + sub %rcx,%rsp + sub \$32,%rsp + + mov %rsi,16(%rsp) # save out + mov %rax,24(%rsp) # save original stack pointer +.cfi_cfa_expression %rsp+24,deref,+8 +.Lenc_prologue: + + mov %rdx,$key + mov 240($key),$rnds # load rounds + + mov 0(%rdi),$s0 # load input vector + mov 4(%rdi),$s1 + mov 8(%rdi),$s2 + mov 12(%rdi),$s3 + + shl \$4,$rnds + lea ($key,$rnds),%rbp + mov $key,(%rsp) # key schedule + mov %rbp,8(%rsp) # end of key schedule + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + lea .LAES_Te+2048(%rip),$sbox + lea 768(%rsp),%rbp + sub $sbox,%rbp + and \$0x300,%rbp + lea ($sbox,%rbp),$sbox + + call _x86_64_AES_encrypt_compact + + mov 16(%rsp),$out # restore out + mov 24(%rsp),%rsi # restore saved stack pointer +.cfi_def_cfa %rsi,8 + mov $s0,0($out) # write output vector + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Lenc_epilogue: + ret +.cfi_endproc +.size AES_encrypt,.-AES_encrypt +___ + +#------------------------------------------------------------------# + +sub decvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + # favor 3-way issue Opteron pipeline... + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + mov 0($sbox,$acc0,8),$t0 + mov 0($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t2 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + movzb `&lo("$s3")`,$acc2 + xor 3($sbox,$acc0,8),$t0 + xor 3($sbox,$acc1,8),$t1 + mov 0($sbox,$acc2,8),$t3 + + movzb `&hi("$s1")`,$acc0 + shr \$16,$s0 + movzb `&hi("$s2")`,$acc2 + xor 3($sbox,$acc0,8),$t2 + shr \$16,$s3 + xor 3($sbox,$acc2,8),$t3 + + shr \$16,$s1 + lea 16($key),$key + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + xor 2($sbox,$acc0,8),$t0 + xor 2($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t2 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + movzb `&lo("$s1")`,$acc2 + xor 1($sbox,$acc0,8),$t0 + xor 1($sbox,$acc1,8),$t1 + xor 2($sbox,$acc2,8),$t3 + + movzb `&hi("$s3")`,$acc0 + mov 12($key),$s3 + movzb `&hi("$s0")`,$acc2 + xor 1($sbox,$acc0,8),$t2 + mov 0($key),$s0 + xor 1($sbox,$acc2,8),$t3 + + xor $t0,$s0 + mov 4($key),$s1 + mov 8($key),$s2 + xor $t2,$s2 + xor $t1,$s1 + xor $t3,$s3 +___ +} + +sub declastvert() +{ my $t3="%r8d"; # zaps $inp! + +$code.=<<___; + lea 2048($sbox),$sbox # size optimization + movzb `&lo("$s0")`,$acc0 + movzb `&lo("$s1")`,$acc1 + movzb `&lo("$s2")`,$acc2 + movzb ($sbox,$acc0,1),$t0 + movzb ($sbox,$acc1,1),$t1 + movzb ($sbox,$acc2,1),$t2 + + movzb `&lo("$s3")`,$acc0 + movzb `&hi("$s3")`,$acc1 + movzb `&hi("$s0")`,$acc2 + movzb ($sbox,$acc0,1),$t3 + movzb ($sbox,$acc1,1),$acc1 #$t0 + movzb ($sbox,$acc2,1),$acc2 #$t1 + + shl \$8,$acc1 + shl \$8,$acc2 + + xor $acc1,$t0 + xor $acc2,$t1 + shr \$16,$s3 + + movzb `&hi("$s1")`,$acc0 + movzb `&hi("$s2")`,$acc1 + shr \$16,$s0 + movzb ($sbox,$acc0,1),$acc0 #$t2 + movzb ($sbox,$acc1,1),$acc1 #$t3 + + shl \$8,$acc0 + shl \$8,$acc1 + shr \$16,$s1 + xor $acc0,$t2 + xor $acc1,$t3 + shr \$16,$s2 + + movzb `&lo("$s2")`,$acc0 + movzb `&lo("$s3")`,$acc1 + movzb `&lo("$s0")`,$acc2 + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$acc1 #$t1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + + shl \$16,$acc0 + shl \$16,$acc1 + shl \$16,$acc2 + + xor $acc0,$t0 + xor $acc1,$t1 + xor $acc2,$t2 + + movzb `&lo("$s1")`,$acc0 + movzb `&hi("$s1")`,$acc1 + movzb `&hi("$s2")`,$acc2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + movzb ($sbox,$acc1,1),$acc1 #$t0 + movzb ($sbox,$acc2,1),$acc2 #$t1 + + shl \$16,$acc0 + shl \$24,$acc1 + shl \$24,$acc2 + + xor $acc0,$t3 + xor $acc1,$t0 + xor $acc2,$t1 + + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + mov 16+12($key),$s3 + movzb ($sbox,$acc0,1),$acc0 #$t2 + movzb ($sbox,$acc1,1),$acc1 #$t3 + mov 16+0($key),$s0 + + shl \$24,$acc0 + shl \$24,$acc1 + + xor $acc0,$t2 + xor $acc1,$t3 + + mov 16+4($key),$s1 + mov 16+8($key),$s2 + lea -2048($sbox),$sbox + xor $t0,$s0 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +sub decstep() +{ my ($i,@s) = @_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" mov 0($sbox,$out,8),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" xor 3($sbox,$tmp0,8),$out\n"; + $code.=" xor 2($sbox,$tmp1,8),$out\n"; + $code.=" xor 1($sbox,$tmp2,8),$out\n"; + + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +sub declast() +{ my ($i,@s)=@_; + my $tmp0=$acc0; + my $tmp1=$acc1; + my $tmp2=$acc2; + my $out=($t0,$t1,$t2,$s[0])[$i]; + + $code.=" mov $s[0],$out\n" if ($i!=3); + $tmp1=$s[2] if ($i==3); + $code.=" mov $s[2],$tmp1\n" if ($i!=3); + $code.=" and \$0xFF,$out\n"; + + $code.=" movzb 2048($sbox,$out,1),$out\n"; + $code.=" shr \$16,$tmp1\n"; + $tmp2=$s[3] if ($i==3); + $code.=" mov $s[3],$tmp2\n" if ($i!=3); + + $tmp0=$s[1] if ($i==3); + $code.=" movzb ".&hi($s[1]).",$tmp0\n"; + $code.=" and \$0xFF,$tmp1\n"; + $code.=" shr \$24,$tmp2\n"; + + $code.=" movzb 2048($sbox,$tmp0,1),$tmp0\n"; + $code.=" movzb 2048($sbox,$tmp1,1),$tmp1\n"; + $code.=" movzb 2048($sbox,$tmp2,1),$tmp2\n"; + + $code.=" shl \$8,$tmp0\n"; + $code.=" shl \$16,$tmp1\n"; + $code.=" shl \$24,$tmp2\n"; + + $code.=" xor $tmp0,$out\n"; + $code.=" mov $t2,$s[1]\n" if ($i==3); + $code.=" xor $tmp1,$out\n"; + $code.=" mov $t1,$s[2]\n" if ($i==3); + $code.=" xor $tmp2,$out\n"; + $code.=" mov $t0,$s[3]\n" if ($i==3); + $code.="\n"; +} + +$code.=<<___; +.type _x86_64_AES_decrypt,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt: +.cfi_startproc + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + + mov 240($key),$rnds # load key->rounds + sub \$1,$rnds + jmp .Ldec_loop +.align 16 +.Ldec_loop: +___ + if ($verticalspin) { &decvert(); } + else { &decstep(0,$s0,$s3,$s2,$s1); + &decstep(1,$s1,$s0,$s3,$s2); + &decstep(2,$s2,$s1,$s0,$s3); + &decstep(3,$s3,$s2,$s1,$s0); + $code.=<<___; + lea 16($key),$key + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 +___ + } +$code.=<<___; + sub \$1,$rnds + jnz .Ldec_loop +___ + if ($verticalspin) { &declastvert(); } + else { &declast(0,$s0,$s3,$s2,$s1); + &declast(1,$s1,$s0,$s3,$s2); + &declast(2,$s2,$s1,$s0,$s3); + &declast(3,$s3,$s2,$s1,$s0); + $code.=<<___; + xor 16+0($key),$s0 # xor with key + xor 16+4($key),$s1 + xor 16+8($key),$s2 + xor 16+12($key),$s3 +___ + } +$code.=<<___; + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_decrypt,.-_x86_64_AES_decrypt +___ + +sub deccompactvert() +{ my ($t3,$t4,$t5)=("%r8d","%r9d","%r13d"); + +$code.=<<___; + movzb `&lo("$s0")`,$t0 + movzb `&lo("$s1")`,$t1 + movzb `&lo("$s2")`,$t2 + movzb `&lo("$s3")`,$t3 + movzb `&hi("$s3")`,$acc0 + movzb `&hi("$s0")`,$acc1 + shr \$16,$s3 + movzb `&hi("$s1")`,$acc2 + movzb ($sbox,$t0,1),$t0 + movzb ($sbox,$t1,1),$t1 + movzb ($sbox,$t2,1),$t2 + movzb ($sbox,$t3,1),$t3 + + movzb ($sbox,$acc0,1),$t4 #$t0 + movzb `&hi("$s2")`,$acc0 + movzb ($sbox,$acc1,1),$t5 #$t1 + movzb ($sbox,$acc2,1),$acc2 #$t2 + movzb ($sbox,$acc0,1),$acc0 #$t3 + + shr \$16,$s2 + shl \$8,$t5 + shl \$8,$t4 + movzb `&lo("$s2")`,$acc1 + shr \$16,$s0 + xor $t4,$t0 + shr \$16,$s1 + movzb `&lo("$s3")`,$t4 + + shl \$8,$acc2 + xor $t5,$t1 + shl \$8,$acc0 + movzb `&lo("$s0")`,$t5 + movzb ($sbox,$acc1,1),$acc1 #$t0 + xor $acc2,$t2 + movzb `&lo("$s1")`,$acc2 + + shl \$16,$acc1 + xor $acc0,$t3 + movzb ($sbox,$t4,1),$t4 #$t1 + movzb `&hi("$s1")`,$acc0 + movzb ($sbox,$acc2,1),$acc2 #$t3 + xor $acc1,$t0 + movzb ($sbox,$t5,1),$t5 #$t2 + movzb `&hi("$s2")`,$acc1 + + shl \$16,$acc2 + shl \$16,$t4 + shl \$16,$t5 + xor $acc2,$t3 + movzb `&hi("$s3")`,$acc2 + xor $t4,$t1 + shr \$8,$s0 + xor $t5,$t2 + + movzb ($sbox,$acc0,1),$acc0 #$t0 + movzb ($sbox,$acc1,1),$s1 #$t1 + movzb ($sbox,$acc2,1),$s2 #$t2 + movzb ($sbox,$s0,1),$s3 #$t3 + + mov $t0,$s0 + shl \$24,$acc0 + shl \$24,$s1 + shl \$24,$s2 + xor $acc0,$s0 + shl \$24,$s3 + xor $t1,$s1 + xor $t2,$s2 + xor $t3,$s3 +___ +} + +# parallelized version! input is pair of 64-bit values: %rax=s1.s0 +# and %rcx=s3.s2, output is four 32-bit values in %eax=s0, %ebx=s1, +# %ecx=s2 and %edx=s3. +sub dectransform() +{ my ($tp10,$tp20,$tp40,$tp80,$acc0)=("%rax","%r8", "%r9", "%r10","%rbx"); + my ($tp18,$tp28,$tp48,$tp88,$acc8)=("%rcx","%r11","%r12","%r13","%rdx"); + my $prefetch = shift; + +$code.=<<___; + mov $mask80,$tp40 + mov $mask80,$tp48 + and $tp10,$tp40 + and $tp18,$tp48 + mov $tp40,$acc0 + mov $tp48,$acc8 + shr \$7,$tp40 + lea ($tp10,$tp10),$tp20 + shr \$7,$tp48 + lea ($tp18,$tp18),$tp28 + sub $tp40,$acc0 + sub $tp48,$acc8 + and $maskfe,$tp20 + and $maskfe,$tp28 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp20 + xor $acc8,$tp28 + mov $mask80,$tp80 + mov $mask80,$tp88 + + and $tp20,$tp80 + and $tp28,$tp88 + mov $tp80,$acc0 + mov $tp88,$acc8 + shr \$7,$tp80 + lea ($tp20,$tp20),$tp40 + shr \$7,$tp88 + lea ($tp28,$tp28),$tp48 + sub $tp80,$acc0 + sub $tp88,$acc8 + and $maskfe,$tp40 + and $maskfe,$tp48 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp40 + xor $acc8,$tp48 + mov $mask80,$tp80 + mov $mask80,$tp88 + + and $tp40,$tp80 + and $tp48,$tp88 + mov $tp80,$acc0 + mov $tp88,$acc8 + shr \$7,$tp80 + xor $tp10,$tp20 # tp2^=tp1 + shr \$7,$tp88 + xor $tp18,$tp28 # tp2^=tp1 + sub $tp80,$acc0 + sub $tp88,$acc8 + lea ($tp40,$tp40),$tp80 + lea ($tp48,$tp48),$tp88 + xor $tp10,$tp40 # tp4^=tp1 + xor $tp18,$tp48 # tp4^=tp1 + and $maskfe,$tp80 + and $maskfe,$tp88 + and $mask1b,$acc0 + and $mask1b,$acc8 + xor $acc0,$tp80 + xor $acc8,$tp88 + + xor $tp80,$tp10 # tp1^=tp8 + xor $tp88,$tp18 # tp1^=tp8 + xor $tp80,$tp20 # tp2^tp1^=tp8 + xor $tp88,$tp28 # tp2^tp1^=tp8 + mov $tp10,$acc0 + mov $tp18,$acc8 + xor $tp80,$tp40 # tp4^tp1^=tp8 + shr \$32,$acc0 + xor $tp88,$tp48 # tp4^tp1^=tp8 + shr \$32,$acc8 + xor $tp20,$tp80 # tp8^=tp8^tp2^tp1=tp2^tp1 + rol \$8,`&LO("$tp10")` # ROTATE(tp1^tp8,8) + xor $tp28,$tp88 # tp8^=tp8^tp2^tp1=tp2^tp1 + rol \$8,`&LO("$tp18")` # ROTATE(tp1^tp8,8) + xor $tp40,$tp80 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2 + rol \$8,`&LO("$acc0")` # ROTATE(tp1^tp8,8) + xor $tp48,$tp88 # tp2^tp1^=tp8^tp4^tp1=tp8^tp4^tp2 + + rol \$8,`&LO("$acc8")` # ROTATE(tp1^tp8,8) + xor `&LO("$tp80")`,`&LO("$tp10")` + shr \$32,$tp80 + xor `&LO("$tp88")`,`&LO("$tp18")` + shr \$32,$tp88 + xor `&LO("$tp80")`,`&LO("$acc0")` + xor `&LO("$tp88")`,`&LO("$acc8")` + + mov $tp20,$tp80 + rol \$24,`&LO("$tp20")` # ROTATE(tp2^tp1^tp8,24) + mov $tp28,$tp88 + rol \$24,`&LO("$tp28")` # ROTATE(tp2^tp1^tp8,24) + shr \$32,$tp80 + xor `&LO("$tp20")`,`&LO("$tp10")` + shr \$32,$tp88 + xor `&LO("$tp28")`,`&LO("$tp18")` + rol \$24,`&LO("$tp80")` # ROTATE(tp2^tp1^tp8,24) + mov $tp40,$tp20 + rol \$24,`&LO("$tp88")` # ROTATE(tp2^tp1^tp8,24) + mov $tp48,$tp28 + shr \$32,$tp20 + xor `&LO("$tp80")`,`&LO("$acc0")` + shr \$32,$tp28 + xor `&LO("$tp88")`,`&LO("$acc8")` + + `"mov 0($sbox),$mask80" if ($prefetch)` + rol \$16,`&LO("$tp40")` # ROTATE(tp4^tp1^tp8,16) + `"mov 64($sbox),$maskfe" if ($prefetch)` + rol \$16,`&LO("$tp48")` # ROTATE(tp4^tp1^tp8,16) + `"mov 128($sbox),$mask1b" if ($prefetch)` + rol \$16,`&LO("$tp20")` # ROTATE(tp4^tp1^tp8,16) + `"mov 192($sbox),$tp80" if ($prefetch)` + xor `&LO("$tp40")`,`&LO("$tp10")` + rol \$16,`&LO("$tp28")` # ROTATE(tp4^tp1^tp8,16) + xor `&LO("$tp48")`,`&LO("$tp18")` + `"mov 256($sbox),$tp88" if ($prefetch)` + xor `&LO("$tp20")`,`&LO("$acc0")` + xor `&LO("$tp28")`,`&LO("$acc8")` +___ +} + +$code.=<<___; +.type _x86_64_AES_decrypt_compact,\@abi-omnipotent +.align 16 +_x86_64_AES_decrypt_compact: +.cfi_startproc + lea 128($sbox),$inp # size optimization + mov 0-128($inp),$acc1 # prefetch Td4 + mov 32-128($inp),$acc2 + mov 64-128($inp),$t0 + mov 96-128($inp),$t1 + mov 128-128($inp),$acc1 + mov 160-128($inp),$acc2 + mov 192-128($inp),$t0 + mov 224-128($inp),$t1 + jmp .Ldec_loop_compact + +.align 16 +.Ldec_loop_compact: + xor 0($key),$s0 # xor with key + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + lea 16($key),$key +___ + &deccompactvert(); +$code.=<<___; + cmp 16(%rsp),$key + je .Ldec_compact_done + + mov 256+0($sbox),$mask80 + shl \$32,%rbx + shl \$32,%rdx + mov 256+8($sbox),$maskfe + or %rbx,%rax + or %rdx,%rcx + mov 256+16($sbox),$mask1b +___ + &dectransform(1); +$code.=<<___; + jmp .Ldec_loop_compact +.align 16 +.Ldec_compact_done: + xor 0($key),$s0 + xor 4($key),$s1 + xor 8($key),$s2 + xor 12($key),$s3 + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact +___ + +# void AES_decrypt (const void *inp,void *out,const AES_KEY *key); +$code.=<<___; +.globl AES_decrypt +.type AES_decrypt,\@function,3 +.align 16 +.globl asm_AES_decrypt +.hidden asm_AES_decrypt +asm_AES_decrypt: +AES_decrypt: +.cfi_startproc + endbranch + mov %rsp,%rax +.cfi_def_cfa_register %rax + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + + # allocate frame "above" key schedule + lea -63(%rdx),%rcx # %rdx is key argument + and \$-64,%rsp + sub %rsp,%rcx + neg %rcx + and \$0x3c0,%rcx + sub %rcx,%rsp + sub \$32,%rsp + + mov %rsi,16(%rsp) # save out + mov %rax,24(%rsp) # save original stack pointer +.cfi_cfa_expression %rsp+24,deref,+8 +.Ldec_prologue: + + mov %rdx,$key + mov 240($key),$rnds # load rounds + + mov 0(%rdi),$s0 # load input vector + mov 4(%rdi),$s1 + mov 8(%rdi),$s2 + mov 12(%rdi),$s3 + + shl \$4,$rnds + lea ($key,$rnds),%rbp + mov $key,(%rsp) # key schedule + mov %rbp,8(%rsp) # end of key schedule + + # pick Td4 copy which can't "overlap" with stack frame or key schedule + lea .LAES_Td+2048(%rip),$sbox + lea 768(%rsp),%rbp + sub $sbox,%rbp + and \$0x300,%rbp + lea ($sbox,%rbp),$sbox + shr \$3,%rbp # recall "magic" constants! + add %rbp,$sbox + + call _x86_64_AES_decrypt_compact + + mov 16(%rsp),$out # restore out + mov 24(%rsp),%rsi # restore saved stack pointer +.cfi_def_cfa %rsi,8 + mov $s0,0($out) # write output vector + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + mov -48(%rsi),%r15 +.cfi_restore %r15 + mov -40(%rsi),%r14 +.cfi_restore %r14 + mov -32(%rsi),%r13 +.cfi_restore %r13 + mov -24(%rsi),%r12 +.cfi_restore %r12 + mov -16(%rsi),%rbp +.cfi_restore %rbp + mov -8(%rsi),%rbx +.cfi_restore %rbx + lea (%rsi),%rsp +.cfi_def_cfa_register %rsp +.Ldec_epilogue: + ret +.cfi_endproc +.size AES_decrypt,.-AES_decrypt +___ +#------------------------------------------------------------------# + +sub enckey() +{ +$code.=<<___; + movz %dl,%esi # rk[i]>>0 + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[i]>>8 + shl \$24,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shr \$16,%edx + movz %dl,%esi # rk[i]>>16 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[i]>>24 + shl \$8,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shl \$16,%ebx + xor %ebx,%eax + + xor 1024-128(%rbp,%rcx,4),%eax # rcon +___ +} + +# int AES_set_encrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +$code.=<<___; +.globl AES_set_encrypt_key +.type AES_set_encrypt_key,\@function,3 +.align 16 +AES_set_encrypt_key: +.cfi_startproc + endbranch + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 # redundant, but allows to share +.cfi_push %r12 + push %r13 # exception handler... +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + sub \$8,%rsp +.cfi_adjust_cfa_offset 8 +.Lenc_key_prologue: + + call _x86_64_AES_set_encrypt_key + + mov 40(%rsp),%rbp +.cfi_restore %rbp + mov 48(%rsp),%rbx +.cfi_restore %rbx + add \$56,%rsp +.cfi_adjust_cfa_offset -56 +.Lenc_key_epilogue: + ret +.cfi_endproc +.size AES_set_encrypt_key,.-AES_set_encrypt_key + +.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent +.align 16 +_x86_64_AES_set_encrypt_key: +.cfi_startproc + mov %esi,%ecx # %ecx=bits + mov %rdi,%rsi # %rsi=userKey + mov %rdx,%rdi # %rdi=key + + test \$-1,%rsi + jz .Lbadpointer + test \$-1,%rdi + jz .Lbadpointer + + lea .LAES_Te(%rip),%rbp + lea 2048+128(%rbp),%rbp + + # prefetch Te4 + mov 0-128(%rbp),%eax + mov 32-128(%rbp),%ebx + mov 64-128(%rbp),%r8d + mov 96-128(%rbp),%edx + mov 128-128(%rbp),%eax + mov 160-128(%rbp),%ebx + mov 192-128(%rbp),%r8d + mov 224-128(%rbp),%edx + + cmp \$128,%ecx + je .L10rounds + cmp \$192,%ecx + je .L12rounds + cmp \$256,%ecx + je .L14rounds + mov \$-2,%rax # invalid number of bits + jmp .Lexit + +.L10rounds: + mov 0(%rsi),%rax # copy first 4 dwords + mov 8(%rsi),%rdx + mov %rax,0(%rdi) + mov %rdx,8(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L10shortcut +.align 4 +.L10loop: + mov 0(%rdi),%eax # rk[0] + mov 12(%rdi),%edx # rk[3] +.L10shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,16(%rdi) # rk[4] + xor 4(%rdi),%eax + mov %eax,20(%rdi) # rk[5] + xor 8(%rdi),%eax + mov %eax,24(%rdi) # rk[6] + xor 12(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + add \$1,%ecx + lea 16(%rdi),%rdi + cmp \$10,%ecx + jl .L10loop + + movl \$10,80(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L12rounds: + mov 0(%rsi),%rax # copy first 6 dwords + mov 8(%rsi),%rbx + mov 16(%rsi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rdx,16(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L12shortcut +.align 4 +.L12loop: + mov 0(%rdi),%eax # rk[0] + mov 20(%rdi),%edx # rk[5] +.L12shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,24(%rdi) # rk[6] + xor 4(%rdi),%eax + mov %eax,28(%rdi) # rk[7] + xor 8(%rdi),%eax + mov %eax,32(%rdi) # rk[8] + xor 12(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + + cmp \$7,%ecx + je .L12break + add \$1,%ecx + + xor 16(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 20(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + lea 24(%rdi),%rdi + jmp .L12loop +.L12break: + movl \$12,72(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.L14rounds: + mov 0(%rsi),%rax # copy first 8 dwords + mov 8(%rsi),%rbx + mov 16(%rsi),%rcx + mov 24(%rsi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,16(%rdi) + mov %rdx,24(%rdi) + + shr \$32,%rdx + xor %ecx,%ecx + jmp .L14shortcut +.align 4 +.L14loop: + mov 0(%rdi),%eax # rk[0] + mov 28(%rdi),%edx # rk[4] +.L14shortcut: +___ + &enckey (); +$code.=<<___; + mov %eax,32(%rdi) # rk[8] + xor 4(%rdi),%eax + mov %eax,36(%rdi) # rk[9] + xor 8(%rdi),%eax + mov %eax,40(%rdi) # rk[10] + xor 12(%rdi),%eax + mov %eax,44(%rdi) # rk[11] + + cmp \$6,%ecx + je .L14break + add \$1,%ecx + + mov %eax,%edx + mov 16(%rdi),%eax # rk[4] + movz %dl,%esi # rk[11]>>0 + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[11]>>8 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shr \$16,%edx + shl \$8,%ebx + movz %dl,%esi # rk[11]>>16 + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + movz %dh,%esi # rk[11]>>24 + shl \$16,%ebx + xor %ebx,%eax + + movzb -128(%rbp,%rsi),%ebx + shl \$24,%ebx + xor %ebx,%eax + + mov %eax,48(%rdi) # rk[12] + xor 20(%rdi),%eax + mov %eax,52(%rdi) # rk[13] + xor 24(%rdi),%eax + mov %eax,56(%rdi) # rk[14] + xor 28(%rdi),%eax + mov %eax,60(%rdi) # rk[15] + + lea 32(%rdi),%rdi + jmp .L14loop +.L14break: + movl \$14,48(%rdi) # setup number of rounds + xor %rax,%rax + jmp .Lexit + +.Lbadpointer: + mov \$-1,%rax +.Lexit: + .byte 0xf3,0xc3 # rep ret +.cfi_endproc +.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key +___ + +sub deckey_ref() +{ my ($i,$ptr,$te,$td) = @_; + my ($tp1,$tp2,$tp4,$tp8,$acc)=("%eax","%ebx","%edi","%edx","%r8d"); +$code.=<<___; + mov $i($ptr),$tp1 + mov $tp1,$acc + and \$0x80808080,$acc + mov $acc,$tp4 + shr \$7,$tp4 + lea 0($tp1,$tp1),$tp2 + sub $tp4,$acc + and \$0xfefefefe,$tp2 + and \$0x1b1b1b1b,$acc + xor $tp2,$acc + mov $acc,$tp2 + + and \$0x80808080,$acc + mov $acc,$tp8 + shr \$7,$tp8 + lea 0($tp2,$tp2),$tp4 + sub $tp8,$acc + and \$0xfefefefe,$tp4 + and \$0x1b1b1b1b,$acc + xor $tp1,$tp2 # tp2^tp1 + xor $tp4,$acc + mov $acc,$tp4 + + and \$0x80808080,$acc + mov $acc,$tp8 + shr \$7,$tp8 + sub $tp8,$acc + lea 0($tp4,$tp4),$tp8 + xor $tp1,$tp4 # tp4^tp1 + and \$0xfefefefe,$tp8 + and \$0x1b1b1b1b,$acc + xor $acc,$tp8 + + xor $tp8,$tp1 # tp1^tp8 + rol \$8,$tp1 # ROTATE(tp1^tp8,8) + xor $tp8,$tp2 # tp2^tp1^tp8 + xor $tp8,$tp4 # tp4^tp1^tp8 + xor $tp2,$tp8 + xor $tp4,$tp8 # tp8^(tp8^tp4^tp1)^(tp8^tp2^tp1)=tp8^tp4^tp2 + + xor $tp8,$tp1 + rol \$24,$tp2 # ROTATE(tp2^tp1^tp8,24) + xor $tp2,$tp1 + rol \$16,$tp4 # ROTATE(tp4^tp1^tp8,16) + xor $tp4,$tp1 + + mov $tp1,$i($ptr) +___ +} + +# int AES_set_decrypt_key(const unsigned char *userKey, const int bits, +# AES_KEY *key) +$code.=<<___; +.globl AES_set_decrypt_key +.type AES_set_decrypt_key,\@function,3 +.align 16 +AES_set_decrypt_key: +.cfi_startproc + endbranch + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + push %rdx # save key schedule +.cfi_adjust_cfa_offset 8 +.Ldec_key_prologue: + + call _x86_64_AES_set_encrypt_key + mov (%rsp),%r8 # restore key schedule + cmp \$0,%eax + jne .Labort + + mov 240(%r8),%r14d # pull number of rounds + xor %rdi,%rdi + lea (%rdi,%r14d,4),%rcx + mov %r8,%rsi + lea (%r8,%rcx,4),%rdi # pointer to last chunk +.align 4 +.Linvert: + mov 0(%rsi),%rax + mov 8(%rsi),%rbx + mov 0(%rdi),%rcx + mov 8(%rdi),%rdx + mov %rax,0(%rdi) + mov %rbx,8(%rdi) + mov %rcx,0(%rsi) + mov %rdx,8(%rsi) + lea 16(%rsi),%rsi + lea -16(%rdi),%rdi + cmp %rsi,%rdi + jne .Linvert + + lea .LAES_Te+2048+1024(%rip),%rax # rcon + + mov 40(%rax),$mask80 + mov 48(%rax),$maskfe + mov 56(%rax),$mask1b + + mov %r8,$key + sub \$1,%r14d +.align 4 +.Lpermute: + lea 16($key),$key + mov 0($key),%rax + mov 8($key),%rcx +___ + &dectransform (); +$code.=<<___; + mov %eax,0($key) + mov %ebx,4($key) + mov %ecx,8($key) + mov %edx,12($key) + sub \$1,%r14d + jnz .Lpermute + + xor %rax,%rax +.Labort: + mov 8(%rsp),%r15 +.cfi_restore %r15 + mov 16(%rsp),%r14 +.cfi_restore %r14 + mov 24(%rsp),%r13 +.cfi_restore %r13 + mov 32(%rsp),%r12 +.cfi_restore %r12 + mov 40(%rsp),%rbp +.cfi_restore %rbp + mov 48(%rsp),%rbx +.cfi_restore %rbx + add \$56,%rsp +.cfi_adjust_cfa_offset -56 +.Ldec_key_epilogue: + ret +.cfi_endproc +.size AES_set_decrypt_key,.-AES_set_decrypt_key +___ + +# void AES_cbc_encrypt (const void char *inp, unsigned char *out, +# size_t length, const AES_KEY *key, +# unsigned char *ivp,const int enc); +{ +# stack frame layout +# -8(%rsp) return address +my $keyp="0(%rsp)"; # one to pass as $key +my $keyend="8(%rsp)"; # &(keyp->rd_key[4*keyp->rounds]) +my $_rsp="16(%rsp)"; # saved %rsp +my $_inp="24(%rsp)"; # copy of 1st parameter, inp +my $_out="32(%rsp)"; # copy of 2nd parameter, out +my $_len="40(%rsp)"; # copy of 3rd parameter, length +my $_key="48(%rsp)"; # copy of 4th parameter, key +my $_ivp="56(%rsp)"; # copy of 5th parameter, ivp +my $ivec="64(%rsp)"; # ivec[16] +my $aes_key="80(%rsp)"; # copy of aes_key +my $mark="80+240(%rsp)"; # copy of aes_key->rounds + +$code.=<<___; +.globl AES_cbc_encrypt +.type AES_cbc_encrypt,\@function,6 +.align 16 +.extern OPENSSL_ia32cap_P +.globl asm_AES_cbc_encrypt +.hidden asm_AES_cbc_encrypt +asm_AES_cbc_encrypt: +AES_cbc_encrypt: +.cfi_startproc + endbranch + cmp \$0,%rdx # check length + je .Lcbc_epilogue + pushfq +# This could be .cfi_push 49, but libunwind fails on registers it does not +# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087. +.cfi_adjust_cfa_offset 8 + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lcbc_prologue: + + cld + mov %r9d,%r9d # clear upper half of enc + + lea .LAES_Te(%rip),$sbox + lea .LAES_Td(%rip),%r10 + cmp \$0,%r9 + cmoveq %r10,$sbox + +.cfi_remember_state + mov OPENSSL_ia32cap_P(%rip),%r10d + cmp \$$speed_limit,%rdx + jb .Lcbc_slow_prologue + test \$15,%rdx + jnz .Lcbc_slow_prologue + bt \$28,%r10d + jc .Lcbc_slow_prologue + + # allocate aligned stack frame... + lea -88-248(%rsp),$key + and \$-64,$key + + # ... and make sure it doesn't alias with AES_T[ed] modulo 4096 + mov $sbox,%r10 + lea 2304($sbox),%r11 + mov $key,%r12 + and \$0xFFF,%r10 # s = $sbox&0xfff + and \$0xFFF,%r11 # e = ($sbox+2048)&0xfff + and \$0xFFF,%r12 # p = %rsp&0xfff + + cmp %r11,%r12 # if (p=>e) %rsp =- (p-e); + jb .Lcbc_te_break_out + sub %r11,%r12 + sub %r12,$key + jmp .Lcbc_te_ok +.Lcbc_te_break_out: # else %rsp -= (p-s)&0xfff + framesz + sub %r10,%r12 + and \$0xFFF,%r12 + add \$320,%r12 + sub %r12,$key +.align 4 +.Lcbc_te_ok: + + xchg %rsp,$key +.cfi_def_cfa_register $key + #add \$8,%rsp # reserve for return address! + mov $key,$_rsp # save %rsp +.cfi_cfa_expression $_rsp,deref,+64 +.Lcbc_fast_body: + mov %rdi,$_inp # save copy of inp + mov %rsi,$_out # save copy of out + mov %rdx,$_len # save copy of len + mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + movl \$0,$mark # copy of aes_key->rounds = 0; + mov %r8,%rbp # rearrange input arguments + mov %r9,%rbx + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + + mov 240($key),%eax # key->rounds + # do we copy key schedule to stack? + mov $key,%r10 + sub $sbox,%r10 + and \$0xfff,%r10 + cmp \$2304,%r10 + jb .Lcbc_do_ecopy + cmp \$4096-248,%r10 + jb .Lcbc_skip_ecopy +.align 4 +.Lcbc_do_ecopy: + mov $key,%rsi + lea $aes_key,%rdi + lea $aes_key,$key + mov \$240/8,%ecx + .long 0x90A548F3 # rep movsq + mov %eax,(%rdi) # copy aes_key->rounds +.Lcbc_skip_ecopy: + mov $key,$keyp # save key pointer + + mov \$18,%ecx +.align 4 +.Lcbc_prefetch_te: + mov 0($sbox),%r10 + mov 32($sbox),%r11 + mov 64($sbox),%r12 + mov 96($sbox),%r13 + lea 128($sbox),$sbox + sub \$1,%ecx + jnz .Lcbc_prefetch_te + lea -2304($sbox),$sbox + + cmp \$0,%rbx + je .LFAST_DECRYPT + +#----------------------------- ENCRYPT -----------------------------# + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + +.align 4 +.Lcbc_fast_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_encrypt + + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + mov %r10,$_len + jnz .Lcbc_fast_enc_loop + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + + jmp .Lcbc_fast_cleanup + +#----------------------------- DECRYPT -----------------------------# +.align 16 +.LFAST_DECRYPT: + cmp $inp,$out + je .Lcbc_fast_dec_in_place + + mov %rbp,$ivec +.align 4 +.Lcbc_fast_dec_loop: + mov 0($inp),$s0 # read input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_decrypt + + mov $ivec,%rbp # load ivp + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 # load len + xor 0(%rbp),$s0 # xor iv + xor 4(%rbp),$s1 + xor 8(%rbp),$s2 + xor 12(%rbp),$s3 + mov $inp,%rbp # current input, next iv + + sub \$16,%r10 + mov %r10,$_len # update len + mov %rbp,$ivec # update ivp + + mov $s0,0($out) # write output + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jnz .Lcbc_fast_dec_loop + mov $_ivp,%r12 # load user ivp + mov 0(%rbp),%r10 # load iv + mov 8(%rbp),%r11 + mov %r10,0(%r12) # copy back to user + mov %r11,8(%r12) + jmp .Lcbc_fast_cleanup + +.align 16 +.Lcbc_fast_dec_in_place: + mov 0(%rbp),%r10 # copy iv to stack + mov 8(%rbp),%r11 + mov %r10,0+$ivec + mov %r11,8+$ivec +.align 4 +.Lcbc_fast_dec_in_place_loop: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # if ($verticalspin) save inp + + call _x86_64_AES_decrypt + + mov $_inp,$inp # if ($verticalspin) restore inp + mov $_len,%r10 + xor 0+$ivec,$s0 + xor 4+$ivec,$s1 + xor 8+$ivec,$s2 + xor 12+$ivec,$s3 + + mov 0($inp),%r11 # load input + mov 8($inp),%r12 + sub \$16,%r10 + jz .Lcbc_fast_dec_in_place_done + + mov %r11,0+$ivec # copy input to iv + mov %r12,8+$ivec + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + mov %r10,$_len + jmp .Lcbc_fast_dec_in_place_loop +.Lcbc_fast_dec_in_place_done: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0($out) # save output [zaps input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + +.align 4 +.Lcbc_fast_cleanup: + cmpl \$0,$mark # was the key schedule copied? + lea $aes_key,%rdi + je .Lcbc_exit + mov \$240/8,%ecx + xor %rax,%rax + .long 0x90AB48F3 # rep stosq + + jmp .Lcbc_exit + +#--------------------------- SLOW ROUTINE ---------------------------# +.align 16 +.Lcbc_slow_prologue: +.cfi_restore_state + # allocate aligned stack frame... + lea -88(%rsp),%rbp + and \$-64,%rbp + # ... just "above" key schedule + lea -88-63(%rcx),%r10 + sub %rbp,%r10 + neg %r10 + and \$0x3c0,%r10 + sub %r10,%rbp + + xchg %rsp,%rbp +.cfi_def_cfa_register %rbp + #add \$8,%rsp # reserve for return address! + mov %rbp,$_rsp # save %rsp +.cfi_cfa_expression $_rsp,deref,+64 +.Lcbc_slow_body: + #mov %rdi,$_inp # save copy of inp + #mov %rsi,$_out # save copy of out + #mov %rdx,$_len # save copy of len + #mov %rcx,$_key # save copy of key + mov %r8,$_ivp # save copy of ivp + mov %r8,%rbp # rearrange input arguments + mov %r9,%rbx + mov %rsi,$out + mov %rdi,$inp + mov %rcx,$key + mov %rdx,%r10 + + mov 240($key),%eax + mov $key,$keyp # save key pointer + shl \$4,%eax + lea ($key,%rax),%rax + mov %rax,$keyend + + # pick Te4 copy which can't "overlap" with stack frame or key schedule + lea 2048($sbox),$sbox + lea 768-8(%rsp),%rax + sub $sbox,%rax + and \$0x300,%rax + lea ($sbox,%rax),$sbox + + cmp \$0,%rbx + je .LSLOW_DECRYPT + +#--------------------------- SLOW ENCRYPT ---------------------------# + test \$-16,%r10 # check upon length + mov 0(%rbp),$s0 # load iv + mov 4(%rbp),$s1 + mov 8(%rbp),$s2 + mov 12(%rbp),$s3 + jz .Lcbc_slow_enc_tail # short input... + +.align 4 +.Lcbc_slow_enc_loop: + xor 0($inp),$s0 + xor 4($inp),$s1 + xor 8($inp),$s2 + xor 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # save inp + mov $out,$_out # save out + mov %r10,$_len # save len + + call _x86_64_AES_encrypt_compact + + mov $_inp,$inp # restore inp + mov $_out,$out # restore out + mov $_len,%r10 # restore len + mov $s0,0($out) + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + sub \$16,%r10 + test \$-16,%r10 + jnz .Lcbc_slow_enc_loop + test \$15,%r10 + jnz .Lcbc_slow_enc_tail + mov $_ivp,%rbp # restore ivp + mov $s0,0(%rbp) # save ivec + mov $s1,4(%rbp) + mov $s2,8(%rbp) + mov $s3,12(%rbp) + + jmp .Lcbc_exit + +.align 4 +.Lcbc_slow_enc_tail: + mov %rax,%r11 + mov %rcx,%r12 + mov %r10,%rcx + mov $inp,%rsi + mov $out,%rdi + .long 0x9066A4F3 # rep movsb + mov \$16,%rcx # zero tail + sub %r10,%rcx + xor %rax,%rax + .long 0x9066AAF3 # rep stosb + mov $out,$inp # this is not a mistake! + mov \$16,%r10 # len=16 + mov %r11,%rax + mov %r12,%rcx + jmp .Lcbc_slow_enc_loop # one more spin... +#--------------------------- SLOW DECRYPT ---------------------------# +.align 16 +.LSLOW_DECRYPT: + shr \$3,%rax + add %rax,$sbox # recall "magic" constants! + + mov 0(%rbp),%r11 # copy iv to stack + mov 8(%rbp),%r12 + mov %r11,0+$ivec + mov %r12,8+$ivec + +.align 4 +.Lcbc_slow_dec_loop: + mov 0($inp),$s0 # load input + mov 4($inp),$s1 + mov 8($inp),$s2 + mov 12($inp),$s3 + mov $keyp,$key # restore key + mov $inp,$_inp # save inp + mov $out,$_out # save out + mov %r10,$_len # save len + + call _x86_64_AES_decrypt_compact + + mov $_inp,$inp # restore inp + mov $_out,$out # restore out + mov $_len,%r10 + xor 0+$ivec,$s0 + xor 4+$ivec,$s1 + xor 8+$ivec,$s2 + xor 12+$ivec,$s3 + + mov 0($inp),%r11 # load input + mov 8($inp),%r12 + sub \$16,%r10 + jc .Lcbc_slow_dec_partial + jz .Lcbc_slow_dec_done + + mov %r11,0+$ivec # copy input to iv + mov %r12,8+$ivec + + mov $s0,0($out) # save output [can zap input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + lea 16($inp),$inp + lea 16($out),$out + jmp .Lcbc_slow_dec_loop +.Lcbc_slow_dec_done: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0($out) # save output [can zap input] + mov $s1,4($out) + mov $s2,8($out) + mov $s3,12($out) + + jmp .Lcbc_exit + +.align 4 +.Lcbc_slow_dec_partial: + mov $_ivp,%rdi + mov %r11,0(%rdi) # copy iv back to user + mov %r12,8(%rdi) + + mov $s0,0+$ivec # save output to stack + mov $s1,4+$ivec + mov $s2,8+$ivec + mov $s3,12+$ivec + + mov $out,%rdi + lea $ivec,%rsi + lea 16(%r10),%rcx + .long 0x9066A4F3 # rep movsb + jmp .Lcbc_exit + +.align 16 +.Lcbc_exit: + mov $_rsp,%rsi +.cfi_def_cfa %rsi,64 + mov (%rsi),%r15 +.cfi_restore %r15 + mov 8(%rsi),%r14 +.cfi_restore %r14 + mov 16(%rsi),%r13 +.cfi_restore %r13 + mov 24(%rsi),%r12 +.cfi_restore %r12 + mov 32(%rsi),%rbp +.cfi_restore %rbp + mov 40(%rsi),%rbx +.cfi_restore %rbx + lea 48(%rsi),%rsp +.cfi_def_cfa %rsp,16 +.Lcbc_popfq: + popfq +# This could be .cfi_pop 49, but libunwind fails on registers it does not +# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087. +.cfi_adjust_cfa_offset -8 +.Lcbc_epilogue: + ret +.cfi_endproc +.size AES_cbc_encrypt,.-AES_cbc_encrypt +___ +} + +$code.=<<___; +.align 64 +.LAES_Te: +___ + &_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6); + &_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591); + &_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56); + &_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec); + &_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa); + &_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb); + &_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45); + &_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b); + &_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c); + &_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83); + &_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9); + &_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a); + &_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d); + &_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f); + &_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df); + &_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea); + &_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34); + &_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b); + &_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d); + &_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413); + &_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1); + &_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6); + &_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972); + &_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85); + &_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed); + &_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511); + &_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe); + &_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b); + &_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05); + &_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1); + &_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142); + &_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf); + &_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3); + &_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e); + &_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a); + &_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6); + &_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3); + &_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b); + &_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428); + &_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad); + &_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14); + &_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8); + &_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4); + &_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2); + &_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda); + &_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949); + &_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf); + &_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810); + &_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c); + &_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697); + &_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e); + &_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f); + &_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc); + &_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c); + &_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969); + &_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27); + &_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122); + &_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433); + &_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9); + &_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5); + &_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a); + &_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0); + &_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e); + &_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c); + +#Te4 # four copies of Te4 to choose from to avoid L1 aliasing + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); + + &data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5); + &data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76); + &data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0); + &data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0); + &data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc); + &data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15); + &data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a); + &data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75); + &data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0); + &data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84); + &data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b); + &data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf); + &data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85); + &data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8); + &data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5); + &data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2); + &data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17); + &data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73); + &data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88); + &data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb); + &data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c); + &data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79); + &data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9); + &data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08); + &data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6); + &data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a); + &data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e); + &data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e); + &data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94); + &data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf); + &data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68); + &data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16); +#rcon: +$code.=<<___; + .long 0x00000001, 0x00000002, 0x00000004, 0x00000008 + .long 0x00000010, 0x00000020, 0x00000040, 0x00000080 + .long 0x0000001b, 0x00000036, 0x80808080, 0x80808080 + .long 0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b +___ +$code.=<<___; +.align 64 +.LAES_Td: +___ + &_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a); + &_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b); + &_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5); + &_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5); + &_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d); + &_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b); + &_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295); + &_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e); + &_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927); + &_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d); + &_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362); + &_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9); + &_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52); + &_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566); + &_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3); + &_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed); + &_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e); + &_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4); + &_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4); + &_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd); + &_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d); + &_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060); + &_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967); + &_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879); + &_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000); + &_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c); + &_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36); + &_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624); + &_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b); + &_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c); + &_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12); + &_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14); + &_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3); + &_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b); + &_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8); + &_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684); + &_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7); + &_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177); + &_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947); + &_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322); + &_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498); + &_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f); + &_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54); + &_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382); + &_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf); + &_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb); + &_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83); + &_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef); + &_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029); + &_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235); + &_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733); + &_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117); + &_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4); + &_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546); + &_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb); + &_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d); + &_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb); + &_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a); + &_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773); + &_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478); + &_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2); + &_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff); + &_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664); + &_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0); + +#Td4: # four copies of Td4 to choose from to avoid L1 aliasing + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +___ + &data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38); + &data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb); + &data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87); + &data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb); + &data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d); + &data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e); + &data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2); + &data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25); + &data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16); + &data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92); + &data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda); + &data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84); + &data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a); + &data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06); + &data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02); + &data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b); + &data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea); + &data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73); + &data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85); + &data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e); + &data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89); + &data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b); + &data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20); + &data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4); + &data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31); + &data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f); + &data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d); + &data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef); + &data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0); + &data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61); + &data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26); + &data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d); +$code.=<<___; + .long 0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe + .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 +.asciz "AES for x86_64, CRYPTOGAMS by " +.align 64 +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type block_se_handler,\@abi-omnipotent +.align 16 +block_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_block_prologue + + mov 24(%rax),%rax # pull saved real stack pointer + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_block_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size block_se_handler,.-block_se_handler + +.type key_se_handler,\@abi-omnipotent +.align 16 +key_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->RipRsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_key_prologue + + lea 56(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_key_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + jmp .Lcommon_seh_exit +.size key_se_handler,.-key_se_handler + +.type cbc_se_handler,\@abi-omnipotent +.align 16 +cbc_se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + lea .Lcbc_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_prologue + jb .Lin_cbc_prologue + + lea .Lcbc_fast_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_fast_body + jb .Lin_cbc_frame_setup + + lea .Lcbc_slow_prologue(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_slow_prologue + jb .Lin_cbc_body + + lea .Lcbc_slow_body(%rip),%r10 + cmp %r10,%rbx # context->Rip<.Lcbc_slow_body + jb .Lin_cbc_frame_setup + +.Lin_cbc_body: + mov 152($context),%rax # pull context->Rsp + + lea .Lcbc_epilogue(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_epilogue + jae .Lin_cbc_prologue + + lea 8(%rax),%rax + + lea .Lcbc_popfq(%rip),%r10 + cmp %r10,%rbx # context->Rip>=.Lcbc_popfq + jae .Lin_cbc_prologue + + mov `16-8`(%rax),%rax # biased $_rsp + lea 56(%rax),%rax + +.Lin_cbc_frame_setup: + mov -16(%rax),%rbx + mov -24(%rax),%rbp + mov -32(%rax),%r12 + mov -40(%rax),%r13 + mov -48(%rax),%r14 + mov -56(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_cbc_prologue: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + +.Lcommon_seh_exit: + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size cbc_se_handler,.-cbc_se_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_AES_encrypt + .rva .LSEH_end_AES_encrypt + .rva .LSEH_info_AES_encrypt + + .rva .LSEH_begin_AES_decrypt + .rva .LSEH_end_AES_decrypt + .rva .LSEH_info_AES_decrypt + + .rva .LSEH_begin_AES_set_encrypt_key + .rva .LSEH_end_AES_set_encrypt_key + .rva .LSEH_info_AES_set_encrypt_key + + .rva .LSEH_begin_AES_set_decrypt_key + .rva .LSEH_end_AES_set_decrypt_key + .rva .LSEH_info_AES_set_decrypt_key + + .rva .LSEH_begin_AES_cbc_encrypt + .rva .LSEH_end_AES_cbc_encrypt + .rva .LSEH_info_AES_cbc_encrypt + +.section .xdata +.align 8 +.LSEH_info_AES_encrypt: + .byte 9,0,0,0 + .rva block_se_handler + .rva .Lenc_prologue,.Lenc_epilogue # HandlerData[] +.LSEH_info_AES_decrypt: + .byte 9,0,0,0 + .rva block_se_handler + .rva .Ldec_prologue,.Ldec_epilogue # HandlerData[] +.LSEH_info_AES_set_encrypt_key: + .byte 9,0,0,0 + .rva key_se_handler + .rva .Lenc_key_prologue,.Lenc_key_epilogue # HandlerData[] +.LSEH_info_AES_set_decrypt_key: + .byte 9,0,0,0 + .rva key_se_handler + .rva .Ldec_key_prologue,.Ldec_key_epilogue # HandlerData[] +.LSEH_info_AES_cbc_encrypt: + .byte 9,0,0,0 + .rva cbc_se_handler +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/aes/asm/aesfx-sparcv9.pl b/crypto/aes/asm/aesfx-sparcv9.pl --- a/crypto/aes/asm/aesfx-sparcv9.pl +++ b/crypto/aes/asm/aesfx-sparcv9.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -33,14 +33,16 @@ # instructions and improve single-block and short-input performance # with misaligned data. -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; { my ($inp,$out,$key,$rounds,$tmp,$mask) = map("%o$_",(0..5)); $code.=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #define LOCALS (STACK_BIAS+STACK_FRAME) diff --git a/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/aes/asm/aesni-mb-x86_64.pl --- a/crypto/aes/asm/aesni-mb-x86_64.pl +++ b/crypto/aes/asm/aesni-mb-x86_64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -42,9 +42,10 @@ # (*) Sandy/Ivy Bridge are known to handle high interleave factors # suboptimally; -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -53,6 +54,11 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; +push(@INC,"${dir}","${dir}../../perlasm"); +require "x86_64-support.pl"; + +$ptr_size=&pointer_size($flavour); + $avx=0; if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` @@ -74,7 +80,8 @@ $avx = ($2>=3.0) + ($2>3.0); } -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; # void aesni_multi_cbc_encrypt ( @@ -86,6 +93,8 @@ $key="%rsi"; # 2nd arg $num="%edx"; +$inp_elm_size=2*$ptr_size+8+16; + @inptr=map("%r$_",(8..11)); @outptr=map("%r$_",(12..15)); @@ -161,21 +170,25 @@ .Lenc4x_body: movdqu ($key),$zero # 0-round key lea 0x78($key),$key # size optimization - lea 40*2($inp),$inp + lea $inp_elm_size*2($inp),$inp .Lenc4x_loop_grande: mov $num,24(%rsp) # original $num xor $num,$num ___ for($i=0;$i<4;$i++) { + $inptr_reg=&pointer_register($flavour,@inptr[$i]); + $outptr_reg=&pointer_register($flavour,@outptr[$i]); $code.=<<___; - mov `40*$i+16-40*2`($inp),$one # borrow $one for number of blocks - mov `40*$i+0-40*2`($inp),@inptr[$i] + # borrow $one for number of blocks + mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*2`($inp),$one + mov `$inp_elm_size*$i+0-$inp_elm_size*2`($inp),$inptr_reg cmp $num,$one - mov `40*$i+8-40*2`($inp),@outptr[$i] + mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*2`($inp),$outptr_reg cmovg $one,$num # find maximum test $one,$one - movdqu `40*$i+24-40*2`($inp),@out[$i] # load IV + # load IV + movdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*2`($inp),@out[$i] mov $one,`32+4*$i`(%rsp) # initialize counters cmovle %rsp,@inptr[$i] # cancel input ___ @@ -333,14 +346,15 @@ #pxor @inp[0],@out[0] #pxor @inp[1],@out[1] - #movdqu @out[0],`40*0+24-40*2`($inp) # output iv FIX ME! + # output iv FIX ME! + #movdqu @out[0],`$inp_elm_size*0+2*$ptr_size+8-$inp_elm_size*2`($inp) #pxor @inp[2],@out[2] - #movdqu @out[1],`40*1+24-40*2`($inp) + #movdqu @out[1],`$inp_elm_size*1+2*$ptr_size+8-$inp_elm_size*2`($inp) #pxor @inp[3],@out[3] - #movdqu @out[2],`40*2+24-40*2`($inp) # won't fix, let caller - #movdqu @out[3],`40*3+24-40*2`($inp) # figure this out... + #movdqu @out[2],`$inp_elm_size*2+2*$ptr_size+8-$inp_elm_size*2`($inp) # won't fix, let caller + #movdqu @out[3],`$inp_elm_size*3+2*$ptr_size+8-$inp_elm_size*2`($inp) # figure this out... - lea `40*4`($inp),$inp + lea `$inp_elm_size*4`($inp),$inp dec $num jnz .Lenc4x_loop_grande @@ -438,21 +452,25 @@ .Ldec4x_body: movdqu ($key),$zero # 0-round key lea 0x78($key),$key # size optimization - lea 40*2($inp),$inp + lea $inp_elm_size*2($inp),$inp .Ldec4x_loop_grande: mov $num,24(%rsp) # original $num xor $num,$num ___ for($i=0;$i<4;$i++) { + $inptr_reg=&pointer_register($flavour,@inptr[$i]); + $outptr_reg=&pointer_register($flavour,@outptr[$i]); $code.=<<___; - mov `40*$i+16-40*2`($inp),$one # borrow $one for number of blocks - mov `40*$i+0-40*2`($inp),@inptr[$i] + # borrow $one for number of blocks + mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*2`($inp),$one + mov `$inp_elm_size*$i+0-$inp_elm_size*2`($inp),$inptr_reg cmp $num,$one - mov `40*$i+8-40*2`($inp),@outptr[$i] + mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*2`($inp),$outptr_reg cmovg $one,$num # find maximum test $one,$one - movdqu `40*$i+24-40*2`($inp),@inp[$i] # load IV + # load IV + movdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*2`($inp),@inp[$i] mov $one,`32+4*$i`(%rsp) # initialize counters cmovle %rsp,@inptr[$i] # cancel input ___ @@ -608,7 +626,7 @@ .cfi_def_cfa %rax,8 mov 24(%rsp),$num - lea `40*4`($inp),$inp + lea `$inp_elm_size*4`($inp),$inp dec $num jnz .Ldec4x_loop_grande @@ -707,7 +725,7 @@ vzeroupper vmovdqu ($key),$zero # 0-round key lea 0x78($key),$key # size optimization - lea 40*4($inp),$inp + lea `$inp_elm_size*4`($inp),$inp shr \$1,$num .Lenc8x_loop_grande: @@ -716,14 +734,20 @@ ___ for($i=0;$i<8;$i++) { my $temp = $i ? $offload : $offset; + $ptr_reg=&pointer_register($flavour,@ptr[$i]); + $temp_reg=&pointer_register($flavour,$temp); $code.=<<___; - mov `40*$i+16-40*4`($inp),$one # borrow $one for number of blocks - mov `40*$i+0-40*4`($inp),@ptr[$i] # input pointer + # borrow $one for number of blocks + mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*4`($inp),$one + # input pointer + mov `$inp_elm_size*$i+0-$inp_elm_size*4`($inp),$ptr_reg cmp $num,$one - mov `40*$i+8-40*4`($inp),$temp # output pointer + # output pointer + mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*4`($inp),$temp_reg cmovg $one,$num # find maximum test $one,$one - vmovdqu `40*$i+24-40*4`($inp),@out[$i] # load IV + # load IV + vmovdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*4`($inp),@out[$i] mov $one,`32+4*$i`(%rsp) # initialize counters cmovle %rsp,@ptr[$i] # cancel input sub @ptr[$i],$temp # distance between input and output @@ -908,7 +932,7 @@ mov 16(%rsp),%rax # original %rsp .cfi_def_cfa %rax,8 #mov 24(%rsp),$num - #lea `40*8`($inp),$inp + #lea `$inp_elm_size*8`($inp),$inp #dec $num #jnz .Lenc8x_loop_grande @@ -1000,7 +1024,7 @@ vzeroupper vmovdqu ($key),$zero # 0-round key lea 0x78($key),$key # size optimization - lea 40*4($inp),$inp + lea `$inp_elm_size*4`($inp),$inp shr \$1,$num .Ldec8x_loop_grande: @@ -1009,14 +1033,20 @@ ___ for($i=0;$i<8;$i++) { my $temp = $i ? $offload : $offset; + $ptr_reg=&pointer_register($flavour,@ptr[$i]); + $temp_reg=&pointer_register($flavour,$temp); $code.=<<___; - mov `40*$i+16-40*4`($inp),$one # borrow $one for number of blocks - mov `40*$i+0-40*4`($inp),@ptr[$i] # input pointer + # borrow $one for number of blocks + mov `$inp_elm_size*$i+2*$ptr_size-$inp_elm_size*4`($inp),$one + # input pointer + mov `$inp_elm_size*$i+0-$inp_elm_size*4`($inp),$ptr_reg cmp $num,$one - mov `40*$i+8-40*4`($inp),$temp # output pointer + # output pointer + mov `$inp_elm_size*$i+$ptr_size-$inp_elm_size*4`($inp),$temp_reg cmovg $one,$num # find maximum test $one,$one - vmovdqu `40*$i+24-40*4`($inp),@out[$i] # load IV + # load IV + vmovdqu `$inp_elm_size*$i+2*$ptr_size+8-$inp_elm_size*4`($inp),@out[$i] mov $one,`32+4*$i`(%rsp) # initialize counters cmovle %rsp,@ptr[$i] # cancel input sub @ptr[$i],$temp # distance between input and output @@ -1232,7 +1262,7 @@ mov 16(%rsp),%rax # original %rsp .cfi_def_cfa %rax,8 #mov 24(%rsp),$num - #lea `40*8`($inp),$inp + #lea `$inp_elm_size*8`($inp),$inp #dec $num #jnz .Ldec8x_loop_grande diff --git a/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/aes/asm/aesni-sha1-x86_64.pl --- a/crypto/aes/asm/aesni-sha1-x86_64.pl +++ b/crypto/aes/asm/aesni-sha1-x86_64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -88,9 +88,10 @@ # (**) Execution is fully dominated by integer code sequence and # SIMD still hardly shows [in single-process benchmark;-] -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -114,7 +115,8 @@ $stitched_decrypt=0; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; # void aesni_cbc_sha1_enc(const void *inp, diff --git a/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/aes/asm/aesni-sha256-x86_64.pl --- a/crypto/aes/asm/aesni-sha256-x86_64.pl +++ b/crypto/aes/asm/aesni-sha256-x86_64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -44,9 +44,10 @@ # -evp aes-256-cbc-hmac-sha256' will vary by percent or two; # (***) these are SHAEXT results; -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -77,7 +78,8 @@ $shaext=$avx; ### set to zero if compiling for 1.0.1 $avx=1 if (!$shaext && $avx); -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $func="aesni_cbc_sha256_enc"; diff --git a/crypto/aes/asm/aesni-x86.pl b/crypto/aes/asm/aesni-x86.pl --- a/crypto/aes/asm/aesni-x86.pl +++ b/crypto/aes/asm/aesni-x86.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -76,9 +76,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open OUT,">$output"; -*STDOUT=*OUT; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0]); diff --git a/crypto/aes/asm/aesni-x86_64.pl b/crypto/aes/asm/aesni-x86_64.pl --- a/crypto/aes/asm/aesni-x86_64.pl +++ b/crypto/aes/asm/aesni-x86_64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -192,9 +192,10 @@ # generates drop-in replacement for # crypto/aes/asm/aes-x86_64.pl:-) -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -203,7 +204,8 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $movkey = $PREFIX eq "aesni" ? "movups" : "movups"; @@ -275,6 +277,7 @@ .align 16 ${PREFIX}_encrypt: .cfi_startproc + endbranch movups ($inp),$inout0 # load input mov 240($key),$rounds # key->rounds ___ @@ -293,6 +296,7 @@ .align 16 ${PREFIX}_decrypt: .cfi_startproc + endbranch movups ($inp),$inout0 # load input mov 240($key),$rounds # key->rounds ___ @@ -613,6 +617,7 @@ .align 16 aesni_ecb_encrypt: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0x58(%rsp),%rsp @@ -985,6 +990,7 @@ .align 16 aesni_ccm64_encrypt_blocks: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0x58(%rsp),%rsp @@ -1077,6 +1083,7 @@ .align 16 aesni_ccm64_decrypt_blocks: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0x58(%rsp),%rsp @@ -1203,6 +1210,7 @@ .align 16 aesni_ctr32_encrypt_blocks: .cfi_startproc + endbranch cmp \$1,$len jne .Lctr32_bulk @@ -1775,6 +1783,7 @@ .align 16 aesni_xts_encrypt: .cfi_startproc + endbranch lea (%rsp),%r11 # frame pointer .cfi_def_cfa_register %r11 push %rbp @@ -2258,6 +2267,7 @@ .align 16 aesni_xts_decrypt: .cfi_startproc + endbranch lea (%rsp),%r11 # frame pointer .cfi_def_cfa_register %r11 push %rbp @@ -2783,6 +2793,7 @@ .align 32 aesni_ocb_encrypt: .cfi_startproc + endbranch lea (%rsp),%rax push %rbx .cfi_push %rbx @@ -3249,6 +3260,7 @@ .align 32 aesni_ocb_decrypt: .cfi_startproc + endbranch lea (%rsp),%rax push %rbx .cfi_push %rbx @@ -3737,6 +3749,7 @@ .align 16 ${PREFIX}_cbc_encrypt: .cfi_startproc + endbranch test $len,$len # check length jz .Lcbc_ret diff --git a/crypto/aes/asm/aesp8-ppc.pl b/crypto/aes/asm/aesp8-ppc.pl --- a/crypto/aes/asm/aesp8-ppc.pl +++ b/crypto/aes/asm/aesp8-ppc.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -43,7 +43,10 @@ # POWER9[le] 4.02/0.86 0.84 1.05 # POWER9[be] 3.99/0.78 0.79 0.97 -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /64/) { $SIZE_T =8; @@ -70,7 +73,8 @@ ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; +open STDOUT,"| $^X $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; $FRAME=8*$SIZE_T; $prefix="aes_p8"; diff --git a/crypto/aes/asm/aest4-sparcv9.pl b/crypto/aes/asm/aest4-sparcv9.pl --- a/crypto/aes/asm/aest4-sparcv9.pl +++ b/crypto/aes/asm/aest4-sparcv9.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -75,8 +75,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "sparcv9_modes.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; $::evp=1; # if $evp is set to 0, script generates module with # AES_[en|de]crypt, AES_set_[en|de]crypt_key and AES_cbc_encrypt entry @@ -92,7 +91,10 @@ my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5)); $code.=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #ifdef __arch64__ .register %g2,#scratch diff --git a/crypto/aes/asm/aesv8-armx.pl b/crypto/aes/asm/aesv8-armx.pl --- a/crypto/aes/asm/aesv8-armx.pl +++ b/crypto/aes/asm/aesv8-armx.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2014-2022 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -27,44 +27,72 @@ # CBC encrypt case. On Cortex-A57 parallelizable mode performance # seems to be limited by sheer amount of NEON instructions... # +# April 2019 +# +# Key to performance of parallelize-able modes is round instruction +# interleaving. But which factor to use? There is optimal one for +# each combination of instruction latency and issue rate, beyond +# which increasing interleave factor doesn't pay off. While on cons +# side we have code size increase and resource waste on platforms for +# which interleave factor is too high. In other words you want it to +# be just right. So far interleave factor of 3x was serving well all +# platforms. But for ThunderX2 optimal interleave factor was measured +# to be 5x... +# # Performance in cycles per byte processed with 128-bit key: # # CBC enc CBC dec CTR # Apple A7 2.39 1.20 1.20 -# Cortex-A53 1.32 1.29 1.46 -# Cortex-A57(*) 1.95 0.85 0.93 -# Denver 1.96 0.86 0.80 -# Mongoose 1.33 1.20 1.20 -# Kryo 1.26 0.94 1.00 +# Cortex-A53 1.32 1.17/1.29(**) 1.36/1.46 +# Cortex-A57(*) 1.95 0.82/0.85 0.89/0.93 +# Cortex-A72 1.33 0.85/0.88 0.92/0.96 +# Denver 1.96 0.65/0.86 0.76/0.80 +# Mongoose 1.33 1.23/1.20 1.30/1.20 +# Kryo 1.26 0.87/0.94 1.00/1.00 +# ThunderX2 5.95 1.25 1.30 # # (*) original 3.64/1.34/1.32 results were for r0p0 revision # and are still same even for updated module; +# (**) numbers after slash are for 32-bit code, which is 3x- +# interleaved; -$flavour = shift; -$output = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; -open OUT,"| \"$^X\" $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $prefix="aes_v8"; +$_byte = ($flavour =~ /win/ ? "DCB" : ".byte"); + $code=<<___; #include "arm_arch.h" #if __ARM_MAX_ARCH__>=7 -.text ___ -$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/); +$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/); $code.=<<___ if ($flavour !~ /64/); .arch armv7-a // don't confuse not-so-latest binutils with argv8 :-) .fpu neon +#ifdef __thumb2__ +.syntax unified +.thumb +# define INST(a,b,c,d) $_byte c,d|0xc,a,b +#else .code 32 -#undef __thumb2__ +# define INST(a,b,c,d) $_byte a,b,c,d +#endif + +.text ___ # Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax, @@ -361,21 +389,148 @@ &gen_block("en"); &gen_block("de"); }}} + +# Performance in cycles per byte. +# Processed with AES-ECB different key size. +# It shows the value before and after optimization as below: +# (before/after): +# +# AES-128-ECB AES-192-ECB AES-256-ECB +# Cortex-A57 1.85/0.82 2.16/0.96 2.47/1.10 +# Cortex-A72 1.64/0.85 1.82/0.99 2.13/1.14 + +# Optimization is implemented by loop unrolling and interleaving. +# Commonly, we choose the unrolling factor as 5, if the input +# data size smaller than 5 blocks, but not smaller than 3 blocks, +# choose 3 as the unrolling factor. +# If the input data size dsize >= 5*16 bytes, then take 5 blocks +# as one iteration, every loop the left size lsize -= 5*16. +# If 5*16 > lsize >= 3*16 bytes, take 3 blocks as one iteration, +# every loop lsize -=3*16. +# If lsize < 3*16 bytes, treat them as the tail, interleave the +# two blocks AES instructions. +# There is one special case, if the original input data size dsize +# = 16 bytes, we will treat it seperately to improve the +# performance: one independent code block without LR, FP load and +# store, just looks like what the original ECB implementation does. + {{{ -my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5"; -my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12"); -my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); +my ($inp,$out,$len,$key)=map("x$_",(0..3)); +my ($enc,$rounds,$cnt,$key_,$step)=("w4","w5","w6","x7","x8"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7)); my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); -my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key); -### q8-q15 preloaded key schedule +### q7 last round key +### q10-q15 q7 Last 7 round keys +### q8-q9 preloaded round keys except last 7 keys for big size +### q5, q6, q8-q9 preloaded round keys except last 7 keys for only 16 byte + +{ +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat3,$in3,$tmp3); # used only in 64-bit mode +my ($dat4,$in4,$tmp4); +if ($flavour =~ /64/) { + ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); +} $code.=<<___; -.globl ${prefix}_cbc_encrypt -.type ${prefix}_cbc_encrypt,%function +.globl ${prefix}_ecb_encrypt +.type ${prefix}_ecb_encrypt,%function .align 5 -${prefix}_cbc_encrypt: +${prefix}_ecb_encrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + subs $len,$len,#16 + // Original input data size bigger than 16, jump to big size processing. + b.ne .Lecb_big_size + vld1.8 {$dat0},[$inp] + cmp $enc,#0 // en- or decrypting? + ldr $rounds,[$key,#240] + vld1.32 {q5-q6},[$key],#32 // load key schedule... + + b.eq .Lecb_small_dec + aese $dat0,q5 + aesmc $dat0,$dat0 + vld1.32 {q8-q9},[$key],#32 // load key schedule... + aese $dat0,q6 + aesmc $dat0,$dat0 + subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-ecb processing + b.eq .Lecb_128_enc +.Lecb_round_loop: + aese $dat0,q8 + aesmc $dat0,$dat0 + vld1.32 {q8},[$key],#16 // load key schedule... + aese $dat0,q9 + aesmc $dat0,$dat0 + vld1.32 {q9},[$key],#16 // load key schedule... + subs $rounds,$rounds,#2 // bias + b.gt .Lecb_round_loop +.Lecb_128_enc: + vld1.32 {q10-q11},[$key],#32 // load key schedule... + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat0,q9 + aesmc $dat0,$dat0 + vld1.32 {q12-q13},[$key],#32 // load key schedule... + aese $dat0,q10 + aesmc $dat0,$dat0 + aese $dat0,q11 + aesmc $dat0,$dat0 + vld1.32 {q14-q15},[$key],#32 // load key schedule... + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat0,q13 + aesmc $dat0,$dat0 + vld1.32 {$rndlast},[$key] + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat0,q15 + veor $dat0,$dat0,$rndlast + vst1.8 {$dat0},[$out] + b .Lecb_Final_abort +.Lecb_small_dec: + aesd $dat0,q5 + aesimc $dat0,$dat0 + vld1.32 {q8-q9},[$key],#32 // load key schedule... + aesd $dat0,q6 + aesimc $dat0,$dat0 + subs $rounds,$rounds,#10 // bias + b.eq .Lecb_128_dec +.Lecb_dec_round_loop: + aesd $dat0,q8 + aesimc $dat0,$dat0 + vld1.32 {q8},[$key],#16 // load key schedule... + aesd $dat0,q9 + aesimc $dat0,$dat0 + vld1.32 {q9},[$key],#16 // load key schedule... + subs $rounds,$rounds,#2 // bias + b.gt .Lecb_dec_round_loop +.Lecb_128_dec: + vld1.32 {q10-q11},[$key],#32 // load key schedule... + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat0,q9 + aesimc $dat0,$dat0 + vld1.32 {q12-q13},[$key],#32 // load key schedule... + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat0,q11 + aesimc $dat0,$dat0 + vld1.32 {q14-q15},[$key],#32 // load key schedule... + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat0,q13 + aesimc $dat0,$dat0 + vld1.32 {$rndlast},[$key] + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat0,q15 + veor $dat0,$dat0,$rndlast + vst1.8 {$dat0},[$out] + b .Lecb_Final_abort +.Lecb_big_size: ___ $code.=<<___ if ($flavour =~ /64/); stp x29,x30,[sp,#-16]! @@ -384,24 +539,23 @@ $code.=<<___ if ($flavour !~ /64/); mov ip,sp stmdb sp!,{r4-r8,lr} - vstmdb sp!,{d8-d15} @ ABI specification says so - ldmia ip,{r4-r5} @ load remaining args + vstmdb sp!,{d8-d15} @ ABI specification says so + ldmia ip,{r4-r5} @ load remaining args + subs $len,$len,#16 ___ $code.=<<___; - subs $len,$len,#16 mov $step,#16 - b.lo .Lcbc_abort + b.lo .Lecb_done cclr $step,eq - cmp $enc,#0 // en- or decrypting? + cmp $enc,#0 // en- or decrypting? ldr $rounds,[$key,#240] and $len,$len,#-16 - vld1.8 {$ivec},[$ivp] vld1.8 {$dat},[$inp],$step - vld1.32 {q8-q9},[$key] // load key schedule... + vld1.32 {q8-q9},[$key] // load key schedule... sub $rounds,$rounds,#6 - add $key_,$key,x5,lsl#4 // pointer to last 7 round keys + add $key_,$key,x5,lsl#4 // pointer to last 7 round keys sub $rounds,$rounds,#2 vld1.32 {q10-q11},[$key_],#32 vld1.32 {q12-q13},[$key_],#32 @@ -410,139 +564,359 @@ add $key_,$key,#32 mov $cnt,$rounds - b.eq .Lcbc_dec + b.eq .Lecb_dec - cmp $rounds,#2 - veor $dat,$dat,$ivec - veor $rndzero_n_last,q8,$rndlast - b.eq .Lcbc_enc128 + vld1.8 {$dat1},[$inp],#16 + subs $len,$len,#32 // bias + add $cnt,$rounds,#2 + vorr $in1,$dat1,$dat1 + vorr $dat2,$dat1,$dat1 + vorr $dat1,$dat,$dat + b.lo .Lecb_enc_tail - vld1.32 {$in0-$in1},[$key_] - add $key_,$key,#16 - add $key4,$key,#16*4 - add $key5,$key,#16*5 - aese $dat,q8 - aesmc $dat,$dat - add $key6,$key,#16*6 - add $key7,$key,#16*7 - b .Lenter_cbc_enc + vorr $dat1,$in1,$in1 + vld1.8 {$dat2},[$inp],#16 +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#32 + b.lo .Loop3x_ecb_enc -.align 4 -.Loop_cbc_enc: - aese $dat,q8 - aesmc $dat,$dat - vst1.8 {$ivec},[$out],#16 -.Lenter_cbc_enc: - aese $dat,q9 - aesmc $dat,$dat - aese $dat,$in0 - aesmc $dat,$dat - vld1.32 {q8},[$key4] - cmp $rounds,#4 - aese $dat,$in1 - aesmc $dat,$dat - vld1.32 {q9},[$key5] - b.eq .Lcbc_enc192 + vld1.8 {$dat3},[$inp],#16 + vld1.8 {$dat4},[$inp],#16 + sub $len,$len,#32 // bias + mov $cnt,$rounds - aese $dat,q8 - aesmc $dat,$dat - vld1.32 {q8},[$key6] - aese $dat,q9 - aesmc $dat,$dat - vld1.32 {q9},[$key7] - nop +.Loop5x_ecb_enc: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 + b.gt .Loop5x_ecb_enc + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + cmp $len,#0x40 // because .Lecb_enc_tail4x + sub $len,$len,#0x50 + + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo + mov $key_,$key + + aese $dat0,q10 + aesmc $dat0,$dat0 + aese $dat1,q10 + aesmc $dat1,$dat1 + aese $dat2,q10 + aesmc $dat2,$dat2 + aese $dat3,q10 + aesmc $dat3,$dat3 + aese $dat4,q10 + aesmc $dat4,$dat4 + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat4 + // are loaded with last "words" + add x6,$len,#0x60 // because .Lecb_enc_tail4x + + aese $dat0,q11 + aesmc $dat0,$dat0 + aese $dat1,q11 + aesmc $dat1,$dat1 + aese $dat2,q11 + aesmc $dat2,$dat2 + aese $dat3,q11 + aesmc $dat3,$dat3 + aese $dat4,q11 + aesmc $dat4,$dat4 + + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + aese $dat3,q12 + aesmc $dat3,$dat3 + aese $dat4,q12 + aesmc $dat4,$dat4 + + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat3,q13 + aesmc $dat3,$dat3 + aese $dat4,q13 + aesmc $dat4,$dat4 + + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + aese $dat3,q14 + aesmc $dat3,$dat3 + aese $dat4,q14 + aesmc $dat4,$dat4 + + aese $dat0,q15 + vld1.8 {$in0},[$inp],#16 + aese $dat1,q15 + vld1.8 {$in1},[$inp],#16 + aese $dat2,q15 + vld1.8 {$in2},[$inp],#16 + aese $dat3,q15 + vld1.8 {$in3},[$inp],#16 + aese $dat4,q15 + vld1.8 {$in4},[$inp],#16 + cbz x6,.Lecb_enc_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$rndlast,$dat0 + vorr $dat0,$in0,$in0 + veor $tmp1,$rndlast,$dat1 + vorr $dat1,$in1,$in1 + veor $tmp2,$rndlast,$dat2 + vorr $dat2,$in2,$in2 + veor $tmp3,$rndlast,$dat3 + vorr $dat3,$in3,$in3 + veor $tmp4,$rndlast,$dat4 + vst1.8 {$tmp0},[$out],#16 + vorr $dat4,$in4,$in4 + vst1.8 {$tmp1},[$out],#16 + mov $cnt,$rounds + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_ecb_enc -.Lcbc_enc192: - aese $dat,q8 - aesmc $dat,$dat - subs $len,$len,#16 - aese $dat,q9 - aesmc $dat,$dat - cclr $step,eq - aese $dat,q10 - aesmc $dat,$dat - aese $dat,q11 - aesmc $dat,$dat - vld1.8 {q8},[$inp],$step - aese $dat,q12 - aesmc $dat,$dat - veor q8,q8,$rndzero_n_last - aese $dat,q13 - aesmc $dat,$dat - vld1.32 {q9},[$key_] // re-pre-load rndkey[1] - aese $dat,q14 - aesmc $dat,$dat - aese $dat,q15 - veor $ivec,$dat,$rndlast - b.hs .Loop_cbc_enc + add $len,$len,#0x50 + cbz $len,.Lecb_done - vst1.8 {$ivec},[$out],#16 - b .Lcbc_done + add $cnt,$rounds,#2 + subs $len,$len,#0x30 + vorr $dat0,$in2,$in2 + vorr $dat1,$in3,$in3 + vorr $dat2,$in4,$in4 + b.lo .Lecb_enc_tail -.align 5 -.Lcbc_enc128: - vld1.32 {$in0-$in1},[$key_] - aese $dat,q8 - aesmc $dat,$dat - b .Lenter_cbc_enc128 -.Loop_cbc_enc128: - aese $dat,q8 - aesmc $dat,$dat - vst1.8 {$ivec},[$out],#16 -.Lenter_cbc_enc128: - aese $dat,q9 - aesmc $dat,$dat - subs $len,$len,#16 - aese $dat,$in0 - aesmc $dat,$dat - cclr $step,eq - aese $dat,$in1 - aesmc $dat,$dat - aese $dat,q10 - aesmc $dat,$dat - aese $dat,q11 - aesmc $dat,$dat - vld1.8 {q8},[$inp],$step - aese $dat,q12 - aesmc $dat,$dat - aese $dat,q13 - aesmc $dat,$dat - aese $dat,q14 - aesmc $dat,$dat - veor q8,q8,$rndzero_n_last - aese $dat,q15 - veor $ivec,$dat,$rndlast - b.hs .Loop_cbc_enc128 + b .Loop3x_ecb_enc - vst1.8 {$ivec},[$out],#16 - b .Lcbc_done +.align 4 +.Lecb_enc_tail4x: + veor $tmp1,$rndlast,$dat1 + veor $tmp2,$rndlast,$dat2 + veor $tmp3,$rndlast,$dat3 + veor $tmp4,$rndlast,$dat4 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + + b .Lecb_done +.align 4 ___ -{ -my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); +$code.=<<___; +.Loop3x_ecb_enc: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_ecb_enc + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + subs $len,$len,#0x30 + mov.lo x6,$len // x6, $cnt, is zero at this point + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat2 + // are loaded with last "words" + mov $key_,$key + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + vld1.8 {$in0},[$inp],#16 + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aese $dat0,q15 + aese $dat1,q15 + aese $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $cnt,$rounds,#2 + veor $tmp0,$rndlast,$dat0 + veor $tmp1,$rndlast,$dat1 + veor $dat2,$dat2,$rndlast + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vorr $dat0,$in0,$in0 + vst1.8 {$tmp1},[$out],#16 + vorr $dat1,$in1,$in1 + vst1.8 {$dat2},[$out],#16 + vorr $dat2,$in2,$in2 + b.hs .Loop3x_ecb_enc + + cmn $len,#0x30 + b.eq .Lecb_done + nop + +.Lecb_enc_tail: + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lecb_enc_tail + + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + cmn $len,#0x20 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + aese $dat1,q15 + aese $dat2,q15 + b.eq .Lecb_enc_one + veor $tmp1,$rndlast,$dat1 + veor $tmp2,$rndlast,$dat2 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + b .Lecb_done + +.Lecb_enc_one: + veor $tmp1,$rndlast,$dat2 + vst1.8 {$tmp1},[$out],#16 + b .Lecb_done +___ + $code.=<<___; .align 5 -.Lcbc_dec: - vld1.8 {$dat2},[$inp],#16 - subs $len,$len,#32 // bias +.Lecb_dec: + vld1.8 {$dat1},[$inp],#16 + subs $len,$len,#32 // bias add $cnt,$rounds,#2 - vorr $in1,$dat,$dat + vorr $in1,$dat1,$dat1 + vorr $dat2,$dat1,$dat1 vorr $dat1,$dat,$dat - vorr $in2,$dat2,$dat2 - b.lo .Lcbc_dec_tail + b.lo .Lecb_dec_tail - vorr $dat1,$dat2,$dat2 + vorr $dat1,$in1,$in1 vld1.8 {$dat2},[$inp],#16 - vorr $in0,$dat,$dat - vorr $in1,$dat1,$dat1 - vorr $in2,$dat2,$dat2 +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#32 + b.lo .Loop3x_ecb_dec -.Loop3x_cbc_dec: + vld1.8 {$dat3},[$inp],#16 + vld1.8 {$dat4},[$inp],#16 + sub $len,$len,#32 // bias + mov $cnt,$rounds + +.Loop5x_ecb_dec: aesd $dat0,q8 aesimc $dat0,$dat0 aesd $dat1,q8 aesimc $dat1,$dat1 aesd $dat2,q8 aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 vld1.32 {q8},[$key_],#16 subs $cnt,$cnt,#2 aesd $dat0,q9 @@ -551,8 +925,12 @@ aesimc $dat1,$dat1 aesd $dat2,q9 aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 vld1.32 {q9},[$key_],#16 - b.gt .Loop3x_cbc_dec + b.gt .Loop5x_ecb_dec aesd $dat0,q8 aesimc $dat0,$dat0 @@ -560,62 +938,738 @@ aesimc $dat1,$dat1 aesd $dat2,q8 aesimc $dat2,$dat2 - veor $tmp0,$ivec,$rndlast - subs $len,$len,#0x30 - veor $tmp1,$in0,$rndlast - mov.lo x6,$len // x6, $cnt, is zero at this point + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + cmp $len,#0x40 // because .Lecb_tail4x + sub $len,$len,#0x50 + aesd $dat0,q9 aesimc $dat0,$dat0 aesd $dat1,q9 aesimc $dat1,$dat1 aesd $dat2,q9 aesimc $dat2,$dat2 - veor $tmp2,$in1,$rndlast - add $inp,$inp,x6 // $inp is adjusted in such way that - // at exit from the loop $dat1-$dat2 - // are loaded with last "words" - vorr $ivec,$in2,$in2 - mov $key_,$key + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo + mov $key_,$key + + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat1,q10 + aesimc $dat1,$dat1 + aesd $dat2,q10 + aesimc $dat2,$dat2 + aesd $dat3,q10 + aesimc $dat3,$dat3 + aesd $dat4,q10 + aesimc $dat4,$dat4 + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat4 + // are loaded with last "words" + add x6,$len,#0x60 // because .Lecb_tail4x + + aesd $dat0,q11 + aesimc $dat0,$dat0 + aesd $dat1,q11 + aesimc $dat1,$dat1 + aesd $dat2,q11 + aesimc $dat2,$dat2 + aesd $dat3,q11 + aesimc $dat3,$dat3 + aesd $dat4,q11 + aesimc $dat4,$dat4 + aesd $dat0,q12 aesimc $dat0,$dat0 aesd $dat1,q12 aesimc $dat1,$dat1 aesd $dat2,q12 aesimc $dat2,$dat2 - vld1.8 {$in0},[$inp],#16 + aesd $dat3,q12 + aesimc $dat3,$dat3 + aesd $dat4,q12 + aesimc $dat4,$dat4 + aesd $dat0,q13 aesimc $dat0,$dat0 aesd $dat1,q13 aesimc $dat1,$dat1 aesd $dat2,q13 aesimc $dat2,$dat2 - vld1.8 {$in1},[$inp],#16 + aesd $dat3,q13 + aesimc $dat3,$dat3 + aesd $dat4,q13 + aesimc $dat4,$dat4 + aesd $dat0,q14 aesimc $dat0,$dat0 aesd $dat1,q14 aesimc $dat1,$dat1 aesd $dat2,q14 aesimc $dat2,$dat2 - vld1.8 {$in2},[$inp],#16 + aesd $dat3,q14 + aesimc $dat3,$dat3 + aesd $dat4,q14 + aesimc $dat4,$dat4 + aesd $dat0,q15 + vld1.8 {$in0},[$inp],#16 aesd $dat1,q15 + vld1.8 {$in1},[$inp],#16 aesd $dat2,q15 - vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] - add $cnt,$rounds,#2 - veor $tmp0,$tmp0,$dat0 - veor $tmp1,$tmp1,$dat1 - veor $dat2,$dat2,$tmp2 - vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vld1.8 {$in2},[$inp],#16 + aesd $dat3,q15 + vld1.8 {$in3},[$inp],#16 + aesd $dat4,q15 + vld1.8 {$in4},[$inp],#16 + cbz x6,.Lecb_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$rndlast,$dat0 + vorr $dat0,$in0,$in0 + veor $tmp1,$rndlast,$dat1 + vorr $dat1,$in1,$in1 + veor $tmp2,$rndlast,$dat2 + vorr $dat2,$in2,$in2 + veor $tmp3,$rndlast,$dat3 + vorr $dat3,$in3,$in3 + veor $tmp4,$rndlast,$dat4 vst1.8 {$tmp0},[$out],#16 - vorr $dat0,$in0,$in0 + vorr $dat4,$in4,$in4 vst1.8 {$tmp1},[$out],#16 - vorr $dat1,$in1,$in1 - vst1.8 {$dat2},[$out],#16 - vorr $dat2,$in2,$in2 - b.hs .Loop3x_cbc_dec + mov $cnt,$rounds + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_ecb_dec - cmn $len,#0x30 - b.eq .Lcbc_done + add $len,$len,#0x50 + cbz $len,.Lecb_done + + add $cnt,$rounds,#2 + subs $len,$len,#0x30 + vorr $dat0,$in2,$in2 + vorr $dat1,$in3,$in3 + vorr $dat2,$in4,$in4 + b.lo .Lecb_dec_tail + + b .Loop3x_ecb_dec + +.align 4 +.Lecb_tail4x: + veor $tmp1,$rndlast,$dat1 + veor $tmp2,$rndlast,$dat2 + veor $tmp3,$rndlast,$dat3 + veor $tmp4,$rndlast,$dat4 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + + b .Lecb_done +.align 4 +___ +$code.=<<___; +.Loop3x_ecb_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_ecb_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + subs $len,$len,#0x30 + mov.lo x6,$len // x6, $cnt, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat2 + // are loaded with last "words" + mov $key_,$key + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + vld1.8 {$in0},[$inp],#16 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aesd $dat0,q15 + aesd $dat1,q15 + aesd $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $cnt,$rounds,#2 + veor $tmp0,$rndlast,$dat0 + veor $tmp1,$rndlast,$dat1 + veor $dat2,$dat2,$rndlast + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vorr $dat0,$in0,$in0 + vst1.8 {$tmp1},[$out],#16 + vorr $dat1,$in1,$in1 + vst1.8 {$dat2},[$out],#16 + vorr $dat2,$in2,$in2 + b.hs .Loop3x_ecb_dec + + cmn $len,#0x30 + b.eq .Lecb_done + nop + +.Lecb_dec_tail: + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lecb_dec_tail + + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + cmn $len,#0x20 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + aesd $dat1,q15 + aesd $dat2,q15 + b.eq .Lecb_dec_one + veor $tmp1,$rndlast,$dat1 + veor $tmp2,$rndlast,$dat2 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + b .Lecb_done + +.Lecb_dec_one: + veor $tmp1,$rndlast,$dat2 + vst1.8 {$tmp1},[$out],#16 + +.Lecb_done: +___ +} +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r8,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldr x29,[sp],#16 +___ +$code.=<<___ if ($flavour =~ /64/); +.Lecb_Final_abort: + ret +___ +$code.=<<___; +.size ${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt +___ +}}} +{{{ +my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my $enc="w5"; +my ($rounds,$cnt,$key_,$step,$step1)=($enc,"w6","x7","x8","x12"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); + +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); +my ($key4,$key5,$key6,$key7)=("x6","x12","x14",$key); + +### q8-q15 preloaded key schedule + +$code.=<<___; +.globl ${prefix}_cbc_encrypt +.type ${prefix}_cbc_encrypt,%function +.align 5 +${prefix}_cbc_encrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + stp x29,x30,[sp,#-16]! + add x29,sp,#0 +___ +$code.=<<___ if ($flavour !~ /64/); + mov ip,sp + stmdb sp!,{r4-r8,lr} + vstmdb sp!,{d8-d15} @ ABI specification says so + ldmia ip,{r4-r5} @ load remaining args +___ +$code.=<<___; + subs $len,$len,#16 + mov $step,#16 + b.lo .Lcbc_abort + cclr $step,eq + + cmp $enc,#0 // en- or decrypting? + ldr $rounds,[$key,#240] + and $len,$len,#-16 + vld1.8 {$ivec},[$ivp] + vld1.8 {$dat},[$inp],$step + + vld1.32 {q8-q9},[$key] // load key schedule... + sub $rounds,$rounds,#6 + add $key_,$key,x5,lsl#4 // pointer to last 7 round keys + sub $rounds,$rounds,#2 + vld1.32 {q10-q11},[$key_],#32 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + add $key_,$key,#32 + mov $cnt,$rounds + b.eq .Lcbc_dec + + cmp $rounds,#2 + veor $dat,$dat,$ivec + veor $rndzero_n_last,q8,$rndlast + b.eq .Lcbc_enc128 + + vld1.32 {$in0-$in1},[$key_] + add $key_,$key,#16 + add $key4,$key,#16*4 + add $key5,$key,#16*5 + aese $dat,q8 + aesmc $dat,$dat + add $key6,$key,#16*6 + add $key7,$key,#16*7 + b .Lenter_cbc_enc + +.align 4 +.Loop_cbc_enc: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc: + aese $dat,q9 + aesmc $dat,$dat + aese $dat,$in0 + aesmc $dat,$dat + vld1.32 {q8},[$key4] + cmp $rounds,#4 + aese $dat,$in1 + aesmc $dat,$dat + vld1.32 {q9},[$key5] + b.eq .Lcbc_enc192 + + aese $dat,q8 + aesmc $dat,$dat + vld1.32 {q8},[$key6] + aese $dat,q9 + aesmc $dat,$dat + vld1.32 {q9},[$key7] + nop + +.Lcbc_enc192: + aese $dat,q8 + aesmc $dat,$dat + subs $len,$len,#16 + aese $dat,q9 + aesmc $dat,$dat + cclr $step,eq + aese $dat,q10 + aesmc $dat,$dat + aese $dat,q11 + aesmc $dat,$dat + vld1.8 {q8},[$inp],$step + aese $dat,q12 + aesmc $dat,$dat + veor q8,q8,$rndzero_n_last + aese $dat,q13 + aesmc $dat,$dat + vld1.32 {q9},[$key_] // re-pre-load rndkey[1] + aese $dat,q14 + aesmc $dat,$dat + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc + + vst1.8 {$ivec},[$out],#16 + b .Lcbc_done + +.align 5 +.Lcbc_enc128: + vld1.32 {$in0-$in1},[$key_] + aese $dat,q8 + aesmc $dat,$dat + b .Lenter_cbc_enc128 +.Loop_cbc_enc128: + aese $dat,q8 + aesmc $dat,$dat + vst1.8 {$ivec},[$out],#16 +.Lenter_cbc_enc128: + aese $dat,q9 + aesmc $dat,$dat + subs $len,$len,#16 + aese $dat,$in0 + aesmc $dat,$dat + cclr $step,eq + aese $dat,$in1 + aesmc $dat,$dat + aese $dat,q10 + aesmc $dat,$dat + aese $dat,q11 + aesmc $dat,$dat + vld1.8 {q8},[$inp],$step + aese $dat,q12 + aesmc $dat,$dat + aese $dat,q13 + aesmc $dat,$dat + aese $dat,q14 + aesmc $dat,$dat + veor q8,q8,$rndzero_n_last + aese $dat,q15 + veor $ivec,$dat,$rndlast + b.hs .Loop_cbc_enc128 + + vst1.8 {$ivec},[$out],#16 + b .Lcbc_done +___ +{ +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat3,$in3,$tmp3); # used only in 64-bit mode +my ($dat4,$in4,$tmp4); +if ($flavour =~ /64/) { + ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); +} + +$code.=<<___; +.align 5 +.Lcbc_dec: + vld1.8 {$dat2},[$inp],#16 + subs $len,$len,#32 // bias + add $cnt,$rounds,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in2,$dat2,$dat2 + b.lo .Lcbc_dec_tail + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + vorr $in2,$dat2,$dat2 +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#32 + b.lo .Loop3x_cbc_dec + + vld1.8 {$dat3},[$inp],#16 + vld1.8 {$dat4},[$inp],#16 + sub $len,$len,#32 // bias + mov $cnt,$rounds + vorr $in3,$dat3,$dat3 + vorr $in4,$dat4,$dat4 + +.Loop5x_cbc_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 + b.gt .Loop5x_cbc_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + cmp $len,#0x40 // because .Lcbc_tail4x + sub $len,$len,#0x50 + + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo + mov $key_,$key + + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat1,q10 + aesimc $dat1,$dat1 + aesd $dat2,q10 + aesimc $dat2,$dat2 + aesd $dat3,q10 + aesimc $dat3,$dat3 + aesd $dat4,q10 + aesimc $dat4,$dat4 + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat4 + // are loaded with last "words" + add x6,$len,#0x60 // because .Lcbc_tail4x + + aesd $dat0,q11 + aesimc $dat0,$dat0 + aesd $dat1,q11 + aesimc $dat1,$dat1 + aesd $dat2,q11 + aesimc $dat2,$dat2 + aesd $dat3,q11 + aesimc $dat3,$dat3 + aesd $dat4,q11 + aesimc $dat4,$dat4 + + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + aesd $dat3,q12 + aesimc $dat3,$dat3 + aesd $dat4,q12 + aesimc $dat4,$dat4 + + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + aesd $dat3,q13 + aesimc $dat3,$dat3 + aesd $dat4,q13 + aesimc $dat4,$dat4 + + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + aesd $dat3,q14 + aesimc $dat3,$dat3 + aesd $dat4,q14 + aesimc $dat4,$dat4 + + veor $tmp0,$ivec,$rndlast + aesd $dat0,q15 + veor $tmp1,$in0,$rndlast + vld1.8 {$in0},[$inp],#16 + aesd $dat1,q15 + veor $tmp2,$in1,$rndlast + vld1.8 {$in1},[$inp],#16 + aesd $dat2,q15 + veor $tmp3,$in2,$rndlast + vld1.8 {$in2},[$inp],#16 + aesd $dat3,q15 + veor $tmp4,$in3,$rndlast + vld1.8 {$in3},[$inp],#16 + aesd $dat4,q15 + vorr $ivec,$in4,$in4 + vld1.8 {$in4},[$inp],#16 + cbz x6,.Lcbc_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + vorr $dat0,$in0,$in0 + veor $tmp1,$tmp1,$dat1 + vorr $dat1,$in1,$in1 + veor $tmp2,$tmp2,$dat2 + vorr $dat2,$in2,$in2 + veor $tmp3,$tmp3,$dat3 + vorr $dat3,$in3,$in3 + veor $tmp4,$tmp4,$dat4 + vst1.8 {$tmp0},[$out],#16 + vorr $dat4,$in4,$in4 + vst1.8 {$tmp1},[$out],#16 + mov $cnt,$rounds + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_cbc_dec + + add $len,$len,#0x50 + cbz $len,.Lcbc_done + + add $cnt,$rounds,#2 + subs $len,$len,#0x30 + vorr $dat0,$in2,$in2 + vorr $in0,$in2,$in2 + vorr $dat1,$in3,$in3 + vorr $in1,$in3,$in3 + vorr $dat2,$in4,$in4 + vorr $in2,$in4,$in4 + b.lo .Lcbc_dec_tail + + b .Loop3x_cbc_dec + +.align 4 +.Lcbc_tail4x: + veor $tmp1,$tmp0,$dat1 + veor $tmp2,$tmp2,$dat2 + veor $tmp3,$tmp3,$dat3 + veor $tmp4,$tmp4,$dat4 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + + b .Lcbc_done +.align 4 +___ +$code.=<<___; +.Loop3x_cbc_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Loop3x_cbc_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + veor $tmp0,$ivec,$rndlast + subs $len,$len,#0x30 + veor $tmp1,$in0,$rndlast + mov.lo x6,$len // x6, $cnt, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + veor $tmp2,$in1,$rndlast + add $inp,$inp,x6 // $inp is adjusted in such way that + // at exit from the loop $dat1-$dat2 + // are loaded with last "words" + vorr $ivec,$in2,$in2 + mov $key_,$key + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + vld1.8 {$in0},[$inp],#16 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + vld1.8 {$in1},[$inp],#16 + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aesd $dat0,q15 + aesd $dat1,q15 + aesd $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $cnt,$rounds,#2 + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vorr $dat0,$in0,$in0 + vst1.8 {$tmp1},[$out],#16 + vorr $dat1,$in1,$in1 + vst1.8 {$dat2},[$out],#16 + vorr $dat2,$in2,$in2 + b.hs .Loop3x_cbc_dec + + cmn $len,#0x30 + b.eq .Lcbc_done nop .Lcbc_dec_tail: @@ -696,6 +1750,9 @@ my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); +# used only in 64-bit mode... +my ($dat3,$dat4,$in3,$in4)=map("q$_",(16..23)); + my ($dat,$tmp)=($dat0,$tmp0); ### q8-q15 preloaded key schedule @@ -762,10 +1819,177 @@ add $ctr, $ctr, #2 vorr $dat1,$ivec,$ivec b.ls .Lctr32_tail - rev $tctr2, $ctr - vmov.32 ${ivec}[3],$tctr2 + rev $tctr2, $ctr + vmov.32 ${ivec}[3],$tctr2 + sub $len,$len,#3 // bias + vorr $dat2,$ivec,$ivec +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#32 + b.lo .Loop3x_ctr32 + + add w13,$ctr,#1 + add w14,$ctr,#2 + vorr $dat3,$dat0,$dat0 + rev w13,w13 + vorr $dat4,$dat0,$dat0 + rev w14,w14 + vmov.32 ${dat3}[3],w13 + sub $len,$len,#2 // bias + vmov.32 ${dat4}[3],w14 + add $ctr,$ctr,#2 + b .Loop5x_ctr32 + +.align 4 +.Loop5x_ctr32: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 + b.gt .Loop5x_ctr32 + + mov $key_,$key + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + + aese $dat0,q12 + aesmc $dat0,$dat0 + add $tctr0,$ctr,#1 + add $tctr1,$ctr,#2 + aese $dat1,q12 + aesmc $dat1,$dat1 + add $tctr2,$ctr,#3 + add w13,$ctr,#4 + aese $dat2,q12 + aesmc $dat2,$dat2 + add w14,$ctr,#5 + rev $tctr0,$tctr0 + aese $dat3,q12 + aesmc $dat3,$dat3 + rev $tctr1,$tctr1 + rev $tctr2,$tctr2 + aese $dat4,q12 + aesmc $dat4,$dat4 + rev w13,w13 + rev w14,w14 + + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat3,q13 + aesmc $dat3,$dat3 + aese $dat4,q13 + aesmc $dat4,$dat4 + + aese $dat0,q14 + aesmc $dat0,$dat0 + vld1.8 {$in0},[$inp],#16 + aese $dat1,q14 + aesmc $dat1,$dat1 + vld1.8 {$in1},[$inp],#16 + aese $dat2,q14 + aesmc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aese $dat3,q14 + aesmc $dat3,$dat3 + vld1.8 {$in3},[$inp],#16 + aese $dat4,q14 + aesmc $dat4,$dat4 + vld1.8 {$in4},[$inp],#16 + + aese $dat0,q15 + veor $in0,$in0,$rndlast + aese $dat1,q15 + veor $in1,$in1,$rndlast + aese $dat2,q15 + veor $in2,$in2,$rndlast + aese $dat3,q15 + veor $in3,$in3,$rndlast + aese $dat4,q15 + veor $in4,$in4,$rndlast + + veor $in0,$in0,$dat0 + vorr $dat0,$ivec,$ivec + veor $in1,$in1,$dat1 + vorr $dat1,$ivec,$ivec + veor $in2,$in2,$dat2 + vorr $dat2,$ivec,$ivec + veor $in3,$in3,$dat3 + vorr $dat3,$ivec,$ivec + veor $in4,$in4,$dat4 + vorr $dat4,$ivec,$ivec + + vst1.8 {$in0},[$out],#16 + vmov.32 ${dat0}[3],$tctr0 + vst1.8 {$in1},[$out],#16 + vmov.32 ${dat1}[3],$tctr1 + vst1.8 {$in2},[$out],#16 + vmov.32 ${dat2}[3],$tctr2 + vst1.8 {$in3},[$out],#16 + vmov.32 ${dat3}[3],w13 + vst1.8 {$in4},[$out],#16 + vmov.32 ${dat4}[3],w14 + + mov $cnt,$rounds + cbz $len,.Lctr32_done + + add $ctr,$ctr,#5 + subs $len,$len,#5 + b.hs .Loop5x_ctr32 + + add $len,$len,#5 + sub $ctr,$ctr,#5 + + cmp $len,#2 + mov $step,#16 + cclr $step,lo + b.ls .Lctr32_tail + sub $len,$len,#3 // bias - vorr $dat2,$ivec,$ivec + add $ctr,$ctr,#3 ___ $code.=<<___; b .Loop3x_ctr32 @@ -888,84 +2112,1510 @@ aese $tmp1,q15 aese $tmp2,q15 - veor $in0,$in0,$tmp0 - vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] - vst1.8 {$in0},[$out],#16 - veor $in1,$in1,$tmp1 - mov $cnt,$rounds - vst1.8 {$in1},[$out],#16 - veor $in2,$in2,$tmp2 - vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] - vst1.8 {$in2},[$out],#16 - b.hs .Loop3x_ctr32 + veor $in0,$in0,$tmp0 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + vst1.8 {$in0},[$out],#16 + veor $in1,$in1,$tmp1 + mov $cnt,$rounds + vst1.8 {$in1},[$out],#16 + veor $in2,$in2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$in2},[$out],#16 + b.hs .Loop3x_ctr32 + + adds $len,$len,#3 + b.eq .Lctr32_done + cmp $len,#1 + mov $step,#16 + cclr $step,eq + +.Lctr32_tail: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + vld1.32 {q8},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.32 {q9},[$key_],#16 + b.gt .Lctr32_tail + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + vld1.8 {$in0},[$inp],$step + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + vld1.8 {$in1},[$inp] + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + veor $in0,$in0,$rndlast + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + veor $in1,$in1,$rndlast + aese $dat0,q15 + aese $dat1,q15 + + cmp $len,#1 + veor $in0,$in0,$dat0 + veor $in1,$in1,$dat1 + vst1.8 {$in0},[$out],#16 + b.eq .Lctr32_done + vst1.8 {$in1},[$out] + +.Lctr32_done: +___ +$code.=<<___ if ($flavour !~ /64/); + vldmia sp!,{d8-d15} + ldmia sp!,{r4-r10,pc} +___ +$code.=<<___ if ($flavour =~ /64/); + ldr x29,[sp],#16 + ret +___ +$code.=<<___; +.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks +___ +}}} +# Performance in cycles per byte. +# Processed with AES-XTS different key size. +# It shows the value before and after optimization as below: +# (before/after): +# +# AES-128-XTS AES-256-XTS +# Cortex-A57 3.36/1.09 4.02/1.37 +# Cortex-A72 3.03/1.02 3.28/1.33 + +# Optimization is implemented by loop unrolling and interleaving. +# Commonly, we choose the unrolling factor as 5, if the input +# data size smaller than 5 blocks, but not smaller than 3 blocks, +# choose 3 as the unrolling factor. +# If the input data size dsize >= 5*16 bytes, then take 5 blocks +# as one iteration, every loop the left size lsize -= 5*16. +# If lsize < 5*16 bytes, treat them as the tail. Note: left 4*16 bytes +# will be processed specially, which be integrated into the 5*16 bytes +# loop to improve the efficiency. +# There is one special case, if the original input data size dsize +# = 16 bytes, we will treat it seperately to improve the +# performance: one independent code block without LR, FP load and +# store. +# Encryption will process the (length -tailcnt) bytes as mentioned +# previously, then encrypt the composite block as last second +# cipher block. +# Decryption will process the (length -tailcnt -1) bytes as mentioned +# previously, then decrypt the last second cipher block to get the +# last plain block(tail), decrypt the composite block as last second +# plain text block. + +{{{ +my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5)); +my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10"); +my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20"); +my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19"); +my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7)); +my ($iv0,$iv1,$iv2,$iv3,$iv4)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b"); +my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]"); +my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]"); + +my ($tmpin)=("v26.16b"); +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); + +# q7 last round key +# q10-q15, q7 Last 7 round keys +# q8-q9 preloaded round keys except last 7 keys for big size +# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte + + +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat3,$in3,$tmp3); # used only in 64-bit mode +my ($dat4,$in4,$tmp4); +if ($flavour =~ /64/) { + ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); +} + +$code.=<<___ if ($flavour =~ /64/); +.globl ${prefix}_xts_encrypt +.type ${prefix}_xts_encrypt,%function +.align 5 +${prefix}_xts_encrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#16 + // Original input data size bigger than 16, jump to big size processing. + b.ne .Lxts_enc_big_size + // Encrypt the iv with key2, as the first XEX iv. + ldr $rounds,[$key2,#240] + vld1.8 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key2],#16 + +.Loop_enc_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_enc_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + vld1.8 {$dat0},[$inp] + veor $dat0,$iv0,$dat0 + + ldr $rounds,[$key1,#240] + vld1.32 {q20-q21},[$key1],#32 // load key schedule... + + aese $dat0,q20 + aesmc $dat0,$dat0 + vld1.32 {q8-q9},[$key1],#32 // load key schedule... + aese $dat0,q21 + aesmc $dat0,$dat0 + subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-xts processing + b.eq .Lxts_128_enc +.Lxts_enc_round_loop: + aese $dat0,q8 + aesmc $dat0,$dat0 + vld1.32 {q8},[$key1],#16 // load key schedule... + aese $dat0,q9 + aesmc $dat0,$dat0 + vld1.32 {q9},[$key1],#16 // load key schedule... + subs $rounds,$rounds,#2 // bias + b.gt .Lxts_enc_round_loop +.Lxts_128_enc: + vld1.32 {q10-q11},[$key1],#32 // load key schedule... + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat0,q9 + aesmc $dat0,$dat0 + vld1.32 {q12-q13},[$key1],#32 // load key schedule... + aese $dat0,q10 + aesmc $dat0,$dat0 + aese $dat0,q11 + aesmc $dat0,$dat0 + vld1.32 {q14-q15},[$key1],#32 // load key schedule... + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat0,q13 + aesmc $dat0,$dat0 + vld1.32 {$rndlast},[$key1] + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat0,q15 + veor $dat0,$dat0,$rndlast + veor $dat0,$dat0,$iv0 + vst1.8 {$dat0},[$out] + b .Lxts_enc_final_abort + +.align 4 +.Lxts_enc_big_size: +___ +$code.=<<___ if ($flavour =~ /64/); + stp $constnumx,$tmpinp,[sp,#-64]! + stp $tailcnt,$midnumx,[sp,#48] + stp $ivd10,$ivd20,[sp,#32] + stp $ivd30,$ivd40,[sp,#16] + + // tailcnt store the tail value of length%16. + and $tailcnt,$len,#0xf + and $len,$len,#-16 + subs $len,$len,#16 + mov $step,#16 + b.lo .Lxts_abort + csel $step,xzr,$step,eq + + // Firstly, encrypt the iv with key2, as the first iv of XEX. + ldr $rounds,[$key2,#240] + vld1.32 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.32 {$dat1},[$key2],#16 + +.Loop_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + // The iv for second block + // $ivl- iv(low), $ivh - iv(high) + // the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4 + fmov $ivl,$ivd00 + fmov $ivh,$ivd01 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + + ldr $rounds0,[$key1,#240] // next starting point + vld1.8 {$dat},[$inp],$step + + vld1.32 {q8-q9},[$key1] // load key schedule... + sub $rounds0,$rounds0,#6 + add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys + sub $rounds0,$rounds0,#2 + vld1.32 {q10-q11},[$key_],#32 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + add $key_,$key1,#32 + mov $rounds,$rounds0 + + // Encryption +.Lxts_enc: + vld1.8 {$dat2},[$inp],#16 + subs $len,$len,#32 // bias + add $rounds,$rounds0,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in3,$dat,$dat + vorr $in2,$dat2,$dat2 + vorr $in4,$dat2,$dat2 + b.lo .Lxts_inner_enc_tail + veor $dat,$dat,$iv0 // before encryption, xor with iv + veor $dat2,$dat2,$iv1 + + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + veor $in2,$dat2,$iv2 // the third block + veor $dat2,$dat2,$iv2 + cmp $len,#32 + b.lo .Lxts_outer_enc_tail + + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + + vld1.8 {$dat3},[$inp],#16 + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$dat4},[$inp],#16 + veor $dat3,$dat3,$iv3 // the fourth block + veor $dat4,$dat4,$iv4 + sub $len,$len,#32 // bias + mov $rounds,$rounds0 + b .Loop5x_xts_enc + +.align 4 +.Loop5x_xts_enc: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 + b.gt .Loop5x_xts_enc + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + subs $len,$len,#0x50 // because .Lxts_enc_tail4x + + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo + mov $key_,$key1 + + aese $dat0,q10 + aesmc $dat0,$dat0 + aese $dat1,q10 + aesmc $dat1,$dat1 + aese $dat2,q10 + aesmc $dat2,$dat2 + aese $dat3,q10 + aesmc $dat3,$dat3 + aese $dat4,q10 + aesmc $dat4,$dat4 + add $inp,$inp,$xoffset // x0 is adjusted in such way that + // at exit from the loop v1.16b-v26.16b + // are loaded with last "words" + add $xoffset,$len,#0x60 // because .Lxts_enc_tail4x + + aese $dat0,q11 + aesmc $dat0,$dat0 + aese $dat1,q11 + aesmc $dat1,$dat1 + aese $dat2,q11 + aesmc $dat2,$dat2 + aese $dat3,q11 + aesmc $dat3,$dat3 + aese $dat4,q11 + aesmc $dat4,$dat4 + + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + aese $dat3,q12 + aesmc $dat3,$dat3 + aese $dat4,q12 + aesmc $dat4,$dat4 + + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat3,q13 + aesmc $dat3,$dat3 + aese $dat4,q13 + aesmc $dat4,$dat4 + + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + aese $dat3,q14 + aesmc $dat3,$dat3 + aese $dat4,q14 + aesmc $dat4,$dat4 + + veor $tmp0,$rndlast,$iv0 + aese $dat0,q15 + // The iv for first block of one iteration + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$rndlast,$iv1 + vld1.8 {$in0},[$inp],#16 + aese $dat1,q15 + // The iv for second block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + veor $tmp2,$rndlast,$iv2 + vld1.8 {$in1},[$inp],#16 + aese $dat2,q15 + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + veor $tmp3,$rndlast,$iv3 + vld1.8 {$in2},[$inp],#16 + aese $dat3,q15 + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + veor $tmp4,$rndlast,$iv4 + vld1.8 {$in3},[$inp],#16 + aese $dat4,q15 + + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$in4},[$inp],#16 + cbz $xoffset,.Lxts_enc_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + veor $dat0,$in0,$iv0 + veor $tmp1,$tmp1,$dat1 + veor $dat1,$in1,$iv1 + veor $tmp2,$tmp2,$dat2 + veor $dat2,$in2,$iv2 + veor $tmp3,$tmp3,$dat3 + veor $dat3,$in3,$iv3 + veor $tmp4,$tmp4,$dat4 + vst1.8 {$tmp0},[$out],#16 + veor $dat4,$in4,$iv4 + vst1.8 {$tmp1},[$out],#16 + mov $rounds,$rounds0 + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_xts_enc + + + // If left 4 blocks, borrow the five block's processing. + cmn $len,#0x10 + b.ne .Loop5x_enc_after + vorr $iv4,$iv3,$iv3 + vorr $iv3,$iv2,$iv2 + vorr $iv2,$iv1,$iv1 + vorr $iv1,$iv0,$iv0 + fmov $ivl,$ivd40 + fmov $ivh,$ivd41 + veor $dat0,$iv0,$in0 + veor $dat1,$iv1,$in1 + veor $dat2,$in2,$iv2 + veor $dat3,$in3,$iv3 + veor $dat4,$in4,$iv4 + b.eq .Loop5x_xts_enc + +.Loop5x_enc_after: + add $len,$len,#0x50 + cbz $len,.Lxts_enc_done + + add $rounds,$rounds0,#2 + subs $len,$len,#0x30 + b.lo .Lxts_inner_enc_tail + + veor $dat0,$iv0,$in2 + veor $dat1,$iv1,$in3 + veor $dat2,$in4,$iv2 + b .Lxts_outer_enc_tail + +.align 4 +.Lxts_enc_tail4x: + add $inp,$inp,#16 + veor $tmp1,$dat1,$tmp1 + vst1.8 {$tmp1},[$out],#16 + veor $tmp2,$dat2,$tmp2 + vst1.8 {$tmp2},[$out],#16 + veor $tmp3,$dat3,$tmp3 + veor $tmp4,$dat4,$tmp4 + vst1.8 {$tmp3-$tmp4},[$out],#32 + + b .Lxts_enc_done +.align 4 +.Lxts_outer_enc_tail: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_outer_enc_tail + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + veor $tmp0,$iv0,$rndlast + subs $len,$len,#0x30 + // The iv for first block + fmov $ivl,$ivd20 + fmov $ivh,$ivd21 + //mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$iv1,$rndlast + csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + veor $tmp2,$iv2,$rndlast + + add $xoffset,$xoffset,#0x20 + add $inp,$inp,$xoffset + mov $key_,$key1 + + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + aese $dat0,q15 + aese $dat1,q15 + aese $dat2,q15 + vld1.8 {$in2},[$inp],#16 + add $rounds,$rounds0,#2 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$dat2},[$out],#16 + cmn $len,#0x30 + b.eq .Lxts_enc_done +.Lxts_encxor_one: + vorr $in3,$in1,$in1 + vorr $in4,$in2,$in2 + nop + +.Lxts_inner_enc_tail: + cmn $len,#0x10 + veor $dat1,$in3,$iv0 + veor $dat2,$in4,$iv1 + b.eq .Lxts_enc_tail_loop + veor $dat2,$in4,$iv0 +.Lxts_enc_tail_loop: + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_enc_tail_loop + + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + cmn $len,#0x20 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + veor $tmp1,$iv0,$rndlast + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + veor $tmp2,$iv1,$rndlast + aese $dat1,q15 + aese $dat2,q15 + b.eq .Lxts_enc_one + veor $tmp1,$tmp1,$dat1 + vst1.8 {$tmp1},[$out],#16 + veor $tmp2,$tmp2,$dat2 + vorr $iv0,$iv1,$iv1 + vst1.8 {$tmp2},[$out],#16 + fmov $ivl,$ivd10 + fmov $ivh,$ivd11 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + b .Lxts_enc_done + +.Lxts_enc_one: + veor $tmp1,$tmp1,$dat2 + vorr $iv0,$iv0,$iv0 + vst1.8 {$tmp1},[$out],#16 + fmov $ivl,$ivd00 + fmov $ivh,$ivd01 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + b .Lxts_enc_done +.align 5 +.Lxts_enc_done: + // Process the tail block with cipher stealing. + tst $tailcnt,#0xf + b.eq .Lxts_abort + + mov $tmpinp,$inp + mov $tmpoutp,$out + sub $out,$out,#16 +.composite_enc_loop: + subs $tailcnt,$tailcnt,#1 + ldrb $l2outp,[$out,$tailcnt] + ldrb $loutp,[$tmpinp,$tailcnt] + strb $l2outp,[$tmpoutp,$tailcnt] + strb $loutp,[$out,$tailcnt] + b.gt .composite_enc_loop +.Lxts_enc_load_done: + vld1.8 {$tmpin},[$out] + veor $tmpin,$tmpin,$iv0 + + // Encrypt the composite block to get the last second encrypted text block + ldr $rounds,[$key1,#240] // load key schedule... + vld1.8 {$dat},[$key1],#16 + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key1],#16 // load key schedule... +.Loop_final_enc: + aese $tmpin,$dat0 + aesmc $tmpin,$tmpin + vld1.32 {$dat0},[$key1],#16 + subs $rounds,$rounds,#2 + aese $tmpin,$dat1 + aesmc $tmpin,$tmpin + vld1.32 {$dat1},[$key1],#16 + b.gt .Loop_final_enc + + aese $tmpin,$dat0 + aesmc $tmpin,$tmpin + vld1.32 {$dat0},[$key1] + aese $tmpin,$dat1 + veor $tmpin,$tmpin,$dat0 + veor $tmpin,$tmpin,$iv0 + vst1.8 {$tmpin},[$out] + +.Lxts_abort: + ldp $tailcnt,$midnumx,[sp,#48] + ldp $ivd10,$ivd20,[sp,#32] + ldp $ivd30,$ivd40,[sp,#16] + ldp $constnumx,$tmpinp,[sp],#64 +.Lxts_enc_final_abort: + ret +.size ${prefix}_xts_encrypt,.-${prefix}_xts_encrypt +___ + +}}} +{{{ +my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5)); +my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10"); +my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20"); +my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19"); +my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7)); +my ($iv0,$iv1,$iv2,$iv3,$iv4,$tmpin)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b","v26.16b"); +my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]"); +my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]"); + +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); + +# q7 last round key +# q10-q15, q7 Last 7 round keys +# q8-q9 preloaded round keys except last 7 keys for big size +# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte + +{ +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat3,$in3,$tmp3); # used only in 64-bit mode +my ($dat4,$in4,$tmp4); +if ($flavour =~ /64/) { + ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); +} + +$code.=<<___ if ($flavour =~ /64/); +.globl ${prefix}_xts_decrypt +.type ${prefix}_xts_decrypt,%function +.align 5 +${prefix}_xts_decrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#16 + // Original input data size bigger than 16, jump to big size processing. + b.ne .Lxts_dec_big_size + // Encrypt the iv with key2, as the first XEX iv. + ldr $rounds,[$key2,#240] + vld1.8 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key2],#16 + +.Loop_dec_small_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_dec_small_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + vld1.8 {$dat0},[$inp] + veor $dat0,$iv0,$dat0 + + ldr $rounds,[$key1,#240] + vld1.32 {q20-q21},[$key1],#32 // load key schedule... + + aesd $dat0,q20 + aesimc $dat0,$dat0 + vld1.32 {q8-q9},[$key1],#32 // load key schedule... + aesd $dat0,q21 + aesimc $dat0,$dat0 + subs $rounds,$rounds,#10 // bias + b.eq .Lxts_128_dec +.Lxts_dec_round_loop: + aesd $dat0,q8 + aesimc $dat0,$dat0 + vld1.32 {q8},[$key1],#16 // load key schedule... + aesd $dat0,q9 + aesimc $dat0,$dat0 + vld1.32 {q9},[$key1],#16 // load key schedule... + subs $rounds,$rounds,#2 // bias + b.gt .Lxts_dec_round_loop +.Lxts_128_dec: + vld1.32 {q10-q11},[$key1],#32 // load key schedule... + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat0,q9 + aesimc $dat0,$dat0 + vld1.32 {q12-q13},[$key1],#32 // load key schedule... + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat0,q11 + aesimc $dat0,$dat0 + vld1.32 {q14-q15},[$key1],#32 // load key schedule... + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat0,q13 + aesimc $dat0,$dat0 + vld1.32 {$rndlast},[$key1] + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat0,q15 + veor $dat0,$dat0,$rndlast + veor $dat0,$iv0,$dat0 + vst1.8 {$dat0},[$out] + b .Lxts_dec_final_abort +.Lxts_dec_big_size: +___ +$code.=<<___ if ($flavour =~ /64/); + stp $constnumx,$tmpinp,[sp,#-64]! + stp $tailcnt,$midnumx,[sp,#48] + stp $ivd10,$ivd20,[sp,#32] + stp $ivd30,$ivd40,[sp,#16] + + and $tailcnt,$len,#0xf + and $len,$len,#-16 + subs $len,$len,#16 + mov $step,#16 + b.lo .Lxts_dec_abort + + // Encrypt the iv with key2, as the first XEX iv + ldr $rounds,[$key2,#240] + vld1.8 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key2],#16 + +.Loop_dec_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_dec_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + // The iv for second block + // $ivl- iv(low), $ivh - iv(high) + // the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4 + fmov $ivl,$ivd00 + fmov $ivh,$ivd01 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + + ldr $rounds0,[$key1,#240] // load rounds number + + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + + vld1.32 {q8-q9},[$key1] // load key schedule... + sub $rounds0,$rounds0,#6 + add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys + sub $rounds0,$rounds0,#2 + vld1.32 {q10-q11},[$key_],#32 // load key schedule... + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + + add $key_,$key1,#32 + mov $rounds,$rounds0 + b .Lxts_dec + + // Decryption +.align 5 +.Lxts_dec: + tst $tailcnt,#0xf + b.eq .Lxts_dec_begin + subs $len,$len,#16 + csel $step,xzr,$step,eq + vld1.8 {$dat},[$inp],#16 + b.lo .Lxts_done + sub $inp,$inp,#16 +.Lxts_dec_begin: + vld1.8 {$dat},[$inp],$step + subs $len,$len,#32 // bias + add $rounds,$rounds0,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in3,$dat,$dat + vld1.8 {$dat2},[$inp],#16 + vorr $in2,$dat2,$dat2 + vorr $in4,$dat2,$dat2 + b.lo .Lxts_inner_dec_tail + veor $dat,$dat,$iv0 // before decryt, xor with iv + veor $dat2,$dat2,$iv1 + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + veor $in2,$dat2,$iv2 // third block xox with third iv + veor $dat2,$dat2,$iv2 + cmp $len,#32 + b.lo .Lxts_outer_dec_tail + + vld1.8 {$dat3},[$inp],#16 + + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$dat4},[$inp],#16 + veor $dat3,$dat3,$iv3 // the fourth block + veor $dat4,$dat4,$iv4 + sub $len,$len,#32 // bias + mov $rounds,$rounds0 + b .Loop5x_xts_dec - adds $len,$len,#3 - b.eq .Lctr32_done - cmp $len,#1 - mov $step,#16 - cclr $step,eq +.align 4 +.Loop5x_xts_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 // load key schedule... + subs $rounds,$rounds,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 // load key schedule... + b.gt .Loop5x_xts_dec -.Lctr32_tail: - aese $dat0,q8 - aesmc $dat0,$dat0 - aese $dat1,q8 - aesmc $dat1,$dat1 - vld1.32 {q8},[$key_],#16 - subs $cnt,$cnt,#2 - aese $dat0,q9 - aesmc $dat0,$dat0 - aese $dat1,q9 - aesmc $dat1,$dat1 - vld1.32 {q9},[$key_],#16 - b.gt .Lctr32_tail + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + subs $len,$len,#0x50 // because .Lxts_dec_tail4x - aese $dat0,q8 - aesmc $dat0,$dat0 - aese $dat1,q8 - aesmc $dat1,$dat1 - aese $dat0,q9 - aesmc $dat0,$dat0 - aese $dat1,q9 - aesmc $dat1,$dat1 - vld1.8 {$in0},[$inp],$step - aese $dat0,q12 - aesmc $dat0,$dat0 - aese $dat1,q12 - aesmc $dat1,$dat1 - vld1.8 {$in1},[$inp] - aese $dat0,q13 - aesmc $dat0,$dat0 - aese $dat1,q13 - aesmc $dat1,$dat1 - veor $in0,$in0,$rndlast - aese $dat0,q14 - aesmc $dat0,$dat0 - aese $dat1,q14 - aesmc $dat1,$dat1 - veor $in1,$in1,$rndlast - aese $dat0,q15 - aese $dat1,q15 + aesd $dat0,q9 + aesimc $dat0,$dat + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo + mov $key_,$key1 + + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat1,q10 + aesimc $dat1,$dat1 + aesd $dat2,q10 + aesimc $dat2,$dat2 + aesd $dat3,q10 + aesimc $dat3,$dat3 + aesd $dat4,q10 + aesimc $dat4,$dat4 + add $inp,$inp,$xoffset // x0 is adjusted in such way that + // at exit from the loop v1.16b-v26.16b + // are loaded with last "words" + add $xoffset,$len,#0x60 // because .Lxts_dec_tail4x + + aesd $dat0,q11 + aesimc $dat0,$dat0 + aesd $dat1,q11 + aesimc $dat1,$dat1 + aesd $dat2,q11 + aesimc $dat2,$dat2 + aesd $dat3,q11 + aesimc $dat3,$dat3 + aesd $dat4,q11 + aesimc $dat4,$dat4 - cmp $len,#1 - veor $in0,$in0,$dat0 - veor $in1,$in1,$dat1 - vst1.8 {$in0},[$out],#16 - b.eq .Lctr32_done - vst1.8 {$in1},[$out] + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + aesd $dat3,q12 + aesimc $dat3,$dat3 + aesd $dat4,q12 + aesimc $dat4,$dat4 -.Lctr32_done: -___ -$code.=<<___ if ($flavour !~ /64/); - vldmia sp!,{d8-d15} - ldmia sp!,{r4-r10,pc} -___ -$code.=<<___ if ($flavour =~ /64/); - ldr x29,[sp],#16 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + aesd $dat3,q13 + aesimc $dat3,$dat3 + aesd $dat4,q13 + aesimc $dat4,$dat4 + + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + aesd $dat3,q14 + aesimc $dat3,$dat3 + aesd $dat4,q14 + aesimc $dat4,$dat4 + + veor $tmp0,$rndlast,$iv0 + aesd $dat0,q15 + // The iv for first block of next iteration. + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$rndlast,$iv1 + vld1.8 {$in0},[$inp],#16 + aesd $dat1,q15 + // The iv for second block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + veor $tmp2,$rndlast,$iv2 + vld1.8 {$in1},[$inp],#16 + aesd $dat2,q15 + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + veor $tmp3,$rndlast,$iv3 + vld1.8 {$in2},[$inp],#16 + aesd $dat3,q15 + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + veor $tmp4,$rndlast,$iv4 + vld1.8 {$in3},[$inp],#16 + aesd $dat4,q15 + + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$in4},[$inp],#16 + cbz $xoffset,.Lxts_dec_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + veor $dat0,$in0,$iv0 + veor $tmp1,$tmp1,$dat1 + veor $dat1,$in1,$iv1 + veor $tmp2,$tmp2,$dat2 + veor $dat2,$in2,$iv2 + veor $tmp3,$tmp3,$dat3 + veor $dat3,$in3,$iv3 + veor $tmp4,$tmp4,$dat4 + vst1.8 {$tmp0},[$out],#16 + veor $dat4,$in4,$iv4 + vst1.8 {$tmp1},[$out],#16 + mov $rounds,$rounds0 + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_xts_dec + + cmn $len,#0x10 + b.ne .Loop5x_dec_after + // If x2($len) equal to -0x10, the left blocks is 4. + // After specially processing, utilize the five blocks processing again. + // It will use the following IVs: $iv0,$iv0,$iv1,$iv2,$iv3. + vorr $iv4,$iv3,$iv3 + vorr $iv3,$iv2,$iv2 + vorr $iv2,$iv1,$iv1 + vorr $iv1,$iv0,$iv0 + fmov $ivl,$ivd40 + fmov $ivh,$ivd41 + veor $dat0,$iv0,$in0 + veor $dat1,$iv1,$in1 + veor $dat2,$in2,$iv2 + veor $dat3,$in3,$iv3 + veor $dat4,$in4,$iv4 + b.eq .Loop5x_xts_dec + +.Loop5x_dec_after: + add $len,$len,#0x50 + cbz $len,.Lxts_done + + add $rounds,$rounds0,#2 + subs $len,$len,#0x30 + b.lo .Lxts_inner_dec_tail + + veor $dat0,$iv0,$in2 + veor $dat1,$iv1,$in3 + veor $dat2,$in4,$iv2 + b .Lxts_outer_dec_tail + +.align 4 +.Lxts_dec_tail4x: + add $inp,$inp,#16 + vld1.32 {$dat0},[$inp],#16 + veor $tmp1,$dat1,$tmp0 + vst1.8 {$tmp1},[$out],#16 + veor $tmp2,$dat2,$tmp2 + vst1.8 {$tmp2},[$out],#16 + veor $tmp3,$dat3,$tmp3 + veor $tmp4,$dat4,$tmp4 + vst1.8 {$tmp3-$tmp4},[$out],#32 + + b .Lxts_done +.align 4 +.Lxts_outer_dec_tail: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_outer_dec_tail + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + veor $tmp0,$iv0,$rndlast + subs $len,$len,#0x30 + // The iv for first block + fmov $ivl,$ivd20 + fmov $ivh,$ivd21 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$iv1,$rndlast + csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + veor $tmp2,$iv2,$rndlast + // The iv for second block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + + add $xoffset,$xoffset,#0x20 + add $inp,$inp,$xoffset // $inp is adjusted to the last data + + mov $key_,$key1 + + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + vld1.8 {$in2},[$inp],#16 + aesd $dat0,q15 + aesd $dat1,q15 + aesd $dat2,q15 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + add $rounds,$rounds0,#2 + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$dat2},[$out],#16 + + cmn $len,#0x30 + add $len,$len,#0x30 + b.eq .Lxts_done + sub $len,$len,#0x30 + vorr $in3,$in1,$in1 + vorr $in4,$in2,$in2 + nop + +.Lxts_inner_dec_tail: + // $len == -0x10 means two blocks left. + cmn $len,#0x10 + veor $dat1,$in3,$iv0 + veor $dat2,$in4,$iv1 + b.eq .Lxts_dec_tail_loop + veor $dat2,$in4,$iv0 +.Lxts_dec_tail_loop: + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_dec_tail_loop + + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + cmn $len,#0x20 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + veor $tmp1,$iv0,$rndlast + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + veor $tmp2,$iv1,$rndlast + aesd $dat1,q15 + aesd $dat2,q15 + b.eq .Lxts_dec_one + veor $tmp1,$tmp1,$dat1 + veor $tmp2,$tmp2,$dat2 + vorr $iv0,$iv2,$iv2 + vorr $iv1,$iv3,$iv3 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$tmp2},[$out],#16 + add $len,$len,#16 + b .Lxts_done + +.Lxts_dec_one: + veor $tmp1,$tmp1,$dat2 + vorr $iv0,$iv1,$iv1 + vorr $iv1,$iv2,$iv2 + vst1.8 {$tmp1},[$out],#16 + add $len,$len,#32 + +.Lxts_done: + tst $tailcnt,#0xf + b.eq .Lxts_dec_abort + // Processing the last two blocks with cipher stealing. + mov x7,x3 + cbnz x2,.Lxts_dec_1st_done + vld1.32 {$dat0},[$inp],#16 + + // Decrypt the last secod block to get the last plain text block +.Lxts_dec_1st_done: + eor $tmpin,$dat0,$iv1 + ldr $rounds,[$key1,#240] + vld1.32 {$dat0},[$key1],#16 + sub $rounds,$rounds,#2 + vld1.32 {$dat1},[$key1],#16 +.Loop_final_2nd_dec: + aesd $tmpin,$dat0 + aesimc $tmpin,$tmpin + vld1.32 {$dat0},[$key1],#16 // load key schedule... + subs $rounds,$rounds,#2 + aesd $tmpin,$dat1 + aesimc $tmpin,$tmpin + vld1.32 {$dat1},[$key1],#16 // load key schedule... + b.gt .Loop_final_2nd_dec + + aesd $tmpin,$dat0 + aesimc $tmpin,$tmpin + vld1.32 {$dat0},[$key1] + aesd $tmpin,$dat1 + veor $tmpin,$tmpin,$dat0 + veor $tmpin,$tmpin,$iv1 + vst1.8 {$tmpin},[$out] + + mov $tmpinp,$inp + add $tmpoutp,$out,#16 + + // Composite the tailcnt "16 byte not aligned block" into the last second plain blocks + // to get the last encrypted block. +.composite_dec_loop: + subs $tailcnt,$tailcnt,#1 + ldrb $l2outp,[$out,$tailcnt] + ldrb $loutp,[$tmpinp,$tailcnt] + strb $l2outp,[$tmpoutp,$tailcnt] + strb $loutp,[$out,$tailcnt] + b.gt .composite_dec_loop +.Lxts_dec_load_done: + vld1.8 {$tmpin},[$out] + veor $tmpin,$tmpin,$iv0 + + // Decrypt the composite block to get the last second plain text block + ldr $rounds,[$key_,#240] + vld1.8 {$dat},[$key_],#16 + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key_],#16 +.Loop_final_dec: + aesd $tmpin,$dat0 + aesimc $tmpin,$tmpin + vld1.32 {$dat0},[$key_],#16 // load key schedule... + subs $rounds,$rounds,#2 + aesd $tmpin,$dat1 + aesimc $tmpin,$tmpin + vld1.32 {$dat1},[$key_],#16 // load key schedule... + b.gt .Loop_final_dec + + aesd $tmpin,$dat0 + aesimc $tmpin,$tmpin + vld1.32 {$dat0},[$key_] + aesd $tmpin,$dat1 + veor $tmpin,$tmpin,$dat0 + veor $tmpin,$tmpin,$iv0 + vst1.8 {$tmpin},[$out] + +.Lxts_dec_abort: + ldp $tailcnt,$midnumx,[sp,#48] + ldp $ivd10,$ivd20,[sp,#32] + ldp $ivd30,$ivd40,[sp,#16] + ldp $constnumx,$tmpinp,[sp],#64 + +.Lxts_dec_final_abort: ret +.size ${prefix}_xts_decrypt,.-${prefix}_xts_decrypt ___ -$code.=<<___; -.size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks -___ +} }}} $code.=<<___; #endif @@ -1025,7 +3675,7 @@ # since ARMv7 instructions are always encoded little-endian. # correct solution is to use .inst directive, but older # assemblers don't implement it:-( - sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", + sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s", $word&0xff,($word>>8)&0xff, ($word>>16)&0xff,($word>>24)&0xff, $mnemonic,$arg; @@ -1066,14 +3716,17 @@ s/\],#[0-9]+/]!/o; s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or - s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or + s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or s/vtbl\.8\s+(.*)/unvtbl($1)/geo or s/vdup\.32\s+(.*)/unvdup32($1)/geo or s/vmov\.32\s+(.*)/unvmov32($1)/geo or s/^(\s+)b\./$1b/o or - s/^(\s+)mov\./$1mov/o or s/^(\s+)ret/$1bx\tlr/o; + if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) { + print " it $2\n"; + } + print $_,"\n"; } } diff --git a/crypto/aes/asm/bsaes-armv7.pl b/crypto/aes/asm/bsaes-armv7.pl --- a/crypto/aes/asm/bsaes-armv7.pl +++ b/crypto/aes/asm/bsaes-armv7.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -50,9 +50,10 @@ # April-August 2013 # Add CBC, CTR and XTS subroutines and adapt for kernel use; courtesy of Ard. -$flavour = shift; -if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } -else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour && $flavour ne "void") { $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; @@ -60,9 +61,10 @@ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; - open STDOUT,"| \"$^X\" $xlate $flavour $output"; + open STDOUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; } else { - open STDOUT,">$output"; + $output and open STDOUT,">$output"; } my ($inp,$out,$len,$key)=("r0","r1","r2","r3"); @@ -728,7 +730,6 @@ .arch armv7-a .fpu neon -.text .syntax unified @ ARMv7-capable assembler is expected to handle this #if defined(__thumb2__) && !defined(__APPLE__) .thumb @@ -737,6 +738,8 @@ # undef __thumb2__ #endif +.text + .type _bsaes_decrypt8,%function .align 4 _bsaes_decrypt8: @@ -1116,18 +1119,18 @@ .extern AES_cbc_encrypt .extern AES_decrypt -.global bsaes_cbc_encrypt -.type bsaes_cbc_encrypt,%function +.global ossl_bsaes_cbc_encrypt +.type ossl_bsaes_cbc_encrypt,%function .align 5 -bsaes_cbc_encrypt: +ossl_bsaes_cbc_encrypt: #ifndef __KERNEL__ cmp $len, #128 #ifndef __thumb__ blo AES_cbc_encrypt #else - bhs 1f + bhs .Lcbc_do_bsaes b AES_cbc_encrypt -1: +.Lcbc_do_bsaes: #endif #endif @@ -1381,7 +1384,7 @@ vst1.8 {@XMM[15]}, [$ivp] @ return IV VFP_ABI_POP ldmia sp!, {r4-r10, pc} -.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt +.size ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt ___ } { @@ -1391,10 +1394,10 @@ $code.=<<___; .extern AES_encrypt -.global bsaes_ctr32_encrypt_blocks -.type bsaes_ctr32_encrypt_blocks,%function +.global ossl_bsaes_ctr32_encrypt_blocks +.type ossl_bsaes_ctr32_encrypt_blocks,%function .align 5 -bsaes_ctr32_encrypt_blocks: +ossl_bsaes_ctr32_encrypt_blocks: cmp $len, #8 @ use plain AES for blo .Lctr_enc_short @ small sizes @@ -1617,7 +1620,7 @@ vstmia sp!, {q0-q1} ldmia sp!, {r4-r8, pc} -.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks +.size ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks ___ } { @@ -1632,10 +1635,10 @@ my @T=@XMM[6..7]; $code.=<<___; -.globl bsaes_xts_encrypt -.type bsaes_xts_encrypt,%function +.globl ossl_bsaes_xts_encrypt +.type ossl_bsaes_xts_encrypt,%function .align 4 -bsaes_xts_encrypt: +ossl_bsaes_xts_encrypt: mov ip, sp stmdb sp!, {r4-r10, lr} @ 0x20 VFP_ABI_PUSH @@ -2034,12 +2037,12 @@ VFP_ABI_POP ldmia sp!, {r4-r10, pc} @ return -.size bsaes_xts_encrypt,.-bsaes_xts_encrypt +.size ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt -.globl bsaes_xts_decrypt -.type bsaes_xts_decrypt,%function +.globl ossl_bsaes_xts_decrypt +.type ossl_bsaes_xts_decrypt,%function .align 4 -bsaes_xts_decrypt: +ossl_bsaes_xts_decrypt: mov ip, sp stmdb sp!, {r4-r10, lr} @ 0x20 VFP_ABI_PUSH @@ -2469,7 +2472,7 @@ VFP_ABI_POP ldmia sp!, {r4-r10, pc} @ return -.size bsaes_xts_decrypt,.-bsaes_xts_decrypt +.size ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt ___ } $code.=<<___; diff --git a/crypto/aes/asm/bsaes-x86_64.pl b/crypto/aes/asm/bsaes-x86_64.pl new file mode 100644 --- /dev/null +++ b/crypto/aes/asm/bsaes-x86_64.pl @@ -0,0 +1,3243 @@ +#! /usr/bin/env perl +# Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +################################################################### +### AES-128 [originally in CTR mode] ### +### bitsliced implementation for Intel Core 2 processors ### +### requires support of SSE extensions up to SSSE3 ### +### Author: Emilia Käsper and Peter Schwabe ### +### Date: 2009-03-19 ### +### Public domain ### +### ### +### See http://homes.esat.kuleuven.be/~ekasper/#software for ### +### further information. ### +################################################################### +# +# September 2011. +# +# Started as transliteration to "perlasm" the original code has +# undergone following changes: +# +# - code was made position-independent; +# - rounds were folded into a loop resulting in >5x size reduction +# from 12.5KB to 2.2KB; +# - above was possible thanks to mixcolumns() modification that +# allowed to feed its output back to aesenc[last], this was +# achieved at cost of two additional inter-registers moves; +# - some instruction reordering and interleaving; +# - this module doesn't implement key setup subroutine, instead it +# relies on conversion of "conventional" key schedule as returned +# by AES_set_encrypt_key (see discussion below); +# - first and last round keys are treated differently, which allowed +# to skip one shiftrows(), reduce bit-sliced key schedule and +# speed-up conversion by 22%; +# - support for 192- and 256-bit keys was added; +# +# Resulting performance in CPU cycles spent to encrypt one byte out +# of 4096-byte buffer with 128-bit key is: +# +# Emilia's this(*) difference +# +# Core 2 9.30 8.69 +7% +# Nehalem(**) 7.63 6.88 +11% +# Atom 17.1 16.4 +4% +# Silvermont - 12.9 +# Goldmont - 8.85 +# +# (*) Comparison is not completely fair, because "this" is ECB, +# i.e. no extra processing such as counter values calculation +# and xor-ing input as in Emilia's CTR implementation is +# performed. However, the CTR calculations stand for not more +# than 1% of total time, so comparison is *rather* fair. +# +# (**) Results were collected on Westmere, which is considered to +# be equivalent to Nehalem for this code. +# +# As for key schedule conversion subroutine. Interface to OpenSSL +# relies on per-invocation on-the-fly conversion. This naturally +# has impact on performance, especially for short inputs. Conversion +# time in CPU cycles and its ratio to CPU cycles spent in 8x block +# function is: +# +# conversion conversion/8x block +# Core 2 240 0.22 +# Nehalem 180 0.20 +# Atom 430 0.20 +# +# The ratio values mean that 128-byte blocks will be processed +# 16-18% slower, 256-byte blocks - 9-10%, 384-byte blocks - 6-7%, +# etc. Then keep in mind that input sizes not divisible by 128 are +# *effectively* slower, especially shortest ones, e.g. consecutive +# 144-byte blocks are processed 44% slower than one would expect, +# 272 - 29%, 400 - 22%, etc. Yet, despite all these "shortcomings" +# it's still faster than ["hyper-threading-safe" code path in] +# aes-x86_64.pl on all lengths above 64 bytes... +# +# October 2011. +# +# Add decryption procedure. Performance in CPU cycles spent to decrypt +# one byte out of 4096-byte buffer with 128-bit key is: +# +# Core 2 9.98 +# Nehalem 7.80 +# Atom 17.9 +# Silvermont 14.0 +# Goldmont 10.2 +# +# November 2011. +# +# Add bsaes_xts_[en|de]crypt. Less-than-80-bytes-block performance is +# suboptimal, but XTS is meant to be used with larger blocks... +# +# + +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; +*STDOUT=*OUT; + +my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx"); +my @XMM=map("%xmm$_",(15,0..14)); # best on Atom, +10% over (0..15) +my $ecb=0; # suppress unreferenced ECB subroutines, spare some space... + +{ +my ($key,$rounds,$const)=("%rax","%r10d","%r11"); + +sub Sbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InBasisChange (@b); + &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s); + &OutBasisChange (@b[7,1,4,2,6,5,0,3]); +} + +sub InBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb +my @b=@_[0..7]; +$code.=<<___; + pxor @b[6], @b[5] + pxor @b[1], @b[2] + pxor @b[0], @b[3] + pxor @b[2], @b[6] + pxor @b[0], @b[5] + + pxor @b[3], @b[6] + pxor @b[7], @b[3] + pxor @b[5], @b[7] + pxor @b[4], @b[3] + pxor @b[5], @b[4] + pxor @b[1], @b[3] + + pxor @b[7], @b[2] + pxor @b[5], @b[1] +___ +} + +sub OutBasisChange { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb +my @b=@_[0..7]; +$code.=<<___; + pxor @b[6], @b[0] + pxor @b[4], @b[1] + pxor @b[0], @b[2] + pxor @b[6], @b[4] + pxor @b[1], @b[6] + + pxor @b[5], @b[1] + pxor @b[3], @b[5] + pxor @b[7], @b[3] + pxor @b[5], @b[7] + pxor @b[5], @b[2] + + pxor @b[7], @b[4] +___ +} + +sub InvSbox { +# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb +# output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb +my @b=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; + &InvInBasisChange (@b); + &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s); + &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]); +} + +sub InvInBasisChange { # OutBasisChange in reverse +my @b=@_[5,1,2,6,3,7,0,4]; +$code.=<<___ + pxor @b[7], @b[4] + + pxor @b[5], @b[7] + pxor @b[5], @b[2] + pxor @b[7], @b[3] + pxor @b[3], @b[5] + pxor @b[5], @b[1] + + pxor @b[1], @b[6] + pxor @b[0], @b[2] + pxor @b[6], @b[4] + pxor @b[6], @b[0] + pxor @b[4], @b[1] +___ +} + +sub InvOutBasisChange { # InBasisChange in reverse +my @b=@_[2,5,7,3,6,1,0,4]; +$code.=<<___; + pxor @b[5], @b[1] + pxor @b[7], @b[2] + + pxor @b[1], @b[3] + pxor @b[5], @b[4] + pxor @b[5], @b[7] + pxor @b[4], @b[3] + pxor @b[0], @b[5] + pxor @b[7], @b[3] + pxor @b[2], @b[6] + pxor @b[1], @b[2] + pxor @b[3], @b[6] + + pxor @b[0], @b[3] + pxor @b[6], @b[5] +___ +} + +sub Mul_GF4 { +#;************************************************************* +#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) * +#;************************************************************* +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + movdqa $y0, $t0 + pxor $y1, $t0 + pand $x0, $t0 + pxor $x1, $x0 + pand $y0, $x1 + pand $y1, $x0 + pxor $x1, $x0 + pxor $t0, $x1 +___ +} + +sub Mul_GF4_N { # not used, see next subroutine +# multiply and scale by N +my ($x0,$x1,$y0,$y1,$t0)=@_; +$code.=<<___; + movdqa $y0, $t0 + pxor $y1, $t0 + pand $x0, $t0 + pxor $x1, $x0 + pand $y0, $x1 + pand $y1, $x0 + pxor $x0, $x1 + pxor $t0, $x0 +___ +} + +sub Mul_GF4_N_GF4 { +# interleaved Mul_GF4_N and Mul_GF4 +my ($x0,$x1,$y0,$y1,$t0, + $x2,$x3,$y2,$y3,$t1)=@_; +$code.=<<___; + movdqa $y0, $t0 + movdqa $y2, $t1 + pxor $y1, $t0 + pxor $y3, $t1 + pand $x0, $t0 + pand $x2, $t1 + pxor $x1, $x0 + pxor $x3, $x2 + pand $y0, $x1 + pand $y2, $x3 + pand $y1, $x0 + pand $y3, $x2 + pxor $x0, $x1 + pxor $x3, $x2 + pxor $t0, $x0 + pxor $t1, $x3 +___ +} +sub Mul_GF16_2 { +my @x=@_[0..7]; +my @y=@_[8..11]; +my @t=@_[12..15]; +$code.=<<___; + movdqa @x[0], @t[0] + movdqa @x[1], @t[1] +___ + &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2]); +$code.=<<___; + pxor @x[2], @t[0] + pxor @x[3], @t[1] + pxor @y[2], @y[0] + pxor @y[3], @y[1] +___ + Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[2], @x[3], @y[2], @y[3], @t[2]); +$code.=<<___; + pxor @t[0], @x[0] + pxor @t[0], @x[2] + pxor @t[1], @x[1] + pxor @t[1], @x[3] + + movdqa @x[4], @t[0] + movdqa @x[5], @t[1] + pxor @x[6], @t[0] + pxor @x[7], @t[1] +___ + &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3], + @x[6], @x[7], @y[2], @y[3], @t[2]); +$code.=<<___; + pxor @y[2], @y[0] + pxor @y[3], @y[1] +___ + &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[3]); +$code.=<<___; + pxor @t[0], @x[4] + pxor @t[0], @x[6] + pxor @t[1], @x[5] + pxor @t[1], @x[7] +___ +} +sub Inv_GF256 { +#;******************************************************************** +#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) * +#;******************************************************************** +my @x=@_[0..7]; +my @t=@_[8..11]; +my @s=@_[12..15]; +# direct optimizations from hardware +$code.=<<___; + movdqa @x[4], @t[3] + movdqa @x[5], @t[2] + movdqa @x[1], @t[1] + movdqa @x[7], @s[1] + movdqa @x[0], @s[0] + + pxor @x[6], @t[3] + pxor @x[7], @t[2] + pxor @x[3], @t[1] + movdqa @t[3], @s[2] + pxor @x[6], @s[1] + movdqa @t[2], @t[0] + pxor @x[2], @s[0] + movdqa @t[3], @s[3] + + por @t[1], @t[2] + por @s[0], @t[3] + pxor @t[0], @s[3] + pand @s[0], @s[2] + pxor @t[1], @s[0] + pand @t[1], @t[0] + pand @s[0], @s[3] + movdqa @x[3], @s[0] + pxor @x[2], @s[0] + pand @s[0], @s[1] + pxor @s[1], @t[3] + pxor @s[1], @t[2] + movdqa @x[4], @s[1] + movdqa @x[1], @s[0] + pxor @x[5], @s[1] + pxor @x[0], @s[0] + movdqa @s[1], @t[1] + pand @s[0], @s[1] + por @s[0], @t[1] + pxor @s[1], @t[0] + pxor @s[3], @t[3] + pxor @s[2], @t[2] + pxor @s[3], @t[1] + movdqa @x[7], @s[0] + pxor @s[2], @t[0] + movdqa @x[6], @s[1] + pxor @s[2], @t[1] + movdqa @x[5], @s[2] + pand @x[3], @s[0] + movdqa @x[4], @s[3] + pand @x[2], @s[1] + pand @x[1], @s[2] + por @x[0], @s[3] + pxor @s[0], @t[3] + pxor @s[1], @t[2] + pxor @s[2], @t[1] + pxor @s[3], @t[0] + + #Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3 + + # new smaller inversion + + movdqa @t[3], @s[0] + pand @t[1], @t[3] + pxor @t[2], @s[0] + + movdqa @t[0], @s[2] + movdqa @s[0], @s[3] + pxor @t[3], @s[2] + pand @s[2], @s[3] + + movdqa @t[1], @s[1] + pxor @t[2], @s[3] + pxor @t[0], @s[1] + + pxor @t[2], @t[3] + + pand @t[3], @s[1] + + movdqa @s[2], @t[2] + pxor @t[0], @s[1] + + pxor @s[1], @t[2] + pxor @s[1], @t[1] + + pand @t[0], @t[2] + + pxor @t[2], @s[2] + pxor @t[2], @t[1] + + pand @s[3], @s[2] + + pxor @s[0], @s[2] +___ +# output in s3, s2, s1, t1 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3 + +# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3 + &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]); + +### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb +} + +# AES linear components + +sub ShiftRows { +my @x=@_[0..7]; +my $mask=pop; +$code.=<<___; + pxor 0x00($key),@x[0] + pxor 0x10($key),@x[1] + pxor 0x20($key),@x[2] + pxor 0x30($key),@x[3] + pshufb $mask,@x[0] + pshufb $mask,@x[1] + pxor 0x40($key),@x[4] + pxor 0x50($key),@x[5] + pshufb $mask,@x[2] + pshufb $mask,@x[3] + pxor 0x60($key),@x[6] + pxor 0x70($key),@x[7] + pshufb $mask,@x[4] + pshufb $mask,@x[5] + pshufb $mask,@x[6] + pshufb $mask,@x[7] + lea 0x80($key),$key +___ +} + +sub MixColumns { +# modified to emit output in order suitable for feeding back to aesenc[last] +my @x=@_[0..7]; +my @t=@_[8..15]; +my $inv=@_[16]; # optional +$code.=<<___; + pshufd \$0x93, @x[0], @t[0] # x0 <<< 32 + pshufd \$0x93, @x[1], @t[1] + pxor @t[0], @x[0] # x0 ^ (x0 <<< 32) + pshufd \$0x93, @x[2], @t[2] + pxor @t[1], @x[1] + pshufd \$0x93, @x[3], @t[3] + pxor @t[2], @x[2] + pshufd \$0x93, @x[4], @t[4] + pxor @t[3], @x[3] + pshufd \$0x93, @x[5], @t[5] + pxor @t[4], @x[4] + pshufd \$0x93, @x[6], @t[6] + pxor @t[5], @x[5] + pshufd \$0x93, @x[7], @t[7] + pxor @t[6], @x[6] + pxor @t[7], @x[7] + + pxor @x[0], @t[1] + pxor @x[7], @t[0] + pxor @x[7], @t[1] + pshufd \$0x4E, @x[0], @x[0] # (x0 ^ (x0 <<< 32)) <<< 64) + pxor @x[1], @t[2] + pshufd \$0x4E, @x[1], @x[1] + pxor @x[4], @t[5] + pxor @t[0], @x[0] + pxor @x[5], @t[6] + pxor @t[1], @x[1] + pxor @x[3], @t[4] + pshufd \$0x4E, @x[4], @t[0] + pxor @x[6], @t[7] + pshufd \$0x4E, @x[5], @t[1] + pxor @x[2], @t[3] + pshufd \$0x4E, @x[3], @x[4] + pxor @x[7], @t[3] + pshufd \$0x4E, @x[7], @x[5] + pxor @x[7], @t[4] + pshufd \$0x4E, @x[6], @x[3] + pxor @t[4], @t[0] + pshufd \$0x4E, @x[2], @x[6] + pxor @t[5], @t[1] +___ +$code.=<<___ if (!$inv); + pxor @t[3], @x[4] + pxor @t[7], @x[5] + pxor @t[6], @x[3] + movdqa @t[0], @x[2] + pxor @t[2], @x[6] + movdqa @t[1], @x[7] +___ +$code.=<<___ if ($inv); + pxor @x[4], @t[3] + pxor @t[7], @x[5] + pxor @x[3], @t[6] + movdqa @t[0], @x[3] + pxor @t[2], @x[6] + movdqa @t[6], @x[2] + movdqa @t[1], @x[7] + movdqa @x[6], @x[4] + movdqa @t[3], @x[6] +___ +} + +sub InvMixColumns_orig { +my @x=@_[0..7]; +my @t=@_[8..15]; + +$code.=<<___; + # multiplication by 0x0e + pshufd \$0x93, @x[7], @t[7] + movdqa @x[2], @t[2] + pxor @x[5], @x[7] # 7 5 + pxor @x[5], @x[2] # 2 5 + pshufd \$0x93, @x[0], @t[0] + movdqa @x[5], @t[5] + pxor @x[0], @x[5] # 5 0 [1] + pxor @x[1], @x[0] # 0 1 + pshufd \$0x93, @x[1], @t[1] + pxor @x[2], @x[1] # 1 25 + pxor @x[6], @x[0] # 01 6 [2] + pxor @x[3], @x[1] # 125 3 [4] + pshufd \$0x93, @x[3], @t[3] + pxor @x[0], @x[2] # 25 016 [3] + pxor @x[7], @x[3] # 3 75 + pxor @x[6], @x[7] # 75 6 [0] + pshufd \$0x93, @x[6], @t[6] + movdqa @x[4], @t[4] + pxor @x[4], @x[6] # 6 4 + pxor @x[3], @x[4] # 4 375 [6] + pxor @x[7], @x[3] # 375 756=36 + pxor @t[5], @x[6] # 64 5 [7] + pxor @t[2], @x[3] # 36 2 + pxor @t[4], @x[3] # 362 4 [5] + pshufd \$0x93, @t[5], @t[5] +___ + my @y = @x[7,5,0,2,1,3,4,6]; +$code.=<<___; + # multiplication by 0x0b + pxor @y[0], @y[1] + pxor @t[0], @y[0] + pxor @t[1], @y[1] + pshufd \$0x93, @t[2], @t[2] + pxor @t[5], @y[0] + pxor @t[6], @y[1] + pxor @t[7], @y[0] + pshufd \$0x93, @t[4], @t[4] + pxor @t[6], @t[7] # clobber t[7] + pxor @y[0], @y[1] + + pxor @t[0], @y[3] + pshufd \$0x93, @t[0], @t[0] + pxor @t[1], @y[2] + pxor @t[1], @y[4] + pxor @t[2], @y[2] + pshufd \$0x93, @t[1], @t[1] + pxor @t[2], @y[3] + pxor @t[2], @y[5] + pxor @t[7], @y[2] + pshufd \$0x93, @t[2], @t[2] + pxor @t[3], @y[3] + pxor @t[3], @y[6] + pxor @t[3], @y[4] + pshufd \$0x93, @t[3], @t[3] + pxor @t[4], @y[7] + pxor @t[4], @y[5] + pxor @t[7], @y[7] + pxor @t[5], @y[3] + pxor @t[4], @y[4] + pxor @t[5], @t[7] # clobber t[7] even more + + pxor @t[7], @y[5] + pshufd \$0x93, @t[4], @t[4] + pxor @t[7], @y[6] + pxor @t[7], @y[4] + + pxor @t[5], @t[7] + pshufd \$0x93, @t[5], @t[5] + pxor @t[6], @t[7] # restore t[7] + + # multiplication by 0x0d + pxor @y[7], @y[4] + pxor @t[4], @y[7] + pshufd \$0x93, @t[6], @t[6] + pxor @t[0], @y[2] + pxor @t[5], @y[7] + pxor @t[2], @y[2] + pshufd \$0x93, @t[7], @t[7] + + pxor @y[1], @y[3] + pxor @t[1], @y[1] + pxor @t[0], @y[0] + pxor @t[0], @y[3] + pxor @t[5], @y[1] + pxor @t[5], @y[0] + pxor @t[7], @y[1] + pshufd \$0x93, @t[0], @t[0] + pxor @t[6], @y[0] + pxor @y[1], @y[3] + pxor @t[1], @y[4] + pshufd \$0x93, @t[1], @t[1] + + pxor @t[7], @y[7] + pxor @t[2], @y[4] + pxor @t[2], @y[5] + pshufd \$0x93, @t[2], @t[2] + pxor @t[6], @y[2] + pxor @t[3], @t[6] # clobber t[6] + pxor @y[7], @y[4] + pxor @t[6], @y[3] + + pxor @t[6], @y[6] + pxor @t[5], @y[5] + pxor @t[4], @y[6] + pshufd \$0x93, @t[4], @t[4] + pxor @t[6], @y[5] + pxor @t[7], @y[6] + pxor @t[3], @t[6] # restore t[6] + + pshufd \$0x93, @t[5], @t[5] + pshufd \$0x93, @t[6], @t[6] + pshufd \$0x93, @t[7], @t[7] + pshufd \$0x93, @t[3], @t[3] + + # multiplication by 0x09 + pxor @y[1], @y[4] + pxor @y[1], @t[1] # t[1]=y[1] + pxor @t[5], @t[0] # clobber t[0] + pxor @t[5], @t[1] + pxor @t[0], @y[3] + pxor @y[0], @t[0] # t[0]=y[0] + pxor @t[6], @t[1] + pxor @t[7], @t[6] # clobber t[6] + pxor @t[1], @y[4] + pxor @t[4], @y[7] + pxor @y[4], @t[4] # t[4]=y[4] + pxor @t[3], @y[6] + pxor @y[3], @t[3] # t[3]=y[3] + pxor @t[2], @y[5] + pxor @y[2], @t[2] # t[2]=y[2] + pxor @t[7], @t[3] + pxor @y[5], @t[5] # t[5]=y[5] + pxor @t[6], @t[2] + pxor @t[6], @t[5] + pxor @y[6], @t[6] # t[6]=y[6] + pxor @y[7], @t[7] # t[7]=y[7] + + movdqa @t[0],@XMM[0] + movdqa @t[1],@XMM[1] + movdqa @t[2],@XMM[2] + movdqa @t[3],@XMM[3] + movdqa @t[4],@XMM[4] + movdqa @t[5],@XMM[5] + movdqa @t[6],@XMM[6] + movdqa @t[7],@XMM[7] +___ +} + +sub InvMixColumns { +my @x=@_[0..7]; +my @t=@_[8..15]; + +# Thanks to Jussi Kivilinna for providing pointer to +# +# | 0e 0b 0d 09 | | 02 03 01 01 | | 05 00 04 00 | +# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 | +# | 0d 09 0e 0b | | 01 01 02 03 | | 04 00 05 00 | +# | 0b 0d 09 0e | | 03 01 01 02 | | 00 04 00 05 | + +$code.=<<___; + # multiplication by 0x05-0x00-0x04-0x00 + pshufd \$0x4E, @x[0], @t[0] + pshufd \$0x4E, @x[6], @t[6] + pxor @x[0], @t[0] + pshufd \$0x4E, @x[7], @t[7] + pxor @x[6], @t[6] + pshufd \$0x4E, @x[1], @t[1] + pxor @x[7], @t[7] + pshufd \$0x4E, @x[2], @t[2] + pxor @x[1], @t[1] + pshufd \$0x4E, @x[3], @t[3] + pxor @x[2], @t[2] + pxor @t[6], @x[0] + pxor @t[6], @x[1] + pshufd \$0x4E, @x[4], @t[4] + pxor @x[3], @t[3] + pxor @t[0], @x[2] + pxor @t[1], @x[3] + pshufd \$0x4E, @x[5], @t[5] + pxor @x[4], @t[4] + pxor @t[7], @x[1] + pxor @t[2], @x[4] + pxor @x[5], @t[5] + + pxor @t[7], @x[2] + pxor @t[6], @x[3] + pxor @t[6], @x[4] + pxor @t[3], @x[5] + pxor @t[4], @x[6] + pxor @t[7], @x[4] + pxor @t[7], @x[5] + pxor @t[5], @x[7] +___ + &MixColumns (@x,@t,1); # flipped 2<->3 and 4<->6 +} + +sub aesenc { # not used +my @b=@_[0..7]; +my @t=@_[8..15]; +$code.=<<___; + movdqa 0x30($const),@t[0] # .LSR +___ + &ShiftRows (@b,@t[0]); + &Sbox (@b,@t); + &MixColumns (@b[0,1,4,6,3,7,2,5],@t); +} + +sub aesenclast { # not used +my @b=@_[0..7]; +my @t=@_[8..15]; +$code.=<<___; + movdqa 0x40($const),@t[0] # .LSRM0 +___ + &ShiftRows (@b,@t[0]); + &Sbox (@b,@t); +$code.=<<___ + pxor 0x00($key),@b[0] + pxor 0x10($key),@b[1] + pxor 0x20($key),@b[4] + pxor 0x30($key),@b[6] + pxor 0x40($key),@b[3] + pxor 0x50($key),@b[7] + pxor 0x60($key),@b[2] + pxor 0x70($key),@b[5] +___ +} + +sub swapmove { +my ($a,$b,$n,$mask,$t)=@_; +$code.=<<___; + movdqa $b,$t + psrlq \$$n,$b + pxor $a,$b + pand $mask,$b + pxor $b,$a + psllq \$$n,$b + pxor $t,$b +___ +} +sub swapmove2x { +my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_; +$code.=<<___; + movdqa $b0,$t0 + psrlq \$$n,$b0 + movdqa $b1,$t1 + psrlq \$$n,$b1 + pxor $a0,$b0 + pxor $a1,$b1 + pand $mask,$b0 + pand $mask,$b1 + pxor $b0,$a0 + psllq \$$n,$b0 + pxor $b1,$a1 + psllq \$$n,$b1 + pxor $t0,$b0 + pxor $t1,$b1 +___ +} + +sub bitslice { +my @x=reverse(@_[0..7]); +my ($t0,$t1,$t2,$t3)=@_[8..11]; +$code.=<<___; + movdqa 0x00($const),$t0 # .LBS0 + movdqa 0x10($const),$t1 # .LBS1 +___ + &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3); + &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); +$code.=<<___; + movdqa 0x20($const),$t0 # .LBS2 +___ + &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3); + &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + + &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3); + &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3); +} + +$code.=<<___; +.text + +.extern asm_AES_encrypt +.extern asm_AES_decrypt + +.type _bsaes_encrypt8,\@abi-omnipotent +.align 64 +_bsaes_encrypt8: +.cfi_startproc + lea .LBS0(%rip), $const # constants table + + movdqa ($key), @XMM[9] # round 0 key + lea 0x10($key), $key + movdqa 0x50($const), @XMM[8] # .LM0SR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] +_bsaes_encrypt8_bitslice: +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + dec $rounds + jmp .Lenc_sbox +.align 16 +.Lenc_loop: +___ + &ShiftRows (@XMM[0..7, 8]); +$code.=".Lenc_sbox:\n"; + &Sbox (@XMM[0..7, 8..15]); +$code.=<<___; + dec $rounds + jl .Lenc_done +___ + &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]); +$code.=<<___; + movdqa 0x30($const), @XMM[8] # .LSR + jnz .Lenc_loop + movdqa 0x40($const), @XMM[8] # .LSRM0 + jmp .Lenc_loop +.align 16 +.Lenc_done: +___ + # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb + &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]); +$code.=<<___; + movdqa ($key), @XMM[8] # last round key + pxor @XMM[8], @XMM[4] + pxor @XMM[8], @XMM[6] + pxor @XMM[8], @XMM[3] + pxor @XMM[8], @XMM[7] + pxor @XMM[8], @XMM[2] + pxor @XMM[8], @XMM[5] + pxor @XMM[8], @XMM[0] + pxor @XMM[8], @XMM[1] + ret +.cfi_endproc +.size _bsaes_encrypt8,.-_bsaes_encrypt8 + +.type _bsaes_decrypt8,\@abi-omnipotent +.align 64 +_bsaes_decrypt8: +.cfi_startproc + lea .LBS0(%rip), $const # constants table + + movdqa ($key), @XMM[9] # round 0 key + lea 0x10($key), $key + movdqa -0x30($const), @XMM[8] # .LM0ISR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] +___ + &bitslice (@XMM[0..7, 8..11]); +$code.=<<___; + dec $rounds + jmp .Ldec_sbox +.align 16 +.Ldec_loop: +___ + &ShiftRows (@XMM[0..7, 8]); +$code.=".Ldec_sbox:\n"; + &InvSbox (@XMM[0..7, 8..15]); +$code.=<<___; + dec $rounds + jl .Ldec_done +___ + &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]); +$code.=<<___; + movdqa -0x10($const), @XMM[8] # .LISR + jnz .Ldec_loop + movdqa -0x20($const), @XMM[8] # .LISRM0 + jmp .Ldec_loop +.align 16 +.Ldec_done: +___ + &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]); +$code.=<<___; + movdqa ($key), @XMM[8] # last round key + pxor @XMM[8], @XMM[6] + pxor @XMM[8], @XMM[4] + pxor @XMM[8], @XMM[2] + pxor @XMM[8], @XMM[7] + pxor @XMM[8], @XMM[3] + pxor @XMM[8], @XMM[5] + pxor @XMM[8], @XMM[0] + pxor @XMM[8], @XMM[1] + ret +.cfi_endproc +.size _bsaes_decrypt8,.-_bsaes_decrypt8 +___ +} +{ +my ($out,$inp,$rounds,$const)=("%rax","%rcx","%r10d","%r11"); + +sub bitslice_key { +my @x=reverse(@_[0..7]); +my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12]; + + &swapmove (@x[0,1],1,$bs0,$t2,$t3); +$code.=<<___; + #&swapmove(@x[2,3],1,$t0,$t2,$t3); + movdqa @x[0], @x[2] + movdqa @x[1], @x[3] +___ + #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3); + + &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3); +$code.=<<___; + #&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3); + movdqa @x[0], @x[4] + movdqa @x[2], @x[6] + movdqa @x[1], @x[5] + movdqa @x[3], @x[7] +___ + &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3); + &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3); +} + +$code.=<<___; +.type _bsaes_key_convert,\@abi-omnipotent +.align 16 +_bsaes_key_convert: +.cfi_startproc + lea .Lmasks(%rip), $const + movdqu ($inp), %xmm7 # load round 0 key + lea 0x10($inp), $inp + movdqa 0x00($const), %xmm0 # 0x01... + movdqa 0x10($const), %xmm1 # 0x02... + movdqa 0x20($const), %xmm2 # 0x04... + movdqa 0x30($const), %xmm3 # 0x08... + movdqa 0x40($const), %xmm4 # .LM0 + pcmpeqd %xmm5, %xmm5 # .LNOT + + movdqu ($inp), %xmm6 # load round 1 key + movdqa %xmm7, ($out) # save round 0 key + lea 0x10($out), $out + dec $rounds + jmp .Lkey_loop +.align 16 +.Lkey_loop: + pshufb %xmm4, %xmm6 # .LM0 + + movdqa %xmm0, %xmm8 + movdqa %xmm1, %xmm9 + + pand %xmm6, %xmm8 + pand %xmm6, %xmm9 + movdqa %xmm2, %xmm10 + pcmpeqb %xmm0, %xmm8 + psllq \$4, %xmm0 # 0x10... + movdqa %xmm3, %xmm11 + pcmpeqb %xmm1, %xmm9 + psllq \$4, %xmm1 # 0x20... + + pand %xmm6, %xmm10 + pand %xmm6, %xmm11 + movdqa %xmm0, %xmm12 + pcmpeqb %xmm2, %xmm10 + psllq \$4, %xmm2 # 0x40... + movdqa %xmm1, %xmm13 + pcmpeqb %xmm3, %xmm11 + psllq \$4, %xmm3 # 0x80... + + movdqa %xmm2, %xmm14 + movdqa %xmm3, %xmm15 + pxor %xmm5, %xmm8 # "pnot" + pxor %xmm5, %xmm9 + + pand %xmm6, %xmm12 + pand %xmm6, %xmm13 + movdqa %xmm8, 0x00($out) # write bit-sliced round key + pcmpeqb %xmm0, %xmm12 + psrlq \$4, %xmm0 # 0x01... + movdqa %xmm9, 0x10($out) + pcmpeqb %xmm1, %xmm13 + psrlq \$4, %xmm1 # 0x02... + lea 0x10($inp), $inp + + pand %xmm6, %xmm14 + pand %xmm6, %xmm15 + movdqa %xmm10, 0x20($out) + pcmpeqb %xmm2, %xmm14 + psrlq \$4, %xmm2 # 0x04... + movdqa %xmm11, 0x30($out) + pcmpeqb %xmm3, %xmm15 + psrlq \$4, %xmm3 # 0x08... + movdqu ($inp), %xmm6 # load next round key + + pxor %xmm5, %xmm13 # "pnot" + pxor %xmm5, %xmm14 + movdqa %xmm12, 0x40($out) + movdqa %xmm13, 0x50($out) + movdqa %xmm14, 0x60($out) + movdqa %xmm15, 0x70($out) + lea 0x80($out),$out + dec $rounds + jnz .Lkey_loop + + movdqa 0x50($const), %xmm7 # .L63 + #movdqa %xmm6, ($out) # don't save last round key + ret +.cfi_endproc +.size _bsaes_key_convert,.-_bsaes_key_convert +___ +} + +if (0 && !$win64) { # following four functions are unsupported interface + # used for benchmarking... +$code.=<<___; +.globl bsaes_enc_key_convert +.type bsaes_enc_key_convert,\@function,2 +.align 16 +bsaes_enc_key_convert: + mov 240($inp),%r10d # pass rounds + mov $inp,%rcx # pass key + mov $out,%rax # pass key schedule + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + ret +.size bsaes_enc_key_convert,.-bsaes_enc_key_convert + +.globl bsaes_encrypt_128 +.type bsaes_encrypt_128,\@function,4 +.align 16 +bsaes_encrypt_128: +.Lenc128_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + movdqu 0x60($inp), @XMM[6] + movdqu 0x70($inp), @XMM[7] + mov $key, %rax # pass the $key + lea 0x80($inp), $inp + mov \$10,%r10d + + call _bsaes_encrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$0x80,$len + ja .Lenc128_loop + ret +.size bsaes_encrypt_128,.-bsaes_encrypt_128 + +.globl bsaes_dec_key_convert +.type bsaes_dec_key_convert,\@function,2 +.align 16 +bsaes_dec_key_convert: + mov 240($inp),%r10d # pass rounds + mov $inp,%rcx # pass key + mov $out,%rax # pass key schedule + call _bsaes_key_convert + pxor ($out),%xmm7 # fix up round 0 key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,($out) + ret +.size bsaes_dec_key_convert,.-bsaes_dec_key_convert + +.globl bsaes_decrypt_128 +.type bsaes_decrypt_128,\@function,4 +.align 16 +bsaes_decrypt_128: +.Ldec128_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + movdqu 0x60($inp), @XMM[6] + movdqu 0x70($inp), @XMM[7] + mov $key, %rax # pass the $key + lea 0x80($inp), $inp + mov \$10,%r10d + + call _bsaes_decrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$0x80,$len + ja .Ldec128_loop + ret +.size bsaes_decrypt_128,.-bsaes_decrypt_128 +___ +} +{ +###################################################################### +# +# OpenSSL interface +# +my ($arg1,$arg2,$arg3,$arg4,$arg5,$arg6)=$win64 ? ("%rcx","%rdx","%r8","%r9","%r10","%r11d") + : ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d"); +my ($inp,$out,$len,$key)=("%r12","%r13","%r14","%r15"); + +if ($ecb) { +$code.=<<___; +.globl bsaes_ecb_encrypt_blocks +.type bsaes_ecb_encrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ecb_encrypt_blocks: +.cfi_startproc + mov %rsp, %rax +.Lecb_enc_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp),%rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lecb_enc_body: +___ +$code.=<<___; + mov %rsp,%rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov 240($arg4),%eax # rounds + mov $arg1,$inp # backup arguments + mov $arg2,$out + mov $arg3,$len + mov $arg4,$key + cmp \$8,$arg3 + jb .Lecb_enc_short + + mov %eax,%ebx # backup rounds + shl \$7,%rax # 128 bytes per inner round key + sub \$`128-32`,%rax # size of bit-sliced key schedule + sub %rax,%rsp + mov %rsp,%rax # pass key schedule + mov $key,%rcx # pass key + mov %ebx,%r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + + sub \$8,$len +.Lecb_enc_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %ebx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + lea 0x80($inp), $inp + + call _bsaes_encrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lecb_enc_loop + + add \$8,$len + jz .Lecb_enc_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %ebx,%r10d # pass rounds + cmp \$2,$len + jb .Lecb_enc_one + movdqu 0x10($inp), @XMM[1] + je .Lecb_enc_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lecb_enc_three + movdqu 0x30($inp), @XMM[3] + je .Lecb_enc_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lecb_enc_five + movdqu 0x50($inp), @XMM[5] + je .Lecb_enc_six + movdqu 0x60($inp), @XMM[6] + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_six: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_five: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_four: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_three: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_two: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_one: + call _bsaes_encrypt8 + movdqu @XMM[0], 0x00($out) # write output + jmp .Lecb_enc_done +.align 16 +.Lecb_enc_short: + lea ($inp), $arg1 + lea ($out), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt + lea 16($inp), $inp + lea 16($out), $out + dec $len + jnz .Lecb_enc_short + +.Lecb_enc_done: + lea (%rsp),%rax + pxor %xmm0, %xmm0 +.Lecb_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + jb .Lecb_enc_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lecb_enc_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lecb_enc_epilogue: + ret +.cfi_endproc +.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks + +.globl bsaes_ecb_decrypt_blocks +.type bsaes_ecb_decrypt_blocks,\@abi-omnipotent +.align 16 +bsaes_ecb_decrypt_blocks: +.cfi_startproc + mov %rsp, %rax +.Lecb_dec_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp),%rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lecb_dec_body: +___ +$code.=<<___; + mov %rsp,%rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov 240($arg4),%eax # rounds + mov $arg1,$inp # backup arguments + mov $arg2,$out + mov $arg3,$len + mov $arg4,$key + cmp \$8,$arg3 + jb .Lecb_dec_short + + mov %eax,%ebx # backup rounds + shl \$7,%rax # 128 bytes per inner round key + sub \$`128-32`,%rax # size of bit-sliced key schedule + sub %rax,%rsp + mov %rsp,%rax # pass key schedule + mov $key,%rcx # pass key + mov %ebx,%r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp),%xmm7 # fix up 0 round key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,(%rsp) + + sub \$8,$len +.Lecb_dec_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %ebx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + lea 0x80($inp), $inp + + call _bsaes_decrypt8 + + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lecb_dec_loop + + add \$8,$len + jz .Lecb_dec_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %ebx,%r10d # pass rounds + cmp \$2,$len + jb .Lecb_dec_one + movdqu 0x10($inp), @XMM[1] + je .Lecb_dec_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lecb_dec_three + movdqu 0x30($inp), @XMM[3] + je .Lecb_dec_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lecb_dec_five + movdqu 0x50($inp), @XMM[5] + je .Lecb_dec_six + movdqu 0x60($inp), @XMM[6] + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_six: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_five: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_four: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_three: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_two: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_one: + call _bsaes_decrypt8 + movdqu @XMM[0], 0x00($out) # write output + jmp .Lecb_dec_done +.align 16 +.Lecb_dec_short: + lea ($inp), $arg1 + lea ($out), $arg2 + lea ($key), $arg3 + call asm_AES_decrypt + lea 16($inp), $inp + lea 16($out), $out + dec $len + jnz .Lecb_dec_short + +.Lecb_dec_done: + lea (%rsp),%rax + pxor %xmm0, %xmm0 +.Lecb_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + jb .Lecb_dec_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lecb_dec_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lecb_dec_epilogue: + ret +.cfi_endproc +.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks +___ +} +$code.=<<___; +.extern asm_AES_cbc_encrypt +.globl ossl_bsaes_cbc_encrypt +.type ossl_bsaes_cbc_encrypt,\@abi-omnipotent +.align 16 +ossl_bsaes_cbc_encrypt: +.cfi_startproc + endbranch +___ +$code.=<<___ if ($win64); + mov 48(%rsp),$arg6 # pull direction flag +___ +$code.=<<___; + cmp \$0,$arg6 + jne asm_AES_cbc_encrypt + cmp \$128,$arg3 + jb asm_AES_cbc_encrypt + + mov %rsp, %rax +.Lcbc_dec_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lcbc_dec_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov 240($arg4), %eax # rounds + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + mov $arg5, %rbx + shr \$4, $len # bytes to blocks + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp),%xmm7 # fix up 0 round key + movdqa %xmm6,(%rax) # save last round key + movdqa %xmm7,(%rsp) + + movdqu (%rbx), @XMM[15] # load IV + sub \$8,$len +.Lcbc_dec_loop: + movdqu 0x00($inp), @XMM[0] # load input + movdqu 0x10($inp), @XMM[1] + movdqu 0x20($inp), @XMM[2] + movdqu 0x30($inp), @XMM[3] + movdqu 0x40($inp), @XMM[4] + movdqu 0x50($inp), @XMM[5] + mov %rsp, %rax # pass key schedule + movdqu 0x60($inp), @XMM[6] + mov %edx,%r10d # pass rounds + movdqu 0x70($inp), @XMM[7] + movdqa @XMM[15], 0x20(%rbp) # put aside IV + + call _bsaes_decrypt8 + + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[13] + pxor @XMM[12], @XMM[7] + movdqu 0x60($inp), @XMM[14] + pxor @XMM[13], @XMM[3] + movdqu 0x70($inp), @XMM[15] # IV + pxor @XMM[14], @XMM[5] + movdqu @XMM[0], 0x00($out) # write output + lea 0x80($inp), $inp + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + sub \$8,$len + jnc .Lcbc_dec_loop + + add \$8,$len + jz .Lcbc_dec_done + + movdqu 0x00($inp), @XMM[0] # load input + mov %rsp, %rax # pass key schedule + mov %edx, %r10d # pass rounds + cmp \$2,$len + jb .Lcbc_dec_one + movdqu 0x10($inp), @XMM[1] + je .Lcbc_dec_two + movdqu 0x20($inp), @XMM[2] + cmp \$4,$len + jb .Lcbc_dec_three + movdqu 0x30($inp), @XMM[3] + je .Lcbc_dec_four + movdqu 0x40($inp), @XMM[4] + cmp \$6,$len + jb .Lcbc_dec_five + movdqu 0x50($inp), @XMM[5] + je .Lcbc_dec_six + movdqu 0x60($inp), @XMM[6] + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[13] + pxor @XMM[12], @XMM[7] + movdqu 0x60($inp), @XMM[15] # IV + pxor @XMM[13], @XMM[3] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_six: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[12] + pxor @XMM[11], @XMM[2] + movdqu 0x50($inp), @XMM[15] # IV + pxor @XMM[12], @XMM[7] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_five: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[11] + pxor @XMM[10], @XMM[4] + movdqu 0x40($inp), @XMM[15] # IV + pxor @XMM[11], @XMM[2] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_four: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[10] + pxor @XMM[9], @XMM[6] + movdqu 0x30($inp), @XMM[15] # IV + pxor @XMM[10], @XMM[4] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_three: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[9] + pxor @XMM[8], @XMM[1] + movdqu 0x20($inp), @XMM[15] # IV + pxor @XMM[9], @XMM[6] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_two: + movdqa @XMM[15], 0x20(%rbp) # put aside IV + call _bsaes_decrypt8 + pxor 0x20(%rbp), @XMM[0] # ^= IV + movdqu 0x00($inp), @XMM[8] # re-load input + movdqu 0x10($inp), @XMM[15] # IV + pxor @XMM[8], @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + jmp .Lcbc_dec_done +.align 16 +.Lcbc_dec_one: + lea ($inp), $arg1 + lea 0x20(%rbp), $arg2 # buffer output + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[15] # ^= IV + movdqu @XMM[15], ($out) # write output + movdqa @XMM[0], @XMM[15] # IV + +.Lcbc_dec_done: + movdqu @XMM[15], (%rbx) # return IV + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lcbc_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lcbc_dec_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lcbc_dec_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lcbc_dec_epilogue: + ret +.cfi_endproc +.size ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt + +.globl ossl_bsaes_ctr32_encrypt_blocks +.type ossl_bsaes_ctr32_encrypt_blocks,\@abi-omnipotent +.align 16 +ossl_bsaes_ctr32_encrypt_blocks: +.cfi_startproc + endbranch + mov %rsp, %rax +.Lctr_enc_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lctr_enc_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp +.cfi_def_cfa_register %rbp + movdqu ($arg5), %xmm0 # load counter + mov 240($arg4), %eax # rounds + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + movdqa %xmm0, 0x20(%rbp) # copy counter + cmp \$8, $arg3 + jb .Lctr_enc_short + + mov %eax, %ebx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %ebx, %r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6,%xmm7 # fix up last round key + movdqa %xmm7,(%rax) # save last round key + + movdqa (%rsp), @XMM[9] # load round0 key + lea .LADD1(%rip), %r11 + movdqa 0x20(%rbp), @XMM[0] # counter copy + movdqa -0x20(%r11), @XMM[8] # .LSWPUP + pshufb @XMM[8], @XMM[9] # byte swap upper part + pshufb @XMM[8], @XMM[0] + movdqa @XMM[9], (%rsp) # save adjusted round0 key + jmp .Lctr_enc_loop +.align 16 +.Lctr_enc_loop: + movdqa @XMM[0], 0x20(%rbp) # save counter + movdqa @XMM[0], @XMM[1] # prepare 8 counter values + movdqa @XMM[0], @XMM[2] + paddd 0x00(%r11), @XMM[1] # .LADD1 + movdqa @XMM[0], @XMM[3] + paddd 0x10(%r11), @XMM[2] # .LADD2 + movdqa @XMM[0], @XMM[4] + paddd 0x20(%r11), @XMM[3] # .LADD3 + movdqa @XMM[0], @XMM[5] + paddd 0x30(%r11), @XMM[4] # .LADD4 + movdqa @XMM[0], @XMM[6] + paddd 0x40(%r11), @XMM[5] # .LADD5 + movdqa @XMM[0], @XMM[7] + paddd 0x50(%r11), @XMM[6] # .LADD6 + paddd 0x60(%r11), @XMM[7] # .LADD7 + + # Borrow prologue from _bsaes_encrypt8 to use the opportunity + # to flip byte order in 32-bit counter + movdqa (%rsp), @XMM[9] # round 0 key + lea 0x10(%rsp), %rax # pass key schedule + movdqa -0x10(%r11), @XMM[8] # .LSWPUPM0SR + pxor @XMM[9], @XMM[0] # xor with round0 key + pxor @XMM[9], @XMM[1] + pxor @XMM[9], @XMM[2] + pxor @XMM[9], @XMM[3] + pshufb @XMM[8], @XMM[0] + pshufb @XMM[8], @XMM[1] + pxor @XMM[9], @XMM[4] + pxor @XMM[9], @XMM[5] + pshufb @XMM[8], @XMM[2] + pshufb @XMM[8], @XMM[3] + pxor @XMM[9], @XMM[6] + pxor @XMM[9], @XMM[7] + pshufb @XMM[8], @XMM[4] + pshufb @XMM[8], @XMM[5] + pshufb @XMM[8], @XMM[6] + pshufb @XMM[8], @XMM[7] + lea .LBS0(%rip), %r11 # constants table + mov %ebx,%r10d # pass rounds + + call _bsaes_encrypt8_bitslice + + sub \$8,$len + jc .Lctr_enc_loop_done + + movdqu 0x00($inp), @XMM[8] # load input + movdqu 0x10($inp), @XMM[9] + movdqu 0x20($inp), @XMM[10] + movdqu 0x30($inp), @XMM[11] + movdqu 0x40($inp), @XMM[12] + movdqu 0x50($inp), @XMM[13] + movdqu 0x60($inp), @XMM[14] + movdqu 0x70($inp), @XMM[15] + lea 0x80($inp),$inp + pxor @XMM[0], @XMM[8] + movdqa 0x20(%rbp), @XMM[0] # load counter + pxor @XMM[9], @XMM[1] + movdqu @XMM[8], 0x00($out) # write output + pxor @XMM[10], @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor @XMM[11], @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor @XMM[12], @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor @XMM[13], @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor @XMM[14], @XMM[2] + movdqu @XMM[7], 0x50($out) + pxor @XMM[15], @XMM[5] + movdqu @XMM[2], 0x60($out) + lea .LADD1(%rip), %r11 + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + paddd 0x70(%r11), @XMM[0] # .LADD8 + jnz .Lctr_enc_loop + + jmp .Lctr_enc_done +.align 16 +.Lctr_enc_loop_done: + add \$8, $len + movdqu 0x00($inp), @XMM[8] # load input + pxor @XMM[8], @XMM[0] + movdqu @XMM[0], 0x00($out) # write output + cmp \$2,$len + jb .Lctr_enc_done + movdqu 0x10($inp), @XMM[9] + pxor @XMM[9], @XMM[1] + movdqu @XMM[1], 0x10($out) + je .Lctr_enc_done + movdqu 0x20($inp), @XMM[10] + pxor @XMM[10], @XMM[4] + movdqu @XMM[4], 0x20($out) + cmp \$4,$len + jb .Lctr_enc_done + movdqu 0x30($inp), @XMM[11] + pxor @XMM[11], @XMM[6] + movdqu @XMM[6], 0x30($out) + je .Lctr_enc_done + movdqu 0x40($inp), @XMM[12] + pxor @XMM[12], @XMM[3] + movdqu @XMM[3], 0x40($out) + cmp \$6,$len + jb .Lctr_enc_done + movdqu 0x50($inp), @XMM[13] + pxor @XMM[13], @XMM[7] + movdqu @XMM[7], 0x50($out) + je .Lctr_enc_done + movdqu 0x60($inp), @XMM[14] + pxor @XMM[14], @XMM[2] + movdqu @XMM[2], 0x60($out) + jmp .Lctr_enc_done + +.align 16 +.Lctr_enc_short: + lea 0x20(%rbp), $arg1 + lea 0x30(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt + movdqu ($inp), @XMM[1] + lea 16($inp), $inp + mov 0x2c(%rbp), %eax # load 32-bit counter + bswap %eax + pxor 0x30(%rbp), @XMM[1] + inc %eax # increment + movdqu @XMM[1], ($out) + bswap %eax + lea 16($out), $out + mov %eax, 0x2c(%rsp) # save 32-bit counter + dec $len + jnz .Lctr_enc_short + +.Lctr_enc_done: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lctr_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lctr_enc_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lctr_enc_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lctr_enc_epilogue: + ret +.cfi_endproc +.size ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks +___ +###################################################################### +# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len, +# const AES_KEY *key1, const AES_KEY *key2, +# const unsigned char iv[16]); +# +my ($twmask,$twres,$twtmp)=@XMM[13..15]; +$arg6=~s/d$//; + +$code.=<<___; +.globl ossl_bsaes_xts_encrypt +.type ossl_bsaes_xts_encrypt,\@abi-omnipotent +.align 16 +ossl_bsaes_xts_encrypt: +.cfi_startproc + mov %rsp, %rax +.Lxts_enc_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull key2 + mov 0xa8(%rsp),$arg6 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lxts_enc_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp +.cfi_def_cfa_register %rbp + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + + lea ($arg6), $arg1 + lea 0x20(%rbp), $arg2 + lea ($arg5), $arg3 + call asm_AES_encrypt # generate initial tweak + + mov 240($key), %eax # rounds + mov $len, %rbx # backup $len + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor %xmm6, %xmm7 # fix up last round key + movdqa %xmm7, (%rax) # save last round key + + and \$-16, $len + sub \$0x80, %rsp # place for tweak[8] + movdqa 0x20(%rbp), @XMM[7] # initial tweak + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + + sub \$0x80, $len + jc .Lxts_enc_short + jmp .Lxts_enc_loop + +.align 16 +.Lxts_enc_loop: +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqu 0x70($inp), @XMM[8+7] + lea 0x80($inp), $inp + movdqa @XMM[7], 0x70(%rsp) + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + pxor @XMM[8+7], @XMM[7] + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor 0x60(%rsp), @XMM[2] + movdqu @XMM[7], 0x50($out) + pxor 0x70(%rsp), @XMM[5] + movdqu @XMM[2], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + + movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] + + sub \$0x80,$len + jnc .Lxts_enc_loop + +.Lxts_enc_short: + add \$0x80, $len + jz .Lxts_enc_done +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] + cmp \$`0x10*$i`,$len + je .Lxts_enc_$i +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqa @XMM[7], 0x70(%rsp) + lea 0x70($inp), $inp + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + pxor 0x60(%rsp), @XMM[2] + movdqu @XMM[7], 0x50($out) + movdqu @XMM[2], 0x60($out) + lea 0x70($out), $out + + movdqa 0x70(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_6: + pxor @XMM[8+4], @XMM[4] + lea 0x60($inp), $inp + pxor @XMM[8+5], @XMM[5] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[3], 0x40($out) + movdqu @XMM[7], 0x50($out) + lea 0x60($out), $out + + movdqa 0x60(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_5: + pxor @XMM[8+3], @XMM[3] + lea 0x50($inp), $inp + pxor @XMM[8+4], @XMM[4] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + pxor 0x40(%rsp), @XMM[3] + movdqu @XMM[6], 0x30($out) + movdqu @XMM[3], 0x40($out) + lea 0x50($out), $out + + movdqa 0x50(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_4: + pxor @XMM[8+2], @XMM[2] + lea 0x40($inp), $inp + pxor @XMM[8+3], @XMM[3] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[6] + movdqu @XMM[4], 0x20($out) + movdqu @XMM[6], 0x30($out) + lea 0x40($out), $out + + movdqa 0x40(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_3: + pxor @XMM[8+1], @XMM[1] + lea 0x30($inp), $inp + pxor @XMM[8+2], @XMM[2] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[4] + movdqu @XMM[1], 0x10($out) + movdqu @XMM[4], 0x20($out) + lea 0x30($out), $out + + movdqa 0x30(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_2: + pxor @XMM[8+0], @XMM[0] + lea 0x20($inp), $inp + pxor @XMM[8+1], @XMM[1] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_encrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + lea 0x20($out), $out + + movdqa 0x20(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_enc_done +.align 16 +.Lxts_enc_1: + pxor @XMM[0], @XMM[8] + lea 0x10($inp), $inp + movdqa @XMM[8], 0x20(%rbp) + lea 0x20(%rbp), $arg1 + lea 0x20(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_encrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[0] # ^= tweak[] + #pxor @XMM[8], @XMM[0] + #lea 0x80(%rsp), %rax # pass key schedule + #mov %edx, %r10d # pass rounds + #call _bsaes_encrypt8 + #pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + movdqu @XMM[0], 0x00($out) # write output + lea 0x10($out), $out + + movdqa 0x10(%rsp), @XMM[7] # next iteration tweak + +.Lxts_enc_done: + and \$15, %ebx + jz .Lxts_enc_ret + mov $out, %rdx + +.Lxts_enc_steal: + movzb ($inp), %eax + movzb -16(%rdx), %ecx + lea 1($inp), $inp + mov %al, -16(%rdx) + mov %cl, 0(%rdx) + lea 1(%rdx), %rdx + sub \$1,%ebx + jnz .Lxts_enc_steal + + movdqu -16($out), @XMM[0] + lea 0x20(%rbp), $arg1 + pxor @XMM[7], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_encrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[7] + movdqu @XMM[7], -16($out) + +.Lxts_enc_ret: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lxts_enc_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lxts_enc_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lxts_enc_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lxts_enc_epilogue: + ret +.cfi_endproc +.size ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt + +.globl ossl_bsaes_xts_decrypt +.type ossl_bsaes_xts_decrypt,\@abi-omnipotent +.align 16 +ossl_bsaes_xts_decrypt: +.cfi_startproc + mov %rsp, %rax +.Lxts_dec_prologue: + push %rbp +.cfi_push %rbp + push %rbx +.cfi_push %rbx + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 + lea -0x48(%rsp), %rsp +.cfi_adjust_cfa_offset 0x48 +___ +$code.=<<___ if ($win64); + mov 0xa0(%rsp),$arg5 # pull key2 + mov 0xa8(%rsp),$arg6 # pull ivp + lea -0xa0(%rsp), %rsp + movaps %xmm6, 0x40(%rsp) + movaps %xmm7, 0x50(%rsp) + movaps %xmm8, 0x60(%rsp) + movaps %xmm9, 0x70(%rsp) + movaps %xmm10, 0x80(%rsp) + movaps %xmm11, 0x90(%rsp) + movaps %xmm12, 0xa0(%rsp) + movaps %xmm13, 0xb0(%rsp) + movaps %xmm14, 0xc0(%rsp) + movaps %xmm15, 0xd0(%rsp) +.Lxts_dec_body: +___ +$code.=<<___; + mov %rsp, %rbp # backup %rsp + mov $arg1, $inp # backup arguments + mov $arg2, $out + mov $arg3, $len + mov $arg4, $key + + lea ($arg6), $arg1 + lea 0x20(%rbp), $arg2 + lea ($arg5), $arg3 + call asm_AES_encrypt # generate initial tweak + + mov 240($key), %eax # rounds + mov $len, %rbx # backup $len + + mov %eax, %edx # rounds + shl \$7, %rax # 128 bytes per inner round key + sub \$`128-32`, %rax # size of bit-sliced key schedule + sub %rax, %rsp + + mov %rsp, %rax # pass key schedule + mov $key, %rcx # pass key + mov %edx, %r10d # pass rounds + call _bsaes_key_convert + pxor (%rsp), %xmm7 # fix up round 0 key + movdqa %xmm6, (%rax) # save last round key + movdqa %xmm7, (%rsp) + + xor %eax, %eax # if ($len%16) len-=16; + and \$-16, $len + test \$15, %ebx + setnz %al + shl \$4, %rax + sub %rax, $len + + sub \$0x80, %rsp # place for tweak[8] + movdqa 0x20(%rbp), @XMM[7] # initial tweak + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + + sub \$0x80, $len + jc .Lxts_dec_short + jmp .Lxts_dec_loop + +.align 16 +.Lxts_dec_loop: +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqu 0x70($inp), @XMM[8+7] + lea 0x80($inp), $inp + movdqa @XMM[7], 0x70(%rsp) + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + pxor @XMM[8+7], @XMM[7] + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + pxor 0x60(%rsp), @XMM[3] + movdqu @XMM[7], 0x50($out) + pxor 0x70(%rsp), @XMM[5] + movdqu @XMM[3], 0x60($out) + movdqu @XMM[5], 0x70($out) + lea 0x80($out), $out + + movdqa 0x70(%rsp), @XMM[7] # prepare next iteration tweak + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] + + sub \$0x80,$len + jnc .Lxts_dec_loop + +.Lxts_dec_short: + add \$0x80, $len + jz .Lxts_dec_done +___ + for ($i=0;$i<7;$i++) { + $code.=<<___; + pshufd \$0x13, $twtmp, $twres + pxor $twtmp, $twtmp + movdqa @XMM[7], @XMM[$i] + movdqa @XMM[7], `0x10*$i`(%rsp)# save tweak[$i] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + pcmpgtd @XMM[7], $twtmp # broadcast upper bits + pxor $twres, @XMM[7] +___ + $code.=<<___ if ($i>=1); + movdqu `0x10*($i-1)`($inp), @XMM[8+$i-1] + cmp \$`0x10*$i`,$len + je .Lxts_dec_$i +___ + $code.=<<___ if ($i>=2); + pxor @XMM[8+$i-2], @XMM[$i-2]# input[] ^ tweak[] +___ + } +$code.=<<___; + movdqu 0x60($inp), @XMM[8+6] + pxor @XMM[8+5], @XMM[5] + movdqa @XMM[7], 0x70(%rsp) + lea 0x70($inp), $inp + pxor @XMM[8+6], @XMM[6] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + pxor 0x60(%rsp), @XMM[3] + movdqu @XMM[7], 0x50($out) + movdqu @XMM[3], 0x60($out) + lea 0x70($out), $out + + movdqa 0x70(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_6: + pxor @XMM[8+4], @XMM[4] + lea 0x60($inp), $inp + pxor @XMM[8+5], @XMM[5] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + pxor 0x50(%rsp), @XMM[7] + movdqu @XMM[2], 0x40($out) + movdqu @XMM[7], 0x50($out) + lea 0x60($out), $out + + movdqa 0x60(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_5: + pxor @XMM[8+3], @XMM[3] + lea 0x50($inp), $inp + pxor @XMM[8+4], @XMM[4] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + pxor 0x40(%rsp), @XMM[2] + movdqu @XMM[4], 0x30($out) + movdqu @XMM[2], 0x40($out) + lea 0x50($out), $out + + movdqa 0x50(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_4: + pxor @XMM[8+2], @XMM[2] + lea 0x40($inp), $inp + pxor @XMM[8+3], @XMM[3] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + pxor 0x30(%rsp), @XMM[4] + movdqu @XMM[6], 0x20($out) + movdqu @XMM[4], 0x30($out) + lea 0x40($out), $out + + movdqa 0x40(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_3: + pxor @XMM[8+1], @XMM[1] + lea 0x30($inp), $inp + pxor @XMM[8+2], @XMM[2] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + pxor 0x20(%rsp), @XMM[6] + movdqu @XMM[1], 0x10($out) + movdqu @XMM[6], 0x20($out) + lea 0x30($out), $out + + movdqa 0x30(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_2: + pxor @XMM[8+0], @XMM[0] + lea 0x20($inp), $inp + pxor @XMM[8+1], @XMM[1] + lea 0x80(%rsp), %rax # pass key schedule + mov %edx, %r10d # pass rounds + + call _bsaes_decrypt8 + + pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + pxor 0x10(%rsp), @XMM[1] + movdqu @XMM[0], 0x00($out) # write output + movdqu @XMM[1], 0x10($out) + lea 0x20($out), $out + + movdqa 0x20(%rsp), @XMM[7] # next iteration tweak + jmp .Lxts_dec_done +.align 16 +.Lxts_dec_1: + pxor @XMM[0], @XMM[8] + lea 0x10($inp), $inp + movdqa @XMM[8], 0x20(%rbp) + lea 0x20(%rbp), $arg1 + lea 0x20(%rbp), $arg2 + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[0] # ^= tweak[] + #pxor @XMM[8], @XMM[0] + #lea 0x80(%rsp), %rax # pass key schedule + #mov %edx, %r10d # pass rounds + #call _bsaes_decrypt8 + #pxor 0x00(%rsp), @XMM[0] # ^= tweak[] + movdqu @XMM[0], 0x00($out) # write output + lea 0x10($out), $out + + movdqa 0x10(%rsp), @XMM[7] # next iteration tweak + +.Lxts_dec_done: + and \$15, %ebx + jz .Lxts_dec_ret + + pxor $twtmp, $twtmp + movdqa .Lxts_magic(%rip), $twmask + pcmpgtd @XMM[7], $twtmp + pshufd \$0x13, $twtmp, $twres + movdqa @XMM[7], @XMM[6] + paddq @XMM[7], @XMM[7] # psllq 1,$tweak + pand $twmask, $twres # isolate carry and residue + movdqu ($inp), @XMM[0] + pxor $twres, @XMM[7] + + lea 0x20(%rbp), $arg1 + pxor @XMM[7], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[7] + mov $out, %rdx + movdqu @XMM[7], ($out) + +.Lxts_dec_steal: + movzb 16($inp), %eax + movzb (%rdx), %ecx + lea 1($inp), $inp + mov %al, (%rdx) + mov %cl, 16(%rdx) + lea 1(%rdx), %rdx + sub \$1,%ebx + jnz .Lxts_dec_steal + + movdqu ($out), @XMM[0] + lea 0x20(%rbp), $arg1 + pxor @XMM[6], @XMM[0] + lea 0x20(%rbp), $arg2 + movdqa @XMM[0], 0x20(%rbp) + lea ($key), $arg3 + call asm_AES_decrypt # doesn't touch %xmm + pxor 0x20(%rbp), @XMM[6] + movdqu @XMM[6], ($out) + +.Lxts_dec_ret: + lea (%rsp), %rax + pxor %xmm0, %xmm0 +.Lxts_dec_bzero: # wipe key schedule [if any] + movdqa %xmm0, 0x00(%rax) + movdqa %xmm0, 0x10(%rax) + lea 0x20(%rax), %rax + cmp %rax, %rbp + ja .Lxts_dec_bzero + + lea 0x78(%rbp),%rax +.cfi_def_cfa %rax,8 +___ +$code.=<<___ if ($win64); + movaps 0x40(%rbp), %xmm6 + movaps 0x50(%rbp), %xmm7 + movaps 0x60(%rbp), %xmm8 + movaps 0x70(%rbp), %xmm9 + movaps 0x80(%rbp), %xmm10 + movaps 0x90(%rbp), %xmm11 + movaps 0xa0(%rbp), %xmm12 + movaps 0xb0(%rbp), %xmm13 + movaps 0xc0(%rbp), %xmm14 + movaps 0xd0(%rbp), %xmm15 + lea 0xa0(%rax), %rax +.Lxts_dec_tail: +___ +$code.=<<___; + mov -48(%rax), %r15 +.cfi_restore %r15 + mov -40(%rax), %r14 +.cfi_restore %r14 + mov -32(%rax), %r13 +.cfi_restore %r13 + mov -24(%rax), %r12 +.cfi_restore %r12 + mov -16(%rax), %rbx +.cfi_restore %rbx + mov -8(%rax), %rbp +.cfi_restore %rbp + lea (%rax), %rsp # restore %rsp +.cfi_def_cfa_register %rsp +.Lxts_dec_epilogue: + ret +.cfi_endproc +.size ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt +___ +} +$code.=<<___; +.type _bsaes_const,\@object +.align 64 +_bsaes_const: +.LM0ISR: # InvShiftRows constants + .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 +.LISRM0: + .quad 0x01040b0e0205080f, 0x0306090c00070a0d +.LISR: + .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 +.LBS0: # bit-slice constants + .quad 0x5555555555555555, 0x5555555555555555 +.LBS1: + .quad 0x3333333333333333, 0x3333333333333333 +.LBS2: + .quad 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f +.LSR: # shiftrows constants + .quad 0x0504070600030201, 0x0f0e0d0c0a09080b +.LSRM0: + .quad 0x0304090e00050a0f, 0x01060b0c0207080d +.LM0SR: + .quad 0x0a0e02060f03070b, 0x0004080c05090d01 +.LSWPUP: # byte-swap upper dword + .quad 0x0706050403020100, 0x0c0d0e0f0b0a0908 +.LSWPUPM0SR: + .quad 0x0a0d02060c03070b, 0x0004080f05090e01 +.LADD1: # counter increment constants + .quad 0x0000000000000000, 0x0000000100000000 +.LADD2: + .quad 0x0000000000000000, 0x0000000200000000 +.LADD3: + .quad 0x0000000000000000, 0x0000000300000000 +.LADD4: + .quad 0x0000000000000000, 0x0000000400000000 +.LADD5: + .quad 0x0000000000000000, 0x0000000500000000 +.LADD6: + .quad 0x0000000000000000, 0x0000000600000000 +.LADD7: + .quad 0x0000000000000000, 0x0000000700000000 +.LADD8: + .quad 0x0000000000000000, 0x0000000800000000 +.Lxts_magic: + .long 0x87,0,1,0 +.Lmasks: + .quad 0x0101010101010101, 0x0101010101010101 + .quad 0x0202020202020202, 0x0202020202020202 + .quad 0x0404040404040404, 0x0404040404040404 + .quad 0x0808080808080808, 0x0808080808080808 +.LM0: + .quad 0x02060a0e03070b0f, 0x0004080c0105090d +.L63: + .quad 0x6363636363636363, 0x6363636363636363 +.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov" +.align 64 +.size _bsaes_const,.-_bsaes_const +___ + +# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, +# CONTEXT *context,DISPATCHER_CONTEXT *disp) +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___; +.extern __imp_RtlVirtualUnwind +.type se_handler,\@abi-omnipotent +.align 16 +se_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->Rip<=prologue label + jbe .Lin_prologue + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=epilogue label + jae .Lin_prologue + + mov 8(%r11),%r10d # HandlerData[2] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=tail label + jae .Lin_tail + + mov 160($context),%rax # pull context->Rbp + + lea 0x40(%rax),%rsi # %xmm save area + lea 512($context),%rdi # &context.Xmm6 + mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax) + .long 0xa548f3fc # cld; rep movsq + lea 0xa0+0x78(%rax),%rax # adjust stack pointer + +.Lin_tail: + mov -48(%rax),%rbp + mov -40(%rax),%rbx + mov -32(%rax),%r12 + mov -24(%rax),%r13 + mov -16(%rax),%r14 + mov -8(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R15 + +.Lin_prologue: + mov %rax,152($context) # restore context->Rsp + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$`1232/8`,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size se_handler,.-se_handler + +.section .pdata +.align 4 +___ +$code.=<<___ if ($ecb); + .rva .Lecb_enc_prologue + .rva .Lecb_enc_epilogue + .rva .Lecb_enc_info + + .rva .Lecb_dec_prologue + .rva .Lecb_dec_epilogue + .rva .Lecb_dec_info +___ +$code.=<<___; + .rva .Lcbc_dec_prologue + .rva .Lcbc_dec_epilogue + .rva .Lcbc_dec_info + + .rva .Lctr_enc_prologue + .rva .Lctr_enc_epilogue + .rva .Lctr_enc_info + + .rva .Lxts_enc_prologue + .rva .Lxts_enc_epilogue + .rva .Lxts_enc_info + + .rva .Lxts_dec_prologue + .rva .Lxts_dec_epilogue + .rva .Lxts_dec_info + +.section .xdata +.align 8 +___ +$code.=<<___ if ($ecb); +.Lecb_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[] + .rva .Lecb_enc_tail + .long 0 +.Lecb_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[] + .rva .Lecb_dec_tail + .long 0 +___ +$code.=<<___; +.Lcbc_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[] + .rva .Lcbc_dec_tail + .long 0 +.Lctr_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[] + .rva .Lctr_enc_tail + .long 0 +.Lxts_enc_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[] + .rva .Lxts_enc_tail + .long 0 +.Lxts_dec_info: + .byte 9,0,0,0 + .rva se_handler + .rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[] + .rva .Lxts_dec_tail + .long 0 +___ +} + +$code =~ s/\`([^\`]*)\`/eval($1)/gem; + +print $code; + +close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/aes/asm/vpaes-armv8.pl b/crypto/aes/asm/vpaes-armv8.pl --- a/crypto/aes/asm/vpaes-armv8.pl +++ b/crypto/aes/asm/vpaes-armv8.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -30,6 +30,7 @@ # Denver(***) 16.6(**) 15.1/17.8(**) [8.80/9.93 ] # Apple A7(***) 22.7(**) 10.9/14.3 [8.45/10.0 ] # Mongoose(***) 26.3(**) 21.0/25.0(**) [13.3/16.8 ] +# ThunderX2(***) 39.4(**) 33.8/48.6(**) # # (*) ECB denotes approximate result for parallelizable modes # such as CBC decrypt, CTR, etc.; @@ -37,15 +38,18 @@ # code, but it's constant-time and therefore preferred; # (***) presented for reference/comparison purposes; -$flavour = shift; -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; -open OUT,"| \"$^X\" $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $code.=<<___; @@ -150,12 +154,12 @@ my ($sb9u,$sb9t,$sbdu,$sbdt,$sbbu,$sbbt,$sbeu,$sbet)=map("v$_.16b",(24..31)); $code.=<<___; -## -## _aes_preheat -## -## Fills register %r10 -> .aes_consts (so you can -fPIC) -## and %xmm9-%xmm15 as specified below. -## +// +// _aes_preheat +// +// Fills register %r10 -> .aes_consts (so you can -fPIC) +// and %xmm9-%xmm15 as specified below. +// .type _vpaes_encrypt_preheat,%function .align 4 _vpaes_encrypt_preheat: @@ -167,21 +171,21 @@ ret .size _vpaes_encrypt_preheat,.-_vpaes_encrypt_preheat -## -## _aes_encrypt_core -## -## AES-encrypt %xmm0. -## -## Inputs: -## %xmm0 = input -## %xmm9-%xmm15 as in _vpaes_preheat -## (%rdx) = scheduled keys -## -## Output in %xmm0 -## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax -## Preserves %xmm6 - %xmm8 so you get some local vectors -## -## +// +// _aes_encrypt_core +// +// AES-encrypt %xmm0. +// +// Inputs: +// %xmm0 = input +// %xmm9-%xmm15 as in _vpaes_preheat +// (%rdx) = scheduled keys +// +// Output in %xmm0 +// Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax +// Preserves %xmm6 - %xmm8 so you get some local vectors +// +// .type _vpaes_encrypt_core,%function .align 4 _vpaes_encrypt_core: @@ -387,11 +391,11 @@ ret .size _vpaes_decrypt_preheat,.-_vpaes_decrypt_preheat -## -## Decryption core -## -## Same API as encryption core. -## +// +// Decryption core +// +// Same API as encryption core. +// .type _vpaes_decrypt_core,%function .align 4 _vpaes_decrypt_core: @@ -643,11 +647,11 @@ my ($invlo,$invhi,$iptlo,$ipthi,$rcon) = map("v$_.16b",(18..21,8)); $code.=<<___; -######################################################## -## ## -## AES key schedule ## -## ## -######################################################## +//////////////////////////////////////////////////////// +// // +// AES key schedule // +// // +//////////////////////////////////////////////////////// .type _vpaes_key_preheat,%function .align 4 _vpaes_key_preheat: @@ -703,14 +707,14 @@ b.eq .Lschedule_192 // 128: fall though -## -## .schedule_128 -## -## 128-bit specific part of key schedule. -## -## This schedule is really simple, because all its parts -## are accomplished by the subroutines. -## +// +// .schedule_128 +// +// 128-bit specific part of key schedule. +// +// This schedule is really simple, because all its parts +// are accomplished by the subroutines. +// .Lschedule_128: mov $inp, #10 // mov \$10, %esi @@ -721,21 +725,21 @@ bl _vpaes_schedule_mangle // write output b .Loop_schedule_128 -## -## .aes_schedule_192 -## -## 192-bit specific part of key schedule. -## -## The main body of this schedule is the same as the 128-bit -## schedule, but with more smearing. The long, high side is -## stored in %xmm7 as before, and the short, low side is in -## the high bits of %xmm6. -## -## This schedule is somewhat nastier, however, because each -## round produces 192 bits of key material, or 1.5 round keys. -## Therefore, on each cycle we do 2 rounds and produce 3 round -## keys. -## +// +// .aes_schedule_192 +// +// 192-bit specific part of key schedule. +// +// The main body of this schedule is the same as the 128-bit +// schedule, but with more smearing. The long, high side is +// stored in %xmm7 as before, and the short, low side is in +// the high bits of %xmm6. +// +// This schedule is somewhat nastier, however, because each +// round produces 192 bits of key material, or 1.5 round keys. +// Therefore, on each cycle we do 2 rounds and produce 3 round +// keys. +// .align 4 .Lschedule_192: sub $inp, $inp, #8 @@ -759,16 +763,16 @@ bl _vpaes_schedule_192_smear b .Loop_schedule_192 -## -## .aes_schedule_256 -## -## 256-bit specific part of key schedule. -## -## The structure here is very similar to the 128-bit -## schedule, but with an additional "low side" in -## %xmm6. The low side's rounds are the same as the -## high side's, except no rcon and no rotation. -## +// +// .aes_schedule_256 +// +// 256-bit specific part of key schedule. +// +// The structure here is very similar to the 128-bit +// schedule, but with an additional "low side" in +// %xmm6. The low side's rounds are the same as the +// high side's, except no rcon and no rotation. +// .align 4 .Lschedule_256: ld1 {v0.16b}, [$inp] // vmovdqu 16(%rdi),%xmm0 # load key part 2 (unaligned) @@ -795,16 +799,16 @@ b .Loop_schedule_256 -## -## .aes_schedule_mangle_last -## -## Mangler for last round of key schedule -## Mangles %xmm0 -## when encrypting, outputs out(%xmm0) ^ 63 -## when decrypting, outputs unskew(%xmm0) -## -## Always called right before return... jumps to cleanup and exits -## +// +// .aes_schedule_mangle_last +// +// Mangler for last round of key schedule +// Mangles %xmm0 +// when encrypting, outputs out(%xmm0) ^ 63 +// when decrypting, outputs unskew(%xmm0) +// +// Always called right before return... jumps to cleanup and exits +// .align 4 .Lschedule_mangle_last: // schedule last round key from xmm0 @@ -838,20 +842,20 @@ ret .size _vpaes_schedule_core,.-_vpaes_schedule_core -## -## .aes_schedule_192_smear -## -## Smear the short, low side in the 192-bit key schedule. -## -## Inputs: -## %xmm7: high side, b a x y -## %xmm6: low side, d c 0 0 -## %xmm13: 0 -## -## Outputs: -## %xmm6: b+c+d b+c 0 0 -## %xmm0: b+c+d b+c b a -## +// +// .aes_schedule_192_smear +// +// Smear the short, low side in the 192-bit key schedule. +// +// Inputs: +// %xmm7: high side, b a x y +// %xmm6: low side, d c 0 0 +// %xmm13: 0 +// +// Outputs: +// %xmm6: b+c+d b+c 0 0 +// %xmm0: b+c+d b+c b a +// .type _vpaes_schedule_192_smear,%function .align 4 _vpaes_schedule_192_smear: @@ -867,24 +871,24 @@ ret .size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear -## -## .aes_schedule_round -## -## Runs one main round of the key schedule on %xmm0, %xmm7 -## -## Specifically, runs subbytes on the high dword of %xmm0 -## then rotates it by one byte and xors into the low dword of -## %xmm7. -## -## Adds rcon from low byte of %xmm8, then rotates %xmm8 for -## next rcon. -## -## Smears the dwords of %xmm7 by xoring the low into the -## second low, result into third, result into highest. -## -## Returns results in %xmm7 = %xmm0. -## Clobbers %xmm1-%xmm4, %r11. -## +// +// .aes_schedule_round +// +// Runs one main round of the key schedule on %xmm0, %xmm7 +// +// Specifically, runs subbytes on the high dword of %xmm0 +// then rotates it by one byte and xors into the low dword of +// %xmm7. +// +// Adds rcon from low byte of %xmm8, then rotates %xmm8 for +// next rcon. +// +// Smears the dwords of %xmm7 by xoring the low into the +// second low, result into third, result into highest. +// +// Returns results in %xmm7 = %xmm0. +// Clobbers %xmm1-%xmm4, %r11. +// .type _vpaes_schedule_round,%function .align 4 _vpaes_schedule_round: @@ -932,15 +936,15 @@ ret .size _vpaes_schedule_round,.-_vpaes_schedule_round -## -## .aes_schedule_transform -## -## Linear-transform %xmm0 according to tables at (%r11) -## -## Requires that %xmm9 = 0x0F0F... as in preheat -## Output in %xmm0 -## Clobbers %xmm1, %xmm2 -## +// +// .aes_schedule_transform +// +// Linear-transform %xmm0 according to tables at (%r11) +// +// Requires that %xmm9 = 0x0F0F... as in preheat +// Output in %xmm0 +// Clobbers %xmm1, %xmm2 +// .type _vpaes_schedule_transform,%function .align 4 _vpaes_schedule_transform: @@ -954,29 +958,29 @@ ret .size _vpaes_schedule_transform,.-_vpaes_schedule_transform -## -## .aes_schedule_mangle -## -## Mangle xmm0 from (basis-transformed) standard version -## to our version. -## -## On encrypt, -## xor with 0x63 -## multiply by circulant 0,1,1,1 -## apply shiftrows transform -## -## On decrypt, -## xor with 0x63 -## multiply by "inverse mixcolumns" circulant E,B,D,9 -## deskew -## apply shiftrows transform -## -## -## Writes out to (%rdx), and increments or decrements it -## Keeps track of round number mod 4 in %r8 -## Preserves xmm0 -## Clobbers xmm1-xmm5 -## +// +// .aes_schedule_mangle +// +// Mangle xmm0 from (basis-transformed) standard version +// to our version. +// +// On encrypt, +// xor with 0x63 +// multiply by circulant 0,1,1,1 +// apply shiftrows transform +// +// On decrypt, +// xor with 0x63 +// multiply by "inverse mixcolumns" circulant E,B,D,9 +// deskew +// apply shiftrows transform +// +// +// Writes out to (%rdx), and increments or decrements it +// Keeps track of round number mod 4 in %r8 +// Preserves xmm0 +// Clobbers xmm1-xmm5 +// .type _vpaes_schedule_mangle,%function .align 4 _vpaes_schedule_mangle: diff --git a/crypto/aes/asm/vpaes-ppc.pl b/crypto/aes/asm/vpaes-ppc.pl --- a/crypto/aes/asm/vpaes-ppc.pl +++ b/crypto/aes/asm/vpaes-ppc.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -35,7 +35,10 @@ # (**) Inadequate POWER6 performance is due to astronomic AltiVec # latency, 9 cycles per simple logical operation. -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /64/) { $SIZE_T =8; @@ -61,7 +64,8 @@ ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; +open STDOUT,"| $^X $xlate $flavour \"$output\"" + || die "can't call $xlate: $!"; $code.=<<___; .machine "any" diff --git a/crypto/aes/asm/vpaes-x86.pl b/crypto/aes/asm/vpaes-x86.pl --- a/crypto/aes/asm/vpaes-x86.pl +++ b/crypto/aes/asm/vpaes-x86.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -58,9 +58,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open OUT,">$output"; -*STDOUT=*OUT; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); diff --git a/crypto/aes/asm/vpaes-x86_64.pl b/crypto/aes/asm/vpaes-x86_64.pl --- a/crypto/aes/asm/vpaes-x86_64.pl +++ b/crypto/aes/asm/vpaes-x86_64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -54,9 +54,10 @@ # # -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -65,7 +66,8 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $PREFIX="vpaes"; @@ -696,6 +698,7 @@ .align 16 ${PREFIX}_set_encrypt_key: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0xb8(%rsp),%rsp @@ -746,6 +749,7 @@ .align 16 ${PREFIX}_set_decrypt_key: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0xb8(%rsp),%rsp @@ -801,6 +805,7 @@ .align 16 ${PREFIX}_encrypt: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0xb8(%rsp),%rsp @@ -846,6 +851,7 @@ .align 16 ${PREFIX}_decrypt: .cfi_startproc + endbranch ___ $code.=<<___ if ($win64); lea -0xb8(%rsp),%rsp @@ -897,6 +903,7 @@ .align 16 ${PREFIX}_cbc_encrypt: .cfi_startproc + endbranch xchg $key,$len ___ ($len,$key)=($key,$len); diff --git a/crypto/aes/build.info b/crypto/aes/build.info --- a/crypto/aes/build.info +++ b/crypto/aes/build.info @@ -1,64 +1,128 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - aes_misc.c aes_ecb.c aes_cfb.c aes_ofb.c \ - aes_ige.c aes_wrap.c {- $target{aes_asm_src} -} + +$AESASM=aes_core.c aes_cbc.c +IF[{- !$disabled{asm} -}] + $AESASM_x86=aes-586.S + $AESDEF_x86=AES_ASM + $AESASM_x86_sse2=vpaes-x86.S aesni-x86.S + $AESDEF_x86_sse2=VPAES_ASM OPENSSL_IA32_SSE2 + + $AESASM_x86_64=\ + aes-x86_64.s vpaes-x86_64.s bsaes-x86_64.s aesni-x86_64.s \ + aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s + $AESDEF_x86_64=AES_ASM VPAES_ASM BSAES_ASM + + $AESASM_ia64=aes_core.c aes_cbc.c aes-ia64.s + $AESDEF_ia64=AES_ASM + + $AESASM_sparcv9=\ + aes_core.c aes_cbc.c aes-sparcv9.S aest4-sparcv9.S aesfx-sparcv9.S + $AESDEF_sparcv9=AES_ASM + + $AESASM_mips32=aes_cbc.c aes-mips.S + $AESDEF_mips32=AES_ASM + $AESASM_mips64=$AESASM_mips32 + $AESDEF_mips64=$AESDEF_mips32 + + $AESASM_s390x=aes-s390x.S + # aes-390x.S implements AES_ctr32_encrypt and AES_xts_[en|de]crypt + $AESDEF_s390x=AES_ASM AES_CTR_ASM AES_XTS_ASM + + $AESASM_armv4=aes_cbc.c aes-armv4.S bsaes-armv7.S aesv8-armx.S + $AESDEF_armv4=AES_ASM BSAES_ASM + $AESASM_aarch64=aes_core.c aes_cbc.c aesv8-armx.S vpaes-armv8.S + $AESDEF_aarch64=VPAES_ASM + + $AESASM_parisc11=aes_core.c aes_cbc.c aes-parisc.s + $AESDEF_parisc11=AES_ASM + $AESASM_parisc20_64=$AESASM_parisc11 + $AESDEF_parisc20_64=$AESDEF_parisc11 + + $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s + $AESDEF_ppc32=AES_ASM VPAES_ASM + $AESASM_ppc64=$AESASM_ppc32 + $AESDEF_ppc64=$AESDEF_ppc32 + + $AESASM_c64xplus=aes-c64xplus.s aes_cbc.c + # aes-c64xplus.s implements AES_ctr32_encrypt + $AESDEF_c64xplus=AES_ASM AES_CTR_ASM + + # Now that we have defined all the arch specific variables, use the + # appropriate one, and define the appropriate macros + IF[$AESASM_{- $target{asm_arch} -}] + $AESASM=$AESASM_{- $target{asm_arch} -} + $AESDEF=$AESDEF_{- $target{asm_arch} -} + IF[{- !$disabled{sse2} -}] + $AESASM=$AESASM $AESASM_{- $target{asm_arch} -}_sse2 + $AESDEF=$AESDEF $AESDEF_{- $target{asm_arch} -}_sse2 + ENDIF + ENDIF +ENDIF + +$COMMON=aes_misc.c aes_ecb.c $AESASM +SOURCE[../../libcrypto]=$COMMON aes_cfb.c aes_ofb.c aes_wrap.c +IF[{- !$disabled{'deprecated-3.0'} -}] + SOURCE[../../libcrypto]=aes_ige.c +ENDIF +SOURCE[../../providers/libfips.a]=$COMMON + +# Implementations are now spread across several libraries, so the defines +# need to be applied to all affected libraries and modules. +DEFINE[../../libcrypto]=$AESDEF +DEFINE[../../providers/libfips.a]=$AESDEF +DEFINE[../../providers/libdefault.a]=$AESDEF +# We only need to include the AESDEF stuff in the legacy provider when it's a +# separate module and it's dynamically linked with libcrypto. Otherwise, it +# already gets everything that the static libcrypto.a has, and doesn't need it +# added again. +IF[{- !$disabled{module} && !$disabled{shared} -}] + DEFINE[../providers/liblegacy.a]=$AESDEF +ENDIF GENERATE[aes-ia64.s]=asm/aes-ia64.S -GENERATE[aes-586.s]=asm/aes-586.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[aes-586.s]=../perlasm/x86asm.pl -GENERATE[vpaes-x86.s]=asm/vpaes-x86.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[vpaes-586.s]=../perlasm/x86asm.pl -GENERATE[aesni-x86.s]=asm/aesni-x86.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[aesni-586.s]=../perlasm/x86asm.pl - -GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl $(PERLASM_SCHEME) -GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl $(PERLASM_SCHEME) -GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl $(PERLASM_SCHEME) -GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl $(PERLASM_SCHEME) -GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl $(PERLASM_SCHEME) -GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl $(PERLASM_SCHEME) -GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl $(PERLASM_SCHEME) - -GENERATE[aes-sparcv9.S]=asm/aes-sparcv9.pl $(PERLASM_SCHEME) +GENERATE[aes-586.S]=asm/aes-586.pl +DEPEND[aes-586.S]=../perlasm/x86asm.pl +GENERATE[vpaes-x86.S]=asm/vpaes-x86.pl +DEPEND[vpaes-586.S]=../perlasm/x86asm.pl +GENERATE[aesni-x86.S]=asm/aesni-x86.pl +DEPEND[aesni-586.S]=../perlasm/x86asm.pl + +GENERATE[aes-x86_64.s]=asm/aes-x86_64.pl +GENERATE[vpaes-x86_64.s]=asm/vpaes-x86_64.pl +GENERATE[bsaes-x86_64.s]=asm/bsaes-x86_64.pl +GENERATE[aesni-x86_64.s]=asm/aesni-x86_64.pl +GENERATE[aesni-sha1-x86_64.s]=asm/aesni-sha1-x86_64.pl +GENERATE[aesni-sha256-x86_64.s]=asm/aesni-sha256-x86_64.pl +GENERATE[aesni-mb-x86_64.s]=asm/aesni-mb-x86_64.pl + +GENERATE[aes-sparcv9.S]=asm/aes-sparcv9.pl INCLUDE[aes-sparcv9.o]=.. -GENERATE[aest4-sparcv9.S]=asm/aest4-sparcv9.pl $(PERLASM_SCHEME) +GENERATE[aest4-sparcv9.S]=asm/aest4-sparcv9.pl INCLUDE[aest4-sparcv9.o]=.. DEPEND[aest4-sparcv9.S]=../perlasm/sparcv9_modes.pl -GENERATE[aesfx-sparcv9.S]=asm/aesfx-sparcv9.pl $(PERLASM_SCHEME) +GENERATE[aesfx-sparcv9.S]=asm/aesfx-sparcv9.pl INCLUDE[aesfx-sparcv9.o]=.. -GENERATE[aes-ppc.s]=asm/aes-ppc.pl $(PERLASM_SCHEME) -GENERATE[vpaes-ppc.s]=asm/vpaes-ppc.pl $(PERLASM_SCHEME) -GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl $(PERLASM_SCHEME) +GENERATE[aes-ppc.s]=asm/aes-ppc.pl +GENERATE[vpaes-ppc.s]=asm/vpaes-ppc.pl +GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl -GENERATE[aes-parisc.s]=asm/aes-parisc.pl $(PERLASM_SCHEME) +GENERATE[aes-parisc.s]=asm/aes-parisc.pl -GENERATE[aes-mips.S]=asm/aes-mips.pl $(PERLASM_SCHEME) +GENERATE[aes-mips.S]=asm/aes-mips.pl INCLUDE[aes-mips.o]=.. -GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl $(PERLASM_SCHEME) +GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl INCLUDE[aesv8-armx.o]=.. -GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl $(PERLASM_SCHEME) +GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl -GENERATE[aes-armv4.S]=asm/aes-armv4.pl $(PERLASM_SCHEME) +GENERATE[aes-armv4.S]=asm/aes-armv4.pl INCLUDE[aes-armv4.o]=.. -GENERATE[bsaes-armv7.S]=asm/bsaes-armv7.pl $(PERLASM_SCHEME) +GENERATE[bsaes-armv7.S]=asm/bsaes-armv7.pl INCLUDE[bsaes-armv7.o]=.. -GENERATE[aes-s390x.S]=asm/aes-s390x.pl $(PERLASM_SCHEME) +GENERATE[aes-s390x.S]=asm/aes-s390x.pl INCLUDE[aes-s390x.o]=.. -BEGINRAW[Makefile] -##### AES assembler implementations - -# GNU make "catch all" -{- $builddir -}/aes-%.S: {- $sourcedir -}/asm/aes-%.pl - CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ -{- $builddir -}/bsaes-%.S: {- $sourcedir -}/asm/bsaes-%.pl - CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ - -ENDRAW[Makefile] +GENERATE[aes-c64xplus.S]=asm/aes-c64xplus.pl diff --git a/crypto/aria/aria.c b/crypto/aria/aria.c --- a/crypto/aria/aria.c +++ b/crypto/aria/aria.c @@ -1,8 +1,8 @@ /* - * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -468,8 +468,8 @@ (Y) = (TMP2) ^ rotr32((TMP) ^ (TMP2), 16); \ } while(0) -void aria_encrypt(const unsigned char *in, unsigned char *out, - const ARIA_KEY *key) +void ossl_aria_encrypt(const unsigned char *in, unsigned char *out, + const ARIA_KEY *key) { register uint32_t reg0, reg1, reg2, reg3; int Nr; @@ -535,8 +535,8 @@ PUT_U32_BE(out, 3, reg3); } -int aria_set_encrypt_key(const unsigned char *userKey, const int bits, - ARIA_KEY *key) +int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) { register uint32_t reg0, reg1, reg2, reg3; uint32_t w0[4], w1[4], w2[4], w3[4]; @@ -667,8 +667,8 @@ return 0; } -int aria_set_decrypt_key(const unsigned char *userKey, const int bits, - ARIA_KEY *key) +int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) { ARIA_u128 *rk_head; ARIA_u128 *rk_tail; @@ -676,7 +676,7 @@ register uint32_t reg0, reg1, reg2, reg3; uint32_t s0, s1, s2, s3; - const int r = aria_set_encrypt_key(userKey, bits, key); + const int r = ossl_aria_set_encrypt_key(userKey, bits, key); if (r != 0) { return r; @@ -1007,7 +1007,7 @@ { unsigned int i; for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) { - o[i ] = sb3[x->c[i ] ^ y->c[i ]]; + o[i ] = sb3[x->c[i ] ^ y->c[i ]]; o[i + 1] = sb4[x->c[i + 1] ^ y->c[i + 1]]; o[i + 2] = sb1[x->c[i + 2] ^ y->c[i + 2]]; o[i + 3] = sb2[x->c[i + 3] ^ y->c[i + 3]]; @@ -1106,8 +1106,8 @@ * Encrypt a single block * in and out can overlap */ -void aria_encrypt(const unsigned char *in, unsigned char *out, - const ARIA_KEY *key) +void ossl_aria_encrypt(const unsigned char *in, unsigned char *out, + const ARIA_KEY *key) { assert(in != NULL && out != NULL && key != NULL); do_encrypt(out, in, key->rounds, key->rd_key); @@ -1119,8 +1119,8 @@ * We short circuit execution of the last two * or four rotations based on the key size. */ -int aria_set_encrypt_key(const unsigned char *userKey, const int bits, - ARIA_KEY *key) +int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) { const ARIA_u128 *ck1, *ck2, *ck3; ARIA_u128 kr, w0, w1, w2, w3; @@ -1192,11 +1192,11 @@ /* * Expand the cipher key into the decryption key schedule. */ -int aria_set_decrypt_key(const unsigned char *userKey, const int bits, - ARIA_KEY *key) +int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits, + ARIA_KEY *key) { ARIA_KEY ek; - const int r = aria_set_encrypt_key(userKey, bits, &ek); + const int r = ossl_aria_set_encrypt_key(userKey, bits, &ek); unsigned int i, rounds = ek.rounds; if (r == 0) { diff --git a/crypto/arm64cpuid.pl b/crypto/arm64cpuid.pl --- a/crypto/arm64cpuid.pl +++ b/crypto/arm64cpuid.pl @@ -1,21 +1,24 @@ #! /usr/bin/env perl # Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html -$flavour = shift; -$output = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or ( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; -open OUT,"| \"$^X\" $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $code.=<<___; @@ -78,6 +81,13 @@ ret .size _armv8_sha512_probe,.-_armv8_sha512_probe +.globl _armv8_cpuid_probe +.type _armv8_cpuid_probe,%function +_armv8_cpuid_probe: + mrs x0, midr_el1 + ret +.size _armv8_cpuid_probe,.-_armv8_cpuid_probe + .globl OPENSSL_cleanse .type OPENSSL_cleanse,%function .align 5 diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h --- a/crypto/arm_arch.h +++ b/crypto/arm_arch.h @@ -1,7 +1,7 @@ /* - * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -71,6 +71,8 @@ # ifndef __ASSEMBLER__ extern unsigned int OPENSSL_armcap_P; +extern unsigned int OPENSSL_arm_midr; +extern unsigned int OPENSSL_armv8_rsa_neonized; # endif # define ARMV7_NEON (1<<0) @@ -80,5 +82,48 @@ # define ARMV8_SHA256 (1<<4) # define ARMV8_PMULL (1<<5) # define ARMV8_SHA512 (1<<6) +# define ARMV8_CPUID (1<<7) +/* + * MIDR_EL1 system register + * + * 63___ _ ___32_31___ _ ___24_23_____20_19_____16_15__ _ __4_3_______0 + * | | | | | | | + * |RES0 | Implementer | Variant | Arch | PartNum |Revision| + * |____ _ _____|_____ _ _____|_________|_______ _|____ _ ___|________| + * + */ + +# define ARM_CPU_IMP_ARM 0x41 + +# define ARM_CPU_PART_CORTEX_A72 0xD08 +# define ARM_CPU_PART_N1 0xD0C + +# define MIDR_PARTNUM_SHIFT 4 +# define MIDR_PARTNUM_MASK (0xfffU << MIDR_PARTNUM_SHIFT) +# define MIDR_PARTNUM(midr) \ + (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT) + +# define MIDR_IMPLEMENTER_SHIFT 24 +# define MIDR_IMPLEMENTER_MASK (0xffU << MIDR_IMPLEMENTER_SHIFT) +# define MIDR_IMPLEMENTER(midr) \ + (((midr) & MIDR_IMPLEMENTER_MASK) >> MIDR_IMPLEMENTER_SHIFT) + +# define MIDR_ARCHITECTURE_SHIFT 16 +# define MIDR_ARCHITECTURE_MASK (0xfU << MIDR_ARCHITECTURE_SHIFT) +# define MIDR_ARCHITECTURE(midr) \ + (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT) + +# define MIDR_CPU_MODEL_MASK \ + (MIDR_IMPLEMENTER_MASK | \ + MIDR_PARTNUM_MASK | \ + MIDR_ARCHITECTURE_MASK) + +# define MIDR_CPU_MODEL(imp, partnum) \ + (((imp) << MIDR_IMPLEMENTER_SHIFT) | \ + (0xfU << MIDR_ARCHITECTURE_SHIFT) | \ + ((partnum) << MIDR_PARTNUM_SHIFT)) + +# define MIDR_IS_CPU_MODEL(midr, imp, partnum) \ + (((midr) & MIDR_CPU_MODEL_MASK) == MIDR_CPU_MODEL(imp, partnum)) #endif diff --git a/crypto/armcap.c b/crypto/armcap.c --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -1,7 +1,7 @@ /* - * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -13,11 +13,16 @@ #include #include #include +#ifdef __APPLE__ +#include +#endif #include "internal/cryptlib.h" #include "arm_arch.h" unsigned int OPENSSL_armcap_P = 0; +unsigned int OPENSSL_arm_midr = 0; +unsigned int OPENSSL_armv8_rsa_neonized = 0; #if __ARM_MAX_ARCH__<7 void OPENSSL_cpuid_setup(void) @@ -48,6 +53,7 @@ void _armv8_pmull_probe(void); # ifdef __aarch64__ void _armv8_sha512_probe(void); +unsigned int _armv8_cpuid_probe(void); # endif uint32_t _armv7_tick(void); @@ -130,6 +136,7 @@ # define HWCAP_CE_PMULL (1 << 4) # define HWCAP_CE_SHA1 (1 << 5) # define HWCAP_CE_SHA256 (1 << 6) +# define HWCAP_CPUID (1 << 11) # define HWCAP_CE_SHA512 (1 << 21) # endif @@ -144,12 +151,15 @@ return; trigger = 1; + OPENSSL_armcap_P = 0; + if ((e = getenv("OPENSSL_armcap"))) { OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); return; } -# if defined(__APPLE__) && !defined(__aarch64__) +# if defined(__APPLE__) +# if !defined(__aarch64__) /* * Capability probing by catching SIGILL appears to be problematic * on iOS. But since Apple universe is "monocultural", it's actually @@ -165,9 +175,16 @@ * Unified code works because it never triggers SIGILL on Apple * devices... */ -# endif +# else + { + unsigned int sha512; + size_t len = sizeof(sha512); - OPENSSL_armcap_P = 0; + if (sysctlbyname("hw.optional.armv8_2_sha512", &sha512, &len, NULL, 0) == 0 && sha512 == 1) + OPENSSL_armcap_P |= ARMV8_SHA512; + } +# endif +# endif # ifdef OSSL_IMPLEMENT_GETAUXVAL if (getauxval(HWCAP) & HWCAP_NEON) { @@ -190,6 +207,9 @@ # ifdef __aarch64__ if (hwcap & HWCAP_CE_SHA512) OPENSSL_armcap_P |= ARMV8_SHA512; + + if (hwcap & HWCAP_CPUID) + OPENSSL_armcap_P |= ARMV8_CPUID; # endif } # endif @@ -237,13 +257,24 @@ } # endif - /* Things that getauxval didn't tell us */ - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv7_tick(); - OPENSSL_armcap_P |= ARMV7_TICK; - } + /* + * Probing for ARMV7_TICK is known to produce unreliable results, + * so we will only use the feature when the user explicitly enables + * it with OPENSSL_armcap. + */ sigaction(SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); + +# ifdef __aarch64__ + if (OPENSSL_armcap_P & ARMV8_CPUID) + OPENSSL_arm_midr = _armv8_cpuid_probe(); + + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N1)) && + (OPENSSL_armcap_P & ARMV7_NEON)) { + OPENSSL_armv8_rsa_neonized = 1; + } +# endif } #endif diff --git a/crypto/armv4cpuid.pl b/crypto/armv4cpuid.pl --- a/crypto/armv4cpuid.pl +++ b/crypto/armv4cpuid.pl @@ -1,27 +1,29 @@ #! /usr/bin/env perl # Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html -$flavour = shift; -$output = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or ( $xlate="${dir}perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; -open OUT,"| \"$^X\" $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; $code.=<<___; #include "arm_arch.h" -.text #if defined(__thumb2__) && !defined(__APPLE__) .syntax unified .thumb @@ -30,6 +32,8 @@ #undef __thumb2__ #endif +.text + .align 5 .global OPENSSL_atomic_add .type OPENSSL_atomic_add,%function diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c --- a/crypto/asn1/a_bitstr.c +++ b/crypto/asn1/a_bitstr.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -18,7 +18,7 @@ return ASN1_STRING_set(x, d, len); } -int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) +int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) { int ret, j, bits, len; unsigned char *p, *d; @@ -76,8 +76,8 @@ return ret; } -ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, - const unsigned char **pp, long len) +ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long len) { ASN1_BIT_STRING *ret = NULL; const unsigned char *p; @@ -134,7 +134,7 @@ *pp = p; return ret; err: - ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i); + ERR_raise(ERR_LIB_ASN1, i); if ((a == NULL) || (*a != ret)) ASN1_BIT_STRING_free(ret); return NULL; @@ -164,7 +164,7 @@ return 1; /* Don't need to set */ c = OPENSSL_clear_realloc(a->data, a->length, w + 1); if (c == NULL) { - ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } if (w + 1 - a->length > 0) diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -13,6 +13,7 @@ #include "internal/numbers.h" #include #include +#include "internal/asn1.h" #include "crypto/asn1.h" #ifndef NO_OLD_ASN1 @@ -24,7 +25,7 @@ void *ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return NULL; } BIO_set_fp(b, in, BIO_NOCLOSE); @@ -54,39 +55,53 @@ #endif -void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) +void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *x, + OSSL_LIB_CTX *libctx, const char *propq) { BUF_MEM *b = NULL; const unsigned char *p; void *ret = NULL; int len; + if (in == NULL) + return NULL; len = asn1_d2i_read_bio(in, &b); if (len < 0) goto err; p = (const unsigned char *)b->data; - ret = ASN1_item_d2i(x, &p, len, it); + ret = ASN1_item_d2i_ex(x, &p, len, it, libctx, propq); err: BUF_MEM_free(b); return ret; } +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) +{ + return ASN1_item_d2i_bio_ex(it, in, x, NULL, NULL); +} + #ifndef OPENSSL_NO_STDIO -void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) +void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x, + OSSL_LIB_CTX *libctx, const char *propq) { BIO *b; char *ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return NULL; } BIO_set_fp(b, in, BIO_NOCLOSE); - ret = ASN1_item_d2i_bio(it, b, x); + ret = ASN1_item_d2i_bio_ex(it, b, x, libctx, propq); BIO_free(b); return ret; } + +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) +{ + return ASN1_item_d2i_fp_ex(it, in, x, NULL, NULL); +} #endif #define HEADER_SIZE 8 @@ -100,6 +115,7 @@ uint32_t eos = 0; size_t off = 0; size_t len = 0; + size_t diff; const unsigned char *q; long slen; @@ -107,27 +123,28 @@ b = BUF_MEM_new(); if (b == NULL) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } - ERR_clear_error(); + ERR_set_mark(); for (;;) { - if (want >= (len - off)) { - want -= (len - off); + diff = len - off; + if (want >= diff) { + want -= diff; if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } i = BIO_read(in, &(b->data[len]), want); - if ((i < 0) && ((len - off) == 0)) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); + if (i < 0 && diff == 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } if (i > 0) { if (len + i < len) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); goto err; } len += i; @@ -137,15 +154,17 @@ p = (unsigned char *)&(b->data[off]); q = p; - inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off); + diff = len - off; + if (diff == 0) + goto err; + inf = ASN1_get_object(&q, &slen, &tag, &xclass, diff); if (inf & 0x80) { unsigned long e; - e = ERR_GET_REASON(ERR_peek_error()); + e = ERR_GET_REASON(ERR_peek_last_error()); if (e != ASN1_R_TOO_LONG) goto err; - else - ERR_clear_error(); /* clear error */ + ERR_pop_to_mark(); } i = q - p; /* header length */ off += i; /* end of data */ @@ -153,7 +172,7 @@ if (inf & 1) { /* no data body so go round again */ if (eos == UINT32_MAX) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG); goto err; } eos++; @@ -174,7 +193,7 @@ want -= (len - off); if (want > INT_MAX /* BIO_read takes an int length */ || len + want < len) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); goto err; } while (want > 0) { @@ -187,15 +206,14 @@ size_t chunk = want > chunk_max ? chunk_max : want; if (!BUF_MEM_grow_clean(b, len + chunk)) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } want -= chunk; while (chunk > 0) { i = BIO_read(in, &(b->data[len]), chunk); if (i <= 0) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, - ASN1_R_NOT_ENOUGH_DATA); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } /* @@ -210,7 +228,7 @@ } } if (off + slen < off) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); goto err; } off += slen; @@ -222,13 +240,14 @@ } if (off > INT_MAX) { - ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); goto err; } *pb = b; return off; err: + ERR_clear_last_mark(); BUF_MEM_free(b); return -1; } diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c --- a/crypto/asn1/a_digest.c +++ b/crypto/asn1/a_digest.c @@ -1,24 +1,29 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* We need to use some engine deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include #include "internal/cryptlib.h" +#include #include #include #include #include +#include "crypto/x509.h" -#ifndef NO_ASN1_OLD +#ifndef OPENSSL_NO_DEPRECATED_3_0 int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, unsigned char *md, unsigned int *len) @@ -28,11 +33,11 @@ inl = i2d(data, NULL); if (inl <= 0) { - ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); return 0; } if ((str = OPENSSL_malloc(inl)) == NULL) { - ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } p = str; @@ -48,20 +53,42 @@ #endif -int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, - unsigned char *md, unsigned int *len) +int ossl_asn1_item_digest_ex(const ASN1_ITEM *it, const EVP_MD *md, void *asn, + unsigned char *data, unsigned int *len, + OSSL_LIB_CTX *libctx, const char *propq) { - int i; + int i, ret = 0; unsigned char *str = NULL; + EVP_MD *fetched_md = (EVP_MD *)md; i = ASN1_item_i2d(asn, &str, it); - if (!str) + if (i < 0 || str == NULL) return 0; - if (!EVP_Digest(str, i, md, len, type, NULL)) { - OPENSSL_free(str); - return 0; + if (EVP_MD_get0_provider(md) == NULL) { +#if !defined(OPENSSL_NO_ENGINE) + ENGINE *tmpeng = ENGINE_get_digest_engine(EVP_MD_get_type(md)); + + if (tmpeng != NULL) + ENGINE_finish(tmpeng); + else +#endif + fetched_md = EVP_MD_fetch(libctx, EVP_MD_get0_name(md), propq); } + if (fetched_md == NULL) + goto err; + + ret = EVP_Digest(str, i, data, len, fetched_md, NULL); +err: OPENSSL_free(str); - return 1; + if (fetched_md != md) + EVP_MD_free(fetched_md); + return ret; } + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *md, void *asn, + unsigned char *data, unsigned int *len) +{ + return ossl_asn1_item_digest_ex(it, md, asn, data, len, NULL, NULL); +} + diff --git a/crypto/asn1/a_dup.c b/crypto/asn1/a_dup.c --- a/crypto/asn1/a_dup.c +++ b/crypto/asn1/a_dup.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -9,11 +9,11 @@ #include #include "internal/cryptlib.h" -#include +#include #ifndef NO_OLD_ASN1 -void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, const void *x) { unsigned char *b, *p; const unsigned char *p2; @@ -24,9 +24,12 @@ return NULL; i = i2d(x, NULL); + if (i <= 0) + return NULL; + b = OPENSSL_malloc(i + 10); if (b == NULL) { - ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } p = b; @@ -46,23 +49,49 @@ * decode. */ -void *ASN1_item_dup(const ASN1_ITEM *it, void *x) +void *ASN1_item_dup(const ASN1_ITEM *it, const void *x) { + ASN1_aux_cb *asn1_cb = NULL; unsigned char *b = NULL; const unsigned char *p; long i; - void *ret; + ASN1_VALUE *ret; + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; if (x == NULL) return NULL; + if (it->itype == ASN1_ITYPE_SEQUENCE || it->itype == ASN1_ITYPE_CHOICE + || it->itype == ASN1_ITYPE_NDEF_SEQUENCE) { + const ASN1_AUX *aux = it->funcs; + + asn1_cb = aux != NULL ? aux->asn1_cb : NULL; + } + + if (asn1_cb != NULL) { + if (!asn1_cb(ASN1_OP_DUP_PRE, (ASN1_VALUE **)&x, it, NULL) + || !asn1_cb(ASN1_OP_GET0_LIBCTX, (ASN1_VALUE **)&x, it, &libctx) + || !asn1_cb(ASN1_OP_GET0_PROPQ, (ASN1_VALUE **)&x, it, &propq)) + goto auxerr; + } + i = ASN1_item_i2d(x, &b, it); if (b == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } p = b; - ret = ASN1_item_d2i(NULL, &p, i, it); + ret = ASN1_item_d2i_ex(NULL, &p, i, it, libctx, propq); OPENSSL_free(b); + + if (asn1_cb != NULL + && !asn1_cb(ASN1_OP_DUP_POST, &ret, it, (void *)x)) + goto auxerr; + return ret; + + auxerr: + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_AUX_ERROR, "Type=%s", it->sname); + return NULL; } diff --git a/crypto/asn1/a_gentm.c b/crypto/asn1/a_gentm.c --- a/crypto/asn1/a_gentm.c +++ b/crypto/asn1/a_gentm.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -16,14 +16,18 @@ #include "internal/cryptlib.h" #include #include "asn1_local.h" +#include + +IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_GENERALIZEDTIME) /* This is the primary function used to parse ASN1_GENERALIZEDTIME */ -int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) +static int asn1_generalizedtime_to_tm(struct tm *tm, + const ASN1_GENERALIZEDTIME *d) { - /* wrapper around asn1_time_to_tm */ + /* wrapper around ossl_asn1_time_to_tm */ if (d->type != V_ASN1_GENERALIZEDTIME) return 0; - return asn1_time_to_tm(tm, d); + return ossl_asn1_time_to_tm(tm, d); } int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) @@ -71,7 +75,7 @@ return NULL; } - return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME); + return ossl_asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME); } int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) diff --git a/crypto/asn1/a_i2d_fp.c b/crypto/asn1/a_i2d_fp.c --- a/crypto/asn1/a_i2d_fp.c +++ b/crypto/asn1/a_i2d_fp.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -15,13 +15,13 @@ #ifndef NO_OLD_ASN1 # ifndef OPENSSL_NO_STDIO -int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, const void *x) { BIO *b; int ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return 0; } BIO_set_fp(b, out, BIO_NOCLOSE); @@ -31,7 +31,7 @@ } # endif -int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x) +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x) { char *b; unsigned char *p; @@ -43,7 +43,7 @@ b = OPENSSL_malloc(n); if (b == NULL) { - ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } @@ -68,13 +68,13 @@ #endif #ifndef OPENSSL_NO_STDIO -int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, const void *x) { BIO *b; int ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return 0; } BIO_set_fp(b, out, BIO_NOCLOSE); @@ -84,14 +84,14 @@ } #endif -int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, const void *x) { unsigned char *b = NULL; int i, j = 0, n, ret = 1; n = ASN1_item_i2d(x, &b, it); if (b == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } @@ -109,3 +109,21 @@ OPENSSL_free(b); return ret; } + +BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val) +{ + BIO *res; + + if (it == NULL || val == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((res = BIO_new(BIO_s_mem())) == NULL) + return NULL; + if (ASN1_item_i2d_bio(it, res, val) <= 0) { + BIO_free(res); + res = NULL; + } + return res; +} diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -79,8 +79,14 @@ unsigned int carry = pad & 1; /* Begin at the end of the encoding */ - dst += len; - src += len; + if (len != 0) { + /* + * if len == 0 then src/dst could be NULL, and this would be undefined + * behaviour. + */ + dst += len; + src += len; + } /* two's complement value: ~value + 1 */ while (len-- != 0) { *(--dst) = (unsigned char)(carry += *(--src) ^ pad); @@ -151,7 +157,7 @@ int neg, pad; /* Zero content length is illegal */ if (plen == 0) { - ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT); return 0; } neg = p[0] & 0x80; @@ -184,7 +190,7 @@ } /* reject illegal padding: first two octets MSB can't match */ if (pad && (neg == (p[1] & 0x80))) { - ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING); return 0; } @@ -198,7 +204,7 @@ return plen; } -int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) +int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) { return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp); } @@ -210,7 +216,7 @@ uint64_t r; if (blen > sizeof(*pr)) { - ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } if (b == NULL) @@ -262,14 +268,14 @@ * on ones'-complement system. */ *pr = (int64_t)(0 - r); } else { - ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); return 0; } } else { if (r <= INT64_MAX) { *pr = (int64_t)r; } else { - ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } } @@ -277,8 +283,8 @@ } /* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */ -ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, - long len) +ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long len) { ASN1_INTEGER *ret = NULL; size_t r; @@ -302,16 +308,18 @@ c2i_ibuf(ret->data, &neg, *pp, len); - if (neg) + if (neg != 0) ret->type |= V_ASN1_NEG; + else + ret->type &= ~V_ASN1_NEG; *pp += len; if (a != NULL) (*a) = ret; return ret; err: - ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); - if ((a == NULL) || (*a != ret)) + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (a == NULL || *a != ret) ASN1_INTEGER_free(ret); return NULL; } @@ -319,11 +327,11 @@ static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype) { if (a == NULL) { - ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); return 0; } if ((a->type & ~V_ASN1_NEG) != itype) { - ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE); return 0; } return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG); @@ -354,15 +362,15 @@ int itype) { if (a == NULL) { - ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); return 0; } if ((a->type & ~V_ASN1_NEG) != itype) { - ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE); return 0; } if (a->type & V_ASN1_NEG) { - ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE); return 0; } return asn1_get_uint64(pr, a->data, a->length); @@ -390,7 +398,7 @@ ASN1_INTEGER *ret = NULL; const unsigned char *p; unsigned char *s; - long len; + long len = 0; int inf, tag, xclass; int i; @@ -413,6 +421,10 @@ goto err; } + if (len < 0) { + i = ASN1_R_ILLEGAL_NEGATIVE_VALUE; + goto err; + } /* * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies * a missing NULL parameter. @@ -440,7 +452,7 @@ *pp = p; return ret; err: - ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i); + ERR_raise(ERR_LIB_ASN1, i); if ((a == NULL) || (*a != ret)) ASN1_INTEGER_free(ret); return NULL; @@ -460,7 +472,7 @@ } if (ret == NULL) { - ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } @@ -473,7 +485,7 @@ len = 1; if (ASN1_STRING_set(ret, NULL, len) == 0) { - ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } @@ -496,13 +508,13 @@ BIGNUM *ret; if ((ai->type & ~V_ASN1_NEG) != itype) { - ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE); return NULL; } ret = BN_bin2bn(ai->data, ai->length, bn); if (ret == NULL) { - ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BN_LIB); return NULL; } if (ai->type & V_ASN1_NEG) @@ -603,7 +615,8 @@ } /* Internal functions used by x_int64.c */ -int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len) +int ossl_c2i_uint64_int(uint64_t *ret, int *neg, + const unsigned char **pp, long len) { unsigned char buf[sizeof(uint64_t)]; size_t buflen; @@ -612,14 +625,14 @@ if (buflen == 0) return 0; if (buflen > sizeof(uint64_t)) { - ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } (void)c2i_ibuf(buf, neg, *pp, len); return asn1_get_uint64(ret, buf, buflen); } -int i2c_uint64_int(unsigned char *p, uint64_t r, int neg) +int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg) { unsigned char buf[sizeof(uint64_t)]; size_t off; diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,6 +10,7 @@ #include #include "crypto/ctype.h" #include "internal/cryptlib.h" +#include "internal/unicode.h" #include static int traverse_string(const unsigned char *p, int len, int inform, @@ -49,20 +50,20 @@ ASN1_STRING *dest; unsigned char *p; int nchar; - char strbuf[32]; int (*cpyfunc) (unsigned long, void *) = NULL; if (len == -1) len = strlen((const char *)in); if (!mask) mask = DIRSTRING_TYPE; + if (len < 0) + return -1; /* First do a string check and work out the number of characters */ switch (inform) { case MBSTRING_BMP: if (len & 1) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, - ASN1_R_INVALID_BMPSTRING_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH); return -1; } nchar = len >> 1; @@ -70,8 +71,7 @@ case MBSTRING_UNIV: if (len & 3) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, - ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); return -1; } nchar = len >> 2; @@ -82,7 +82,7 @@ /* This counts the characters and does utf8 syntax checking */ ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); if (ret < 0) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING); return -1; } break; @@ -92,27 +92,25 @@ break; default: - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT); return -1; } if ((minsize > 0) && (nchar < minsize)) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT); - BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize); - ERR_add_error_data(2, "minsize=", strbuf); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT, + "minsize=%ld", minsize); return -1; } if ((maxsize > 0) && (nchar > maxsize)) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG); - BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize); - ERR_add_error_data(2, "maxsize=", strbuf); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG, + "maxsize=%ld", maxsize); return -1; } /* Now work out minimal type (if any) */ if (traverse_string(in, len, inform, type_str, &mask) < 0) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS); return -1; } @@ -149,7 +147,7 @@ free_out = 1; dest = ASN1_STRING_type_new(str_type); if (dest == NULL) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } *out = dest; @@ -157,7 +155,7 @@ /* If both the same type just copy across */ if (inform == outform) { if (!ASN1_STRING_set(dest, in, len)) { - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } return str_type; @@ -189,7 +187,7 @@ if ((p = OPENSSL_malloc(outlen + 1)) == NULL) { if (free_out) ASN1_STRING_free(dest); - ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } dest->length = outlen; @@ -247,6 +245,9 @@ static int in_utf8(unsigned long value, void *arg) { int *nchar; + + if (!is_unicode_valid(value)) + return -2; nchar = arg; (*nchar)++; return 1; @@ -256,9 +257,13 @@ static int out_utf8(unsigned long value, void *arg) { - int *outlen; + int *outlen, len; + + len = UTF8_putc(NULL, -1, value); + if (len <= 0) + return len; outlen = arg; - *outlen += UTF8_putc(NULL, -1, value); + *outlen += len; return 1; } @@ -283,6 +288,8 @@ types &= ~B_ASN1_T61STRING; if ((types & B_ASN1_BMPSTRING) && (value > 0xffff)) types &= ~B_ASN1_BMPSTRING; + if ((types & B_ASN1_UTF8STRING) && !is_unicode_valid(value)) + types &= ~B_ASN1_UTF8STRING; if (!types) return -1; *((unsigned long *)arg) = types; diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -32,7 +32,7 @@ if (*pp == NULL) { if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) { - ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } } else { @@ -70,12 +70,12 @@ if ((c >= '0') && (c <= '2')) { first = c - '0'; } else { - ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_FIRST_NUM_TOO_LARGE); goto err; } if (num <= 0) { - ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_SECOND_NUMBER); goto err; } c = *(p++); @@ -84,7 +84,7 @@ if (num <= 0) break; if ((c != '.') && (c != ' ')) { - ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_SEPARATOR); goto err; } l = 0; @@ -97,7 +97,7 @@ if ((c == ' ') || (c == '.')) break; if (!ossl_isdigit(c)) { - ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_DIGIT); goto err; } if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { @@ -116,8 +116,7 @@ } if (len == 0) { if ((first < 2) && (l >= 40)) { - ASN1err(ASN1_F_A2D_ASN1_OBJECT, - ASN1_R_SECOND_NUMBER_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE); goto err; } if (use_bn) { @@ -136,8 +135,10 @@ OPENSSL_free(tmp); tmpsize = blsize + 32; tmp = OPENSSL_malloc(tmpsize); - if (tmp == NULL) + if (tmp == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; + } } while (blsize--) { BN_ULONG t = BN_div_word(bl, 0x80L); @@ -157,7 +158,7 @@ } if (out != NULL) { if (len + i > olen) { - ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BUFFER_TOO_SMALL); goto err; } while (--i > 0) @@ -191,8 +192,12 @@ return BIO_write(bp, "NULL", 4); i = i2t_ASN1_OBJECT(buf, sizeof(buf), a); if (i > (int)(sizeof(buf) - 1)) { + if (i > INT_MAX - 1) { /* catch an integer overflow */ + ERR_raise(ERR_LIB_ASN1, ASN1_R_LENGTH_TOO_LONG); + return -1; + } if ((p = OPENSSL_malloc(i + 1)) == NULL) { - ASN1err(ASN1_F_I2A_ASN1_OBJECT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } i2t_ASN1_OBJECT(p, i + 1, a); @@ -227,17 +232,17 @@ i = ASN1_R_EXPECTING_AN_OBJECT; goto err; } - ret = c2i_ASN1_OBJECT(a, &p, len); + ret = ossl_c2i_ASN1_OBJECT(a, &p, len); if (ret) *pp = p; return ret; err: - ASN1err(ASN1_F_D2I_ASN1_OBJECT, i); + ERR_raise(ERR_LIB_ASN1, i); return NULL; } -ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, - long len) +ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long len) { ASN1_OBJECT *ret = NULL, tobj; const unsigned char *p; @@ -251,7 +256,7 @@ */ if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || p[len - 1] & 0x80) { - ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING); return NULL; } /* Now 0 < len <= INT_MAX, so the cast is safe. */ @@ -281,7 +286,7 @@ } for (i = 0; i < length; i++, p++) { if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { - ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING); return NULL; } } @@ -329,7 +334,7 @@ *pp = p; return ret; err: - ASN1err(ASN1_F_C2I_ASN1_OBJECT, i); + ERR_raise(ERR_LIB_ASN1, i); if ((a == NULL) || (*a != ret)) ASN1_OBJECT_free(ret); return NULL; @@ -341,7 +346,7 @@ ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; @@ -353,9 +358,11 @@ if (a == NULL) return; if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { -#ifndef CONST_STRICT /* disable purely for compile-time strict - * const checking. Doing this on a "real" - * compile will cause memory leaks */ +#ifndef CONST_STRICT + /* + * Disable purely for compile-time strict const checking. Doing this + * on a "real" compile will cause memory leaks + */ OPENSSL_free((void*)a->sn); OPENSSL_free((void*)a->ln); #endif diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c --- a/crypto/asn1/a_octet.c +++ b/crypto/asn1/a_octet.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/a_print.c b/crypto/asn1/a_print.c --- a/crypto/asn1/a_print.c +++ b/crypto/asn1/a_print.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c --- a/crypto/asn1/a_sign.c +++ b/crypto/asn1/a_sign.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -18,10 +18,11 @@ #include #include #include +#include #include "crypto/asn1.h" #include "crypto/evp.h" -#ifndef NO_ASN1_OLD +#ifndef OPENSSL_NO_DEPRECATED_3_0 int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey, @@ -34,7 +35,7 @@ X509_ALGOR *a; if (ctx == NULL) { - ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } for (i = 0; i < 2; i++) { @@ -61,27 +62,27 @@ ASN1_OBJECT_free(a->algorithm); a->algorithm = OBJ_nid2obj(type->pkey_type); if (a->algorithm == NULL) { - ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_OBJECT_TYPE); goto err; } if (a->algorithm->length == 0) { - ASN1err(ASN1_F_ASN1_SIGN, - ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); + ERR_raise(ERR_LIB_ASN1, + ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); goto err; } } inl = i2d(data, NULL); if (inl <= 0) { - ASN1err(ASN1_F_ASN1_SIGN, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); goto err; } inll = (size_t)inl; buf_in = OPENSSL_malloc(inll); - outll = outl = EVP_PKEY_size(pkey); + outll = outl = EVP_PKEY_get_size(pkey); buf_out = OPENSSL_malloc(outll); if (buf_in == NULL || buf_out == NULL) { outl = 0; - ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } p = buf_in; @@ -92,7 +93,7 @@ || !EVP_SignFinal(ctx, (unsigned char *)buf_out, (unsigned int *)&outl, pkey)) { outl = 0; - ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } OPENSSL_free(signature->data); @@ -114,54 +115,104 @@ #endif -int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, - X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn, - EVP_PKEY *pkey, const EVP_MD *type) +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, const void *data, + EVP_PKEY *pkey, const EVP_MD *md) { - int rv; - EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + return ASN1_item_sign_ex(it, algor1, algor2, signature, data, NULL, pkey, + md, NULL, NULL); +} + +int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + const void *data, const ASN1_OCTET_STRING *id, + EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx, + const char *propq) +{ + int rv = 0; + EVP_MD_CTX *ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq); if (ctx == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE); - return 0; - } - if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) { - EVP_MD_CTX_free(ctx); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } + /* We can use the non _ex variant here since the pkey is already setup */ + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, pkey)) + goto err; - rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx); + rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, data, ctx); + err: + EVP_PKEY_CTX_free(EVP_MD_CTX_get_pkey_ctx(ctx)); EVP_MD_CTX_free(ctx); return rv; } -int ASN1_item_sign_ctx(const ASN1_ITEM *it, - X509_ALGOR *algor1, X509_ALGOR *algor2, - ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) +int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + const void *data, EVP_MD_CTX *ctx) { - const EVP_MD *type; + const EVP_MD *md; EVP_PKEY *pkey; unsigned char *buf_in = NULL, *buf_out = NULL; size_t inl = 0, outl = 0, outll = 0; int signid, paramtype, buf_len = 0; - int rv; + int rv, pkey_id; - type = EVP_MD_CTX_md(ctx); - pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); + md = EVP_MD_CTX_get0_md(ctx); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx)); if (pkey == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); goto err; } if (pkey->ameth == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); - goto err; - } + EVP_PKEY_CTX *pctx = EVP_MD_CTX_get_pkey_ctx(ctx); + OSSL_PARAM params[2]; + unsigned char aid[128]; + size_t aid_len = 0; + + if (pctx == NULL + || !EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); + goto err; + } - if (pkey->ameth->item_sign) { - rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature); + params[0] = + OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, + aid, sizeof(aid)); + params[1] = OSSL_PARAM_construct_end(); + + if (EVP_PKEY_CTX_get_params(pctx, params) <= 0) + goto err; + + if ((aid_len = params[0].return_size) == 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + goto err; + } + + if (algor1 != NULL) { + const unsigned char *pp = aid; + + if (d2i_X509_ALGOR(&algor1, &pp, aid_len) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (algor2 != NULL) { + const unsigned char *pp = aid; + + if (d2i_X509_ALGOR(&algor2, &pp, aid_len) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + rv = 3; + } else if (pkey->ameth->item_sign) { + rv = pkey->ameth->item_sign(ctx, it, data, algor1, algor2, signature); if (rv == 1) outl = signature->length; /*- @@ -172,7 +223,7 @@ * 3: ASN1 method sets algorithm identifiers: just sign. */ if (rv <= 0) - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); if (rv <= 1) goto err; } else { @@ -180,15 +231,19 @@ } if (rv == 2) { - if (type == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); + if (md == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); goto err; } - if (!OBJ_find_sigid_by_algs(&signid, - EVP_MD_nid(type), - pkey->ameth->pkey_id)) { - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, - ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + + pkey_id = +#ifndef OPENSSL_NO_SM2 + EVP_PKEY_get_id(pkey) == NID_sm2 ? NID_sm2 : +#endif + pkey->ameth->pkey_id; + + if (!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(md), pkey_id)) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); goto err; } @@ -204,24 +259,29 @@ } - buf_len = ASN1_item_i2d(asn, &buf_in, it); + buf_len = ASN1_item_i2d(data, &buf_in, it); if (buf_len <= 0) { outl = 0; - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); goto err; } inl = buf_len; - outll = outl = EVP_PKEY_size(pkey); + if (!EVP_DigestSign(ctx, NULL, &outll, buf_in, inl)) { + outl = 0; + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); + goto err; + } + outl = outll; buf_out = OPENSSL_malloc(outll); if (buf_in == NULL || buf_out == NULL) { outl = 0; - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) { outl = 0; - ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } OPENSSL_free(signature->data); diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -1,7 +1,7 @@ /* * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -32,7 +32,7 @@ ASN1_STRFLGS_ESC_MSB) /* - * Three IO functions for sending data to memory, a BIO and and a FILE + * Three IO functions for sending data to memory, a BIO and a FILE * pointer. */ static int send_bio_chars(void *arg, const void *buf, int len) @@ -152,13 +152,13 @@ switch (charwidth) { case 4: if (buflen & 3) { - ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); return -1; } break; case 2: if (buflen & 1) { - ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH); return -1; } break; @@ -283,7 +283,7 @@ if (der_len <= 0) return -1; if ((der_buf = OPENSSL_malloc(der_len)) == NULL) { - ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } p = der_buf; diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c --- a/crypto/asn1/a_strnid.c +++ b/crypto/asn1/a_strnid.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -51,7 +51,7 @@ char *end; if (strncmp(p, "MASK:", 5) == 0) { - if (!p[5]) + if (p[5] == '\0') return 0; mask = strtoul(p + 5, &end, 0); if (*end) @@ -129,6 +129,9 @@ int idx; ASN1_STRING_TABLE fnd; + /* "stable" can be impacted by config, so load the config file first */ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); + fnd.nid = nid; if (stable) { idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); @@ -157,7 +160,7 @@ if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC) return tmp; if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) { - ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { @@ -187,7 +190,7 @@ tmp = stable_get(nid); if (tmp == NULL) { - ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } if (minsize >= 0) diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -16,6 +16,7 @@ #include #include +#include "crypto/asn1.h" #include "crypto/ctype.h" #include "internal/cryptlib.h" #include @@ -24,6 +25,7 @@ IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) +IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_TIME) static int is_utc(const int year) { @@ -71,7 +73,7 @@ tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7; } -int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) +int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) { static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; @@ -128,14 +130,14 @@ i++; break; } - if (!ascii_isdigit(a[o])) + if (!ossl_ascii_isdigit(a[o])) goto err; n = a[o] - num_zero; /* incomplete 2-digital number */ if (++o == l) goto err; - if (!ascii_isdigit(a[o])) + if (!ossl_ascii_isdigit(a[o])) goto err; n = (n * 10) + a[o] - num_zero; /* no more bytes to read, but we haven't seen time-zone yet */ @@ -196,7 +198,7 @@ if (++o == l) goto err; i = o; - while ((o < l) && ascii_isdigit(a[o])) + while ((o < l) && ossl_ascii_isdigit(a[o])) o++; /* Must have at least one digit after decimal point */ if (i == o) @@ -227,11 +229,11 @@ if (o + 4 != l) goto err; for (i = end; i < end + 2; i++) { - if (!ascii_isdigit(a[o])) + if (!ossl_ascii_isdigit(a[o])) goto err; n = a[o] - num_zero; o++; - if (!ascii_isdigit(a[o])) + if (!ossl_ascii_isdigit(a[o])) goto err; n = (n * 10) + a[o] - num_zero; i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i; @@ -262,7 +264,7 @@ return 0; } -ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type) +ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type) { char* p; ASN1_TIME *tmps = NULL; @@ -327,14 +329,14 @@ ts = OPENSSL_gmtime(&t, &data); if (ts == NULL) { - ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME); return NULL; } if (offset_day || offset_sec) { if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) return NULL; } - return asn1_time_from_tm(s, ts, V_ASN1_UNDEF); + return ossl_asn1_time_from_tm(s, ts, V_ASN1_UNDEF); } int ASN1_TIME_check(const ASN1_TIME *t) @@ -359,7 +361,7 @@ if (out != NULL) ret = *out; - ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME); + ret = ossl_asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME); if (out != NULL && ret != NULL) *out = ret; @@ -408,7 +410,7 @@ */ if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) { - if (!asn1_time_to_tm(&tm, &t)) + if (!ossl_asn1_time_to_tm(&tm, &t)) goto out; if (is_utc(tm.tm_year)) { t.length -= 2; @@ -418,8 +420,10 @@ * new t.data would be freed after ASN1_STRING_copy is done. */ t.data = OPENSSL_zalloc(t.length + 1); - if (t.data == NULL) + if (t.data == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto out; + } memcpy(t.data, str + 2, t.length); t.type = V_ASN1_UTCTIME; } @@ -446,7 +450,7 @@ return 0; } - return asn1_time_to_tm(tm, s); + return ossl_asn1_time_to_tm(tm, s); } int ASN1_TIME_diff(int *pday, int *psec, @@ -466,17 +470,31 @@ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +/* prints the time with the default date format (RFC 822) */ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) +{ + return ASN1_TIME_print_ex(bp, tm, ASN1_DTFLGS_RFC822); +} + +/* returns 1 on success, 0 on BIO write error or parse failure */ +int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags) +{ + return ossl_asn1_time_print_ex(bp, tm, flags) > 0; +} + + +/* prints the time with the date format of ISO 8601 */ +/* returns 0 on BIO write error, else -1 in case of parse failure, else 1 */ +int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags) { char *v; int gmt = 0, l; struct tm stm; const char upper_z = 0x5A, period = 0x2E; - if (!asn1_time_to_tm(&stm, tm)) { - /* asn1_time_to_tm will check the time type */ - goto err; - } + /* ossl_asn1_time_to_tm will check the time type */ + if (!ossl_asn1_time_to_tm(&stm, tm)) + return BIO_write(bp, "Bad time value", 14) ? -1 : 0; l = tm->length; v = (char *)tm->data; @@ -494,23 +512,38 @@ if (tm->length > 15 && v[14] == period) { f = &v[14]; f_len = 1; - while (14 + f_len < l && ascii_isdigit(f[f_len])) + while (14 + f_len < l && ossl_ascii_isdigit(f[f_len])) ++f_len; } - return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", + if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) { + return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s", + stm.tm_year + 1900, stm.tm_mon + 1, + stm.tm_mday, stm.tm_hour, + stm.tm_min, stm.tm_sec, f_len, f, + (gmt ? "Z" : "")) > 0; + } + else { + return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900, (gmt ? " GMT" : "")) > 0; + } } else { - return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", + if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) { + return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s", + stm.tm_year + 1900, stm.tm_mon + 1, + stm.tm_mday, stm.tm_hour, + stm.tm_min, stm.tm_sec, + (gmt ? "Z" : "")) > 0; + } + else { + return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec, stm.tm_year + 1900, (gmt ? " GMT" : "")) > 0; + } } - err: - BIO_write(bp, "Bad time value", 14); - return 0; } int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t) @@ -541,7 +574,7 @@ if (!ASN1_TIME_to_tm(t, &tm)) return 0; - return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL; + return ossl_asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL; } int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b) diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c --- a/crypto/asn1/a_type.c +++ b/crypto/asn1/a_type.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -29,7 +29,7 @@ && a->type != V_ASN1_NULL && a->value.ptr != NULL) { ASN1_TYPE **tmp_a = &a; - asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0); + ossl_asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0); } a->type = type; if (type == V_ASN1_BOOLEAN) diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c --- a/crypto/asn1/a_utctm.c +++ b/crypto/asn1/a_utctm.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -12,19 +12,22 @@ #include "internal/cryptlib.h" #include #include "asn1_local.h" +#include + +IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_UTCTIME) /* This is the primary function used to parse ASN1_UTCTIME */ -int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) +int ossl_asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) { - /* wrapper around ans1_time_to_tm */ + /* wrapper around ossl_asn1_time_to_tm */ if (d->type != V_ASN1_UTCTIME) return 0; - return asn1_time_to_tm(tm, d); + return ossl_asn1_time_to_tm(tm, d); } int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) { - return asn1_utctime_to_tm(NULL, d); + return ossl_asn1_utctime_to_tm(NULL, d); } /* Sets the string via simple copy without cleaning it up */ @@ -66,7 +69,7 @@ return NULL; } - return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME); + return ossl_asn1_time_from_tm(s, ts, V_ASN1_UTCTIME); } int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) @@ -74,7 +77,7 @@ struct tm stm, ttm; int day, sec; - if (!asn1_utctime_to_tm(&stm, s)) + if (!ossl_asn1_utctime_to_tm(&stm, s)) return -2; if (OPENSSL_gmtime(&t, &ttm) == NULL) diff --git a/crypto/asn1/a_utf8.c b/crypto/asn1/a_utf8.c --- a/crypto/asn1/a_utf8.c +++ b/crypto/asn1/a_utf8.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -9,6 +9,7 @@ #include #include "internal/cryptlib.h" +#include "internal/unicode.h" #include /* UTF8 utilities */ @@ -58,6 +59,8 @@ value |= *p++ & 0x3f; if (value < 0x800) return -4; + if (is_unicode_surrogate(value)) + return -2; ret = 3; } else if ((*p & 0xf8) == 0xf0) { if (len < 4) @@ -73,40 +76,6 @@ if (value < 0x10000) return -4; ret = 4; - } else if ((*p & 0xfc) == 0xf8) { - if (len < 5) - return -1; - if (((p[1] & 0xc0) != 0x80) - || ((p[2] & 0xc0) != 0x80) - || ((p[3] & 0xc0) != 0x80) - || ((p[4] & 0xc0) != 0x80)) - return -3; - value = ((unsigned long)(*p++ & 0x3)) << 24; - value |= ((unsigned long)(*p++ & 0x3f)) << 18; - value |= ((unsigned long)(*p++ & 0x3f)) << 12; - value |= (*p++ & 0x3f) << 6; - value |= *p++ & 0x3f; - if (value < 0x200000) - return -4; - ret = 5; - } else if ((*p & 0xfe) == 0xfc) { - if (len < 6) - return -1; - if (((p[1] & 0xc0) != 0x80) - || ((p[2] & 0xc0) != 0x80) - || ((p[3] & 0xc0) != 0x80) - || ((p[4] & 0xc0) != 0x80) - || ((p[5] & 0xc0) != 0x80)) - return -3; - value = ((unsigned long)(*p++ & 0x1)) << 30; - value |= ((unsigned long)(*p++ & 0x3f)) << 24; - value |= ((unsigned long)(*p++ & 0x3f)) << 18; - value |= ((unsigned long)(*p++ & 0x3f)) << 12; - value |= (*p++ & 0x3f) << 6; - value |= *p++ & 0x3f; - if (value < 0x4000000) - return -4; - ret = 6; } else return -2; *val = value; @@ -116,15 +85,15 @@ /* * This takes a character 'value' and writes the UTF8 encoded value in 'str' * where 'str' is a buffer containing 'len' characters. Returns the number of - * characters written or -1 if 'len' is too small. 'str' can be set to NULL - * in which case it just returns the number of characters. It will need at - * most 6 characters. + * characters written, -1 if 'len' is too small or -2 if 'value' is out of + * range. 'str' can be set to NULL in which case it just returns the number of + * characters. It will need at most 4 characters. */ int UTF8_putc(unsigned char *str, int len, unsigned long value) { if (!str) - len = 6; /* Maximum we will need */ + len = 4; /* Maximum we will need */ else if (len <= 0) return -1; if (value < 0x80) { @@ -142,6 +111,8 @@ return 2; } if (value < 0x10000) { + if (is_unicode_surrogate(value)) + return -2; if (len < 3) return -1; if (str) { @@ -151,7 +122,7 @@ } return 3; } - if (value < 0x200000) { + if (value < UNICODE_LIMIT) { if (len < 4) return -1; if (str) { @@ -162,27 +133,5 @@ } return 4; } - if (value < 0x4000000) { - if (len < 5) - return -1; - if (str) { - *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); - *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 5; - } - if (len < 6) - return -1; - if (str) { - *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); - *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 6; + return -2; } diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/a_verify.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -20,8 +20,9 @@ #include #include "crypto/asn1.h" #include "crypto/evp.h" +#include "crypto/rsa.h" -#ifndef NO_ASN1_OLD +#ifndef OPENSSL_NO_DEPRECATED_3_0 int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey) @@ -32,29 +33,29 @@ int ret = -1, i, inl; if (ctx == NULL) { - ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } i = OBJ_obj2nid(a->algorithm); type = EVP_get_digestbyname(OBJ_nid2sn(i)); if (type == NULL) { - ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); goto err; } if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { - ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); goto err; } inl = i2d(data, NULL); if (inl <= 0) { - ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); goto err; } buf_in = OPENSSL_malloc((unsigned int)inl); if (buf_in == NULL) { - ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } p = buf_in; @@ -66,14 +67,14 @@ OPENSSL_clear_free(buf_in, (unsigned int)inl); if (!ret) { - ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } ret = -1; if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data, (unsigned int)signature->length, pkey) <= 0) { - ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); ret = 0; goto err; } @@ -85,81 +86,127 @@ #endif -int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, - ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) +int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg, + const ASN1_BIT_STRING *signature, const void *data, + EVP_PKEY *pkey) { - EVP_MD_CTX *ctx = NULL; + return ASN1_item_verify_ex(it, alg, signature, data, NULL, pkey, NULL, NULL); +} + +int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg, + const ASN1_BIT_STRING *signature, const void *data, + const ASN1_OCTET_STRING *id, EVP_PKEY *pkey, + OSSL_LIB_CTX *libctx, const char *propq) +{ + EVP_MD_CTX *ctx; + int rv = -1; + + if ((ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq)) != NULL) { + rv = ASN1_item_verify_ctx(it, alg, signature, data, ctx); + EVP_PKEY_CTX_free(EVP_MD_CTX_get_pkey_ctx(ctx)); + EVP_MD_CTX_free(ctx); + } + return rv; +} + +int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, + const ASN1_BIT_STRING *signature, const void *data, + EVP_MD_CTX *ctx) +{ + EVP_PKEY *pkey; unsigned char *buf_in = NULL; int ret = -1, inl = 0; int mdnid, pknid; size_t inll = 0; - if (!pkey) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx)); + + if (pkey == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); return -1; } if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); return -1; } - ctx = EVP_MD_CTX_new(); - if (ctx == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE); - goto err; - } - /* Convert signature OID into digest and public key OIDs */ - if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); goto err; } - if (mdnid == NID_undef) { - if (!pkey->ameth || !pkey->ameth->item_verify) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, - ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); + + if (mdnid == NID_undef && evp_pkey_is_legacy(pkey)) { + if (pkey->ameth == NULL || pkey->ameth->item_verify == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); goto err; } - ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey); + ret = pkey->ameth->item_verify(ctx, it, data, alg, signature, pkey); /* - * Return value of 2 means carry on, anything else means we exit - * straight away: either a fatal error of the underlying verification - * routine handles all verification. + * Return values meaning: + * <=0: error. + * 1: method does everything. + * 2: carry on as normal, method has called EVP_DigestVerifyInit() */ - if (ret != 2) + if (ret <= 0) + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); + if (ret <= 1) goto err; - ret = -1; } else { - const EVP_MD *type = EVP_get_digestbynid(mdnid); - - if (type == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, - ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); - goto err; - } - - /* Check public key OID matches public key type */ - if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE); - goto err; - } + const EVP_MD *type = NULL; - if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); - ret = 0; - goto err; + /* + * We don't yet have the ability for providers to be able to handle + * X509_ALGOR style parameters. Fortunately the only one that needs this + * so far is RSA-PSS, so we just special case this for now. In some + * future version of OpenSSL we should push this to the provider. + */ + if (mdnid == NID_undef && pknid == EVP_PKEY_RSA_PSS) { + if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE); + goto err; + } + /* This function also calls EVP_DigestVerifyInit */ + if (ossl_rsa_pss_to_ctx(ctx, NULL, alg, pkey) <= 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + /* Check public key OID matches public key type */ + if (!EVP_PKEY_is_a(pkey, OBJ_nid2sn(pknid))) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE); + goto err; + } + + if (mdnid != NID_undef) { + type = EVP_get_digestbynid(mdnid); + if (type == NULL) { + ERR_raise(ERR_LIB_ASN1, + ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + goto err; + } + } + + /* + * Note that some algorithms (notably Ed25519 and Ed448) may allow + * a NULL digest value. + */ + if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); + ret = 0; + goto err; + } } - } - inl = ASN1_item_i2d(asn, &buf_in, it); + inl = ASN1_item_i2d(data, &buf_in, it); if (inl <= 0) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); goto err; } if (buf_in == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } inll = inl; @@ -167,12 +214,11 @@ ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length, buf_in, inl); if (ret <= 0) { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } ret = 1; err: OPENSSL_clear_free(buf_in, inll); - EVP_MD_CTX_free(ctx); return ret; } diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c @@ -1,13 +1,15 @@ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ -#include "e_os.h" /* for strncasecmp */ +/* We need to use some engine deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include "internal/cryptlib.h" #include #include @@ -56,6 +58,7 @@ { EVP_PKEY_ASN1_METHOD tmp; const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret; + tmp.pkey_id = type; if (app_methods) { int idx; @@ -64,7 +67,7 @@ return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); } ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods)); - if (!ret || !*ret) + if (ret == NULL || *ret == NULL) return NULL; return *ret; } @@ -130,7 +133,7 @@ if (ameth->pkey_flags & ASN1_PKEY_ALIAS) continue; if ((int)strlen(ameth->pem_str) == len - && strncasecmp(ameth->pem_str, str, len) == 0) + && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0) return ameth; } return NULL; @@ -152,7 +155,7 @@ && (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0) || (ameth->pem_str != NULL && (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) { - EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, ERR_R_PASSED_INVALID_ARGUMENT); + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } @@ -164,8 +167,8 @@ tmp.pkey_id = ameth->pkey_id; if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) { - EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, - EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED); + ERR_raise(ERR_LIB_EVP, + EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED); return 0; } @@ -219,8 +222,10 @@ { EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth)); - if (ameth == NULL) + if (ameth == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; + } ameth->pkey_id = id; ameth->pkey_base_id = id; @@ -228,13 +233,13 @@ if (info) { ameth->info = OPENSSL_strdup(info); - if (!ameth->info) + if (ameth->info == NULL) goto err; } if (pem_str) { ameth->pem_str = OPENSSL_strdup(pem_str); - if (!ameth->pem_str) + if (ameth->pem_str == NULL) goto err; } @@ -242,46 +247,27 @@ err: EVP_PKEY_asn1_free(ameth); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; - } void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src) { - - dst->pub_decode = src->pub_decode; - dst->pub_encode = src->pub_encode; - dst->pub_cmp = src->pub_cmp; - dst->pub_print = src->pub_print; - - dst->priv_decode = src->priv_decode; - dst->priv_encode = src->priv_encode; - dst->priv_print = src->priv_print; - - dst->old_priv_encode = src->old_priv_encode; - dst->old_priv_decode = src->old_priv_decode; - - dst->pkey_size = src->pkey_size; - dst->pkey_bits = src->pkey_bits; - - dst->param_decode = src->param_decode; - dst->param_encode = src->param_encode; - dst->param_missing = src->param_missing; - dst->param_copy = src->param_copy; - dst->param_cmp = src->param_cmp; - dst->param_print = src->param_print; - - dst->pkey_free = src->pkey_free; - dst->pkey_ctrl = src->pkey_ctrl; - - dst->item_sign = src->item_sign; - dst->item_verify = src->item_verify; - - dst->siginf_set = src->siginf_set; - - dst->pkey_check = src->pkey_check; - + int pkey_id = dst->pkey_id; + int pkey_base_id = dst->pkey_base_id; + unsigned long pkey_flags = dst->pkey_flags; + char *pem_str = dst->pem_str; + char *info = dst->info; + + *dst = *src; + + /* We only copy the function pointers so restore the other values */ + dst->pkey_id = pkey_id; + dst->pkey_base_id = pkey_base_id; + dst->pkey_flags = pkey_flags; + dst->pem_str = pem_str; + dst->info = info; } void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth) @@ -295,7 +281,7 @@ void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, int (*pub_decode) (EVP_PKEY *pk, - X509_PUBKEY *pub), + const X509_PUBKEY *pub), int (*pub_encode) (X509_PUBKEY *pub, const EVP_PKEY *pk), int (*pub_cmp) (const EVP_PKEY *a, @@ -376,13 +362,13 @@ void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth, int (*item_verify) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, - void *asn, - X509_ALGOR *a, - ASN1_BIT_STRING *sig, + const void *data, + const X509_ALGOR *a, + const ASN1_BIT_STRING *sig, EVP_PKEY *pkey), int (*item_sign) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, - void *asn, + const void *data, X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *sig)) diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -1,8 +1,8 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,150 +10,10 @@ #include #include +#include "crypto/asn1err.h" #ifndef OPENSSL_NO_ERR -static const ERR_STRING_DATA ASN1_str_functs[] = { - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2D_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_STRING, 0), "a2i_ASN1_STRING"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_APPEND_EXP, 0), "append_exp"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIO_INIT, 0), "asn1_bio_init"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_SET_BIT, 0), - "ASN1_BIT_STRING_set_bit"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CB, 0), "asn1_cb"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, 0), "asn1_check_tlen"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_COLLECT, 0), "asn1_collect"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_EX_PRIMITIVE, 0), - "asn1_d2i_ex_primitive"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_FP, 0), "ASN1_d2i_fp"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, 0), "asn1_d2i_read_bio"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DIGEST, 0), "ASN1_digest"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_ADB, 0), "asn1_do_adb"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_LOCK, 0), "asn1_do_lock"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DUP, 0), "ASN1_dup"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENC_SAVE, 0), "asn1_enc_save"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_EX_C2I, 0), "asn1_ex_c2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_FIND_END, 0), "asn1_find_end"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_ADJ, 0), - "ASN1_GENERALIZEDTIME_adj"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERATE_V3, 0), "ASN1_generate_v3"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_INT64, 0), "asn1_get_int64"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, 0), "ASN1_get_object"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_UINT64, 0), "asn1_get_uint64"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_BIO, 0), "ASN1_i2d_bio"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_FP, 0), "ASN1_i2d_fp"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_D2I_FP, 0), "ASN1_item_d2i_fp"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_DUP, 0), "ASN1_item_dup"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_D2I, 0), - "asn1_item_embed_d2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_NEW, 0), - "asn1_item_embed_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EX_I2D, 0), "ASN1_item_ex_i2d"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_FLAGS_I2D, 0), - "asn1_item_flags_i2d"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_BIO, 0), "ASN1_item_i2d_bio"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_FP, 0), "ASN1_item_i2d_fp"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_PACK, 0), "ASN1_item_pack"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN, 0), "ASN1_item_sign"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN_CTX, 0), - "ASN1_item_sign_ctx"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_UNPACK, 0), "ASN1_item_unpack"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_VERIFY, 0), "ASN1_item_verify"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_MBSTRING_NCOPY, 0), - "ASN1_mbstring_ncopy"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_NEW, 0), "ASN1_OBJECT_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OUTPUT_DATA, 0), "asn1_output_data"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_NEW, 0), "ASN1_PCTX_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PRIMITIVE_NEW, 0), - "asn1_primitive_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SCTX_NEW, 0), "ASN1_SCTX_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SIGN, 0), "ASN1_sign"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STR2TYPE, 0), "asn1_str2type"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_INT64, 0), - "asn1_string_get_int64"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_UINT64, 0), - "asn1_string_get_uint64"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_SET, 0), "ASN1_STRING_set"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_ADD, 0), - "ASN1_STRING_TABLE_add"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TO_BN, 0), "asn1_string_to_bn"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TYPE_NEW, 0), - "ASN1_STRING_type_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_EX_D2I, 0), - "asn1_template_ex_d2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NEW, 0), "asn1_template_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 0), - "asn1_template_noexp_d2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_ADJ, 0), "ASN1_TIME_adj"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, 0), - "ASN1_TYPE_get_int_octetstring"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_OCTETSTRING, 0), - "ASN1_TYPE_get_octetstring"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_ADJ, 0), "ASN1_UTCTIME_adj"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_VERIFY, 0), "ASN1_verify"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_READ_ASN1, 0), "b64_read_asn1"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_WRITE_ASN1, 0), "B64_write_ASN1"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_NEW_NDEF, 0), "BIO_new_NDEF"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BITSTR_CB, 0), "bitstr_cb"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_TO_ASN1_STRING, 0), "bn_to_asn1_string"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_BIT_STRING, 0), - "c2i_ASN1_BIT_STRING"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_IBUF, 0), "c2i_ibuf"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_UINT64_INT, 0), "c2i_uint64_int"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_COLLECT_DATA, 0), "collect_data"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_AUTOPRIVATEKEY, 0), - "d2i_AutoPrivateKey"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0), - "i2d_ASN1_bio_stream"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PUBLICKEY, 0), "i2d_PublicKey"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_LONG_C2I, 0), "long_c2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_PREFIX, 0), "ndef_prefix"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_SUFFIX, 0), "ndef_suffix"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_OID_MODULE_INIT, 0), "oid_module_init"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PARSE_TAGGING, 0), "parse_tagging"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_IV, 0), "PKCS5_pbe2_set_iv"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_SCRYPT, 0), - "PKCS5_pbe2_set_scrypt"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET, 0), "PKCS5_pbe_set"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET0_ALGOR, 0), - "PKCS5_pbe_set0_algor"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBKDF2_SET, 0), "PKCS5_pbkdf2_set"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_SCRYPT_SET, 0), "pkcs5_scrypt_set"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_READ_ASN1, 0), "SMIME_read_ASN1"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_TEXT, 0), "SMIME_text"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STABLE_GET, 0), "stable_get"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STBL_MODULE_INIT, 0), "stbl_module_init"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_C2I, 0), "uint32_c2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_NEW, 0), "uint32_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_C2I, 0), "uint64_c2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_NEW, 0), "uint64_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_CRL_ADD0_REVOKED, 0), - "X509_CRL_add0_revoked"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_INFO_NEW, 0), "X509_INFO_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_ENCODE, 0), "x509_name_encode"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_D2I, 0), "x509_name_ex_d2i"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_NEW, 0), "x509_name_ex_new"}, - {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_PKEY_NEW, 0), "X509_PKEY_new"}, - {0, NULL} -}; - static const ERR_STRING_DATA ASN1_str_reasons[] = { {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "adding object"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"}, @@ -249,6 +109,7 @@ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING), "invalid utf8string"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_VALUE), "invalid value"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LENGTH_TOO_LONG), "length too long"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "list error"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE), "mime no content type"}, @@ -313,6 +174,7 @@ {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), "universalstring is wrong length"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_DIGEST), "unknown digest"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), "unknown message digest algorithm"}, @@ -340,13 +202,11 @@ #endif -int ERR_load_ASN1_strings(void) +int ossl_err_load_ASN1_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) { - ERR_load_strings_const(ASN1_str_functs); + if (ERR_reason_error_string(ASN1_str_reasons[0].error) == NULL) ERR_load_strings_const(ASN1_str_reasons); - } #endif return 1; } diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c --- a/crypto/asn1/asn1_gen.c +++ b/crypto/asn1/asn1_gen.c @@ -1,7 +1,7 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -91,7 +91,7 @@ int err = 0; ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err); if (err) - ASN1err(ASN1_F_ASN1_GENERATE_V3, err); + ERR_raise(ERR_LIB_ASN1, err); return ret; } @@ -263,8 +263,7 @@ utype = asn1_str2tag(elem, len); if (utype == -1) { - ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG); - ERR_add_error_data(2, "tag=", elem); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_UNKNOWN_TAG, "tag=%s", elem); return -1; } @@ -274,7 +273,7 @@ arg->str = vstart; /* If no value and not end of string, error */ if (!vstart && elem[len]) { - ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_VALUE); return -1; } return 0; @@ -285,7 +284,7 @@ case ASN1_GEN_FLAG_IMP: /* Check for illegal multiple IMPLICIT tagging */ if (arg->imp_tag != -1) { - ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING); return -1; } if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) @@ -322,7 +321,7 @@ case ASN1_GEN_FLAG_FORMAT: if (!vstart) { - ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT); return -1; } if (strncmp(vstart, "ASCII", 5) == 0) @@ -334,7 +333,7 @@ else if (strncmp(vstart, "BITLIST", 7) == 0) arg->format = ASN1_GEN_FORMAT_BITLIST; else { - ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT); return -1; } break; @@ -347,7 +346,6 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) { - char erch[2]; long tag_num; char *eptr; if (!vstart) @@ -357,7 +355,7 @@ if (eptr && *eptr && (eptr > vstart + vlen)) return 0; if (tag_num < 0) { - ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER); return 0; } *ptag = tag_num; @@ -386,10 +384,8 @@ break; default: - erch[0] = *eptr; - erch[1] = 0; - ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER); - ERR_add_error_data(2, "Char=", erch); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MODIFIER, + "Char=%c", *eptr); return 0; } @@ -469,12 +465,12 @@ tag_exp_type *exp_tmp; /* Can only have IMPLICIT if permitted */ if ((arg->imp_tag != -1) && !imp_ok) { - ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG); return 0; } if (arg->exp_count == ASN1_FLAG_EXP_MAX) { - ASN1err(ASN1_F_APPEND_EXP, ASN1_R_DEPTH_EXCEEDED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_DEPTH_EXCEEDED); return 0; } @@ -568,7 +564,8 @@ tntmp = tnst; for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) { - if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0)) + if ((len == tntmp->len) + && (OPENSSL_strncasecmp(tntmp->strnam, tagstr, len) == 0)) return tntmp->tag; } @@ -584,7 +581,7 @@ int no_unused = 1; if ((atmp = ASN1_TYPE_new()) == NULL) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } @@ -595,21 +592,21 @@ case V_ASN1_NULL: if (str && *str) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL_VALUE); goto bad_form; } break; case V_ASN1_BOOLEAN: if (format != ASN1_GEN_FORMAT_ASCII) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ASCII_FORMAT); goto bad_form; } vtmp.name = NULL; vtmp.section = NULL; vtmp.value = (char *)str; if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BOOLEAN); goto bad_str; } break; @@ -617,23 +614,23 @@ case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: if (format != ASN1_GEN_FORMAT_ASCII) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT); goto bad_form; } if ((atmp->value.integer = s2i_ASN1_INTEGER(NULL, str)) == NULL) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_INTEGER); goto bad_str; } break; case V_ASN1_OBJECT: if (format != ASN1_GEN_FORMAT_ASCII) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT); goto bad_form; } if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT); goto bad_str; } break; @@ -641,20 +638,20 @@ case V_ASN1_UTCTIME: case V_ASN1_GENERALIZEDTIME: if (format != ASN1_GEN_FORMAT_ASCII) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT); goto bad_form; } if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto bad_str; } if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto bad_str; } atmp->value.asn1_string->type = utype; if (!ASN1_TIME_check(atmp->value.asn1_string)) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TIME_VALUE); goto bad_str; } @@ -674,13 +671,13 @@ else if (format == ASN1_GEN_FORMAT_UTF8) format = MBSTRING_UTF8; else { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_FORMAT); goto bad_form; } if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, -1, format, ASN1_tag2bit(utype)) <= 0) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto bad_str; } @@ -689,13 +686,13 @@ case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto bad_form; } if (format == ASN1_GEN_FORMAT_HEX) { if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_HEX); goto bad_str; } atmp->value.asn1_string->data = rdata; @@ -707,13 +704,13 @@ && (utype == V_ASN1_BIT_STRING)) { if (!CONF_parse_list (str, ',', 1, bitstr_cb, atmp->value.bit_string)) { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_LIST_ERROR); goto bad_str; } no_unused = 0; } else { - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT); goto bad_form; } @@ -726,7 +723,7 @@ break; default: - ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE); goto bad_str; } @@ -752,11 +749,11 @@ if (eptr && *eptr && (eptr != elem + len)) return 0; if (bitnum < 0) { - ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER); return 0; } if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { - ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } return 1; diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h --- a/crypto/asn1/asn1_item_list.h +++ b/crypto/asn1/asn1_item_list.h @@ -1,7 +1,7 @@ /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -63,8 +63,10 @@ ASN1_ITEM_ref(DIST_POINT_NAME), ASN1_ITEM_ref(DIST_POINT), #ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_DEPRECATED_3_0 ASN1_ITEM_ref(ECPARAMETERS), ASN1_ITEM_ref(ECPKPARAMETERS), +# endif #endif ASN1_ITEM_ref(EDIPARTYNAME), ASN1_ITEM_ref(EXTENDED_KEY_USAGE), @@ -78,7 +80,7 @@ ASN1_ITEM_ref(IPAddressRange), #endif ASN1_ITEM_ref(ISSUING_DIST_POINT), -#if OPENSSL_API_COMPAT < 0x10200000L +#ifndef OPENSSL_NO_DEPRECATED_3_0 ASN1_ITEM_ref(LONG), #endif ASN1_ITEM_ref(NAME_CONSTRAINTS), @@ -134,7 +136,7 @@ ASN1_ITEM_ref(POLICY_MAPPING), ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), ASN1_ITEM_ref(PROXY_POLICY), -#ifndef OPENSSL_NO_RSA +#ifndef OPENSSL_NO_DEPRECATED_3_0 ASN1_ITEM_ref(RSAPrivateKey), ASN1_ITEM_ref(RSAPublicKey), ASN1_ITEM_ref(RSA_OAEP_PARAMS), @@ -145,6 +147,7 @@ #endif ASN1_ITEM_ref(SXNETID), ASN1_ITEM_ref(SXNET), + ASN1_ITEM_ref(ISSUER_SIGN_TOOL), ASN1_ITEM_ref(USERNOTICE), ASN1_ITEM_ref(X509_ALGORS), ASN1_ITEM_ref(X509_ALGOR), @@ -164,7 +167,7 @@ ASN1_ITEM_ref(X509_SIG), ASN1_ITEM_ref(X509_VAL), ASN1_ITEM_ref(X509), -#if OPENSSL_API_COMPAT < 0x10200000L +#ifndef OPENSSL_NO_DEPRECATED_3_0 ASN1_ITEM_ref(ZLONG), #endif ASN1_ITEM_ref(INT32), diff --git a/crypto/asn1/asn1_item_list.c b/crypto/asn1/asn1_item_list.c --- a/crypto/asn1/asn1_item_list.c +++ b/crypto/asn1/asn1_item_list.c @@ -1,12 +1,15 @@ /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* We need to use the low level ASN1 items until they are removed */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include "internal/cryptlib.h" #include diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -22,11 +22,13 @@ /* * If there is 0 or 1 byte left, the length check should pick things up */ - if (len <= 0) - return 1; - else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { - (*p) += 2; + if (len <= 0) { return 1; + } else { + if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { + (*p) += 2; + return 1; + } } return 0; } @@ -45,13 +47,15 @@ int *pclass, long omax) { int i, ret; - long l; + long len; const unsigned char *p = *pp; int tag, xclass, inf; long max = omax; - if (!max) - goto err; + if (omax <= 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); + return 0x80; + } ret = (*p & V_ASN1_CONSTRUCTED); xclass = (*p & V_ASN1_PRIVATE); i = *p & V_ASN1_PRIMITIVE_TAG; @@ -59,18 +63,18 @@ p++; if (--max == 0) goto err; - l = 0; + len = 0; while (*p & 0x80) { - l <<= 7L; - l |= *(p++) & 0x7f; + len <<= 7L; + len |= *(p++) & 0x7f; if (--max == 0) goto err; - if (l > (INT_MAX >> 7L)) + if (len > (INT_MAX >> 7L)) goto err; } - l <<= 7L; - l |= *(p++) & 0x7f; - tag = (int)l; + len <<= 7L; + len |= *(p++) & 0x7f; + tag = (int)len; if (--max == 0) goto err; } else { @@ -88,7 +92,7 @@ goto err; if (*plength > (omax - (p - *pp))) { - ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); /* * Set this so that even if things are not long enough the values are * set correctly @@ -98,7 +102,7 @@ *pp = p; return ret | inf; err: - ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG); return 0x80; } @@ -141,8 +145,9 @@ } if (ret > LONG_MAX) return 0; - } else + } else { ret = i; + } } *pp = p; *rl = (long)ret; @@ -150,7 +155,7 @@ } /* - * class 0 is constructed constructed == 2 for indefinite length constructed + * constructed == 2 for indefinite length constructed */ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, int xclass) @@ -160,9 +165,9 @@ i = (constructed) ? V_ASN1_CONSTRUCTED : 0; i |= (xclass & V_ASN1_PRIVATE); - if (tag < 31) + if (tag < 31) { *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); - else { + } else { *(p++) = i | V_ASN1_PRIMITIVE_TAG; for (i = 0, ttag = tag; ttag > 0; i++) ttag >>= 7; @@ -185,6 +190,7 @@ int ASN1_put_eoc(unsigned char **pp) { unsigned char *p = *pp; + *p++ = 0; *p++ = 0; *pp = p; @@ -194,20 +200,21 @@ static void asn1_put_length(unsigned char **pp, int length) { unsigned char *p = *pp; - int i, l; - if (length <= 127) + int i, len; + + if (length <= 127) { *(p++) = (unsigned char)length; - else { - l = length; - for (i = 0; l > 0; i++) - l >>= 8; + } else { + len = length; + for (i = 0; len > 0; i++) + len >>= 8; *(p++) = i | 0x80; - l = i; + len = i; while (i-- > 0) { p[i] = length & 0xff; length >>= 8; } - p += l; + p += len; } *pp = p; } @@ -215,6 +222,7 @@ int ASN1_object_size(int constructed, int length, int tag) { int ret = 1; + if (length < 0) return -1; if (tag >= 31) { @@ -256,6 +264,7 @@ ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) { ASN1_STRING *ret; + if (!str) return NULL; ret = ASN1_STRING_new(); @@ -287,7 +296,7 @@ * '\0' terminator even though this isn't strictly necessary. */ if (len > INT_MAX - 1) { - ASN1err(0, ASN1_R_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } if ((size_t)str->length <= len || str->data == NULL) { @@ -299,7 +308,7 @@ str->data = OPENSSL_realloc(c, len + 1); #endif if (str->data == NULL) { - ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); str->data = c; return 0; } @@ -340,14 +349,14 @@ ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } ret->type = type; return ret; } -void asn1_string_embed_free(ASN1_STRING *a, int embed) +void ossl_asn1_string_embed_free(ASN1_STRING *a, int embed) { if (a == NULL) return; @@ -361,7 +370,7 @@ { if (a == NULL) return; - asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED); + ossl_asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED); } void ASN1_STRING_clear_free(ASN1_STRING *a) @@ -385,8 +394,9 @@ return a->type - b->type; else return i; - } else + } else { return i; + } } int ASN1_STRING_length(const ASN1_STRING *x) @@ -394,10 +404,12 @@ return x->length; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 void ASN1_STRING_length_set(ASN1_STRING *x, int len) { x->length = len; } +#endif int ASN1_STRING_type(const ASN1_STRING *x) { @@ -409,9 +421,50 @@ return x->data; } -# if OPENSSL_API_COMPAT < 0x10100000L +#ifndef OPENSSL_NO_DEPRECATED_1_1_0 unsigned char *ASN1_STRING_data(ASN1_STRING *x) { return x->data; } #endif + +/* |max_len| excludes NUL terminator and may be 0 to indicate no restriction */ +char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, + const char *sep, size_t max_len) +{ + int i; + ASN1_UTF8STRING *current; + size_t length = 0, sep_len; + char *result = NULL; + char *p; + + if (sep == NULL) + sep = ""; + sep_len = strlen(sep); + + for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { + current = sk_ASN1_UTF8STRING_value(text, i); + if (i > 0) + length += sep_len; + length += ASN1_STRING_length(current); + if (max_len != 0 && length > max_len) + return NULL; + } + if ((result = OPENSSL_malloc(length + 1)) == NULL) + return NULL; + + p = result; + for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { + current = sk_ASN1_UTF8STRING_value(text, i); + length = ASN1_STRING_length(current); + if (i > 0 && sep_len > 0) { + strncpy(p, sep, sep_len + 1); /* using + 1 to silence gcc warning */ + p += sep_len; + } + strncpy(p, (const char *)ASN1_STRING_get0_data(current), length); + p += length; + } + *p = '\0'; + + return result; +} diff --git a/crypto/asn1/asn1_local.h b/crypto/asn1/asn1_local.h --- a/crypto/asn1/asn1_local.h +++ b/crypto/asn1/asn1_local.h @@ -1,7 +1,7 @@ /* - * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -9,9 +9,11 @@ /* Internal ASN1 structures and functions: not for application use */ -int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d); -int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); -int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); +typedef const ASN1_VALUE const_ASN1_VALUE; +SKM_DEFINE_STACK_OF(const_ASN1_VALUE, const ASN1_VALUE, ASN1_VALUE) + +int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d); +int ossl_asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); /* ASN1 scan context structure */ @@ -43,41 +45,50 @@ typedef struct mime_header_st MIME_HEADER; DEFINE_STACK_OF(MIME_HEADER) -void asn1_string_embed_free(ASN1_STRING *a, int embed); +void ossl_asn1_string_embed_free(ASN1_STRING *a, int embed); -int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); -int asn1_set_choice_selector(ASN1_VALUE **pval, int value, - const ASN1_ITEM *it); +int ossl_asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); +int ossl_asn1_get_choice_selector_const(const ASN1_VALUE **pval, + const ASN1_ITEM *it); +int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value, + const ASN1_ITEM *it); -ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +ASN1_VALUE **ossl_asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +const ASN1_VALUE **ossl_asn1_get_const_field_ptr(const ASN1_VALUE **pval, + const ASN1_TEMPLATE *tt); -const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, - int nullerr); +const ASN1_TEMPLATE *ossl_asn1_do_adb(const ASN1_VALUE *val, + const ASN1_TEMPLATE *tt, + int nullerr); -int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); +int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); -void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); -void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); -int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, - const ASN1_ITEM *it); -int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, - const ASN1_ITEM *it); +void ossl_asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ossl_asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int ossl_asn1_enc_restore(int *len, unsigned char **out, const ASN1_VALUE **pval, + const ASN1_ITEM *it); +int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, + const ASN1_ITEM *it); -void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); -void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); -void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +void ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); +void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); +void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); -ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, - long length); -int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp); -ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, - const unsigned char **pp, long length); -int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp); -ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, - long length); +ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); +int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp); +ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long length); +int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp); +ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); /* Internal functions used by x_int64.c */ -int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len); -int i2c_uint64_int(unsigned char *p, uint64_t r, int neg); +int ossl_c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, + long len); +int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg); + +ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type); -ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type); +int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq); diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c deleted file mode 100644 --- a/crypto/asn1/asn1_par.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include - -#ifndef ASN1_PARSE_MAXDEPTH -#define ASN1_PARSE_MAXDEPTH 128 -#endif - -static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, - int indent); -static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, - int offset, int depth, int indent, int dump); -static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, - int indent) -{ - static const char fmt[] = "%-18s"; - char str[128]; - const char *p; - - if (constructed & V_ASN1_CONSTRUCTED) - p = "cons: "; - else - p = "prim: "; - if (BIO_write(bp, p, 6) < 6) - goto err; - BIO_indent(bp, indent, 128); - - p = str; - if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) - BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag); - else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) - BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag); - else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) - BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag); - else if (tag > 30) - BIO_snprintf(str, sizeof(str), "", tag); - else - p = ASN1_tag2str(tag); - - if (BIO_printf(bp, fmt, p) <= 0) - goto err; - return 1; - err: - return 0; -} - -int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent) -{ - return asn1_parse2(bp, &pp, len, 0, 0, indent, 0); -} - -int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, - int dump) -{ - return asn1_parse2(bp, &pp, len, 0, 0, indent, dump); -} - -static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, - int offset, int depth, int indent, int dump) -{ - const unsigned char *p, *ep, *tot, *op, *opp; - long len; - int tag, xclass, ret = 0; - int nl, hl, j, r; - ASN1_OBJECT *o = NULL; - ASN1_OCTET_STRING *os = NULL; - ASN1_INTEGER *ai = NULL; - ASN1_ENUMERATED *ae = NULL; - /* ASN1_BMPSTRING *bmp=NULL; */ - int dump_indent, dump_cont = 0; - - if (depth > ASN1_PARSE_MAXDEPTH) { - BIO_puts(bp, "BAD RECURSION DEPTH\n"); - return 0; - } - - dump_indent = 6; /* Because we know BIO_dump_indent() */ - p = *pp; - tot = p + length; - while (length > 0) { - op = p; - j = ASN1_get_object(&p, &len, &tag, &xclass, length); - if (j & 0x80) { - if (BIO_write(bp, "Error in encoding\n", 18) <= 0) - goto end; - ret = 0; - goto end; - } - hl = (p - op); - length -= hl; - /* - * if j == 0x21 it is a constructed indefinite length object - */ - if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp)) - <= 0) - goto end; - - if (j != (V_ASN1_CONSTRUCTED | 1)) { - if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ", - depth, (long)hl, len) <= 0) - goto end; - } else { - if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0) - goto end; - } - if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0)) - goto end; - if (j & V_ASN1_CONSTRUCTED) { - const unsigned char *sp = p; - - ep = p + len; - if (BIO_write(bp, "\n", 1) <= 0) - goto end; - if (len > length) { - BIO_printf(bp, "length is greater than %ld\n", length); - ret = 0; - goto end; - } - if ((j == 0x21) && (len == 0)) { - for (;;) { - r = asn1_parse2(bp, &p, (long)(tot - p), - offset + (p - *pp), depth + 1, - indent, dump); - if (r == 0) { - ret = 0; - goto end; - } - if ((r == 2) || (p >= tot)) { - len = p - sp; - break; - } - } - } else { - long tmp = len; - - while (p < ep) { - sp = p; - r = asn1_parse2(bp, &p, tmp, - offset + (p - *pp), depth + 1, - indent, dump); - if (r == 0) { - ret = 0; - goto end; - } - tmp -= p - sp; - } - } - } else if (xclass != 0) { - p += len; - if (BIO_write(bp, "\n", 1) <= 0) - goto end; - } else { - nl = 0; - if ((tag == V_ASN1_PRINTABLESTRING) || - (tag == V_ASN1_T61STRING) || - (tag == V_ASN1_IA5STRING) || - (tag == V_ASN1_VISIBLESTRING) || - (tag == V_ASN1_NUMERICSTRING) || - (tag == V_ASN1_UTF8STRING) || - (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) { - if (BIO_write(bp, ":", 1) <= 0) - goto end; - if ((len > 0) && BIO_write(bp, (const char *)p, (int)len) - != (int)len) - goto end; - } else if (tag == V_ASN1_OBJECT) { - opp = op; - if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) { - if (BIO_write(bp, ":", 1) <= 0) - goto end; - i2a_ASN1_OBJECT(bp, o); - } else { - if (BIO_puts(bp, ":BAD OBJECT") <= 0) - goto end; - dump_cont = 1; - } - } else if (tag == V_ASN1_BOOLEAN) { - if (len != 1) { - if (BIO_puts(bp, ":BAD BOOLEAN") <= 0) - goto end; - dump_cont = 1; - } - if (len > 0) - BIO_printf(bp, ":%u", p[0]); - } else if (tag == V_ASN1_BMPSTRING) { - /* do the BMP thang */ - } else if (tag == V_ASN1_OCTET_STRING) { - int i, printable = 1; - - opp = op; - os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl); - if (os != NULL && os->length > 0) { - opp = os->data; - /* - * testing whether the octet string is printable - */ - for (i = 0; i < os->length; i++) { - if (((opp[i] < ' ') && - (opp[i] != '\n') && - (opp[i] != '\r') && - (opp[i] != '\t')) || (opp[i] > '~')) { - printable = 0; - break; - } - } - if (printable) - /* printable string */ - { - if (BIO_write(bp, ":", 1) <= 0) - goto end; - if (BIO_write(bp, (const char *)opp, os->length) <= 0) - goto end; - } else if (!dump) - /* - * not printable => print octet string as hex dump - */ - { - if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0) - goto end; - for (i = 0; i < os->length; i++) { - if (BIO_printf(bp, "%02X", opp[i]) <= 0) - goto end; - } - } else - /* print the normal dump */ - { - if (!nl) { - if (BIO_write(bp, "\n", 1) <= 0) - goto end; - } - if (BIO_dump_indent(bp, - (const char *)opp, - ((dump == -1 || dump > - os-> - length) ? os->length : dump), - dump_indent) <= 0) - goto end; - nl = 1; - } - } - ASN1_OCTET_STRING_free(os); - os = NULL; - } else if (tag == V_ASN1_INTEGER) { - int i; - - opp = op; - ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl); - if (ai != NULL) { - if (BIO_write(bp, ":", 1) <= 0) - goto end; - if (ai->type == V_ASN1_NEG_INTEGER) - if (BIO_write(bp, "-", 1) <= 0) - goto end; - for (i = 0; i < ai->length; i++) { - if (BIO_printf(bp, "%02X", ai->data[i]) <= 0) - goto end; - } - if (ai->length == 0) { - if (BIO_write(bp, "00", 2) <= 0) - goto end; - } - } else { - if (BIO_puts(bp, ":BAD INTEGER") <= 0) - goto end; - dump_cont = 1; - } - ASN1_INTEGER_free(ai); - ai = NULL; - } else if (tag == V_ASN1_ENUMERATED) { - int i; - - opp = op; - ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl); - if (ae != NULL) { - if (BIO_write(bp, ":", 1) <= 0) - goto end; - if (ae->type == V_ASN1_NEG_ENUMERATED) - if (BIO_write(bp, "-", 1) <= 0) - goto end; - for (i = 0; i < ae->length; i++) { - if (BIO_printf(bp, "%02X", ae->data[i]) <= 0) - goto end; - } - if (ae->length == 0) { - if (BIO_write(bp, "00", 2) <= 0) - goto end; - } - } else { - if (BIO_puts(bp, ":BAD ENUMERATED") <= 0) - goto end; - dump_cont = 1; - } - ASN1_ENUMERATED_free(ae); - ae = NULL; - } else if (len > 0 && dump) { - if (!nl) { - if (BIO_write(bp, "\n", 1) <= 0) - goto end; - } - if (BIO_dump_indent(bp, (const char *)p, - ((dump == -1 || dump > len) ? len : dump), - dump_indent) <= 0) - goto end; - nl = 1; - } - if (dump_cont) { - int i; - const unsigned char *tmp = op + hl; - if (BIO_puts(bp, ":[") <= 0) - goto end; - for (i = 0; i < len; i++) { - if (BIO_printf(bp, "%02X", tmp[i]) <= 0) - goto end; - } - if (BIO_puts(bp, "]") <= 0) - goto end; - dump_cont = 0; - } - - if (!nl) { - if (BIO_write(bp, "\n", 1) <= 0) - goto end; - } - p += len; - if ((tag == V_ASN1_EOC) && (xclass == 0)) { - ret = 2; /* End of sequence */ - goto end; - } - } - length -= len; - } - ret = 1; - end: - ASN1_OBJECT_free(o); - ASN1_OCTET_STRING_free(os); - ASN1_INTEGER_free(ai); - ASN1_ENUMERATED_free(ae); - *pp = p; - return ret; -} - -const char *ASN1_tag2str(int tag) -{ - static const char *const tag2str[] = { - /* 0-4 */ - "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", - /* 5-9 */ - "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", - /* 10-13 */ - "ENUMERATED", "", "UTF8STRING", "", - /* 15-17 */ - "", "", "SEQUENCE", "SET", - /* 18-20 */ - "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", - /* 21-24 */ - "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", - /* 25-27 */ - "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", - /* 28-30 */ - "UNIVERSALSTRING", "", "BMPSTRING" - }; - - if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) - tag &= ~0x100; - - if (tag < 0 || tag > 30) - return "(unknown)"; - return tag2str[tag]; -} diff --git a/crypto/asn1/asn1_parse.c b/crypto/asn1/asn1_parse.c new file mode 100644 --- /dev/null +++ b/crypto/asn1/asn1_parse.c @@ -0,0 +1,387 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/cryptlib.h" +#include +#include +#include + +#ifndef ASN1_PARSE_MAXDEPTH +#define ASN1_PARSE_MAXDEPTH 128 +#endif + +static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, + int offset, int depth, int indent, int dump); +static int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len, + int tag, int xclass, int constructed, int indent) +{ + char str[128]; + const char *p; + int pop_f_prefix = 0; + long saved_indent = -1; + int i = 0; + BIO *bio = NULL; + + if (constructed & V_ASN1_CONSTRUCTED) + p = "cons: "; + else + p = "prim: "; + if (constructed != (V_ASN1_CONSTRUCTED | 1)) { + if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=%4ld %s", + offset, depth, (long)hl, len, p) <= 0) + goto err; + } else { + if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=inf %s", + offset, depth, (long)hl, p) <= 0) + goto err; + } + if (bp != NULL) { + if (BIO_set_prefix(bp, str) <= 0) { + if ((bio = BIO_new(BIO_f_prefix())) == NULL + || (bp = BIO_push(bio, bp)) == NULL) + goto err; + pop_f_prefix = 1; + } + saved_indent = BIO_get_indent(bp); + if (BIO_set_prefix(bp, str) <= 0 || BIO_set_indent(bp, indent) < 0) + goto err; + } + + /* + * BIO_set_prefix made a copy of |str|, so we can safely use it for + * something else, ASN.1 tag printout. + */ + p = str; + if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) + BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag); + else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) + BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag); + else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) + BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag); + else if (tag > 30) + BIO_snprintf(str, sizeof(str), "", tag); + else + p = ASN1_tag2str(tag); + + i = (BIO_printf(bp, "%-18s", p) > 0); + err: + if (saved_indent >= 0) + BIO_set_indent(bp, saved_indent); + if (pop_f_prefix) + BIO_pop(bp); + BIO_free(bio); + return i; +} + +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent) +{ + return asn1_parse2(bp, &pp, len, 0, 0, indent, 0); +} + +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, + int dump) +{ + return asn1_parse2(bp, &pp, len, 0, 0, indent, dump); +} + +static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, + int offset, int depth, int indent, int dump) +{ + const unsigned char *p, *ep, *tot, *op, *opp; + long len; + int tag, xclass, ret = 0; + int nl, hl, j, r; + ASN1_OBJECT *o = NULL; + ASN1_OCTET_STRING *os = NULL; + ASN1_INTEGER *ai = NULL; + ASN1_ENUMERATED *ae = NULL; + /* ASN1_BMPSTRING *bmp=NULL; */ + int dump_indent, dump_cont = 0; + + if (depth > ASN1_PARSE_MAXDEPTH) { + BIO_puts(bp, "BAD RECURSION DEPTH\n"); + return 0; + } + + dump_indent = 6; /* Because we know BIO_dump_indent() */ + p = *pp; + tot = p + length; + while (length > 0) { + op = p; + j = ASN1_get_object(&p, &len, &tag, &xclass, length); + if (j & 0x80) { + BIO_puts(bp, "Error in encoding\n"); + goto end; + } + hl = (p - op); + length -= hl; + /* + * if j == 0x21 it is a constructed indefinite length object + */ + if (!asn1_print_info(bp, (long)offset + (long)(op - *pp), depth, + hl, len, tag, xclass, j, (indent) ? depth : 0)) + goto end; + if (j & V_ASN1_CONSTRUCTED) { + const unsigned char *sp = p; + + ep = p + len; + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + if (len > length) { + BIO_printf(bp, "length is greater than %ld\n", length); + goto end; + } + if ((j == 0x21) && (len == 0)) { + for (;;) { + r = asn1_parse2(bp, &p, (long)(tot - p), + offset + (p - *pp), depth + 1, + indent, dump); + if (r == 0) + goto end; + if ((r == 2) || (p >= tot)) { + len = p - sp; + break; + } + } + } else { + long tmp = len; + + while (p < ep) { + sp = p; + r = asn1_parse2(bp, &p, tmp, + offset + (p - *pp), depth + 1, + indent, dump); + if (r == 0) + goto end; + tmp -= p - sp; + } + } + } else if (xclass != 0) { + p += len; + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } else { + nl = 0; + if ((tag == V_ASN1_PRINTABLESTRING) || + (tag == V_ASN1_T61STRING) || + (tag == V_ASN1_IA5STRING) || + (tag == V_ASN1_VISIBLESTRING) || + (tag == V_ASN1_NUMERICSTRING) || + (tag == V_ASN1_UTF8STRING) || + (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if ((len > 0) && BIO_write(bp, (const char *)p, (int)len) + != (int)len) + goto end; + } else if (tag == V_ASN1_OBJECT) { + opp = op; + if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + i2a_ASN1_OBJECT(bp, o); + } else { + if (BIO_puts(bp, ":BAD OBJECT") <= 0) + goto end; + dump_cont = 1; + } + } else if (tag == V_ASN1_BOOLEAN) { + if (len != 1) { + if (BIO_puts(bp, ":BAD BOOLEAN") <= 0) + goto end; + dump_cont = 1; + } + if (len > 0) + BIO_printf(bp, ":%u", p[0]); + } else if (tag == V_ASN1_BMPSTRING) { + /* do the BMP thang */ + } else if (tag == V_ASN1_OCTET_STRING) { + int i, printable = 1; + + opp = op; + os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl); + if (os != NULL && os->length > 0) { + opp = os->data; + /* + * testing whether the octet string is printable + */ + for (i = 0; i < os->length; i++) { + if (((opp[i] < ' ') && + (opp[i] != '\n') && + (opp[i] != '\r') && + (opp[i] != '\t')) || (opp[i] > '~')) { + printable = 0; + break; + } + } + if (printable) + /* printable string */ + { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if (BIO_write(bp, (const char *)opp, os->length) <= 0) + goto end; + } else if (!dump) + /* + * not printable => print octet string as hex dump + */ + { + if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0) + goto end; + for (i = 0; i < os->length; i++) { + if (BIO_printf(bp, "%02X", opp[i]) <= 0) + goto end; + } + } else + /* print the normal dump */ + { + if (!nl) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } + if (BIO_dump_indent(bp, + (const char *)opp, + ((dump == -1 || dump > + os-> + length) ? os->length : dump), + dump_indent) <= 0) + goto end; + nl = 1; + } + } + ASN1_OCTET_STRING_free(os); + os = NULL; + } else if (tag == V_ASN1_INTEGER) { + int i; + + opp = op; + ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl); + if (ai != NULL) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if (ai->type == V_ASN1_NEG_INTEGER) + if (BIO_write(bp, "-", 1) <= 0) + goto end; + for (i = 0; i < ai->length; i++) { + if (BIO_printf(bp, "%02X", ai->data[i]) <= 0) + goto end; + } + if (ai->length == 0) { + if (BIO_write(bp, "00", 2) <= 0) + goto end; + } + } else { + if (BIO_puts(bp, ":BAD INTEGER") <= 0) + goto end; + dump_cont = 1; + } + ASN1_INTEGER_free(ai); + ai = NULL; + } else if (tag == V_ASN1_ENUMERATED) { + int i; + + opp = op; + ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl); + if (ae != NULL) { + if (BIO_write(bp, ":", 1) <= 0) + goto end; + if (ae->type == V_ASN1_NEG_ENUMERATED) + if (BIO_write(bp, "-", 1) <= 0) + goto end; + for (i = 0; i < ae->length; i++) { + if (BIO_printf(bp, "%02X", ae->data[i]) <= 0) + goto end; + } + if (ae->length == 0) { + if (BIO_write(bp, "00", 2) <= 0) + goto end; + } + } else { + if (BIO_puts(bp, ":BAD ENUMERATED") <= 0) + goto end; + dump_cont = 1; + } + ASN1_ENUMERATED_free(ae); + ae = NULL; + } else if (len > 0 && dump) { + if (!nl) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } + if (BIO_dump_indent(bp, (const char *)p, + ((dump == -1 || dump > len) ? len : dump), + dump_indent) <= 0) + goto end; + nl = 1; + } + if (dump_cont) { + int i; + const unsigned char *tmp = op + hl; + if (BIO_puts(bp, ":[") <= 0) + goto end; + for (i = 0; i < len; i++) { + if (BIO_printf(bp, "%02X", tmp[i]) <= 0) + goto end; + } + if (BIO_puts(bp, "]") <= 0) + goto end; + dump_cont = 0; + } + + if (!nl) { + if (BIO_write(bp, "\n", 1) <= 0) + goto end; + } + p += len; + if ((tag == V_ASN1_EOC) && (xclass == 0)) { + ret = 2; /* End of sequence */ + goto end; + } + } + length -= len; + } + ret = 1; + end: + ASN1_OBJECT_free(o); + ASN1_OCTET_STRING_free(os); + ASN1_INTEGER_free(ai); + ASN1_ENUMERATED_free(ae); + *pp = p; + return ret; +} + +const char *ASN1_tag2str(int tag) +{ + static const char *const tag2str[] = { + /* 0-4 */ + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", + /* 5-9 */ + "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", + /* 10-13 */ + "ENUMERATED", "", "UTF8STRING", "", + /* 15-17 */ + "", "", "SEQUENCE", "SET", + /* 18-20 */ + "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", + /* 21-24 */ + "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", + /* 25-27 */ + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", + /* 28-30 */ + "UNIVERSALSTRING", "", "BMPSTRING" + }; + + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) + tag &= ~0x100; + + if (tag < 0 || tag > 30) + return "(unknown)"; + return tag2str[tag]; +} diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c --- a/crypto/asn1/asn_mime.c +++ b/crypto/asn1/asn_mime.c @@ -1,7 +1,7 @@ /* - * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -14,6 +14,7 @@ #include #include #include +#include #include "crypto/evp.h" #include "internal/bio.h" #include "asn1_local.h" @@ -53,7 +54,7 @@ const MIME_PARAM *const *b); static void mime_param_free(MIME_PARAM *param); static int mime_bound_check(char *line, int linelen, const char *bound, int blen); -static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret); +static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret); static int strip_eol(char *linebuf, int *plen, int flags); static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name); static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name); @@ -64,18 +65,24 @@ /* Output an ASN1 structure in BER format streaming if necessary */ +/* unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() */ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const ASN1_ITEM *it) { + int rv = 1; + /* If streaming create stream BIO and copy all content through it */ if (flags & SMIME_STREAM) { BIO *bio, *tbio; bio = BIO_new_NDEF(out, val, it); if (!bio) { - ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } - SMIME_crlf_copy(in, bio, flags); + if (!SMIME_crlf_copy(in, bio, flags)) { + rv = 0; + } + (void)BIO_flush(bio); /* Free up successive BIOs until we hit the old output BIO */ do { @@ -90,7 +97,7 @@ */ else ASN1_item_i2d_bio(it, out, val); - return 1; + return rv; } /* Base 64 read and write of ASN1 structure */ @@ -102,7 +109,7 @@ int r; b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { - ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } /* @@ -128,19 +135,20 @@ return r; } -static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) +static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x, + OSSL_LIB_CTX *libctx, const char *propq) { BIO *b64; ASN1_VALUE *val; if ((b64 = BIO_new(BIO_f_base64())) == NULL) { - ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } bio = BIO_push(b64, bio); - val = ASN1_item_d2i_bio(it, bio, NULL); + val = ASN1_item_d2i_bio_ex(it, bio, x, libctx, propq); if (!val) - ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); (void)BIO_flush(bio); BIO_pop(bio); BIO_free(b64); @@ -207,9 +215,9 @@ goto err; default: - if (have_unknown) + if (have_unknown) { write_comma = 0; - else { + } else { BIO_puts(out, "unknown"); have_unknown = 1; } @@ -227,14 +235,16 @@ /* SMIME sender */ -int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, - int ctype_nid, int econt_nid, - STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it) +int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq) { char bound[33], c; int i; const char *mime_prefix, *mime_eol, *cname = "smime.p7m"; const char *msg_type = NULL; + if (flags & SMIME_OLDMIME) mime_prefix = "application/x-pkcs7-"; else @@ -247,7 +257,7 @@ if ((flags & SMIME_DETACHED) && data) { /* We want multipart/signed */ /* Generate a random boundary */ - if (RAND_bytes((unsigned char *)bound, 32) <= 0) + if (RAND_bytes_ex(libctx, (unsigned char *)bound, 32, 0) <= 0) return 0; for (i = 0; i < 32; i++) { c = bound[i] & 0xf; @@ -288,9 +298,9 @@ /* Determine smime-type header */ - if (ctype_nid == NID_pkcs7_enveloped) + if (ctype_nid == NID_pkcs7_enveloped) { msg_type = "enveloped-data"; - else if (ctype_nid == NID_pkcs7_signed) { + } else if (ctype_nid == NID_pkcs7_signed) { if (econt_nid == NID_id_smime_ct_receipt) msg_type = "signed-receipt"; else if (sk_X509_ALGOR_num(mdalgs) >= 0) @@ -317,8 +327,17 @@ return 1; } +int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it) +{ + return SMIME_write_ASN1_ex(bio, val, data, flags, ctype_nid, econt_nid, + mdalgs, it, NULL, NULL); +} + /* Handle output of ASN1 data */ +/* cannot constify val because of CMS_dataFinal() */ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, const ASN1_ITEM *it) { @@ -332,12 +351,11 @@ * set up to finalise when it is written through. */ if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) { - SMIME_crlf_copy(data, out, flags); - return 1; + return SMIME_crlf_copy(data, out, flags); } if (!aux || !aux->asn1_cb) { - ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED); return 0; } @@ -351,7 +369,8 @@ return 0; /* Copy data across, passing through filter BIOs for processing */ - SMIME_crlf_copy(data, sarg.ndef_bio, flags); + if (!SMIME_crlf_copy(data, sarg.ndef_bio, flags)) + rv = 0; /* Finalize structure */ if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0) @@ -375,7 +394,9 @@ * opaque this is set to NULL */ -ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) +ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont, + const ASN1_ITEM *it, ASN1_VALUE **x, + OSSL_LIB_CTX *libctx, const char *propq) { BIO *asnin; STACK_OF(MIME_HEADER) *headers = NULL; @@ -389,14 +410,14 @@ *bcont = NULL; if ((headers = mime_parse_hdr(bio)) == NULL) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR); return NULL; } if ((hdr = mime_hdr_find(headers, "content-type")) == NULL || hdr->value == NULL) { sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE); return NULL; } @@ -405,15 +426,15 @@ if (strcmp(hdr->value, "multipart/signed") == 0) { /* Split into two parts */ prm = mime_param_find(hdr, "boundary"); - if (!prm || !prm->param_value) { + if (prm == NULL || prm->param_value == NULL) { sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); return NULL; } - ret = multi_split(bio, prm->param_value, &parts); + ret = multi_split(bio, flags, prm->param_value, &parts); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); if (!ret || (sk_BIO_num(parts) != 2)) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); sk_BIO_pop_free(parts, BIO_vfree); return NULL; } @@ -422,7 +443,7 @@ asnin = sk_BIO_value(parts, 1); if ((headers = mime_parse_hdr(asnin)) == NULL) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR); sk_BIO_pop_free(parts, BIO_vfree); return NULL; } @@ -432,23 +453,23 @@ if ((hdr = mime_hdr_find(headers, "content-type")) == NULL || hdr->value == NULL) { sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); sk_BIO_pop_free(parts, BIO_vfree); return NULL; } if (strcmp(hdr->value, "application/x-pkcs7-signature") && strcmp(hdr->value, "application/pkcs7-signature")) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE); - ERR_add_error_data(2, "type: ", hdr->value); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE, + "type: %s", hdr->value); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); sk_BIO_pop_free(parts, BIO_vfree); return NULL; } sk_MIME_HEADER_pop_free(headers, mime_hdr_free); /* Read in ASN1 */ - if ((val = b64_read_asn1(asnin, it)) == NULL) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR); + if ((val = b64_read_asn1(asnin, it, x, libctx, propq)) == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR); sk_BIO_pop_free(parts, BIO_vfree); return NULL; } @@ -457,8 +478,9 @@ *bcont = sk_BIO_value(parts, 0); BIO_free(asnin); sk_BIO_free(parts); - } else + } else { sk_BIO_pop_free(parts, BIO_vfree); + } return val; } @@ -466,20 +488,24 @@ if (strcmp(hdr->value, "application/x-pkcs7-mime") && strcmp(hdr->value, "application/pkcs7-mime")) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE); - ERR_add_error_data(2, "type: ", hdr->value); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE, + "type: %s", hdr->value); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return NULL; } sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - if ((val = b64_read_asn1(bio, it)) == NULL) { - ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); + if ((val = b64_read_asn1(bio, it, x, libctx, propq)) == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR); return NULL; } return val; +} +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) +{ + return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL, NULL, NULL); } /* Copy text from one BIO to another making the output CRLF at EOL */ @@ -495,8 +521,10 @@ * when streaming as we don't end up with one OCTET STRING per line. */ bf = BIO_new(BIO_f_buffer()); - if (bf == NULL) + if (bf == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; + } out = BIO_push(bf, out); if (flags & SMIME_BINARY) { while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) @@ -507,7 +535,7 @@ BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { eol = strip_eol(linebuf, &len, flags); - if (len) { + if (len > 0) { /* Not EOF: write out all CRLF */ if (flags & SMIME_ASCIICRLF) { int i; @@ -518,10 +546,11 @@ BIO_write(out, linebuf, len); if (eol) BIO_write(out, "\r\n", 2); - } else if (flags & SMIME_ASCIICRLF) + } else if (flags & SMIME_ASCIICRLF) { eolcnt++; - else if (eol) + } else if (eol) { BIO_write(out, "\r\n", 2); + } } } ret = BIO_flush(out); @@ -542,18 +571,18 @@ MIME_HEADER *hdr; if ((headers = mime_parse_hdr(in)) == NULL) { - ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR); return 0; } if ((hdr = mime_hdr_find(headers, "content-type")) == NULL || hdr->value == NULL) { - ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return 0; } if (strcmp(hdr->value, "text/plain")) { - ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE); - ERR_add_error_data(2, "type: ", hdr->value); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE, + "type: %s", hdr->value); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return 0; } @@ -570,7 +599,7 @@ * canonical parts in a STACK of bios */ -static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret) +static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret) { char linebuf[MAX_SMLEN]; int len, blen; @@ -587,7 +616,7 @@ *ret = parts; if (*ret == NULL) return 0; - while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + while ((len = BIO_get_line(bio, linebuf, MAX_SMLEN)) > 0) { state = mime_bound_check(linebuf, len, bound, blen); if (state == 1) { first = 1; @@ -598,9 +627,9 @@ return 0; } return 1; - } else if (part) { - /* Strip CR+LF from linebuf */ - next_eol = strip_eol(linebuf, &len, 0); + } else if (part != 0) { + /* Strip (possibly CR +) LF from linebuf */ + next_eol = strip_eol(linebuf, &len, flags); if (first) { first = 0; if (bpart) @@ -612,10 +641,20 @@ if (bpart == NULL) return 0; BIO_set_mem_eof_return(bpart, 0); - } else if (eol) - BIO_write(bpart, "\r\n", 2); + } else if (eol) { + if ( +#ifndef OPENSSL_NO_CMS + (flags & CMS_BINARY) == 0 +#else + 1 +#endif + || (flags & SMIME_CRLFEOL) != 0) + BIO_write(bpart, "\r\n", 2); + else + BIO_write(bpart, "\n", 1); + } eol = next_eol; - if (len) + if (len > 0) BIO_write(bpart, linebuf, len); } } @@ -739,15 +778,16 @@ goto err; mhdr = new_hdr; new_hdr = NULL; - } else if (state == MIME_VALUE) + } else if (state == MIME_VALUE) { mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + } if (p == linebuf) break; /* Blank line means end of headers */ } return headers; -err: + err: mime_hdr_free(new_hdr); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return NULL; @@ -762,7 +802,7 @@ static char *strip_start(char *name) { char *p, c; - /* Look for first non white space or quote */ + /* Look for first non whitespace or quote */ for (p = name; (c = *p); p++) { if (c == '"') { /* Next char is start of string if non null */ @@ -783,7 +823,7 @@ char *p, c; if (!name) return NULL; - /* Look for first non white space or quote */ + /* Look for first non whitespace or quote */ for (p = name + strlen(name) - 1; p >= name; p--) { c = *p; if (c == '"') { @@ -869,8 +909,8 @@ static int mime_hdr_cmp(const MIME_HEADER *const *a, const MIME_HEADER *const *b) { - if (!(*a)->name || !(*b)->name) - return ! !(*a)->name - ! !(*b)->name; + if ((*a)->name == NULL || (*b)->name == NULL) + return ((*a)->name != NULL) - ((*b)->name != NULL); return strcmp((*a)->name, (*b)->name); } @@ -878,8 +918,8 @@ static int mime_param_cmp(const MIME_PARAM *const *a, const MIME_PARAM *const *b) { - if (!(*a)->param_name || !(*b)->param_name) - return ! !(*a)->param_name - ! !(*b)->param_name; + if ((*a)->param_name == NULL || (*b)->param_name == NULL) + return ((*a)->param_name != NULL) - ((*b)->param_name != NULL); return strcmp((*a)->param_name, (*b)->param_name); } @@ -959,11 +999,26 @@ char *p, c; int is_eol = 0; +#ifndef OPENSSL_NO_CMS + if ((flags & CMS_BINARY) != 0) { + if (len <= 0 || linebuf[len - 1] != '\n') + return 0; + if ((flags & SMIME_CRLFEOL) != 0) { + if (len <= 1 || linebuf[len - 2] != '\r') + return 0; + len--; + } + len--; + *plen = len; + return 1; + } +#endif + for (p = linebuf + len - 1; len > 0; len--, p--) { c = *p; if (c == '\n') { is_eol = 1; - } else if (is_eol && flags & SMIME_ASCIICRLF && c == 32) { + } else if (is_eol && (flags & SMIME_ASCIICRLF) != 0 && c == 32) { /* Strip trailing space on a line; 32 == ASCII for ' ' */ continue; } else if (c != '\r') { diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c --- a/crypto/asn1/asn_moid.c +++ b/crypto/asn1/asn_moid.c @@ -1,7 +1,7 @@ /* - * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -29,13 +29,13 @@ oid_section = CONF_imodule_get_value(md); if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) { - ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION); return 0; } for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { oval = sk_CONF_VALUE_value(sktmp, i); if (!do_create(oval->value, oval->name)) { - ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ADDING_OBJECT); return 0; } } @@ -84,7 +84,7 @@ } p++; if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) { - ASN1err(ASN1_F_DO_CREATE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } memcpy(lntmp, ln, p - ln); diff --git a/crypto/asn1/asn_mstbl.c b/crypto/asn1/asn_mstbl.c --- a/crypto/asn1/asn_mstbl.c +++ b/crypto/asn1/asn_mstbl.c @@ -1,7 +1,7 @@ /* - * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -26,13 +26,13 @@ stbl_section = CONF_imodule_get_value(md); if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) { - ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION); return 0; } for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { mval = sk_CONF_VALUE_value(sktmp, i); if (!do_tcreate(mval->value, mval->name)) { - ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_VALUE); return 0; } } @@ -96,17 +96,17 @@ rv = 1; err: if (rv == 0) { - ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE); if (cnf) - ERR_add_error_data(4, "field=", cnf->name, - ", value=", cnf->value); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE, + "field=%s, value=%s", cnf->name, cnf->value); else - ERR_add_error_data(4, "name=", name, ", value=", value); + ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE, + "name=%s, value=%s", name, value); } else { rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max, tbl_mask, tbl_flags); if (!rv) - ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); } sk_CONF_VALUE_pop_free(lst, X509V3_conf_free); return rv; diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c --- a/crypto/asn1/asn_pack.c +++ b/crypto/asn1/asn_pack.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,7 +19,7 @@ if (oct == NULL || *oct == NULL) { if ((octmp = ASN1_STRING_new()) == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } } else { @@ -30,11 +30,11 @@ octmp->data = NULL; if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) { - ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ENCODE_ERROR); goto err; } if (octmp->data == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } @@ -57,6 +57,6 @@ p = oct->data; if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL) - ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); return ret; } diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c --- a/crypto/asn1/bio_asn1.c +++ b/crypto/asn1/bio_asn1.c @@ -1,7 +1,7 @@ /* * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -79,10 +79,8 @@ static const BIO_METHOD methods_asn1 = { BIO_TYPE_ASN1, "asn1", - /* TODO: Convert to new style write function */ bwrite_conv, asn1_bio_write, - /* TODO: Convert to new style read function */ bread_conv, asn1_bio_read, asn1_bio_puts, @@ -102,8 +100,10 @@ { BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) + if (ctx == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; + } if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) { OPENSSL_free(ctx); return 0; @@ -116,8 +116,8 @@ static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size) { - if ((ctx->buf = OPENSSL_malloc(size)) == NULL) { - ASN1err(ASN1_F_ASN1_BIO_INIT, ERR_R_MALLOC_FAILURE); + if (size <= 0 || (ctx->buf = OPENSSL_malloc(size)) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } ctx->bufsize = size; diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c --- a/crypto/asn1/bio_ndef.c +++ b/crypto/asn1/bio_ndef.c @@ -1,7 +1,7 @@ /* * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -64,7 +64,7 @@ BIO *pop_bio = NULL; if (!aux || !aux->asn1_cb) { - ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED); return NULL; } ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux)); @@ -132,7 +132,7 @@ unsigned char *p; int derlen; - if (!parg) + if (parg == NULL) return 0; ndef_aux = *(NDEF_SUPPORT **)parg; @@ -141,15 +141,15 @@ if (derlen < 0) return 0; if ((p = OPENSSL_malloc(derlen)) == NULL) { - ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } ndef_aux->derbuf = p; *pbuf = p; - derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); + ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); - if (!*ndef_aux->boundary) + if (*ndef_aux->boundary == NULL) return 0; *plen = *ndef_aux->boundary - *pbuf; @@ -162,7 +162,7 @@ { NDEF_SUPPORT *ndef_aux; - if (!parg) + if (parg == NULL) return 0; ndef_aux = *(NDEF_SUPPORT **)parg; @@ -197,7 +197,7 @@ const ASN1_AUX *aux; ASN1_STREAM_ARG sarg; - if (!parg) + if (parg == NULL) return 0; ndef_aux = *(NDEF_SUPPORT **)parg; @@ -213,8 +213,10 @@ return 0; derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); + if (derlen < 0) + return 0; if ((p = OPENSSL_malloc(derlen)) == NULL) { - ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } @@ -222,7 +224,7 @@ *pbuf = p; derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); - if (!*ndef_aux->boundary) + if (*ndef_aux->boundary == NULL) return 0; *pbuf = *ndef_aux->boundary; *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); diff --git a/crypto/asn1/build.info b/crypto/asn1/build.info --- a/crypto/asn1/build.info +++ b/crypto/asn1/build.info @@ -4,13 +4,20 @@ a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \ a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \ x_algor.c x_val.c x_sig.c x_bignum.c \ - x_long.c x_int64.c x_info.c x_spki.c nsseq.c \ - d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ + x_int64.c x_info.c x_spki.c nsseq.c \ + d2i_pu.c d2i_pr.c i2d_evp.c \ t_pkey.c t_spki.c t_bitst.c \ tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \ tasn_prn.c tasn_scn.c ameth_lib.c \ - f_int.c f_string.c n_pkey.c \ + f_int.c f_string.c \ x_pkey.c bio_asn1.c bio_ndef.c asn_mime.c \ - asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c \ + asn1_gen.c asn1_parse.c asn1_lib.c asn1_err.c a_strnid.c \ evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p5_scrypt.c p8_pkey.c \ - asn_moid.c asn_mstbl.c asn1_item_list.c + asn_moid.c asn_mstbl.c asn1_item_list.c \ + d2i_param.c +IF[{- !$disabled{'rsa'} and !$disabled{'rc4'} -}] + SOURCE[../../libcrypto]=n_pkey.c +ENDIF +IF[{- !$disabled{'deprecated-3.0'} -}] + SOURCE[../../libcrypto]=x_long.c +ENDIF diff --git a/crypto/asn1/charmap.h b/crypto/asn1/charmap.h --- a/crypto/asn1/charmap.h +++ b/crypto/asn1/charmap.h @@ -2,9 +2,9 @@ * WARNING: do not edit! * Generated by crypto/asn1/charmap.pl * - * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/charmap.pl b/crypto/asn1/charmap.pl --- a/crypto/asn1/charmap.pl +++ b/crypto/asn1/charmap.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -87,6 +87,7 @@ # Year the file was generated. my $YEAR = OpenSSL::copyright::year_of($0); + print < +#include "internal/cryptlib.h" +#include +#include +#include "internal/asn1.h" +#include "crypto/asn1.h" +#include "crypto/evp.h" + +EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp, + long length) +{ + EVP_PKEY *ret = NULL; + + if ((a == NULL) || (*a == NULL)) { + if ((ret = EVP_PKEY_new()) == NULL) + return NULL; + } else + ret = *a; + + if (type != EVP_PKEY_get_id(ret) && !EVP_PKEY_set_type(ret, type)) + goto err; + + if (ret->ameth == NULL || ret->ameth->param_decode == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE); + goto err; + } + + if (!ret->ameth->param_decode(ret, pp, length)) + goto err; + + if (a != NULL) + (*a) = ret; + return ret; +err: + if (a == NULL || *a != ret) + EVP_PKEY_free(ret); + return NULL; +} + +EVP_PKEY *d2i_KeyParams_bio(int type, EVP_PKEY **a, BIO *in) +{ + BUF_MEM *b = NULL; + const unsigned char *p; + void *ret = NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if (len < 0) + goto err; + + p = (unsigned char *)b->data; + ret = d2i_KeyParams(type, a, &p, len); +err: + BUF_MEM_free(b); + return ret; +} diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -1,32 +1,89 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* We need to use some engine deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include "internal/cryptlib.h" #include #include #include +#include #include #include #include #include "crypto/asn1.h" #include "crypto/evp.h" +#include "internal/asn1.h" -EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, - long length) +static EVP_PKEY * +d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, const char *propq) +{ + OSSL_DECODER_CTX *dctx = NULL; + size_t len = length; + EVP_PKEY *pkey = NULL, *bak_a = NULL; + EVP_PKEY **ppkey = &pkey; + const char *key_name = NULL; + const char *input_structures[] = { "type-specific", "PrivateKeyInfo", NULL }; + int i, ret; + + if (keytype != EVP_PKEY_NONE) { + key_name = evp_pkey_type2name(keytype); + if (key_name == NULL) + return NULL; + } + + for (i = 0; i < (int)OSSL_NELEM(input_structures); ++i) { + const unsigned char *p = *pp; + + if (a != NULL && (bak_a = *a) != NULL) + ppkey = a; + dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", + input_structures[i], key_name, + EVP_PKEY_KEYPAIR, libctx, propq); + if (a != NULL) + *a = bak_a; + if (dctx == NULL) + continue; + + ret = OSSL_DECODER_from_data(dctx, pp, &len); + OSSL_DECODER_CTX_free(dctx); + if (ret) { + if (*ppkey != NULL + && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) { + if (a != NULL) + *a = *ppkey; + return *ppkey; + } + *pp = p; + goto err; + } + } + /* Fall through to error if all decodes failed */ +err: + if (ppkey != a) + EVP_PKEY_free(*ppkey); + return NULL; +} + +EVP_PKEY * +ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, const char *propq) { EVP_PKEY *ret; const unsigned char *p = *pp; - if ((a == NULL) || (*a == NULL)) { + if (a == NULL || *a == NULL) { if ((ret = EVP_PKEY_new()) == NULL) { - ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return NULL; } } else { @@ -37,35 +94,45 @@ #endif } - if (!EVP_PKEY_set_type(ret, type)) { - ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); + if (!EVP_PKEY_set_type(ret, keytype)) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; } + ERR_set_mark(); if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &p, length)) { - if (ret->ameth->priv_decode) { + if (ret->ameth->priv_decode != NULL + || ret->ameth->priv_decode_ex != NULL) { EVP_PKEY *tmp; PKCS8_PRIV_KEY_INFO *p8 = NULL; p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); - if (!p8) + if (p8 == NULL) { + ERR_clear_last_mark(); goto err; - tmp = EVP_PKCS82PKEY(p8); + } + tmp = evp_pkcs82pkey_legacy(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); - if (tmp == NULL) + if (tmp == NULL) { + ERR_clear_last_mark(); goto err; + } EVP_PKEY_free(ret); ret = tmp; - if (EVP_PKEY_type(type) != EVP_PKEY_base_id(ret)) + ERR_pop_to_mark(); + if (EVP_PKEY_type(keytype) != EVP_PKEY_get_base_id(ret)) goto err; } else { - ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB); + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } + } else { + ERR_clear_last_mark(); } *pp = p; if (a != NULL) - (*a) = ret; + *a = ret; return ret; err: if (a == NULL || *a != ret) @@ -73,58 +140,36 @@ return NULL; } -/* - * This works like d2i_PrivateKey() except it automatically works out the - * type - */ - -static EVP_PKEY *key_as_pkcs8(const unsigned char **pp, long length, int *carry_on) +EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, + const char *propq) { - const unsigned char *p = *pp; - PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); EVP_PKEY *ret; - if (p8 == NULL) - return NULL; - - ret = EVP_PKCS82PKEY(p8); + ret = d2i_PrivateKey_decoder(keytype, a, pp, length, libctx, propq); + /* try the legacy path if the decoder failed */ if (ret == NULL) - *carry_on = 0; - - PKCS8_PRIV_KEY_INFO_free(p8); - - if (ret != NULL) - *pp = p; - + ret = ossl_d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq); return ret; } -EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, - long length) +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length) +{ + return d2i_PrivateKey_ex(type, a, pp, length, NULL, NULL); +} + +static EVP_PKEY *d2i_AutoPrivateKey_legacy(EVP_PKEY **a, + const unsigned char **pp, + long length, + OSSL_LIB_CTX *libctx, + const char *propq) { STACK_OF(ASN1_TYPE) *inkey; const unsigned char *p; int keytype; - EVP_PKEY *ret = NULL; - int carry_on = 1; - - ERR_set_mark(); - ret = key_as_pkcs8(pp, length, &carry_on); - if (ret != NULL) { - ERR_clear_last_mark(); - if (a != NULL) - *a = ret; - return ret; - } - if (carry_on == 0) { - ERR_clear_last_mark(); - ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY, - ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return NULL; - } p = *pp; - /* * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by * analyzing it we can determine the passed structure: this assumes the @@ -136,19 +181,55 @@ * Since we only need to discern "traditional format" RSA and DSA keys we * can just count the elements. */ - if (sk_ASN1_TYPE_num(inkey) == 6) + if (sk_ASN1_TYPE_num(inkey) == 6) { keytype = EVP_PKEY_DSA; - else if (sk_ASN1_TYPE_num(inkey) == 4) + } else if (sk_ASN1_TYPE_num(inkey) == 4) { keytype = EVP_PKEY_EC; - else + } else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not + * traditional format */ + PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); + EVP_PKEY *ret; + + sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); + if (p8 == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return NULL; + } + ret = evp_pkcs82pkey_legacy(p8, libctx, propq); + PKCS8_PRIV_KEY_INFO_free(p8); + if (ret == NULL) + return NULL; + *pp = p; + if (a != NULL) { + *a = ret; + } + return ret; + } else { keytype = EVP_PKEY_RSA; + } sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); + return ossl_d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq); +} - ret = d2i_PrivateKey(keytype, a, pp, length); - if (ret != NULL) - ERR_pop_to_mark(); - else - ERR_clear_last_mark(); +/* + * This works like d2i_PrivateKey() except it passes the keytype as + * EVP_PKEY_NONE, which then figures out the type during decoding. + */ +EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, + const char *propq) +{ + EVP_PKEY *ret; + ret = d2i_PrivateKey_decoder(EVP_PKEY_NONE, a, pp, length, libctx, propq); + /* try the legacy path if the decoder failed */ + if (ret == NULL) + ret = d2i_AutoPrivateKey_legacy(a, pp, length, libctx, propq); return ret; } + +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, + long length) +{ + return d2i_AutoPrivateKey_ex(a, pp, length, NULL, NULL); +} diff --git a/crypto/asn1/d2i_pu.c b/crypto/asn1/d2i_pu.c --- a/crypto/asn1/d2i_pu.c +++ b/crypto/asn1/d2i_pu.c @@ -1,12 +1,18 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * DSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include #include "internal/cryptlib.h" #include @@ -23,55 +29,70 @@ long length) { EVP_PKEY *ret; + EVP_PKEY *copy = NULL; if ((a == NULL) || (*a == NULL)) { if ((ret = EVP_PKEY_new()) == NULL) { - ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return NULL; } - } else + } else { ret = *a; - if (type != EVP_PKEY_id(ret) && !EVP_PKEY_set_type(ret, type)) { - ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); +#ifndef OPENSSL_NO_EC + if (evp_pkey_is_provided(ret) + && EVP_PKEY_get_base_id(ret) == EVP_PKEY_EC) { + if (!evp_pkey_copy_downgraded(©, ret)) + goto err; + } +#endif + } + + if ((type != EVP_PKEY_get_id(ret) || copy != NULL) + && !EVP_PKEY_set_type(ret, type)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } - switch (EVP_PKEY_id(ret)) { -#ifndef OPENSSL_NO_RSA + switch (EVP_PKEY_get_base_id(ret)) { case EVP_PKEY_RSA: if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) { - ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } break; -#endif #ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: - /* TMP UGLY CAST */ if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) { - ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } break; #endif #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: + if (copy != NULL) { + /* use downgraded parameters from copy */ + ret->pkey.ec = copy->pkey.ec; + copy->pkey.ec = NULL; + } if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) { - ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } break; #endif default: - ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; } if (a != NULL) (*a) = ret; + EVP_PKEY_free(copy); return ret; err: if (a == NULL || *a != ret) EVP_PKEY_free(ret); + EVP_PKEY_free(copy); return NULL; } diff --git a/crypto/asn1/evp_asn1.c b/crypto/asn1/evp_asn1.c --- a/crypto/asn1/evp_asn1.c +++ b/crypto/asn1/evp_asn1.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,6 +11,7 @@ #include "internal/cryptlib.h" #include #include +#include "crypto/asn1.h" int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len) { @@ -26,14 +27,17 @@ return 1; } -/* int max_len: for returned value */ +/* int max_len: for returned value + * if passing NULL in data, nothing is copied but the necessary length + * for it is returned. + */ int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len) { int ret, num; const unsigned char *p; if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) { - ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG); return -1; } p = ASN1_STRING_get0_data(a->value.octet_string); @@ -42,7 +46,36 @@ num = ret; else num = max_len; - memcpy(data, p, num); + if (num > 0 && data != NULL) + memcpy(data, p, num); + return ret; +} + +static ossl_inline void asn1_type_init_oct(ASN1_OCTET_STRING *oct, + unsigned char *data, int len) +{ + oct->data = data; + oct->type = V_ASN1_OCTET_STRING; + oct->length = len; + oct->flags = 0; +} + +static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum, + long *num, unsigned char *data, int max_len) +{ + int ret = ASN1_STRING_length(oct), n; + + if (num != NULL) + *num = anum; + + if (max_len > ret) + n = ret; + else + n = max_len; + + if (data != NULL) + memcpy(data, ASN1_STRING_get0_data(oct), n); + return ret; } @@ -66,25 +99,18 @@ atmp.num = num; atmp.oct = &oct; - oct.data = data; - oct.type = V_ASN1_OCTET_STRING; - oct.length = len; - oct.flags = 0; + asn1_type_init_oct(&oct, data, len); if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a)) return 1; return 0; } -/* - * we return the actual length... - */ -/* int max_len: for returned value */ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, unsigned char *data, int max_len) { asn1_int_oct *atmp = NULL; - int ret = -1, n; + int ret = -1; if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) { goto err; @@ -95,21 +121,67 @@ if (atmp == NULL) goto err; - if (num != NULL) - *num = atmp->num; + ret = asn1_type_get_int_oct(atmp->oct, atmp->num, num, data, max_len); - ret = ASN1_STRING_length(atmp->oct); - if (max_len > ret) - n = ret; - else - n = max_len; - - if (data != NULL) - memcpy(data, ASN1_STRING_get0_data(atmp->oct), n); if (ret == -1) { err: - ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG); } M_ASN1_free_of(atmp, asn1_int_oct); return ret; } + +typedef struct { + ASN1_OCTET_STRING *oct; + int32_t num; +} asn1_oct_int; + +/* + * Defined in RFC 5084 - + * Section 2. "Content-Authenticated Encryption Algorithms" + */ +ASN1_SEQUENCE(asn1_oct_int) = { + ASN1_SIMPLE(asn1_oct_int, oct, ASN1_OCTET_STRING), + ASN1_EMBED(asn1_oct_int, num, INT32) +} static_ASN1_SEQUENCE_END(asn1_oct_int) + +DECLARE_ASN1_ITEM(asn1_oct_int) + +int ossl_asn1_type_set_octetstring_int(ASN1_TYPE *a, long num, + unsigned char *data, int len) +{ + asn1_oct_int atmp; + ASN1_OCTET_STRING oct; + + atmp.num = num; + atmp.oct = &oct; + asn1_type_init_oct(&oct, data, len); + + if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_oct_int), &atmp, &a)) + return 1; + return 0; +} + +int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len) +{ + asn1_oct_int *atmp = NULL; + int ret = -1; + + if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) + goto err; + + atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_oct_int), a); + + if (atmp == NULL) + goto err; + + ret = asn1_type_get_int_oct(atmp->oct, atmp->num, num, data, max_len); + + if (ret == -1) { + err: + ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG); + } + M_ASN1_free_of(atmp, asn1_oct_int); + return ret; +} diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c --- a/crypto/asn1/f_int.c +++ b/crypto/asn1/f_int.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -100,7 +100,7 @@ k = 0; i -= again; if (i % 2 != 0) { - ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS); OPENSSL_free(s); return 0; } @@ -108,7 +108,7 @@ if (num + i > slen) { sp = OPENSSL_clear_realloc(s, slen, num + i * 2); if (sp == NULL) { - ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); OPENSSL_free(s); return 0; } @@ -119,8 +119,7 @@ for (n = 0; n < 2; n++) { m = OPENSSL_hexchar2int(bufp[k + n]); if (m < 0) { - ASN1err(ASN1_F_A2I_ASN1_INTEGER, - ASN1_R_NON_HEX_CHARACTERS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS); goto err; } s[num + j] <<= 4; @@ -137,7 +136,7 @@ bs->data = s; return 1; err: - ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE); OPENSSL_free(s); return 0; } diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c --- a/crypto/asn1/f_string.c +++ b/crypto/asn1/f_string.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -91,7 +91,7 @@ k = 0; i -= again; if (i % 2 != 0) { - ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS); OPENSSL_free(s); return 0; } @@ -99,7 +99,7 @@ if (num + i > slen) { sp = OPENSSL_realloc(s, (unsigned int)num + i * 2); if (sp == NULL) { - ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); OPENSSL_free(s); return 0; } @@ -110,8 +110,7 @@ for (n = 0; n < 2; n++) { m = OPENSSL_hexchar2int(bufp[k + n]); if (m < 0) { - ASN1err(ASN1_F_A2I_ASN1_STRING, - ASN1_R_NON_HEX_CHARACTERS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS); OPENSSL_free(s); return 0; } @@ -130,7 +129,7 @@ return 1; err: - ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE); OPENSSL_free(s); return 0; } diff --git a/crypto/asn1/i2d_evp.c b/crypto/asn1/i2d_evp.c new file mode 100644 --- /dev/null +++ b/crypto/asn1/i2d_evp.c @@ -0,0 +1,149 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +/* + * Low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include /* For i2d_RSAPublicKey */ +#include /* For i2d_DSAPublicKey */ +#include /* For i2o_ECPublicKey */ +#include "crypto/asn1.h" +#include "crypto/evp.h" + +struct type_and_structure_st { + const char *output_type; + const char *output_structure; +}; + +static int i2d_provided(const EVP_PKEY *a, int selection, + const struct type_and_structure_st *output_info, + unsigned char **pp) +{ + OSSL_ENCODER_CTX *ctx = NULL; + int ret; + + for (ret = -1; + ret == -1 && output_info->output_type != NULL; + output_info++) { + /* + * The i2d_ calls don't take a boundary length for *pp. However, + * OSSL_ENCODER_to_data() needs one, so we make one up. Because + * OSSL_ENCODER_to_data() decrements this number by the amount of + * bytes written, we need to calculate the length written further + * down, when pp != NULL. + */ + size_t len = INT_MAX; + int pp_was_NULL = (pp == NULL || *pp == NULL); + + ctx = OSSL_ENCODER_CTX_new_for_pkey(a, selection, + output_info->output_type, + output_info->output_structure, + NULL); + if (ctx == NULL) + return -1; + if (OSSL_ENCODER_to_data(ctx, pp, &len)) { + if (pp_was_NULL) + ret = (int)len; + else + ret = INT_MAX - (int)len; + } + OSSL_ENCODER_CTX_free(ctx); + ctx = NULL; + } + + if (ret == -1) + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE); + return ret; +} + +int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp) +{ + if (evp_pkey_is_provided(a)) { + static const struct type_and_structure_st output_info[] = { + { "DER", "type-specific" }, + { NULL, } + }; + + return i2d_provided(a, EVP_PKEY_KEY_PARAMETERS, output_info, pp); + } + if (a->ameth != NULL && a->ameth->param_encode != NULL) + return a->ameth->param_encode(a, pp); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE); + return -1; +} + +int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey) +{ + return ASN1_i2d_bio_of(EVP_PKEY, i2d_KeyParams, bp, pkey); +} + +int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp) +{ + if (evp_pkey_is_provided(a)) { + static const struct type_and_structure_st output_info[] = { + { "DER", "type-specific" }, + { "DER", "PrivateKeyInfo" }, + { NULL, } + }; + + return i2d_provided(a, EVP_PKEY_KEYPAIR, output_info, pp); + } + if (a->ameth != NULL && a->ameth->old_priv_encode != NULL) { + return a->ameth->old_priv_encode(a, pp); + } + if (a->ameth != NULL && a->ameth->priv_encode != NULL) { + PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a); + int ret = 0; + + if (p8 != NULL) { + ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp); + PKCS8_PRIV_KEY_INFO_free(p8); + } + return ret; + } + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; +} + +int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp) +{ + if (evp_pkey_is_provided(a)) { + static const struct type_and_structure_st output_info[] = { + { "DER", "type-specific" }, + { "blob", NULL }, /* for EC */ + { NULL, } + }; + + return i2d_provided(a, EVP_PKEY_PUBLIC_KEY, output_info, pp); + } + switch (EVP_PKEY_get_base_id(a)) { + case EVP_PKEY_RSA: + return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp); +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp); +#endif +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp); +#endif + default: + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return -1; + } +} diff --git a/crypto/asn1/i2d_pr.c b/crypto/asn1/i2d_pr.c deleted file mode 100644 --- a/crypto/asn1/i2d_pr.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include "crypto/asn1.h" -#include "crypto/evp.h" - -int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp) -{ - if (a->ameth && a->ameth->old_priv_encode) { - return a->ameth->old_priv_encode(a, pp); - } - if (a->ameth && a->ameth->priv_encode) { - PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a); - int ret = 0; - if (p8 != NULL) { - ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp); - PKCS8_PRIV_KEY_INFO_free(p8); - } - return ret; - } - ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return -1; -} diff --git a/crypto/asn1/i2d_pu.c b/crypto/asn1/i2d_pu.c deleted file mode 100644 --- a/crypto/asn1/i2d_pu.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "internal/cryptlib.h" -#include -#include -#include -#include -#include -#include - -int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) -{ - switch (EVP_PKEY_id(a)) { -#ifndef OPENSSL_NO_RSA - case EVP_PKEY_RSA: - return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp); -#endif -#ifndef OPENSSL_NO_DSA - case EVP_PKEY_DSA: - return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp); -#endif -#ifndef OPENSSL_NO_EC - case EVP_PKEY_EC: - return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp); -#endif - default: - ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return -1; - } -} diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c --- a/crypto/asn1/n_pkey.c +++ b/crypto/asn1/n_pkey.c @@ -1,26 +1,26 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ -#include "openssl/opensslconf.h" -#ifdef OPENSSL_NO_RSA -NON_EMPTY_TRANSLATION_UNIT -#else - -# include "internal/cryptlib.h" -# include -# include -# include -# include -# include -# include - -# ifndef OPENSSL_NO_RC4 +#include +#include "internal/cryptlib.h" +#include +#include +#include +#include +#include +#include + +#define ASN1_BROKEN_SEQUENCE(tname) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \ + ASN1_SEQUENCE(tname) +#define static_ASN1_BROKEN_SEQUENCE_END(stname) \ + static_ASN1_SEQUENCE_END_ref(stname, stname) typedef struct netscape_pkey_st { int32_t version; @@ -43,9 +43,9 @@ ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG) } static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY) -DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY) -IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_ENCRYPTED_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_name(NETSCAPE_ENCRYPTED_PKEY, NETSCAPE_ENCRYPTED_PKEY) +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_ENCRYPTED_PKEY) ASN1_SEQUENCE(NETSCAPE_PKEY) = { ASN1_EMBED(NETSCAPE_PKEY, version, INT32), @@ -53,10 +53,6 @@ ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING) } static_ASN1_SEQUENCE_END(NETSCAPE_PKEY) -DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY) -IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) - -# endif /* OPENSSL_NO_RC4 */ - -#endif +DECLARE_ASN1_FUNCTIONS(NETSCAPE_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_name(NETSCAPE_PKEY, NETSCAPE_PKEY) +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_PKEY) diff --git a/crypto/asn1/nsseq.c b/crypto/asn1/nsseq.c --- a/crypto/asn1/nsseq.c +++ b/crypto/asn1/nsseq.c @@ -1,7 +1,7 @@ /* * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c --- a/crypto/asn1/p5_pbe.c +++ b/crypto/asn1/p5_pbe.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -24,8 +24,9 @@ /* Set an algorithm identifier for a PKCS#5 PBE algorithm */ -int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, - const unsigned char *salt, int saltlen) +int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen, + OSSL_LIB_CTX *ctx) { PBEPARAM *pbe = NULL; ASN1_STRING *pbe_str = NULL; @@ -33,33 +34,35 @@ pbe = PBEPARAM_new(); if (pbe == NULL) { - ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } if (iter <= 0) iter = PKCS5_DEFAULT_ITER; if (!ASN1_INTEGER_set(pbe->iter, iter)) { - ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } if (!saltlen) saltlen = PKCS5_SALT_LEN; + if (saltlen < 0) + goto err; sstr = OPENSSL_malloc(saltlen); if (sstr == NULL) { - ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } if (salt) memcpy(sstr, salt, saltlen); - else if (RAND_bytes(sstr, saltlen) <= 0) + else if (RAND_bytes_ex(ctx, sstr, saltlen, 0) <= 0) goto err; ASN1_STRING_set0(pbe->salt, sstr, saltlen); sstr = NULL; if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) { - ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } @@ -76,21 +79,35 @@ return 0; } +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen) +{ + return PKCS5_pbe_set0_algor_ex(algor, alg, iter, salt, saltlen, NULL); +} + /* Return an algorithm identifier for a PKCS#5 PBE algorithm */ -X509_ALGOR *PKCS5_pbe_set(int alg, int iter, - const unsigned char *salt, int saltlen) +X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter, + const unsigned char *salt, int saltlen, + OSSL_LIB_CTX *ctx) { X509_ALGOR *ret; ret = X509_ALGOR_new(); if (ret == NULL) { - ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } - if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen)) + if (PKCS5_pbe_set0_algor_ex(ret, alg, iter, salt, saltlen, ctx)) return ret; X509_ALGOR_free(ret); return NULL; } + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen) +{ + return PKCS5_pbe_set_ex(alg, iter, salt, saltlen, NULL); +} + diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c --- a/crypto/asn1/p5_pbev2.c +++ b/crypto/asn1/p5_pbev2.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,6 +10,8 @@ #include #include "internal/cryptlib.h" #include +#include +#include #include #include @@ -37,20 +39,20 @@ * and IV. */ -X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, - unsigned char *salt, int saltlen, - unsigned char *aiv, int prf_nid) +X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid, + OSSL_LIB_CTX *libctx) { X509_ALGOR *scheme = NULL, *ret = NULL; - int alg_nid, keylen; + int alg_nid, keylen, ivlen; EVP_CIPHER_CTX *ctx = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; PBE2PARAM *pbe2 = NULL; - alg_nid = EVP_CIPHER_type(cipher); + alg_nid = EVP_CIPHER_get_type(cipher); if (alg_nid == NID_undef) { - ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, - ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); goto err; } @@ -64,10 +66,11 @@ goto merr; /* Create random IV */ - if (EVP_CIPHER_iv_length(cipher)) { + ivlen = EVP_CIPHER_get_iv_length(cipher); + if (ivlen > 0) { if (aiv) - memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); - else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0) + memcpy(iv, aiv, ivlen); + else if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0) goto err; } @@ -79,25 +82,26 @@ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0)) goto err; if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) { - ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); goto err; } /* * If prf NID unspecified see if cipher has a preference. An error is OK * here: just means use default PRF. */ + ERR_set_mark(); if ((prf_nid == -1) && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) { - ERR_clear_error(); prf_nid = NID_hmacWithSHA256; } + ERR_pop_to_mark(); EVP_CIPHER_CTX_free(ctx); ctx = NULL; /* If its RC2 then we'd better setup the key length */ if (alg_nid == NID_rc2_cbc) - keylen = EVP_CIPHER_key_length(cipher); + keylen = EVP_CIPHER_get_key_length(cipher); else keylen = -1; @@ -105,9 +109,10 @@ X509_ALGOR_free(pbe2->keyfunc); - pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen); + pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, + libctx); - if (!pbe2->keyfunc) + if (pbe2->keyfunc == NULL) goto merr; /* Now set up top level AlgorithmIdentifier */ @@ -129,7 +134,7 @@ return ret; merr: - ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); err: EVP_CIPHER_CTX_free(ctx); @@ -140,14 +145,25 @@ return NULL; } +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid) +{ + return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, aiv, prf_nid, + NULL); +} + X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, unsigned char *salt, int saltlen) { - return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1); + return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1, + NULL); } -X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, - int prf_nid, int keylen) + +X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen, + OSSL_LIB_CTX *libctx) { X509_ALGOR *keyfunc = NULL; PBKDF2PARAM *kdf = NULL; @@ -161,6 +177,8 @@ kdf->salt->value.octet_string = osalt; kdf->salt->type = V_ASN1_OCTET_STRING; + if (saltlen < 0) + goto merr; if (saltlen == 0) saltlen = PKCS5_SALT_LEN; if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL) @@ -170,7 +188,7 @@ if (salt) memcpy(osalt->data, salt, saltlen); - else if (RAND_bytes(osalt->data, saltlen) <= 0) + else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0) goto merr; if (iter <= 0) @@ -214,8 +232,15 @@ return keyfunc; merr: - ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); PBKDF2PARAM_free(kdf); X509_ALGOR_free(keyfunc); return NULL; } + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen) +{ + return PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, NULL); +} + diff --git a/crypto/asn1/p5_scrypt.c b/crypto/asn1/p5_scrypt.c --- a/crypto/asn1/p5_scrypt.c +++ b/crypto/asn1/p5_scrypt.c @@ -1,7 +1,7 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,10 +10,12 @@ #include #include "internal/cryptlib.h" #include +#include #include #include #include #include +#include "crypto/evp.h" #ifndef OPENSSL_NO_SCRYPT /* PKCS#5 scrypt password based encryption structures */ @@ -49,20 +51,18 @@ PBE2PARAM *pbe2 = NULL; if (!cipher) { - ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); goto err; } if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { - ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, - ASN1_R_INVALID_SCRYPT_PARAMETERS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_SCRYPT_PARAMETERS); goto err; } - alg_nid = EVP_CIPHER_type(cipher); + alg_nid = EVP_CIPHER_get_type(cipher); if (alg_nid == NID_undef) { - ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, - ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); goto err; } @@ -79,10 +79,10 @@ goto merr; /* Create random IV */ - if (EVP_CIPHER_iv_length(cipher)) { + if (EVP_CIPHER_get_iv_length(cipher)) { if (aiv) - memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); - else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0) + memcpy(iv, aiv, EVP_CIPHER_get_iv_length(cipher)); + else if (RAND_bytes(iv, EVP_CIPHER_get_iv_length(cipher)) <= 0) goto err; } @@ -94,8 +94,7 @@ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0) goto err; if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) { - ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, - ASN1_R_ERROR_SETTING_CIPHER_PARAMS); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); goto err; } EVP_CIPHER_CTX_free(ctx); @@ -104,7 +103,7 @@ /* If its RC2 then we'd better setup the key length */ if (alg_nid == NID_rc2_cbc) - keylen = EVP_CIPHER_key_length(cipher); + keylen = EVP_CIPHER_get_key_length(cipher); /* Setup keyfunc */ @@ -135,7 +134,7 @@ return ret; merr: - ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); err: PBE2PARAM_free(pbe2); @@ -202,26 +201,27 @@ return keyfunc; merr: - ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); err: SCRYPT_PARAMS_free(sparam); X509_ALGOR_free(keyfunc); return NULL; } -int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, - int passlen, ASN1_TYPE *param, - const EVP_CIPHER *c, const EVP_MD *md, int en_de) +int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, int en_de, + OSSL_LIB_CTX *libctx, const char *propq) { unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; uint64_t p, r, N; size_t saltlen; size_t keylen = 0; - int rv = 0; + int t, rv = 0; SCRYPT_PARAMS *sparam = NULL; - if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { - EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET); + if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET); goto err; } @@ -230,11 +230,16 @@ sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param); if (sparam == NULL) { - EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR); + ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR); goto err; } - keylen = EVP_CIPHER_CTX_key_length(ctx); + t = EVP_CIPHER_CTX_get_key_length(ctx); + if (t < 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + goto err; + } + keylen = t; /* Now check the parameters of sparam */ @@ -242,8 +247,7 @@ uint64_t spkeylen; if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0) || (spkeylen != keylen)) { - EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, - EVP_R_UNSUPPORTED_KEYLENGTH); + ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEYLENGTH); goto err; } } @@ -251,9 +255,9 @@ if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0 || ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0 || ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0 - || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { - EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, - EVP_R_ILLEGAL_SCRYPT_PARAMETERS); + || EVP_PBE_scrypt_ex(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0, + libctx, propq) == 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_ILLEGAL_SCRYPT_PARAMETERS); goto err; } @@ -261,8 +265,8 @@ salt = sparam->salt->data; saltlen = sparam->salt->length; - if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen) - == 0) + if (EVP_PBE_scrypt_ex(pass, passlen, salt, saltlen, N, r, p, 0, key, + keylen, libctx, propq) == 0) goto err; rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); err: @@ -271,4 +275,12 @@ SCRYPT_PARAMS_free(sparam); return rv; } + +int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *c, const EVP_MD *md, int en_de) +{ + return PKCS5_v2_scrypt_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de, NULL, NULL); +} + #endif /* OPENSSL_NO_SCRYPT */ diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c --- a/crypto/asn1/p8_pkey.c +++ b/crypto/asn1/p8_pkey.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -78,3 +78,14 @@ return 1; return 0; } + +int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) +{ + return (X509at_add1_attr_by_OBJ(&p8->attributes, obj, type, bytes, len) != NULL); +} + +int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr) +{ + return (X509at_add1_attr(&p8->attributes, attr) != NULL); +} diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h --- a/crypto/asn1/standard_methods.h +++ b/crypto/asn1/standard_methods.h @@ -1,7 +1,7 @@ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -13,49 +13,35 @@ * is used to search it. */ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { -#ifndef OPENSSL_NO_RSA - &rsa_asn1_meths[0], - &rsa_asn1_meths[1], -#endif + &ossl_rsa_asn1_meths[0], + &ossl_rsa_asn1_meths[1], #ifndef OPENSSL_NO_DH - &dh_asn1_meth, + &ossl_dh_asn1_meth, #endif #ifndef OPENSSL_NO_DSA - &dsa_asn1_meths[0], - &dsa_asn1_meths[1], - &dsa_asn1_meths[2], - &dsa_asn1_meths[3], - &dsa_asn1_meths[4], + &ossl_dsa_asn1_meths[0], + &ossl_dsa_asn1_meths[1], + &ossl_dsa_asn1_meths[2], + &ossl_dsa_asn1_meths[3], + &ossl_dsa_asn1_meths[4], #endif #ifndef OPENSSL_NO_EC - &eckey_asn1_meth, -#endif - &hmac_asn1_meth, -#ifndef OPENSSL_NO_CMAC - &cmac_asn1_meth, -#endif -#ifndef OPENSSL_NO_RSA - &rsa_pss_asn1_meth, + &ossl_eckey_asn1_meth, #endif + &ossl_rsa_pss_asn1_meth, #ifndef OPENSSL_NO_DH - &dhx_asn1_meth, + &ossl_dhx_asn1_meth, #endif #ifndef OPENSSL_NO_EC - &ecx25519_asn1_meth, - &ecx448_asn1_meth, -#endif -#ifndef OPENSSL_NO_POLY1305 - &poly1305_asn1_meth, -#endif -#ifndef OPENSSL_NO_SIPHASH - &siphash_asn1_meth, + &ossl_ecx25519_asn1_meth, + &ossl_ecx448_asn1_meth, #endif #ifndef OPENSSL_NO_EC - &ed25519_asn1_meth, - &ed448_asn1_meth, + &ossl_ed25519_asn1_meth, + &ossl_ed448_asn1_meth, #endif #ifndef OPENSSL_NO_SM2 - &sm2_asn1_meth, + &ossl_sm2_asn1_meth, #endif }; diff --git a/crypto/asn1/t_bitst.c b/crypto/asn1/t_bitst.c --- a/crypto/asn1/t_bitst.c +++ b/crypto/asn1/t_bitst.c @@ -1,7 +1,7 @@ /* * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/t_pkey.c b/crypto/asn1/t_pkey.c --- a/crypto/asn1/t_pkey.c +++ b/crypto/asn1/t_pkey.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/t_spki.c b/crypto/asn1/t_spki.c --- a/crypto/asn1/t_spki.c +++ b/crypto/asn1/t_spki.c @@ -1,7 +1,7 @@ /* * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -30,7 +30,7 @@ BIO_printf(out, " Public Key Algorithm: %s\n", (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i)); pkey = X509_PUBKEY_get(spki->spkac->pubkey); - if (!pkey) + if (pkey == NULL) BIO_printf(out, " Unable to load public key\n"); else { EVP_PKEY_print_public(out, pkey, 4, NULL); diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -17,7 +17,6 @@ #include "internal/numbers.h" #include "asn1_local.h" - /* * Constructed types with a recursive definition (such as can be found in PKCS7) * could eventually exceed the stack given malicious input with excessive @@ -29,7 +28,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx, - int depth); + int depth, OSSL_LIB_CTX *libctx, + const char *propq); static int asn1_check_eoc(const unsigned char **in, long len); static int asn1_find_end(const unsigned char **in, long len, char inf); @@ -47,11 +47,13 @@ static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx, int depth); + ASN1_TLC *ctx, int depth, OSSL_LIB_CTX *libctx, + const char *propq); static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx, int depth); + ASN1_TLC *ctx, int depth, + OSSL_LIB_CTX *libctx, const char *propq); static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, @@ -67,7 +69,7 @@ /* tags 4- 7 */ B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, /* tags 8-11 */ - B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, + B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 0, B_ASN1_UNKNOWN, /* tags 12-15 */ B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags 16-19 */ @@ -91,9 +93,9 @@ /* Macro to initialize and invalidate the cache */ -#define asn1_tlc_clear(c) if (c) (c)->valid = 0 +#define asn1_tlc_clear(c) do { if ((c) != NULL) (c)->valid = 0; } while (0) /* Version to avoid compiler warning about 'c' always non-NULL */ -#define asn1_tlc_clear_nc(c) (c)->valid = 0 +#define asn1_tlc_clear_nc(c) do {(c)->valid = 0; } while (0) /* * Decode an ASN1 item, this currently behaves just like a standard 'd2i' @@ -102,29 +104,54 @@ * this will simply be a special case. */ -ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, - const unsigned char **in, long len, - const ASN1_ITEM *it) +static int asn1_item_ex_d2i_intern(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, + int aclass, char opt, ASN1_TLC *ctx, + OSSL_LIB_CTX *libctx, const char *propq) +{ + int rv; + + if (pval == NULL || it == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0, + libctx, propq); + if (rv <= 0) + ASN1_item_ex_free(pval, it); + return rv; +} + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + return asn1_item_ex_d2i_intern(pval, in, len, it, tag, aclass, opt, ctx, + NULL, NULL); +} + +ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_ITEM *it, OSSL_LIB_CTX *libctx, + const char *propq) { ASN1_TLC c; ASN1_VALUE *ptmpval = NULL; - if (!pval) + + if (pval == NULL) pval = &ptmpval; asn1_tlc_clear_nc(&c); - if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) + if (asn1_item_ex_d2i_intern(pval, in, len, it, -1, 0, 0, &c, libctx, + propq) > 0) return *pval; return NULL; } -int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, - const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx) +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, + const unsigned char **in, long len, + const ASN1_ITEM *it) { - int rv; - rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); - if (rv <= 0) - ASN1_item_ex_free(pval, it); - return rv; + return ASN1_item_d2i_ex(pval, in, len, it, NULL, NULL); } /* @@ -135,11 +162,12 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx, - int depth) + int depth, OSSL_LIB_CTX *libctx, + const char *propq) { const ASN1_TEMPLATE *tt, *errtt = NULL; const ASN1_EXTERN_FUNCS *ef; - const ASN1_AUX *aux = it->funcs; + const ASN1_AUX *aux; ASN1_aux_cb *asn1_cb; const unsigned char *p = NULL, *q; unsigned char oclass; @@ -149,15 +177,23 @@ int otag; int ret = 0; ASN1_VALUE **pchptr; - if (!pval) + + if (pval == NULL || it == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER); return 0; + } + if (len <= 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); + return 0; + } + aux = it->funcs; if (aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; else asn1_cb = 0; if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NESTED_TOO_DEEP); goto err; } @@ -171,12 +207,12 @@ * template in the template itself. */ if ((tag != -1) || opt) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, - ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); + ERR_raise(ERR_LIB_ASN1, + ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); goto err; } - return asn1_template_ex_d2i(pval, in, len, - it->templates, opt, ctx, depth); + return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx, + depth, libctx, propq); } return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt, ctx); @@ -187,7 +223,7 @@ * if tag != -1, then this looks like an error in the template. */ if (tag != -1) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_BAD_TEMPLATE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE); goto err; } @@ -196,7 +232,7 @@ ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, &p, len, -1, 0, 1, ctx); if (!ret) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } @@ -205,7 +241,7 @@ /* If OPTIONAL, assume this is OK */ if (opt) return -1; - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL); goto err; } @@ -214,7 +250,7 @@ /* If OPTIONAL, assume this is OK */ if (opt) return -1; - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_WRONG_TAG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_WRONG_TAG); goto err; } return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); @@ -222,6 +258,9 @@ case ASN1_ITYPE_EXTERN: /* Use new style d2i */ ef = it->funcs; + if (ef->asn1_ex_d2i_ex != NULL) + return ef->asn1_ex_d2i_ex(pval, in, len, it, tag, aclass, opt, ctx, + libctx, propq); return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); case ASN1_ITYPE_CHOICE: @@ -230,7 +269,7 @@ * if tag != -1, then this looks like an error in the template. */ if (tag != -1) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_BAD_TEMPLATE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE); goto err; } @@ -238,25 +277,26 @@ goto auxerr; if (*pval) { /* Free up and zero CHOICE value if initialised */ - i = asn1_get_choice_selector(pval, it); + i = ossl_asn1_get_choice_selector(pval, it); if ((i >= 0) && (i < it->tcount)) { tt = it->templates + i; - pchptr = asn1_get_field_ptr(pval, tt); - asn1_template_free(pchptr, tt); - asn1_set_choice_selector(pval, -1, it); + pchptr = ossl_asn1_get_field_ptr(pval, tt); + ossl_asn1_template_free(pchptr, tt); + ossl_asn1_set_choice_selector(pval, -1, it); } - } else if (!ASN1_item_ex_new(pval, it)) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + } else if (!ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } /* CHOICE type, try each possibility in turn */ p = *in; for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { - pchptr = asn1_get_field_ptr(pval, tt); + pchptr = ossl_asn1_get_field_ptr(pval, tt); /* * We mark field as OPTIONAL so its absence can be recognised. */ - ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth); + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth, + libctx, propq); /* If field not present, try the next one */ if (ret == -1) continue; @@ -267,9 +307,9 @@ * Must be an ASN1 parsing error. * Free up any partial choice value */ - asn1_template_free(pchptr, tt); + ossl_asn1_template_free(pchptr, tt); errtt = tt; - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } @@ -281,11 +321,11 @@ ASN1_item_ex_free(pval, it); return -1; } - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); goto err; } - asn1_set_choice_selector(pval, i, it); + ossl_asn1_set_choice_selector(pval, i, it); if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) goto auxerr; @@ -306,7 +346,7 @@ ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, &p, len, tag, aclass, opt, ctx); if (!ret) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } else if (ret == -1) return -1; @@ -318,12 +358,13 @@ else seq_nolen = seq_eoc; if (!cst) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); goto err; } - if (!*pval && !ASN1_item_ex_new(pval, it)) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); + if (*pval == NULL + && !ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } @@ -335,11 +376,11 @@ if (tt->flags & ASN1_TFLG_ADB_MASK) { const ASN1_TEMPLATE *seqtt; ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 0); + seqtt = ossl_asn1_do_adb(*pval, tt, 0); if (seqtt == NULL) continue; - pseqval = asn1_get_field_ptr(pval, seqtt); - asn1_template_free(pseqval, seqtt); + pseqval = ossl_asn1_get_field_ptr(pval, seqtt); + ossl_asn1_template_free(pseqval, seqtt); } } @@ -347,22 +388,21 @@ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { const ASN1_TEMPLATE *seqtt; ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 1); + seqtt = ossl_asn1_do_adb(*pval, tt, 1); if (seqtt == NULL) goto err; - pseqval = asn1_get_field_ptr(pval, seqtt); + pseqval = ossl_asn1_get_field_ptr(pval, seqtt); /* Have we ran out of data? */ if (!len) break; q = p; if (asn1_check_eoc(&p, len)) { if (!seq_eoc) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_UNEXPECTED_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC); goto err; } len -= p - q; seq_eoc = 0; - q = p; break; } /* @@ -380,7 +420,7 @@ */ ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx, - depth); + depth, libctx, propq); if (!ret) { errtt = seqtt; goto err; @@ -388,7 +428,7 @@ /* * OPTIONAL component absent. Free and zero the field. */ - asn1_template_free(pseqval, seqtt); + ossl_asn1_template_free(pseqval, seqtt); continue; } /* Update length */ @@ -397,12 +437,12 @@ /* Check for EOC if expecting one */ if (seq_eoc && !asn1_check_eoc(&p, len)) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MISSING_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC); goto err; } /* Check all data read */ if (!seq_nolen && len) { - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH); goto err; } @@ -413,21 +453,21 @@ */ for (; i < it->tcount; tt++, i++) { const ASN1_TEMPLATE *seqtt; - seqtt = asn1_do_adb(pval, tt, 1); + seqtt = ossl_asn1_do_adb(*pval, tt, 1); if (seqtt == NULL) goto err; if (seqtt->flags & ASN1_TFLG_OPTIONAL) { ASN1_VALUE **pseqval; - pseqval = asn1_get_field_ptr(pval, seqtt); - asn1_template_free(pseqval, seqtt); + pseqval = ossl_asn1_get_field_ptr(pval, seqtt); + ossl_asn1_template_free(pseqval, seqtt); } else { errtt = seqtt; - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_FIELD_MISSING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_FIELD_MISSING); goto err; } } /* Save encoding */ - if (!asn1_enc_save(pval, *in, p - *in, it)) + if (!ossl_asn1_enc_save(pval, *in, p - *in, it)) goto auxerr; if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) goto auxerr; @@ -438,7 +478,7 @@ return 0; } auxerr: - ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_AUX_ERROR); + ERR_raise(ERR_LIB_ASN1, ASN1_R_AUX_ERROR); err: if (errtt) ERR_add_error_data(4, "Field=", errtt->field_name, @@ -456,7 +496,8 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx, int depth) + ASN1_TLC *ctx, int depth, + OSSL_LIB_CTX *libctx, const char *propq) { int flags, aclass; int ret; @@ -481,19 +522,19 @@ &p, inlen, tt->tag, aclass, opt, ctx); q = p; if (!ret) { - ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } else if (ret == -1) return -1; if (!cst) { - ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, - ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); return 0; } /* We've found the field so it can't be OPTIONAL now */ - ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth, libctx, + propq); if (!ret) { - ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } /* We read the field in OK so update length */ @@ -501,7 +542,7 @@ if (exp_eoc) { /* If NDEF we must have an EOC here */ if (!asn1_check_eoc(&p, len)) { - ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC); goto err; } } else { @@ -509,13 +550,13 @@ * Otherwise we must hit the EXPLICIT tag end or its an error */ if (len) { - ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, - ASN1_R_EXPLICIT_LENGTH_MISMATCH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH); goto err; } } } else - return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth); + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth, + libctx, propq); *in = p; return 1; @@ -527,7 +568,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, - ASN1_TLC *ctx, int depth) + ASN1_TLC *ctx, int depth, + OSSL_LIB_CTX *libctx, const char *propq) { int flags, aclass; int ret; @@ -539,7 +581,6 @@ aclass = flags & ASN1_TFLG_TAG_CLASS; p = *in; - q = p; /* * If field is embedded then val needs fixing so it is a pointer to @@ -569,11 +610,11 @@ ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, &p, len, sktag, skaclass, opt, ctx); if (!ret) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } else if (ret == -1) return -1; - if (!*val) + if (*val == NULL) *val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null(); else { /* @@ -587,8 +628,8 @@ } } - if (!*val) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); + if (*val == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } @@ -599,8 +640,7 @@ /* See if EOC found */ if (asn1_check_eoc(&p, len)) { if (!sk_eoc) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, - ASN1_R_UNEXPECTED_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC); goto err; } len -= p - q; @@ -608,42 +648,41 @@ break; } skfield = NULL; - if (!asn1_item_embed_d2i(&skfield, &p, len, + if (asn1_item_embed_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx, - depth)) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, - ERR_R_NESTED_ASN1_ERROR); + depth, libctx, propq) <= 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); /* |skfield| may be partially allocated despite failure. */ ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); goto err; } len -= p - q; if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); goto err; } } if (sk_eoc) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC); goto err; } } else if (flags & ASN1_TFLG_IMPTAG) { /* IMPLICIT tagging */ ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, - ctx, depth); + ctx, depth, libctx, propq); if (!ret) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } else if (ret == -1) return -1; } else { /* Nothing special */ ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), - -1, 0, opt, ctx, depth); + -1, 0, opt, ctx, depth, libctx, propq); if (!ret) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); goto err; } else if (ret == -1) return -1; @@ -668,8 +707,9 @@ BUF_MEM buf = { 0, NULL, 0, 0 }; const unsigned char *cont = NULL; long len; - if (!pval) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); + + if (pval == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL); return 0; /* Should never happen */ } @@ -683,19 +723,18 @@ /* If type is ANY need to figure out type from tag */ unsigned char oclass; if (tag >= 0) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); return 0; } if (opt) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, - ASN1_R_ILLEGAL_OPTIONAL_ANY); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); return 0; } p = *in; ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, &p, inlen, -1, 0, 0, ctx); if (!ret) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } if (oclass != V_ASN1_UNIVERSAL) @@ -710,7 +749,7 @@ ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, &p, inlen, tag, aclass, opt, ctx); if (!ret) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } else if (ret == -1) return -1; @@ -727,8 +766,7 @@ } /* SEQUENCE and SET must be constructed */ else if (!cst) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, - ASN1_R_TYPE_NOT_CONSTRUCTED); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); return 0; } @@ -746,7 +784,7 @@ if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER || utype == V_ASN1_ENUMERATED) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); return 0; } @@ -764,7 +802,7 @@ len = buf.length; /* Append a final null to string */ if (!BUF_MEM_grow_clean(&buf, len + 1)) { - ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } buf.data[len] = 0; @@ -805,7 +843,7 @@ return pf->prim_c2i(pval, cont, len, utype, free_cont, it); /* If ANY type clear type and set pointer to internal value */ if (it->utype == V_ASN1_ANY) { - if (!*pval) { + if (*pval == NULL) { typ = ASN1_TYPE_new(); if (typ == NULL) goto err; @@ -820,13 +858,13 @@ } switch (utype) { case V_ASN1_OBJECT: - if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) + if (!ossl_c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) goto err; break; case V_ASN1_NULL: if (len) { - ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); goto err; } *pval = (ASN1_VALUE *)1; @@ -834,7 +872,7 @@ case V_ASN1_BOOLEAN: if (len != 1) { - ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); goto err; } else { ASN1_BOOLEAN *tbool; @@ -844,14 +882,14 @@ break; case V_ASN1_BIT_STRING: - if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) + if (!ossl_c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) goto err; break; case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: tint = (ASN1_INTEGER **)pval; - if (!c2i_ASN1_INTEGER(tint, &cont, len)) + if (!ossl_c2i_ASN1_INTEGER(tint, &cont, len)) goto err; /* Fixup type to match the expected form */ (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); @@ -876,19 +914,18 @@ case V_ASN1_SEQUENCE: default: if (utype == V_ASN1_BMPSTRING && (len & 1)) { - ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); goto err; } if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { - ASN1err(ASN1_F_ASN1_EX_C2I, - ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); goto err; } /* All based on ASN1_STRING and handled the same */ - if (!*pval) { + if (*pval == NULL) { stmp = ASN1_STRING_type_new(utype); if (stmp == NULL) { - ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } *pval = (ASN1_VALUE *)stmp; @@ -904,7 +941,7 @@ *free_cont = 0; } else { if (!ASN1_STRING_set(stmp, cont, len)) { - ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); ASN1_STRING_free(stmp); *pval = NULL; goto err; @@ -962,12 +999,12 @@ /* Just read in a header: only care about the length */ if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, -1, 0, 0, NULL)) { - ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } if (inf) { if (expected_eoc == UINT32_MAX) { - ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } expected_eoc++; @@ -977,7 +1014,7 @@ len -= p - q; } if (expected_eoc) { - ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC); return 0; } *in = p; @@ -1024,7 +1061,7 @@ * EOC is illegal outside indefinite length constructed form */ if (!inf) { - ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC); return 0; } inf = 0; @@ -1033,14 +1070,14 @@ if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, len, tag, aclass, 0, NULL)) { - ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); + ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR); return 0; } /* If indefinite length constructed update max length */ if (cst) { if (depth >= ASN1_MAX_STRING_NEST) { - ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_NESTED_ASN1_STRING); return 0; } if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1)) @@ -1050,7 +1087,7 @@ len -= p - q; } if (inf) { - ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); + ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC); return 0; } *in = p; @@ -1063,7 +1100,7 @@ if (buf) { len = buf->length; if (!BUF_MEM_grow_clean(buf, len + plen)) { - ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } memcpy(buf->data + len, *p, plen); @@ -1077,10 +1114,11 @@ static int asn1_check_eoc(const unsigned char **in, long len) { const unsigned char *p; + if (len < 2) return 0; p = *in; - if (!p[0] && !p[1]) { + if (p[0] == '\0' && p[1] == '\0') { *in += 2; return 1; } @@ -1106,7 +1144,11 @@ p = *in; q = p; - if (ctx && ctx->valid) { + if (len <= 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); + goto err; + } + if (ctx != NULL && ctx->valid) { i = ctx->ret; plen = ctx->plen; pclass = ctx->pclass; @@ -1114,7 +1156,7 @@ p += ctx->hdrlen; } else { i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); - if (ctx) { + if (ctx != NULL) { ctx->ret = i; ctx->plen = plen; ctx->pclass = pclass; @@ -1125,29 +1167,26 @@ * If definite length, and no error, length + header can't exceed * total amount of data available. */ - if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { - ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); - asn1_tlc_clear(ctx); - return 0; + if ((i & 0x81) == 0 && (plen + ctx->hdrlen) > len) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); + goto err; } } } - if (i & 0x80) { - ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); - asn1_tlc_clear(ctx); - return 0; + if ((i & 0x80) != 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_OBJECT_HEADER); + goto err; } if (exptag >= 0) { - if ((exptag != ptag) || (expclass != pclass)) { + if (exptag != ptag || expclass != pclass) { /* * If type is OPTIONAL, not an error: indicate missing type. */ - if (opt) + if (opt != 0) return -1; - asn1_tlc_clear(ctx); - ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); - return 0; + ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_TAG); + goto err; } /* * We have a tag and class match: assume we are going to do something @@ -1156,24 +1195,28 @@ asn1_tlc_clear(ctx); } - if (i & 1) + if ((i & 1) != 0) plen = len - (p - q); - if (inf) + if (inf != NULL) *inf = i & 1; - if (cst) + if (cst != NULL) *cst = i & V_ASN1_CONSTRUCTED; - if (olen) + if (olen != NULL) *olen = plen; - if (oclass) + if (oclass != NULL) *oclass = pclass; - if (otag) + if (otag != NULL) *otag = ptag; *in = p; return 1; + + err: + asn1_tlc_clear(ctx); + return 0; } diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -16,16 +16,17 @@ #include "crypto/asn1.h" #include "asn1_local.h" -static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, +static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); -static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, +static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk, + unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort, int iclass); -static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, +static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt, int tag, int aclass); -static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, +static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, int flags); -static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, +static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it); /* @@ -33,13 +34,13 @@ * indefinite length constructed encoding, where appropriate */ -int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, +int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); } -int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) +int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { return asn1_item_flags_i2d(val, out, it, 0); } @@ -51,10 +52,10 @@ * allocated and populated with the encoding. */ -static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, +static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, int flags) { - if (out && !*out) { + if (out != NULL && *out == NULL) { unsigned char *p, *buf; int len; @@ -62,7 +63,7 @@ if (len <= 0) return len; if ((buf = OPENSSL_malloc(len)) == NULL) { - ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } p = buf; @@ -79,20 +80,22 @@ * performs the normal item handling: it can be used in external types. */ -int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, +int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) { const ASN1_TEMPLATE *tt = NULL; int i, seqcontlen, seqlen, ndef = 1; const ASN1_EXTERN_FUNCS *ef; const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb = 0; + ASN1_aux_const_cb *asn1_cb = NULL; - if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL) return 0; - if (aux && aux->asn1_cb) - asn1_cb = aux->asn1_cb; + if (aux != NULL) { + asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb + : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */ + } switch (it->itype) { @@ -108,7 +111,7 @@ * if tag != -1, then this looks like an error in the template. */ if (tag != -1) { - ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE); return -1; } return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); @@ -119,17 +122,17 @@ * if tag != -1, then this looks like an error in the template. */ if (tag != -1) { - ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE); return -1; } if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) return 0; - i = asn1_get_choice_selector(pval, it); + i = ossl_asn1_get_choice_selector_const(pval, it); if ((i >= 0) && (i < it->tcount)) { - ASN1_VALUE **pchval; + const ASN1_VALUE **pchval; const ASN1_TEMPLATE *chtt; chtt = it->templates + i; - pchval = asn1_get_field_ptr(pval, chtt); + pchval = ossl_asn1_get_const_field_ptr(pval, chtt); return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); } /* Fixme: error condition if selector out of range */ @@ -149,7 +152,7 @@ /* fall through */ case ASN1_ITYPE_SEQUENCE: - i = asn1_enc_restore(&seqcontlen, out, pval, it); + i = ossl_asn1_enc_restore(&seqcontlen, out, pval, it); /* An error occurred */ if (i < 0) return 0; @@ -170,12 +173,12 @@ /* First work out sequence content length */ for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { const ASN1_TEMPLATE *seqtt; - ASN1_VALUE **pseqval; + const ASN1_VALUE **pseqval; int tmplen; - seqtt = asn1_do_adb(pval, tt, 1); + seqtt = ossl_asn1_do_adb(*pval, tt, 1); if (!seqtt) return 0; - pseqval = asn1_get_field_ptr(pval, seqtt); + pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt); tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) return -1; @@ -189,11 +192,11 @@ ASN1_put_object(out, ndef, seqcontlen, tag, aclass); for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { const ASN1_TEMPLATE *seqtt; - ASN1_VALUE **pseqval; - seqtt = asn1_do_adb(pval, tt, 1); + const ASN1_VALUE **pseqval; + seqtt = ossl_asn1_do_adb(*pval, tt, 1); if (!seqtt) return 0; - pseqval = asn1_get_field_ptr(pval, seqtt); + pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt); /* FIXME: check for errors in enhanced version */ asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); } @@ -210,12 +213,12 @@ return 0; } -static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, +static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt, int tag, int iclass) { - int i, ret, flags, ttag, tclass, ndef; - ASN1_VALUE *tval; - flags = tt->flags; + const int flags = tt->flags; + int i, ret, ttag, tclass, ndef, len; + const ASN1_VALUE *tval; /* * If field is embedded then val needs fixing so it is a pointer to @@ -266,12 +269,12 @@ if (flags & ASN1_TFLG_SK_MASK) { /* SET OF, SEQUENCE OF */ - STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + STACK_OF(const_ASN1_VALUE) *sk = (STACK_OF(const_ASN1_VALUE) *)*pval; int isset, sktag, skaclass; int skcontlen, sklen; - ASN1_VALUE *skitem; + const ASN1_VALUE *skitem; - if (!*pval) + if (*pval == NULL) return 0; if (flags & ASN1_TFLG_SET_OF) { @@ -299,14 +302,17 @@ /* Determine total length of items */ skcontlen = 0; - for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { - int tmplen; - skitem = sk_ASN1_VALUE_value(sk, i); - tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), - -1, iclass); - if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) + for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) { + skitem = sk_const_ASN1_VALUE_value(sk, i); + len = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), + -1, iclass); + if (len == -1 || (skcontlen > INT_MAX - len)) return -1; - skcontlen += tmplen; + if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT); + return -1; + } + skcontlen += len; } sklen = ASN1_object_size(ndef, skcontlen, sktag); if (sklen == -1) @@ -342,8 +348,13 @@ /* EXPLICIT tagging */ /* Find length of tagged item */ i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); - if (!i) + if (i == 0) { + if ((tt->flags & ASN1_TFLG_OPTIONAL) == 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT); + return -1; + } return 0; + } /* Find length of EXPLICIT tag */ ret = ASN1_object_size(ndef, i, ttag); if (out && ret != -1) { @@ -357,9 +368,13 @@ } /* Either normal or IMPLICIT tagging: combine class and flags */ - return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), - ttag, tclass | iclass); - + len = ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), + ttag, tclass | iclass); + if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT); + return -1; + } + return len; } /* Temporary structure used to hold DER encoding of items for SET OF */ @@ -367,7 +382,7 @@ typedef struct { unsigned char *data; int length; - ASN1_VALUE *field; + const ASN1_VALUE *field; } DER_ENC; static int der_cmp(const void *a, const void *b) @@ -383,34 +398,38 @@ /* Output the content octets of SET OF or SEQUENCE OF */ -static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, +static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk, + unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort, int iclass) { - int i; - ASN1_VALUE *skitem; + int i, ret = 0; + const ASN1_VALUE *skitem; unsigned char *tmpdat = NULL, *p = NULL; DER_ENC *derlst = NULL, *tder; + if (do_sort) { /* Don't need to sort less than 2 items */ - if (sk_ASN1_VALUE_num(sk) < 2) + if (sk_const_ASN1_VALUE_num(sk) < 2) do_sort = 0; else { - derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) + derlst = OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk) * sizeof(*derlst)); - if (derlst == NULL) + if (derlst == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; + } tmpdat = OPENSSL_malloc(skcontlen); if (tmpdat == NULL) { - OPENSSL_free(derlst); - return 0; + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + goto err; } } } /* If not sorting just output each item */ if (!do_sort) { - for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { - skitem = sk_ASN1_VALUE_value(sk, i); + for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) { + skitem = sk_const_ASN1_VALUE_value(sk, i); ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); } return 1; @@ -418,33 +437,35 @@ p = tmpdat; /* Doing sort: build up a list of each member's DER encoding */ - for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { - skitem = sk_ASN1_VALUE_value(sk, i); + for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) { + skitem = sk_const_ASN1_VALUE_value(sk, i); tder->data = p; tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); tder->field = skitem; } /* Now sort them */ - qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); + qsort(derlst, sk_const_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); /* Output sorted DER encoding */ p = *out; - for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) { memcpy(p, tder->data, tder->length); p += tder->length; } *out = p; /* If do_sort is 2 then reorder the STACK */ if (do_sort == 2) { - for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) - (void)sk_ASN1_VALUE_set(sk, i, tder->field); + for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) + (void)sk_const_ASN1_VALUE_set(sk, i, tder->field); } + ret = 1; +err: OPENSSL_free(derlst); OPENSSL_free(tmpdat); - return 1; + return ret; } -static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, +static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) { int len; @@ -504,7 +525,7 @@ /* Produce content octets from a structure */ -static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, +static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it) { ASN1_BOOLEAN *tbool = NULL; @@ -522,7 +543,7 @@ /* Should type be omitted? */ if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { - if (!*pval) + if (*pval == NULL) return -1; } @@ -537,7 +558,7 @@ typ = (ASN1_TYPE *)*pval; utype = typ->type; *putype = utype; - pval = &typ->value.asn1_value; + pval = (const ASN1_VALUE **)&typ->value.asn1_value; /* actually is const */ } else utype = *putype; @@ -574,15 +595,15 @@ break; case V_ASN1_BIT_STRING: - return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, - cout ? &cout : NULL); + return ossl_i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, + cout ? &cout : NULL); case V_ASN1_INTEGER: case V_ASN1_ENUMERATED: /* * These are all have the same content format as ASN1_INTEGER */ - return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); + return ossl_i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); case V_ASN1_OCTET_STRING: case V_ASN1_NUMERICSTRING: diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -17,15 +17,15 @@ void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) { - asn1_item_embed_free(&val, it, 0); + ossl_asn1_item_embed_free(&val, it, 0); } void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { - asn1_item_embed_free(pval, it, 0); + ossl_asn1_item_embed_free(pval, it, 0); } -void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +void ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) { const ASN1_TEMPLATE *tt = NULL, *seqtt; const ASN1_EXTERN_FUNCS *ef; @@ -33,9 +33,9 @@ ASN1_aux_cb *asn1_cb; int i; - if (!pval) + if (pval == NULL) return; - if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) + if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL) return; if (aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; @@ -46,13 +46,13 @@ case ASN1_ITYPE_PRIMITIVE: if (it->templates) - asn1_template_free(pval, it->templates); + ossl_asn1_template_free(pval, it->templates); else - asn1_primitive_free(pval, it, embed); + ossl_asn1_primitive_free(pval, it, embed); break; case ASN1_ITYPE_MSTRING: - asn1_primitive_free(pval, it, embed); + ossl_asn1_primitive_free(pval, it, embed); break; case ASN1_ITYPE_CHOICE: @@ -61,13 +61,13 @@ if (i == 2) return; } - i = asn1_get_choice_selector(pval, it); + i = ossl_asn1_get_choice_selector(pval, it); if ((i >= 0) && (i < it->tcount)) { ASN1_VALUE **pchval; tt = it->templates + i; - pchval = asn1_get_field_ptr(pval, tt); - asn1_template_free(pchval, tt); + pchval = ossl_asn1_get_field_ptr(pval, tt); + ossl_asn1_template_free(pchval, tt); } if (asn1_cb) asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); @@ -85,14 +85,14 @@ case ASN1_ITYPE_NDEF_SEQUENCE: case ASN1_ITYPE_SEQUENCE: - if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */ + if (ossl_asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */ return; if (asn1_cb) { i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); if (i == 2) return; } - asn1_enc_free(pval, it); + ossl_asn1_enc_free(pval, it); /* * If we free up as normal we will invalidate any ANY DEFINED BY * field and we won't be able to determine the type of the field it @@ -103,11 +103,11 @@ ASN1_VALUE **pseqval; tt--; - seqtt = asn1_do_adb(pval, tt, 0); + seqtt = ossl_asn1_do_adb(*pval, tt, 0); if (!seqtt) continue; - pseqval = asn1_get_field_ptr(pval, seqtt); - asn1_template_free(pseqval, seqtt); + pseqval = ossl_asn1_get_field_ptr(pval, seqtt); + ossl_asn1_template_free(pseqval, seqtt); } if (asn1_cb) asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); @@ -119,7 +119,7 @@ } } -void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { int embed = tt->flags & ASN1_TFLG_EMBED; ASN1_VALUE *tval; @@ -134,16 +134,16 @@ for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i); - asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed); + ossl_asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed); } sk_ASN1_VALUE_free(sk); *pval = NULL; } else { - asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed); + ossl_asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed); } } -void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) { int utype; @@ -168,15 +168,15 @@ utype = typ->type; pval = &typ->value.asn1_value; - if (!*pval) + if (*pval == NULL) return; } else if (it->itype == ASN1_ITYPE_MSTRING) { utype = -1; - if (!*pval) + if (*pval == NULL) return; } else { utype = it->utype; - if ((utype != V_ASN1_BOOLEAN) && !*pval) + if ((utype != V_ASN1_BOOLEAN) && *pval == NULL) return; } @@ -196,12 +196,12 @@ break; case V_ASN1_ANY: - asn1_primitive_free(pval, NULL, 0); + ossl_asn1_primitive_free(pval, NULL, 0); OPENSSL_free(*pval); break; default: - asn1_string_embed_free((ASN1_STRING *)*pval, embed); + ossl_asn1_string_embed_free((ASN1_STRING *)*pval, embed); break; } *pval = NULL; diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c --- a/crypto/asn1/tasn_new.c +++ b/crypto/asn1/tasn_new.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -16,11 +16,13 @@ #include "asn1_local.h" static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, - int embed); + int embed, OSSL_LIB_CTX *libctx, + const char *propq); static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); -static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + OSSL_LIB_CTX *libctx, const char *propq); static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); @@ -32,14 +34,31 @@ return NULL; } +ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx, + const char *propq) +{ + ASN1_VALUE *ret = NULL; + if (asn1_item_embed_new(&ret, it, 0, libctx, propq) > 0) + return ret; + return NULL; +} + /* Allocate an ASN1 structure */ + +int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq) +{ + return asn1_item_embed_new(pval, it, 0, libctx, propq); +} + int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - return asn1_item_embed_new(pval, it, 0); + return asn1_item_embed_new(pval, it, 0, NULL, NULL); } -int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, + OSSL_LIB_CTX *libctx, const char *propq) { const ASN1_TEMPLATE *tt = NULL; const ASN1_EXTERN_FUNCS *ef; @@ -52,23 +71,24 @@ else asn1_cb = 0; -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_push(it->sname ? it->sname : "asn1_item_embed_new"); -#endif - switch (it->itype) { case ASN1_ITYPE_EXTERN: ef = it->funcs; - if (ef && ef->asn1_ex_new) { - if (!ef->asn1_ex_new(pval, it)) - goto memerr; + if (ef != NULL) { + if (ef->asn1_ex_new_ex != NULL) { + if (!ef->asn1_ex_new_ex(pval, it, libctx, propq)) + goto memerr; + } else if (ef->asn1_ex_new != NULL) { + if (!ef->asn1_ex_new(pval, it)) + goto memerr; + } } break; case ASN1_ITYPE_PRIMITIVE: if (it->templates) { - if (!asn1_template_new(pval, it->templates)) + if (!asn1_template_new(pval, it->templates, libctx, propq)) goto memerr; } else if (!asn1_primitive_new(pval, it, embed)) goto memerr; @@ -85,9 +105,6 @@ if (!i) goto auxerr; if (i == 2) { -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_pop(); -#endif return 1; } } @@ -98,7 +115,7 @@ if (*pval == NULL) goto memerr; } - asn1_set_choice_selector(pval, -1, it); + ossl_asn1_set_choice_selector(pval, -1, it); if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr2; break; @@ -110,9 +127,6 @@ if (!i) goto auxerr; if (i == 2) { -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_pop(); -#endif return 1; } } @@ -124,44 +138,35 @@ goto memerr; } /* 0 : init. lock */ - if (asn1_do_lock(pval, 0, it) < 0) { + if (ossl_asn1_do_lock(pval, 0, it) < 0) { if (!embed) { OPENSSL_free(*pval); *pval = NULL; } goto memerr; } - asn1_enc_init(pval, it); + ossl_asn1_enc_init(pval, it); for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { - pseqval = asn1_get_field_ptr(pval, tt); - if (!asn1_template_new(pseqval, tt)) + pseqval = ossl_asn1_get_field_ptr(pval, tt); + if (!asn1_template_new(pseqval, tt, libctx, propq)) goto memerr2; } if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr2; break; } -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_pop(); -#endif return 1; memerr2: - asn1_item_embed_free(pval, it, embed); + ossl_asn1_item_embed_free(pval, it, embed); memerr: - ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE); -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_pop(); -#endif + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; auxerr2: - asn1_item_embed_free(pval, it, embed); + ossl_asn1_item_embed_free(pval, it, embed); auxerr: - ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR); -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_pop(); -#endif + ERR_raise(ERR_LIB_ASN1, ASN1_R_AUX_ERROR); return 0; } @@ -199,7 +204,8 @@ } } -static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + OSSL_LIB_CTX *libctx, const char *propq) { const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); int embed = tt->flags & ASN1_TFLG_EMBED; @@ -219,16 +225,12 @@ *pval = NULL; return 1; } -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_push(tt->field_name - ? tt->field_name : "asn1_template_new"); -#endif /* If SET OF or SEQUENCE OF, its a STACK */ if (tt->flags & ASN1_TFLG_SK_MASK) { STACK_OF(ASN1_VALUE) *skval; skval = sk_ASN1_VALUE_new_null(); if (!skval) { - ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); ret = 0; goto done; } @@ -237,11 +239,8 @@ goto done; } /* Otherwise pass it back to the item routine */ - ret = asn1_item_embed_new(pval, it, embed); + ret = asn1_item_embed_new(pval, it, embed, libctx, propq); done: -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - OPENSSL_mem_debug_pop(); -#endif return ret; } @@ -300,7 +299,7 @@ case V_ASN1_ANY: if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) { - ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } typ->value.ptr = NULL; diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c --- a/crypto/asn1/tasn_prn.c +++ b/crypto/asn1/tasn_prn.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -38,7 +38,7 @@ ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } return ret; @@ -101,15 +101,15 @@ /* Main print routines */ -static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, const ASN1_ITEM *it, const char *fname, const char *sname, int nohdr, const ASN1_PCTX *pctx); -static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx); -static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, +static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld, const ASN1_ITEM *it, int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx); @@ -118,7 +118,7 @@ const char *fname, const char *sname, const ASN1_PCTX *pctx); -int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, +int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it, const ASN1_PCTX *pctx) { const char *sname; @@ -131,25 +131,25 @@ return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx); } -static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, const ASN1_ITEM *it, const char *fname, const char *sname, int nohdr, const ASN1_PCTX *pctx) { const ASN1_TEMPLATE *tt; const ASN1_EXTERN_FUNCS *ef; - ASN1_VALUE **tmpfld; + const ASN1_VALUE **tmpfld; const ASN1_AUX *aux = it->funcs; - ASN1_aux_cb *asn1_cb; + ASN1_aux_const_cb *asn1_cb = NULL; ASN1_PRINT_ARG parg; int i; - if (aux && aux->asn1_cb) { + if (aux != NULL) { parg.out = out; parg.indent = indent; parg.pctx = pctx; - asn1_cb = aux->asn1_cb; - } else - asn1_cb = 0; + asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb + : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */ + } if (((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) { @@ -195,7 +195,7 @@ case ASN1_ITYPE_CHOICE: /* CHOICE type, get selector */ - i = asn1_get_choice_selector(fld, it); + i = ossl_asn1_get_choice_selector_const(fld, it); /* This should never happen... */ if ((i < 0) || (i >= it->tcount)) { if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0) @@ -203,7 +203,7 @@ return 1; } tt = it->templates + i; - tmpfld = asn1_get_field_ptr(fld, tt); + tmpfld = ossl_asn1_get_const_field_ptr(fld, tt); if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx)) return 0; break; @@ -233,10 +233,10 @@ /* Print each field entry */ for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { const ASN1_TEMPLATE *seqtt; - seqtt = asn1_do_adb(fld, tt, 1); + seqtt = ossl_asn1_do_adb(*fld, tt, 1); if (!seqtt) return 0; - tmpfld = asn1_get_field_ptr(fld, seqtt); + tmpfld = ossl_asn1_get_const_field_ptr(fld, seqtt); if (!asn1_template_print_ctx(out, tmpfld, indent + 2, seqtt, pctx)) return 0; @@ -261,12 +261,12 @@ return 1; } -static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx) { int i, flags; const char *sname, *fname; - ASN1_VALUE *tfld; + const ASN1_VALUE *tfld; flags = tt->flags; if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME) sname = ASN1_ITEM_ptr(tt->item)->sname; @@ -282,14 +282,14 @@ * a pointer to a field. */ if (flags & ASN1_TFLG_EMBED) { - tfld = (ASN1_VALUE *)fld; + tfld = (const ASN1_VALUE *)fld; fld = &tfld; } if (flags & ASN1_TFLG_SK_MASK) { char *tname; - ASN1_VALUE *skitem; - STACK_OF(ASN1_VALUE) *stack; + const ASN1_VALUE *skitem; + STACK_OF(const_ASN1_VALUE) *stack; /* SET OF, SEQUENCE OF */ if (fname) { @@ -304,12 +304,12 @@ } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0) return 0; } - stack = (STACK_OF(ASN1_VALUE) *)*fld; - for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) { + stack = (STACK_OF(const_ASN1_VALUE) *)*fld; + for (i = 0; i < sk_const_ASN1_VALUE_num(stack); i++) { if ((i > 0) && (BIO_puts(out, "\n") <= 0)) return 0; - skitem = sk_ASN1_VALUE_value(stack, i); + skitem = sk_const_ASN1_VALUE_value(stack, i); if (!asn1_item_print_ctx(out, &skitem, indent + 2, ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx)) @@ -430,7 +430,7 @@ return 1; } -static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, +static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld, const ASN1_ITEM *it, int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx) @@ -456,9 +456,9 @@ str = (ASN1_STRING *)*fld; } if (utype == V_ASN1_ANY) { - ASN1_TYPE *atype = (ASN1_TYPE *)*fld; + const ASN1_TYPE *atype = (const ASN1_TYPE *)*fld; utype = atype->type; - fld = &atype->value.asn1_value; + fld = (const ASN1_VALUE **)&atype->value.asn1_value; /* actually is const */ str = (ASN1_STRING *)*fld; if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) pname = NULL; diff --git a/crypto/asn1/tasn_scn.c b/crypto/asn1/tasn_scn.c --- a/crypto/asn1/tasn_scn.c +++ b/crypto/asn1/tasn_scn.c @@ -1,7 +1,7 @@ /* - * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -27,7 +27,7 @@ ASN1_SCTX *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ASN1err(ASN1_F_ASN1_SCTX_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } ret->scan_cb = scan_cb; diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c --- a/crypto/asn1/tasn_typ.c +++ b/crypto/asn1/tasn_typ.c @@ -1,7 +1,7 @@ /* * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -80,5 +80,5 @@ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY) ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c --- a/crypto/asn1/tasn_utl.c +++ b/crypto/asn1/tasn_utl.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -26,9 +26,18 @@ * Given an ASN1_ITEM CHOICE type return the selector value */ -int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) +int ossl_asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) { int *sel = offset2ptr(*pval, it->utype); + + return *sel; +} + +int ossl_asn1_get_choice_selector_const(const ASN1_VALUE **pval, + const ASN1_ITEM *it) +{ + int *sel = offset2ptr(*pval, it->utype); + return *sel; } @@ -36,10 +45,11 @@ * Given an ASN1_ITEM CHOICE type set the selector value, return old value. */ -int asn1_set_choice_selector(ASN1_VALUE **pval, int value, - const ASN1_ITEM *it) +int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value, + const ASN1_ITEM *it) { int *sel, ret; + sel = offset2ptr(*pval, it->utype); ret = *sel; *sel = value; @@ -55,7 +65,7 @@ * It returns -1 on initialisation error. * Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects */ -int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) +int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) { const ASN1_AUX *aux; CRYPTO_REF_COUNT *lck; @@ -66,7 +76,7 @@ && (it->itype != ASN1_ITYPE_NDEF_SEQUENCE)) return 0; aux = it->funcs; - if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) + if (aux == NULL || (aux->flags & ASN1_AFLG_REFCOUNT) == 0) return 0; lck = offset2ptr(*pval, aux->ref_offset); lock = offset2ptr(*pval, aux->ref_lock); @@ -76,7 +86,7 @@ *lck = ret = 1; *lock = CRYPTO_THREAD_lock_new(); if (*lock == NULL) { - ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } break; @@ -87,9 +97,7 @@ case -1: if (!CRYPTO_DOWN_REF(lck, &ret, *lock)) return -1; /* failed */ -#ifdef REF_PRINT - fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname); -#endif + REF_PRINT_EX(it->sname, ret, (void *)it); REF_ASSERT_ISNT(ret < 0); if (ret == 0) { CRYPTO_THREAD_lock_free(*lock); @@ -104,30 +112,44 @@ static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) { const ASN1_AUX *aux; - if (!pval || !*pval) + + if (pval == NULL || *pval == NULL) + return NULL; + aux = it->funcs; + if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0) + return NULL; + return offset2ptr(*pval, aux->enc_offset); +} + +static const ASN1_ENCODING *asn1_get_const_enc_ptr(const ASN1_VALUE **pval, + const ASN1_ITEM *it) +{ + const ASN1_AUX *aux; + + if (pval == NULL || *pval == NULL) return NULL; aux = it->funcs; - if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) + if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0) return NULL; return offset2ptr(*pval, aux->enc_offset); } -void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) +void ossl_asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) { - ASN1_ENCODING *enc; - enc = asn1_get_enc_ptr(pval, it); - if (enc) { + ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); + + if (enc != NULL) { enc->enc = NULL; enc->len = 0; enc->modified = 1; } } -void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +void ossl_asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { - ASN1_ENCODING *enc; - enc = asn1_get_enc_ptr(pval, it); - if (enc) { + ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); + + if (enc != NULL) { OPENSSL_free(enc->enc); enc->enc = NULL; enc->len = 0; @@ -135,17 +157,19 @@ } } -int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, - const ASN1_ITEM *it) +int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, + const ASN1_ITEM *it) { - ASN1_ENCODING *enc; - enc = asn1_get_enc_ptr(pval, it); - if (!enc) + ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); + + if (enc == NULL) return 1; OPENSSL_free(enc->enc); + if (inlen <= 0) + return 0; if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) { - ASN1err(ASN1_F_ASN1_ENC_SAVE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } memcpy(enc->enc, in, inlen); @@ -155,27 +179,27 @@ return 1; } -int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, - const ASN1_ITEM *it) +int ossl_asn1_enc_restore(int *len, unsigned char **out, const ASN1_VALUE **pval, + const ASN1_ITEM *it) { - ASN1_ENCODING *enc; - enc = asn1_get_enc_ptr(pval, it); - if (!enc || enc->modified) + const ASN1_ENCODING *enc = asn1_get_const_enc_ptr(pval, it); + + if (enc == NULL || enc->modified) return 0; if (out) { memcpy(*out, enc->enc, enc->len); *out += enc->len; } - if (len) + if (len != NULL) *len = enc->len; return 1; } /* Given an ASN1_TEMPLATE get a pointer to a field */ -ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +ASN1_VALUE **ossl_asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { - ASN1_VALUE **pvaltmp; - pvaltmp = offset2ptr(*pval, tt->offset); + ASN1_VALUE **pvaltmp = offset2ptr(*pval, tt->offset); + /* * NOTE for BOOLEAN types the field is just a plain int so we can't * return int **, so settle for (int *). @@ -183,31 +207,40 @@ return pvaltmp; } +/* Given an ASN1_TEMPLATE get a const pointer to a field */ +const ASN1_VALUE **ossl_asn1_get_const_field_ptr(const ASN1_VALUE **pval, + const ASN1_TEMPLATE *tt) +{ + return offset2ptr(*pval, tt->offset); +} + /* * Handle ANY DEFINED BY template, find the selector, look up the relevant * ASN1_TEMPLATE in the table and return it. */ -const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, - int nullerr) +const ASN1_TEMPLATE *ossl_asn1_do_adb(const ASN1_VALUE *val, + const ASN1_TEMPLATE *tt, + int nullerr) { const ASN1_ADB *adb; const ASN1_ADB_TABLE *atbl; long selector; - ASN1_VALUE **sfld; + const ASN1_VALUE **sfld; int i; - if (!(tt->flags & ASN1_TFLG_ADB_MASK)) + + if ((tt->flags & ASN1_TFLG_ADB_MASK) == 0) return tt; /* Else ANY DEFINED BY ... get the table */ adb = ASN1_ADB_ptr(tt->item); /* Get the selector field */ - sfld = offset2ptr(*pval, adb->offset); + sfld = offset2ptr(val, adb->offset); /* Check if NULL */ if (*sfld == NULL) { - if (!adb->null_tt) + if (adb->null_tt == NULL) goto err; return adb->null_tt; } @@ -216,14 +249,14 @@ * Convert type to a long: NB: don't check for NID_undef here because it * might be a legitimate value in the table */ - if (tt->flags & ASN1_TFLG_ADB_OID) + if ((tt->flags & ASN1_TFLG_ADB_OID) != 0) selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); else selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); /* Let application callback translate value */ if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) { - ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); return NULL; } @@ -248,6 +281,6 @@ err: /* FIXME: should log the value or OID of unsupported type */ if (nullerr) - ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); return NULL; } diff --git a/crypto/asn1/tbl_standard.h b/crypto/asn1/tbl_standard.h --- a/crypto/asn1/tbl_standard.h +++ b/crypto/asn1/tbl_standard.h @@ -1,7 +1,7 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -56,6 +56,7 @@ {NID_SNILS, 1, 11, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, {NID_countryCode3c, 3, 3, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, {NID_countryCode3n, 3, 3, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, - {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK} + {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK}, + {NID_id_on_SmtpUTF8Mailbox, 1, ub_email_address, B_ASN1_UTF8STRING, STABLE_NO_MASK} }; diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c --- a/crypto/asn1/x_algor.c +++ b/crypto/asn1/x_algor.c @@ -1,7 +1,7 @@ /* - * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,6 +11,8 @@ #include #include #include +#include +#include "crypto/asn1.h" #include "crypto/evp.h" ASN1_SEQUENCE(X509_ALGOR) = { @@ -78,7 +80,7 @@ else param_type = V_ASN1_NULL; - X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); + X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_get_type(md)), param_type, NULL); } @@ -96,7 +98,7 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src) { if (src == NULL || dest == NULL) - return 0; + return 0; if (dest->algorithm) ASN1_OBJECT_free(dest->algorithm); @@ -108,9 +110,9 @@ if (src->algorithm) if ((dest->algorithm = OBJ_dup(src->algorithm)) == NULL) - return 0; + return 0; - if (src->parameter) { + if (src->parameter != NULL) { dest->parameter = ASN1_TYPE_new(); if (dest->parameter == NULL) return 0; @@ -118,9 +120,71 @@ /* Assuming this is also correct for a BOOL. * set does copy as a side effect. */ - if (ASN1_TYPE_set1(dest->parameter, - src->parameter->type, src->parameter->value.ptr) == 0) + if (ASN1_TYPE_set1(dest->parameter, src->parameter->type, + src->parameter->value.ptr) == 0) return 0; } + + return 1; +} + +/* allocate and set algorithm ID from EVP_MD, default SHA1 */ +int ossl_x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md) +{ + /* Default is SHA1 so no need to create it - still success */ + if (md == NULL || EVP_MD_is_a(md, "SHA1")) + return 1; + *palg = X509_ALGOR_new(); + if (*palg == NULL) + return 0; + X509_ALGOR_set_md(*palg, md); return 1; } + +/* convert algorithm ID to EVP_MD, default SHA1 */ +const EVP_MD *ossl_x509_algor_get_md(X509_ALGOR *alg) +{ + const EVP_MD *md; + + if (alg == NULL) + return EVP_sha1(); + md = EVP_get_digestbyobj(alg->algorithm); + if (md == NULL) + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_DIGEST); + return md; +} + +X509_ALGOR *ossl_x509_algor_mgf1_decode(X509_ALGOR *alg) +{ + if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) + return NULL; + return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), + alg->parameter); +} + +/* Allocate and set MGF1 algorithm ID from EVP_MD */ +int ossl_x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) +{ + X509_ALGOR *algtmp = NULL; + ASN1_STRING *stmp = NULL; + + *palg = NULL; + if (mgf1md == NULL || EVP_MD_is_a(mgf1md, "SHA1")) + return 1; + /* need to embed algorithm ID inside another */ + if (!ossl_x509_algor_new_from_md(&algtmp, mgf1md)) + goto err; + if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL) + goto err; + *palg = X509_ALGOR_new(); + if (*palg == NULL) + goto err; + X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp); + stmp = NULL; + err: + ASN1_STRING_free(stmp); + X509_ALGOR_free(algtmp); + if (*palg != NULL) + return 1; + return 0; +} diff --git a/crypto/asn1/x_bignum.c b/crypto/asn1/x_bignum.c --- a/crypto/asn1/x_bignum.c +++ b/crypto/asn1/x_bignum.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -25,13 +25,13 @@ static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it); static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it); -static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +static int bn_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); -static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx); static ASN1_PRIMITIVE_FUNCS bignum_pf = { @@ -91,7 +91,7 @@ *pval = NULL; } -static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +static int bn_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it) { BIGNUM *bn; @@ -146,7 +146,7 @@ return ret; } -static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx) { if (!BN_print(out, *(BIGNUM **)pval)) diff --git a/crypto/asn1/x_info.c b/crypto/asn1/x_info.c --- a/crypto/asn1/x_info.c +++ b/crypto/asn1/x_info.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,7 +19,7 @@ ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ASN1err(ASN1_F_X509_INFO_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/crypto/asn1/x_int64.c b/crypto/asn1/x_int64.c --- a/crypto/asn1/x_int64.c +++ b/crypto/asn1/x_int64.c @@ -1,7 +1,7 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -29,7 +29,7 @@ static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) { - ASN1err(ASN1_F_UINT64_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } return 1; @@ -46,8 +46,8 @@ **(uint64_t **)pval = 0; } -static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, - const ASN1_ITEM *it) +static int uint64_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) { uint64_t utmp; int neg = 0; @@ -62,16 +62,16 @@ return -1; if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED && (int64_t)utmp < 0) { - /* i2c_uint64_int() assumes positive values */ + /* ossl_i2c_uint64_int() assumes positive values */ utmp = 0 - utmp; neg = 1; } - return i2c_uint64_int(cont, utmp, neg); + return ossl_i2c_uint64_int(cont, utmp, neg); } static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, - int utype, char *free_cont, const ASN1_ITEM *it) + int utype, char *free_cont, const ASN1_ITEM *it) { uint64_t utmp = 0; char *cp; @@ -91,19 +91,19 @@ if (len == 0) goto long_compat; - if (!c2i_uint64_int(&utmp, &neg, &cont, len)) + if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len)) return 0; if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { - ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE); return 0; } if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED && !neg && utmp > INT64_MAX) { - ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } if (neg) - /* c2i_uint64_int() returns positive values */ + /* ossl_c2i_uint64_int() returns positive values */ utmp = 0 - utmp; long_compat: @@ -111,7 +111,7 @@ return 1; } -static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +static int uint64_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx) { if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) @@ -124,7 +124,7 @@ static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) { - ASN1err(ASN1_F_UINT32_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return 0; } return 1; @@ -141,8 +141,8 @@ **(uint32_t **)pval = 0; } -static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, - const ASN1_ITEM *it) +static int uint32_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it) { uint32_t utmp; int neg = 0; @@ -157,12 +157,12 @@ return -1; if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED && (int32_t)utmp < 0) { - /* i2c_uint64_int() assumes positive values */ + /* ossl_i2c_uint64_int() assumes positive values */ utmp = 0 - utmp; neg = 1; } - return i2c_uint64_int(cont, (uint64_t)utmp, neg); + return ossl_i2c_uint64_int(cont, (uint64_t)utmp, neg); } /* @@ -173,7 +173,7 @@ #define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1) static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, - int utype, char *free_cont, const ASN1_ITEM *it) + int utype, char *free_cont, const ASN1_ITEM *it) { uint64_t utmp = 0; uint32_t utmp2 = 0; @@ -194,22 +194,22 @@ if (len == 0) goto long_compat; - if (!c2i_uint64_int(&utmp, &neg, &cont, len)) + if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len)) return 0; if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { - ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE); return 0; } if (neg) { if (utmp > ABS_INT32_MIN) { - ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_SMALL); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); return 0; } utmp = 0 - utmp; } else { if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX) || ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) { - ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE); + ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE); return 0; } } @@ -220,7 +220,7 @@ return 1; } -static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +static int uint32_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx) { if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) diff --git a/crypto/asn1/x_long.c b/crypto/asn1/x_long.c --- a/crypto/asn1/x_long.c +++ b/crypto/asn1/x_long.c @@ -1,7 +1,7 @@ /* - * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,10 +11,6 @@ #include "internal/cryptlib.h" #include -#if !(OPENSSL_API_COMPAT < 0x10200000L) -NON_EMPTY_TRANSLATION_UNIT -#else - #define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b)) /* @@ -25,11 +21,11 @@ static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it); static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); -static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); -static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +static int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx); static ASN1_PRIMITIVE_FUNCS long_pf = { @@ -86,7 +82,7 @@ return (int)ret; } -static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it) { long ltmp; @@ -156,7 +152,7 @@ } } if (len > (int)sizeof(long)) { - ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); return 0; } @@ -167,7 +163,7 @@ else sign = 0; } else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */ - ASN1err(ASN1_F_LONG_C2I, ASN1_R_ILLEGAL_PADDING); + ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING); return 0; } utmp = 0; @@ -177,20 +173,20 @@ } ltmp = (long)utmp; if (ltmp < 0) { - ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); return 0; } if (sign) ltmp = -ltmp - 1; if (ltmp == it->size) { - ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); return 0; } memcpy(pval, <mp, COPY_SIZE(*pval, ltmp)); return 1; } -static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +static int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx) { long l; @@ -198,4 +194,3 @@ memcpy(&l, pval, COPY_SIZE(*pval, l)); return BIO_printf(out, "%ld\n", l); } -#endif diff --git a/crypto/asn1/x_pkey.c b/crypto/asn1/x_pkey.c --- a/crypto/asn1/x_pkey.c +++ b/crypto/asn1/x_pkey.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -29,7 +29,7 @@ return ret; err: X509_PKEY_free(ret); - ASN1err(ASN1_F_X509_PKEY_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/crypto/asn1/x_sig.c b/crypto/asn1/x_sig.c --- a/crypto/asn1/x_sig.c +++ b/crypto/asn1/x_sig.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/x_spki.c b/crypto/asn1/x_spki.c --- a/crypto/asn1/x_spki.c +++ b/crypto/asn1/x_spki.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1/x_val.c b/crypto/asn1/x_val.c --- a/crypto/asn1/x_val.c +++ b/crypto/asn1/x_val.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/asn1_dsa.c b/crypto/asn1_dsa.c new file mode 100644 --- /dev/null +++ b/crypto/asn1_dsa.c @@ -0,0 +1,252 @@ +/* + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * A simple ASN.1 DER encoder/decoder for DSA-Sig-Value and ECDSA-Sig-Value. + * + * DSA-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * ECDSA-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + */ + +#include +#include +#include "crypto/asn1_dsa.h" +#include "internal/packet.h" + +#define ID_SEQUENCE 0x30 +#define ID_INTEGER 0x02 + +/* + * Outputs the encoding of the length octets for a DER value with a content + * length of cont_len bytes to pkt. The maximum supported content length is + * 65535 (0xffff) bytes. + * + * Returns 1 on success or 0 on error. + */ +int ossl_encode_der_length(WPACKET *pkt, size_t cont_len) +{ + if (cont_len > 0xffff) + return 0; /* Too large for supported length encodings */ + + if (cont_len > 0xff) { + if (!WPACKET_put_bytes_u8(pkt, 0x82) + || !WPACKET_put_bytes_u16(pkt, cont_len)) + return 0; + } else { + if (cont_len > 0x7f + && !WPACKET_put_bytes_u8(pkt, 0x81)) + return 0; + if (!WPACKET_put_bytes_u8(pkt, cont_len)) + return 0; + } + + return 1; +} + +/* + * Outputs the DER encoding of a positive ASN.1 INTEGER to pkt. + * + * Results in an error if n is negative or too large. + * + * Returns 1 on success or 0 on error. + */ +int ossl_encode_der_integer(WPACKET *pkt, const BIGNUM *n) +{ + unsigned char *bnbytes; + size_t cont_len; + + if (BN_is_negative(n)) + return 0; + + /* + * Calculate the ASN.1 INTEGER DER content length for n. + * This is the number of whole bytes required to represent n (i.e. rounded + * down), plus one. + * If n is zero then the content is a single zero byte (length = 1). + * If the number of bits of n is a multiple of 8 then an extra zero padding + * byte is included to ensure that the value is still treated as positive + * in the INTEGER two's complement representation. + */ + cont_len = BN_num_bits(n) / 8 + 1; + + if (!WPACKET_start_sub_packet(pkt) + || !WPACKET_put_bytes_u8(pkt, ID_INTEGER) + || !ossl_encode_der_length(pkt, cont_len) + || !WPACKET_allocate_bytes(pkt, cont_len, &bnbytes) + || !WPACKET_close(pkt)) + return 0; + + if (bnbytes != NULL + && BN_bn2binpad(n, bnbytes, (int)cont_len) != (int)cont_len) + return 0; + + return 1; +} + +/* + * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to pkt. pkt + * may be initialised with a NULL buffer which enables pkt to be used to + * calculate how many bytes would be needed. + * + * Returns 1 on success or 0 on error. + */ +int ossl_encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s) +{ + WPACKET tmppkt, *dummypkt; + size_t cont_len; + int isnull = WPACKET_is_null_buf(pkt); + + if (!WPACKET_start_sub_packet(pkt)) + return 0; + + if (!isnull) { + if (!WPACKET_init_null(&tmppkt, 0)) + return 0; + dummypkt = &tmppkt; + } else { + /* If the input packet has a NULL buffer, we don't need a dummy packet */ + dummypkt = pkt; + } + + /* Calculate the content length */ + if (!ossl_encode_der_integer(dummypkt, r) + || !ossl_encode_der_integer(dummypkt, s) + || !WPACKET_get_length(dummypkt, &cont_len) + || (!isnull && !WPACKET_finish(dummypkt))) { + if (!isnull) + WPACKET_cleanup(dummypkt); + return 0; + } + + /* Add the tag and length bytes */ + if (!WPACKET_put_bytes_u8(pkt, ID_SEQUENCE) + || !ossl_encode_der_length(pkt, cont_len) + /* + * Really encode the integers. We already wrote to the main pkt + * if it had a NULL buffer, so don't do it again + */ + || (!isnull && !ossl_encode_der_integer(pkt, r)) + || (!isnull && !ossl_encode_der_integer(pkt, s)) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +/* + * Decodes the DER length octets in pkt and initialises subpkt with the + * following bytes of that length. + * + * Returns 1 on success or 0 on failure. + */ +int ossl_decode_der_length(PACKET *pkt, PACKET *subpkt) +{ + unsigned int byte; + + if (!PACKET_get_1(pkt, &byte)) + return 0; + + if (byte < 0x80) + return PACKET_get_sub_packet(pkt, subpkt, (size_t)byte); + if (byte == 0x81) + return PACKET_get_length_prefixed_1(pkt, subpkt); + if (byte == 0x82) + return PACKET_get_length_prefixed_2(pkt, subpkt); + + /* Too large, invalid, or not DER. */ + return 0; +} + +/* + * Decodes a single ASN.1 INTEGER value from pkt, which must be DER encoded, + * and updates n with the decoded value. + * + * The BIGNUM, n, must have already been allocated by calling BN_new(). + * pkt must not be NULL. + * + * An attempt to consume more than len bytes results in an error. + * Returns 1 on success or 0 on error. + * + * If the PACKET is supposed to only contain a single INTEGER value with no + * trailing garbage then it is up to the caller to verify that all bytes + * were consumed. + */ +int ossl_decode_der_integer(PACKET *pkt, BIGNUM *n) +{ + PACKET contpkt, tmppkt; + unsigned int tag, tmp; + + /* Check we have an integer and get the content bytes */ + if (!PACKET_get_1(pkt, &tag) + || tag != ID_INTEGER + || !ossl_decode_der_length(pkt, &contpkt)) + return 0; + + /* Peek ahead at the first bytes to check for proper encoding */ + tmppkt = contpkt; + /* The INTEGER must be positive */ + if (!PACKET_get_1(&tmppkt, &tmp) + || (tmp & 0x80) != 0) + return 0; + /* If there a zero padding byte the next byte must have the msb set */ + if (PACKET_remaining(&tmppkt) > 0 && tmp == 0) { + if (!PACKET_get_1(&tmppkt, &tmp) + || (tmp & 0x80) == 0) + return 0; + } + + if (BN_bin2bn(PACKET_data(&contpkt), + (int)PACKET_remaining(&contpkt), n) == NULL) + return 0; + + return 1; +} + +/* + * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be + * DER encoded, updates r and s with the decoded values, and increments *ppin + * past the data that was consumed. + * + * The BIGNUMs, r and s, must have already been allocated by calls to BN_new(). + * ppin and *ppin must not be NULL. + * + * An attempt to consume more than len bytes results in an error. + * Returns the number of bytes of input consumed or 0 if an error occurs. + * + * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no + * trailing garbage then it is up to the caller to verify that all bytes + * were consumed. + */ +size_t ossl_decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, + const unsigned char **ppin, size_t len) +{ + size_t consumed; + PACKET pkt, contpkt; + unsigned int tag; + + if (!PACKET_buf_init(&pkt, *ppin, len) + || !PACKET_get_1(&pkt, &tag) + || tag != ID_SEQUENCE + || !ossl_decode_der_length(&pkt, &contpkt) + || !ossl_decode_der_integer(&contpkt, r) + || !ossl_decode_der_integer(&contpkt, s) + || PACKET_remaining(&contpkt) != 0) + return 0; + + consumed = PACKET_data(&pkt) - *ppin; + *ppin += consumed; + return consumed; +} diff --git a/crypto/async/arch/async_null.h b/crypto/async/arch/async_null.h --- a/crypto/async/arch/async_null.h +++ b/crypto/async/arch/async_null.h @@ -1,7 +1,7 @@ /* * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/async/arch/async_null.c b/crypto/async/arch/async_null.c --- a/crypto/async/arch/async_null.c +++ b/crypto/async/arch/async_null.c @@ -1,7 +1,7 @@ /* * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h --- a/crypto/async/arch/async_posix.h +++ b/crypto/async/arch/async_posix.h @@ -1,7 +1,7 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -25,17 +25,47 @@ # define ASYNC_POSIX # define ASYNC_ARCH +# if defined(__CET__) || defined(__ia64__) +/* + * When Intel CET is enabled, makecontext will create a different + * shadow stack for each context. async_fibre_swapcontext cannot + * use _longjmp. It must call swapcontext to swap shadow stack as + * well as normal stack. + * On IA64 the register stack engine is not saved across setjmp/longjmp. Here + * swapcontext() performs correctly. + */ +# define USE_SWAPCONTEXT +# endif +# if defined(__aarch64__) && defined(__clang__) \ + && defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 +/* + * setjmp/longjmp don't currently work with BTI on all libc implementations + * when compiled by clang. This is because clang doesn't put a BTI after the + * call to setjmp where it returns the second time. This then fails on libc + * implementations - notably glibc - which use an indirect jump to there. + * So use the swapcontext implementation, which does work. + * See https://github.com/llvm/llvm-project/issues/48888. + */ +# define USE_SWAPCONTEXT +# endif # include -# include +# ifndef USE_SWAPCONTEXT +# include +# endif typedef struct async_fibre_st { ucontext_t fibre; +# ifndef USE_SWAPCONTEXT jmp_buf env; int env_init; +# endif } async_fibre; static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r) { +# ifdef USE_SWAPCONTEXT + swapcontext(&o->fibre, &n->fibre); +# else o->env_init = 1; if (!r || !_setjmp(o->env)) { @@ -44,6 +74,7 @@ else setcontext(&n->fibre); } +# endif return 1; } diff --git a/crypto/async/arch/async_posix.c b/crypto/async/arch/async_posix.c --- a/crypto/async/arch/async_posix.c +++ b/crypto/async/arch/async_posix.c @@ -1,7 +1,7 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -34,7 +34,9 @@ int async_fibre_makecontext(async_fibre *fibre) { +#ifndef USE_SWAPCONTEXT fibre->env_init = 0; +#endif if (getcontext(&fibre->fibre) == 0) { fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE); if (fibre->fibre.uc_stack.ss_sp != NULL) { diff --git a/crypto/async/arch/async_win.h b/crypto/async/arch/async_win.h --- a/crypto/async/arch/async_win.h +++ b/crypto/async/arch/async_win.h @@ -1,7 +1,7 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -26,8 +26,16 @@ # define async_fibre_swapcontext(o,n,r) \ (SwitchToFiber((n)->fibre), 1) -# define async_fibre_makecontext(c) \ + +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 +# define async_fibre_makecontext(c) \ + ((c)->fibre = CreateFiberEx(0, 0, FIBER_FLAG_FLOAT_SWITCH, \ + async_start_func_win, 0)) +# else +# define async_fibre_makecontext(c) \ ((c)->fibre = CreateFiber(0, async_start_func_win, 0)) +# endif + # define async_fibre_free(f) (DeleteFiber((f)->fibre)) int async_fibre_init_dispatcher(async_fibre *fibre); diff --git a/crypto/async/async.c b/crypto/async/async.c --- a/crypto/async/async.c +++ b/crypto/async/async.c @@ -1,7 +1,7 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -30,16 +30,18 @@ static CRYPTO_THREAD_LOCAL ctxkey; static CRYPTO_THREAD_LOCAL poolkey; +static void async_delete_thread_state(void *arg); + static async_ctx *async_ctx_new(void) { async_ctx *nctx; - if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC)) + if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state)) return NULL; nctx = OPENSSL_malloc(sizeof(*nctx)); if (nctx == NULL) { - ASYNCerr(ASYNC_F_ASYNC_CTX_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); goto err; } @@ -81,7 +83,7 @@ job = OPENSSL_zalloc(sizeof(*job)); if (job == NULL) { - ASYNCerr(ASYNC_F_ASYNC_JOB_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); return NULL; } @@ -136,6 +138,10 @@ async_pool *pool; pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); + if (pool == NULL) { + ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); + return; + } OPENSSL_free(job->funcargs); job->funcargs = NULL; sk_ASYNC_JOB_push(pool->jobs, job); @@ -146,6 +152,10 @@ ASYNC_JOB *job; async_ctx *ctx = async_get_ctx(); + if (ctx == NULL) { + ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); + return; + } while (1) { /* Run the job */ job = ctx->currjob; @@ -159,7 +169,7 @@ * Should not happen. Getting here will close the thread...can't do * much about it */ - ASYNCerr(ASYNC_F_ASYNC_START_FUNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); + ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); } } } @@ -168,6 +178,7 @@ int (*func)(void *), void *args, size_t size) { async_ctx *ctx; + OSSL_LIB_CTX *libctx; if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) return ASYNC_ERR; @@ -178,7 +189,7 @@ if (ctx == NULL) return ASYNC_ERR; - if (*job) + if (*job != NULL) ctx->currjob = *job; for (;;) { @@ -200,19 +211,38 @@ } if (ctx->currjob->status == ASYNC_JOB_PAUSED) { + if (*job == NULL) + return ASYNC_ERR; ctx->currjob = *job; + + /* + * Restore the default libctx to what it was the last time the + * fibre ran + */ + libctx = OSSL_LIB_CTX_set0_default(ctx->currjob->libctx); + if (libctx == NULL) { + /* Failed to set the default context */ + ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); + goto err; + } /* Resume previous job */ if (!async_fibre_swapcontext(&ctx->dispatcher, &ctx->currjob->fibrectx, 1)) { - ASYNCerr(ASYNC_F_ASYNC_START_JOB, - ASYNC_R_FAILED_TO_SWAP_CONTEXT); + ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx); + ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); goto err; } + /* + * In case the fibre changed the default libctx we set it back + * again to what it was originally, and remember what it had + * been changed to. + */ + ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx); continue; } /* Should not happen */ - ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); async_release_job(ctx->currjob); ctx->currjob = NULL; *job = NULL; @@ -226,7 +256,7 @@ if (args != NULL) { ctx->currjob->funcargs = OPENSSL_malloc(size); if (ctx->currjob->funcargs == NULL) { - ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); async_release_job(ctx->currjob); ctx->currjob = NULL; return ASYNC_ERR; @@ -238,11 +268,17 @@ ctx->currjob->func = func; ctx->currjob->waitctx = wctx; + libctx = ossl_lib_ctx_get_concrete(NULL); if (!async_fibre_swapcontext(&ctx->dispatcher, &ctx->currjob->fibrectx, 1)) { - ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT); + ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); goto err; } + /* + * In case the fibre changed the default libctx we set it back again + * to what it was, and remember what it had been changed to. + */ + ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx); } err: @@ -272,7 +308,7 @@ if (!async_fibre_swapcontext(&job->fibrectx, &ctx->dispatcher, 1)) { - ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT); + ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); return 0; } /* Reset counts of added and deleted fds */ @@ -285,7 +321,7 @@ { ASYNC_JOB *job; - if (!pool || !pool->jobs) + if (pool == NULL || pool->jobs == NULL) return; do { @@ -319,25 +355,25 @@ size_t curr_size = 0; if (init_size > max_size) { - ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INVALID_POOL_SIZE); + ERR_raise(ERR_LIB_ASYNC, ASYNC_R_INVALID_POOL_SIZE); return 0; } if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) return 0; - if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC)) + if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state)) return 0; pool = OPENSSL_zalloc(sizeof(*pool)); if (pool == NULL) { - ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); return 0; } pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size); if (pool->jobs == NULL) { - ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); OPENSSL_free(pool); return 0; } @@ -362,7 +398,7 @@ } pool->curr_size = curr_size; if (!CRYPTO_THREAD_set_local(&poolkey, pool)) { - ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_FAILED_TO_SET_POOL); + ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL); goto err; } @@ -374,7 +410,7 @@ return 0; } -void async_delete_thread_state(void) +static void async_delete_thread_state(void *arg) { async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); @@ -393,7 +429,7 @@ if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) return; - async_delete_thread_state(); + async_delete_thread_state(NULL); } ASYNC_JOB *ASYNC_get_current_job(void) diff --git a/crypto/async/async_err.c b/crypto/async/async_err.c --- a/crypto/async/async_err.c +++ b/crypto/async/async_err.c @@ -1,8 +1,8 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,22 +10,10 @@ #include #include +#include "crypto/asyncerr.h" #ifndef OPENSSL_NO_ERR -static const ERR_STRING_DATA ASYNC_str_functs[] = { - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_CTX_NEW, 0), "async_ctx_new"}, - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_INIT_THREAD, 0), - "ASYNC_init_thread"}, - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_JOB_NEW, 0), "async_job_new"}, - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_PAUSE_JOB, 0), "ASYNC_pause_job"}, - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_FUNC, 0), "async_start_func"}, - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_JOB, 0), "ASYNC_start_job"}, - {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, 0), - "ASYNC_WAIT_CTX_set_wait_fd"}, - {0, NULL} -}; - static const ERR_STRING_DATA ASYNC_str_reasons[] = { {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SET_POOL), "failed to set pool"}, @@ -39,13 +27,11 @@ #endif -int ERR_load_ASYNC_strings(void) +int ossl_err_load_ASYNC_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(ASYNC_str_functs[0].error) == NULL) { - ERR_load_strings_const(ASYNC_str_functs); + if (ERR_reason_error_string(ASYNC_str_reasons[0].error) == NULL) ERR_load_strings_const(ASYNC_str_reasons); - } #endif return 1; } diff --git a/crypto/async/async_local.h b/crypto/async/async_local.h --- a/crypto/async/async_local.h +++ b/crypto/async/async_local.h @@ -1,7 +1,7 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -43,6 +43,7 @@ int ret; int status; ASYNC_WAIT_CTX *waitctx; + OSSL_LIB_CTX *libctx; }; struct fd_lookup_st { @@ -59,6 +60,9 @@ struct fd_lookup_st *fds; size_t numadd; size_t numdel; + ASYNC_callback_fn callback; + void *callback_arg; + int status; }; DEFINE_STACK_OF(ASYNC_JOB) diff --git a/crypto/async/async_wait.c b/crypto/async/async_wait.c --- a/crypto/async/async_wait.c +++ b/crypto/async/async_wait.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -48,7 +48,7 @@ struct fd_lookup_st *fdlookup; if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) { - ASYNCerr(ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); return 0; } @@ -182,6 +182,41 @@ return 0; } +int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx, + ASYNC_callback_fn callback, + void *callback_arg) +{ + if (ctx == NULL) + return 0; + + ctx->callback = callback; + ctx->callback_arg = callback_arg; + return 1; +} + +int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx, + ASYNC_callback_fn *callback, + void **callback_arg) +{ + if (ctx->callback == NULL) + return 0; + + *callback = ctx->callback; + *callback_arg = ctx->callback_arg; + return 1; +} + +int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status) +{ + ctx->status = status; + return 1; +} + +int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx) +{ + return ctx->status; +} + void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx) { struct fd_lookup_st *curr, *prev = NULL; diff --git a/crypto/bf/asm/bf-586.pl b/crypto/bf/asm/bf-586.pl --- a/crypto/bf/asm/bf-586.pl +++ b/crypto/bf/asm/bf-586.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -12,8 +12,7 @@ require "x86asm.pl"; require "cbc.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); diff --git a/crypto/bf/bf_cfb64.c b/crypto/bf/bf_cfb64.c --- a/crypto/bf/bf_cfb64.c +++ b/crypto/bf/bf_cfb64.c @@ -1,12 +1,18 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * BF low level APIs are deprecated for public use, but still ok for internal + * use. + */ +#include "internal/deprecated.h" + #include #include "bf_local.h" diff --git a/crypto/bf/bf_ecb.c b/crypto/bf/bf_ecb.c --- a/crypto/bf/bf_ecb.c +++ b/crypto/bf/bf_ecb.c @@ -1,12 +1,18 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * BF low level APIs are deprecated for public use, but still ok for internal + * use. + */ +#include "internal/deprecated.h" + #include #include "bf_local.h" #include diff --git a/crypto/bf/bf_enc.c b/crypto/bf/bf_enc.c --- a/crypto/bf/bf_enc.c +++ b/crypto/bf/bf_enc.c @@ -1,12 +1,18 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * BF low level APIs are deprecated for public use, but still ok for internal + * use. + */ +#include "internal/deprecated.h" + #include #include "bf_local.h" diff --git a/crypto/bf/bf_local.h b/crypto/bf/bf_local.h --- a/crypto/bf/bf_local.h +++ b/crypto/bf/bf_local.h @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bf/bf_ofb64.c b/crypto/bf/bf_ofb64.c --- a/crypto/bf/bf_ofb64.c +++ b/crypto/bf/bf_ofb64.c @@ -1,12 +1,18 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * BF low level APIs are deprecated for public use, but still ok for internal + * use. + */ +#include "internal/deprecated.h" + #include #include "bf_local.h" diff --git a/crypto/bf/bf_pi.h b/crypto/bf/bf_pi.h --- a/crypto/bf/bf_pi.h +++ b/crypto/bf/bf_pi.h @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bf/bf_skey.c b/crypto/bf/bf_skey.c --- a/crypto/bf/bf_skey.c +++ b/crypto/bf/bf_skey.c @@ -1,12 +1,18 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +/* + * BF low level APIs are deprecated for public use, but still ok for internal + * use. + */ +#include "internal/deprecated.h" + #include #include #include diff --git a/crypto/bf/build.info b/crypto/bf/build.info --- a/crypto/bf/build.info +++ b/crypto/bf/build.info @@ -1,7 +1,25 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c \ - {- $target{bf_asm_src} -} -GENERATE[bf-586.s]=asm/bf-586.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[bf-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl +$BFASM=bf_enc.c +IF[{- !$disabled{asm} -}] + $BFASM_x86=bf-586.S + + # Now that we have defined all the arch specific variables, use the + # appropriate one + IF[$BFASM_{- $target{asm_arch} -}] + $BFASM=$BFASM_{- $target{asm_arch} -} + ENDIF +ENDIF + +$ALL=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c $BFASM + +SOURCE[../../libcrypto]=$ALL + +# When all deprecated symbols are removed, libcrypto doesn't export the +# blowfish functions, so we must include them directly in liblegacy.a +IF[{- $disabled{'deprecated-3.0'} && !$disabled{module} && !$disabled{shared} -}] + SOURCE[../../providers/liblegacy.a]=$ALL +ENDIF + +GENERATE[bf-586.S]=asm/bf-586.pl +DEPEND[bf-586.S]=../perlasm/x86asm.pl ../perlasm/cbc.pl diff --git a/crypto/bio/b_addr.c b/crypto/bio/b_addr.c deleted file mode 100644 --- a/crypto/bio/b_addr.c +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Copyright 2016-2022 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 - */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include -#include - -#include "bio_local.h" -#include - -#ifndef OPENSSL_NO_SOCK -#include -#include -#include "internal/thread_once.h" - -CRYPTO_RWLOCK *bio_lookup_lock; -static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT; - -/* - * Throughout this file and bio_local.h, the existence of the macro - * AI_PASSIVE is used to detect the availability of struct addrinfo, - * getnameinfo() and getaddrinfo(). If that macro doesn't exist, - * we use our own implementation instead, using gethostbyname, - * getservbyname and a few other. - */ - -/********************************************************************** - * - * Address structure - * - */ - -BIO_ADDR *BIO_ADDR_new(void) -{ - BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret)); - - if (ret == NULL) { - BIOerr(BIO_F_BIO_ADDR_NEW, ERR_R_MALLOC_FAILURE); - return NULL; - } - - ret->sa.sa_family = AF_UNSPEC; - return ret; -} - -void BIO_ADDR_free(BIO_ADDR *ap) -{ - OPENSSL_free(ap); -} - -void BIO_ADDR_clear(BIO_ADDR *ap) -{ - memset(ap, 0, sizeof(*ap)); - ap->sa.sa_family = AF_UNSPEC; -} - -/* - * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents - * of a struct sockaddr. - */ -int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa) -{ - if (sa->sa_family == AF_INET) { - memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in)); - return 1; - } -#ifdef AF_INET6 - if (sa->sa_family == AF_INET6) { - memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6)); - return 1; - } -#endif -#ifdef AF_UNIX - if (sa->sa_family == AF_UNIX) { - memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un)); - return 1; - } -#endif - - return 0; -} - -int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, - const void *where, size_t wherelen, - unsigned short port) -{ -#ifdef AF_UNIX - if (family == AF_UNIX) { - if (wherelen + 1 > sizeof(ap->s_un.sun_path)) - return 0; - memset(&ap->s_un, 0, sizeof(ap->s_un)); - ap->s_un.sun_family = family; - strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1); - return 1; - } -#endif - if (family == AF_INET) { - if (wherelen != sizeof(struct in_addr)) - return 0; - memset(&ap->s_in, 0, sizeof(ap->s_in)); - ap->s_in.sin_family = family; - ap->s_in.sin_port = port; - ap->s_in.sin_addr = *(struct in_addr *)where; - return 1; - } -#ifdef AF_INET6 - if (family == AF_INET6) { - if (wherelen != sizeof(struct in6_addr)) - return 0; - memset(&ap->s_in6, 0, sizeof(ap->s_in6)); - ap->s_in6.sin6_family = family; - ap->s_in6.sin6_port = port; - ap->s_in6.sin6_addr = *(struct in6_addr *)where; - return 1; - } -#endif - - return 0; -} - -int BIO_ADDR_family(const BIO_ADDR *ap) -{ - return ap->sa.sa_family; -} - -int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l) -{ - size_t len = 0; - const void *addrptr = NULL; - - if (ap->sa.sa_family == AF_INET) { - len = sizeof(ap->s_in.sin_addr); - addrptr = &ap->s_in.sin_addr; - } -#ifdef AF_INET6 - else if (ap->sa.sa_family == AF_INET6) { - len = sizeof(ap->s_in6.sin6_addr); - addrptr = &ap->s_in6.sin6_addr; - } -#endif -#ifdef AF_UNIX - else if (ap->sa.sa_family == AF_UNIX) { - len = strlen(ap->s_un.sun_path); - addrptr = &ap->s_un.sun_path; - } -#endif - - if (addrptr == NULL) - return 0; - - if (p != NULL) { - memcpy(p, addrptr, len); - } - if (l != NULL) - *l = len; - - return 1; -} - -unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap) -{ - if (ap->sa.sa_family == AF_INET) - return ap->s_in.sin_port; -#ifdef AF_INET6 - if (ap->sa.sa_family == AF_INET6) - return ap->s_in6.sin6_port; -#endif - return 0; -} - -/*- - * addr_strings - helper function to get host and service names - * @ap: the BIO_ADDR that has the input info - * @numeric: 0 if actual names should be returned, 1 if the numeric - * representation should be returned. - * @hostname: a pointer to a pointer to a memory area to store the - * host name or numeric representation. Unused if NULL. - * @service: a pointer to a pointer to a memory area to store the - * service name or numeric representation. Unused if NULL. - * - * The return value is 0 on failure, with the error code in the error - * stack, and 1 on success. - */ -static int addr_strings(const BIO_ADDR *ap, int numeric, - char **hostname, char **service) -{ - if (BIO_sock_init() != 1) - return 0; - - if (1) { -#ifdef AI_PASSIVE - int ret = 0; - char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = ""; - int flags = 0; - - if (numeric) - flags |= NI_NUMERICHOST | NI_NUMERICSERV; - - if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap), - BIO_ADDR_sockaddr_size(ap), - host, sizeof(host), serv, sizeof(serv), - flags)) != 0) { -# ifdef EAI_SYSTEM - if (ret == EAI_SYSTEM) { - SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error()); - BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); - } else -# endif - { - BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); - ERR_add_error_data(1, gai_strerror(ret)); - } - return 0; - } - - /* VMS getnameinfo() has a bug, it doesn't fill in serv, which - * leaves it with whatever garbage that happens to be there. - * However, we initialise serv with the empty string (serv[0] - * is therefore NUL), so it gets real easy to detect when things - * didn't go the way one might expect. - */ - if (serv[0] == '\0') { - BIO_snprintf(serv, sizeof(serv), "%d", - ntohs(BIO_ADDR_rawport(ap))); - } - - if (hostname != NULL) - *hostname = OPENSSL_strdup(host); - if (service != NULL) - *service = OPENSSL_strdup(serv); - } else { -#endif - if (hostname != NULL) - *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr)); - if (service != NULL) { - char serv[6]; /* port is 16 bits => max 5 decimal digits */ - BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port)); - *service = OPENSSL_strdup(serv); - } - } - - if ((hostname != NULL && *hostname == NULL) - || (service != NULL && *service == NULL)) { - if (hostname != NULL) { - OPENSSL_free(*hostname); - *hostname = NULL; - } - if (service != NULL) { - OPENSSL_free(*service); - *service = NULL; - } - BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE); - return 0; - } - - return 1; -} - -char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric) -{ - char *hostname = NULL; - - if (addr_strings(ap, numeric, &hostname, NULL)) - return hostname; - - return NULL; -} - -char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric) -{ - char *service = NULL; - - if (addr_strings(ap, numeric, NULL, &service)) - return service; - - return NULL; -} - -char *BIO_ADDR_path_string(const BIO_ADDR *ap) -{ -#ifdef AF_UNIX - if (ap->sa.sa_family == AF_UNIX) - return OPENSSL_strdup(ap->s_un.sun_path); -#endif - return NULL; -} - -/* - * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr - * for a given BIO_ADDR. In reality, this is simply a type safe cast. - * The returned struct sockaddr is const, so it can't be tampered with. - */ -const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap) -{ - return &(ap->sa); -} - -/* - * BIO_ADDR_sockaddr_noconst - non-public function that does the same - * as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as - * it allows you to tamper with the data (and thereby the contents - * of the input BIO_ADDR). - */ -struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap) -{ - return &(ap->sa); -} - -/* - * BIO_ADDR_sockaddr_size - non-public function that returns the size - * of the struct sockaddr the BIO_ADDR is using. If the protocol family - * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX, - * the size of the BIO_ADDR type is returned. - */ -socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap) -{ - if (ap->sa.sa_family == AF_INET) - return sizeof(ap->s_in); -#ifdef AF_INET6 - if (ap->sa.sa_family == AF_INET6) - return sizeof(ap->s_in6); -#endif -#ifdef AF_UNIX - if (ap->sa.sa_family == AF_UNIX) - return sizeof(ap->s_un); -#endif - return sizeof(*ap); -} - -/********************************************************************** - * - * Address info database - * - */ - -const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) - return bai->bai_next; - return NULL; -} - -int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) - return bai->bai_family; - return 0; -} - -int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) - return bai->bai_socktype; - return 0; -} - -int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) { - if (bai->bai_protocol != 0) - return bai->bai_protocol; - -#ifdef AF_UNIX - if (bai->bai_family == AF_UNIX) - return 0; -#endif - - switch (bai->bai_socktype) { - case SOCK_STREAM: - return IPPROTO_TCP; - case SOCK_DGRAM: - return IPPROTO_UDP; - default: - break; - } - } - return 0; -} - -/* - * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size - * of the struct sockaddr inside the BIO_ADDRINFO. - */ -socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) - return bai->bai_addrlen; - return 0; -} - -/* - * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr - * as the struct sockaddr it is. - */ -const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) - return bai->bai_addr; - return NULL; -} - -const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai) -{ - if (bai != NULL) - return (BIO_ADDR *)bai->bai_addr; - return NULL; -} - -void BIO_ADDRINFO_free(BIO_ADDRINFO *bai) -{ - if (bai == NULL) - return; - -#ifdef AI_PASSIVE -# ifdef AF_UNIX -# define _cond bai->bai_family != AF_UNIX -# else -# define _cond 1 -# endif - if (_cond) { - freeaddrinfo(bai); - return; - } -#endif - - /* Free manually when we know that addrinfo_wrap() was used. - * See further comment above addrinfo_wrap() - */ - while (bai != NULL) { - BIO_ADDRINFO *next = bai->bai_next; - OPENSSL_free(bai->bai_addr); - OPENSSL_free(bai); - bai = next; - } -} - -/********************************************************************** - * - * Service functions - * - */ - -/*- - * The specs in hostserv can take these forms: - * - * host:service => *host = "host", *service = "service" - * host:* => *host = "host", *service = NULL - * host: => *host = "host", *service = NULL - * :service => *host = NULL, *service = "service" - * *:service => *host = NULL, *service = "service" - * - * in case no : is present in the string, the result depends on - * hostserv_prio, as follows: - * - * when hostserv_prio == BIO_PARSE_PRIO_HOST - * host => *host = "host", *service untouched - * - * when hostserv_prio == BIO_PARSE_PRIO_SERV - * service => *host untouched, *service = "service" - * - */ -int BIO_parse_hostserv(const char *hostserv, char **host, char **service, - enum BIO_hostserv_priorities hostserv_prio) -{ - const char *h = NULL; size_t hl = 0; - const char *p = NULL; size_t pl = 0; - - if (*hostserv == '[') { - if ((p = strchr(hostserv, ']')) == NULL) - goto spec_err; - h = hostserv + 1; - hl = p - h; - p++; - if (*p == '\0') - p = NULL; - else if (*p != ':') - goto spec_err; - else { - p++; - pl = strlen(p); - } - } else { - const char *p2 = strrchr(hostserv, ':'); - p = strchr(hostserv, ':'); - - /*- - * Check for more than one colon. There are three possible - * interpretations: - * 1. IPv6 address with port number, last colon being separator. - * 2. IPv6 address only. - * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST, - * IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV - * Because of this ambiguity, we currently choose to make it an - * error. - */ - if (p != p2) - goto amb_err; - - if (p != NULL) { - h = hostserv; - hl = p - h; - p++; - pl = strlen(p); - } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) { - h = hostserv; - hl = strlen(h); - } else { - p = hostserv; - pl = strlen(p); - } - } - - if (p != NULL && strchr(p, ':')) - goto spec_err; - - if (h != NULL && host != NULL) { - if (hl == 0 - || (hl == 1 && h[0] == '*')) { - *host = NULL; - } else { - *host = OPENSSL_strndup(h, hl); - if (*host == NULL) - goto memerr; - } - } - if (p != NULL && service != NULL) { - if (pl == 0 - || (pl == 1 && p[0] == '*')) { - *service = NULL; - } else { - *service = OPENSSL_strndup(p, pl); - if (*service == NULL) - goto memerr; - } - } - - return 1; - amb_err: - BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE); - return 0; - spec_err: - BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE); - return 0; - memerr: - BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE); - return 0; -} - -/* addrinfo_wrap is used to build our own addrinfo "chain". - * (it has only one entry, so calling it a chain may be a stretch) - * It should ONLY be called when getaddrinfo() and friends - * aren't available, OR when dealing with a non IP protocol - * family, such as AF_UNIX - * - * the return value is 1 on success, or 0 on failure, which - * only happens if a memory allocation error occurred. - */ -static int addrinfo_wrap(int family, int socktype, - const void *where, size_t wherelen, - unsigned short port, - BIO_ADDRINFO **bai) -{ - if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) { - BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE); - return 0; - } - - (*bai)->bai_family = family; - (*bai)->bai_socktype = socktype; - if (socktype == SOCK_STREAM) - (*bai)->bai_protocol = IPPROTO_TCP; - if (socktype == SOCK_DGRAM) - (*bai)->bai_protocol = IPPROTO_UDP; -#ifdef AF_UNIX - if (family == AF_UNIX) - (*bai)->bai_protocol = 0; -#endif - { - /* Magic: We know that BIO_ADDR_sockaddr_noconst is really - just an advanced cast of BIO_ADDR* to struct sockaddr * - by the power of union, so while it may seem that we're - creating a memory leak here, we are not. It will be - all right. */ - BIO_ADDR *addr = BIO_ADDR_new(); - if (addr != NULL) { - BIO_ADDR_rawmake(addr, family, where, wherelen, port); - (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr); - } - } - (*bai)->bai_next = NULL; - if ((*bai)->bai_addr == NULL) { - BIO_ADDRINFO_free(*bai); - *bai = NULL; - return 0; - } - return 1; -} - -DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init) -{ - if (!OPENSSL_init_crypto(0, NULL)) - return 0; - bio_lookup_lock = CRYPTO_THREAD_lock_new(); - return bio_lookup_lock != NULL; -} - -int BIO_lookup(const char *host, const char *service, - enum BIO_lookup_type lookup_type, - int family, int socktype, BIO_ADDRINFO **res) -{ - return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res); -} - -/*- - * BIO_lookup_ex - look up the node and service you want to connect to. - * @node: the node you want to connect to. - * @service: the service you want to connect to. - * @lookup_type: declare intent with the result, client or server. - * @family: the address family you want to use. Use AF_UNSPEC for any, or - * AF_INET, AF_INET6 or AF_UNIX. - * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM - * or 0 for all. - * @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all. - * Note that some platforms may not return IPPROTO_SCTP without - * explicitly requesting it (i.e. IPPROTO_SCTP may not be returned - * with 0 for the protocol) - * @res: Storage place for the resulting list of returned addresses - * - * This will do a lookup of the node and service that you want to connect to. - * It returns a linked list of different addresses you can try to connect to. - * - * When no longer needed you should call BIO_ADDRINFO_free() to free the result. - * - * The return value is 1 on success or 0 in case of error. - */ -int BIO_lookup_ex(const char *host, const char *service, int lookup_type, - int family, int socktype, int protocol, BIO_ADDRINFO **res) -{ - int ret = 0; /* Assume failure */ - - switch(family) { - case AF_INET: -#ifdef AF_INET6 - case AF_INET6: -#endif -#ifdef AF_UNIX - case AF_UNIX: -#endif -#ifdef AF_UNSPEC - case AF_UNSPEC: -#endif - break; - default: - BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY); - return 0; - } - -#ifdef AF_UNIX - if (family == AF_UNIX) { - if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res)) - return 1; - else - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); - return 0; - } -#endif - - if (BIO_sock_init() != 1) - return 0; - - if (1) { -#ifdef AI_PASSIVE - int gai_ret = 0, old_ret = 0; - struct addrinfo hints; - - memset(&hints, 0, sizeof(hints)); - - hints.ai_family = family; - hints.ai_socktype = socktype; - hints.ai_protocol = protocol; -# ifdef AI_ADDRCONFIG -# ifdef AF_UNSPEC - if (host != NULL && family == AF_UNSPEC) -# endif - hints.ai_flags |= AI_ADDRCONFIG; -# endif - - if (lookup_type == BIO_LOOKUP_SERVER) - hints.ai_flags |= AI_PASSIVE; - - /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to - * macro magic in bio_local.h - */ -# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST) - retry: -# endif - switch ((gai_ret = getaddrinfo(host, service, &hints, res))) { -# ifdef EAI_SYSTEM - case EAI_SYSTEM: - SYSerr(SYS_F_GETADDRINFO, get_last_socket_error()); - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB); - break; -# endif -# ifdef EAI_MEMORY - case EAI_MEMORY: - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); - break; -# endif - case 0: - ret = 1; /* Success */ - break; - default: -# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST) - if (hints.ai_flags & AI_ADDRCONFIG) { - hints.ai_flags &= ~AI_ADDRCONFIG; - hints.ai_flags |= AI_NUMERICHOST; - old_ret = gai_ret; - goto retry; - } -# endif - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB); - ERR_add_error_data(1, gai_strerror(old_ret ? old_ret : gai_ret)); - break; - } - } else { -#endif - const struct hostent *he; -/* - * Because struct hostent is defined for 32-bit pointers only with - * VMS C, we need to make sure that '&he_fallback_address' and - * '&he_fallback_addresses' are 32-bit pointers - */ -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma pointer_size save -# pragma pointer_size 32 -#endif - /* Windows doesn't seem to have in_addr_t */ -#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) - static uint32_t he_fallback_address; - static const char *he_fallback_addresses[] = - { (char *)&he_fallback_address, NULL }; -#else - static in_addr_t he_fallback_address; - static const char *he_fallback_addresses[] = - { (char *)&he_fallback_address, NULL }; -#endif - static const struct hostent he_fallback = - { NULL, NULL, AF_INET, sizeof(he_fallback_address), - (char **)&he_fallback_addresses }; -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma pointer_size restore -#endif - - struct servent *se; - /* Apparently, on WIN64, s_proto and s_port have traded places... */ -#ifdef _WIN64 - struct servent se_fallback = { NULL, NULL, NULL, 0 }; -#else - struct servent se_fallback = { NULL, NULL, 0, NULL }; -#endif - - if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) { - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); - ret = 0; - goto err; - } - - CRYPTO_THREAD_write_lock(bio_lookup_lock); - he_fallback_address = INADDR_ANY; - if (host == NULL) { - he = &he_fallback; - switch(lookup_type) { - case BIO_LOOKUP_CLIENT: - he_fallback_address = INADDR_LOOPBACK; - break; - case BIO_LOOKUP_SERVER: - he_fallback_address = INADDR_ANY; - break; - default: - /* We forgot to handle a lookup type! */ - assert("We forgot to handle a lookup type!" == NULL); - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_INTERNAL_ERROR); - ret = 0; - goto err; - } - } else { - he = gethostbyname(host); - - if (he == NULL) { -#ifndef OPENSSL_SYS_WINDOWS - /* - * This might be misleading, because h_errno is used as if - * it was errno. To minimize mixup add 1000. Underlying - * reason for this is that hstrerror is declared obsolete, - * not to mention that a) h_errno is not always guaranteed - * to be meaningless; b) hstrerror can reside in yet another - * library, linking for sake of hstrerror is an overkill; - * c) this path is not executed on contemporary systems - * anyway [above getaddrinfo/gai_strerror is]. We just let - * system administrator figure this out... - */ -# if defined(OPENSSL_SYS_VXWORKS) - /* h_errno doesn't exist on VxWorks */ - SYSerr(SYS_F_GETHOSTBYNAME, 1000 ); -# else - SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno); -# endif -#else - SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError()); -#endif - ret = 0; - goto err; - } - } - - if (service == NULL) { - se_fallback.s_port = 0; - se_fallback.s_proto = NULL; - se = &se_fallback; - } else { - char *endp = NULL; - long portnum = strtol(service, &endp, 10); - -/* - * Because struct servent is defined for 32-bit pointers only with - * VMS C, we need to make sure that 'proto' is a 32-bit pointer. - */ -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma pointer_size save -# pragma pointer_size 32 -#endif - char *proto = NULL; -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma pointer_size restore -#endif - - switch (socktype) { - case SOCK_STREAM: - proto = "tcp"; - break; - case SOCK_DGRAM: - proto = "udp"; - break; - } - - if (endp != service && *endp == '\0' - && portnum > 0 && portnum < 65536) { - se_fallback.s_port = htons((unsigned short)portnum); - se_fallback.s_proto = proto; - se = &se_fallback; - } else if (endp == service) { - se = getservbyname(service, proto); - - if (se == NULL) { -#ifndef OPENSSL_SYS_WINDOWS - SYSerr(SYS_F_GETSERVBYNAME, errno); -#else - SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError()); -#endif - goto err; - } - } else { - BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE); - goto err; - } - } - - *res = NULL; - - { -/* - * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C, - * we must make sure our iterator designates the same element type, hence - * the pointer size dance. - */ -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma pointer_size save -# pragma pointer_size 32 -#endif - char **addrlistp; -#if defined(OPENSSL_SYS_VMS) && defined(__DECC) -# pragma pointer_size restore -#endif - size_t addresses; - BIO_ADDRINFO *tmp_bai = NULL; - - /* The easiest way to create a linked list from an - array is to start from the back */ - for(addrlistp = he->h_addr_list; *addrlistp != NULL; - addrlistp++) - ; - - for(addresses = addrlistp - he->h_addr_list; - addrlistp--, addresses-- > 0; ) { - if (!addrinfo_wrap(he->h_addrtype, socktype, - *addrlistp, he->h_length, - se->s_port, &tmp_bai)) - goto addrinfo_malloc_err; - tmp_bai->bai_next = *res; - *res = tmp_bai; - continue; - addrinfo_malloc_err: - BIO_ADDRINFO_free(*res); - *res = NULL; - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); - ret = 0; - goto err; - } - - ret = 1; - } - err: - CRYPTO_THREAD_unlock(bio_lookup_lock); - } - - return ret; -} - -#endif /* OPENSSL_NO_SOCK */ diff --git a/crypto/bio/b_dump.c b/crypto/bio/b_dump.c deleted file mode 100644 --- a/crypto/bio/b_dump.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Stolen from tjh's ssl/ssl_trc.c stuff. - */ - -#include -#include "bio_local.h" - -#define DUMP_WIDTH 16 -#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4)) - -#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) -{ - 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) -{ - int ret = 0; - char buf[288 + 1]; - int i, j, rows, n; - unsigned char ch; - int dump_width; - - if (indent < 0) - indent = 0; - else if (indent > 64) - indent = 64; - - dump_width = DUMP_WIDTH_LESS_INDENT(indent); - rows = len / dump_width; - if ((rows * dump_width) < len) - rows++; - for (i = 0; i < rows; i++) { - n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "", - i * dump_width); - for (j = 0; j < dump_width; j++) { - if (SPACE(buf, n, 3)) { - if (((i * dump_width) + j) >= len) { - strcpy(buf + n, " "); - } else { - ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; - BIO_snprintf(buf + n, 4, "%02x%c", ch, - j == 7 ? '-' : ' '); - } - n += 3; - } - } - if (SPACE(buf, n, 2)) { - strcpy(buf + n, " "); - n += 2; - } - for (j = 0; j < dump_width; j++) { - if (((i * dump_width) + j) >= len) - break; - if (SPACE(buf, n, 1)) { - ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; -#ifndef CHARSET_EBCDIC - buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.'; -#else - buf[n++] = ((ch >= os_toascii[' ']) && (ch <= os_toascii['~'])) - ? os_toebcdic[ch] - : '.'; -#endif - buf[n] = '\0'; - } - } - if (SPACE(buf, n, 1)) { - buf[n++] = '\n'; - buf[n] = '\0'; - } - /* - * if this is the last call then update the ddt_dump thing so that we - * will move the selection point in the debug window - */ - ret += cb((void *)buf, n, u); - } - return ret; -} - -#ifndef OPENSSL_NO_STDIO -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) -{ - return BIO_dump_cb(write_fp, fp, s, len); -} - -int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent) -{ - return BIO_dump_indent_cb(write_fp, fp, s, len, indent); -} -#endif - -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) -{ - return BIO_dump_cb(write_bio, bp, s, len); -} - -int BIO_dump_indent(BIO *bp, const char *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 datalen) -{ - int i, j = 0; - - if (datalen < 1) - return 1; - - for (i = 0; i < datalen - 1; i++) { - if (i && !j) - BIO_printf(out, "%*s", indent, ""); - - BIO_printf(out, "%02X:", data[i]); - - j = (j + 1) % width; - if (!j) - BIO_printf(out, "\n"); - } - - if (i && !j) - BIO_printf(out, "%*s", indent, ""); - BIO_printf(out, "%02X", data[datalen - 1]); - return 1; -} diff --git a/crypto/bio/b_print.c b/crypto/bio/b_print.c deleted file mode 100644 --- a/crypto/bio/b_print.c +++ /dev/null @@ -1,954 +0,0 @@ -/* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include "internal/cryptlib.h" -#include "crypto/ctype.h" -#include "internal/numbers.h" -#include -#include - -/* - * Copyright Patrick Powell 1995 - * This code is based on code written by Patrick Powell - * It may be used for any purpose as long as this notice remains intact - * on all source code distributions. - */ - -#ifdef HAVE_LONG_DOUBLE -# define LDOUBLE long double -#else -# define LDOUBLE double -#endif - -static int fmtstr(char **, char **, size_t *, size_t *, - const char *, int, int, int); -static int fmtint(char **, char **, size_t *, size_t *, - int64_t, int, int, int, int); -#ifndef OPENSSL_SYS_UEFI -static int fmtfp(char **, char **, size_t *, size_t *, - LDOUBLE, int, int, int, int); -#endif -static int doapr_outch(char **, char **, size_t *, size_t *, int); -static int _dopr(char **sbuffer, char **buffer, - size_t *maxlen, size_t *retlen, int *truncated, - const char *format, va_list args); - -/* format read states */ -#define DP_S_DEFAULT 0 -#define DP_S_FLAGS 1 -#define DP_S_MIN 2 -#define DP_S_DOT 3 -#define DP_S_MAX 4 -#define DP_S_MOD 5 -#define DP_S_CONV 6 -#define DP_S_DONE 7 - -/* format flags - Bits */ -/* left-aligned padding */ -#define DP_F_MINUS (1 << 0) -/* print an explicit '+' for a value with positive sign */ -#define DP_F_PLUS (1 << 1) -/* print an explicit ' ' for a value with positive sign */ -#define DP_F_SPACE (1 << 2) -/* print 0/0x prefix for octal/hex and decimal point for floating point */ -#define DP_F_NUM (1 << 3) -/* print leading zeroes */ -#define DP_F_ZERO (1 << 4) -/* print HEX in UPPPERcase */ -#define DP_F_UP (1 << 5) -/* treat value as unsigned */ -#define DP_F_UNSIGNED (1 << 6) - -/* conversion flags */ -#define DP_C_SHORT 1 -#define DP_C_LONG 2 -#define DP_C_LDOUBLE 3 -#define DP_C_LLONG 4 -#define DP_C_SIZE 5 - -/* Floating point formats */ -#define F_FORMAT 0 -#define E_FORMAT 1 -#define G_FORMAT 2 - -/* some handy macros */ -#define char_to_int(p) (p - '0') -#define OSSL_MAX(p,q) ((p >= q) ? p : q) - -static int -_dopr(char **sbuffer, - char **buffer, - size_t *maxlen, - size_t *retlen, int *truncated, const char *format, va_list args) -{ - char ch; - int64_t value; -#ifndef OPENSSL_SYS_UEFI - LDOUBLE fvalue; -#endif - char *strvalue; - int min; - int max; - int state; - int flags; - int cflags; - size_t currlen; - - state = DP_S_DEFAULT; - flags = currlen = cflags = min = 0; - max = -1; - ch = *format++; - - while (state != DP_S_DONE) { - if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) - state = DP_S_DONE; - - switch (state) { - case DP_S_DEFAULT: - if (ch == '%') - state = DP_S_FLAGS; - else - if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) - return 0; - ch = *format++; - break; - case DP_S_FLAGS: - switch (ch) { - case '-': - flags |= DP_F_MINUS; - ch = *format++; - break; - case '+': - flags |= DP_F_PLUS; - ch = *format++; - break; - case ' ': - flags |= DP_F_SPACE; - ch = *format++; - break; - case '#': - flags |= DP_F_NUM; - ch = *format++; - break; - case '0': - flags |= DP_F_ZERO; - ch = *format++; - break; - default: - state = DP_S_MIN; - break; - } - break; - case DP_S_MIN: - if (ossl_isdigit(ch)) { - min = 10 * min + char_to_int(ch); - ch = *format++; - } else if (ch == '*') { - min = va_arg(args, int); - ch = *format++; - state = DP_S_DOT; - } else - state = DP_S_DOT; - break; - case DP_S_DOT: - if (ch == '.') { - state = DP_S_MAX; - ch = *format++; - } else - state = DP_S_MOD; - break; - case DP_S_MAX: - if (ossl_isdigit(ch)) { - if (max < 0) - max = 0; - max = 10 * max + char_to_int(ch); - ch = *format++; - } else if (ch == '*') { - max = va_arg(args, int); - ch = *format++; - state = DP_S_MOD; - } else - state = DP_S_MOD; - break; - case DP_S_MOD: - switch (ch) { - case 'h': - cflags = DP_C_SHORT; - ch = *format++; - break; - case 'l': - if (*format == 'l') { - cflags = DP_C_LLONG; - format++; - } else - cflags = DP_C_LONG; - ch = *format++; - break; - case 'q': - case 'j': - cflags = DP_C_LLONG; - ch = *format++; - break; - case 'L': - cflags = DP_C_LDOUBLE; - ch = *format++; - break; - case 'z': - cflags = DP_C_SIZE; - ch = *format++; - break; - default: - break; - } - state = DP_S_CONV; - break; - case DP_S_CONV: - switch (ch) { - case 'd': - case 'i': - switch (cflags) { - case DP_C_SHORT: - value = (short int)va_arg(args, int); - break; - case DP_C_LONG: - value = va_arg(args, long int); - break; - case DP_C_LLONG: - value = va_arg(args, int64_t); - break; - case DP_C_SIZE: - value = va_arg(args, ossl_ssize_t); - break; - default: - value = va_arg(args, int); - break; - } - if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, - max, flags)) - return 0; - break; - case 'X': - flags |= DP_F_UP; - /* FALLTHROUGH */ - case 'x': - case 'o': - case 'u': - flags |= DP_F_UNSIGNED; - switch (cflags) { - case DP_C_SHORT: - value = (unsigned short int)va_arg(args, unsigned int); - break; - case DP_C_LONG: - value = va_arg(args, unsigned long int); - break; - case DP_C_LLONG: - value = va_arg(args, uint64_t); - break; - case DP_C_SIZE: - value = va_arg(args, size_t); - break; - default: - value = va_arg(args, unsigned int); - break; - } - if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, - ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), - min, max, flags)) - return 0; - break; -#ifndef OPENSSL_SYS_UEFI - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, LDOUBLE); - else - fvalue = va_arg(args, double); - if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, - flags, F_FORMAT)) - return 0; - break; - case 'E': - flags |= DP_F_UP; - /* fall thru */ - case 'e': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, LDOUBLE); - else - fvalue = va_arg(args, double); - if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, - flags, E_FORMAT)) - return 0; - break; - case 'G': - flags |= DP_F_UP; - /* fall thru */ - case 'g': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, LDOUBLE); - else - fvalue = va_arg(args, double); - if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, - flags, G_FORMAT)) - return 0; - break; -#else - case 'f': - case 'E': - case 'e': - case 'G': - case 'g': - /* not implemented for UEFI */ - ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED); - return 0; -#endif - case 'c': - if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, - va_arg(args, int))) - return 0; - break; - case 's': - strvalue = va_arg(args, char *); - if (max < 0) { - if (buffer) - max = INT_MAX; - else - max = *maxlen; - } - if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, - flags, min, max)) - return 0; - break; - case 'p': - value = (size_t)va_arg(args, void *); - if (!fmtint(sbuffer, buffer, &currlen, maxlen, - value, 16, min, max, flags | DP_F_NUM)) - return 0; - break; - case 'n': - { - int *num; - num = va_arg(args, int *); - *num = currlen; - } - break; - case '%': - if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) - return 0; - break; - case 'w': - /* not supported yet, treat as next char */ - ch = *format++; - break; - default: - /* unknown, skip */ - break; - } - ch = *format++; - state = DP_S_DEFAULT; - flags = cflags = min = 0; - max = -1; - break; - case DP_S_DONE: - break; - default: - break; - } - } - /* - * We have to truncate if there is no dynamic buffer and we have filled the - * static buffer. - */ - if (buffer == NULL) { - *truncated = (currlen > *maxlen - 1); - if (*truncated) - currlen = *maxlen - 1; - } - if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) - return 0; - *retlen = currlen - 1; - return 1; -} - -static int -fmtstr(char **sbuffer, - char **buffer, - size_t *currlen, - size_t *maxlen, const char *value, int flags, int min, int max) -{ - int padlen; - size_t strln; - int cnt = 0; - - if (value == 0) - value = ""; - - strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max); - - padlen = min - strln; - if (min < 0 || padlen < 0) - padlen = 0; - if (max >= 0) { - /* - * Calculate the maximum output including padding. - * Make sure max doesn't overflow into negativity - */ - if (max < INT_MAX - padlen) - max += padlen; - else - max = INT_MAX; - } - if (flags & DP_F_MINUS) - padlen = -padlen; - - while ((padlen > 0) && (max < 0 || cnt < max)) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) - return 0; - --padlen; - ++cnt; - } - while (strln > 0 && (max < 0 || cnt < max)) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) - return 0; - --strln; - ++cnt; - } - while ((padlen < 0) && (max < 0 || cnt < max)) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) - return 0; - ++padlen; - ++cnt; - } - return 1; -} - -static int -fmtint(char **sbuffer, - char **buffer, - size_t *currlen, - size_t *maxlen, int64_t value, int base, int min, int max, int flags) -{ - int signvalue = 0; - const char *prefix = ""; - uint64_t uvalue; - char convert[DECIMAL_SIZE(value) + 3]; - int place = 0; - int spadlen = 0; - int zpadlen = 0; - int caps = 0; - - if (max < 0) - max = 0; - uvalue = value; - if (!(flags & DP_F_UNSIGNED)) { - if (value < 0) { - signvalue = '-'; - uvalue = 0 - (uint64_t)value; - } else if (flags & DP_F_PLUS) - signvalue = '+'; - else if (flags & DP_F_SPACE) - signvalue = ' '; - } - if (flags & DP_F_NUM) { - if (base == 8) - prefix = "0"; - if (base == 16) - prefix = "0x"; - } - if (flags & DP_F_UP) - caps = 1; - do { - convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") - [uvalue % (unsigned)base]; - uvalue = (uvalue / (unsigned)base); - } while (uvalue && (place < (int)sizeof(convert))); - if (place == sizeof(convert)) - place--; - convert[place] = 0; - - zpadlen = max - place; - spadlen = - min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); - if (zpadlen < 0) - zpadlen = 0; - if (spadlen < 0) - spadlen = 0; - if (flags & DP_F_ZERO) { - zpadlen = OSSL_MAX(zpadlen, spadlen); - spadlen = 0; - } - if (flags & DP_F_MINUS) - spadlen = -spadlen; - - /* spaces */ - while (spadlen > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) - return 0; - --spadlen; - } - - /* sign */ - if (signvalue) - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) - return 0; - - /* prefix */ - while (*prefix) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) - return 0; - prefix++; - } - - /* zeros */ - if (zpadlen > 0) { - while (zpadlen > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) - return 0; - --zpadlen; - } - } - /* digits */ - while (place > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) - return 0; - } - - /* left justified spaces */ - while (spadlen < 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) - return 0; - ++spadlen; - } - return 1; -} - -#ifndef OPENSSL_SYS_UEFI - -static LDOUBLE abs_val(LDOUBLE value) -{ - LDOUBLE result = value; - if (value < 0) - result = -value; - return result; -} - -static LDOUBLE pow_10(int in_exp) -{ - LDOUBLE result = 1; - while (in_exp) { - result *= 10; - in_exp--; - } - return result; -} - -static long roundv(LDOUBLE value) -{ - long intpart; - intpart = (long)value; - value = value - intpart; - if (value >= 0.5) - intpart++; - return intpart; -} - -static int -fmtfp(char **sbuffer, - char **buffer, - size_t *currlen, - size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style) -{ - int signvalue = 0; - LDOUBLE ufvalue; - LDOUBLE tmpvalue; - char iconvert[20]; - char fconvert[20]; - char econvert[20]; - int iplace = 0; - int fplace = 0; - int eplace = 0; - int padlen = 0; - int zpadlen = 0; - long exp = 0; - unsigned long intpart; - unsigned long fracpart; - unsigned long max10; - int realstyle; - - if (max < 0) - max = 6; - - if (fvalue < 0) - signvalue = '-'; - else if (flags & DP_F_PLUS) - signvalue = '+'; - else if (flags & DP_F_SPACE) - signvalue = ' '; - - /* - * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT - * depending on the number to be printed. Work out which one it is and use - * that from here on. - */ - if (style == G_FORMAT) { - if (fvalue == 0.0) { - realstyle = F_FORMAT; - } else if (fvalue < 0.0001) { - realstyle = E_FORMAT; - } else if ((max == 0 && fvalue >= 10) - || (max > 0 && fvalue >= pow_10(max))) { - realstyle = E_FORMAT; - } else { - realstyle = F_FORMAT; - } - } else { - realstyle = style; - } - - if (style != F_FORMAT) { - tmpvalue = fvalue; - /* Calculate the exponent */ - if (fvalue != 0.0) { - while (tmpvalue < 1) { - tmpvalue *= 10; - exp--; - } - while (tmpvalue > 10) { - tmpvalue /= 10; - exp++; - } - } - if (style == G_FORMAT) { - /* - * In G_FORMAT the "precision" represents significant digits. We - * always have at least 1 significant digit. - */ - if (max == 0) - max = 1; - /* Now convert significant digits to decimal places */ - if (realstyle == F_FORMAT) { - max -= (exp + 1); - if (max < 0) { - /* - * Should not happen. If we're in F_FORMAT then exp < max? - */ - return 0; - } - } else { - /* - * In E_FORMAT there is always one significant digit in front - * of the decimal point, so: - * significant digits == 1 + decimal places - */ - max--; - } - } - if (realstyle == E_FORMAT) - fvalue = tmpvalue; - } - ufvalue = abs_val(fvalue); - /* - * By subtracting 65535 (2^16-1) we cancel the low order 15 bits - * of ULONG_MAX to avoid using imprecise floating point values. - */ - if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) { - /* Number too big */ - return 0; - } - intpart = (unsigned long)ufvalue; - - /* - * sorry, we only support 9 digits past the decimal because of our - * conversion method - */ - if (max > 9) - max = 9; - - /* - * we "cheat" by converting the fractional part to integer by multiplying - * by a factor of 10 - */ - max10 = roundv(pow_10(max)); - fracpart = roundv(pow_10(max) * (ufvalue - intpart)); - - if (fracpart >= max10) { - intpart++; - fracpart -= max10; - } - - /* convert integer part */ - do { - iconvert[iplace++] = "0123456789"[intpart % 10]; - intpart = (intpart / 10); - } while (intpart && (iplace < (int)sizeof(iconvert))); - if (iplace == sizeof(iconvert)) - iplace--; - iconvert[iplace] = 0; - - /* convert fractional part */ - while (fplace < max) { - if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) { - /* We strip trailing zeros in G_FORMAT */ - max--; - fracpart = fracpart / 10; - if (fplace < max) - continue; - break; - } - fconvert[fplace++] = "0123456789"[fracpart % 10]; - fracpart = (fracpart / 10); - } - - if (fplace == sizeof(fconvert)) - fplace--; - fconvert[fplace] = 0; - - /* convert exponent part */ - if (realstyle == E_FORMAT) { - int tmpexp; - if (exp < 0) - tmpexp = -exp; - else - tmpexp = exp; - - do { - econvert[eplace++] = "0123456789"[tmpexp % 10]; - tmpexp = (tmpexp / 10); - } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); - /* Exponent is huge!! Too big to print */ - if (tmpexp > 0) - return 0; - /* Add a leading 0 for single digit exponents */ - if (eplace == 1) - econvert[eplace++] = '0'; - } - - /* - * -1 for decimal point (if we have one, i.e. max > 0), - * another -1 if we are printing a sign - */ - padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0); - /* Take some off for exponent prefix "+e" and exponent */ - if (realstyle == E_FORMAT) - padlen -= 2 + eplace; - zpadlen = max - fplace; - if (zpadlen < 0) - zpadlen = 0; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; - - if ((flags & DP_F_ZERO) && (padlen > 0)) { - if (signvalue) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) - return 0; - --padlen; - signvalue = 0; - } - while (padlen > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) - return 0; - --padlen; - } - } - while (padlen > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) - return 0; - --padlen; - } - if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) - return 0; - - while (iplace > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) - return 0; - } - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - if (max > 0 || (flags & DP_F_NUM)) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) - return 0; - - while (fplace > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, - fconvert[--fplace])) - return 0; - } - } - while (zpadlen > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) - return 0; - --zpadlen; - } - if (realstyle == E_FORMAT) { - char ech; - - if ((flags & DP_F_UP) == 0) - ech = 'e'; - else - ech = 'E'; - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech)) - return 0; - if (exp < 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-')) - return 0; - } else { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+')) - return 0; - } - while (eplace > 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, - econvert[--eplace])) - return 0; - } - } - - while (padlen < 0) { - if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) - return 0; - ++padlen; - } - return 1; -} - -#endif /* OPENSSL_SYS_UEFI */ - -#define BUFFER_INC 1024 - -static int -doapr_outch(char **sbuffer, - char **buffer, size_t *currlen, size_t *maxlen, int c) -{ - /* If we haven't at least one buffer, someone has done a big booboo */ - if (!ossl_assert(*sbuffer != NULL || buffer != NULL)) - return 0; - - /* |currlen| must always be <= |*maxlen| */ - if (!ossl_assert(*currlen <= *maxlen)) - return 0; - - if (buffer && *currlen == *maxlen) { - if (*maxlen > INT_MAX - BUFFER_INC) - return 0; - - *maxlen += BUFFER_INC; - if (*buffer == NULL) { - if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { - BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE); - return 0; - } - if (*currlen > 0) { - if (!ossl_assert(*sbuffer != NULL)) - return 0; - memcpy(*buffer, *sbuffer, *currlen); - } - *sbuffer = NULL; - } else { - char *tmpbuf; - tmpbuf = OPENSSL_realloc(*buffer, *maxlen); - if (tmpbuf == NULL) - return 0; - *buffer = tmpbuf; - } - } - - if (*currlen < *maxlen) { - if (*sbuffer) - (*sbuffer)[(*currlen)++] = (char)c; - else - (*buffer)[(*currlen)++] = (char)c; - } - - return 1; -} - -/***************************************************************************/ - -int BIO_printf(BIO *bio, const char *format, ...) -{ - va_list args; - int ret; - - va_start(args, format); - - ret = BIO_vprintf(bio, format, args); - - va_end(args); - return ret; -} - -int BIO_vprintf(BIO *bio, const char *format, va_list args) -{ - int ret; - size_t retlen; - char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable - * in small-stack environments, like threads - * or DOS programs. */ - char *hugebufp = hugebuf; - size_t hugebufsize = sizeof(hugebuf); - char *dynbuf = NULL; - int ignored; - - dynbuf = NULL; - if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, - args)) { - OPENSSL_free(dynbuf); - return -1; - } - if (dynbuf) { - ret = BIO_write(bio, dynbuf, (int)retlen); - OPENSSL_free(dynbuf); - } else { - ret = BIO_write(bio, hugebuf, (int)retlen); - } - return ret; -} - -/* - * As snprintf is not available everywhere, we provide our own - * implementation. This function has nothing to do with BIOs, but it's - * closely related to BIO_printf, and we need *some* name prefix ... (XXX the - * function should be renamed, but to what?) - */ -int BIO_snprintf(char *buf, size_t n, const char *format, ...) -{ - va_list args; - int ret; - - va_start(args, format); - - ret = BIO_vsnprintf(buf, n, format, args); - - va_end(args); - return ret; -} - -int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) -{ - size_t retlen; - int truncated; - - if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) - return -1; - - if (truncated) - /* - * In case of truncation, return -1 like traditional snprintf. - * (Current drafts for ISO/IEC 9899 say snprintf should return the - * number of characters that would have been written, had the buffer - * been large enough.) - */ - return -1; - else - return (retlen <= INT_MAX) ? (int)retlen : -1; -} diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c deleted file mode 100644 --- a/crypto/bio/b_sock.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include "bio_local.h" -#ifndef OPENSSL_NO_SOCK -# define SOCKET_PROTOCOL IPPROTO_TCP -# ifdef SO_MAXCONN -# define MAX_LISTEN SO_MAXCONN -# elif defined(SOMAXCONN) -# define MAX_LISTEN SOMAXCONN -# else -# define MAX_LISTEN 32 -# endif -# if defined(OPENSSL_SYS_WINDOWS) -static int wsa_init_done = 0; -# endif - -# if OPENSSL_API_COMPAT < 0x10100000L -int BIO_get_host_ip(const char *str, unsigned char *ip) -{ - BIO_ADDRINFO *res = NULL; - int ret = 0; - - if (BIO_sock_init() != 1) - return 0; /* don't generate another error code here */ - - if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { - size_t l; - - if (BIO_ADDRINFO_family(res) != AF_INET) { - BIOerr(BIO_F_BIO_GET_HOST_IP, - BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); - } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { - /* - * Because only AF_INET addresses will reach this far, we can assert - * that l should be 4 - */ - if (ossl_assert(l == 4)) - ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); - } - BIO_ADDRINFO_free(res); - } else { - ERR_add_error_data(2, "host=", str); - } - - return ret; -} - -int BIO_get_port(const char *str, unsigned short *port_ptr) -{ - BIO_ADDRINFO *res = NULL; - int ret = 0; - - if (str == NULL) { - BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); - return 0; - } - - if (BIO_sock_init() != 1) - return 0; /* don't generate another error code here */ - - if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { - if (BIO_ADDRINFO_family(res) != AF_INET) { - BIOerr(BIO_F_BIO_GET_PORT, - BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); - } else { - *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); - ret = 1; - } - BIO_ADDRINFO_free(res); - } else { - ERR_add_error_data(2, "host=", str); - } - - return ret; -} -# endif - -int BIO_sock_error(int sock) -{ - int j = 0, i; - socklen_t size = sizeof(j); - - /* - * Note: under Windows the third parameter is of type (char *) whereas - * under other systems it is (void *) if you don't have a cast it will - * choke the compiler: if you do have a cast then you can either go for - * (char *) or (void *). - */ - i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); - if (i < 0) - return get_last_socket_error(); - else - return j; -} - -# if OPENSSL_API_COMPAT < 0x10100000L -struct hostent *BIO_gethostbyname(const char *name) -{ - /* - * Caching gethostbyname() results forever is wrong, so we have to let - * the true gethostbyname() worry about this - */ - return gethostbyname(name); -} -# endif - -int BIO_sock_init(void) -{ -# ifdef OPENSSL_SYS_WINDOWS - static struct WSAData wsa_state; - - if (!wsa_init_done) { - int err; - - wsa_init_done = 1; - memset(&wsa_state, 0, sizeof(wsa_state)); - /* - * Not making wsa_state available to the rest of the code is formally - * wrong. But the structures we use are [believed to be] invariable - * among Winsock DLLs, while API availability is [expected to be] - * probed at run-time with DSO_global_lookup. - */ - if (WSAStartup(0x0202, &wsa_state) != 0) { - err = WSAGetLastError(); - SYSerr(SYS_F_WSASTARTUP, err); - BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); - return -1; - } - } -# endif /* OPENSSL_SYS_WINDOWS */ -# ifdef WATT32 - extern int _watt_do_exit; - _watt_do_exit = 0; /* don't make sock_init() call exit() */ - if (sock_init()) - return -1; -# endif - - return 1; -} - -void bio_sock_cleanup_int(void) -{ -# ifdef OPENSSL_SYS_WINDOWS - if (wsa_init_done) { - wsa_init_done = 0; - WSACleanup(); - } -# endif -} - -int BIO_socket_ioctl(int fd, long type, void *arg) -{ - int i; - -# ifdef __DJGPP__ - i = ioctlsocket(fd, type, (char *)arg); -# else -# if defined(OPENSSL_SYS_VMS) - /*- - * 2011-02-18 SMS. - * VMS ioctl() can't tolerate a 64-bit "void *arg", but we - * observe that all the consumers pass in an "unsigned long *", - * so we arrange a local copy with a short pointer, and use - * that, instead. - */ -# if __INITIAL_POINTER_SIZE == 64 -# define ARG arg_32p -# pragma pointer_size save -# pragma pointer_size 32 - unsigned long arg_32; - unsigned long *arg_32p; -# pragma pointer_size restore - arg_32p = &arg_32; - arg_32 = *((unsigned long *)arg); -# else /* __INITIAL_POINTER_SIZE == 64 */ -# define ARG arg -# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ -# else /* defined(OPENSSL_SYS_VMS) */ -# define ARG arg -# endif /* defined(OPENSSL_SYS_VMS) [else] */ - - i = ioctlsocket(fd, type, ARG); -# endif /* __DJGPP__ */ - if (i < 0) - SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); - return i; -} - -# if OPENSSL_API_COMPAT < 0x10100000L -int BIO_get_accept_socket(char *host, int bind_mode) -{ - int s = INVALID_SOCKET; - char *h = NULL, *p = NULL; - BIO_ADDRINFO *res = NULL; - - if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV)) - return INVALID_SOCKET; - - if (BIO_sock_init() != 1) - return INVALID_SOCKET; - - if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) - goto err; - - if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res), - BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) { - s = INVALID_SOCKET; - goto err; - } - - if (!BIO_listen(s, BIO_ADDRINFO_address(res), - bind_mode ? BIO_SOCK_REUSEADDR : 0)) { - BIO_closesocket(s); - s = INVALID_SOCKET; - } - - err: - BIO_ADDRINFO_free(res); - OPENSSL_free(h); - OPENSSL_free(p); - - return s; -} - -int BIO_accept(int sock, char **ip_port) -{ - BIO_ADDR res; - int ret = -1; - - ret = BIO_accept_ex(sock, &res, 0); - if (ret == (int)INVALID_SOCKET) { - if (BIO_sock_should_retry(ret)) { - ret = -2; - goto end; - } - SYSerr(SYS_F_ACCEPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); - goto end; - } - - if (ip_port != NULL) { - char *host = BIO_ADDR_hostname_string(&res, 1); - char *port = BIO_ADDR_service_string(&res, 1); - if (host != NULL && port != NULL) - *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); - else - *ip_port = NULL; - - if (*ip_port == NULL) { - BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); - BIO_closesocket(ret); - ret = (int)INVALID_SOCKET; - } else { - strcpy(*ip_port, host); - strcat(*ip_port, ":"); - strcat(*ip_port, port); - } - OPENSSL_free(host); - OPENSSL_free(port); - } - - end: - return ret; -} -# endif - -int BIO_set_tcp_ndelay(int s, int on) -{ - int ret = 0; -# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) - int opt; - -# ifdef SOL_TCP - opt = SOL_TCP; -# else -# ifdef IPPROTO_TCP - opt = IPPROTO_TCP; -# endif -# endif - - ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); -# endif - return (ret == 0); -} - -int BIO_socket_nbio(int s, int mode) -{ - int ret = -1; - int l; - - l = mode; -# ifdef FIONBIO - l = mode; - - ret = BIO_socket_ioctl(s, FIONBIO, &l); -# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY)) - /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ - - l = fcntl(s, F_GETFL, 0); - if (l == -1) { - SYSerr(SYS_F_FCNTL, get_last_sys_error()); - ret = -1; - } else { -# if defined(O_NONBLOCK) - l &= ~O_NONBLOCK; -# else - l &= ~FNDELAY; /* BSD4.x */ -# endif - if (mode) { -# if defined(O_NONBLOCK) - l |= O_NONBLOCK; -# else - l |= FNDELAY; /* BSD4.x */ -# endif - } - ret = fcntl(s, F_SETFL, l); - - if (ret < 0) { - SYSerr(SYS_F_FCNTL, get_last_sys_error()); - } - } -# else - /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ - BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT); -# endif - - return (ret == 0); -} - -int BIO_sock_info(int sock, - enum BIO_sock_info_type type, union BIO_sock_info_u *info) -{ - switch (type) { - case BIO_SOCK_INFO_ADDRESS: - { - socklen_t addr_len; - int ret = 0; - addr_len = sizeof(*info->addr); - ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), - &addr_len); - if (ret == -1) { - SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error()); - BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR); - return 0; - } - if ((size_t)addr_len > sizeof(*info->addr)) { - BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); - return 0; - } - } - break; - default: - BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE); - return 0; - } - return 1; -} - -#endif diff --git a/crypto/bio/b_sock2.c b/crypto/bio/b_sock2.c deleted file mode 100644 --- a/crypto/bio/b_sock2.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include - -#include "bio_local.h" - -#include - -#ifndef OPENSSL_NO_SOCK -# ifdef SO_MAXCONN -# define MAX_LISTEN SO_MAXCONN -# elif defined(SOMAXCONN) -# define MAX_LISTEN SOMAXCONN -# else -# define MAX_LISTEN 32 -# endif - -/*- - * BIO_socket - create a socket - * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...) - * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM) - * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP) - * @options: BIO socket options (currently unused) - * - * Creates a socket. This should be called before calling any - * of BIO_connect and BIO_listen. - * - * Returns the file descriptor on success or INVALID_SOCKET on failure. On - * failure errno is set, and a status is added to the OpenSSL error stack. - */ -int BIO_socket(int domain, int socktype, int protocol, int options) -{ - int sock = -1; - - if (BIO_sock_init() != 1) - return INVALID_SOCKET; - - sock = socket(domain, socktype, protocol); - if (sock == -1) { - SYSerr(SYS_F_SOCKET, get_last_socket_error()); - BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); - return INVALID_SOCKET; - } - - return sock; -} - -/*- - * BIO_connect - connect to an address - * @sock: the socket to connect with - * @addr: the address to connect to - * @options: BIO socket options - * - * Connects to the address using the given socket and options. - * - * Options can be a combination of the following: - * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. - * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. - * - BIO_SOCK_NODELAY: don't delay small messages. - * - * options holds BIO socket options that can be used - * You should call this for every address returned by BIO_lookup - * until the connection is successful. - * - * Returns 1 on success or 0 on failure. On failure errno is set - * and an error status is added to the OpenSSL error stack. - */ -int BIO_connect(int sock, const BIO_ADDR *addr, int options) -{ - const int on = 1; - - if (sock == -1) { - BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET); - return 0; - } - - if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0)) - return 0; - - if (options & BIO_SOCK_KEEPALIVE) { - if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, - (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE); - return 0; - } - } - - if (options & BIO_SOCK_NODELAY) { - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY); - return 0; - } - } - - if (connect(sock, BIO_ADDR_sockaddr(addr), - BIO_ADDR_sockaddr_size(addr)) == -1) { - if (!BIO_sock_should_retry(-1)) { - SYSerr(SYS_F_CONNECT, get_last_socket_error()); - BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR); - } - return 0; - } - return 1; -} - -/*- - * BIO_bind - bind socket to address - * @sock: the socket to set - * @addr: local address to bind to - * @options: BIO socket options - * - * Binds to the address using the given socket and options. - * - * Options can be a combination of the following: - * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination - * for a recently closed port. - * - * When restarting the program it could be that the port is still in use. If - * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway. - * It's recommended that you use this. - */ -int BIO_bind(int sock, const BIO_ADDR *addr, int options) -{ -# ifndef OPENSSL_SYS_WINDOWS - int on = 1; -# endif - - if (sock == -1) { - BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET); - return 0; - } - -# ifndef OPENSSL_SYS_WINDOWS - /* - * SO_REUSEADDR has different behavior on Windows than on - * other operating systems, don't set it there. - */ - if (options & BIO_SOCK_REUSEADDR) { - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_REUSEADDR); - return 0; - } - } -# endif - - if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) { - SYSerr(SYS_F_BIND, get_last_socket_error()); - BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET); - return 0; - } - - return 1; -} - -/*- - * BIO_listen - Creates a listen socket - * @sock: the socket to listen with - * @addr: local address to bind to - * @options: BIO socket options - * - * Binds to the address using the given socket and options, then - * starts listening for incoming connections. - * - * Options can be a combination of the following: - * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. - * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. - * - BIO_SOCK_NODELAY: don't delay small messages. - * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination - * for a recently closed port. - * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only - * for IPv6 addresses and not IPv4 addresses mapped to IPv6. - * - * It's recommended that you set up both an IPv6 and IPv4 listen socket, and - * then check both for new clients that connect to it. You want to set up - * the socket as non-blocking in that case since else it could hang. - * - * Not all operating systems support IPv4 addresses on an IPv6 socket, and for - * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to - * create the IPv6 sockets to only listen for IPv6 connection. - * - * It could be that the first BIO_listen() call will listen to all the IPv6 - * and IPv4 addresses and that then trying to bind to the IPv4 address will - * fail. We can't tell the difference between already listening ourself to - * it and someone else listening to it when failing and errno is EADDRINUSE, so - * it's recommended to not give an error in that case if the first call was - * successful. - * - * When restarting the program it could be that the port is still in use. If - * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway. - * It's recommended that you use this. - */ -int BIO_listen(int sock, const BIO_ADDR *addr, int options) -{ - int on = 1; - int socktype; - socklen_t socktype_len = sizeof(socktype); - - if (sock == -1) { - BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET); - return 0; - } - - if (getsockopt(sock, SOL_SOCKET, SO_TYPE, - (void *)&socktype, &socktype_len) != 0 - || socktype_len != sizeof(socktype)) { - SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE); - return 0; - } - - if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0)) - return 0; - - if (options & BIO_SOCK_KEEPALIVE) { - if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, - (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE); - return 0; - } - } - - if (options & BIO_SOCK_NODELAY) { - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY); - return 0; - } - } - - /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */ -# if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) - if (BIO_ADDR_family(addr) == AF_INET6) { - /* - * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF. - * Therefore we always have to use setsockopt here. - */ - on = options & BIO_SOCK_V6_ONLY ? 1 : 0; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, - (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY); - return 0; - } - } -# endif - - if (!BIO_bind(sock, addr, options)) - return 0; - - if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) { - SYSerr(SYS_F_LISTEN, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET); - return 0; - } - - return 1; -} - -/*- - * BIO_accept_ex - Accept new incoming connections - * @sock: the listening socket - * @addr: the BIO_ADDR to store the peer address in - * @options: BIO socket options, applied on the accepted socket. - * - */ -int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options) -{ - socklen_t len; - int accepted_sock; - BIO_ADDR locaddr; - BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_; - - len = sizeof(*addr); - accepted_sock = accept(accept_sock, - BIO_ADDR_sockaddr_noconst(addr), &len); - if (accepted_sock == -1) { - if (!BIO_sock_should_retry(accepted_sock)) { - SYSerr(SYS_F_ACCEPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR); - } - return INVALID_SOCKET; - } - - if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) { - closesocket(accepted_sock); - return INVALID_SOCKET; - } - - return accepted_sock; -} - -/*- - * BIO_closesocket - Close a socket - * @sock: the socket to close - */ -int BIO_closesocket(int sock) -{ - if (closesocket(sock) < 0) - return 0; - return 1; -} -#endif diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c --- a/crypto/bio/bf_buff.c +++ b/crypto/bio/bf_buff.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -25,10 +25,8 @@ static const BIO_METHOD methods_buffer = { BIO_TYPE_BUFFER, "buffer", - /* TODO: Convert to new style write function */ bwrite_conv, buffer_write, - /* TODO: Convert to new style read function */ bread_conv, buffer_read, buffer_puts, @@ -289,7 +287,9 @@ break; case BIO_C_SET_BUFF_READ_DATA: if (num > ctx->ibuf_size) { - p1 = OPENSSL_malloc((int)num); + if (num <= 0) + return 0; + p1 = OPENSSL_malloc((size_t)num); if (p1 == NULL) goto malloc_error; OPENSSL_free(ctx->ibuf); @@ -318,12 +318,14 @@ p1 = ctx->ibuf; p2 = ctx->obuf; if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) { - p1 = OPENSSL_malloc((int)num); + if (num <= 0) + return 0; + p1 = OPENSSL_malloc((size_t)num); if (p1 == NULL) goto malloc_error; } if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { - p2 = OPENSSL_malloc((int)num); + p2 = OPENSSL_malloc((size_t)num); if (p2 == NULL) { if (p1 != ctx->ibuf) OPENSSL_free(p1); @@ -381,8 +383,8 @@ break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; - if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) || - !BIO_set_write_buffer_size(dbio, ctx->obuf_size)) + if (BIO_set_read_buffer_size(dbio, ctx->ibuf_size) <= 0 || + BIO_set_write_buffer_size(dbio, ctx->obuf_size) <= 0) ret = 0; break; case BIO_CTRL_PEEK: @@ -404,22 +406,15 @@ } return ret; malloc_error: - BIOerr(BIO_F_BUFFER_CTRL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } static long buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int buffer_gets(BIO *b, char *buf, int size) diff --git a/crypto/bio/bf_lbuf.c b/crypto/bio/bf_lbuf.c --- a/crypto/bio/bf_lbuf.c +++ b/crypto/bio/bf_lbuf.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -30,10 +30,8 @@ static const BIO_METHOD methods_linebuffer = { BIO_TYPE_LINEBUFFER, "linebuffer", - /* TODO: Convert to new style write function */ bwrite_conv, linebuffer_write, - /* TODO: Convert to new style read function */ bread_conv, linebuffer_read, linebuffer_puts, @@ -60,12 +58,12 @@ BIO_LINEBUFFER_CTX *ctx; if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { - BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE); if (ctx->obuf == NULL) { - BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); OPENSSL_free(ctx); return 0; } @@ -232,10 +230,12 @@ } break; case BIO_C_SET_BUFF_SIZE: + if (num > INT_MAX) + return 0; obs = (int)num; p = ctx->obuf; if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) { - p = OPENSSL_malloc((int)num); + p = OPENSSL_malloc((size_t)obs); if (p == NULL) goto malloc_error; } @@ -284,7 +284,7 @@ break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; - if (!BIO_set_write_buffer_size(dbio, ctx->obuf_size)) + if (BIO_set_write_buffer_size(dbio, ctx->obuf_size) <= 0) ret = 0; break; default: @@ -295,22 +295,15 @@ } return ret; malloc_error: - BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } static long linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int linebuffer_gets(BIO *b, char *buf, int size) diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c --- a/crypto/bio/bf_nbio.c +++ b/crypto/bio/bf_nbio.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -34,10 +34,8 @@ static const BIO_METHOD methods_nbiof = { BIO_TYPE_NBIO_TEST, "non-blocking IO test filter", - /* TODO: Convert to new style write function */ bwrite_conv, nbiof_write, - /* TODO: Convert to new style read function */ bread_conv, nbiof_read, nbiof_puts, @@ -58,7 +56,7 @@ NBIO_TEST *nt; if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) { - BIOerr(BIO_F_NBIOF_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } nt->lrn = -1; @@ -173,16 +171,9 @@ static long nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int nbiof_gets(BIO *bp, char *buf, int size) diff --git a/crypto/bio/bf_null.c b/crypto/bio/bf_null.c --- a/crypto/bio/bf_null.c +++ b/crypto/bio/bf_null.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -25,10 +25,8 @@ static const BIO_METHOD methods_nullf = { BIO_TYPE_NULL_FILTER, "NULL filter", - /* TODO: Convert to new style write function */ bwrite_conv, nullf_write, - /* TODO: Convert to new style read function */ bread_conv, nullf_read, nullf_puts, @@ -95,16 +93,9 @@ static long nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int nullf_gets(BIO *bp, char *buf, int size) diff --git a/crypto/bio/bf_prefix.c b/crypto/bio/bf_prefix.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bf_prefix.c @@ -0,0 +1,207 @@ +/* + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "bio_local.h" + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten); +static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); +static int prefix_puts(BIO *b, const char *str); +static int prefix_gets(BIO *b, char *str, int size); +static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); +static int prefix_create(BIO *b); +static int prefix_destroy(BIO *b); +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD prefix_meth = { + BIO_TYPE_BUFFER, + "prefix", + prefix_write, + NULL, + prefix_read, + NULL, + prefix_puts, + prefix_gets, + prefix_ctrl, + prefix_create, + prefix_destroy, + prefix_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_prefix(void) +{ + return &prefix_meth; +} + +typedef struct prefix_ctx_st { + char *prefix; /* Text prefix, given by user */ + unsigned int indent; /* Indentation amount, given by user */ + + int linestart; /* flag to indicate we're at the line start */ +} PREFIX_CTX; + +static int prefix_create(BIO *b) +{ + PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + + ctx->prefix = NULL; + ctx->indent = 0; + ctx->linestart = 1; + BIO_set_data(b, ctx); + BIO_set_init(b, 1); + return 1; +} + +static int prefix_destroy(BIO *b) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + OPENSSL_free(ctx->prefix); + OPENSSL_free(ctx); + return 1; +} + +static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) +{ + return BIO_read_ex(BIO_next(b), in, size, numread); +} + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + return 0; + + /* + * If no prefix is set or if it's empty, and no indentation amount is set, + * we've got nothing to do here + */ + if ((ctx->prefix == NULL || *ctx->prefix == '\0') + && ctx->indent == 0) { + /* + * We do note if what comes next will be a new line, though, so we're + * prepared to handle prefix and indentation the next time around. + */ + if (outl > 0) + ctx->linestart = (out[outl-1] == '\n'); + return BIO_write_ex(BIO_next(b), out, outl, numwritten); + } + + *numwritten = 0; + + while (outl > 0) { + size_t i; + char c; + + /* + * If we know that we're at the start of the line, output prefix and + * indentation. + */ + if (ctx->linestart) { + size_t dontcare; + + if (ctx->prefix != NULL + && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), + &dontcare)) + return 0; + BIO_printf(BIO_next(b), "%*s", ctx->indent, ""); + ctx->linestart = 0; + } + + /* Now, go look for the next LF, or the end of the string */ + for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) + continue; + if (c == '\n') + i++; + + /* Output what we found so far */ + while (i > 0) { + size_t num = 0; + + if (!BIO_write_ex(BIO_next(b), out, i, &num)) + return 0; + out += num; + outl -= num; + *numwritten += num; + i -= num; + } + + /* If we found a LF, what follows is a new line, so take note */ + if (c == '\n') + ctx->linestart = 1; + } + + return 1; +} + +static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 0; + PREFIX_CTX *ctx; + + if (b == NULL || (ctx = BIO_get_data(b)) == NULL) + return -1; + + switch (cmd) { + case BIO_CTRL_SET_PREFIX: + OPENSSL_free(ctx->prefix); + if (ptr == NULL) { + ctx->prefix = NULL; + ret = 1; + } else { + ctx->prefix = OPENSSL_strdup((const char *)ptr); + ret = ctx->prefix != NULL; + } + break; + case BIO_CTRL_SET_INDENT: + if (num >= 0) { + ctx->indent = (unsigned int)num; + ret = 1; + } + break; + case BIO_CTRL_GET_INDENT: + ret = (long)ctx->indent; + break; + default: + /* Commands that we intercept before passing them along */ + switch (cmd) { + case BIO_C_FILE_SEEK: + case BIO_CTRL_RESET: + ctx->linestart = 1; + break; + } + if (BIO_next(b) != NULL) + ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); + break; + } + return ret; +} + +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + return BIO_callback_ctrl(BIO_next(b), cmd, fp); +} + +static int prefix_gets(BIO *b, char *buf, int size) +{ + return BIO_gets(BIO_next(b), buf, size); +} + +static int prefix_puts(BIO *b, const char *str) +{ + return BIO_write(b, str, strlen(str)); +} diff --git a/crypto/bio/bf_readbuff.c b/crypto/bio/bf_readbuff.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bf_readbuff.c @@ -0,0 +1,288 @@ +/* + * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This is a read only BIO filter that can be used to add BIO_tell() and + * BIO_seek() support to source/sink BIO's (such as a file BIO that uses stdin). + * It does this by caching ALL data read from the BIO source/sink into a + * resizable memory buffer. + */ + +#include +#include +#include "bio_local.h" +#include "internal/cryptlib.h" + +#define DEFAULT_BUFFER_SIZE 4096 + +static int readbuffer_write(BIO *h, const char *buf, int num); +static int readbuffer_read(BIO *h, char *buf, int size); +static int readbuffer_puts(BIO *h, const char *str); +static int readbuffer_gets(BIO *h, char *str, int size); +static long readbuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int readbuffer_new(BIO *h); +static int readbuffer_free(BIO *data); +static long readbuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD methods_readbuffer = { + BIO_TYPE_BUFFER, + "readbuffer", + bwrite_conv, + readbuffer_write, + bread_conv, + readbuffer_read, + readbuffer_puts, + readbuffer_gets, + readbuffer_ctrl, + readbuffer_new, + readbuffer_free, + readbuffer_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_readbuffer(void) +{ + return &methods_readbuffer; +} + +static int readbuffer_new(BIO *bi) +{ + BIO_F_BUFFER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + ctx->ibuf_size = DEFAULT_BUFFER_SIZE; + ctx->ibuf = OPENSSL_zalloc(DEFAULT_BUFFER_SIZE); + if (ctx->ibuf == NULL) { + OPENSSL_free(ctx); + return 0; + } + + bi->init = 1; + bi->ptr = (char *)ctx; + bi->flags = 0; + return 1; +} + +static int readbuffer_free(BIO *a) +{ + BIO_F_BUFFER_CTX *b; + + if (a == NULL) + return 0; + b = (BIO_F_BUFFER_CTX *)a->ptr; + OPENSSL_free(b->ibuf); + OPENSSL_free(a->ptr); + a->ptr = NULL; + a->init = 0; + a->flags = 0; + return 1; +} + +static int readbuffer_resize(BIO_F_BUFFER_CTX *ctx, int sz) +{ + char *tmp; + + /* Figure out how many blocks are required */ + sz += (ctx->ibuf_off + DEFAULT_BUFFER_SIZE - 1); + sz = DEFAULT_BUFFER_SIZE * (sz / DEFAULT_BUFFER_SIZE); + + /* Resize if the buffer is not big enough */ + if (sz > ctx->ibuf_size) { + tmp = OPENSSL_realloc(ctx->ibuf, sz); + if (tmp == NULL) + return 0; + ctx->ibuf = tmp; + ctx->ibuf_size = sz; + } + return 1; +} + +static int readbuffer_read(BIO *b, char *out, int outl) +{ + int i, num = 0; + BIO_F_BUFFER_CTX *ctx; + + if (out == NULL || outl == 0) + return 0; + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + if ((ctx == NULL) || (b->next_bio == NULL)) + return 0; + BIO_clear_retry_flags(b); + + for (;;) { + i = ctx->ibuf_len; + /* If there is something in the buffer just read it. */ + if (i != 0) { + if (i > outl) + i = outl; + memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i); + ctx->ibuf_off += i; + ctx->ibuf_len -= i; + num += i; + /* Exit if we have read the bytes required out of the buffer */ + if (outl == i) + return num; + outl -= i; + out += i; + } + + /* Only gets here if the buffer has been consumed */ + if (!readbuffer_resize(ctx, outl)) + return 0; + + /* Do some buffering by reading from the next bio */ + i = BIO_read(b->next_bio, ctx->ibuf + ctx->ibuf_off, outl); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) + return ((num > 0) ? num : i); + else + return num; /* i == 0 */ + } + ctx->ibuf_len = i; + } +} + +static int readbuffer_write(BIO *b, const char *in, int inl) +{ + return 0; +} +static int readbuffer_puts(BIO *b, const char *str) +{ + return 0; +} + +static long readbuffer_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO_F_BUFFER_CTX *ctx; + long ret = 1, sz; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_EOF: + if (ctx->ibuf_len > 0) + return 0; + if (b->next_bio == NULL) + return 1; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_C_FILE_SEEK: + case BIO_CTRL_RESET: + sz = ctx->ibuf_off + ctx->ibuf_len; + /* Assume it can only seek backwards */ + if (num < 0 || num > sz) + return 0; + ctx->ibuf_off = num; + ctx->ibuf_len = sz - num; + break; + + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = (long)ctx->ibuf_off; + break; + case BIO_CTRL_PENDING: + ret = (long)ctx->ibuf_len; + if (ret == 0) { + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +static long readbuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + if (b->next_bio == NULL) + return 0; + return BIO_callback_ctrl(b->next_bio, cmd, fp); +} + +static int readbuffer_gets(BIO *b, char *buf, int size) +{ + BIO_F_BUFFER_CTX *ctx; + int num = 0, num_chars, found_newline; + char *p; + int i, j; + + if (size == 0) + return 0; + --size; /* the passed in size includes the terminator - so remove it here */ + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + BIO_clear_retry_flags(b); + + /* If data is already buffered then use this first */ + if (ctx->ibuf_len > 0) { + p = ctx->ibuf + ctx->ibuf_off; + found_newline = 0; + for (num_chars = 0; + (num_chars < ctx->ibuf_len) && (num_chars < size); + num_chars++) { + *buf++ = p[num_chars]; + if (p[num_chars] == '\n') { + found_newline = 1; + num_chars++; + break; + } + } + num += num_chars; + size -= num_chars; + ctx->ibuf_len -= num_chars; + ctx->ibuf_off += num_chars; + if (found_newline || size == 0) { + *buf = '\0'; + return num; + } + } + /* + * If there is no buffered data left then read any remaining data from the + * next bio. + */ + + /* Resize if we have to */ + if (!readbuffer_resize(ctx, 1 + size)) + return 0; + /* + * Read more data from the next bio using BIO_read_ex: + * Note we cannot use BIO_gets() here as it does not work on a + * binary stream that contains 0x00. (Since strlen() will stop at + * any 0x00 not at the last read '\n' in a FILE bio). + * Also note that some applications open and close the file bio + * multiple times and need to read the next available block when using + * stdin - so we need to READ one byte at a time! + */ + p = ctx->ibuf + ctx->ibuf_off; + for (i = 0; i < size; ++i) { + j = BIO_read(b->next_bio, p, 1); + if (j <= 0) { + BIO_copy_next_retry(b); + *buf = '\0'; + return num > 0 ? num : j; + } + *buf++ = *p; + num++; + ctx->ibuf_off++; + if (*p == '\n') + break; + ++p; + } + *buf = '\0'; + return num; +} diff --git a/crypto/bio/bio_addr.c b/crypto/bio/bio_addr.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bio_addr.c @@ -0,0 +1,939 @@ +/* + * Copyright 2016-2022 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +/* + * VC configurations may define UNICODE, to indicate to the C RTL that + * WCHAR functions are preferred. + * This affects functions like gai_strerror(), which is implemented as + * an alias macro for gai_strerrorA() (which returns a const char *) or + * gai_strerrorW() (which returns a const WCHAR *). This source file + * assumes POSIX declarations, so prefer the non-UNICODE definitions. + */ +#undef UNICODE + +#include +#include + +#include "bio_local.h" +#include + +#ifndef OPENSSL_NO_SOCK +#include +#include +#include "internal/thread_once.h" + +CRYPTO_RWLOCK *bio_lookup_lock; +static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT; + +/* + * Throughout this file and bio_local.h, the existence of the macro + * AI_PASSIVE is used to detect the availability of struct addrinfo, + * getnameinfo() and getaddrinfo(). If that macro doesn't exist, + * we use our own implementation instead, using gethostbyname, + * getservbyname and a few other. + */ + +/********************************************************************** + * + * Address structure + * + */ + +BIO_ADDR *BIO_ADDR_new(void) +{ + BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->sa.sa_family = AF_UNSPEC; + return ret; +} + +void BIO_ADDR_free(BIO_ADDR *ap) +{ + OPENSSL_free(ap); +} + +void BIO_ADDR_clear(BIO_ADDR *ap) +{ + memset(ap, 0, sizeof(*ap)); + ap->sa.sa_family = AF_UNSPEC; +} + +/* + * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents + * of a struct sockaddr. + */ +int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in)); + return 1; + } +#ifdef AF_INET6 + if (sa->sa_family == AF_INET6) { + memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6)); + return 1; + } +#endif +#ifdef AF_UNIX + if (sa->sa_family == AF_UNIX) { + memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un)); + return 1; + } +#endif + + return 0; +} + +int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, + const void *where, size_t wherelen, + unsigned short port) +{ +#ifdef AF_UNIX + if (family == AF_UNIX) { + if (wherelen + 1 > sizeof(ap->s_un.sun_path)) + return 0; + memset(&ap->s_un, 0, sizeof(ap->s_un)); + ap->s_un.sun_family = family; + strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1); + return 1; + } +#endif + if (family == AF_INET) { + if (wherelen != sizeof(struct in_addr)) + return 0; + memset(&ap->s_in, 0, sizeof(ap->s_in)); + ap->s_in.sin_family = family; + ap->s_in.sin_port = port; + ap->s_in.sin_addr = *(struct in_addr *)where; + return 1; + } +#ifdef AF_INET6 + if (family == AF_INET6) { + if (wherelen != sizeof(struct in6_addr)) + return 0; + memset(&ap->s_in6, 0, sizeof(ap->s_in6)); + ap->s_in6.sin6_family = family; + ap->s_in6.sin6_port = port; + ap->s_in6.sin6_addr = *(struct in6_addr *)where; + return 1; + } +#endif + + return 0; +} + +int BIO_ADDR_family(const BIO_ADDR *ap) +{ + return ap->sa.sa_family; +} + +int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l) +{ + size_t len = 0; + const void *addrptr = NULL; + + if (ap->sa.sa_family == AF_INET) { + len = sizeof(ap->s_in.sin_addr); + addrptr = &ap->s_in.sin_addr; + } +#ifdef AF_INET6 + else if (ap->sa.sa_family == AF_INET6) { + len = sizeof(ap->s_in6.sin6_addr); + addrptr = &ap->s_in6.sin6_addr; + } +#endif +#ifdef AF_UNIX + else if (ap->sa.sa_family == AF_UNIX) { + len = strlen(ap->s_un.sun_path); + addrptr = &ap->s_un.sun_path; + } +#endif + + if (addrptr == NULL) + return 0; + + if (p != NULL) { + memcpy(p, addrptr, len); + } + if (l != NULL) + *l = len; + + return 1; +} + +unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap) +{ + if (ap->sa.sa_family == AF_INET) + return ap->s_in.sin_port; +#ifdef AF_INET6 + if (ap->sa.sa_family == AF_INET6) + return ap->s_in6.sin6_port; +#endif + return 0; +} + +/*- + * addr_strings - helper function to get host and service names + * @ap: the BIO_ADDR that has the input info + * @numeric: 0 if actual names should be returned, 1 if the numeric + * representation should be returned. + * @hostname: a pointer to a pointer to a memory area to store the + * host name or numeric representation. Unused if NULL. + * @service: a pointer to a pointer to a memory area to store the + * service name or numeric representation. Unused if NULL. + * + * The return value is 0 on failure, with the error code in the error + * stack, and 1 on success. + */ +static int addr_strings(const BIO_ADDR *ap, int numeric, + char **hostname, char **service) +{ + if (BIO_sock_init() != 1) + return 0; + + if (1) { +#ifdef AI_PASSIVE + int ret = 0; + char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = ""; + int flags = 0; + + if (numeric) + flags |= NI_NUMERICHOST | NI_NUMERICSERV; + + if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap), + BIO_ADDR_sockaddr_size(ap), + host, sizeof(host), serv, sizeof(serv), + flags)) != 0) { +# ifdef EAI_SYSTEM + if (ret == EAI_SYSTEM) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getnameinfo()"); + } else +# endif + { + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, gai_strerror(ret)); + } + return 0; + } + + /* VMS getnameinfo() has a bug, it doesn't fill in serv, which + * leaves it with whatever garbage that happens to be there. + * However, we initialise serv with the empty string (serv[0] + * is therefore NUL), so it gets real easy to detect when things + * didn't go the way one might expect. + */ + if (serv[0] == '\0') { + BIO_snprintf(serv, sizeof(serv), "%d", + ntohs(BIO_ADDR_rawport(ap))); + } + + if (hostname != NULL) + *hostname = OPENSSL_strdup(host); + if (service != NULL) + *service = OPENSSL_strdup(serv); + } else { +#endif + if (hostname != NULL) + *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr)); + if (service != NULL) { + char serv[6]; /* port is 16 bits => max 5 decimal digits */ + BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port)); + *service = OPENSSL_strdup(serv); + } + } + + if ((hostname != NULL && *hostname == NULL) + || (service != NULL && *service == NULL)) { + if (hostname != NULL) { + OPENSSL_free(*hostname); + *hostname = NULL; + } + if (service != NULL) { + OPENSSL_free(*service); + *service = NULL; + } + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + + return 1; +} + +char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric) +{ + char *hostname = NULL; + + if (addr_strings(ap, numeric, &hostname, NULL)) + return hostname; + + return NULL; +} + +char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric) +{ + char *service = NULL; + + if (addr_strings(ap, numeric, NULL, &service)) + return service; + + return NULL; +} + +char *BIO_ADDR_path_string(const BIO_ADDR *ap) +{ +#ifdef AF_UNIX + if (ap->sa.sa_family == AF_UNIX) + return OPENSSL_strdup(ap->s_un.sun_path); +#endif + return NULL; +} + +/* + * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr + * for a given BIO_ADDR. In reality, this is simply a type safe cast. + * The returned struct sockaddr is const, so it can't be tampered with. + */ +const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap) +{ + return &(ap->sa); +} + +/* + * BIO_ADDR_sockaddr_noconst - non-public function that does the same + * as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as + * it allows you to tamper with the data (and thereby the contents + * of the input BIO_ADDR). + */ +struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap) +{ + return &(ap->sa); +} + +/* + * BIO_ADDR_sockaddr_size - non-public function that returns the size + * of the struct sockaddr the BIO_ADDR is using. If the protocol family + * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX, + * the size of the BIO_ADDR type is returned. + */ +socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap) +{ + if (ap->sa.sa_family == AF_INET) + return sizeof(ap->s_in); +#ifdef AF_INET6 + if (ap->sa.sa_family == AF_INET6) + return sizeof(ap->s_in6); +#endif +#ifdef AF_UNIX + if (ap->sa.sa_family == AF_UNIX) + return sizeof(ap->s_un); +#endif + return sizeof(*ap); +} + +/********************************************************************** + * + * Address info database + * + */ + +const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_next; + return NULL; +} + +int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_family; + return 0; +} + +int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_socktype; + return 0; +} + +int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) { + if (bai->bai_protocol != 0) + return bai->bai_protocol; + +#ifdef AF_UNIX + if (bai->bai_family == AF_UNIX) + return 0; +#endif + + switch (bai->bai_socktype) { + case SOCK_STREAM: + return IPPROTO_TCP; + case SOCK_DGRAM: + return IPPROTO_UDP; + default: + break; + } + } + return 0; +} + +/* + * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size + * of the struct sockaddr inside the BIO_ADDRINFO. + */ +socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_addrlen; + return 0; +} + +/* + * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr + * as the struct sockaddr it is. + */ +const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return bai->bai_addr; + return NULL; +} + +const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai) +{ + if (bai != NULL) + return (BIO_ADDR *)bai->bai_addr; + return NULL; +} + +void BIO_ADDRINFO_free(BIO_ADDRINFO *bai) +{ + if (bai == NULL) + return; + +#ifdef AI_PASSIVE +# ifdef AF_UNIX +# define _cond bai->bai_family != AF_UNIX +# else +# define _cond 1 +# endif + if (_cond) { + freeaddrinfo(bai); + return; + } +#endif + + /* Free manually when we know that addrinfo_wrap() was used. + * See further comment above addrinfo_wrap() + */ + while (bai != NULL) { + BIO_ADDRINFO *next = bai->bai_next; + OPENSSL_free(bai->bai_addr); + OPENSSL_free(bai); + bai = next; + } +} + +/********************************************************************** + * + * Service functions + * + */ + +/*- + * The specs in hostserv can take these forms: + * + * host:service => *host = "host", *service = "service" + * host:* => *host = "host", *service = NULL + * host: => *host = "host", *service = NULL + * :service => *host = NULL, *service = "service" + * *:service => *host = NULL, *service = "service" + * + * in case no : is present in the string, the result depends on + * hostserv_prio, as follows: + * + * when hostserv_prio == BIO_PARSE_PRIO_HOST + * host => *host = "host", *service untouched + * + * when hostserv_prio == BIO_PARSE_PRIO_SERV + * service => *host untouched, *service = "service" + * + */ +int BIO_parse_hostserv(const char *hostserv, char **host, char **service, + enum BIO_hostserv_priorities hostserv_prio) +{ + const char *h = NULL; size_t hl = 0; + const char *p = NULL; size_t pl = 0; + + if (*hostserv == '[') { + if ((p = strchr(hostserv, ']')) == NULL) + goto spec_err; + h = hostserv + 1; + hl = p - h; + p++; + if (*p == '\0') + p = NULL; + else if (*p != ':') + goto spec_err; + else { + p++; + pl = strlen(p); + } + } else { + const char *p2 = strrchr(hostserv, ':'); + p = strchr(hostserv, ':'); + + /*- + * Check for more than one colon. There are three possible + * interpretations: + * 1. IPv6 address with port number, last colon being separator. + * 2. IPv6 address only. + * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST, + * IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV + * Because of this ambiguity, we currently choose to make it an + * error. + */ + if (p != p2) + goto amb_err; + + if (p != NULL) { + h = hostserv; + hl = p - h; + p++; + pl = strlen(p); + } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) { + h = hostserv; + hl = strlen(h); + } else { + p = hostserv; + pl = strlen(p); + } + } + + if (p != NULL && strchr(p, ':')) + goto spec_err; + + if (h != NULL && host != NULL) { + if (hl == 0 + || (hl == 1 && h[0] == '*')) { + *host = NULL; + } else { + *host = OPENSSL_strndup(h, hl); + if (*host == NULL) + goto memerr; + } + } + if (p != NULL && service != NULL) { + if (pl == 0 + || (pl == 1 && p[0] == '*')) { + *service = NULL; + } else { + *service = OPENSSL_strndup(p, pl); + if (*service == NULL) + goto memerr; + } + } + + return 1; + amb_err: + ERR_raise(ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE); + return 0; + spec_err: + ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE); + return 0; + memerr: + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; +} + +/* addrinfo_wrap is used to build our own addrinfo "chain". + * (it has only one entry, so calling it a chain may be a stretch) + * It should ONLY be called when getaddrinfo() and friends + * aren't available, OR when dealing with a non IP protocol + * family, such as AF_UNIX + * + * the return value is 1 on success, or 0 on failure, which + * only happens if a memory allocation error occurred. + */ +static int addrinfo_wrap(int family, int socktype, + const void *where, size_t wherelen, + unsigned short port, + BIO_ADDRINFO **bai) +{ + if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + + (*bai)->bai_family = family; + (*bai)->bai_socktype = socktype; + if (socktype == SOCK_STREAM) + (*bai)->bai_protocol = IPPROTO_TCP; + if (socktype == SOCK_DGRAM) + (*bai)->bai_protocol = IPPROTO_UDP; +#ifdef AF_UNIX + if (family == AF_UNIX) + (*bai)->bai_protocol = 0; +#endif + { + /* Magic: We know that BIO_ADDR_sockaddr_noconst is really + just an advanced cast of BIO_ADDR* to struct sockaddr * + by the power of union, so while it may seem that we're + creating a memory leak here, we are not. It will be + all right. */ + BIO_ADDR *addr = BIO_ADDR_new(); + if (addr != NULL) { + BIO_ADDR_rawmake(addr, family, where, wherelen, port); + (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr); + } + } + (*bai)->bai_next = NULL; + if ((*bai)->bai_addr == NULL) { + BIO_ADDRINFO_free(*bai); + *bai = NULL; + return 0; + } + return 1; +} + +DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init) +{ + bio_lookup_lock = CRYPTO_THREAD_lock_new(); + return bio_lookup_lock != NULL; +} + +int BIO_lookup(const char *host, const char *service, + enum BIO_lookup_type lookup_type, + int family, int socktype, BIO_ADDRINFO **res) +{ + return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res); +} + +/*- + * BIO_lookup_ex - look up the host and service you want to connect to. + * @host: the host (or node, in case family == AF_UNIX) you want to connect to. + * @service: the service you want to connect to. + * @lookup_type: declare intent with the result, client or server. + * @family: the address family you want to use. Use AF_UNSPEC for any, or + * AF_INET, AF_INET6 or AF_UNIX. + * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM + * or 0 for all. + * @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all. + * Note that some platforms may not return IPPROTO_SCTP without + * explicitly requesting it (i.e. IPPROTO_SCTP may not be returned + * with 0 for the protocol) + * @res: Storage place for the resulting list of returned addresses + * + * This will do a lookup of the host and service that you want to connect to. + * It returns a linked list of different addresses you can try to connect to. + * + * When no longer needed you should call BIO_ADDRINFO_free() to free the result. + * + * The return value is 1 on success or 0 in case of error. + */ +int BIO_lookup_ex(const char *host, const char *service, int lookup_type, + int family, int socktype, int protocol, BIO_ADDRINFO **res) +{ + int ret = 0; /* Assume failure */ + + switch(family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif +#ifdef AF_UNIX + case AF_UNIX: +#endif +#ifdef AF_UNSPEC + case AF_UNSPEC: +#endif + break; + default: + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY); + return 0; + } + +#ifdef AF_UNIX + if (family == AF_UNIX) { + if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res)) + return 1; + else + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } +#endif + + if (BIO_sock_init() != 1) + return 0; + + if (1) { +#ifdef AI_PASSIVE + int gai_ret = 0, old_ret = 0; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = family; + hints.ai_socktype = socktype; + hints.ai_protocol = protocol; +# ifdef AI_ADDRCONFIG +# ifdef AF_UNSPEC + if (host != NULL && family == AF_UNSPEC) +# endif + hints.ai_flags |= AI_ADDRCONFIG; +# endif + + if (lookup_type == BIO_LOOKUP_SERVER) + hints.ai_flags |= AI_PASSIVE; + + /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to + * macro magic in bio_local.h + */ +# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST) + retry: +# endif + switch ((gai_ret = getaddrinfo(host, service, &hints, res))) { +# ifdef EAI_SYSTEM + case EAI_SYSTEM: + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getaddrinfo()"); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); + break; +# endif +# ifdef EAI_MEMORY + case EAI_MEMORY: + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + break; +# endif + case 0: + ret = 1; /* Success */ + break; + default: +# if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST) + if (hints.ai_flags & AI_ADDRCONFIG) { + hints.ai_flags &= ~AI_ADDRCONFIG; + hints.ai_flags |= AI_NUMERICHOST; + old_ret = gai_ret; + goto retry; + } +# endif + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + gai_strerror(old_ret ? old_ret : gai_ret)); + break; + } + } else { +#endif + const struct hostent *he; +/* + * Because struct hostent is defined for 32-bit pointers only with + * VMS C, we need to make sure that '&he_fallback_address' and + * '&he_fallback_addresses' are 32-bit pointers + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size save +# pragma pointer_size 32 +#endif + /* Windows doesn't seem to have in_addr_t */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) + static uint32_t he_fallback_address; + static const char *he_fallback_addresses[] = + { (char *)&he_fallback_address, NULL }; +#else + static in_addr_t he_fallback_address; + static const char *he_fallback_addresses[] = + { (char *)&he_fallback_address, NULL }; +#endif + static const struct hostent he_fallback = + { NULL, NULL, AF_INET, sizeof(he_fallback_address), + (char **)&he_fallback_addresses }; +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size restore +#endif + + struct servent *se; + /* Apparently, on WIN64, s_proto and s_port have traded places... */ +#ifdef _WIN64 + struct servent se_fallback = { NULL, NULL, NULL, 0 }; +#else + struct servent se_fallback = { NULL, NULL, 0, NULL }; +#endif + + if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + ret = 0; + goto err; + } + + if (!CRYPTO_THREAD_write_lock(bio_lookup_lock)) { + ret = 0; + goto err; + } + he_fallback_address = INADDR_ANY; + if (host == NULL) { + he = &he_fallback; + switch(lookup_type) { + case BIO_LOOKUP_CLIENT: + he_fallback_address = INADDR_LOOPBACK; + break; + case BIO_LOOKUP_SERVER: + he_fallback_address = INADDR_ANY; + break; + default: + /* We forgot to handle a lookup type! */ + assert("We forgot to handle a lookup type!" == NULL); + ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR); + ret = 0; + goto err; + } + } else { + he = gethostbyname(host); + + if (he == NULL) { +#ifndef OPENSSL_SYS_WINDOWS + /* + * This might be misleading, because h_errno is used as if + * it was errno. To minimize mixup add 1000. Underlying + * reason for this is that hstrerror is declared obsolete, + * not to mention that a) h_errno is not always guaranteed + * to be meaningless; b) hstrerror can reside in yet another + * library, linking for sake of hstrerror is an overkill; + * c) this path is not executed on contemporary systems + * anyway [above getaddrinfo/gai_strerror is]. We just let + * system administrator figure this out... + */ +# if defined(OPENSSL_SYS_VXWORKS) + /* h_errno doesn't exist on VxWorks */ + ERR_raise_data(ERR_LIB_SYS, 1000, + "calling gethostbyname()"); +# else + ERR_raise_data(ERR_LIB_SYS, 1000 + h_errno, + "calling gethostbyname()"); +# endif +#else + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling gethostbyname()"); +#endif + ret = 0; + goto err; + } + } + + if (service == NULL) { + se_fallback.s_port = 0; + se_fallback.s_proto = NULL; + se = &se_fallback; + } else { + char *endp = NULL; + long portnum = strtol(service, &endp, 10); + +/* + * Because struct servent is defined for 32-bit pointers only with + * VMS C, we need to make sure that 'proto' is a 32-bit pointer. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size save +# pragma pointer_size 32 +#endif + char *proto = NULL; +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size restore +#endif + + switch (socktype) { + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + } + + if (endp != service && *endp == '\0' + && portnum > 0 && portnum < 65536) { + se_fallback.s_port = htons((unsigned short)portnum); + se_fallback.s_proto = proto; + se = &se_fallback; + } else if (endp == service) { + se = getservbyname(service, proto); + + if (se == NULL) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getservbyname()"); + goto err; + } + } else { + ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE); + goto err; + } + } + + *res = NULL; + + { +/* + * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C, + * we must make sure our iterator designates the same element type, hence + * the pointer size dance. + */ +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size save +# pragma pointer_size 32 +#endif + char **addrlistp; +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) +# pragma pointer_size restore +#endif + size_t addresses; + BIO_ADDRINFO *tmp_bai = NULL; + + /* The easiest way to create a linked list from an + array is to start from the back */ + for(addrlistp = he->h_addr_list; *addrlistp != NULL; + addrlistp++) + ; + + for(addresses = addrlistp - he->h_addr_list; + addrlistp--, addresses-- > 0; ) { + if (!addrinfo_wrap(he->h_addrtype, socktype, + *addrlistp, he->h_length, + se->s_port, &tmp_bai)) + goto addrinfo_malloc_err; + tmp_bai->bai_next = *res; + *res = tmp_bai; + continue; + addrinfo_malloc_err: + BIO_ADDRINFO_free(*res); + *res = NULL; + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + ret = 0; + goto err; + } + + ret = 1; + } + err: + CRYPTO_THREAD_unlock(bio_lookup_lock); + } + + return ret; +} + +#endif /* OPENSSL_NO_SOCK */ diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c --- a/crypto/bio/bio_cb.c +++ b/crypto/bio/bio_cb.c @@ -1,12 +1,14 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include @@ -14,25 +16,25 @@ #include "internal/cryptlib.h" #include -long BIO_debug_callback(BIO *bio, int cmd, const char *argp, - int argi, long argl, long ret) +long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, + int argi, long argl, int ret, size_t *processed) { BIO *b; char buf[256]; char *p; - long r = 1; - int len, left; + int left; + size_t l = 0; - if (BIO_CB_RETURN & cmd) - r = ret; + if (processed != NULL) + l = *processed; - len = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio); + left = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio); /* Ignore errors and continue printing the other information. */ - if (len < 0) - len = 0; - p = buf + len; - left = sizeof(buf) - len; + if (left < 0) + left = 0; + p = buf + left; + left = sizeof(buf) - left; switch (cmd) { case BIO_CB_FREE: @@ -40,47 +42,47 @@ break; case BIO_CB_READ: if (bio->method->type & BIO_TYPE_DESCRIPTOR) - BIO_snprintf(p, left, "read(%d,%lu) - %s fd=%d\n", - bio->num, (unsigned long)argi, + BIO_snprintf(p, left, "read(%d,%zu) - %s fd=%d\n", + bio->num, len, bio->method->name, bio->num); else - BIO_snprintf(p, left, "read(%d,%lu) - %s\n", - bio->num, (unsigned long)argi, bio->method->name); + BIO_snprintf(p, left, "read(%d,%zu) - %s\n", + bio->num, len, bio->method->name); break; case BIO_CB_WRITE: if (bio->method->type & BIO_TYPE_DESCRIPTOR) - BIO_snprintf(p, left, "write(%d,%lu) - %s fd=%d\n", - bio->num, (unsigned long)argi, + BIO_snprintf(p, left, "write(%d,%zu) - %s fd=%d\n", + bio->num, len, bio->method->name, bio->num); else - BIO_snprintf(p, left, "write(%d,%lu) - %s\n", - bio->num, (unsigned long)argi, bio->method->name); + BIO_snprintf(p, left, "write(%d,%zu) - %s\n", + bio->num, len, bio->method->name); break; case BIO_CB_PUTS: BIO_snprintf(p, left, "puts() - %s\n", bio->method->name); break; case BIO_CB_GETS: - BIO_snprintf(p, left, "gets(%lu) - %s\n", (unsigned long)argi, + BIO_snprintf(p, left, "gets(%zu) - %s\n", len, bio->method->name); break; case BIO_CB_CTRL: - BIO_snprintf(p, left, "ctrl(%lu) - %s\n", (unsigned long)argi, + BIO_snprintf(p, left, "ctrl(%d) - %s\n", argi, bio->method->name); break; case BIO_CB_RETURN | BIO_CB_READ: - BIO_snprintf(p, left, "read return %ld\n", ret); + BIO_snprintf(p, left, "read return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_WRITE: - BIO_snprintf(p, left, "write return %ld\n", ret); + BIO_snprintf(p, left, "write return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_GETS: - BIO_snprintf(p, left, "gets return %ld\n", ret); + BIO_snprintf(p, left, "gets return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_PUTS: - BIO_snprintf(p, left, "puts return %ld\n", ret); + BIO_snprintf(p, left, "puts return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_CTRL: - BIO_snprintf(p, left, "ctrl return %ld\n", ret); + BIO_snprintf(p, left, "ctrl return %d\n", ret); break; default: BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd); @@ -94,5 +96,19 @@ else fputs(buf, stderr); #endif - return r; + return ret; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret) +{ + size_t processed = 0; + + if (ret > 0) + processed = (size_t)ret; + BIO_debug_callback_ex(bio, cmd, argp, (size_t)argi, + argi, argl, ret > 0 ? 1 : (int)ret, &processed); + return ret; } +#endif diff --git a/crypto/bio/bio_dump.c b/crypto/bio/bio_dump.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bio_dump.c @@ -0,0 +1,153 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Stolen from tjh's ssl/ssl_trc.c stuff. + */ + +#include +#include "bio_local.h" + +#define DUMP_WIDTH 16 +#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4)) + +#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 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 void *v, int len, int indent) +{ + const unsigned char *s = v; + int res, ret = 0; + char buf[288 + 1]; + int i, j, rows, n; + unsigned char ch; + int dump_width; + + if (indent < 0) + indent = 0; + else if (indent > 64) + indent = 64; + + dump_width = DUMP_WIDTH_LESS_INDENT(indent); + rows = len / dump_width; + if ((rows * dump_width) < len) + rows++; + for (i = 0; i < rows; i++) { + n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "", + i * dump_width); + for (j = 0; j < dump_width; j++) { + if (SPACE(buf, n, 3)) { + if (((i * dump_width) + j) >= len) { + strcpy(buf + n, " "); + } else { + ch = *(s + i * dump_width + j) & 0xff; + BIO_snprintf(buf + n, 4, "%02x%c", ch, + j == 7 ? '-' : ' '); + } + n += 3; + } + } + if (SPACE(buf, n, 2)) { + strcpy(buf + n, " "); + n += 2; + } + for (j = 0; j < dump_width; j++) { + if (((i * dump_width) + j) >= len) + break; + if (SPACE(buf, n, 1)) { + ch = *(s + i * dump_width + j) & 0xff; +#ifndef CHARSET_EBCDIC + buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.'; +#else + buf[n++] = ((ch >= os_toascii[' ']) && (ch <= os_toascii['~'])) + ? os_toebcdic[ch] + : '.'; +#endif + buf[n] = '\0'; + } + } + if (SPACE(buf, n, 1)) { + buf[n++] = '\n'; + buf[n] = '\0'; + } + /* + * if this is the last call then update the ddt_dump thing so that we + * will move the selection point in the debug window + */ + res = cb((void *)buf, n, u); + if (res < 0) + return res; + ret += res; + } + return ret; +} + +#ifndef OPENSSL_NO_STDIO +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 void *s, int len) +{ + return BIO_dump_cb(write_fp, fp, s, len); +} + +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); +} +#endif + +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 void *s, int len) +{ + return BIO_dump_cb(write_bio, bp, s, len); +} + +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, const void *data, + int datalen) +{ + const unsigned char *d = data; + int i, j = 0; + + if (datalen < 1) + return 1; + + for (i = 0; i < datalen - 1; i++) { + if (i && !j) + BIO_printf(out, "%*s", indent, ""); + + BIO_printf(out, "%02X:", d[i]); + + j = (j + 1) % width; + if (!j) + BIO_printf(out, "\n"); + } + + if (i && !j) + BIO_printf(out, "%*s", indent, ""); + BIO_printf(out, "%02X", d[datalen - 1]); + return 1; +} diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c --- a/crypto/bio/bio_err.c +++ b/crypto/bio/bio_err.c @@ -1,8 +1,8 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,69 +10,10 @@ #include #include +#include "crypto/bioerr.h" #ifndef OPENSSL_NO_ERR -static const ERR_STRING_DATA BIO_str_functs[] = { - {ERR_PACK(ERR_LIB_BIO, BIO_F_ACPT_STATE, 0), "acpt_state"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDRINFO_WRAP, 0), "addrinfo_wrap"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDR_STRINGS, 0), "addr_strings"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT, 0), "BIO_accept"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_EX, 0), "BIO_accept_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_NEW, 0), "BIO_ACCEPT_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ADDR_NEW, 0), "BIO_ADDR_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_BIND, 0), "BIO_bind"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CALLBACK_CTRL, 0), "BIO_callback_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT, 0), "BIO_connect"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT_NEW, 0), "BIO_CONNECT_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CTRL, 0), "BIO_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GETS, 0), "BIO_gets"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_HOST_IP, 0), "BIO_get_host_ip"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_NEW_INDEX, 0), "BIO_get_new_index"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_PORT, 0), "BIO_get_port"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LISTEN, 0), "BIO_listen"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP, 0), "BIO_lookup"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP_EX, 0), "BIO_lookup_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_MAKE_PAIR, 0), "bio_make_pair"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_METH_NEW, 0), "BIO_meth_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW, 0), "BIO_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_DGRAM_SCTP, 0), "BIO_new_dgram_sctp"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_FILE, 0), "BIO_new_file"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_MEM_BUF, 0), "BIO_new_mem_buf"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD, 0), "BIO_nread"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD0, 0), "BIO_nread0"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE, 0), "BIO_nwrite"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE0, 0), "BIO_nwrite0"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PARSE_HOSTSERV, 0), "BIO_parse_hostserv"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PUTS, 0), "BIO_puts"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ, 0), "BIO_read"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_EX, 0), "BIO_read_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_INTERN, 0), "bio_read_intern"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET, 0), "BIO_socket"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET_NBIO, 0), "BIO_socket_nbio"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INFO, 0), "BIO_sock_info"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INIT, 0), "BIO_sock_init"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE, 0), "BIO_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_EX, 0), "BIO_write_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_INTERN, 0), "bio_write_intern"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BUFFER_CTRL, 0), "buffer_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_CTRL, 0), "conn_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_STATE, 0), "conn_state"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_NEW, 0), "dgram_sctp_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_READ, 0), "dgram_sctp_read"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_WRITE, 0), "dgram_sctp_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DOAPR_OUTCH, 0), "doapr_outch"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_CTRL, 0), "file_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_READ, 0), "file_read"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_CTRL, 0), "linebuffer_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_NEW, 0), "linebuffer_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_MEM_WRITE, 0), "mem_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_NBIOF_NEW, 0), "nbiof_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_SLG_WRITE, 0), "slg_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_SSL_NEW, 0), "SSL_new"}, - {0, NULL} -}; - static const ERR_STRING_DATA BIO_str_reasons[] = { {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ACCEPT_ERROR), "accept error"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET), @@ -82,6 +23,7 @@ {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "bad fopen mode"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "broken pipe"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "connect error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_TIMEOUT), "connect timeout"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET), "gethostbyname addr is not af inet"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_ERROR), "getsockname error"}, @@ -104,7 +46,8 @@ "no hostname or service specified"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_DEFINED), "no port defined"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "no such file"}, - {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "null parameter"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_ERROR), "transfer error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_TIMEOUT), "transfer timeout"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_BIND_SOCKET), "unable to bind socket"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET), @@ -133,13 +76,11 @@ #endif -int ERR_load_BIO_strings(void) +int ossl_err_load_BIO_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) { - ERR_load_strings_const(BIO_str_functs); + if (ERR_reason_error_string(BIO_str_reasons[0].error) == NULL) ERR_load_strings_const(BIO_str_reasons); - } #endif return 1; } diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -1,26 +1,32 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include +#include "internal/numbers.h" #include "bio_local.h" -#include "internal/cryptlib.h" - /* * Helper macro for the callback to determine whether an operator expects a * len parameter or not */ -#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \ - (o) == BIO_CB_GETS) +#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE \ + || (o) == BIO_CB_GETS) +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# define HAS_CALLBACK(b) ((b)->callback != NULL || (b)->callback_ex != NULL) +#else +# define HAS_CALLBACK(b) ((b)->callback_ex != NULL) +#endif /* * Helper function to work out whether to call the new style callback or the old * one, and translate between the two. @@ -29,14 +35,18 @@ * for the "long" used for "inret" */ static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len, - int argi, long argl, long inret, size_t *processed) + int argi, long argl, long inret, + size_t *processed) { - long ret; + long ret = inret; +#ifndef OPENSSL_NO_DEPRECATED_3_0 int bareoper; if (b->callback_ex != NULL) +#endif return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed); +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* Strip off any BIO_CB_RETURN flag */ bareoper = oper & ~BIO_CB_RETURN; @@ -64,19 +74,20 @@ *processed = (size_t)ret; ret = 1; } - +#endif return ret; } -BIO *BIO_new(const BIO_METHOD *method) +BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method) { BIO *bio = OPENSSL_zalloc(sizeof(*bio)); if (bio == NULL) { - BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } + bio->libctx = libctx; bio->method = method; bio->shutdown = 1; bio->references = 1; @@ -86,13 +97,13 @@ bio->lock = CRYPTO_THREAD_lock_new(); if (bio->lock == NULL) { - BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); goto err; } if (method->create != NULL && !method->create(bio)) { - BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL); + ERR_raise(ERR_LIB_BIO, ERR_R_INIT_FAIL); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); CRYPTO_THREAD_lock_free(bio->lock); goto err; @@ -107,6 +118,11 @@ return NULL; } +BIO *BIO_new(const BIO_METHOD *method) +{ + return BIO_new_ex(NULL, method); +} + int BIO_free(BIO *a) { int ret; @@ -122,10 +138,10 @@ return 1; REF_ASSERT_ISNT(ret < 0); - if (a->callback != NULL || a->callback_ex != NULL) { + if (HAS_CALLBACK(a)) { ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); if (ret <= 0) - return ret; + return 0; } if ((a->method != NULL) && (a->method->destroy != NULL)) @@ -184,7 +200,7 @@ REF_PRINT_COUNT("BIO", a); REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); + return i > 1; } void BIO_clear_flags(BIO *b, int flags) @@ -202,6 +218,7 @@ b->flags |= flags; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 BIO_callback_fn BIO_get_callback(const BIO *b) { return b->callback; @@ -211,6 +228,7 @@ { b->callback = cb; } +#endif BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b) { @@ -252,19 +270,23 @@ { int ret; - if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) { - BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD); + if (b == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (b->method == NULL || b->method->bread == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if ((b->callback != NULL || b->callback_ex != NULL) && + if (HAS_CALLBACK(b) && ((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L, NULL)) <= 0)) return ret; if (!b->init) { - BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } ret = b->method->bread(b, data, dlen, readbytes); @@ -272,13 +294,13 @@ if (ret > 0) b->num_read += (uint64_t)*readbytes; - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data, dlen, 0, 0L, ret, readbytes); /* Shouldn't happen */ if (ret > 0 && *readbytes > dlen) { - BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR); return -1; } @@ -305,50 +327,50 @@ int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes) { - int ret; - - ret = bio_read_intern(b, data, dlen, readbytes); - - if (ret > 0) - ret = 1; - else - ret = 0; - - return ret; + return bio_read_intern(b, data, dlen, readbytes) > 0; } static int bio_write_intern(BIO *b, const void *data, size_t dlen, size_t *written) { + size_t local_written; int ret; + if (written != NULL) + *written = 0; + /* + * b == NULL is not an error but just means that zero bytes are written. + * Do not raise an error here. + */ if (b == NULL) return 0; - if ((b->method == NULL) || (b->method->bwrite == NULL)) { - BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD); + if (b->method == NULL || b->method->bwrite == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if ((b->callback != NULL || b->callback_ex != NULL) && + if (HAS_CALLBACK(b) && ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L, NULL)) <= 0)) return ret; if (!b->init) { - BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } - ret = b->method->bwrite(b, data, dlen, written); + ret = b->method->bwrite(b, data, dlen, &local_written); if (ret > 0) - b->num_write += (uint64_t)*written; + b->num_write += (uint64_t)local_written; - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data, - dlen, 0, 0L, ret, written); + dlen, 0, 0L, ret, &local_written); + if (written != NULL) + *written = local_written; return ret; } @@ -357,13 +379,13 @@ size_t written; int ret; - if (dlen < 0) + if (dlen <= 0) return 0; ret = bio_write_intern(b, data, (size_t)dlen, &written); if (ret > 0) { - /* *written should always be <= dlen */ + /* written should always be <= dlen */ ret = (int)written; } @@ -372,16 +394,8 @@ int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) { - int ret; - - ret = bio_write_intern(b, data, dlen, written); - - if (ret > 0) - ret = 1; - else - ret = 0; - - return ret; + return bio_write_intern(b, data, dlen, written) > 0 + || (b != NULL && dlen == 0); /* order is important for *written */ } int BIO_puts(BIO *b, const char *buf) @@ -389,20 +403,24 @@ int ret; size_t written = 0; - if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { - BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD); + if (b == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (b->method == NULL || b->method->bputs == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL); if (ret <= 0) return ret; } if (!b->init) { - BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } ret = b->method->bputs(b, buf); @@ -413,13 +431,13 @@ ret = 1; } - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0, 0L, ret, &written); if (ret > 0) { if (written > INT_MAX) { - BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG); + ERR_raise(ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG); ret = -1; } else { ret = (int)written; @@ -434,25 +452,29 @@ int ret; size_t readbytes = 0; - if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { - BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD); + if (b == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (b->method == NULL || b->method->bgets == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } if (size < 0) { - BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT); - return 0; + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); + return -1; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL); if (ret <= 0) return ret; } if (!b->init) { - BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } ret = b->method->bgets(b, buf, size); @@ -462,7 +484,7 @@ ret = 1; } - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, 0, 0L, ret, &readbytes); @@ -477,6 +499,37 @@ return ret; } +int BIO_get_line(BIO *bio, char *buf, int size) +{ + int ret = 0; + char *ptr = buf; + + if (buf == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (size <= 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); + return -1; + } + *buf = '\0'; + + if (bio == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (!bio->init) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; + } + + while (size-- > 1 && (ret = BIO_read(bio, ptr, 1)) > 0) + if (*ptr++ == '\n') + break; + *ptr = '\0'; + return ret > 0 || BIO_eof(bio) ? ptr - buf : ret; +} + int BIO_indent(BIO *b, int indent, int max) { if (indent < 0) @@ -512,14 +565,13 @@ long ret; if (b == NULL) - return 0; - - if ((b->method == NULL) || (b->method->ctrl == NULL)) { - BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD); + return -1; + if (b->method == NULL || b->method->ctrl == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL); if (ret <= 0) return ret; @@ -527,7 +579,7 @@ ret = b->method->ctrl(b, cmd, larg, parg); - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, larg, ret, NULL); @@ -539,15 +591,14 @@ long ret; if (b == NULL) - return 0; - - if ((b->method == NULL) || (b->method->callback_ctrl == NULL) - || (cmd != BIO_CTRL_SET_CALLBACK)) { - BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD); + return -2; + if (b->method == NULL || b->method->callback_ctrl == NULL + || cmd != BIO_CTRL_SET_CALLBACK) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L, NULL); if (ret <= 0) @@ -556,7 +607,7 @@ ret = b->method->callback_ctrl(b, cmd, fp); - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0, cmd, 0, ret, NULL); @@ -570,12 +621,28 @@ */ size_t BIO_ctrl_pending(BIO *bio) { - return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + long ret = BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + + if (ret < 0) + ret = 0; +#if LONG_MAX > SIZE_MAX + if (ret > SIZE_MAX) + ret = SIZE_MAX; +#endif + return (size_t)ret; } size_t BIO_ctrl_wpending(BIO *bio) { - return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + long ret = BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + + if (ret < 0) + ret = 0; +#if LONG_MAX > SIZE_MAX + if (ret > SIZE_MAX) + ret = SIZE_MAX; +#endif + return (size_t)ret; } /* put the 'bio' on the end of b's list of operators */ @@ -649,8 +716,10 @@ { int mt, mask; - if (bio == NULL) + if (bio == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } mask = type & 0xff; do { if (bio->method != NULL) { @@ -659,8 +728,9 @@ if (!mask) { if (mt & type) return bio; - } else if (mt == type) + } else if (mt == type) { return bio; + } } bio = bio->next_bio; } while (bio != NULL); @@ -702,7 +772,9 @@ for (bio = in; bio != NULL; bio = bio->next_bio) { if ((new_bio = BIO_new(bio->method)) == NULL) goto err; +#ifndef OPENSSL_NO_DEPRECATED_3_0 new_bio->callback = bio->callback; +#endif new_bio->callback_ex = bio->callback_ex; new_bio->cb_arg = bio->cb_arg; new_bio->init = bio->init; @@ -750,7 +822,7 @@ return CRYPTO_set_ex_data(&(bio->ex_data), idx, data); } -void *BIO_get_ex_data(BIO *bio, int idx) +void *BIO_get_ex_data(const BIO *bio, int idx) { return CRYPTO_get_ex_data(&(bio->ex_data), idx); } @@ -784,3 +856,127 @@ CRYPTO_THREAD_lock_free(bio_type_lock); bio_type_lock = NULL; } + +/* Internal variant of the below BIO_wait() not calling BIOerr() */ +static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) +{ +#ifndef OPENSSL_NO_SOCK + int fd; +#endif + long sec_diff; + + if (max_time == 0) /* no timeout */ + return 1; + +#ifndef OPENSSL_NO_SOCK + if (BIO_get_fd(bio, &fd) > 0 && fd < FD_SETSIZE) + return BIO_socket_wait(fd, BIO_should_read(bio), max_time); +#endif + /* fall back to polling since no sockets are available */ + + sec_diff = (long)(max_time - time(NULL)); /* might overflow */ + if (sec_diff < 0) + return 0; /* clearly timeout */ + + /* now take a nap at most the given number of milliseconds */ + if (sec_diff == 0) { /* we are below the 1 seconds resolution of max_time */ + if (nap_milliseconds > 1000) + nap_milliseconds = 1000; + } else { /* for sec_diff > 0, take min(sec_diff * 1000, nap_milliseconds) */ + if ((unsigned long)sec_diff * 1000 < nap_milliseconds) + nap_milliseconds = (unsigned int)sec_diff * 1000; + } + ossl_sleep(nap_milliseconds); + return 1; +} + +/*- + * Wait on (typically socket-based) BIO at most until max_time. + * Succeed immediately if max_time == 0. + * If sockets are not available support polling: succeed after waiting at most + * the number of nap_milliseconds in order to avoid a tight busy loop. + * Call BIOerr(...) on timeout or error. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) +{ + int rv = bio_wait(bio, max_time, nap_milliseconds); + + if (rv <= 0) + ERR_raise(ERR_LIB_BIO, + rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR); + return rv; +} + +/* + * Connect via given BIO using BIO_do_connect() until success/timeout/error. + * Parameter timeout == 0 means no timeout, < 0 means exactly one try. + * For non-blocking and potentially even non-socket BIOs perform polling with + * the given density: between polls sleep nap_milliseconds using BIO_wait() + * in order to avoid a tight busy loop. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds) +{ + int blocking = timeout <= 0; + time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; + int rv; + + if (bio == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (nap_milliseconds < 0) + nap_milliseconds = 100; + BIO_set_nbio(bio, !blocking); + + retry: + ERR_set_mark(); + rv = BIO_do_connect(bio); + + if (rv <= 0) { /* could be timeout or retryable error or fatal error */ + int err = ERR_peek_last_error(); + int reason = ERR_GET_REASON(err); + int do_retry = BIO_should_retry(bio); /* may be 1 only if !blocking */ + + if (ERR_GET_LIB(err) == ERR_LIB_BIO) { + switch (reason) { + case ERR_R_SYS_LIB: + /* + * likely retryable system error occurred, which may be + * EAGAIN (resource temporarily unavailable) some 40 secs after + * calling getaddrinfo(): Temporary failure in name resolution + * or a premature ETIMEDOUT, some 30 seconds after connect() + */ + case BIO_R_CONNECT_ERROR: + case BIO_R_NBIO_CONNECT_ERROR: + /* some likely retryable connection error occurred */ + (void)BIO_reset(bio); /* often needed to avoid retry failure */ + do_retry = 1; + break; + default: + break; + } + } + if (timeout >= 0 && do_retry) { + ERR_pop_to_mark(); + /* will not actually wait if timeout == 0 (i.e., blocking BIO): */ + rv = bio_wait(bio, max_time, nap_milliseconds); + if (rv > 0) + goto retry; + ERR_raise(ERR_LIB_BIO, + rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR); + } else { + ERR_clear_last_mark(); + rv = -1; + if (err == 0) /* missing error queue entry */ + /* workaround: general error */ + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); + } + } else { + ERR_clear_last_mark(); + } + + return rv; +} diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h --- a/crypto/bio/bio_local.h +++ b/crypto/bio/bio_local.h @@ -1,7 +1,7 @@ /* - * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -9,7 +9,6 @@ #include "e_os.h" #include "internal/sockets.h" -#include "internal/refcount.h" /* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */ @@ -30,7 +29,7 @@ # ifdef OSSL_INTERNAL_CRYPTLIB_H # error internal/cryptlib.h included before bio_local.h # endif -# ifdef HEADER_BIO_H +# ifdef OPENSSL_BIO_H # error openssl/bio.h included before bio_local.h # endif @@ -88,6 +87,7 @@ #include "internal/cryptlib.h" #include "internal/bio.h" +#include "internal/refcount.h" typedef struct bio_f_buffer_ctx_struct { /*- @@ -113,9 +113,12 @@ } BIO_F_BUFFER_CTX; struct bio_st { + OSSL_LIB_CTX *libctx; const BIO_METHOD *method; /* bio, mode, argp, argi, argl, ret */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 BIO_callback_fn callback; +#endif BIO_callback_fn_ex callback_ex; char *cb_arg; /* first argument for the callback */ int init; @@ -152,7 +155,7 @@ void bio_sock_cleanup_int(void); -#if BIO_FLAGS_UPLINK==0 +#if BIO_FLAGS_UPLINK_INTERNAL==0 /* Shortcut UPLINK calls on most platforms... */ # define UP_stdin stdin # define UP_stdout stdout diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c --- a/crypto/bio/bio_meth.c +++ b/crypto/bio/bio_meth.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -25,7 +25,7 @@ int newval; if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) { - BIOerr(BIO_F_BIO_GET_NEW_INDEX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return -1; } if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock)) @@ -40,7 +40,7 @@ if (biom == NULL || (biom->name = OPENSSL_strdup(name)) == NULL) { OPENSSL_free(biom); - BIOerr(BIO_F_BIO_METH_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } biom->type = type; diff --git a/crypto/bio/bio_print.c b/crypto/bio/bio_print.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bio_print.c @@ -0,0 +1,960 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "crypto/ctype.h" +#include "internal/numbers.h" +#include +#include + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions. + */ + +#ifdef HAVE_LONG_DOUBLE +# define LDOUBLE long double +#else +# define LDOUBLE double +#endif + +static int fmtstr(char **, char **, size_t *, size_t *, + const char *, int, int, int); +static int fmtint(char **, char **, size_t *, size_t *, + int64_t, int, int, int, int); +#ifndef OPENSSL_SYS_UEFI +static int fmtfp(char **, char **, size_t *, size_t *, + LDOUBLE, int, int, int, int); +#endif +static int doapr_outch(char **, char **, size_t *, size_t *, int); +static int _dopr(char **sbuffer, char **buffer, + size_t *maxlen, size_t *retlen, int *truncated, + const char *format, va_list args); + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +/* left-aligned padding */ +#define DP_F_MINUS (1 << 0) +/* print an explicit '+' for a value with positive sign */ +#define DP_F_PLUS (1 << 1) +/* print an explicit ' ' for a value with positive sign */ +#define DP_F_SPACE (1 << 2) +/* print 0/0x prefix for octal/hex and decimal point for floating point */ +#define DP_F_NUM (1 << 3) +/* print leading zeroes */ +#define DP_F_ZERO (1 << 4) +/* print HEX in UPPPERcase */ +#define DP_F_UP (1 << 5) +/* treat value as unsigned */ +#define DP_F_UNSIGNED (1 << 6) + +/* conversion flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 +#define DP_C_SIZE 5 + +/* Floating point formats */ +#define F_FORMAT 0 +#define E_FORMAT 1 +#define G_FORMAT 2 + +/* some handy macros */ +#define char_to_int(p) (p - '0') +#define OSSL_MAX(p,q) ((p >= q) ? p : q) + +static int +_dopr(char **sbuffer, + char **buffer, + size_t *maxlen, + size_t *retlen, int *truncated, const char *format, va_list args) +{ + char ch; + int64_t value; +#ifndef OPENSSL_SYS_UEFI + LDOUBLE fvalue; +#endif + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + flags = currlen = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) + state = DP_S_DONE; + + switch (state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (ossl_isdigit(ch)) { + min = 10 * min + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg(args, int); + ch = *format++; + state = DP_S_DOT; + } else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (ossl_isdigit(ch)) { + if (max < 0) + max = 0; + max = 10 * max + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg(args, int); + ch = *format++; + state = DP_S_MOD; + } else + state = DP_S_MOD; + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + if (*format == 'l') { + cflags = DP_C_LLONG; + format++; + } else + cflags = DP_C_LONG; + ch = *format++; + break; + case 'q': + case 'j': + cflags = DP_C_LLONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + case 'z': + cflags = DP_C_SIZE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + switch (cflags) { + case DP_C_SHORT: + value = (short int)va_arg(args, int); + break; + case DP_C_LONG: + value = va_arg(args, long int); + break; + case DP_C_LLONG: + value = va_arg(args, int64_t); + break; + case DP_C_SIZE: + value = va_arg(args, ossl_ssize_t); + break; + default: + value = va_arg(args, int); + break; + } + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, + max, flags)) + return 0; + break; + case 'X': + flags |= DP_F_UP; + /* FALLTHROUGH */ + case 'x': + case 'o': + case 'u': + flags |= DP_F_UNSIGNED; + switch (cflags) { + case DP_C_SHORT: + value = (unsigned short int)va_arg(args, unsigned int); + break; + case DP_C_LONG: + value = va_arg(args, unsigned long int); + break; + case DP_C_LLONG: + value = va_arg(args, uint64_t); + break; + case DP_C_SIZE: + value = va_arg(args, size_t); + break; + default: + value = va_arg(args, unsigned int); + break; + } + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, + ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), + min, max, flags)) + return 0; + break; +#ifndef OPENSSL_SYS_UEFI + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags, F_FORMAT)) + return 0; + break; + case 'E': + flags |= DP_F_UP; + /* fall thru */ + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags, E_FORMAT)) + return 0; + break; + case 'G': + flags |= DP_F_UP; + /* fall thru */ + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags, G_FORMAT)) + return 0; + break; +#else + case 'f': + case 'E': + case 'e': + case 'G': + case 'g': + /* not implemented for UEFI */ + ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED); + return 0; +#endif + case 'c': + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, + va_arg(args, int))) + return 0; + break; + case 's': + strvalue = va_arg(args, char *); + if (max < 0) { + if (buffer) + max = INT_MAX; + else + max = *maxlen; + } + if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, + flags, min, max)) + return 0; + break; + case 'p': + value = (size_t)va_arg(args, void *); + if (!fmtint(sbuffer, buffer, &currlen, maxlen, + value, 16, min, max, flags | DP_F_NUM)) + return 0; + break; + case 'n': + { + int *num; + num = va_arg(args, int *); + *num = currlen; + } + break; + case '%': + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; + break; + case 'w': + /* not supported yet, treat as next char */ + format++; + break; + default: + /* unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + break; + } + } + /* + * We have to truncate if there is no dynamic buffer and we have filled the + * static buffer. + */ + if (buffer == NULL) { + *truncated = (currlen > *maxlen - 1); + if (*truncated) + currlen = *maxlen - 1; + } + if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) + return 0; + *retlen = currlen - 1; + return 1; +} + +static int +fmtstr(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, const char *value, int flags, int min, int max) +{ + int padlen; + size_t strln; + int cnt = 0; + + if (value == 0) + value = ""; + + strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max); + + padlen = min - strln; + if (min < 0 || padlen < 0) + padlen = 0; + if (max >= 0) { + /* + * Calculate the maximum output including padding. + * Make sure max doesn't overflow into negativity + */ + if (max < INT_MAX - padlen) + max += padlen; + else + max = INT_MAX; + } + if (flags & DP_F_MINUS) + padlen = -padlen; + + while ((padlen > 0) && (max < 0 || cnt < max)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --padlen; + ++cnt; + } + while (strln > 0 && (max < 0 || cnt < max)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) + return 0; + --strln; + ++cnt; + } + while ((padlen < 0) && (max < 0 || cnt < max)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++padlen; + ++cnt; + } + return 1; +} + +static int +fmtint(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, int64_t value, int base, int min, int max, int flags) +{ + int signvalue = 0; + const char *prefix = ""; + uint64_t uvalue; + char convert[DECIMAL_SIZE(value) + 3]; + int place = 0; + int spadlen = 0; + int zpadlen = 0; + int caps = 0; + + if (max < 0) + max = 0; + uvalue = value; + if (!(flags & DP_F_UNSIGNED)) { + if (value < 0) { + signvalue = '-'; + uvalue = 0 - (uint64_t)value; + } else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + if (flags & DP_F_NUM) { + if (base == 8) + prefix = "0"; + if (base == 16) + prefix = "0x"; + } + if (flags & DP_F_UP) + caps = 1; + do { + convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") + [uvalue % (unsigned)base]; + uvalue = (uvalue / (unsigned)base); + } while (uvalue && (place < (int)sizeof(convert))); + if (place == sizeof(convert)) + place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = + min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = OSSL_MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; + + /* spaces */ + while (spadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --spadlen; + } + + /* sign */ + if (signvalue) + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + + /* prefix */ + while (*prefix) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) + return 0; + prefix++; + } + + /* zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --zpadlen; + } + } + /* digits */ + while (place > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) + return 0; + } + + /* left justified spaces */ + while (spadlen < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++spadlen; + } + return 1; +} + +#ifndef OPENSSL_SYS_UEFI + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + if (value < 0) + result = -value; + return result; +} + +static LDOUBLE pow_10(int in_exp) +{ + LDOUBLE result = 1; + while (in_exp) { + result *= 10; + in_exp--; + } + return result; +} + +static long roundv(LDOUBLE value) +{ + long intpart; + intpart = (long)value; + value = value - intpart; + if (value >= 0.5) + intpart++; + return intpart; +} + +static int +fmtfp(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style) +{ + int signvalue = 0; + LDOUBLE ufvalue; + LDOUBLE tmpvalue; + char iconvert[20]; + char fconvert[20]; + char econvert[20]; + int iplace = 0; + int fplace = 0; + int eplace = 0; + int padlen = 0; + int zpadlen = 0; + long exp = 0; + unsigned long intpart; + unsigned long fracpart; + unsigned long max10; + int realstyle; + + if (max < 0) + max = 6; + + if (fvalue < 0) + signvalue = '-'; + else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + + /* + * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT + * depending on the number to be printed. Work out which one it is and use + * that from here on. + */ + if (style == G_FORMAT) { + if (fvalue == 0.0) { + realstyle = F_FORMAT; + } else if (fvalue < 0.0001) { + realstyle = E_FORMAT; + } else if ((max == 0 && fvalue >= 10) + || (max > 0 && fvalue >= pow_10(max))) { + realstyle = E_FORMAT; + } else { + realstyle = F_FORMAT; + } + } else { + realstyle = style; + } + + if (style != F_FORMAT) { + tmpvalue = fvalue; + /* Calculate the exponent */ + if (fvalue != 0.0) { + while (tmpvalue < 1) { + tmpvalue *= 10; + exp--; + } + while (tmpvalue > 10) { + tmpvalue /= 10; + exp++; + } + } + if (style == G_FORMAT) { + /* + * In G_FORMAT the "precision" represents significant digits. We + * always have at least 1 significant digit. + */ + if (max == 0) + max = 1; + /* Now convert significant digits to decimal places */ + if (realstyle == F_FORMAT) { + max -= (exp + 1); + if (max < 0) { + /* + * Should not happen. If we're in F_FORMAT then exp < max? + */ + (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); + return 0; + } + } else { + /* + * In E_FORMAT there is always one significant digit in front + * of the decimal point, so: + * significant digits == 1 + decimal places + */ + max--; + } + } + if (realstyle == E_FORMAT) + fvalue = tmpvalue; + } + ufvalue = abs_val(fvalue); + /* + * By subtracting 65535 (2^16-1) we cancel the low order 15 bits + * of ULONG_MAX to avoid using imprecise floating point values. + */ + if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) { + /* Number too big */ + (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); + return 0; + } + intpart = (unsigned long)ufvalue; + + /* + * sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* + * we "cheat" by converting the fractional part to integer by multiplying + * by a factor of 10 + */ + max10 = roundv(pow_10(max)); + fracpart = roundv(pow_10(max) * (ufvalue - intpart)); + + if (fracpart >= max10) { + intpart++; + fracpart -= max10; + } + + /* convert integer part */ + do { + iconvert[iplace++] = "0123456789"[intpart % 10]; + intpart = (intpart / 10); + } while (intpart && (iplace < (int)sizeof(iconvert))); + if (iplace == sizeof(iconvert)) + iplace--; + iconvert[iplace] = 0; + + /* convert fractional part */ + while (fplace < max) { + if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) { + /* We strip trailing zeros in G_FORMAT */ + max--; + fracpart = fracpart / 10; + if (fplace < max) + continue; + break; + } + fconvert[fplace++] = "0123456789"[fracpart % 10]; + fracpart = (fracpart / 10); + } + + if (fplace == sizeof(fconvert)) + fplace--; + fconvert[fplace] = 0; + + /* convert exponent part */ + if (realstyle == E_FORMAT) { + int tmpexp; + if (exp < 0) + tmpexp = -exp; + else + tmpexp = exp; + + do { + econvert[eplace++] = "0123456789"[tmpexp % 10]; + tmpexp = (tmpexp / 10); + } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); + /* Exponent is huge!! Too big to print */ + if (tmpexp > 0) { + (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); + return 0; + } + /* Add a leading 0 for single digit exponents */ + if (eplace == 1) + econvert[eplace++] = '0'; + } + + /* + * -1 for decimal point (if we have one, i.e. max > 0), + * another -1 if we are printing a sign + */ + padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0); + /* Take some off for exponent prefix "+e" and exponent */ + if (realstyle == E_FORMAT) + padlen -= 2 + eplace; + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + --padlen; + signvalue = 0; + } + while (padlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --padlen; + } + } + while (padlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --padlen; + } + if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + + while (iplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) + return 0; + } + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0 || (flags & DP_F_NUM)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) + return 0; + + while (fplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, + fconvert[--fplace])) + return 0; + } + } + while (zpadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --zpadlen; + } + if (realstyle == E_FORMAT) { + char ech; + + if ((flags & DP_F_UP) == 0) + ech = 'e'; + else + ech = 'E'; + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech)) + return 0; + if (exp < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-')) + return 0; + } else { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+')) + return 0; + } + while (eplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, + econvert[--eplace])) + return 0; + } + } + + while (padlen < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++padlen; + } + return 1; +} + +#endif /* OPENSSL_SYS_UEFI */ + +#define BUFFER_INC 1024 + +static int +doapr_outch(char **sbuffer, + char **buffer, size_t *currlen, size_t *maxlen, int c) +{ + /* If we haven't at least one buffer, someone has done a big booboo */ + if (!ossl_assert(*sbuffer != NULL || buffer != NULL)) + return 0; + + /* |currlen| must always be <= |*maxlen| */ + if (!ossl_assert(*currlen <= *maxlen)) + return 0; + + if (buffer && *currlen == *maxlen) { + if (*maxlen > INT_MAX - BUFFER_INC) + return 0; + + *maxlen += BUFFER_INC; + if (*buffer == NULL) { + if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + if (*currlen > 0) { + if (!ossl_assert(*sbuffer != NULL)) + return 0; + memcpy(*buffer, *sbuffer, *currlen); + } + *sbuffer = NULL; + } else { + char *tmpbuf; + + tmpbuf = OPENSSL_realloc(*buffer, *maxlen); + if (tmpbuf == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; + } + *buffer = tmpbuf; + } + } + + if (*currlen < *maxlen) { + if (*sbuffer) + (*sbuffer)[(*currlen)++] = (char)c; + else + (*buffer)[(*currlen)++] = (char)c; + } + + return 1; +} + +/***************************************************************************/ + +int BIO_printf(BIO *bio, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_vprintf(bio, format, args); + + va_end(args); + return ret; +} + +int BIO_vprintf(BIO *bio, const char *format, va_list args) +{ + int ret; + size_t retlen; + char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable + * in small-stack environments, like threads + * or DOS programs. */ + char *hugebufp = hugebuf; + size_t hugebufsize = sizeof(hugebuf); + char *dynbuf = NULL; + int ignored; + + dynbuf = NULL; + if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, + args)) { + OPENSSL_free(dynbuf); + return -1; + } + if (dynbuf) { + ret = BIO_write(bio, dynbuf, (int)retlen); + OPENSSL_free(dynbuf); + } else { + ret = BIO_write(bio, hugebuf, (int)retlen); + } + return ret; +} + +/* + * As snprintf is not available everywhere, we provide our own + * implementation. This function has nothing to do with BIOs, but it's + * closely related to BIO_printf, and we need *some* name prefix ... (XXX the + * function should be renamed, but to what?) + */ +int BIO_snprintf(char *buf, size_t n, const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_vsnprintf(buf, n, format, args); + + va_end(args); + return ret; +} + +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) +{ + size_t retlen; + int truncated; + + if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) + return -1; + + if (truncated) + /* + * In case of truncation, return -1 like traditional snprintf. + * (Current drafts for ISO/IEC 9899 say snprintf should return the + * number of characters that would have been written, had the buffer + * been large enough.) + */ + return -1; + return (retlen <= INT_MAX) ? (int)retlen : -1; +} diff --git a/crypto/bio/bio_sock.c b/crypto/bio/bio_sock.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bio_sock.c @@ -0,0 +1,415 @@ +/* + * Copyright 1995-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "bio_local.h" +#ifndef OPENSSL_NO_SOCK +# define SOCKET_PROTOCOL IPPROTO_TCP +# ifdef SO_MAXCONN +# define MAX_LISTEN SO_MAXCONN +# elif defined(SOMAXCONN) +# define MAX_LISTEN SOMAXCONN +# else +# define MAX_LISTEN 32 +# endif +# if defined(OPENSSL_SYS_WINDOWS) +static int wsa_init_done = 0; +# endif + +# if defined __TANDEM +# include +# include /* select */ +# if defined(OPENSSL_TANDEM_FLOSS) +# include +# endif +# elif defined _WIN32 +# include /* for type fd_set */ +# else +# include +# if defined __VMS +# include +# elif defined _HPUX_SOURCE +# include +# else +# include +# endif +# endif + +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 +int BIO_get_host_ip(const char *str, unsigned char *ip) +{ + BIO_ADDRINFO *res = NULL; + int ret = 0; + + if (BIO_sock_init() != 1) + return 0; /* don't generate another error code here */ + + if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { + size_t l; + + if (BIO_ADDRINFO_family(res) != AF_INET) { + ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); + } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { + /* + * Because only AF_INET addresses will reach this far, we can assert + * that l should be 4 + */ + if (ossl_assert(l == 4)) + ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); + } + BIO_ADDRINFO_free(res); + } else { + ERR_add_error_data(2, "host=", str); + } + + return ret; +} + +int BIO_get_port(const char *str, unsigned short *port_ptr) +{ + BIO_ADDRINFO *res = NULL; + int ret = 0; + + if (str == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED); + return 0; + } + + if (BIO_sock_init() != 1) + return 0; /* don't generate another error code here */ + + if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { + if (BIO_ADDRINFO_family(res) != AF_INET) { + ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); + } else { + *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); + ret = 1; + } + BIO_ADDRINFO_free(res); + } else { + ERR_add_error_data(2, "host=", str); + } + + return ret; +} +# endif + +int BIO_sock_error(int sock) +{ + int j = 0, i; + socklen_t size = sizeof(j); + + /* + * Note: under Windows the third parameter is of type (char *) whereas + * under other systems it is (void *) if you don't have a cast it will + * choke the compiler: if you do have a cast then you can either go for + * (char *) or (void *). + */ + i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); + if (i < 0) + return get_last_socket_error(); + else + return j; +} + +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 +struct hostent *BIO_gethostbyname(const char *name) +{ + /* + * Caching gethostbyname() results forever is wrong, so we have to let + * the true gethostbyname() worry about this + */ + return gethostbyname(name); +} +# endif + +int BIO_sock_init(void) +{ +# ifdef OPENSSL_SYS_WINDOWS + static struct WSAData wsa_state; + + if (!wsa_init_done) { + wsa_init_done = 1; + memset(&wsa_state, 0, sizeof(wsa_state)); + /* + * Not making wsa_state available to the rest of the code is formally + * wrong. But the structures we use are [believed to be] invariable + * among Winsock DLLs, while API availability is [expected to be] + * probed at run-time with DSO_global_lookup. + */ + if (WSAStartup(0x0202, &wsa_state) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling wsastartup()"); + ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP); + return -1; + } + } +# endif /* OPENSSL_SYS_WINDOWS */ +# ifdef WATT32 + extern int _watt_do_exit; + _watt_do_exit = 0; /* don't make sock_init() call exit() */ + if (sock_init()) + return -1; +# endif + + return 1; +} + +void bio_sock_cleanup_int(void) +{ +# ifdef OPENSSL_SYS_WINDOWS + if (wsa_init_done) { + wsa_init_done = 0; + WSACleanup(); + } +# endif +} + +int BIO_socket_ioctl(int fd, long type, void *arg) +{ + int i; + +# ifdef __DJGPP__ + i = ioctlsocket(fd, type, (char *)arg); +# else +# if defined(OPENSSL_SYS_VMS) + /*- + * 2011-02-18 SMS. + * VMS ioctl() can't tolerate a 64-bit "void *arg", but we + * observe that all the consumers pass in an "unsigned long *", + * so we arrange a local copy with a short pointer, and use + * that, instead. + */ +# if __INITIAL_POINTER_SIZE == 64 +# define ARG arg_32p +# pragma pointer_size save +# pragma pointer_size 32 + unsigned long arg_32; + unsigned long *arg_32p; +# pragma pointer_size restore + arg_32p = &arg_32; + arg_32 = *((unsigned long *)arg); +# else /* __INITIAL_POINTER_SIZE == 64 */ +# define ARG arg +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ +# else /* defined(OPENSSL_SYS_VMS) */ +# define ARG arg +# endif /* defined(OPENSSL_SYS_VMS) [else] */ + + i = ioctlsocket(fd, type, ARG); +# endif /* __DJGPP__ */ + if (i < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling ioctlsocket()"); + return i; +} + +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 +int BIO_get_accept_socket(char *host, int bind_mode) +{ + int s = INVALID_SOCKET; + char *h = NULL, *p = NULL; + BIO_ADDRINFO *res = NULL; + + if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV)) + return INVALID_SOCKET; + + if (BIO_sock_init() != 1) + return INVALID_SOCKET; + + if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) + goto err; + + if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res), + BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) { + s = INVALID_SOCKET; + goto err; + } + + if (!BIO_listen(s, BIO_ADDRINFO_address(res), + bind_mode ? BIO_SOCK_REUSEADDR : 0)) { + BIO_closesocket(s); + s = INVALID_SOCKET; + } + + err: + BIO_ADDRINFO_free(res); + OPENSSL_free(h); + OPENSSL_free(p); + + return s; +} + +int BIO_accept(int sock, char **ip_port) +{ + BIO_ADDR res; + int ret = -1; + + ret = BIO_accept_ex(sock, &res, 0); + if (ret == (int)INVALID_SOCKET) { + if (BIO_sock_should_retry(ret)) { + ret = -2; + goto end; + } + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling accept()"); + ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR); + goto end; + } + + if (ip_port != NULL) { + char *host = BIO_ADDR_hostname_string(&res, 1); + char *port = BIO_ADDR_service_string(&res, 1); + if (host != NULL && port != NULL) + *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); + else + *ip_port = NULL; + + if (*ip_port == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + BIO_closesocket(ret); + ret = (int)INVALID_SOCKET; + } else { + strcpy(*ip_port, host); + strcat(*ip_port, ":"); + strcat(*ip_port, port); + } + OPENSSL_free(host); + OPENSSL_free(port); + } + + end: + return ret; +} +# endif + +int BIO_set_tcp_ndelay(int s, int on) +{ + int ret = 0; +# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) + int opt; + +# ifdef SOL_TCP + opt = SOL_TCP; +# else +# ifdef IPPROTO_TCP + opt = IPPROTO_TCP; +# endif +# endif + + ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); +# endif + return (ret == 0); +} + +int BIO_socket_nbio(int s, int mode) +{ + int ret = -1; + int l; + + l = mode; +# ifdef FIONBIO + l = mode; + + ret = BIO_socket_ioctl(s, FIONBIO, &l); +# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY)) + /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ + + l = fcntl(s, F_GETFL, 0); + if (l == -1) { + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fcntl()"); + ret = -1; + } else { +# if defined(O_NONBLOCK) + l &= ~O_NONBLOCK; +# else + l &= ~FNDELAY; /* BSD4.x */ +# endif + if (mode) { +# if defined(O_NONBLOCK) + l |= O_NONBLOCK; +# else + l |= FNDELAY; /* BSD4.x */ +# endif + } + ret = fcntl(s, F_SETFL, l); + + if (ret < 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fcntl()"); + } + } +# else + /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT); +# endif + + return (ret == 0); +} + +int BIO_sock_info(int sock, + enum BIO_sock_info_type type, union BIO_sock_info_u *info) +{ + switch (type) { + case BIO_SOCK_INFO_ADDRESS: + { + socklen_t addr_len; + int ret = 0; + addr_len = sizeof(*info->addr); + ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), + &addr_len); + if (ret == -1) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockname()"); + ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR); + return 0; + } + if ((size_t)addr_len > sizeof(*info->addr)) { + ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); + return 0; + } + } + break; + default: + ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE); + return 0; + } + return 1; +} + +/* + * Wait on fd at most until max_time; succeed immediately if max_time == 0. + * If for_read == 0 then assume to wait for writing, else wait for reading. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_socket_wait(int fd, int for_read, time_t max_time) +{ + fd_set confds; + struct timeval tv; + time_t now; + + if (fd < 0 || fd >= FD_SETSIZE) + return -1; + if (max_time == 0) + return 1; + + now = time(NULL); + if (max_time < now) + return 0; + + FD_ZERO(&confds); + openssl_fdset(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = (long)(max_time - now); /* might overflow */ + return select(fd + 1, for_read ? &confds : NULL, + for_read ? NULL : &confds, NULL, &tv); +} +#endif /* !defined(OPENSSL_NO_SOCK) */ diff --git a/crypto/bio/bio_sock2.c b/crypto/bio/bio_sock2.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bio_sock2.c @@ -0,0 +1,340 @@ +/* + * Copyright 2016-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "bio_local.h" +#include "internal/ktls.h" + +#include + +#ifndef OPENSSL_NO_SOCK +# ifdef SO_MAXCONN +# define MAX_LISTEN SO_MAXCONN +# elif defined(SOMAXCONN) +# define MAX_LISTEN SOMAXCONN +# else +# define MAX_LISTEN 32 +# endif + +/*- + * BIO_socket - create a socket + * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...) + * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM) + * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP) + * @options: BIO socket options (currently unused) + * + * Creates a socket. This should be called before calling any + * of BIO_connect and BIO_listen. + * + * Returns the file descriptor on success or INVALID_SOCKET on failure. On + * failure errno is set, and a status is added to the OpenSSL error stack. + */ +int BIO_socket(int domain, int socktype, int protocol, int options) +{ + int sock = -1; + + if (BIO_sock_init() != 1) + return INVALID_SOCKET; + + sock = socket(domain, socktype, protocol); + if (sock == -1) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling socket()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); + return INVALID_SOCKET; + } + + return sock; +} + +/*- + * BIO_connect - connect to an address + * @sock: the socket to connect with + * @addr: the address to connect to + * @options: BIO socket options + * + * Connects to the address using the given socket and options. + * + * Options can be a combination of the following: + * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. + * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. + * - BIO_SOCK_NODELAY: don't delay small messages. + * + * options holds BIO socket options that can be used + * You should call this for every address returned by BIO_lookup + * until the connection is successful. + * + * Returns 1 on success or 0 on failure. On failure errno is set + * and an error status is added to the OpenSSL error stack. + */ +int BIO_connect(int sock, const BIO_ADDR *addr, int options) +{ + const int on = 1; + + if (sock == -1) { + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET); + return 0; + } + + if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0)) + return 0; + + if (options & BIO_SOCK_KEEPALIVE) { + if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE); + return 0; + } + } + + if (options & BIO_SOCK_NODELAY) { + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY); + return 0; + } + } + + if (connect(sock, BIO_ADDR_sockaddr(addr), + BIO_ADDR_sockaddr_size(addr)) == -1) { + if (!BIO_sock_should_retry(-1)) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling connect()"); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); + } + return 0; + } +# ifndef OPENSSL_NO_KTLS + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(sock); +# endif + return 1; +} + +/*- + * BIO_bind - bind socket to address + * @sock: the socket to set + * @addr: local address to bind to + * @options: BIO socket options + * + * Binds to the address using the given socket and options. + * + * Options can be a combination of the following: + * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination + * for a recently closed port. + * + * When restarting the program it could be that the port is still in use. If + * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway. + * It's recommended that you use this. + */ +int BIO_bind(int sock, const BIO_ADDR *addr, int options) +{ +# ifndef OPENSSL_SYS_WINDOWS + int on = 1; +# endif + + if (sock == -1) { + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET); + return 0; + } + +# ifndef OPENSSL_SYS_WINDOWS + /* + * SO_REUSEADDR has different behavior on Windows than on + * other operating systems, don't set it there. + */ + if (options & BIO_SOCK_REUSEADDR) { + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR); + return 0; + } + } +# endif + + if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error() /* may be 0 */, + "calling bind()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET); + return 0; + } + + return 1; +} + +/*- + * BIO_listen - Creates a listen socket + * @sock: the socket to listen with + * @addr: local address to bind to + * @options: BIO socket options + * + * Binds to the address using the given socket and options, then + * starts listening for incoming connections. + * + * Options can be a combination of the following: + * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. + * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. + * - BIO_SOCK_NODELAY: don't delay small messages. + * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination + * for a recently closed port. + * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only + * for IPv6 addresses and not IPv4 addresses mapped to IPv6. + * + * It's recommended that you set up both an IPv6 and IPv4 listen socket, and + * then check both for new clients that connect to it. You want to set up + * the socket as non-blocking in that case since else it could hang. + * + * Not all operating systems support IPv4 addresses on an IPv6 socket, and for + * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to + * create the IPv6 sockets to only listen for IPv6 connection. + * + * It could be that the first BIO_listen() call will listen to all the IPv6 + * and IPv4 addresses and that then trying to bind to the IPv4 address will + * fail. We can't tell the difference between already listening ourself to + * it and someone else listening to it when failing and errno is EADDRINUSE, so + * it's recommended to not give an error in that case if the first call was + * successful. + * + * When restarting the program it could be that the port is still in use. If + * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway. + * It's recommended that you use this. + */ +int BIO_listen(int sock, const BIO_ADDR *addr, int options) +{ + int on = 1; + int socktype; + socklen_t socktype_len = sizeof(socktype); + + if (sock == -1) { + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET); + return 0; + } + + if (getsockopt(sock, SOL_SOCKET, SO_TYPE, + (void *)&socktype, &socktype_len) != 0 + || socktype_len != sizeof(socktype)) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE); + return 0; + } + + if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0)) + return 0; + + if (options & BIO_SOCK_KEEPALIVE) { + if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE); + return 0; + } + } + + if (options & BIO_SOCK_NODELAY) { + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY); + return 0; + } + } + + /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */ +# if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) + if (BIO_ADDR_family(addr) == AF_INET6) { + /* + * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF. + * Therefore we always have to use setsockopt here. + */ + on = options & BIO_SOCK_V6_ONLY ? 1 : 0; + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY); + return 0; + } + } +# endif + + if (!BIO_bind(sock, addr, options)) + return 0; + + if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling listen()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET); + return 0; + } + + return 1; +} + +/*- + * BIO_accept_ex - Accept new incoming connections + * @sock: the listening socket + * @addr: the BIO_ADDR to store the peer address in + * @options: BIO socket options, applied on the accepted socket. + * + */ +int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options) +{ + socklen_t len; + int accepted_sock; + BIO_ADDR locaddr; + BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_; + + len = sizeof(*addr); + accepted_sock = accept(accept_sock, + BIO_ADDR_sockaddr_noconst(addr), &len); + if (accepted_sock == -1) { + if (!BIO_sock_should_retry(accepted_sock)) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling accept()"); + ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR); + } + return INVALID_SOCKET; + } + + if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) { + closesocket(accepted_sock); + return INVALID_SOCKET; + } + + return accepted_sock; +} + +/*- + * BIO_closesocket - Close a socket + * @sock: the socket to close + */ +int BIO_closesocket(int sock) +{ + if (sock < 0 || closesocket(sock) < 0) + return 0; + return 1; +} +#endif diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -1,12 +1,14 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include "bio_local.h" @@ -54,10 +56,8 @@ static const BIO_METHOD methods_acceptp = { BIO_TYPE_ACCEPT, "socket accept", - /* TODO: Convert to new style write function */ bwrite_conv, acpt_write, - /* TODO: Convert to new style read function */ bread_conv, acpt_read, acpt_puts, @@ -93,7 +93,7 @@ BIO_ACCEPT *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } ret->accept_family = BIO_FAMILY_IPANY; @@ -156,10 +156,10 @@ switch (c->state) { case ACPT_S_BEFORE: if (c->param_addr == NULL && c->param_serv == NULL) { - BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED); - ERR_add_error_data(4, - "hostname=", c->param_addr, - " service=", c->param_serv); + ERR_raise_data(ERR_LIB_BIO, + BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED, + "hostname=%s, service=%s", + c->param_addr, c->param_serv); goto exit_loop; } @@ -192,7 +192,7 @@ family = AF_INET6; } else { #endif - BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY); goto exit_loop; } break; @@ -203,7 +203,7 @@ family = AF_UNSPEC; break; default: - BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY); goto exit_loop; } if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER, @@ -211,26 +211,31 @@ goto exit_loop; } if (c->addr_first == NULL) { - BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); + ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING); goto exit_loop; } - /* We're currently not iterating, but set this as preparation - * for possible future development in that regard - */ c->addr_iter = c->addr_first; c->state = ACPT_S_CREATE_SOCKET; break; case ACPT_S_CREATE_SOCKET: + ERR_set_mark(); s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), BIO_ADDRINFO_socktype(c->addr_iter), BIO_ADDRINFO_protocol(c->addr_iter), 0); if (s == (int)INVALID_SOCKET) { - SYSerr(SYS_F_SOCKET, get_last_socket_error()); - ERR_add_error_data(4, - "hostname=", c->param_addr, - " service=", c->param_serv); - BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); + if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) { + /* + * if there are more addresses to try, do that first + */ + ERR_pop_to_mark(); + break; + } + ERR_clear_last_mark(); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling socket(%s, %s)", + c->param_addr, c->param_serv); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } c->accept_sock = s; @@ -306,9 +311,11 @@ if (bio == NULL) goto exit_loop; + BIO_set_callback_ex(bio, BIO_get_callback_ex(b)); +#ifndef OPENSSL_NO_DEPRECATED_3_0 BIO_set_callback(bio, BIO_get_callback(b)); +#endif BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); - /* * If the accept BIO has an bio_chain, we dup it and put the new * socket at the end. diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c --- a/crypto/bio/bss_bio.c +++ b/crypto/bio/bss_bio.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -38,10 +38,8 @@ static const BIO_METHOD methods_biop = { BIO_TYPE_BIO, "BIO pair", - /* TODO: Convert to new style write function */ bwrite_conv, bio_write, - /* TODO: Convert to new style read function */ bread_conv, bio_read, bio_puts, @@ -286,7 +284,7 @@ b->request = 0; if (b->closed) { /* we already closed */ - BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); + ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE); return -1; } @@ -362,7 +360,7 @@ b->request = 0; if (b->closed) { - BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); + ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE); return -1; } @@ -427,10 +425,10 @@ case BIO_C_SET_WRITE_BUF_SIZE: if (b->peer) { - BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); + ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE); ret = 0; } else if (num == 0) { - BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); ret = 0; } else { size_t new_size = num; @@ -616,14 +614,14 @@ b2 = bio2->ptr; if (b1->peer != NULL || b2->peer != NULL) { - BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); + ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE); return 0; } if (b1->buf == NULL) { b1->buf = OPENSSL_malloc(b1->size); if (b1->buf == NULL) { - BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } b1->len = 0; @@ -633,7 +631,7 @@ if (b2->buf == NULL) { b2->buf = OPENSSL_malloc(b2->size); if (b2->buf == NULL) { - BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } b2->len = 0; @@ -750,7 +748,7 @@ long ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } @@ -766,7 +764,7 @@ int ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } @@ -781,7 +779,7 @@ long ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } @@ -797,7 +795,7 @@ int ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,6 +11,7 @@ #include #include "bio_local.h" +#include "internal/ktls.h" #ifndef OPENSSL_NO_SOCK @@ -20,6 +21,9 @@ char *param_hostname; char *param_service; int connect_mode; +# ifndef OPENSSL_NO_KTLS + unsigned char record_type; +# endif BIO_ADDRINFO *addr_first; const BIO_ADDRINFO *addr_iter; @@ -59,10 +63,8 @@ static const BIO_METHOD methods_connectp = { BIO_TYPE_CONNECT, "socket connect", - /* TODO: Convert to new style write function */ bwrite_conv, conn_write, - /* TODO: Convert to new style read function */ bread_conv, conn_read, conn_puts, @@ -85,10 +87,10 @@ switch (c->state) { case BIO_CONN_S_BEFORE: if (c->param_hostname == NULL && c->param_service == NULL) { - BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); + ERR_raise_data(ERR_LIB_BIO, + BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED, + "hostname=%s service=%s", + c->param_hostname, c->param_service); goto exit_loop; } c->state = BIO_CONN_S_GET_ADDR; @@ -107,7 +109,7 @@ family = AF_INET6; } else { #endif - BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY); goto exit_loop; } break; @@ -118,7 +120,7 @@ family = AF_UNSPEC; break; default: - BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY); goto exit_loop; } if (BIO_lookup(c->param_hostname, c->param_service, @@ -127,7 +129,7 @@ goto exit_loop; } if (c->addr_first == NULL) { - BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); + ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING); goto exit_loop; } c->addr_iter = c->addr_first; @@ -139,11 +141,10 @@ BIO_ADDRINFO_socktype(c->addr_iter), BIO_ADDRINFO_protocol(c->addr_iter), 0); if (ret == (int)INVALID_SOCKET) { - SYSerr(SYS_F_SOCKET, get_last_socket_error()); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); - BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling socket(%s, %s)", + c->param_hostname, c->param_service); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } b->num = ret; @@ -152,6 +153,7 @@ case BIO_CONN_S_CONNECT: BIO_clear_retry_flags(b); + ERR_set_mark(); ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter), BIO_SOCK_KEEPALIVE | c->connect_mode); b->retry_reason = 0; @@ -160,7 +162,7 @@ BIO_set_retry_special(b); c->state = BIO_CONN_S_BLOCKED_CONNECT; b->retry_reason = BIO_RR_CONNECT; - ERR_clear_error(); + ERR_pop_to_mark(); } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) { /* @@ -168,23 +170,27 @@ */ BIO_closesocket(b->num); c->state = BIO_CONN_S_CREATE_SOCKET; - ERR_clear_error(); + ERR_pop_to_mark(); break; } else { - SYSerr(SYS_F_CONNECT, get_last_socket_error()); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); + ERR_clear_last_mark(); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling connect(%s, %s)", + c->param_hostname, c->param_service); c->state = BIO_CONN_S_CONNECT_ERROR; break; } goto exit_loop; } else { + ERR_clear_last_mark(); c->state = BIO_CONN_S_OK; } break; case BIO_CONN_S_BLOCKED_CONNECT: + /* wait for socket being writable, before querying BIO_sock_error */ + if (BIO_socket_wait(b->num, 0, time(NULL)) == 0) + break; i = BIO_sock_error(b->num); if (i != 0) { BIO_clear_retry_flags(b); @@ -194,22 +200,30 @@ */ BIO_closesocket(b->num); c->state = BIO_CONN_S_CREATE_SOCKET; - ERR_clear_error(); break; } - SYSerr(SYS_F_CONNECT, i); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); - BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR); + ERR_raise_data(ERR_LIB_SYS, i, + "calling connect(%s, %s)", + c->param_hostname, c->param_service); + ERR_raise(ERR_LIB_BIO, BIO_R_NBIO_CONNECT_ERROR); ret = 0; goto exit_loop; - } else + } else { c->state = BIO_CONN_S_OK; +# ifndef OPENSSL_NO_KTLS + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(b->num); +# endif + } break; case BIO_CONN_S_CONNECT_ERROR: - BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); ret = 0; goto exit_loop; @@ -240,7 +254,7 @@ BIO_CONNECT *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } ret->state = BIO_CONN_S_BEFORE; @@ -320,7 +334,12 @@ if (out != NULL) { clear_socket_error(); - ret = readsocket(b->num, out, outl); +# ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_recv(b)) + ret = ktls_read_record(b->num, out, outl); + else +# endif + ret = readsocket(b->num, out, outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -345,7 +364,16 @@ } clear_socket_error(); - ret = writesocket(b->num, in, inl); +# ifndef OPENSSL_NO_KTLS + if (BIO_should_ktls_ctrl_msg_flag(b)) { + ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl); + if (ret >= 0) { + ret = inl; + BIO_clear_ktls_ctrl_msg_flag(b); + } + } else +# endif + ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -361,6 +389,9 @@ const char **pptr = NULL; long ret = 1; BIO_CONNECT *data; +# ifndef OPENSSL_NO_KTLS + ktls_crypto_info_t *crypto_info; +# endif data = (BIO_CONNECT *)b->ptr; @@ -518,8 +549,29 @@ } break; case BIO_CTRL_EOF: - ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; + break; +# ifndef OPENSSL_NO_KTLS + case BIO_CTRL_SET_KTLS: + crypto_info = (ktls_crypto_info_t *)ptr; + ret = ktls_start(b->num, crypto_info, num); + if (ret) + BIO_set_ktls_flag(b, num); + break; + case BIO_CTRL_GET_KTLS_SEND: + return BIO_should_ktls_flag(b, 1) != 0; + case BIO_CTRL_GET_KTLS_RECV: + return BIO_should_ktls_flag(b, 0) != 0; + case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: + BIO_set_ktls_ctrl_msg_flag(b); + data->record_type = num; + ret = 0; + break; + case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: + BIO_clear_ktls_ctrl_msg_flag(b); + ret = 0; break; +# endif default: ret = 0; break; diff --git a/crypto/bio/bss_core.c b/crypto/bio/bss_core.c new file mode 100644 --- /dev/null +++ b/crypto/bio/bss_core.c @@ -0,0 +1,194 @@ +/* + * Copyright 2019-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include "bio_local.h" +#include "internal/cryptlib.h" + +typedef struct { + OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex; + OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex; + OSSL_FUNC_BIO_gets_fn *c_bio_gets; + OSSL_FUNC_BIO_puts_fn *c_bio_puts; + OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl; + OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref; + OSSL_FUNC_BIO_free_fn *c_bio_free; +} BIO_CORE_GLOBALS; + +static void bio_core_globals_free(void *vbcg) +{ + OPENSSL_free(vbcg); +} + +static void *bio_core_globals_new(OSSL_LIB_CTX *ctx) +{ + return OPENSSL_zalloc(sizeof(BIO_CORE_GLOBALS)); +} + +static const OSSL_LIB_CTX_METHOD bio_core_globals_method = { + OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, + bio_core_globals_new, + bio_core_globals_free, +}; + +static ossl_inline BIO_CORE_GLOBALS *get_globals(OSSL_LIB_CTX *libctx) +{ + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX, + &bio_core_globals_method); +} + +static int bio_core_read_ex(BIO *bio, char *data, size_t data_len, + size_t *bytes_read) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_read_ex == NULL) + return 0; + return bcgbl->c_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read); +} + +static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len, + size_t *written) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_write_ex == NULL) + return 0; + return bcgbl->c_bio_write_ex(BIO_get_data(bio), data, data_len, written); +} + +static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_ctrl == NULL) + return -1; + return bcgbl->c_bio_ctrl(BIO_get_data(bio), cmd, num, ptr); +} + +static int bio_core_gets(BIO *bio, char *buf, int size) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_gets == NULL) + return -1; + return bcgbl->c_bio_gets(BIO_get_data(bio), buf, size); +} + +static int bio_core_puts(BIO *bio, const char *str) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_puts == NULL) + return -1; + return bcgbl->c_bio_puts(BIO_get_data(bio), str); +} + +static int bio_core_new(BIO *bio) +{ + BIO_set_init(bio, 1); + + return 1; +} + +static int bio_core_free(BIO *bio) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL) + return 0; + + BIO_set_init(bio, 0); + bcgbl->c_bio_free(BIO_get_data(bio)); + + return 1; +} + +static const BIO_METHOD corebiometh = { + BIO_TYPE_CORE_TO_PROV, + "BIO to Core filter", + bio_core_write_ex, + NULL, + bio_core_read_ex, + NULL, + bio_core_puts, + bio_core_gets, + bio_core_ctrl, + bio_core_new, + bio_core_free, + NULL, +}; + +const BIO_METHOD *BIO_s_core(void) +{ + return &corebiometh; +} + +BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio) +{ + BIO *outbio; + BIO_CORE_GLOBALS *bcgbl = get_globals(libctx); + + /* Check the library context has been initialised with the callbacks */ + if (bcgbl == NULL || (bcgbl->c_bio_write_ex == NULL && bcgbl->c_bio_read_ex == NULL)) + return NULL; + + if ((outbio = BIO_new_ex(libctx, BIO_s_core())) == NULL) + return NULL; + + if (!bcgbl->c_bio_up_ref(corebio)) { + BIO_free(outbio); + return NULL; + } + BIO_set_data(outbio, corebio); + return outbio; +} + +int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(libctx); + + if (bcgbl == NULL) + return 0; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_BIO_READ_EX: + if (bcgbl->c_bio_read_ex == NULL) + bcgbl->c_bio_read_ex = OSSL_FUNC_BIO_read_ex(fns); + break; + case OSSL_FUNC_BIO_WRITE_EX: + if (bcgbl->c_bio_write_ex == NULL) + bcgbl->c_bio_write_ex = OSSL_FUNC_BIO_write_ex(fns); + break; + case OSSL_FUNC_BIO_GETS: + if (bcgbl->c_bio_gets == NULL) + bcgbl->c_bio_gets = OSSL_FUNC_BIO_gets(fns); + break; + case OSSL_FUNC_BIO_PUTS: + if (bcgbl->c_bio_puts == NULL) + bcgbl->c_bio_puts = OSSL_FUNC_BIO_puts(fns); + break; + case OSSL_FUNC_BIO_CTRL: + if (bcgbl->c_bio_ctrl == NULL) + bcgbl->c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns); + break; + case OSSL_FUNC_BIO_UP_REF: + if (bcgbl->c_bio_up_ref == NULL) + bcgbl->c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns); + break; + case OSSL_FUNC_BIO_FREE: + if (bcgbl->c_bio_free == NULL) + bcgbl->c_bio_free = OSSL_FUNC_BIO_free(fns); + break; + } + } + + return 1; +} diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -1,7 +1,7 @@ /* - * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -57,6 +57,8 @@ static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int dgram_sctp_new(BIO *h); static int dgram_sctp_free(BIO *data); +static int dgram_sctp_wait_for_dry(BIO *b); +static int dgram_sctp_msg_waiting(BIO *b); # ifdef SCTP_AUTHENTICATION_EVENT static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp); @@ -70,10 +72,8 @@ static const BIO_METHOD methods_dgramp = { BIO_TYPE_DGRAM, "datagram socket", - /* TODO: Convert to new style write function */ bwrite_conv, dgram_write, - /* TODO: Convert to new style read function */ bread_conv, dgram_read, dgram_puts, @@ -88,10 +88,8 @@ static const BIO_METHOD methods_dgramp_sctp = { BIO_TYPE_DGRAM_SCTP, "datagram sctp socket", - /* TODO: Convert to new style write function */ bwrite_conv, dgram_sctp_write, - /* TODO: Convert to new style write function */ bread_conv, dgram_sctp_read, dgram_sctp_puts, @@ -128,7 +126,7 @@ struct bio_dgram_sctp_sndinfo sndinfo; struct bio_dgram_sctp_rcvinfo rcvinfo; struct bio_dgram_sctp_prinfo prinfo; - void (*handle_notifications) (BIO *bio, void *context, void *buf); + BIO_dgram_sctp_notification_handler_fn handle_notifications; void *notification_context; int in_handshake; int ccs_rcvd; @@ -197,12 +195,6 @@ { # if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; - union { - size_t s; - int i; - } sz = { - 0 - }; /* Is a timer active? */ if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { @@ -212,21 +204,21 @@ # ifdef OPENSSL_SYS_WINDOWS int timeout; - sz.i = sizeof(timeout); + int sz = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, &sz.i) < 0) { + (void *)&timeout, &sz) < 0) { perror("getsockopt"); } else { data->socket_timeout.tv_sec = timeout / 1000; data->socket_timeout.tv_usec = (timeout % 1000) * 1000; } # else - sz.i = sizeof(data->socket_timeout); + socklen_t sz = sizeof(data->socket_timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - &(data->socket_timeout), (void *)&sz) < 0) { + &(data->socket_timeout), &sz) < 0) { perror("getsockopt"); - } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) - OPENSSL_assert(sz.s <= sizeof(data->socket_timeout)); + } else + OPENSSL_assert(sz <= sizeof(data->socket_timeout)); # endif /* Get current time */ @@ -609,19 +601,14 @@ break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: { - union { - size_t s; - int i; - } sz = { - 0 - }; # ifdef OPENSSL_SYS_WINDOWS + int sz = 0; int timeout; struct timeval *tv = (struct timeval *)ptr; - sz.i = sizeof(timeout); + sz = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, &sz.i) < 0) { + (void *)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } else { @@ -630,16 +617,15 @@ ret = sizeof(*tv); } # else - sz.i = sizeof(struct timeval); + socklen_t sz = sizeof(struct timeval); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - ptr, (void *)&sz) < 0) { + ptr, &sz) < 0) { perror("getsockopt"); ret = -1; - } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) { - OPENSSL_assert(sz.s <= sizeof(struct timeval)); - ret = (int)sz.s; - } else - ret = sz.i; + } else { + OPENSSL_assert(sz <= sizeof(struct timeval)); + ret = (int)sz; + } # endif } break; @@ -666,19 +652,14 @@ break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: { - union { - size_t s; - int i; - } sz = { - 0 - }; # ifdef OPENSSL_SYS_WINDOWS + int sz = 0; int timeout; struct timeval *tv = (struct timeval *)ptr; - sz.i = sizeof(timeout); + sz = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - (void *)&timeout, &sz.i) < 0) { + (void *)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } else { @@ -687,16 +668,15 @@ ret = sizeof(*tv); } # else - sz.i = sizeof(struct timeval); + socklen_t sz = sizeof(struct timeval); if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - ptr, (void *)&sz) < 0) { + ptr, &sz) < 0) { perror("getsockopt"); ret = -1; - } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) { - OPENSSL_assert(sz.s <= sizeof(struct timeval)); - ret = (int)sz.s; - } else - ret = sz.i; + } else { + OPENSSL_assert(sz <= sizeof(struct timeval)); + ret = (int)sz; + } # endif } break; @@ -845,8 +825,8 @@ sizeof(struct sctp_authchunk)); if (ret < 0) { BIO_vfree(bio); - BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); - ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel"); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + "Ensure SCTP AUTH chunks are enabled in kernel"); return NULL; } auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE; @@ -855,8 +835,8 @@ sizeof(struct sctp_authchunk)); if (ret < 0) { BIO_vfree(bio); - BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); - ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel"); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + "Ensure SCTP AUTH chunks are enabled in kernel"); return NULL; } @@ -893,10 +873,9 @@ if (!auth_data || !auth_forward) { BIO_vfree(bio); - BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); - ERR_add_error_data(1, - "Ensure SCTP AUTH chunks are enabled on the " - "underlying socket"); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + "Ensure SCTP AUTH chunks are enabled on the " + "underlying socket"); return NULL; } @@ -960,7 +939,7 @@ bi->init = 0; bi->num = 0; if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) { - BIOerr(BIO_F_DGRAM_SCTP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } # ifdef SCTP_PR_SCTP_NONE @@ -1011,7 +990,6 @@ int ret = 0, n = 0, i, optval; socklen_t optlen; bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; - union sctp_notification *snp; struct msghdr msg; struct iovec iov; struct cmsghdr *cmsg; @@ -1077,8 +1055,10 @@ } if (msg.msg_flags & MSG_NOTIFICATION) { - snp = (union sctp_notification *)out; - if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) { + union sctp_notification snp; + + memcpy(&snp, out, sizeof(snp)); + if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) { # ifdef SCTP_EVENT struct sctp_event event; # else @@ -1118,17 +1098,19 @@ # endif } # ifdef SCTP_AUTHENTICATION_EVENT - if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) - dgram_sctp_handle_auth_free_key_event(b, snp); + if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, &snp); # endif if (data->handle_notifications != NULL) data->handle_notifications(b, data->notification_context, (void *)out); + memset(&snp, 0, sizeof(snp)); memset(out, 0, outl); - } else + } else { ret += n; + } } while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl)); @@ -1195,7 +1177,7 @@ (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); authchunks = OPENSSL_malloc(optlen); if (authchunks == NULL) { - BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return -1; } memset(authchunks, 0, optlen); @@ -1215,7 +1197,7 @@ OPENSSL_free(authchunks); if (!auth_data || !auth_forward) { - BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); return -1; } @@ -1566,6 +1548,10 @@ else data->save_shutdown = 0; break; + case BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY: + return dgram_sctp_wait_for_dry(b); + case BIO_CTRL_DGRAM_SCTP_MSG_WAITING: + return dgram_sctp_msg_waiting(b); default: /* @@ -1578,11 +1564,8 @@ } int BIO_dgram_sctp_notification_cb(BIO *b, - void (*handle_notifications) (BIO *bio, - void - *context, - void *buf), - void *context) + BIO_dgram_sctp_notification_handler_fn handle_notifications, + void *context) { bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; @@ -1609,6 +1592,11 @@ * 1 when dry */ int BIO_dgram_sctp_wait_for_dry(BIO *b) +{ + return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY, 0, NULL); +} + +static int dgram_sctp_wait_for_dry(BIO *b) { int is_dry = 0; int sockflags = 0; @@ -1767,6 +1755,11 @@ } int BIO_dgram_sctp_msg_waiting(BIO *b) +{ + return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_MSG_WAITING, 0, NULL); +} + +static int dgram_sctp_msg_waiting(BIO *b) { int n, sockflags; union sctp_notification snp; @@ -1907,22 +1900,22 @@ { # if defined(_WIN32) SYSTEMTIME st; - union { - unsigned __int64 ul; - FILETIME ft; - } now; + unsigned __int64 now_ul; + FILETIME now_ft; GetSystemTime(&st); - SystemTimeToFileTime(&st, &now.ft); + SystemTimeToFileTime(&st, &now_ft); + now_ul = ((unsigned __int64)now_ft.dwHighDateTime << 32) | now_ft.dwLowDateTime; # ifdef __MINGW32__ - now.ul -= 116444736000000000ULL; + now_ul -= 116444736000000000ULL; # else - now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ + now_ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ # endif - t->tv_sec = (long)(now.ul / 10000000); - t->tv_usec = ((int)(now.ul % 10000000)) / 10; + t->tv_sec = (long)(now_ul / 10000000); + t->tv_usec = ((int)(now_ul % 10000000)) / 10; # else - gettimeofday(t, NULL); + if (gettimeofday(t, NULL) < 0) + perror("gettimeofday"); # endif } diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c --- a/crypto/bio/bss_fd.c +++ b/crypto/bio/bss_fd.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -60,10 +60,8 @@ static const BIO_METHOD methods_fdp = { BIO_TYPE_FD, "file descriptor", - /* TODO: Convert to new style write function */ bwrite_conv, fd_write, - /* TODO: Convert to new style read function */ bread_conv, fd_read, fd_puts, @@ -94,7 +92,7 @@ bi->init = 0; bi->num = -1; bi->ptr = NULL; - bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */ + bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* essentially redundant */ return 1; } @@ -107,7 +105,7 @@ UP_close(a->num); } a->init = 0; - a->flags = BIO_FLAGS_UPLINK; + a->flags = BIO_FLAGS_UPLINK_INTERNAL; } return 1; } @@ -189,7 +187,7 @@ ret = 1; break; case BIO_CTRL_EOF: - ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; break; default: ret = 0; diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -42,10 +42,8 @@ static const BIO_METHOD methods_filep = { BIO_TYPE_FILE, "FILE pointer", - /* TODO: Convert to new style write function */ bwrite_conv, file_write, - /* TODO: Convert to new style read function */ bread_conv, file_read, file_puts, @@ -66,16 +64,17 @@ fp_flags |= BIO_FP_TEXT; if (file == NULL) { - SYSerr(SYS_F_FOPEN, get_last_sys_error()); - ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fopen(%s, %s)", + filename, mode); if (errno == ENOENT #ifdef ENXIO || errno == ENXIO #endif ) - BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); + ERR_raise(ERR_LIB_BIO, BIO_R_NO_SUCH_FILE); else - BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); return NULL; } if ((ret = BIO_new(BIO_s_file())) == NULL) { @@ -83,8 +82,8 @@ return NULL; } - BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage - * UPLINK */ + /* we did fopen -> we disengage UPLINK */ + BIO_clear_flags(ret, BIO_FLAGS_UPLINK_INTERNAL); BIO_set_fp(ret, file, fp_flags); return ret; } @@ -97,7 +96,7 @@ return NULL; /* redundant flag, left for documentation purposes */ - BIO_set_flags(ret, BIO_FLAGS_UPLINK); + BIO_set_flags(ret, BIO_FLAGS_UPLINK_INTERNAL); BIO_set_fp(ret, stream, close_flag); return ret; } @@ -112,7 +111,7 @@ bi->init = 0; bi->num = 0; bi->ptr = NULL; - bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */ + bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* default to UPLINK */ return 1; } @@ -122,12 +121,12 @@ return 0; if (a->shutdown) { if ((a->init) && (a->ptr != NULL)) { - if (a->flags & BIO_FLAGS_UPLINK) + if (a->flags & BIO_FLAGS_UPLINK_INTERNAL) UP_fclose(a->ptr); else fclose(a->ptr); a->ptr = NULL; - a->flags = BIO_FLAGS_UPLINK; + a->flags = BIO_FLAGS_UPLINK_INTERNAL; } a->init = 0; } @@ -139,15 +138,16 @@ int ret = 0; if (b->init && (out != NULL)) { - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = UP_fread(out, 1, (int)outl, b->ptr); else ret = fread(out, 1, (int)outl, (FILE *)b->ptr); if (ret == 0 - && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) : - ferror((FILE *)b->ptr)) { - SYSerr(SYS_F_FREAD, get_last_sys_error()); - BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB); + && (b->flags & BIO_FLAGS_UPLINK_INTERNAL + ? UP_ferror((FILE *)b->ptr) : ferror((FILE *)b->ptr))) { + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fread()"); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); ret = -1; } } @@ -159,7 +159,7 @@ int ret = 0; if (b->init && (in != NULL)) { - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = UP_fwrite(in, (int)inl, 1, b->ptr); else ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr); @@ -186,20 +186,20 @@ switch (cmd) { case BIO_C_FILE_SEEK: case BIO_CTRL_RESET: - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = (long)UP_fseek(b->ptr, num, 0); else ret = (long)fseek(fp, num, 0); break; case BIO_CTRL_EOF: - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = (long)UP_feof(fp); else ret = (long)feof(fp); break; case BIO_C_FILE_TELL: case BIO_CTRL_INFO: - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = UP_ftell(b->ptr); else ret = ftell(fp); @@ -209,22 +209,22 @@ b->shutdown = (int)num & BIO_CLOSE; b->ptr = ptr; b->init = 1; -# if BIO_FLAGS_UPLINK!=0 +# if BIO_FLAGS_UPLINK_INTERNAL!=0 # if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES) # define _IOB_ENTRIES 20 # endif /* Safety net to catch purely internal BIO_set_fp calls */ -# if defined(_MSC_VER) && _MSC_VER>=1900 +# if (defined(_MSC_VER) && _MSC_VER>=1900) || defined(__BORLANDC__) if (ptr == stdin || ptr == stdout || ptr == stderr) - BIO_clear_flags(b, BIO_FLAGS_UPLINK); + BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL); # elif defined(_IOB_ENTRIES) if ((size_t)ptr >= (size_t)stdin && (size_t)ptr < (size_t)(stdin + _IOB_ENTRIES)) - BIO_clear_flags(b, BIO_FLAGS_UPLINK); + BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL); # endif # endif # ifdef UP_fsetmod - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b')); else # endif @@ -235,6 +235,15 @@ _setmode(fd, _O_TEXT); else _setmode(fd, _O_BINARY); + /* + * Reports show that ftell() isn't trustable in text mode. + * This has been confirmed as a bug in the Universal C RTL, see + * https://developercommunity.visualstudio.com/content/problem/425878/fseek-ftell-fail-in-text-mode-for-unix-style-text.html + * The suggested work-around from Microsoft engineering is to + * turn off buffering until the bug is resolved. + */ + if ((num & BIO_FP_TEXT) != 0) + setvbuf((FILE *)ptr, NULL, _IONBF, 0); # elif defined(OPENSSL_SYS_MSDOS) int fd = fileno((FILE *)ptr); /* Set correct text/binary mode */ @@ -270,7 +279,7 @@ else if (num & BIO_FP_READ) OPENSSL_strlcpy(p, "r", sizeof(p)); else { - BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE); + ERR_raise(ERR_LIB_BIO, BIO_R_BAD_FOPEN_MODE); ret = 0; break; } @@ -285,16 +294,17 @@ # endif fp = openssl_fopen(ptr, p); if (fp == NULL) { - SYSerr(SYS_F_FOPEN, get_last_sys_error()); - ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); - BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fopen(%s, %s)", + ptr, p); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); ret = 0; break; } b->ptr = fp; b->init = 1; - BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage - * UPLINK */ + /* we did fopen -> we disengage UPLINK */ + BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL); break; case BIO_C_GET_FILE_PTR: /* the ptr parameter is actually a FILE ** in this case. */ @@ -310,12 +320,12 @@ b->shutdown = (int)num; break; case BIO_CTRL_FLUSH: - st = b->flags & BIO_FLAGS_UPLINK + st = b->flags & BIO_FLAGS_UPLINK_INTERNAL ? UP_fflush(b->ptr) : fflush((FILE *)b->ptr); if (st == EOF) { - SYSerr(SYS_F_FFLUSH, get_last_sys_error()); - ERR_add_error_data(1, "fflush()"); - BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fflush()"); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); ret = 0; } break; @@ -339,7 +349,7 @@ int ret = 0; buf[0] = '\0'; - if (bp->flags & BIO_FLAGS_UPLINK) { + if (bp->flags & BIO_FLAGS_UPLINK_INTERNAL) { if (!UP_fgets(buf, size, bp->ptr)) goto err; } else { @@ -395,10 +405,8 @@ static const BIO_METHOD methods_filep = { BIO_TYPE_FILE, "FILE pointer", - /* TODO: Convert to new style write function */ bwrite_conv, file_write, - /* TODO: Convert to new style read function */ bread_conv, file_read, file_puts, diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -87,7 +87,6 @@ static const BIO_METHOD methods_slg = { BIO_TYPE_MEM, "syslog", - /* TODO: Convert to new style write function */ bwrite_conv, slg_write, NULL, /* slg_write_old, */ @@ -196,8 +195,10 @@ /* The default */ }; + if (inl < 0) + return 0; if ((buf = OPENSSL_malloc(inl + 1)) == NULL) { - BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } memcpy(buf, in, inl); diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c --- a/crypto/bio/bss_mem.c +++ b/crypto/bio/bss_mem.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -26,10 +26,8 @@ static const BIO_METHOD mem_method = { BIO_TYPE_MEM, "memory buffer", - /* TODO: Convert to new style write function */ bwrite_conv, mem_write, - /* TODO: Convert to new style read function */ bread_conv, mem_read, mem_puts, @@ -43,10 +41,8 @@ static const BIO_METHOD secmem_method = { BIO_TYPE_MEM, "secure memory buffer", - /* TODO: Convert to new style write function */ bwrite_conv, mem_write, - /* TODO: Convert to new style read function */ bread_conv, mem_read, mem_puts, @@ -91,7 +87,7 @@ size_t sz; if (buf == NULL) { - BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER); + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); return NULL; } sz = (len < 0) ? strlen(buf) : (size_t)len; @@ -176,6 +172,7 @@ /* * Reallocate memory buffer if read pointer differs + * NOT FOR RDONLY */ static int mem_buf_sync(BIO *b) { @@ -220,17 +217,17 @@ int blen; BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; - if (in == NULL) { - BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); - goto end; - } if (b->flags & BIO_FLAGS_MEM_RDONLY) { - BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO); + ERR_raise(ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO); goto end; } BIO_clear_retry_flags(b); if (inl == 0) return 0; + if (in == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + goto end; + } blen = bbm->readp->length; mem_buf_sync(b); if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) @@ -247,12 +244,18 @@ long ret = 1; char **pptr; BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; - BUF_MEM *bm; + BUF_MEM *bm, *bo; /* bio_mem, bio_other */ + long off, remain; - if (b->flags & BIO_FLAGS_MEM_RDONLY) + if (b->flags & BIO_FLAGS_MEM_RDONLY) { bm = bbm->buf; - else + bo = bbm->readp; + } else { bm = bbm->readp; + bo = bbm->buf; + } + off = (bm->data == bo->data) ? 0 : bm->data - bo->data; + remain = bm->length; switch (cmd) { case BIO_CTRL_RESET: @@ -270,6 +273,18 @@ } } break; + case BIO_C_FILE_SEEK: + if (num < 0 || num > off + remain) + return -1; /* Can't see outside of the current buffer */ + + bm->data = (num != 0) ? bo->data + num : bo->data; + bm->length = bo->length - num; + bm->max = bo->max - num; + off = num; + /* FALLTHRU */ + case BIO_C_FILE_TELL: + ret = off; + break; case BIO_CTRL_EOF: ret = (long)(bm->length == 0); break; @@ -280,7 +295,7 @@ ret = (long)bm->length; if (ptr != NULL) { pptr = (char **)ptr; - *pptr = (char *)bm->data; + *pptr = (char *)(bm->data); } break; case BIO_C_SET_BUF_MEM: diff --git a/crypto/bio/bss_null.c b/crypto/bio/bss_null.c --- a/crypto/bio/bss_null.c +++ b/crypto/bio/bss_null.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -20,10 +20,8 @@ static const BIO_METHOD null_method = { BIO_TYPE_NULL, "NULL", - /* TODO: Convert to new style write function */ bwrite_conv, null_write, - /* TODO: Convert to new style read function */ bread_conv, null_read, null_puts, diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c --- a/crypto/bio/bss_sock.c +++ b/crypto/bio/bss_sock.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -11,6 +11,7 @@ #include #include "bio_local.h" #include "internal/cryptlib.h" +#include "internal/ktls.h" #ifndef OPENSSL_NO_SOCK @@ -37,10 +38,8 @@ static const BIO_METHOD methods_sockp = { BIO_TYPE_SOCKET, "socket", - /* TODO: Convert to new style write function */ bwrite_conv, sock_write, - /* TODO: Convert to new style read function */ bread_conv, sock_read, sock_puts, @@ -64,6 +63,17 @@ if (ret == NULL) return NULL; BIO_set_fd(ret, fd, close_flag); +# ifndef OPENSSL_NO_KTLS + { + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(fd); + } +# endif return ret; } @@ -96,7 +106,12 @@ if (out != NULL) { clear_socket_error(); - ret = readsocket(b->num, out, outl); +# ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_recv(b)) + ret = ktls_read_record(b->num, out, outl); + else +# endif + ret = readsocket(b->num, out, outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -110,10 +125,20 @@ static int sock_write(BIO *b, const char *in, int inl) { - int ret; + int ret = 0; clear_socket_error(); - ret = writesocket(b->num, in, inl); +# ifndef OPENSSL_NO_KTLS + if (BIO_should_ktls_ctrl_msg_flag(b)) { + unsigned char record_type = (intptr_t)b->ptr; + ret = ktls_send_ctrl_message(b->num, record_type, in, inl); + if (ret >= 0) { + ret = inl; + BIO_clear_ktls_ctrl_msg_flag(b); + } + } else +# endif + ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -126,6 +151,9 @@ { long ret = 1; int *ip; +# ifndef OPENSSL_NO_KTLS + ktls_crypto_info_t *crypto_info; +# endif switch (cmd) { case BIO_C_SET_FD: @@ -153,8 +181,29 @@ case BIO_CTRL_FLUSH: ret = 1; break; +# ifndef OPENSSL_NO_KTLS + case BIO_CTRL_SET_KTLS: + crypto_info = (ktls_crypto_info_t *)ptr; + ret = ktls_start(b->num, crypto_info, num); + if (ret) + BIO_set_ktls_flag(b, num); + break; + case BIO_CTRL_GET_KTLS_SEND: + return BIO_should_ktls_flag(b, 1) != 0; + case BIO_CTRL_GET_KTLS_RECV: + return BIO_should_ktls_flag(b, 0) != 0; + case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: + BIO_set_ktls_ctrl_msg_flag(b); + b->ptr = (void *)num; + ret = 0; + break; + case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: + BIO_clear_ktls_ctrl_msg_flag(b); + ret = 0; + break; +# endif case BIO_CTRL_EOF: - ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; break; default: ret = 0; diff --git a/crypto/bio/build.info b/crypto/bio/build.info --- a/crypto/bio/build.info +++ b/crypto/bio/build.info @@ -1,8 +1,18 @@ LIBS=../../libcrypto + +# Base library SOURCE[../../libcrypto]=\ bio_lib.c bio_cb.c bio_err.c \ - bss_mem.c bss_null.c bss_fd.c \ - bss_file.c bss_sock.c bss_conn.c \ - bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \ - b_sock.c b_sock2.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \ - bss_dgram.c bio_meth.c bf_lbuf.c + bio_print.c bio_dump.c bio_addr.c \ + bio_sock.c bio_sock2.c \ + bio_meth.c ossl_core_bio.c + +# Source / sink implementations +SOURCE[../../libcrypto]=\ + bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \ + bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \ + bss_log.c bss_core.c + +# Filters +SOURCE[../../libcrypto]=\ + bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c bf_prefix.c bf_readbuff.c diff --git a/crypto/bio/ossl_core_bio.c b/crypto/bio/ossl_core_bio.c new file mode 100644 --- /dev/null +++ b/crypto/bio/ossl_core_bio.c @@ -0,0 +1,124 @@ +/* + * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "bio_local.h" + +/*- + * Core BIO structure + * This is distinct from a BIO to prevent casting between the two which could + * lead to versioning problems. + */ +struct ossl_core_bio_st { + CRYPTO_REF_COUNT ref_cnt; + CRYPTO_RWLOCK *ref_lock; + BIO *bio; +}; + +static OSSL_CORE_BIO *core_bio_new(void) +{ + OSSL_CORE_BIO *cb = OPENSSL_malloc(sizeof(*cb)); + + if (cb == NULL || (cb->ref_lock = CRYPTO_THREAD_lock_new()) == NULL) { + OPENSSL_free(cb); + return NULL; + } + cb->ref_cnt = 1; + return cb; +} + +int ossl_core_bio_up_ref(OSSL_CORE_BIO *cb) +{ + int ref = 0; + + return CRYPTO_UP_REF(&cb->ref_cnt, &ref, cb->ref_lock); +} + +int ossl_core_bio_free(OSSL_CORE_BIO *cb) +{ + int ref = 0, res = 1; + + if (cb != NULL) { + CRYPTO_DOWN_REF(&cb->ref_cnt, &ref, cb->ref_lock); + if (ref <= 0) { + res = BIO_free(cb->bio); + CRYPTO_THREAD_lock_free(cb->ref_lock); + OPENSSL_free(cb); + } + } + return res; +} + +OSSL_CORE_BIO *ossl_core_bio_new_from_bio(BIO *bio) +{ + OSSL_CORE_BIO *cb = core_bio_new(); + + if (cb == NULL || !BIO_up_ref(bio)) { + ossl_core_bio_free(cb); + return NULL; + } + cb->bio = bio; + return cb; +} + +static OSSL_CORE_BIO *core_bio_new_from_new_bio(BIO *bio) +{ + OSSL_CORE_BIO *cb = NULL; + + if (bio == NULL) + return NULL; + if ((cb = core_bio_new()) == NULL) { + BIO_free(bio); + return NULL; + } + cb->bio = bio; + return cb; +} + +OSSL_CORE_BIO *ossl_core_bio_new_file(const char *filename, const char *mode) +{ + return core_bio_new_from_new_bio(BIO_new_file(filename, mode)); +} + +OSSL_CORE_BIO *ossl_core_bio_new_mem_buf(const void *buf, int len) +{ + return core_bio_new_from_new_bio(BIO_new_mem_buf(buf, len)); +} + +int ossl_core_bio_read_ex(OSSL_CORE_BIO *cb, void *data, size_t dlen, + size_t *readbytes) +{ + return BIO_read_ex(cb->bio, data, dlen, readbytes); +} + +int ossl_core_bio_write_ex(OSSL_CORE_BIO *cb, const void *data, size_t dlen, + size_t *written) +{ + return BIO_write_ex(cb->bio, data, dlen, written); +} + +int ossl_core_bio_gets(OSSL_CORE_BIO *cb, char *buf, int size) +{ + return BIO_gets(cb->bio, buf, size); +} + +int ossl_core_bio_puts(OSSL_CORE_BIO *cb, const char *buf) +{ + return BIO_puts(cb->bio, buf); +} + +long ossl_core_bio_ctrl(OSSL_CORE_BIO *cb, int cmd, long larg, void *parg) +{ + return BIO_ctrl(cb->bio, cmd, larg, parg); +} + +int ossl_core_bio_vprintf(OSSL_CORE_BIO *cb, const char *format, va_list args) +{ + return BIO_vprintf(cb->bio, format, args); +} diff --git a/crypto/blake2/blake2_impl.h b/crypto/blake2/blake2_impl.h deleted file mode 100644 --- a/crypto/blake2/blake2_impl.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2016-2017 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 - */ - -/* - * Derived from the BLAKE2 reference implementation written by Samuel Neves. - * Copyright 2012, Samuel Neves - * More information about the BLAKE2 hash function and its implementations - * can be found at https://blake2.net. - */ - -#include - -static ossl_inline uint32_t load32(const uint8_t *src) -{ - const union { - long one; - char little; - } is_endian = { 1 }; - - if (is_endian.little) { - uint32_t w; - memcpy(&w, src, sizeof(w)); - return w; - } else { - uint32_t w = ((uint32_t)src[0]) - | ((uint32_t)src[1] << 8) - | ((uint32_t)src[2] << 16) - | ((uint32_t)src[3] << 24); - return w; - } -} - -static ossl_inline uint64_t load64(const uint8_t *src) -{ - const union { - long one; - char little; - } is_endian = { 1 }; - - if (is_endian.little) { - uint64_t w; - memcpy(&w, src, sizeof(w)); - return w; - } else { - uint64_t w = ((uint64_t)src[0]) - | ((uint64_t)src[1] << 8) - | ((uint64_t)src[2] << 16) - | ((uint64_t)src[3] << 24) - | ((uint64_t)src[4] << 32) - | ((uint64_t)src[5] << 40) - | ((uint64_t)src[6] << 48) - | ((uint64_t)src[7] << 56); - return w; - } -} - -static ossl_inline void store32(uint8_t *dst, uint32_t w) -{ - const union { - long one; - char little; - } is_endian = { 1 }; - - if (is_endian.little) { - memcpy(dst, &w, sizeof(w)); - } else { - uint8_t *p = (uint8_t *)dst; - int i; - - for (i = 0; i < 4; i++) - p[i] = (uint8_t)(w >> (8 * i)); - } -} - -static ossl_inline void store64(uint8_t *dst, uint64_t w) -{ - const union { - long one; - char little; - } is_endian = { 1 }; - - if (is_endian.little) { - memcpy(dst, &w, sizeof(w)); - } else { - uint8_t *p = (uint8_t *)dst; - int i; - - for (i = 0; i < 8; i++) - p[i] = (uint8_t)(w >> (8 * i)); - } -} - -static ossl_inline uint64_t load48(const uint8_t *src) -{ - uint64_t w = ((uint64_t)src[0]) - | ((uint64_t)src[1] << 8) - | ((uint64_t)src[2] << 16) - | ((uint64_t)src[3] << 24) - | ((uint64_t)src[4] << 32) - | ((uint64_t)src[5] << 40); - return w; -} - -static ossl_inline void store48(uint8_t *dst, uint64_t w) -{ - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)w; - p[1] = (uint8_t)(w>>8); - p[2] = (uint8_t)(w>>16); - p[3] = (uint8_t)(w>>24); - p[4] = (uint8_t)(w>>32); - p[5] = (uint8_t)(w>>40); -} - -static ossl_inline uint32_t rotr32(const uint32_t w, const unsigned int c) -{ - return (w >> c) | (w << (32 - c)); -} - -static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c) -{ - return (w >> c) | (w << (64 - c)); -} diff --git a/crypto/blake2/blake2_local.h b/crypto/blake2/blake2_local.h deleted file mode 100644 --- a/crypto/blake2/blake2_local.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2016-2017 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 - */ - -/* - * Derived from the BLAKE2 reference implementation written by Samuel Neves. - * Copyright 2012, Samuel Neves - * More information about the BLAKE2 hash function and its implementations - * can be found at https://blake2.net. - */ - -#include - -#define BLAKE2S_BLOCKBYTES 64 -#define BLAKE2S_OUTBYTES 32 -#define BLAKE2S_KEYBYTES 32 -#define BLAKE2S_SALTBYTES 8 -#define BLAKE2S_PERSONALBYTES 8 - -#define BLAKE2B_BLOCKBYTES 128 -#define BLAKE2B_OUTBYTES 64 -#define BLAKE2B_KEYBYTES 64 -#define BLAKE2B_SALTBYTES 16 -#define BLAKE2B_PERSONALBYTES 16 - -struct blake2s_param_st { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint8_t leaf_length[4];/* 8 */ - uint8_t node_offset[6];/* 14 */ - uint8_t node_depth; /* 15 */ - uint8_t inner_length; /* 16 */ - uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ - uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ -}; - -typedef struct blake2s_param_st BLAKE2S_PARAM; - -struct blake2s_ctx_st { - uint32_t h[8]; - uint32_t t[2]; - uint32_t f[2]; - uint8_t buf[BLAKE2S_BLOCKBYTES]; - size_t buflen; -}; - -struct blake2b_param_st { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint8_t leaf_length[4];/* 8 */ - uint8_t node_offset[8];/* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ -}; - -typedef struct blake2b_param_st BLAKE2B_PARAM; - -struct blake2b_ctx_st { - uint64_t h[8]; - uint64_t t[2]; - uint64_t f[2]; - uint8_t buf[BLAKE2B_BLOCKBYTES]; - size_t buflen; -}; - -#define BLAKE2B_DIGEST_LENGTH 64 -#define BLAKE2S_DIGEST_LENGTH 32 - -typedef struct blake2s_ctx_st BLAKE2S_CTX; -typedef struct blake2b_ctx_st BLAKE2B_CTX; - -int BLAKE2b_Init(BLAKE2B_CTX *c); -int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen); -int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c); - -int BLAKE2s_Init(BLAKE2S_CTX *c); -int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen); -int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c); diff --git a/crypto/blake2/blake2b.c b/crypto/blake2/blake2b.c deleted file mode 100644 --- a/crypto/blake2/blake2b.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2016-2019 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 - */ - -/* - * Derived from the BLAKE2 reference implementation written by Samuel Neves. - * Copyright 2012, Samuel Neves - * More information about the BLAKE2 hash function and its implementations - * can be found at https://blake2.net. - */ - -#include -#include -#include - -#include "blake2_local.h" -#include "blake2_impl.h" - -static const uint64_t blake2b_IV[8] = -{ - 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, - 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, - 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL -}; - -static const uint8_t blake2b_sigma[12][16] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } -}; - -/* Set that it's the last block we'll compress */ -static ossl_inline void blake2b_set_lastblock(BLAKE2B_CTX *S) -{ - S->f[0] = -1; -} - -/* Initialize the hashing state. */ -static ossl_inline void blake2b_init0(BLAKE2B_CTX *S) -{ - int i; - - memset(S, 0, sizeof(BLAKE2B_CTX)); - for (i = 0; i < 8; ++i) { - S->h[i] = blake2b_IV[i]; - } -} - -/* init xors IV with input parameter block */ -static void blake2b_init_param(BLAKE2B_CTX *S, const BLAKE2B_PARAM *P) -{ - size_t i; - const uint8_t *p = (const uint8_t *)(P); - blake2b_init0(S); - - /* The param struct is carefully hand packed, and should be 64 bytes on - * every platform. */ - assert(sizeof(BLAKE2B_PARAM) == 64); - /* IV XOR ParamBlock */ - for (i = 0; i < 8; ++i) { - S->h[i] ^= load64(p + sizeof(S->h[i]) * i); - } -} - -/* Initialize the hashing context. Always returns 1. */ -int BLAKE2b_Init(BLAKE2B_CTX *c) -{ - BLAKE2B_PARAM P[1]; - P->digest_length = BLAKE2B_DIGEST_LENGTH; - P->key_length = 0; - P->fanout = 1; - P->depth = 1; - store32(P->leaf_length, 0); - store64(P->node_offset, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->reserved, 0, sizeof(P->reserved)); - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - blake2b_init_param(c, P); - return 1; -} - -/* Permute the state while xoring in the block of data. */ -static void blake2b_compress(BLAKE2B_CTX *S, - const uint8_t *blocks, - size_t len) -{ - uint64_t m[16]; - uint64_t v[16]; - int i; - size_t increment; - - /* - * There are two distinct usage vectors for this function: - * - * a) BLAKE2b_Update uses it to process complete blocks, - * possibly more than one at a time; - * - * b) BLAK2b_Final uses it to process last block, always - * single but possibly incomplete, in which case caller - * pads input with zeros. - */ - assert(len < BLAKE2B_BLOCKBYTES || len % BLAKE2B_BLOCKBYTES == 0); - - /* - * Since last block is always processed with separate call, - * |len| not being multiple of complete blocks can be observed - * only with |len| being less than BLAKE2B_BLOCKBYTES ("less" - * including even zero), which is why following assignment doesn't - * have to reside inside the main loop below. - */ - increment = len < BLAKE2B_BLOCKBYTES ? len : BLAKE2B_BLOCKBYTES; - - for (i = 0; i < 8; ++i) { - v[i] = S->h[i]; - } - - do { - for (i = 0; i < 16; ++i) { - m[i] = load64(blocks + i * sizeof(m[i])); - } - - /* blake2b_increment_counter */ - S->t[0] += increment; - S->t[1] += (S->t[0] < increment); - - v[8] = blake2b_IV[0]; - v[9] = blake2b_IV[1]; - v[10] = blake2b_IV[2]; - v[11] = blake2b_IV[3]; - v[12] = S->t[0] ^ blake2b_IV[4]; - v[13] = S->t[1] ^ blake2b_IV[5]; - v[14] = S->f[0] ^ blake2b_IV[6]; - v[15] = S->f[1] ^ blake2b_IV[7]; -#define G(r,i,a,b,c,d) \ - do { \ - a = a + b + m[blake2b_sigma[r][2*i+0]]; \ - d = rotr64(d ^ a, 32); \ - c = c + d; \ - b = rotr64(b ^ c, 24); \ - a = a + b + m[blake2b_sigma[r][2*i+1]]; \ - d = rotr64(d ^ a, 16); \ - c = c + d; \ - b = rotr64(b ^ c, 63); \ - } while (0) -#define ROUND(r) \ - do { \ - G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ - G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ - G(r,2,v[ 2],v[ 6],v[10],v[14]); \ - G(r,3,v[ 3],v[ 7],v[11],v[15]); \ - G(r,4,v[ 0],v[ 5],v[10],v[15]); \ - G(r,5,v[ 1],v[ 6],v[11],v[12]); \ - G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ - G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ - } while (0) -#if defined(OPENSSL_SMALL_FOOTPRINT) - /* 3x size reduction on x86_64, almost 7x on ARMv8, 9x on ARMv4 */ - for (i = 0; i < 12; i++) { - ROUND(i); - } -#else - ROUND(0); - ROUND(1); - ROUND(2); - ROUND(3); - ROUND(4); - ROUND(5); - ROUND(6); - ROUND(7); - ROUND(8); - ROUND(9); - ROUND(10); - ROUND(11); -#endif - - for (i = 0; i < 8; ++i) { - S->h[i] = v[i] ^= v[i + 8] ^ S->h[i]; - } -#undef G -#undef ROUND - blocks += increment; - len -= increment; - } while (len); -} - -/* Absorb the input data into the hash state. Always returns 1. */ -int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen) -{ - const uint8_t *in = data; - size_t fill; - - /* - * Intuitively one would expect intermediate buffer, c->buf, to - * store incomplete blocks. But in this case we are interested to - * temporarily stash even complete blocks, because last one in the - * stream has to be treated in special way, and at this point we - * don't know if last block in *this* call is last one "ever". This - * is the reason for why |datalen| is compared as >, and not >=. - */ - fill = sizeof(c->buf) - c->buflen; - if (datalen > fill) { - if (c->buflen) { - memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */ - blake2b_compress(c, c->buf, BLAKE2B_BLOCKBYTES); - c->buflen = 0; - in += fill; - datalen -= fill; - } - if (datalen > BLAKE2B_BLOCKBYTES) { - size_t stashlen = datalen % BLAKE2B_BLOCKBYTES; - /* - * If |datalen| is a multiple of the blocksize, stash - * last complete block, it can be final one... - */ - stashlen = stashlen ? stashlen : BLAKE2B_BLOCKBYTES; - datalen -= stashlen; - blake2b_compress(c, in, datalen); - in += datalen; - datalen = stashlen; - } - } - - assert(datalen <= BLAKE2B_BLOCKBYTES); - - memcpy(c->buf + c->buflen, in, datalen); - c->buflen += datalen; /* Be lazy, do not compress */ - - return 1; -} - -/* - * Calculate the final hash and save it in md. - * Always returns 1. - */ -int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c) -{ - int i; - - blake2b_set_lastblock(c); - /* Padding */ - memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen); - blake2b_compress(c, c->buf, c->buflen); - - /* Output full hash to message digest */ - for (i = 0; i < 8; ++i) { - store64(md + sizeof(c->h[i]) * i, c->h[i]); - } - - OPENSSL_cleanse(c, sizeof(BLAKE2B_CTX)); - return 1; -} diff --git a/crypto/blake2/blake2s.c b/crypto/blake2/blake2s.c deleted file mode 100644 --- a/crypto/blake2/blake2s.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2016-2017 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 - */ - -/* - * Derived from the BLAKE2 reference implementation written by Samuel Neves. - * Copyright 2012, Samuel Neves - * More information about the BLAKE2 hash function and its implementations - * can be found at https://blake2.net. - */ - -#include -#include -#include - -#include "blake2_local.h" -#include "blake2_impl.h" - -static const uint32_t blake2s_IV[8] = -{ - 0x6A09E667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, - 0x510E527FU, 0x9B05688CU, 0x1F83D9ABU, 0x5BE0CD19U -}; - -static const uint8_t blake2s_sigma[10][16] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , -}; - -/* Set that it's the last block we'll compress */ -static ossl_inline void blake2s_set_lastblock(BLAKE2S_CTX *S) -{ - S->f[0] = -1; -} - -/* Initialize the hashing state. */ -static ossl_inline void blake2s_init0(BLAKE2S_CTX *S) -{ - int i; - - memset(S, 0, sizeof(BLAKE2S_CTX)); - for (i = 0; i < 8; ++i) { - S->h[i] = blake2s_IV[i]; - } -} - -/* init2 xors IV with input parameter block */ -static void blake2s_init_param(BLAKE2S_CTX *S, const BLAKE2S_PARAM *P) -{ - const uint8_t *p = (const uint8_t *)(P); - size_t i; - - /* The param struct is carefully hand packed, and should be 32 bytes on - * every platform. */ - assert(sizeof(BLAKE2S_PARAM) == 32); - blake2s_init0(S); - /* IV XOR ParamBlock */ - for (i = 0; i < 8; ++i) { - S->h[i] ^= load32(&p[i*4]); - } -} - -/* Initialize the hashing context. Always returns 1. */ -int BLAKE2s_Init(BLAKE2S_CTX *c) -{ - BLAKE2S_PARAM P[1]; - - P->digest_length = BLAKE2S_DIGEST_LENGTH; - P->key_length = 0; - P->fanout = 1; - P->depth = 1; - store32(P->leaf_length, 0); - store48(P->node_offset, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - blake2s_init_param(c, P); - return 1; -} - -/* Permute the state while xoring in the block of data. */ -static void blake2s_compress(BLAKE2S_CTX *S, - const uint8_t *blocks, - size_t len) -{ - uint32_t m[16]; - uint32_t v[16]; - size_t i; - size_t increment; - - /* - * There are two distinct usage vectors for this function: - * - * a) BLAKE2s_Update uses it to process complete blocks, - * possibly more than one at a time; - * - * b) BLAK2s_Final uses it to process last block, always - * single but possibly incomplete, in which case caller - * pads input with zeros. - */ - assert(len < BLAKE2S_BLOCKBYTES || len % BLAKE2S_BLOCKBYTES == 0); - - /* - * Since last block is always processed with separate call, - * |len| not being multiple of complete blocks can be observed - * only with |len| being less than BLAKE2S_BLOCKBYTES ("less" - * including even zero), which is why following assignment doesn't - * have to reside inside the main loop below. - */ - increment = len < BLAKE2S_BLOCKBYTES ? len : BLAKE2S_BLOCKBYTES; - - for (i = 0; i < 8; ++i) { - v[i] = S->h[i]; - } - - do { - for (i = 0; i < 16; ++i) { - m[i] = load32(blocks + i * sizeof(m[i])); - } - - /* blake2s_increment_counter */ - S->t[0] += increment; - S->t[1] += (S->t[0] < increment); - - v[ 8] = blake2s_IV[0]; - v[ 9] = blake2s_IV[1]; - v[10] = blake2s_IV[2]; - v[11] = blake2s_IV[3]; - v[12] = S->t[0] ^ blake2s_IV[4]; - v[13] = S->t[1] ^ blake2s_IV[5]; - v[14] = S->f[0] ^ blake2s_IV[6]; - v[15] = S->f[1] ^ blake2s_IV[7]; -#define G(r,i,a,b,c,d) \ - do { \ - a = a + b + m[blake2s_sigma[r][2*i+0]]; \ - d = rotr32(d ^ a, 16); \ - c = c + d; \ - b = rotr32(b ^ c, 12); \ - a = a + b + m[blake2s_sigma[r][2*i+1]]; \ - d = rotr32(d ^ a, 8); \ - c = c + d; \ - b = rotr32(b ^ c, 7); \ - } while (0) -#define ROUND(r) \ - do { \ - G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ - G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ - G(r,2,v[ 2],v[ 6],v[10],v[14]); \ - G(r,3,v[ 3],v[ 7],v[11],v[15]); \ - G(r,4,v[ 0],v[ 5],v[10],v[15]); \ - G(r,5,v[ 1],v[ 6],v[11],v[12]); \ - G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ - G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ - } while (0) -#if defined(OPENSSL_SMALL_FOOTPRINT) - /* almost 3x reduction on x86_64, 4.5x on ARMv8, 4x on ARMv4 */ - for (i = 0; i < 10; i++) { - ROUND(i); - } -#else - ROUND(0); - ROUND(1); - ROUND(2); - ROUND(3); - ROUND(4); - ROUND(5); - ROUND(6); - ROUND(7); - ROUND(8); - ROUND(9); -#endif - - for (i = 0; i < 8; ++i) { - S->h[i] = v[i] ^= v[i + 8] ^ S->h[i]; - } -#undef G -#undef ROUND - blocks += increment; - len -= increment; - } while (len); -} - -/* Absorb the input data into the hash state. Always returns 1. */ -int BLAKE2s_Update(BLAKE2S_CTX *c, const void *data, size_t datalen) -{ - const uint8_t *in = data; - size_t fill; - - /* - * Intuitively one would expect intermediate buffer, c->buf, to - * store incomplete blocks. But in this case we are interested to - * temporarily stash even complete blocks, because last one in the - * stream has to be treated in special way, and at this point we - * don't know if last block in *this* call is last one "ever". This - * is the reason for why |datalen| is compared as >, and not >=. - */ - fill = sizeof(c->buf) - c->buflen; - if (datalen > fill) { - if (c->buflen) { - memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */ - blake2s_compress(c, c->buf, BLAKE2S_BLOCKBYTES); - c->buflen = 0; - in += fill; - datalen -= fill; - } - if (datalen > BLAKE2S_BLOCKBYTES) { - size_t stashlen = datalen % BLAKE2S_BLOCKBYTES; - /* - * If |datalen| is a multiple of the blocksize, stash - * last complete block, it can be final one... - */ - stashlen = stashlen ? stashlen : BLAKE2S_BLOCKBYTES; - datalen -= stashlen; - blake2s_compress(c, in, datalen); - in += datalen; - datalen = stashlen; - } - } - - assert(datalen <= BLAKE2S_BLOCKBYTES); - - memcpy(c->buf + c->buflen, in, datalen); - c->buflen += datalen; /* Be lazy, do not compress */ - - return 1; -} - -/* - * Calculate the final hash and save it in md. - * Always returns 1. - */ -int BLAKE2s_Final(unsigned char *md, BLAKE2S_CTX *c) -{ - int i; - - blake2s_set_lastblock(c); - /* Padding */ - memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen); - blake2s_compress(c, c->buf, c->buflen); - - /* Output full hash to temp buffer */ - for (i = 0; i < 8; ++i) { - store32(md + sizeof(c->h[i]) * i, c->h[i]); - } - - OPENSSL_cleanse(c, sizeof(BLAKE2S_CTX)); - return 1; -} diff --git a/crypto/blake2/build.info b/crypto/blake2/build.info deleted file mode 100644 --- a/crypto/blake2/build.info +++ /dev/null @@ -1,3 +0,0 @@ -LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - blake2b.c blake2s.c m_blake2b.c m_blake2s.c diff --git a/crypto/blake2/m_blake2b.c b/crypto/blake2/m_blake2b.c deleted file mode 100644 --- a/crypto/blake2/m_blake2b.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Derived from the BLAKE2 reference implementation written by Samuel Neves. - * Copyright 2012, Samuel Neves - * More information about the BLAKE2 hash function and its implementations - * can be found at https://blake2.net. - */ - -#include "internal/cryptlib.h" - -#ifndef OPENSSL_NO_BLAKE2 - -# include -# include -# include "blake2_local.h" -# include "crypto/evp.h" - -static int init(EVP_MD_CTX *ctx) -{ - return BLAKE2b_Init(EVP_MD_CTX_md_data(ctx)); -} - -static int update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - return BLAKE2b_Update(EVP_MD_CTX_md_data(ctx), data, count); -} - -static int final(EVP_MD_CTX *ctx, unsigned char *md) -{ - return BLAKE2b_Final(md, EVP_MD_CTX_md_data(ctx)); -} - -static const EVP_MD blake2b_md = { - NID_blake2b512, - 0, - BLAKE2B_DIGEST_LENGTH, - 0, - init, - update, - final, - NULL, - NULL, - BLAKE2B_BLOCKBYTES, - sizeof(EVP_MD *) + sizeof(BLAKE2B_CTX), -}; - -const EVP_MD *EVP_blake2b512(void) -{ - return &blake2b_md; -} -#endif diff --git a/crypto/blake2/m_blake2s.c b/crypto/blake2/m_blake2s.c deleted file mode 100644 --- a/crypto/blake2/m_blake2s.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Derived from the BLAKE2 reference implementation written by Samuel Neves. - * Copyright 2012, Samuel Neves - * More information about the BLAKE2 hash function and its implementations - * can be found at https://blake2.net. - */ - -#include "internal/cryptlib.h" - -#ifndef OPENSSL_NO_BLAKE2 - -# include -# include -# include "blake2_local.h" -# include "crypto/evp.h" - -static int init(EVP_MD_CTX *ctx) -{ - return BLAKE2s_Init(EVP_MD_CTX_md_data(ctx)); -} - -static int update(EVP_MD_CTX *ctx, const void *data, size_t count) -{ - return BLAKE2s_Update(EVP_MD_CTX_md_data(ctx), data, count); -} - -static int final(EVP_MD_CTX *ctx, unsigned char *md) -{ - return BLAKE2s_Final(md, EVP_MD_CTX_md_data(ctx)); -} - -static const EVP_MD blake2s_md = { - NID_blake2s256, - 0, - BLAKE2S_DIGEST_LENGTH, - 0, - init, - update, - final, - NULL, - NULL, - BLAKE2S_BLOCKBYTES, - sizeof(EVP_MD *) + sizeof(BLAKE2S_CTX), -}; - -const EVP_MD *EVP_blake2s256(void) -{ - return &blake2s_md; -} -#endif diff --git a/crypto/bn/README.pod b/crypto/bn/README.pod --- a/crypto/bn/README.pod +++ b/crypto/bn/README.pod @@ -233,7 +233,7 @@ Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. -Licensed under the OpenSSL license (the "License"). You may not use +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 L. diff --git a/crypto/bn/asm/armv4-gf2m.pl b/crypto/bn/asm/armv4-gf2m.pl --- a/crypto/bn/asm/armv4-gf2m.pl +++ b/crypto/bn/asm/armv4-gf2m.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -39,9 +39,10 @@ # # http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf -$flavour = shift; -if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } -else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour && $flavour ne "void") { $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; @@ -49,21 +50,23 @@ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; - open STDOUT,"| \"$^X\" $xlate $flavour $output"; + open STDOUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $1"; } else { - open STDOUT,">$output"; + $output and open STDOUT,">$output"; } $code=<<___; #include "arm_arch.h" -.text #if defined(__thumb2__) .syntax unified .thumb #else .code 32 #endif + +.text ___ ################ # private interface to mul_1x1_ialu @@ -176,11 +179,13 @@ #if __ARM_MAX_ARCH__>=7 stmdb sp!,{r10,lr} ldr r12,.LOPENSSL_armcap +# if !defined(_WIN32) adr r10,.LOPENSSL_armcap ldr r12,[r12,r10] -#ifdef __APPLE__ +# endif +# if defined(__APPLE__) || defined(_WIN32) ldr r12,[r12] -#endif +# endif tst r12,#ARMV7_NEON itt ne ldrne r10,[sp],#8 @@ -310,7 +315,11 @@ #if __ARM_MAX_ARCH__>=7 .align 5 .LOPENSSL_armcap: +# ifdef _WIN32 +.word OPENSSL_armcap_P +# else .word OPENSSL_armcap_P-. +# endif #endif .asciz "GF(2^m) Multiplication for ARMv4/NEON, CRYPTOGAMS by " .align 5 diff --git a/crypto/bn/asm/armv4-mont.pl b/crypto/bn/asm/armv4-mont.pl --- a/crypto/bn/asm/armv4-mont.pl +++ b/crypto/bn/asm/armv4-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -54,9 +54,10 @@ # integer-only on Cortex-A8, ~10-210% on Cortex-A15, ~70-450% on # Snapdragon S4. -$flavour = shift; -if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } -else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour && $flavour ne "void") { $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; @@ -64,9 +65,10 @@ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; - open STDOUT,"| \"$^X\" $xlate $flavour $output"; + open STDOUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $1"; } else { - open STDOUT,">$output"; + $output and open STDOUT,">$output"; } $num="r0"; # starts as num argument, but holds &tp[num-1] @@ -97,7 +99,6 @@ $code=<<___; #include "arm_arch.h" -.text #if defined(__thumb2__) .syntax unified .thumb @@ -105,10 +106,16 @@ .code 32 #endif +.text + #if __ARM_MAX_ARCH__>=7 .align 5 .LOPENSSL_armcap: +# ifdef _WIN32 +.word OPENSSL_armcap_P +# else .word OPENSSL_armcap_P-.Lbn_mul_mont +# endif #endif .global bn_mul_mont @@ -122,12 +129,14 @@ #if __ARM_MAX_ARCH__>=7 tst ip,#7 bne .Lialu - adr r0,.Lbn_mul_mont - ldr r2,.LOPENSSL_armcap + ldr r0,.LOPENSSL_armcap +#if !defined(_WIN32) + adr r2,.Lbn_mul_mont ldr r0,[r0,r2] -#ifdef __APPLE__ +# endif +# if defined(__APPLE__) || defined(_WIN32) ldr r0,[r0] -#endif +# endif tst r0,#ARMV7_NEON @ NEON available? ldmia sp, {r0,r2} beq .Lialu diff --git a/crypto/bn/asm/armv8-mont.pl b/crypto/bn/asm/armv8-mont.pl --- a/crypto/bn/asm/armv8-mont.pl +++ b/crypto/bn/asm/armv8-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -40,15 +40,18 @@ # 50-70% improvement for RSA4096 sign. RSA2048 sign is ~25% faster # on Cortex-A57 and ~60-100% faster on others. -$flavour = shift; -$output = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; -open OUT,"| \"$^X\" $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $1"; *STDOUT=*OUT; ($lo0,$hi0,$aj,$m0,$alo,$ahi, @@ -64,16 +67,34 @@ $num="x5"; # int num); $code.=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" +.extern OPENSSL_armv8_rsa_neonized +.hidden OPENSSL_armv8_rsa_neonized +#endif .text .globl bn_mul_mont .type bn_mul_mont,%function .align 5 bn_mul_mont: +.Lbn_mul_mont: + tst $num,#3 + b.ne .Lmul_mont + cmp $num,#32 + b.le .Lscalar_impl +#ifndef __KERNEL__ + adrp x17,OPENSSL_armv8_rsa_neonized + ldr w17,[x17,#:lo12:OPENSSL_armv8_rsa_neonized] + cbnz w17, bn_mul8x_mont_neon +#endif + +.Lscalar_impl: tst $num,#7 b.eq __bn_sqr8x_mont tst $num,#3 b.eq __bn_mul4x_mont + .Lmul_mont: stp x29,x30,[sp,#-64]! add x29,sp,#0 @@ -197,7 +218,7 @@ mul $nlo,$nj,$m1 // np[j]*m1 adds $lo1,$lo1,$lo0 umulh $nhi,$nj,$m1 - str $lo1,[$tp,#-16] // tp[j-1] + stur $lo1,[$tp,#-16] // tp[j-1] cbnz $j,.Linner .Linner_skip: @@ -253,13 +274,13 @@ csel $nj,$tj,$aj,lo // did it borrow? ldr $tj,[$tp],#8 ldr $aj,[$rp],#8 - str xzr,[$tp,#-16] // wipe tp - str $nj,[$rp,#-16] + stur xzr,[$tp,#-16] // wipe tp + stur $nj,[$rp,#-16] cbnz $num,.Lcond_copy csel $nj,$tj,$aj,lo - str xzr,[$tp,#-8] // wipe tp - str $nj,[$rp,#-8] + stur xzr,[$tp,#-8] // wipe tp + stur $nj,[$rp,#-8] ldp x19,x20,[x29,#16] mov sp,x29 @@ -271,6 +292,369 @@ .size bn_mul_mont,.-bn_mul_mont ___ { +my ($A0,$A1,$N0,$N1)=map("v$_",(0..3)); +my ($Z,$Temp)=("v4.16b","v5"); +my @ACC=map("v$_",(6..13)); +my ($Bi,$Ni,$M0)=map("v$_",(28..30)); +my $sBi="s28"; +my $sM0="s30"; +my $zero="v14"; +my $temp="v15"; +my $ACCTemp="v16"; + +my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("x$_",(0..5)); +my ($tinptr,$toutptr,$inner,$outer,$bnptr)=map("x$_",(6..11)); + +$code.=<<___; +.type bn_mul8x_mont_neon,%function +.align 5 +bn_mul8x_mont_neon: + stp x29,x30,[sp,#-80]! + mov x16,sp + stp d8,d9,[sp,#16] + stp d10,d11,[sp,#32] + stp d12,d13,[sp,#48] + stp d14,d15,[sp,#64] + lsl $num,$num,#1 + eor $zero.16b,$zero.16b,$zero.16b + +.align 4 +.LNEON_8n: + eor @ACC[0].16b,@ACC[0].16b,@ACC[0].16b + sub $toutptr,sp,#128 + eor @ACC[1].16b,@ACC[1].16b,@ACC[1].16b + sub $toutptr,$toutptr,$num,lsl#4 + eor @ACC[2].16b,@ACC[2].16b,@ACC[2].16b + and $toutptr,$toutptr,#-64 + eor @ACC[3].16b,@ACC[3].16b,@ACC[3].16b + mov sp,$toutptr // alloca + eor @ACC[4].16b,@ACC[4].16b,@ACC[4].16b + add $toutptr,$toutptr,#256 + eor @ACC[5].16b,@ACC[5].16b,@ACC[5].16b + sub $inner,$num,#8 + eor @ACC[6].16b,@ACC[6].16b,@ACC[6].16b + eor @ACC[7].16b,@ACC[7].16b,@ACC[7].16b + +.LNEON_8n_init: + st1 {@ACC[0].2d,@ACC[1].2d},[$toutptr],#32 + subs $inner,$inner,#8 + st1 {@ACC[2].2d,@ACC[3].2d},[$toutptr],#32 + st1 {@ACC[4].2d,@ACC[5].2d},[$toutptr],#32 + st1 {@ACC[6].2d,@ACC[7].2d},[$toutptr],#32 + bne .LNEON_8n_init + + add $tinptr,sp,#256 + ld1 {$A0.4s,$A1.4s},[$aptr],#32 + add $bnptr,sp,#8 + ldr $sM0,[$n0],#4 + mov $outer,$num + b .LNEON_8n_outer + +.align 4 +.LNEON_8n_outer: + ldr $sBi,[$bptr],#4 // *b++ + uxtl $Bi.4s,$Bi.4h + add $toutptr,sp,#128 + ld1 {$N0.4s,$N1.4s},[$nptr],#32 + + umlal @ACC[0].2d,$Bi.2s,$A0.s[0] + umlal @ACC[1].2d,$Bi.2s,$A0.s[1] + umlal @ACC[2].2d,$Bi.2s,$A0.s[2] + shl $Ni.2d,@ACC[0].2d,#16 + ext $Ni.16b,$Ni.16b,$Ni.16b,#8 + umlal @ACC[3].2d,$Bi.2s,$A0.s[3] + add $Ni.2d,$Ni.2d,@ACC[0].2d + umlal @ACC[4].2d,$Bi.2s,$A1.s[0] + mul $Ni.2s,$Ni.2s,$M0.2s + umlal @ACC[5].2d,$Bi.2s,$A1.s[1] + st1 {$Bi.2s},[sp] // put aside smashed b[8*i+0] + umlal @ACC[6].2d,$Bi.2s,$A1.s[2] + uxtl $Ni.4s,$Ni.4h + umlal @ACC[7].2d,$Bi.2s,$A1.s[3] +___ +for ($i=0; $i<7;) { +$code.=<<___; + ldr $sBi,[$bptr],#4 // *b++ + umlal @ACC[0].2d,$Ni.2s,$N0.s[0] + umlal @ACC[1].2d,$Ni.2s,$N0.s[1] + uxtl $Bi.4s,$Bi.4h + umlal @ACC[2].2d,$Ni.2s,$N0.s[2] + ushr $temp.2d,@ACC[0].2d,#16 + umlal @ACC[3].2d,$Ni.2s,$N0.s[3] + umlal @ACC[4].2d,$Ni.2s,$N1.s[0] + ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8 + add @ACC[0].2d,@ACC[0].2d,$temp.2d + umlal @ACC[5].2d,$Ni.2s,$N1.s[1] + ushr @ACC[0].2d,@ACC[0].2d,#16 + umlal @ACC[6].2d,$Ni.2s,$N1.s[2] + umlal @ACC[7].2d,$Ni.2s,$N1.s[3] + add $ACCTemp.2d,@ACC[1].2d,@ACC[0].2d + ins @ACC[1].d[0],$ACCTemp.d[0] + st1 {$Ni.2s},[$bnptr],#8 // put aside smashed m[8*i+$i] +___ + push(@ACC,shift(@ACC)); $i++; +$code.=<<___; + umlal @ACC[0].2d,$Bi.2s,$A0.s[0] + ld1 {@ACC[7].2d},[$tinptr],#16 + umlal @ACC[1].2d,$Bi.2s,$A0.s[1] + umlal @ACC[2].2d,$Bi.2s,$A0.s[2] + shl $Ni.2d,@ACC[0].2d,#16 + ext $Ni.16b,$Ni.16b,$Ni.16b,#8 + umlal @ACC[3].2d,$Bi.2s,$A0.s[3] + add $Ni.2d,$Ni.2d,@ACC[0].2d + umlal @ACC[4].2d,$Bi.2s,$A1.s[0] + mul $Ni.2s,$Ni.2s,$M0.2s + umlal @ACC[5].2d,$Bi.2s,$A1.s[1] + st1 {$Bi.2s},[$bnptr],#8 // put aside smashed b[8*i+$i] + umlal @ACC[6].2d,$Bi.2s,$A1.s[2] + uxtl $Ni.4s,$Ni.4h + umlal @ACC[7].2d,$Bi.2s,$A1.s[3] +___ +} +$code.=<<___; + ld1 {$Bi.2s},[sp] // pull smashed b[8*i+0] + umlal @ACC[0].2d,$Ni.2s,$N0.s[0] + ld1 {$A0.4s,$A1.4s},[$aptr],#32 + umlal @ACC[1].2d,$Ni.2s,$N0.s[1] + umlal @ACC[2].2d,$Ni.2s,$N0.s[2] + mov $Temp.16b,@ACC[0].16b + ushr $Temp.2d,$Temp.2d,#16 + ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8 + umlal @ACC[3].2d,$Ni.2s,$N0.s[3] + umlal @ACC[4].2d,$Ni.2s,$N1.s[0] + add @ACC[0].2d,@ACC[0].2d,$Temp.2d + umlal @ACC[5].2d,$Ni.2s,$N1.s[1] + ushr @ACC[0].2d,@ACC[0].2d,#16 + eor $temp.16b,$temp.16b,$temp.16b + ins @ACC[0].d[1],$temp.d[0] + umlal @ACC[6].2d,$Ni.2s,$N1.s[2] + umlal @ACC[7].2d,$Ni.2s,$N1.s[3] + add @ACC[1].2d,@ACC[1].2d,@ACC[0].2d + st1 {$Ni.2s},[$bnptr],#8 // put aside smashed m[8*i+$i] + add $bnptr,sp,#8 // rewind +___ + push(@ACC,shift(@ACC)); +$code.=<<___; + sub $inner,$num,#8 + b .LNEON_8n_inner + +.align 4 +.LNEON_8n_inner: + subs $inner,$inner,#8 + umlal @ACC[0].2d,$Bi.2s,$A0.s[0] + ld1 {@ACC[7].2d},[$tinptr] + umlal @ACC[1].2d,$Bi.2s,$A0.s[1] + ld1 {$Ni.2s},[$bnptr],#8 // pull smashed m[8*i+0] + umlal @ACC[2].2d,$Bi.2s,$A0.s[2] + ld1 {$N0.4s,$N1.4s},[$nptr],#32 + umlal @ACC[3].2d,$Bi.2s,$A0.s[3] + b.eq .LInner_jump + add $tinptr,$tinptr,#16 // don't advance in last iteration +.LInner_jump: + umlal @ACC[4].2d,$Bi.2s,$A1.s[0] + umlal @ACC[5].2d,$Bi.2s,$A1.s[1] + umlal @ACC[6].2d,$Bi.2s,$A1.s[2] + umlal @ACC[7].2d,$Bi.2s,$A1.s[3] +___ +for ($i=1; $i<8; $i++) { +$code.=<<___; + ld1 {$Bi.2s},[$bnptr],#8 // pull smashed b[8*i+$i] + umlal @ACC[0].2d,$Ni.2s,$N0.s[0] + umlal @ACC[1].2d,$Ni.2s,$N0.s[1] + umlal @ACC[2].2d,$Ni.2s,$N0.s[2] + umlal @ACC[3].2d,$Ni.2s,$N0.s[3] + umlal @ACC[4].2d,$Ni.2s,$N1.s[0] + umlal @ACC[5].2d,$Ni.2s,$N1.s[1] + umlal @ACC[6].2d,$Ni.2s,$N1.s[2] + umlal @ACC[7].2d,$Ni.2s,$N1.s[3] + st1 {@ACC[0].2d},[$toutptr],#16 +___ + push(@ACC,shift(@ACC)); +$code.=<<___; + umlal @ACC[0].2d,$Bi.2s,$A0.s[0] + ld1 {@ACC[7].2d},[$tinptr] + umlal @ACC[1].2d,$Bi.2s,$A0.s[1] + ld1 {$Ni.2s},[$bnptr],#8 // pull smashed m[8*i+$i] + umlal @ACC[2].2d,$Bi.2s,$A0.s[2] + b.eq .LInner_jump$i + add $tinptr,$tinptr,#16 // don't advance in last iteration +.LInner_jump$i: + umlal @ACC[3].2d,$Bi.2s,$A0.s[3] + umlal @ACC[4].2d,$Bi.2s,$A1.s[0] + umlal @ACC[5].2d,$Bi.2s,$A1.s[1] + umlal @ACC[6].2d,$Bi.2s,$A1.s[2] + umlal @ACC[7].2d,$Bi.2s,$A1.s[3] +___ +} +$code.=<<___; + b.ne .LInner_after_rewind$i + sub $aptr,$aptr,$num,lsl#2 // rewind +.LInner_after_rewind$i: + umlal @ACC[0].2d,$Ni.2s,$N0.s[0] + ld1 {$Bi.2s},[sp] // pull smashed b[8*i+0] + umlal @ACC[1].2d,$Ni.2s,$N0.s[1] + ld1 {$A0.4s,$A1.4s},[$aptr],#32 + umlal @ACC[2].2d,$Ni.2s,$N0.s[2] + add $bnptr,sp,#8 // rewind + umlal @ACC[3].2d,$Ni.2s,$N0.s[3] + umlal @ACC[4].2d,$Ni.2s,$N1.s[0] + umlal @ACC[5].2d,$Ni.2s,$N1.s[1] + umlal @ACC[6].2d,$Ni.2s,$N1.s[2] + st1 {@ACC[0].2d},[$toutptr],#16 + umlal @ACC[7].2d,$Ni.2s,$N1.s[3] + + bne .LNEON_8n_inner +___ + push(@ACC,shift(@ACC)); +$code.=<<___; + add $tinptr,sp,#128 + st1 {@ACC[0].2d,@ACC[1].2d},[$toutptr],#32 + eor $N0.16b,$N0.16b,$N0.16b // $N0 + st1 {@ACC[2].2d,@ACC[3].2d},[$toutptr],#32 + eor $N1.16b,$N1.16b,$N1.16b // $N1 + st1 {@ACC[4].2d,@ACC[5].2d},[$toutptr],#32 + st1 {@ACC[6].2d},[$toutptr] + + subs $outer,$outer,#8 + ld1 {@ACC[0].2d,@ACC[1].2d},[$tinptr],#32 + ld1 {@ACC[2].2d,@ACC[3].2d},[$tinptr],#32 + ld1 {@ACC[4].2d,@ACC[5].2d},[$tinptr],#32 + ld1 {@ACC[6].2d,@ACC[7].2d},[$tinptr],#32 + + b.eq .LInner_8n_jump_2steps + sub $nptr,$nptr,$num,lsl#2 // rewind + b .LNEON_8n_outer + +.LInner_8n_jump_2steps: + add $toutptr,sp,#128 + st1 {$N0.2d,$N1.2d}, [sp],#32 // start wiping stack frame + mov $Temp.16b,@ACC[0].16b + ushr $temp.2d,@ACC[0].2d,#16 + ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8 + st1 {$N0.2d,$N1.2d}, [sp],#32 + add @ACC[0].2d,@ACC[0].2d,$temp.2d + st1 {$N0.2d,$N1.2d}, [sp],#32 + ushr $temp.2d,@ACC[0].2d,#16 + st1 {$N0.2d,$N1.2d}, [sp],#32 + zip1 @ACC[0].4h,$Temp.4h,@ACC[0].4h + ins $temp.d[1],$zero.d[0] + + mov $inner,$num + b .LNEON_tail_entry + +.align 4 +.LNEON_tail: + add @ACC[0].2d,@ACC[0].2d,$temp.2d + mov $Temp.16b,@ACC[0].16b + ushr $temp.2d,@ACC[0].2d,#16 + ext @ACC[0].16b,@ACC[0].16b,@ACC[0].16b,#8 + ld1 {@ACC[2].2d,@ACC[3].2d}, [$tinptr],#32 + add @ACC[0].2d,@ACC[0].2d,$temp.2d + ld1 {@ACC[4].2d,@ACC[5].2d}, [$tinptr],#32 + ushr $temp.2d,@ACC[0].2d,#16 + ld1 {@ACC[6].2d,@ACC[7].2d}, [$tinptr],#32 + zip1 @ACC[0].4h,$Temp.4h,@ACC[0].4h + ins $temp.d[1],$zero.d[0] + +.LNEON_tail_entry: +___ +for ($i=1; $i<8; $i++) { +$code.=<<___; + add @ACC[1].2d,@ACC[1].2d,$temp.2d + st1 {@ACC[0].s}[0], [$toutptr],#4 + ushr $temp.2d,@ACC[1].2d,#16 + mov $Temp.16b,@ACC[1].16b + ext @ACC[1].16b,@ACC[1].16b,@ACC[1].16b,#8 + add @ACC[1].2d,@ACC[1].2d,$temp.2d + ushr $temp.2d,@ACC[1].2d,#16 + zip1 @ACC[1].4h,$Temp.4h,@ACC[1].4h + ins $temp.d[1],$zero.d[0] +___ + push(@ACC,shift(@ACC)); +} + push(@ACC,shift(@ACC)); +$code.=<<___; + ld1 {@ACC[0].2d,@ACC[1].2d}, [$tinptr],#32 + subs $inner,$inner,#8 + st1 {@ACC[7].s}[0], [$toutptr],#4 + bne .LNEON_tail + + st1 {$temp.s}[0], [$toutptr],#4 // top-most bit + sub $nptr,$nptr,$num,lsl#2 // rewind $nptr + subs $aptr,sp,#0 // clear carry flag + add $bptr,sp,$num,lsl#2 + +.LNEON_sub: + ldp w4,w5,[$aptr],#8 + ldp w6,w7,[$aptr],#8 + ldp w8,w9,[$nptr],#8 + ldp w10,w11,[$nptr],#8 + sbcs w8,w4,w8 + sbcs w9,w5,w9 + sbcs w10,w6,w10 + sbcs w11,w7,w11 + sub x17,$bptr,$aptr + stp w8,w9,[$rptr],#8 + stp w10,w11,[$rptr],#8 + cbnz x17,.LNEON_sub + + ldr w10, [$aptr] // load top-most bit + mov x11,sp + eor v0.16b,v0.16b,v0.16b + sub x11,$bptr,x11 // this is num*4 + eor v1.16b,v1.16b,v1.16b + mov $aptr,sp + sub $rptr,$rptr,x11 // rewind $rptr + mov $nptr,$bptr // second 3/4th of frame + sbcs w10,w10,wzr // result is carry flag + +.LNEON_copy_n_zap: + ldp w4,w5,[$aptr],#8 + ldp w6,w7,[$aptr],#8 + ldp w8,w9,[$rptr],#8 + ldp w10,w11,[$rptr] + sub $rptr,$rptr,#8 + b.cs .LCopy_1 + mov w8,w4 + mov w9,w5 + mov w10,w6 + mov w11,w7 +.LCopy_1: + st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe + st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe + ldp w4,w5,[$aptr],#8 + ldp w6,w7,[$aptr],#8 + stp w8,w9,[$rptr],#8 + stp w10,w11,[$rptr],#8 + sub $aptr,$aptr,#32 + ldp w8,w9,[$rptr],#8 + ldp w10,w11,[$rptr] + sub $rptr,$rptr,#8 + b.cs .LCopy_2 + mov w8, w4 + mov w9, w5 + mov w10, w6 + mov w11, w7 +.LCopy_2: + st1 {v0.2d,v1.2d}, [$aptr],#32 // wipe + st1 {v0.2d,v1.2d}, [$nptr],#32 // wipe + sub x17,$bptr,$aptr // preserves carry + stp w8,w9,[$rptr],#8 + stp w10,w11,[$rptr],#8 + cbnz x17,.LNEON_copy_n_zap + + mov sp,x16 + ldp d14,d15,[sp,#64] + ldp d12,d13,[sp,#48] + ldp d10,d11,[sp,#32] + ldp d8,d9,[sp,#16] + ldr x29,[sp],#80 + ret // bx lr + +.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon +___ +} +{ ######################################################################## # Following is ARMv8 adaptation of sqrx8x_mont from x86_64-mont5 module. @@ -596,7 +980,7 @@ ldp $a4,$a5,[$tp,#8*4] ldp $a6,$a7,[$tp,#8*6] adds $acc0,$acc0,$a0 - ldr $n0,[$rp,#-8*8] + ldur $n0,[$rp,#-8*8] adcs $acc1,$acc1,$a1 ldp $a0,$a1,[$ap,#8*0] adcs $acc2,$acc2,$a2 @@ -794,7 +1178,7 @@ //adc $carry,xzr,xzr // moved below cbz $cnt,.Lsqr8x8_post_condition - ldr $n0,[$tp,#-8*8] + ldur $n0,[$tp,#-8*8] ldp $a0,$a1,[$np,#8*0] ldp $a2,$a3,[$np,#8*2] ldp $a4,$a5,[$np,#8*4] @@ -852,7 +1236,7 @@ ldp $a6,$a7,[$tp,#8*6] cbz $cnt,.Lsqr8x_tail_break - ldr $n0,[$rp,#-8*8] + ldur $n0,[$rp,#-8*8] adds $acc0,$acc0,$a0 adcs $acc1,$acc1,$a1 ldp $a0,$a1,[$np,#8*0] diff --git a/crypto/bn/asm/bn-586.pl b/crypto/bn/asm/bn-586.pl --- a/crypto/bn/asm/bn-586.pl +++ b/crypto/bn/asm/bn-586.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -11,8 +11,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0]); diff --git a/crypto/bn/asm/bn-c64xplus.asm b/crypto/bn/asm/bn-c64xplus.asm --- a/crypto/bn/asm/bn-c64xplus.asm +++ b/crypto/bn/asm/bn-c64xplus.asm @@ -1,6 +1,6 @@ ;; Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. ;; -;; Licensed under the OpenSSL license (the "License"). You may not use +;; 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 ;; https://www.openssl.org/source/license.html @@ -10,8 +10,7 @@ ;; project. ;; ;; Rights for redistribution and usage in source and binary forms are -;; granted according to the OpenSSL license. Warranty of any kind is -;; disclaimed. +;; granted according to the License. Warranty of any kind is disclaimed. ;;==================================================================== ;; Compiler-generated multiply-n-add SPLOOP runs at 12*n cycles, n ;; being the number of 32-bit words, addition - 8*n. Corresponding 4x diff --git a/crypto/bn/asm/c64xplus-gf2m.pl b/crypto/bn/asm/c64xplus-gf2m.pl --- a/crypto/bn/asm/c64xplus-gf2m.pl +++ b/crypto/bn/asm/c64xplus-gf2m.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -23,8 +23,7 @@ # totally unfair, because this module utilizes Galois Field Multiply # instruction. -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; ($rp,$a1,$a0,$b1,$b0)=("A4","B4","A6","B6","A8"); # argument vector diff --git a/crypto/bn/asm/co-586.pl b/crypto/bn/asm/co-586.pl --- a/crypto/bn/asm/co-586.pl +++ b/crypto/bn/asm/co-586.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -10,8 +10,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0]); diff --git a/crypto/bn/asm/ia64-mont.pl b/crypto/bn/asm/ia64-mont.pl --- a/crypto/bn/asm/ia64-mont.pl +++ b/crypto/bn/asm/ia64-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -67,7 +67,8 @@ # hereafter less for longer keys, while verify - by 74-13%. # DSA performance improves by 115-30%. -$output=pop; +# $output is the last argument if it looks like a file (it has an extension) +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; if ($^O eq "hpux") { $ADDP="addp4"; diff --git a/crypto/bn/asm/ia64.S b/crypto/bn/asm/ia64.S --- a/crypto/bn/asm/ia64.S +++ b/crypto/bn/asm/ia64.S @@ -3,9 +3,9 @@ .ident "ia64.S, Version 2.1" .ident "IA-64 ISA artwork by Andy Polyakov " -// Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. +// Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. // -// Licensed under the OpenSSL license (the "License"). You may not use +// 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 // https://www.openssl.org/source/license.html @@ -16,8 +16,7 @@ // project. // // Rights for redistribution and usage in source and binary forms are -// granted according to the OpenSSL license. Warranty of any kind is -// disclaimed. +// granted according to the License. Warranty of any kind is disclaimed. // ==================================================================== // // Version 2.x is Itanium2 re-tune. Few words about how Itanium2 is diff --git a/crypto/bn/asm/mips-mont.pl b/crypto/bn/asm/mips-mont.pl --- a/crypto/bn/asm/mips-mont.pl +++ b/crypto/bn/asm/mips-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -52,8 +52,12 @@ # ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25)); # ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23)); # ($gp,$sp,$fp,$ra)=map("\$$_",(28..31)); -# -$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64 + +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +# supported flavours are o32,n32,64,nubi32,nubi64, default is o32 +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32"; if ($flavour =~ /64|n32/i) { $PTR_ADD="daddu"; # incidentally works even on n32 @@ -74,8 +78,7 @@ # ###################################################################### -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +$output and open STDOUT,">$output"; if ($flavour =~ /64|n32/i) { $LD="ld"; diff --git a/crypto/bn/asm/mips.pl b/crypto/bn/asm/mips.pl --- a/crypto/bn/asm/mips.pl +++ b/crypto/bn/asm/mips.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -12,8 +12,7 @@ # project. # # Rights for redistribution and usage in source and binary forms are -# granted according to the OpenSSL license. Warranty of any kind is -# disclaimed. +# granted according to the License. Warranty of any kind is disclaimed. # ==================================================================== @@ -55,9 +54,10 @@ # has to content with 40-85% improvement depending on benchmark and # key length, more for longer keys. -$flavour = shift || "o32"; -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32"; if ($flavour =~ /64|n32/i) { $LD="ld"; @@ -92,6 +92,8 @@ $code="#if !(defined (__mips_isa_rev) && (__mips_isa_rev >= 6))\n.set mips2\n#endif\n"; } +$output and open STDOUT,">$output"; + # Below is N32/64 register layout used in the original module. # ($zero,$at,$v0,$v1)=map("\$$_",(0..3)); diff --git a/crypto/bn/asm/parisc-mont.pl b/crypto/bn/asm/parisc-mont.pl --- a/crypto/bn/asm/parisc-mont.pl +++ b/crypto/bn/asm/parisc-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -69,10 +69,12 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; -$flavour = shift; -$output = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; -open STDOUT,">$output"; +$output and open STDOUT,">$output"; if ($flavour =~ /64/) { $LEVEL ="2.0W"; diff --git a/crypto/bn/asm/ppc-mont.pl b/crypto/bn/asm/ppc-mont.pl --- a/crypto/bn/asm/ppc-mont.pl +++ b/crypto/bn/asm/ppc-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -41,7 +41,10 @@ # builds. On low-end 32-bit processors performance improvement turned # to be marginal... -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /32/) { $BITS= 32; @@ -94,7 +97,8 @@ ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; +open STDOUT,"| $^X $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; $sp="r1"; $toc="r2"; diff --git a/crypto/bn/asm/ppc.pl b/crypto/bn/asm/ppc.pl --- a/crypto/bn/asm/ppc.pl +++ b/crypto/bn/asm/ppc.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -103,7 +103,10 @@ # Performance increase of ~60% # Based on submission from Suresh N. Chari of IBM -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /32/) { $BITS= 32; @@ -159,7 +162,8 @@ ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; +open STDOUT,"| $^X $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; $data=<= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /32/) { $SIZE_T=4; @@ -108,7 +111,8 @@ ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; +open STDOUT,"| $^X $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; $FRAME=64; # padded frame header $TRANSFER=16*8; diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/bn/asm/rsaz-avx2.pl --- a/crypto/bn/asm/rsaz-avx2.pl +++ b/crypto/bn/asm/rsaz-avx2.pl @@ -2,7 +2,7 @@ # Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2012, Intel Corporation. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -37,9 +37,10 @@ # (***) scalar AD*X code is faster than AVX2 and is preferred code # path for Broadwell; -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -72,7 +73,8 @@ $addx = ($ver>=3.03); } -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT = *OUT; if ($avx>1) {{{ diff --git a/crypto/bn/asm/rsaz-avx512.pl b/crypto/bn/asm/rsaz-avx512.pl new file mode 100644 --- /dev/null +++ b/crypto/bn/asm/rsaz-avx512.pl @@ -0,0 +1,754 @@ +# Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright (c) 2020, Intel Corporation. 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 +# https://www.openssl.org/source/license.html +# +# +# Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov +# Intel Corporation +# +# December 2020 +# +# Initial release. +# +# Implementation utilizes 256-bit (ymm) registers to avoid frequency scaling issues. +# +# IceLake-Client @ 1.3GHz +# |---------+----------------------+--------------+-------------| +# | | OpenSSL 3.0.0-alpha9 | this | Unit | +# |---------+----------------------+--------------+-------------| +# | rsa2048 | 2 127 659 | 1 015 625 | cycles/sign | +# | | 611 | 1280 / +109% | sign/s | +# |---------+----------------------+--------------+-------------| +# + +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; + +$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); +$avx512ifma=0; + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or +die "can't locate x86_64-xlate.pl"; + +if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` + =~ /GNU assembler version ([2-9]\.[0-9]+)/) { + $avx512ifma = ($1>=2.26); +} + +if (!$avx512 && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && + `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) { + $avx512ifma = ($1==2.11 && $2>=8) + ($1>=2.12); +} + +if (!$avx512 && `$ENV{CC} -v 2>&1` + =~ /(Apple)?\s*((?:clang|LLVM) version|.*based on LLVM) ([0-9]+)\.([0-9]+)\.([0-9]+)?/) { + my $ver = $3 + $4/100.0 + $5/10000.0; # 3.1.0->3.01, 3.10.1->3.1001 + if ($1) { + # Apple conditions, they use a different version series, see + # https://en.wikipedia.org/wiki/Xcode#Xcode_7.0_-_10.x_(since_Free_On-Device_Development)_2 + # clang 7.0.0 is Apple clang 10.0.1 + $avx512ifma = ($ver>=10.0001) + } else { + $avx512ifma = ($3>=7.0); + } +} + +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; +*STDOUT=*OUT; + +if ($avx512ifma>0) {{{ +@_6_args_universal_ABI = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); + +$code.=<<___; +.extern OPENSSL_ia32cap_P +.globl ossl_rsaz_avx512ifma_eligible +.type ossl_rsaz_avx512ifma_eligible,\@abi-omnipotent +.align 32 +ossl_rsaz_avx512ifma_eligible: + mov OPENSSL_ia32cap_P+8(%rip), %ecx + xor %eax,%eax + and \$`1<<31|1<<21|1<<17|1<<16`, %ecx # avx512vl + avx512ifma + avx512dq + avx512f + cmp \$`1<<31|1<<21|1<<17|1<<16`, %ecx + cmove %ecx,%eax + ret +.size ossl_rsaz_avx512ifma_eligible, .-ossl_rsaz_avx512ifma_eligible +___ + +############################################################################### +# Almost Montgomery Multiplication (AMM) for 20-digit number in radix 2^52. +# +# AMM is defined as presented in the paper +# "Efficient Software Implementations of Modular Exponentiation" by Shay Gueron. +# +# The input and output are presented in 2^52 radix domain, i.e. +# |res|, |a|, |b|, |m| are arrays of 20 64-bit qwords with 12 high bits zeroed. +# |k0| is a Montgomery coefficient, which is here k0 = -1/m mod 2^64 +# (note, the implementation counts only 52 bits from it). +# +# NB: the AMM implementation does not perform "conditional" subtraction step as +# specified in the original algorithm as according to the paper "Enhanced Montgomery +# Multiplication" by Shay Gueron (see Lemma 1), the result will be always < 2*2^1024 +# and can be used as a direct input to the next AMM iteration. +# This post-condition is true, provided the correct parameter |s| is choosen, i.e. +# s >= n + 2 * k, which matches our case: 1040 > 1024 + 2 * 1. +# +# void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res, +# const BN_ULONG *a, +# const BN_ULONG *b, +# const BN_ULONG *m, +# BN_ULONG k0); +############################################################################### +{ +# input parameters ("%rdi","%rsi","%rdx","%rcx","%r8") +my ($res,$a,$b,$m,$k0) = @_6_args_universal_ABI; + +my $mask52 = "%rax"; +my $acc0_0 = "%r9"; +my $acc0_0_low = "%r9d"; +my $acc0_1 = "%r15"; +my $acc0_1_low = "%r15d"; +my $b_ptr = "%r11"; + +my $iter = "%ebx"; + +my $zero = "%ymm0"; +my ($R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0) = ("%ymm1", map("%ymm$_",(16..19))); +my ($R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1) = ("%ymm2", map("%ymm$_",(20..23))); +my $Bi = "%ymm3"; +my $Yi = "%ymm4"; + +# Registers mapping for normalization. +# We can reuse Bi, Yi registers here. +my $TMP = $Bi; +my $mask52x4 = $Yi; +my ($T0,$T0h,$T1,$T1h,$T2) = map("%ymm$_", (24..28)); + +sub amm52x20_x1() { +# _data_offset - offset in the |a| or |m| arrays pointing to the beginning +# of data for corresponding AMM operation; +# _b_offset - offset in the |b| array pointing to the next qword digit; +my ($_data_offset,$_b_offset,$_acc,$_R0,$_R0h,$_R1,$_R1h,$_R2,$_k0) = @_; +my $_R0_xmm = $_R0; +$_R0_xmm =~ s/%y/%x/; +$code.=<<___; + movq $_b_offset($b_ptr), %r13 # b[i] + + vpbroadcastq %r13, $Bi # broadcast b[i] + movq $_data_offset($a), %rdx + mulx %r13, %r13, %r12 # a[0]*b[i] = (t0,t2) + addq %r13, $_acc # acc += t0 + movq %r12, %r10 + adcq \$0, %r10 # t2 += CF + + movq $_k0, %r13 + imulq $_acc, %r13 # acc * k0 + andq $mask52, %r13 # yi = (acc * k0) & mask52 + + vpbroadcastq %r13, $Yi # broadcast y[i] + movq $_data_offset($m), %rdx + mulx %r13, %r13, %r12 # yi * m[0] = (t0,t1) + addq %r13, $_acc # acc += t0 + adcq %r12, %r10 # t2 += (t1 + CF) + + shrq \$52, $_acc + salq \$12, %r10 + or %r10, $_acc # acc = ((acc >> 52) | (t2 << 12)) + + vpmadd52luq `$_data_offset+64*0`($a), $Bi, $_R0 + vpmadd52luq `$_data_offset+64*0+32`($a), $Bi, $_R0h + vpmadd52luq `$_data_offset+64*1`($a), $Bi, $_R1 + vpmadd52luq `$_data_offset+64*1+32`($a), $Bi, $_R1h + vpmadd52luq `$_data_offset+64*2`($a), $Bi, $_R2 + + vpmadd52luq `$_data_offset+64*0`($m), $Yi, $_R0 + vpmadd52luq `$_data_offset+64*0+32`($m), $Yi, $_R0h + vpmadd52luq `$_data_offset+64*1`($m), $Yi, $_R1 + vpmadd52luq `$_data_offset+64*1+32`($m), $Yi, $_R1h + vpmadd52luq `$_data_offset+64*2`($m), $Yi, $_R2 + + # Shift accumulators right by 1 qword, zero extending the highest one + valignq \$1, $_R0, $_R0h, $_R0 + valignq \$1, $_R0h, $_R1, $_R0h + valignq \$1, $_R1, $_R1h, $_R1 + valignq \$1, $_R1h, $_R2, $_R1h + valignq \$1, $_R2, $zero, $_R2 + + vmovq $_R0_xmm, %r13 + addq %r13, $_acc # acc += R0[0] + + vpmadd52huq `$_data_offset+64*0`($a), $Bi, $_R0 + vpmadd52huq `$_data_offset+64*0+32`($a), $Bi, $_R0h + vpmadd52huq `$_data_offset+64*1`($a), $Bi, $_R1 + vpmadd52huq `$_data_offset+64*1+32`($a), $Bi, $_R1h + vpmadd52huq `$_data_offset+64*2`($a), $Bi, $_R2 + + vpmadd52huq `$_data_offset+64*0`($m), $Yi, $_R0 + vpmadd52huq `$_data_offset+64*0+32`($m), $Yi, $_R0h + vpmadd52huq `$_data_offset+64*1`($m), $Yi, $_R1 + vpmadd52huq `$_data_offset+64*1+32`($m), $Yi, $_R1h + vpmadd52huq `$_data_offset+64*2`($m), $Yi, $_R2 +___ +} + +# Normalization routine: handles carry bits in R0..R2 QWs and +# gets R0..R2 back to normalized 2^52 representation. +# +# Uses %r8-14,%e[bcd]x +sub amm52x20_x1_norm { +my ($_acc,$_R0,$_R0h,$_R1,$_R1h,$_R2) = @_; +$code.=<<___; + # Put accumulator to low qword in R0 + vpbroadcastq $_acc, $TMP + vpblendd \$3, $TMP, $_R0, $_R0 + + # Extract "carries" (12 high bits) from each QW of R0..R2 + # Save them to LSB of QWs in T0..T2 + vpsrlq \$52, $_R0, $T0 + vpsrlq \$52, $_R0h, $T0h + vpsrlq \$52, $_R1, $T1 + vpsrlq \$52, $_R1h, $T1h + vpsrlq \$52, $_R2, $T2 + + # "Shift left" T0..T2 by 1 QW + valignq \$3, $T1h, $T2, $T2 + valignq \$3, $T1, $T1h, $T1h + valignq \$3, $T0h, $T1, $T1 + valignq \$3, $T0, $T0h, $T0h + valignq \$3, $zero, $T0, $T0 + + # Drop "carries" from R0..R2 QWs + vpandq $mask52x4, $_R0, $_R0 + vpandq $mask52x4, $_R0h, $_R0h + vpandq $mask52x4, $_R1, $_R1 + vpandq $mask52x4, $_R1h, $_R1h + vpandq $mask52x4, $_R2, $_R2 + + # Sum R0..R2 with corresponding adjusted carries + vpaddq $T0, $_R0, $_R0 + vpaddq $T0h, $_R0h, $_R0h + vpaddq $T1, $_R1, $_R1 + vpaddq $T1h, $_R1h, $_R1h + vpaddq $T2, $_R2, $_R2 + + # Now handle carry bits from this addition + # Get mask of QWs which 52-bit parts overflow... + vpcmpuq \$1, $_R0, $mask52x4, %k1 # OP=lt + vpcmpuq \$1, $_R0h, $mask52x4, %k2 + vpcmpuq \$1, $_R1, $mask52x4, %k3 + vpcmpuq \$1, $_R1h, $mask52x4, %k4 + vpcmpuq \$1, $_R2, $mask52x4, %k5 + kmovb %k1, %r14d # k1 + kmovb %k2, %r13d # k1h + kmovb %k3, %r12d # k2 + kmovb %k4, %r11d # k2h + kmovb %k5, %r10d # k3 + + # ...or saturated + vpcmpuq \$0, $_R0, $mask52x4, %k1 # OP=eq + vpcmpuq \$0, $_R0h, $mask52x4, %k2 + vpcmpuq \$0, $_R1, $mask52x4, %k3 + vpcmpuq \$0, $_R1h, $mask52x4, %k4 + vpcmpuq \$0, $_R2, $mask52x4, %k5 + kmovb %k1, %r9d # k4 + kmovb %k2, %r8d # k4h + kmovb %k3, %ebx # k5 + kmovb %k4, %ecx # k5h + kmovb %k5, %edx # k6 + + # Get mask of QWs where carries shall be propagated to. + # Merge 4-bit masks to 8-bit values to use add with carry. + shl \$4, %r13b + or %r13b, %r14b + shl \$4, %r11b + or %r11b, %r12b + + add %r14b, %r14b + adc %r12b, %r12b + adc %r10b, %r10b + + shl \$4, %r8b + or %r8b,%r9b + shl \$4, %cl + or %cl, %bl + + add %r9b, %r14b + adc %bl, %r12b + adc %dl, %r10b + + xor %r9b, %r14b + xor %bl, %r12b + xor %dl, %r10b + + kmovb %r14d, %k1 + shr \$4, %r14b + kmovb %r14d, %k2 + kmovb %r12d, %k3 + shr \$4, %r12b + kmovb %r12d, %k4 + kmovb %r10d, %k5 + + # Add carries according to the obtained mask + vpsubq $mask52x4, $_R0, ${_R0}{%k1} + vpsubq $mask52x4, $_R0h, ${_R0h}{%k2} + vpsubq $mask52x4, $_R1, ${_R1}{%k3} + vpsubq $mask52x4, $_R1h, ${_R1h}{%k4} + vpsubq $mask52x4, $_R2, ${_R2}{%k5} + + vpandq $mask52x4, $_R0, $_R0 + vpandq $mask52x4, $_R0h, $_R0h + vpandq $mask52x4, $_R1, $_R1 + vpandq $mask52x4, $_R1h, $_R1h + vpandq $mask52x4, $_R2, $_R2 +___ +} + +$code.=<<___; +.text + +.globl ossl_rsaz_amm52x20_x1_256 +.type ossl_rsaz_amm52x20_x1_256,\@function,5 +.align 32 +ossl_rsaz_amm52x20_x1_256: +.cfi_startproc + endbranch + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lrsaz_amm52x20_x1_256_body: + + # Zeroing accumulators + vpxord $zero, $zero, $zero + vmovdqa64 $zero, $R0_0 + vmovdqa64 $zero, $R0_0h + vmovdqa64 $zero, $R1_0 + vmovdqa64 $zero, $R1_0h + vmovdqa64 $zero, $R2_0 + + xorl $acc0_0_low, $acc0_0_low + + movq $b, $b_ptr # backup address of b + movq \$0xfffffffffffff, $mask52 # 52-bit mask + + # Loop over 20 digits unrolled by 4 + mov \$5, $iter + +.align 32 +.Lloop5: +___ + foreach my $idx (0..3) { + &amm52x20_x1(0,8*$idx,$acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0,$k0); + } +$code.=<<___; + lea `4*8`($b_ptr), $b_ptr + dec $iter + jne .Lloop5 + + vmovdqa64 .Lmask52x4(%rip), $mask52x4 +___ + &amm52x20_x1_norm($acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0); +$code.=<<___; + + vmovdqu64 $R0_0, ($res) + vmovdqu64 $R0_0h, 32($res) + vmovdqu64 $R1_0, 64($res) + vmovdqu64 $R1_0h, 96($res) + vmovdqu64 $R2_0, 128($res) + + vzeroupper + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lrsaz_amm52x20_x1_256_epilogue: + ret +.cfi_endproc +.size ossl_rsaz_amm52x20_x1_256, .-ossl_rsaz_amm52x20_x1_256 +___ + +$code.=<<___; +.data +.align 32 +.Lmask52x4: + .quad 0xfffffffffffff + .quad 0xfffffffffffff + .quad 0xfffffffffffff + .quad 0xfffffffffffff +___ + +############################################################################### +# Dual Almost Montgomery Multiplication for 20-digit number in radix 2^52 +# +# See description of ossl_rsaz_amm52x20_x1_256() above for details about Almost +# Montgomery Multiplication algorithm and function input parameters description. +# +# This function does two AMMs for two independent inputs, hence dual. +# +# void ossl_rsaz_amm52x20_x2_256(BN_ULONG out[2][20], +# const BN_ULONG a[2][20], +# const BN_ULONG b[2][20], +# const BN_ULONG m[2][20], +# const BN_ULONG k0[2]); +############################################################################### + +$code.=<<___; +.text + +.globl ossl_rsaz_amm52x20_x2_256 +.type ossl_rsaz_amm52x20_x2_256,\@function,5 +.align 32 +ossl_rsaz_amm52x20_x2_256: +.cfi_startproc + endbranch + push %rbx +.cfi_push %rbx + push %rbp +.cfi_push %rbp + push %r12 +.cfi_push %r12 + push %r13 +.cfi_push %r13 + push %r14 +.cfi_push %r14 + push %r15 +.cfi_push %r15 +.Lrsaz_amm52x20_x2_256_body: + + # Zeroing accumulators + vpxord $zero, $zero, $zero + vmovdqa64 $zero, $R0_0 + vmovdqa64 $zero, $R0_0h + vmovdqa64 $zero, $R1_0 + vmovdqa64 $zero, $R1_0h + vmovdqa64 $zero, $R2_0 + vmovdqa64 $zero, $R0_1 + vmovdqa64 $zero, $R0_1h + vmovdqa64 $zero, $R1_1 + vmovdqa64 $zero, $R1_1h + vmovdqa64 $zero, $R2_1 + + xorl $acc0_0_low, $acc0_0_low + xorl $acc0_1_low, $acc0_1_low + + movq $b, $b_ptr # backup address of b + movq \$0xfffffffffffff, $mask52 # 52-bit mask + + mov \$20, $iter + +.align 32 +.Lloop20: +___ + &amm52x20_x1( 0, 0,$acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0,"($k0)"); + # 20*8 = offset of the next dimension in two-dimension array + &amm52x20_x1(20*8,20*8,$acc0_1,$R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1,"8($k0)"); +$code.=<<___; + lea 8($b_ptr), $b_ptr + dec $iter + jne .Lloop20 + + vmovdqa64 .Lmask52x4(%rip), $mask52x4 +___ + &amm52x20_x1_norm($acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0); + &amm52x20_x1_norm($acc0_1,$R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1); +$code.=<<___; + + vmovdqu64 $R0_0, ($res) + vmovdqu64 $R0_0h, 32($res) + vmovdqu64 $R1_0, 64($res) + vmovdqu64 $R1_0h, 96($res) + vmovdqu64 $R2_0, 128($res) + + vmovdqu64 $R0_1, 160($res) + vmovdqu64 $R0_1h, 192($res) + vmovdqu64 $R1_1, 224($res) + vmovdqu64 $R1_1h, 256($res) + vmovdqu64 $R2_1, 288($res) + + vzeroupper + mov 0(%rsp),%r15 +.cfi_restore %r15 + mov 8(%rsp),%r14 +.cfi_restore %r14 + mov 16(%rsp),%r13 +.cfi_restore %r13 + mov 24(%rsp),%r12 +.cfi_restore %r12 + mov 32(%rsp),%rbp +.cfi_restore %rbp + mov 40(%rsp),%rbx +.cfi_restore %rbx + lea 48(%rsp),%rsp +.cfi_adjust_cfa_offset -48 +.Lrsaz_amm52x20_x2_256_epilogue: + ret +.cfi_endproc +.size ossl_rsaz_amm52x20_x2_256, .-ossl_rsaz_amm52x20_x2_256 +___ +} + +############################################################################### +# Constant time extraction from the precomputed table of powers base^i, where +# i = 0..2^EXP_WIN_SIZE-1 +# +# The input |red_table| contains precomputations for two independent base values, +# so the |tbl_idx| indicates for which base shall we extract the value. +# |red_table_idx| is a power index. +# +# Extracted value (output) is 20 digit number in 2^52 radix. +# +# void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y, +# const BN_ULONG red_table[1 << EXP_WIN_SIZE][2][20], +# int red_table_idx, +# int tbl_idx); # 0 or 1 +# +# EXP_WIN_SIZE = 5 +############################################################################### +{ +# input parameters +my ($out,$red_tbl,$red_tbl_idx,$tbl_idx) = @_6_args_universal_ABI; + +my ($t0,$t1,$t2,$t3,$t4) = map("%ymm$_", (0..4)); +my $t4xmm = $t4; +$t4xmm =~ s/%y/%x/; +my ($tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = map("%ymm$_", (16..20)); +my ($cur_idx,$idx,$ones) = map("%ymm$_", (21..23)); + +$code.=<<___; +.text + +.align 32 +.globl ossl_extract_multiplier_2x20_win5 +.type ossl_extract_multiplier_2x20_win5,\@function,4 +ossl_extract_multiplier_2x20_win5: +.cfi_startproc + endbranch + leaq ($tbl_idx,$tbl_idx,4), %rax + salq \$5, %rax + addq %rax, $red_tbl + + vmovdqa64 .Lones(%rip), $ones # broadcast ones + vpbroadcastq $red_tbl_idx, $idx + leaq `(1<<5)*2*20*8`($red_tbl), %rax # holds end of the tbl + + vpxor $t4xmm, $t4xmm, $t4xmm + vmovdqa64 $t4, $t3 # zeroing t0..4, cur_idx + vmovdqa64 $t4, $t2 + vmovdqa64 $t4, $t1 + vmovdqa64 $t4, $t0 + vmovdqa64 $t4, $cur_idx + +.align 32 +.Lloop: + vpcmpq \$0, $cur_idx, $idx, %k1 # mask of (idx == cur_idx) + addq \$320, $red_tbl # 320 = 2 * 20 digits * 8 bytes + vpaddq $ones, $cur_idx, $cur_idx # increment cur_idx + vmovdqu64 -320($red_tbl), $tmp0 # load data from red_tbl + vmovdqu64 -288($red_tbl), $tmp1 + vmovdqu64 -256($red_tbl), $tmp2 + vmovdqu64 -224($red_tbl), $tmp3 + vmovdqu64 -192($red_tbl), $tmp4 + vpblendmq $tmp0, $t0, ${t0}{%k1} # extract data when mask is not zero + vpblendmq $tmp1, $t1, ${t1}{%k1} + vpblendmq $tmp2, $t2, ${t2}{%k1} + vpblendmq $tmp3, $t3, ${t3}{%k1} + vpblendmq $tmp4, $t4, ${t4}{%k1} + cmpq $red_tbl, %rax + jne .Lloop + + vmovdqu64 $t0, ($out) # store t0..4 + vmovdqu64 $t1, 32($out) + vmovdqu64 $t2, 64($out) + vmovdqu64 $t3, 96($out) + vmovdqu64 $t4, 128($out) + + ret +.cfi_endproc +.size ossl_extract_multiplier_2x20_win5, .-ossl_extract_multiplier_2x20_win5 +___ +$code.=<<___; +.data +.align 32 +.Lones: + .quad 1,1,1,1 +___ +} + +if ($win64) { +$rec="%rcx"; +$frame="%rdx"; +$context="%r8"; +$disp="%r9"; + +$code.=<<___ +.extern __imp_RtlVirtualUnwind +.type rsaz_def_handler,\@abi-omnipotent +.align 16 +rsaz_def_handler: + push %rsi + push %rdi + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + pushfq + sub \$64,%rsp + + mov 120($context),%rax # pull context->Rax + mov 248($context),%rbx # pull context->Rip + + mov 8($disp),%rsi # disp->ImageBase + mov 56($disp),%r11 # disp->HandlerData + + mov 0(%r11),%r10d # HandlerData[0] + lea (%rsi,%r10),%r10 # prologue label + cmp %r10,%rbx # context->Rip<.Lprologue + jb .Lcommon_seh_tail + + mov 152($context),%rax # pull context->Rsp + + mov 4(%r11),%r10d # HandlerData[1] + lea (%rsi,%r10),%r10 # epilogue label + cmp %r10,%rbx # context->Rip>=.Lepilogue + jae .Lcommon_seh_tail + + lea 48(%rax),%rax + + mov -8(%rax),%rbx + mov -16(%rax),%rbp + mov -24(%rax),%r12 + mov -32(%rax),%r13 + mov -40(%rax),%r14 + mov -48(%rax),%r15 + mov %rbx,144($context) # restore context->Rbx + mov %rbp,160($context) # restore context->Rbp + mov %r12,216($context) # restore context->R12 + mov %r13,224($context) # restore context->R13 + mov %r14,232($context) # restore context->R14 + mov %r15,240($context) # restore context->R14 + +.Lcommon_seh_tail: + mov 8(%rax),%rdi + mov 16(%rax),%rsi + mov %rax,152($context) # restore context->Rsp + mov %rsi,168($context) # restore context->Rsi + mov %rdi,176($context) # restore context->Rdi + + mov 40($disp),%rdi # disp->ContextRecord + mov $context,%rsi # context + mov \$154,%ecx # sizeof(CONTEXT) + .long 0xa548f3fc # cld; rep movsq + + mov $disp,%rsi + xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER + mov 8(%rsi),%rdx # arg2, disp->ImageBase + mov 0(%rsi),%r8 # arg3, disp->ControlPc + mov 16(%rsi),%r9 # arg4, disp->FunctionEntry + mov 40(%rsi),%r10 # disp->ContextRecord + lea 56(%rsi),%r11 # &disp->HandlerData + lea 24(%rsi),%r12 # &disp->EstablisherFrame + mov %r10,32(%rsp) # arg5 + mov %r11,40(%rsp) # arg6 + mov %r12,48(%rsp) # arg7 + mov %rcx,56(%rsp) # arg8, (NULL) + call *__imp_RtlVirtualUnwind(%rip) + + mov \$1,%eax # ExceptionContinueSearch + add \$64,%rsp + popfq + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + pop %rdi + pop %rsi + ret +.size rsaz_def_handler,.-rsaz_def_handler + +.section .pdata +.align 4 + .rva .LSEH_begin_ossl_rsaz_amm52x20_x1_256 + .rva .LSEH_end_ossl_rsaz_amm52x20_x1_256 + .rva .LSEH_info_ossl_rsaz_amm52x20_x1_256 + + .rva .LSEH_begin_ossl_rsaz_amm52x20_x2_256 + .rva .LSEH_end_ossl_rsaz_amm52x20_x2_256 + .rva .LSEH_info_ossl_rsaz_amm52x20_x2_256 + + .rva .LSEH_begin_ossl_extract_multiplier_2x20_win5 + .rva .LSEH_end_ossl_extract_multiplier_2x20_win5 + .rva .LSEH_info_ossl_extract_multiplier_2x20_win5 + +.section .xdata +.align 8 +.LSEH_info_ossl_rsaz_amm52x20_x1_256: + .byte 9,0,0,0 + .rva rsaz_def_handler + .rva .Lrsaz_amm52x20_x1_256_body,.Lrsaz_amm52x20_x1_256_epilogue +.LSEH_info_ossl_rsaz_amm52x20_x2_256: + .byte 9,0,0,0 + .rva rsaz_def_handler + .rva .Lrsaz_amm52x20_x2_256_body,.Lrsaz_amm52x20_x2_256_epilogue +.LSEH_info_ossl_extract_multiplier_2x20_win5: + .byte 9,0,0,0 + .rva rsaz_def_handler + .rva .LSEH_begin_ossl_extract_multiplier_2x20_win5,.LSEH_begin_ossl_extract_multiplier_2x20_win5 +___ +} +}}} else {{{ # fallback for old assembler +$code.=<<___; +.text + +.globl ossl_rsaz_avx512ifma_eligible +.type ossl_rsaz_avx512ifma_eligible,\@abi-omnipotent +ossl_rsaz_avx512ifma_eligible: + xor %eax,%eax + ret +.size ossl_rsaz_avx512ifma_eligible, .-ossl_rsaz_avx512ifma_eligible + +.globl ossl_rsaz_amm52x20_x1_256 +.globl ossl_rsaz_amm52x20_x2_256 +.globl ossl_extract_multiplier_2x20_win5 +.type ossl_rsaz_amm52x20_x1_256,\@abi-omnipotent +ossl_rsaz_amm52x20_x1_256: +ossl_rsaz_amm52x20_x2_256: +ossl_extract_multiplier_2x20_win5: + .byte 0x0f,0x0b # ud2 + ret +.size ossl_rsaz_amm52x20_x1_256, .-ossl_rsaz_amm52x20_x1_256 +___ +}}} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl --- a/crypto/bn/asm/rsaz-x86_64.pl +++ b/crypto/bn/asm/rsaz-x86_64.pl @@ -2,7 +2,7 @@ # Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2012, Intel Corporation. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -52,9 +52,10 @@ # purposes; # (**) MULX was attempted, but found to give only marginal improvement; -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -63,7 +64,8 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` diff --git a/crypto/bn/asm/s390x-gf2m.pl b/crypto/bn/asm/s390x-gf2m.pl --- a/crypto/bn/asm/s390x-gf2m.pl +++ b/crypto/bn/asm/s390x-gf2m.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -32,7 +32,10 @@ # so that improvement coefficients can vary from one specific # setup to another. -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /3[12]/) { $SIZE_T=4; @@ -42,8 +45,7 @@ $g="g"; } -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +$output and open STDOUT,">$output"; $stdframe=16*$SIZE_T+4*8; diff --git a/crypto/bn/asm/s390x-mont.pl b/crypto/bn/asm/s390x-mont.pl --- a/crypto/bn/asm/s390x-mont.pl +++ b/crypto/bn/asm/s390x-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -51,7 +51,10 @@ # On z990 it was measured to perform 2.6-2.2 times better than # compiler-generated code, less for longer keys... -$flavour = shift; +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour =~ /3[12]/) { $SIZE_T=4; @@ -61,8 +64,7 @@ $g="g"; } -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} -open STDOUT,">$output"; +$output and open STDOUT,">$output"; $stdframe=16*$SIZE_T+4*8; diff --git a/crypto/bn/asm/s390x.S b/crypto/bn/asm/s390x.S --- a/crypto/bn/asm/s390x.S +++ b/crypto/bn/asm/s390x.S @@ -2,7 +2,7 @@ // ==================================================================== // Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. // -// Licensed under the OpenSSL license (the "License"). You may not use +// 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 // https://www.openssl.org/source/license.html diff --git a/crypto/bn/asm/sparct4-mont.pl b/crypto/bn/asm/sparct4-mont.pl --- a/crypto/bn/asm/sparct4-mont.pl +++ b/crypto/bn/asm/sparct4-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -83,11 +83,13 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "sparcv9_modes.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; $code.=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #ifdef __arch64__ .register %g2,#scratch diff --git a/crypto/bn/asm/sparcv8.S b/crypto/bn/asm/sparcv8.S --- a/crypto/bn/asm/sparcv8.S +++ b/crypto/bn/asm/sparcv8.S @@ -5,7 +5,7 @@ * ==================================================================== * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/asm/sparcv8plus.S b/crypto/bn/asm/sparcv8plus.S --- a/crypto/bn/asm/sparcv8plus.S +++ b/crypto/bn/asm/sparcv8plus.S @@ -3,9 +3,9 @@ /* * ==================================================================== - * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/asm/sparcv9-gf2m.pl b/crypto/bn/asm/sparcv9-gf2m.pl --- a/crypto/bn/asm/sparcv9-gf2m.pl +++ b/crypto/bn/asm/sparcv9-gf2m.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -25,8 +25,7 @@ # ~100-230% faster than gcc-generated code and ~35-90% faster than # the pure SPARCv9 code path. -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; $locals=16*8; @@ -39,7 +38,10 @@ ($lo,$hi,$b)=("%g1",$a8,"%o7"); $a=$lo; $code.=<<___; -#include +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #ifdef __arch64__ .register %g2,#scratch diff --git a/crypto/bn/asm/sparcv9-mont.pl b/crypto/bn/asm/sparcv9-mont.pl --- a/crypto/bn/asm/sparcv9-mont.pl +++ b/crypto/bn/asm/sparcv9-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -49,8 +49,7 @@ # module still have hidden potential [see TODO list there], which is # estimated to be larger than 20%... -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; # int bn_mul_mont( $rp="%i0"; # BN_ULONG *rp, @@ -84,7 +83,10 @@ $fname="bn_mul_mont_int"; $code=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" .section ".text",#alloc,#execinstr diff --git a/crypto/bn/asm/sparcv9a-mont.pl b/crypto/bn/asm/sparcv9a-mont.pl --- a/crypto/bn/asm/sparcv9a-mont.pl +++ b/crypto/bn/asm/sparcv9a-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -62,8 +62,10 @@ # key length, more for longer keys] on USI&II cores and 30-80% - on # USIII&IV. -$output = pop; -open STDOUT,">$output"; +# $output is the last argument if it looks like a file (it has an extension) +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; + +$output and open STDOUT,">$output"; $fname="bn_mul_mont_fpu"; @@ -124,7 +126,10 @@ $ASI_FL16_P=0xD2; # magic ASI value to engage 16-bit FP load $code=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" .section ".text",#alloc,#execinstr diff --git a/crypto/bn/asm/via-mont.pl b/crypto/bn/asm/via-mont.pl --- a/crypto/bn/asm/via-mont.pl +++ b/crypto/bn/asm/via-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -88,8 +88,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0]); diff --git a/crypto/bn/asm/vis3-mont.pl b/crypto/bn/asm/vis3-mont.pl --- a/crypto/bn/asm/vis3-mont.pl +++ b/crypto/bn/asm/vis3-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -25,14 +25,16 @@ # for reference purposes, because T4 has dedicated Montgomery # multiplication and squaring *instructions* that deliver even more. -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; $frame = "STACK_FRAME"; $bias = "STACK_BIAS"; $code.=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #ifdef __arch64__ .register %g2,#scratch diff --git a/crypto/bn/asm/x86-gf2m.pl b/crypto/bn/asm/x86-gf2m.pl --- a/crypto/bn/asm/x86-gf2m.pl +++ b/crypto/bn/asm/x86-gf2m.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -43,8 +43,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386"); diff --git a/crypto/bn/asm/x86-mont.pl b/crypto/bn/asm/x86-mont.pl --- a/crypto/bn/asm/x86-mont.pl +++ b/crypto/bn/asm/x86-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -37,8 +37,7 @@ push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; &asm_init($ARGV[0]); diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c --- a/crypto/bn/asm/x86_64-gcc.c +++ b/crypto/bn/asm/x86_64-gcc.c @@ -1,7 +1,7 @@ /* * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -18,8 +18,7 @@ * project. * * Rights for redistribution and usage in source and binary forms are - * granted according to the OpenSSL license. Warranty of any kind is - * disclaimed. + * granted according to the License. Warranty of any kind is disclaimed. * * Q. Version 0.1? It doesn't sound like Andy, he used to assign real * versions, like 1.0... diff --git a/crypto/bn/asm/x86_64-gf2m.pl b/crypto/bn/asm/x86_64-gf2m.pl --- a/crypto/bn/asm/x86_64-gf2m.pl +++ b/crypto/bn/asm/x86_64-gf2m.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -27,9 +27,10 @@ # these coefficients are not ones for bn_GF2m_mul_2x2 itself, as not # all CPU time is burnt in it... -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -38,7 +39,8 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; ($lo,$hi)=("%rax","%rdx"); $a=$lo; diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl --- a/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/bn/asm/x86_64-mont.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -46,9 +46,10 @@ # # Add MULX/ADOX/ADCX code path. -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -57,7 +58,8 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -31,9 +31,10 @@ # the np argument is not just modulus value, but one interleaved # with 0. This is to optimize post-condition... -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -42,7 +43,8 @@ ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` diff --git a/crypto/bn/bn_add.c b/crypto/bn/bn_add.c --- a/crypto/bn/bn_add.c +++ b/crypto/bn/bn_add.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -136,7 +136,7 @@ dif = max - min; if (dif < 0) { /* hmm... should not be happening */ - BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3); + ERR_raise(ERR_LIB_BN, BN_R_ARG2_LT_ARG3); return 0; } diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c --- a/crypto/bn/bn_asm.c +++ b/crypto/bn/bn_asm.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -1,7 +1,7 @@ /* * Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -20,13 +20,13 @@ bn_check_top(mod); if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -81,7 +81,7 @@ int ret = 0; if ((b->A == NULL) || (b->Ai == NULL)) { - BNerr(BN_F_BN_BLINDING_UPDATE, BN_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); goto err; } @@ -124,7 +124,7 @@ bn_check_top(n); if ((b->A == NULL) || (b->Ai == NULL)) { - BNerr(BN_F_BN_BLINDING_CONVERT_EX, BN_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); return 0; } @@ -158,7 +158,7 @@ bn_check_top(n); if (r == NULL && (r = b->Ai) == NULL) { - BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); return 0; } @@ -256,7 +256,7 @@ do { int rv; - if (!BN_priv_rand_range(ret->A, ret->mod)) + if (!BN_priv_rand_range_ex(ret->A, ret->mod, 0, ctx)) goto err; if (int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv)) break; @@ -268,7 +268,7 @@ goto err; if (retry_counter-- == 0) { - BNerr(BN_F_BN_BLINDING_CREATE_PARAM, BN_R_TOO_MANY_ITERATIONS); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS); goto err; } } while (1); diff --git a/crypto/bn/bn_const.c b/crypto/bn/bn_const.c --- a/crypto/bn/bn_const.c +++ b/crypto/bn/bn_const.c @@ -1,13 +1,17 @@ /* - * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include +#include "crypto/bn_dh.h" + +#define COPY_BN(dst, src) (dst != NULL) ? BN_copy(dst, &src) : BN_dup(&src) + /*- * "First Oakley Default Group" from RFC2409, section 6.1. @@ -80,33 +84,7 @@ BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) { - static const unsigned char RFC3526_PRIME_1536[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), bn); + return COPY_BN(bn, ossl_bignum_modp_1536_p); } /*- @@ -119,41 +97,7 @@ BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) { - static const unsigned char RFC3526_PRIME_2048[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_2048, sizeof(RFC3526_PRIME_2048), bn); + return COPY_BN(bn, ossl_bignum_modp_2048_p); } /*- @@ -166,57 +110,7 @@ BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) { - static const unsigned char RFC3526_PRIME_3072[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_3072, sizeof(RFC3526_PRIME_3072), bn); + return COPY_BN(bn, ossl_bignum_modp_3072_p); } /*- @@ -229,73 +123,7 @@ BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) { - static const unsigned char RFC3526_PRIME_4096[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_4096, sizeof(RFC3526_PRIME_4096), bn); + return COPY_BN(bn, ossl_bignum_modp_4096_p); } /*- @@ -308,105 +136,7 @@ BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) { - static const unsigned char RFC3526_PRIME_6144[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, - 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, - 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, - 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, - 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, - 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, - 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, - 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, - 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, - 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, - 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, - 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, - 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, - 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, - 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, - 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, - 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, - 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, - 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, - 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, - 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, - 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, - 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, - 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, - 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, - 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, - 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, - 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_6144, sizeof(RFC3526_PRIME_6144), bn); + return COPY_BN(bn, ossl_bignum_modp_6144_p); } /*- @@ -419,135 +149,5 @@ BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) { - static const unsigned char RFC3526_PRIME_8192[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, - 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, - 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, - 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, - 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, - 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, - 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, - 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, - 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, - 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, - 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, - 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, - 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, - 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, - 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, - 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, - 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, - 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, - 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, - 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, - 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, - 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, - 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, - 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, - 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, - 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, - 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, - 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, - 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, - 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, - 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, - 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, - 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, - 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, - 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, - 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, - 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, - 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, - 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, - 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, - 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, - 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, - 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, - 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, - 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, - 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, - 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, - 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, - 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, - 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, - 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, - 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, - 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, - 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, - 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, - 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, - 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, - 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, - 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, - 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_8192, sizeof(RFC3526_PRIME_8192), bn); + return COPY_BN(bn, ossl_bignum_modp_8192_p); } diff --git a/crypto/bn/bn_conv.c b/crypto/bn/bn_conv.c new file mode 100644 --- /dev/null +++ b/crypto/bn/bn_conv.c @@ -0,0 +1,291 @@ +/* + * Copyright 1995-2020 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include "crypto/ctype.h" +#include "bn_local.h" + +static const char Hex[] = "0123456789ABCDEF"; + +/* Must 'OPENSSL_free' the returned data */ +char *BN_bn2hex(const BIGNUM *a) +{ + int i, j, v, z = 0; + char *buf; + char *p; + + if (BN_is_zero(a)) + return OPENSSL_strdup("0"); + buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); + if (buf == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + goto err; + } + p = buf; + if (a->neg) + *p++ = '-'; + for (i = a->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 8; j >= 0; j -= 8) { + /* strip leading zeros */ + v = (int)((a->d[i] >> j) & 0xff); + if (z || v != 0) { + *p++ = Hex[v >> 4]; + *p++ = Hex[v & 0x0f]; + z = 1; + } + } + } + *p = '\0'; + err: + return buf; +} + +#ifndef FIPS_MODULE +/* No BIO_snprintf in FIPS_MODULE */ +/* Must 'OPENSSL_free' the returned data */ +char *BN_bn2dec(const BIGNUM *a) +{ + int i = 0, num, ok = 0, n, tbytes; + char *buf = NULL; + char *p; + BIGNUM *t = NULL; + BN_ULONG *bn_data = NULL, *lp; + int bn_data_num; + + /*- + * get an upper bound for the length of the decimal integer + * num <= (BN_num_bits(a) + 1) * log(2) + * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error) + * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1 + */ + i = BN_num_bits(a) * 3; + num = (i / 10 + i / 1000 + 1) + 1; + tbytes = num + 3; /* negative and terminator and one spare? */ + bn_data_num = num / BN_DEC_NUM + 1; + bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); + buf = OPENSSL_malloc(tbytes); + if (buf == NULL || bn_data == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + goto err; + } + if ((t = BN_dup(a)) == NULL) + goto err; + + p = buf; + lp = bn_data; + if (BN_is_zero(t)) { + *p++ = '0'; + *p++ = '\0'; + } else { + if (BN_is_negative(t)) + *p++ = '-'; + + while (!BN_is_zero(t)) { + if (lp - bn_data >= bn_data_num) + goto err; + *lp = BN_div_word(t, BN_DEC_CONV); + if (*lp == (BN_ULONG)-1) + goto err; + lp++; + } + lp--; + /* + * We now have a series of blocks, BN_DEC_NUM chars in length, where + * the last one needs truncation. The blocks need to be reversed in + * order. + */ + n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp); + if (n < 0) + goto err; + p += n; + while (lp != bn_data) { + lp--; + n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp); + if (n < 0) + goto err; + p += n; + } + } + ok = 1; + err: + OPENSSL_free(bn_data); + BN_free(t); + if (ok) + return buf; + OPENSSL_free(buf); + return NULL; +} +#endif + +int BN_hex2bn(BIGNUM **bn, const char *a) +{ + BIGNUM *ret = NULL; + BN_ULONG l = 0; + int neg = 0, h, m, i, j, k, c; + int num; + + if (a == NULL || *a == '\0') + return 0; + + if (*a == '-') { + neg = 1; + a++; + } + + for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++) + continue; + + if (i == 0 || i > INT_MAX / 4) + return 0; + + num = i + neg; + if (bn == NULL) + return num; + + /* a is the start of the hex digits, and it is 'i' long */ + if (*bn == NULL) { + if ((ret = BN_new()) == NULL) + return 0; + } else { + ret = *bn; + if (BN_get_flags(ret, BN_FLG_STATIC_DATA)) { + ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + BN_zero(ret); + } + + /* i is the number of hex digits */ + if (bn_expand(ret, i * 4) == NULL) + goto err; + + j = i; /* least significant 'hex' */ + m = 0; + h = 0; + while (j > 0) { + m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j; + l = 0; + for (;;) { + c = a[j - m]; + k = OPENSSL_hexchar2int(c); + if (k < 0) + k = 0; /* paranoia */ + l = (l << 4) | k; + + if (--m <= 0) { + ret->d[h++] = l; + break; + } + } + j -= BN_BYTES * 2; + } + ret->top = h; + bn_correct_top(ret); + + *bn = ret; + bn_check_top(ret); + /* Don't set the negative flag if it's zero. */ + if (ret->top != 0) + ret->neg = neg; + return num; + err: + if (*bn == NULL) + BN_free(ret); + return 0; +} + +int BN_dec2bn(BIGNUM **bn, const char *a) +{ + BIGNUM *ret = NULL; + BN_ULONG l = 0; + int neg = 0, i, j; + int num; + + if (a == NULL || *a == '\0') + return 0; + if (*a == '-') { + neg = 1; + a++; + } + + for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++) + continue; + + if (i == 0 || i > INT_MAX / 4) + goto err; + + num = i + neg; + if (bn == NULL) + return num; + + /* + * a is the start of the digits, and it is 'i' long. We chop it into + * BN_DEC_NUM digits at a time + */ + if (*bn == NULL) { + if ((ret = BN_new()) == NULL) + return 0; + } else { + ret = *bn; + BN_zero(ret); + } + + /* i is the number of digits, a bit of an over expand */ + if (bn_expand(ret, i * 4) == NULL) + goto err; + + j = BN_DEC_NUM - i % BN_DEC_NUM; + if (j == BN_DEC_NUM) + j = 0; + l = 0; + while (--i >= 0) { + l *= 10; + l += *a - '0'; + a++; + if (++j == BN_DEC_NUM) { + if (!BN_mul_word(ret, BN_DEC_CONV) + || !BN_add_word(ret, l)) + goto err; + l = 0; + j = 0; + } + } + + bn_correct_top(ret); + *bn = ret; + bn_check_top(ret); + /* Don't set the negative flag if it's zero. */ + if (ret->top != 0) + ret->neg = neg; + return num; + err: + if (*bn == NULL) + BN_free(ret); + return 0; +} + +int BN_asc2bn(BIGNUM **bn, const char *a) +{ + const char *p = a; + + if (*p == '-') + p++; + + if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { + if (!BN_hex2bn(bn, p + 2)) + return 0; + } else { + if (!BN_dec2bn(bn, p)) + return 0; + } + /* Don't set the negative flag if it's zero. */ + if (*a == '-' && (*bn)->top != 0) + (*bn)->neg = 1; + return 1; +} diff --git a/crypto/bn/bn_ctx.c b/crypto/bn/bn_ctx.c --- a/crypto/bn/bn_ctx.c +++ b/crypto/bn/bn_ctx.c @@ -1,28 +1,16 @@ /* - * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +#include #include "internal/cryptlib.h" #include "bn_local.h" -/*- - * TODO list - * - * 1. Check a bunch of "(words+1)" type hacks in various bignum functions and - * check they can be safely removed. - * - Check +1 and other ugliness in BN_from_montgomery() - * - * 2. Consider allowing a BN_new_ex() that, at least, lets you specify an - * appropriate 'block' size that will be honoured by bn_expand_internal() to - * prevent piddly little reallocations. OTOH, profiling bignum expansions in - * BN_CTX doesn't show this to be a big issue. - */ - /* How many bignums are in each "pool item"; */ #define BN_CTX_POOL_SIZE 16 /* The stack frame info is resizing, set a first-time expansion size; */ @@ -85,93 +73,105 @@ int too_many; /* Flags. */ int flags; + /* The library context */ + OSSL_LIB_CTX *libctx; }; -/* Enable this to find BN_CTX bugs */ -#ifdef BN_CTX_DEBUG -static const char *ctxdbg_cur = NULL; -static void ctxdbg(BN_CTX *ctx) +#ifndef FIPS_MODULE +/* Debugging functionality */ +static void ctxdbg(BIO *channel, const char *text, BN_CTX *ctx) { unsigned int bnidx = 0, fpidx = 0; BN_POOL_ITEM *item = ctx->pool.head; BN_STACK *stack = &ctx->stack; - fprintf(stderr, "(%16p): ", ctx); + + BIO_printf(channel, "%s\n", text); + BIO_printf(channel, " (%16p): ", (void*)ctx); while (bnidx < ctx->used) { - fprintf(stderr, "%03x ", item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax); + BIO_printf(channel, "%03x ", + item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax); if (!(bnidx % BN_CTX_POOL_SIZE)) item = item->next; } - fprintf(stderr, "\n"); + BIO_printf(channel, "\n"); bnidx = 0; - fprintf(stderr, " : "); + BIO_printf(channel, " %16s : ", ""); while (fpidx < stack->depth) { while (bnidx++ < stack->indexes[fpidx]) - fprintf(stderr, " "); - fprintf(stderr, "^^^ "); + BIO_printf(channel, " "); + BIO_printf(channel, "^^^ "); bnidx++; fpidx++; } - fprintf(stderr, "\n"); + BIO_printf(channel, "\n"); } -# define CTXDBG_ENTRY(str, ctx) do { \ - ctxdbg_cur = (str); \ - fprintf(stderr,"Starting %s\n", ctxdbg_cur); \ - ctxdbg(ctx); \ - } while(0) -# define CTXDBG_EXIT(ctx) do { \ - fprintf(stderr,"Ending %s\n", ctxdbg_cur); \ - ctxdbg(ctx); \ - } while(0) -# define CTXDBG_RET(ctx,ret) +# define CTXDBG(str, ctx) \ + OSSL_TRACE_BEGIN(BN_CTX) { \ + ctxdbg(trc_out, str, ctx); \ + } OSSL_TRACE_END(BN_CTX) #else -# define CTXDBG_ENTRY(str, ctx) -# define CTXDBG_EXIT(ctx) -# define CTXDBG_RET(ctx,ret) -#endif - +/* We do not want tracing in FIPS module */ +# define CTXDBG(str, ctx) do {} while(0) +#endif /* FIPS_MODULE */ -BN_CTX *BN_CTX_new(void) +BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx) { BN_CTX *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } /* Initialise the structure */ BN_POOL_init(&ret->pool); BN_STACK_init(&ret->stack); + ret->libctx = ctx; return ret; } -BN_CTX *BN_CTX_secure_new(void) +#ifndef FIPS_MODULE +BN_CTX *BN_CTX_new(void) { - BN_CTX *ret = BN_CTX_new(); + return BN_CTX_new_ex(NULL); +} +#endif + +BN_CTX *BN_CTX_secure_new_ex(OSSL_LIB_CTX *ctx) +{ + BN_CTX *ret = BN_CTX_new_ex(ctx); if (ret != NULL) ret->flags = BN_FLG_SECURE; return ret; } +#ifndef FIPS_MODULE +BN_CTX *BN_CTX_secure_new(void) +{ + return BN_CTX_secure_new_ex(NULL); +} +#endif + void BN_CTX_free(BN_CTX *ctx) { if (ctx == NULL) return; -#ifdef BN_CTX_DEBUG - { +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(BN_CTX) { BN_POOL_ITEM *pool = ctx->pool.head; - fprintf(stderr, "BN_CTX_free, stack-size=%d, pool-bignums=%d\n", - ctx->stack.size, ctx->pool.size); - fprintf(stderr, "dmaxs: "); + BIO_printf(trc_out, + "BN_CTX_free(): stack-size=%d, pool-bignums=%d\n", + ctx->stack.size, ctx->pool.size); + BIO_printf(trc_out, " dmaxs: "); while (pool) { unsigned loop = 0; while (loop < BN_CTX_POOL_SIZE) - fprintf(stderr, "%02x ", pool->vals[loop++].dmax); + BIO_printf(trc_out, "%02x ", pool->vals[loop++].dmax); pool = pool->next; } - fprintf(stderr, "\n"); - } + BIO_printf(trc_out, "\n"); + } OSSL_TRACE_END(BN_CTX); #endif BN_STACK_finish(&ctx->stack); BN_POOL_finish(&ctx->pool); @@ -180,23 +180,23 @@ void BN_CTX_start(BN_CTX *ctx) { - CTXDBG_ENTRY("BN_CTX_start", ctx); + CTXDBG("ENTER BN_CTX_start()", ctx); /* If we're already overflowing ... */ if (ctx->err_stack || ctx->too_many) ctx->err_stack++; /* (Try to) get a new frame pointer */ else if (!BN_STACK_push(&ctx->stack, ctx->used)) { - BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES); ctx->err_stack++; } - CTXDBG_EXIT(ctx); + CTXDBG("LEAVE BN_CTX_start()", ctx); } void BN_CTX_end(BN_CTX *ctx) { if (ctx == NULL) return; - CTXDBG_ENTRY("BN_CTX_end", ctx); + CTXDBG("ENTER BN_CTX_end()", ctx); if (ctx->err_stack) ctx->err_stack--; else { @@ -208,14 +208,14 @@ /* Unjam "too_many" in case "get" had failed */ ctx->too_many = 0; } - CTXDBG_EXIT(ctx); + CTXDBG("LEAVE BN_CTX_end()", ctx); } BIGNUM *BN_CTX_get(BN_CTX *ctx) { BIGNUM *ret; - CTXDBG_ENTRY("BN_CTX_get", ctx); + CTXDBG("ENTER BN_CTX_get()", ctx); if (ctx->err_stack || ctx->too_many) return NULL; if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) { @@ -224,7 +224,7 @@ * the error stack. */ ctx->too_many = 1; - BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_TEMPORARY_VARIABLES); return NULL; } /* OK, make sure the returned bignum is "zero" */ @@ -232,10 +232,17 @@ /* clear BN_FLG_CONSTTIME if leaked from previous frames */ ret->flags &= (~BN_FLG_CONSTTIME); ctx->used++; - CTXDBG_RET(ctx, ret); + CTXDBG("LEAVE BN_CTX_get()", ctx); return ret; } +OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->libctx; +} + /************/ /* BN_STACK */ /************/ @@ -262,7 +269,7 @@ unsigned int *newitems; if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) { - BNerr(BN_F_BN_STACK_PUSH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return 0; } if (st->depth) @@ -316,7 +323,7 @@ BN_POOL_ITEM *item; if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) { - BNerr(BN_F_BN_POOL_GET, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) { diff --git a/crypto/bn/bn_depr.c b/crypto/bn/bn_depr.c --- a/crypto/bn/bn_depr.c +++ b/crypto/bn/bn_depr.c @@ -1,7 +1,7 @@ /* - * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -13,14 +13,11 @@ */ #include -#if OPENSSL_API_COMPAT >= 0x00908000L -NON_EMPTY_TRANSLATION_UNIT -#else -# include -# include -# include "internal/cryptlib.h" -# include "bn_local.h" +#include +#include +#include "internal/cryptlib.h" +#include "bn_local.h" BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, const BIGNUM *add, const BIGNUM *rem, @@ -52,7 +49,7 @@ { BN_GENCB cb; BN_GENCB_set_old(&cb, callback, cb_arg); - return BN_is_prime_ex(a, checks, ctx_passed, &cb); + return ossl_bn_check_prime(a, checks, ctx_passed, 0, &cb); } int BN_is_prime_fasttest(const BIGNUM *a, int checks, @@ -62,7 +59,5 @@ { BN_GENCB cb; BN_GENCB_set_old(&cb, callback, cb_arg); - return BN_is_prime_fasttest_ex(a, checks, ctx_passed, - do_trial_division, &cb); + return ossl_bn_check_prime(a, checks, ctx_passed, do_trial_division, &cb); } -#endif diff --git a/crypto/bn/bn_dh.c b/crypto/bn/bn_dh.c --- a/crypto/bn/bn_dh.c +++ b/crypto/bn/bn_dh.c @@ -1,7 +1,7 @@ /* - * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,503 +10,1045 @@ #include "bn_local.h" #include "internal/nelem.h" -#ifndef OPENSSL_NO_DH -#include -#include "crypto/bn_dh.h" -/* DH parameters from RFC5114 */ +# include +# include "crypto/bn_dh.h" # if BN_BITS2 == 64 -static const BN_ULONG dh1024_160_p[] = { - 0xDF1FB2BC2E4A4371ULL, 0xE68CFDA76D4DA708ULL, 0x45BF37DF365C1A65ULL, - 0xA151AF5F0DC8B4BDULL, 0xFAA31A4FF55BCCC0ULL, 0x4EFFD6FAE5644738ULL, - 0x98488E9C219A7372ULL, 0xACCBDD7D90C4BD70ULL, 0x24975C3CD49B83BFULL, - 0x13ECB4AEA9061123ULL, 0x9838EF1E2EE652C0ULL, 0x6073E28675A23D18ULL, - 0x9A6A9DCA52D23B61ULL, 0x52C99FBCFB06A3C6ULL, 0xDE92DE5EAE5D54ECULL, - 0xB10B8F96A080E01DULL -}; +# define BN_DEF(lo, hi) (BN_ULONG)hi << 32 | lo +# else +# define BN_DEF(lo, hi) lo, hi +# endif -static const BN_ULONG dh1024_160_g[] = { - 0x855E6EEB22B3B2E5ULL, 0x858F4DCEF97C2A24ULL, 0x2D779D5918D08BC8ULL, - 0xD662A4D18E73AFA3ULL, 0x1DBF0A0169B6A28AULL, 0xA6A24C087A091F53ULL, - 0x909D0D2263F80A76ULL, 0xD7FBD7D3B9A92EE1ULL, 0x5E91547F9E2749F4ULL, - 0x160217B4B01B886AULL, 0x777E690F5504F213ULL, 0x266FEA1E5C41564BULL, - 0xD6406CFF14266D31ULL, 0xF8104DD258AC507FULL, 0x6765A442EFB99905ULL, - 0xA4D1CBD5C3FD3412ULL -}; +/* DH parameters from RFC3526 */ -static const BN_ULONG dh1024_160_q[] = { - 0x64B7CB9D49462353ULL, 0x81A8DF278ABA4E7DULL, 0x00000000F518AA87ULL +# ifndef FIPS_MODULE +/* + * "1536-bit MODP Group" from RFC3526, Section 2. + * + * The prime is: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } + * + * RFC3526 specifies a generator of 2. + * RFC2412 specifies a generator of 22. + */ +static const BN_ULONG modp_1536_p[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xCA237327, 0xF1746C08), + BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907), + BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23), + BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836), + BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651), + BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB), + BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9), + BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D), + BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3), + BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6), + BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B), + BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) }; - -static const BN_ULONG dh2048_224_p[] = { - 0x0AC4DFFE0C10E64FULL, 0xCF9DE5384E71B81CULL, 0x7EF363E2FFA31F71ULL, - 0xE3FB73C16B8E75B9ULL, 0xC9B53DCF4BA80A29ULL, 0x23F10B0E16E79763ULL, - 0xC52172E413042E9BULL, 0xBE60E69CC928B2B9ULL, 0x80CD86A1B9E587E8ULL, - 0x315D75E198C641A4ULL, 0xCDF93ACC44328387ULL, 0x15987D9ADC0A486DULL, - 0x7310F7121FD5A074ULL, 0x278273C7DE31EFDCULL, 0x1602E714415D9330ULL, - 0x81286130BC8985DBULL, 0xB3BF8A3170918836ULL, 0x6A00E0A0B9C49708ULL, - 0xC6BA0B2C8BBC27BEULL, 0xC9F98D11ED34DBF6ULL, 0x7AD5B7D0B6C12207ULL, - 0xD91E8FEF55B7394BULL, 0x9037C9EDEFDA4DF8ULL, 0x6D3F8152AD6AC212ULL, - 0x1DE6B85A1274A0A6ULL, 0xEB3D688A309C180EULL, 0xAF9A3C407BA1DF15ULL, - 0xE6FA141DF95A56DBULL, 0xB54B1597B61D0A75ULL, 0xA20D64E5683B9FD1ULL, - 0xD660FAA79559C51FULL, 0xAD107E1E9123A9D0ULL +/* q = (p - 1) / 2 */ +static const BN_ULONG modp_1536_q[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x6511B993, 0x78BA3604), + BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483), + BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91), + BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B), + BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328), + BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD), + BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174), + BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6), + BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9), + BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53), + BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145), + BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF) }; +# endif /* FIPS_MODULE */ -static const BN_ULONG dh2048_224_g[] = { - 0x84B890D3191F2BFAULL, 0x81BC087F2A7065B3ULL, 0x19C418E1F6EC0179ULL, - 0x7B5A0F1C71CFFF4CULL, 0xEDFE72FE9B6AA4BDULL, 0x81E1BCFE94B30269ULL, - 0x566AFBB48D6C0191ULL, 0xB539CCE3409D13CDULL, 0x6AA21E7F5F2FF381ULL, - 0xD9E263E4770589EFULL, 0x10E183EDD19963DDULL, 0xB70A8137150B8EEBULL, - 0x051AE3D428C8F8ACULL, 0xBB77A86F0C1AB15BULL, 0x6E3025E316A330EFULL, - 0x19529A45D6F83456ULL, 0xF180EB34118E98D1ULL, 0xB5F6C6B250717CBEULL, - 0x09939D54DA7460CDULL, 0xE247150422EA1ED4ULL, 0xB8A762D0521BC98AULL, - 0xF4D027275AC1348BULL, 0xC17669101999024AULL, 0xBE5E9001A8D66AD7ULL, - 0xC57DB17C620A8652ULL, 0xAB739D7700C29F52ULL, 0xDD921F01A70C4AFAULL, - 0xA6824A4E10B9A6F0ULL, 0x74866A08CFE4FFE3ULL, 0x6CDEBE7B89998CAFULL, - 0x9DF30B5C8FFDAC50ULL, 0xAC4032EF4F2D9AE3ULL +/*- + * "2048-bit MODP Group" from RFC3526, Section 3. + * + * The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } + * + * RFC3526 specifies a generator of 2. + */ +static const BN_ULONG modp_2048_p[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x8AACAA68, 0x15728E5A), + BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C), + BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0), + BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C), + BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08), + BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907), + BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23), + BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836), + BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651), + BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB), + BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9), + BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D), + BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3), + BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6), + BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B), + BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) }; - -static const BN_ULONG dh2048_224_q[] = { - 0xBF389A99B36371EBULL, 0x1F80535A4738CEBCULL, 0xC58D93FE99717710ULL, - 0x00000000801C0D34ULL +/* q = (p - 1) / 2 */ +static const BN_ULONG modp_2048_q[] = { + BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x45565534, 0x0AB9472D), + BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE), + BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8), + BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96), + BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604), + BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483), + BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91), + BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B), + BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328), + BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD), + BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174), + BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6), + BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9), + BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53), + BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145), + BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; -static const BN_ULONG dh2048_256_p[] = { - 0xDB094AE91E1A1597ULL, 0x693877FAD7EF09CAULL, 0x6116D2276E11715FULL, - 0xA4B54330C198AF12ULL, 0x75F26375D7014103ULL, 0xC3A3960A54E710C3ULL, - 0xDED4010ABD0BE621ULL, 0xC0B857F689962856ULL, 0xB3CA3F7971506026ULL, - 0x1CCACB83E6B486F6ULL, 0x67E144E514056425ULL, 0xF6A167B5A41825D9ULL, - 0x3AD8347796524D8EULL, 0xF13C6D9A51BFA4ABULL, 0x2D52526735488A0EULL, - 0xB63ACAE1CAA6B790ULL, 0x4FDB70C581B23F76ULL, 0xBC39A0BF12307F5CULL, - 0xB941F54EB1E59BB8ULL, 0x6C5BFC11D45F9088ULL, 0x22E0B1EF4275BF7BULL, - 0x91F9E6725B4758C0ULL, 0x5A8A9D306BCF67EDULL, 0x209E0C6497517ABDULL, - 0x3BF4296D830E9A7CULL, 0x16C3D91134096FAAULL, 0xFAF7DF4561B2AA30ULL, - 0xE00DF8F1D61957D4ULL, 0x5D2CEED4435E3B00ULL, 0x8CEEF608660DD0F2ULL, - 0xFFBBD19C65195999ULL, 0x87A8E61DB4B6663CULL +/*- + * "3072-bit MODP Group" from RFC3526, Section 4. + * + * The prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } + * + * RFC3526 specifies a generator of 2. + */ +static const BN_ULONG modp_3072_p[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xA93AD2CA, 0x4B82D120), + BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0), + BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757), + BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273), + BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226), + BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C), + BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157), + BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB), + BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A), + BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C), + BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0), + BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C), + BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08), + BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907), + BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23), + BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836), + BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651), + BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB), + BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9), + BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D), + BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3), + BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6), + BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B), + BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) }; - -static const BN_ULONG dh2048_256_g[] = { - 0x664B4C0F6CC41659ULL, 0x5E2327CFEF98C582ULL, 0xD647D148D4795451ULL, - 0x2F63078490F00EF8ULL, 0x184B523D1DB246C3ULL, 0xC7891428CDC67EB6ULL, - 0x7FD028370DF92B52ULL, 0xB3353BBB64E0EC37ULL, 0xECD06E1557CD0915ULL, - 0xB7D2BBD2DF016199ULL, 0xC8484B1E052588B9ULL, 0xDB2A3B7313D3FE14ULL, - 0xD052B985D182EA0AULL, 0xA4BD1BFFE83B9C80ULL, 0xDFC967C1FB3F2E55ULL, - 0xB5045AF2767164E1ULL, 0x1D14348F6F2F9193ULL, 0x64E67982428EBC83ULL, - 0x8AC376D282D6ED38ULL, 0x777DE62AAAB8A862ULL, 0xDDF463E5E9EC144BULL, - 0x0196F931C77A57F2ULL, 0xA55AE31341000A65ULL, 0x901228F8C28CBB18ULL, - 0xBC3773BF7E8C6F62ULL, 0xBE3A6C1B0C6B47B1ULL, 0xFF4FED4AAC0BB555ULL, - 0x10DBC15077BE463FULL, 0x07F4793A1A0BA125ULL, 0x4CA7B18F21EF2054ULL, - 0x2E77506660EDBD48ULL, 0x3FB32C9B73134D0BULL +/* q = (p - 1) / 2 */ +static const BN_ULONG modp_3072_q[] = { + BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x549D6965, 0x25C16890), + BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0), + BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB), + BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139), + BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913), + BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746), + BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB), + BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5), + BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D), + BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE), + BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8), + BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96), + BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604), + BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483), + BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91), + BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B), + BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328), + BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD), + BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174), + BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6), + BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9), + BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53), + BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145), + BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; -static const BN_ULONG dh2048_256_q[] = { - 0xA308B0FE64F5FBD3ULL, 0x99B1A47D1EB3750BULL, 0xB447997640129DA2ULL, - 0x8CF83642A709A097ULL +/*- + * "4096-bit MODP Group" from RFC3526, Section 5. + * + * The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } + * + * RFC3526 specifies a generator of 2. + */ +static const BN_ULONG modp_4096_p[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x34063199, 0x4DF435C9), + BN_DEF(0x90A6C08F, 0x86FFB7DC), BN_DEF(0x8D8FDDC1, 0x93B4EA98), + BN_DEF(0xD5B05AA9, 0xD0069127), BN_DEF(0x2170481C, 0xB81BDD76), + BN_DEF(0xCEE2D7AF, 0x1F612970), BN_DEF(0x515BE7ED, 0x233BA186), + BN_DEF(0xA090C3A2, 0x99B2964F), BN_DEF(0x4E6BC05D, 0x287C5947), + BN_DEF(0x1FBECAA6, 0x2E8EFC14), BN_DEF(0x04DE8EF9, 0xDBBBC2DB), + BN_DEF(0x2AD44CE8, 0x2583E9CA), BN_DEF(0xB6150BDA, 0x1A946834), + BN_DEF(0x6AF4E23C, 0x99C32718), BN_DEF(0xBDBA5B26, 0x88719A10), + BN_DEF(0xA787E6D7, 0x1A723C12), BN_DEF(0xA9210801, 0x4B82D120), + BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0), + BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757), + BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273), + BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226), + BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C), + BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157), + BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB), + BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A), + BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C), + BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0), + BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C), + BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08), + BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907), + BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23), + BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836), + BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651), + BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB), + BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9), + BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D), + BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3), + BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6), + BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B), + BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) }; - -/* Primes from RFC 7919 */ -static const BN_ULONG ffdhe2048_p[] = { - 0xFFFFFFFFFFFFFFFFULL, 0x886B423861285C97ULL, 0xC6F34A26C1B2EFFAULL, - 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, - 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, - 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, - 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, - 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, - 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, - 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, - 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, - 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, - 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +/* q = (p - 1) / 2 */ +static const BN_ULONG modp_4096_q[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x9A0318CC, 0xA6FA1AE4), + BN_DEF(0x48536047, 0xC37FDBEE), BN_DEF(0x46C7EEE0, 0xC9DA754C), + BN_DEF(0xEAD82D54, 0x68034893), BN_DEF(0x10B8240E, 0xDC0DEEBB), + BN_DEF(0x67716BD7, 0x8FB094B8), BN_DEF(0x28ADF3F6, 0x119DD0C3), + BN_DEF(0xD04861D1, 0xCCD94B27), BN_DEF(0xA735E02E, 0x143E2CA3), + BN_DEF(0x0FDF6553, 0x97477E0A), BN_DEF(0x826F477C, 0x6DDDE16D), + BN_DEF(0x156A2674, 0x12C1F4E5), BN_DEF(0x5B0A85ED, 0x0D4A341A), + BN_DEF(0x357A711E, 0x4CE1938C), BN_DEF(0x5EDD2D93, 0xC438CD08), + BN_DEF(0x53C3F36B, 0x8D391E09), BN_DEF(0x54908400, 0x25C16890), + BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0), + BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB), + BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139), + BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913), + BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746), + BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB), + BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5), + BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D), + BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE), + BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8), + BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96), + BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604), + BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483), + BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91), + BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B), + BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328), + BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD), + BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174), + BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6), + BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9), + BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53), + BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145), + BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; -static const BN_ULONG ffdhe3072_p[] = { - 0xFFFFFFFFFFFFFFFFULL, 0x25E41D2B66C62E37ULL, 0x3C1B20EE3FD59D7CULL, - 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, - 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, - 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, - 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, - 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, - 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, - 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, - 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, - 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, - 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, - 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, - 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, - 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, - 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, - 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +/*- + * "6144-bit MODP Group" from RFC3526, Section 6. + * + * The prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } + * + * RFC3526 specifies a generator of 2. + */ +static const BN_ULONG modp_6144_p[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x6DCC4024, 0xE694F91E), + BN_DEF(0x0B7474D6, 0x12BF2D5B), BN_DEF(0x3F4860EE, 0x043E8F66), + BN_DEF(0x6E3C0468, 0x387FE8D7), BN_DEF(0x2EF29632, 0xDA56C9EC), + BN_DEF(0xA313D55C, 0xEB19CCB1), BN_DEF(0x8A1FBFF0, 0xF550AA3D), + BN_DEF(0xB7C5DA76, 0x06A1D58B), BN_DEF(0xF29BE328, 0xA79715EE), + BN_DEF(0x0F8037E0, 0x14CC5ED2), BN_DEF(0xBF48E1D8, 0xCC8F6D7E), + BN_DEF(0x2B4154AA, 0x4BD407B2), BN_DEF(0xFF585AC5, 0x0F1D45B7), + BN_DEF(0x36CC88BE, 0x23A97A7E), BN_DEF(0xBEC7E8F3, 0x59E7C97F), + BN_DEF(0x900B1C9E, 0xB5A84031), BN_DEF(0x46980C82, 0xD55E702F), + BN_DEF(0x6E74FEF6, 0xF482D7CE), BN_DEF(0xD1721D03, 0xF032EA15), + BN_DEF(0xC64B92EC, 0x5983CA01), BN_DEF(0x378CD2BF, 0x6FB8F401), + BN_DEF(0x2BD7AF42, 0x33205151), BN_DEF(0xE6CC254B, 0xDB7F1447), + BN_DEF(0xCED4BB1B, 0x44CE6CBA), BN_DEF(0xCF9B14ED, 0xDA3EDBEB), + BN_DEF(0x865A8918, 0x179727B0), BN_DEF(0x9027D831, 0xB06A53ED), + BN_DEF(0x413001AE, 0xE5DB382F), BN_DEF(0xAD9E530E, 0xF8FF9406), + BN_DEF(0x3DBA37BD, 0xC9751E76), BN_DEF(0x602646DE, 0xC1D4DCB2), + BN_DEF(0xD27C7026, 0x36C3FAB4), BN_DEF(0x34028492, 0x4DF435C9), + BN_DEF(0x90A6C08F, 0x86FFB7DC), BN_DEF(0x8D8FDDC1, 0x93B4EA98), + BN_DEF(0xD5B05AA9, 0xD0069127), BN_DEF(0x2170481C, 0xB81BDD76), + BN_DEF(0xCEE2D7AF, 0x1F612970), BN_DEF(0x515BE7ED, 0x233BA186), + BN_DEF(0xA090C3A2, 0x99B2964F), BN_DEF(0x4E6BC05D, 0x287C5947), + BN_DEF(0x1FBECAA6, 0x2E8EFC14), BN_DEF(0x04DE8EF9, 0xDBBBC2DB), + BN_DEF(0x2AD44CE8, 0x2583E9CA), BN_DEF(0xB6150BDA, 0x1A946834), + BN_DEF(0x6AF4E23C, 0x99C32718), BN_DEF(0xBDBA5B26, 0x88719A10), + BN_DEF(0xA787E6D7, 0x1A723C12), BN_DEF(0xA9210801, 0x4B82D120), + BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0), + BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757), + BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273), + BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226), + BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C), + BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157), + BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB), + BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A), + BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C), + BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0), + BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C), + BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08), + BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907), + BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23), + BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836), + BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651), + BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB), + BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9), + BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D), + BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3), + BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6), + BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B), + BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) }; - -static const BN_ULONG ffdhe4096_p[] = { - 0xFFFFFFFFFFFFFFFFULL, 0xC68A007E5E655F6AULL, 0x4DB5A851F44182E1ULL, - 0x8EC9B55A7F88A46BULL, 0x0A8291CDCEC97DCFULL, 0x2A4ECEA9F98D0ACCULL, - 0x1A1DB93D7140003CULL, 0x092999A333CB8B7AULL, 0x6DC778F971AD0038ULL, - 0xA907600A918130C4ULL, 0xED6A1E012D9E6832ULL, 0x7135C886EFB4318AULL, - 0x87F55BA57E31CC7AULL, 0x7763CF1D55034004ULL, 0xAC7D5F42D69F6D18ULL, - 0x7930E9E4E58857B6ULL, 0x6E6F52C3164DF4FBULL, 0x25E41D2B669E1EF1ULL, - 0x3C1B20EE3FD59D7CULL, 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, - 0xABC521979B0DEADAULL, 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, - 0x64F2E21E71F54BFFULL, 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, - 0xAEFE130985139270ULL, 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, - 0x61B46FC9D6E6C907ULL, 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, - 0x886B4238611FCFDCULL, 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, - 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, - 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, - 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, - 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, - 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, - 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, - 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, - 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, - 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, - 0xFFFFFFFFFFFFFFFFULL +/* q = (p - 1) / 2 */ +static const BN_ULONG modp_6144_q[] = { + BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x36E62012, 0x734A7C8F), + BN_DEF(0x85BA3A6B, 0x095F96AD), BN_DEF(0x1FA43077, 0x021F47B3), + BN_DEF(0xB71E0234, 0x1C3FF46B), BN_DEF(0x17794B19, 0x6D2B64F6), + BN_DEF(0xD189EAAE, 0x758CE658), BN_DEF(0xC50FDFF8, 0x7AA8551E), + BN_DEF(0xDBE2ED3B, 0x0350EAC5), BN_DEF(0x794DF194, 0x53CB8AF7), + BN_DEF(0x07C01BF0, 0x0A662F69), BN_DEF(0x5FA470EC, 0x6647B6BF), + BN_DEF(0x15A0AA55, 0xA5EA03D9), BN_DEF(0xFFAC2D62, 0x078EA2DB), + BN_DEF(0x1B66445F, 0x91D4BD3F), BN_DEF(0xDF63F479, 0x2CF3E4BF), + BN_DEF(0xC8058E4F, 0x5AD42018), BN_DEF(0xA34C0641, 0x6AAF3817), + BN_DEF(0x373A7F7B, 0xFA416BE7), BN_DEF(0xE8B90E81, 0x7819750A), + BN_DEF(0xE325C976, 0xACC1E500), BN_DEF(0x9BC6695F, 0x37DC7A00), + BN_DEF(0x95EBD7A1, 0x999028A8), BN_DEF(0xF36612A5, 0xEDBF8A23), + BN_DEF(0x676A5D8D, 0xA267365D), BN_DEF(0xE7CD8A76, 0x6D1F6DF5), + BN_DEF(0x432D448C, 0x8BCB93D8), BN_DEF(0xC813EC18, 0x583529F6), + BN_DEF(0xA09800D7, 0x72ED9C17), BN_DEF(0x56CF2987, 0xFC7FCA03), + BN_DEF(0x1EDD1BDE, 0x64BA8F3B), BN_DEF(0x3013236F, 0x60EA6E59), + BN_DEF(0x693E3813, 0x1B61FD5A), BN_DEF(0x9A014249, 0xA6FA1AE4), + BN_DEF(0x48536047, 0xC37FDBEE), BN_DEF(0x46C7EEE0, 0xC9DA754C), + BN_DEF(0xEAD82D54, 0x68034893), BN_DEF(0x10B8240E, 0xDC0DEEBB), + BN_DEF(0x67716BD7, 0x8FB094B8), BN_DEF(0x28ADF3F6, 0x119DD0C3), + BN_DEF(0xD04861D1, 0xCCD94B27), BN_DEF(0xA735E02E, 0x143E2CA3), + BN_DEF(0x0FDF6553, 0x97477E0A), BN_DEF(0x826F477C, 0x6DDDE16D), + BN_DEF(0x156A2674, 0x12C1F4E5), BN_DEF(0x5B0A85ED, 0x0D4A341A), + BN_DEF(0x357A711E, 0x4CE1938C), BN_DEF(0x5EDD2D93, 0xC438CD08), + BN_DEF(0x53C3F36B, 0x8D391E09), BN_DEF(0x54908400, 0x25C16890), + BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0), + BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB), + BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139), + BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913), + BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746), + BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB), + BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5), + BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D), + BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE), + BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8), + BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96), + BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604), + BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483), + BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91), + BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B), + BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328), + BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD), + BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174), + BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6), + BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9), + BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53), + BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145), + BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; -static const BN_ULONG ffdhe6144_p[] = { - 0xFFFFFFFFFFFFFFFFULL, 0xA40E329CD0E40E65ULL, 0xA41D570D7938DAD4ULL, - 0x62A69526D43161C1ULL, 0x3FDD4A8E9ADB1E69ULL, 0x5B3B71F9DC6B80D6ULL, - 0xEC9D1810C6272B04ULL, 0x8CCF2DD5CACEF403ULL, 0xE49F5235C95B9117ULL, - 0x505DC82DB854338AULL, 0x62292C311562A846ULL, 0xD72B03746AE77F5EULL, - 0xF9C9091B462D538CULL, 0x0AE8DB5847A67CBEULL, 0xB3A739C122611682ULL, - 0xEEAAC0232A281BF6ULL, 0x94C6651E77CAF992ULL, 0x763E4E4B94B2BBC1ULL, - 0x587E38DA0077D9B4ULL, 0x7FB29F8C183023C3ULL, 0x0ABEC1FFF9E3A26EULL, - 0xA00EF092350511E3ULL, 0xB855322EDB6340D8ULL, 0xA52471F7A9A96910ULL, - 0x388147FB4CFDB477ULL, 0x9B1F5C3E4E46041FULL, 0xCDAD0657FCCFEC71ULL, - 0xB38E8C334C701C3AULL, 0x917BDD64B1C0FD4CULL, 0x3BB454329B7624C8ULL, - 0x23BA4442CAF53EA6ULL, 0x4E677D2C38532A3AULL, 0x0BFD64B645036C7AULL, - 0xC68A007E5E0DD902ULL, 0x4DB5A851F44182E1ULL, 0x8EC9B55A7F88A46BULL, - 0x0A8291CDCEC97DCFULL, 0x2A4ECEA9F98D0ACCULL, 0x1A1DB93D7140003CULL, - 0x092999A333CB8B7AULL, 0x6DC778F971AD0038ULL, 0xA907600A918130C4ULL, - 0xED6A1E012D9E6832ULL, 0x7135C886EFB4318AULL, 0x87F55BA57E31CC7AULL, - 0x7763CF1D55034004ULL, 0xAC7D5F42D69F6D18ULL, 0x7930E9E4E58857B6ULL, - 0x6E6F52C3164DF4FBULL, 0x25E41D2B669E1EF1ULL, 0x3C1B20EE3FD59D7CULL, - 0x0ABCD06BFA53DDEFULL, 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, - 0xE86D2BC522363A0DULL, 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, - 0xF4FD4452E2D74DD3ULL, 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, - 0x598CB0FAC186D91CULL, 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, - 0xBC34F4DEF99C0238ULL, 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, - 0xC6F34A26C1B2EFFAULL, 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, - 0xC3FE3B1B4C6FAD73ULL, 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, - 0xC03404CD28342F61ULL, 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, - 0xAE56EDE76372BB19ULL, 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, - 0xD108A94BB2C8E3FBULL, 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, - 0x1DF158A136ADE735ULL, 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, - 0xB557135E7F57C935ULL, 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, - 0xD3DF1ED5D5FD6561ULL, 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, - 0xCC939DCE249B3EF9ULL, 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, - 0xAFDC5620273D3CF1ULL, 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +/* + * "8192-bit MODP Group" from RFC3526, Section 7. + * + * The prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } + * + * RFC3526 specifies a generator of 2. + */ +static const BN_ULONG modp_8192_p[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x98EDD3DF, 0x60C980DD), + BN_DEF(0x80B96E71, 0xC81F56E8), BN_DEF(0x765694DF, 0x9E3050E2), + BN_DEF(0x5677E9AA, 0x9558E447), BN_DEF(0xFC026E47, 0xC9190DA6), + BN_DEF(0xD5EE382B, 0x889A002E), BN_DEF(0x481C6CD7, 0x4009438B), + BN_DEF(0xEB879F92, 0x359046F4), BN_DEF(0x1ECFA268, 0xFAF36BC3), + BN_DEF(0x7EE74D73, 0xB1D510BD), BN_DEF(0x5DED7EA1, 0xF9AB4819), + BN_DEF(0x0846851D, 0x64F31CC5), BN_DEF(0xA0255DC1, 0x4597E899), + BN_DEF(0x74AB6A36, 0xDF310EE0), BN_DEF(0x3F44F82D, 0x6D2A13F8), + BN_DEF(0xB3A278A6, 0x062B3CF5), BN_DEF(0xED5BDD3A, 0x79683303), + BN_DEF(0xA2C087E8, 0xFA9D4B7F), BN_DEF(0x2F8385DD, 0x4BCBC886), + BN_DEF(0x6CEA306B, 0x3473FC64), BN_DEF(0x1A23F0C7, 0x13EB57A8), + BN_DEF(0xA4037C07, 0x22222E04), BN_DEF(0xFC848AD9, 0xE3FDB8BE), + BN_DEF(0xE39D652D, 0x238F16CB), BN_DEF(0x2BF1C978, 0x3423B474), + BN_DEF(0x5AE4F568, 0x3AAB639C), BN_DEF(0x6BA42466, 0x2576F693), + BN_DEF(0x8AFC47ED, 0x741FA7BF), BN_DEF(0x8D9DD300, 0x3BC832B6), + BN_DEF(0x73B931BA, 0xD8BEC4D0), BN_DEF(0xA932DF8C, 0x38777CB6), + BN_DEF(0x12FEE5E4, 0x74A3926F), BN_DEF(0x6DBE1159, 0xE694F91E), + BN_DEF(0x0B7474D6, 0x12BF2D5B), BN_DEF(0x3F4860EE, 0x043E8F66), + BN_DEF(0x6E3C0468, 0x387FE8D7), BN_DEF(0x2EF29632, 0xDA56C9EC), + BN_DEF(0xA313D55C, 0xEB19CCB1), BN_DEF(0x8A1FBFF0, 0xF550AA3D), + BN_DEF(0xB7C5DA76, 0x06A1D58B), BN_DEF(0xF29BE328, 0xA79715EE), + BN_DEF(0x0F8037E0, 0x14CC5ED2), BN_DEF(0xBF48E1D8, 0xCC8F6D7E), + BN_DEF(0x2B4154AA, 0x4BD407B2), BN_DEF(0xFF585AC5, 0x0F1D45B7), + BN_DEF(0x36CC88BE, 0x23A97A7E), BN_DEF(0xBEC7E8F3, 0x59E7C97F), + BN_DEF(0x900B1C9E, 0xB5A84031), BN_DEF(0x46980C82, 0xD55E702F), + BN_DEF(0x6E74FEF6, 0xF482D7CE), BN_DEF(0xD1721D03, 0xF032EA15), + BN_DEF(0xC64B92EC, 0x5983CA01), BN_DEF(0x378CD2BF, 0x6FB8F401), + BN_DEF(0x2BD7AF42, 0x33205151), BN_DEF(0xE6CC254B, 0xDB7F1447), + BN_DEF(0xCED4BB1B, 0x44CE6CBA), BN_DEF(0xCF9B14ED, 0xDA3EDBEB), + BN_DEF(0x865A8918, 0x179727B0), BN_DEF(0x9027D831, 0xB06A53ED), + BN_DEF(0x413001AE, 0xE5DB382F), BN_DEF(0xAD9E530E, 0xF8FF9406), + BN_DEF(0x3DBA37BD, 0xC9751E76), BN_DEF(0x602646DE, 0xC1D4DCB2), + BN_DEF(0xD27C7026, 0x36C3FAB4), BN_DEF(0x34028492, 0x4DF435C9), + BN_DEF(0x90A6C08F, 0x86FFB7DC), BN_DEF(0x8D8FDDC1, 0x93B4EA98), + BN_DEF(0xD5B05AA9, 0xD0069127), BN_DEF(0x2170481C, 0xB81BDD76), + BN_DEF(0xCEE2D7AF, 0x1F612970), BN_DEF(0x515BE7ED, 0x233BA186), + BN_DEF(0xA090C3A2, 0x99B2964F), BN_DEF(0x4E6BC05D, 0x287C5947), + BN_DEF(0x1FBECAA6, 0x2E8EFC14), BN_DEF(0x04DE8EF9, 0xDBBBC2DB), + BN_DEF(0x2AD44CE8, 0x2583E9CA), BN_DEF(0xB6150BDA, 0x1A946834), + BN_DEF(0x6AF4E23C, 0x99C32718), BN_DEF(0xBDBA5B26, 0x88719A10), + BN_DEF(0xA787E6D7, 0x1A723C12), BN_DEF(0xA9210801, 0x4B82D120), + BN_DEF(0xE0FD108E, 0x43DB5BFC), BN_DEF(0x74E5AB31, 0x08E24FA0), + BN_DEF(0xBAD946E2, 0x770988C0), BN_DEF(0x7A615D6C, 0xBBE11757), + BN_DEF(0x177B200C, 0x521F2B18), BN_DEF(0x3EC86A64, 0xD8760273), + BN_DEF(0xD98A0864, 0xF12FFA06), BN_DEF(0x1AD2EE6B, 0xCEE3D226), + BN_DEF(0x4A25619D, 0x1E8C94E0), BN_DEF(0xDB0933D7, 0xABF5AE8C), + BN_DEF(0xA6E1E4C7, 0xB3970F85), BN_DEF(0x5D060C7D, 0x8AEA7157), + BN_DEF(0x58DBEF0A, 0xECFB8504), BN_DEF(0xDF1CBA64, 0xA85521AB), + BN_DEF(0x04507A33, 0xAD33170D), BN_DEF(0x8AAAC42D, 0x15728E5A), + BN_DEF(0x98FA0510, 0x15D22618), BN_DEF(0xEA956AE5, 0x3995497C), + BN_DEF(0x95581718, 0xDE2BCBF6), BN_DEF(0x6F4C52C9, 0xB5C55DF0), + BN_DEF(0xEC07A28F, 0x9B2783A2), BN_DEF(0x180E8603, 0xE39E772C), + BN_DEF(0x2E36CE3B, 0x32905E46), BN_DEF(0xCA18217C, 0xF1746C08), + BN_DEF(0x4ABC9804, 0x670C354E), BN_DEF(0x7096966D, 0x9ED52907), + BN_DEF(0x208552BB, 0x1C62F356), BN_DEF(0xDCA3AD96, 0x83655D23), + BN_DEF(0xFD24CF5F, 0x69163FA8), BN_DEF(0x1C55D39A, 0x98DA4836), + BN_DEF(0xA163BF05, 0xC2007CB8), BN_DEF(0xECE45B3D, 0x49286651), + BN_DEF(0x7C4B1FE6, 0xAE9F2411), BN_DEF(0x5A899FA5, 0xEE386BFB), + BN_DEF(0xF406B7ED, 0x0BFF5CB6), BN_DEF(0xA637ED6B, 0xF44C42E9), + BN_DEF(0x625E7EC6, 0xE485B576), BN_DEF(0x6D51C245, 0x4FE1356D), + BN_DEF(0xF25F1437, 0x302B0A6D), BN_DEF(0xCD3A431B, 0xEF9519B3), + BN_DEF(0x8E3404DD, 0x514A0879), BN_DEF(0x3B139B22, 0x020BBEA6), + BN_DEF(0x8A67CC74, 0x29024E08), BN_DEF(0x80DC1CD1, 0xC4C6628B), + BN_DEF(0x2168C234, 0xC90FDAA2), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) }; - -static const BN_ULONG ffdhe8192_p[] = { - 0xFFFFFFFFFFFFFFFFULL, 0xD68C8BB7C5C6424CULL, 0x011E2A94838FF88CULL, - 0x0822E506A9F4614EULL, 0x97D11D49F7A8443DULL, 0xA6BBFDE530677F0DULL, - 0x2F741EF8C1FE86FEULL, 0xFAFABE1C5D71A87EULL, 0xDED2FBABFBE58A30ULL, - 0xB6855DFE72B0A66EULL, 0x1EFC8CE0BA8A4FE8ULL, 0x83F81D4A3F2FA457ULL, - 0xA1FE3075A577E231ULL, 0xD5B8019488D9C0A0ULL, 0x624816CDAD9A95F9ULL, - 0x99E9E31650C1217BULL, 0x51AA691E0E423CFCULL, 0x1C217E6C3826E52CULL, - 0x51A8A93109703FEEULL, 0xBB7099876A460E74ULL, 0x541FC68C9C86B022ULL, - 0x59160CC046FD8251ULL, 0x2846C0BA35C35F5CULL, 0x54504AC78B758282ULL, - 0x29388839D2AF05E4ULL, 0xCB2C0F1CC01BD702ULL, 0x555B2F747C932665ULL, - 0x86B63142A3AB8829ULL, 0x0B8CC3BDF64B10EFULL, 0x687FEB69EDD1CC5EULL, - 0xFDB23FCEC9509D43ULL, 0x1E425A31D951AE64ULL, 0x36AD004CF600C838ULL, - 0xA40E329CCFF46AAAULL, 0xA41D570D7938DAD4ULL, 0x62A69526D43161C1ULL, - 0x3FDD4A8E9ADB1E69ULL, 0x5B3B71F9DC6B80D6ULL, 0xEC9D1810C6272B04ULL, - 0x8CCF2DD5CACEF403ULL, 0xE49F5235C95B9117ULL, 0x505DC82DB854338AULL, - 0x62292C311562A846ULL, 0xD72B03746AE77F5EULL, 0xF9C9091B462D538CULL, - 0x0AE8DB5847A67CBEULL, 0xB3A739C122611682ULL, 0xEEAAC0232A281BF6ULL, - 0x94C6651E77CAF992ULL, 0x763E4E4B94B2BBC1ULL, 0x587E38DA0077D9B4ULL, - 0x7FB29F8C183023C3ULL, 0x0ABEC1FFF9E3A26EULL, 0xA00EF092350511E3ULL, - 0xB855322EDB6340D8ULL, 0xA52471F7A9A96910ULL, 0x388147FB4CFDB477ULL, - 0x9B1F5C3E4E46041FULL, 0xCDAD0657FCCFEC71ULL, 0xB38E8C334C701C3AULL, - 0x917BDD64B1C0FD4CULL, 0x3BB454329B7624C8ULL, 0x23BA4442CAF53EA6ULL, - 0x4E677D2C38532A3AULL, 0x0BFD64B645036C7AULL, 0xC68A007E5E0DD902ULL, - 0x4DB5A851F44182E1ULL, 0x8EC9B55A7F88A46BULL, 0x0A8291CDCEC97DCFULL, - 0x2A4ECEA9F98D0ACCULL, 0x1A1DB93D7140003CULL, 0x092999A333CB8B7AULL, - 0x6DC778F971AD0038ULL, 0xA907600A918130C4ULL, 0xED6A1E012D9E6832ULL, - 0x7135C886EFB4318AULL, 0x87F55BA57E31CC7AULL, 0x7763CF1D55034004ULL, - 0xAC7D5F42D69F6D18ULL, 0x7930E9E4E58857B6ULL, 0x6E6F52C3164DF4FBULL, - 0x25E41D2B669E1EF1ULL, 0x3C1B20EE3FD59D7CULL, 0x0ABCD06BFA53DDEFULL, - 0x1DBF9A42D5C4484EULL, 0xABC521979B0DEADAULL, 0xE86D2BC522363A0DULL, - 0x5CAE82AB9C9DF69EULL, 0x64F2E21E71F54BFFULL, 0xF4FD4452E2D74DD3ULL, - 0xB4130C93BC437944ULL, 0xAEFE130985139270ULL, 0x598CB0FAC186D91CULL, - 0x7AD91D2691F7F7EEULL, 0x61B46FC9D6E6C907ULL, 0xBC34F4DEF99C0238ULL, - 0xDE355B3B6519035BULL, 0x886B4238611FCFDCULL, 0xC6F34A26C1B2EFFAULL, - 0xC58EF1837D1683B2ULL, 0x3BB5FCBC2EC22005ULL, 0xC3FE3B1B4C6FAD73ULL, - 0x8E4F1232EEF28183ULL, 0x9172FE9CE98583FFULL, 0xC03404CD28342F61ULL, - 0x9E02FCE1CDF7E2ECULL, 0x0B07A7C8EE0A6D70ULL, 0xAE56EDE76372BB19ULL, - 0x1D4F42A3DE394DF4ULL, 0xB96ADAB760D7F468ULL, 0xD108A94BB2C8E3FBULL, - 0xBC0AB182B324FB61ULL, 0x30ACCA4F483A797AULL, 0x1DF158A136ADE735ULL, - 0xE2A689DAF3EFE872ULL, 0x984F0C70E0E68B77ULL, 0xB557135E7F57C935ULL, - 0x856365553DED1AF3ULL, 0x2433F51F5F066ED0ULL, 0xD3DF1ED5D5FD6561ULL, - 0xF681B202AEC4617AULL, 0x7D2FE363630C75D8ULL, 0xCC939DCE249B3EF9ULL, - 0xA9E13641146433FBULL, 0xD8B9C583CE2D3695ULL, 0xAFDC5620273D3CF1ULL, - 0xADF85458A2BB4A9AULL, 0xFFFFFFFFFFFFFFFFULL +/* q = (p - 1) / 2 */ +static const BN_ULONG modp_8192_q[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xCC76E9EF, 0xB064C06E), + BN_DEF(0x405CB738, 0xE40FAB74), BN_DEF(0x3B2B4A6F, 0x4F182871), + BN_DEF(0xAB3BF4D5, 0xCAAC7223), BN_DEF(0x7E013723, 0xE48C86D3), + BN_DEF(0x6AF71C15, 0xC44D0017), BN_DEF(0xA40E366B, 0x2004A1C5), + BN_DEF(0x75C3CFC9, 0x1AC8237A), BN_DEF(0x8F67D134, 0xFD79B5E1), + BN_DEF(0xBF73A6B9, 0xD8EA885E), BN_DEF(0xAEF6BF50, 0xFCD5A40C), + BN_DEF(0x8423428E, 0xB2798E62), BN_DEF(0xD012AEE0, 0x22CBF44C), + BN_DEF(0x3A55B51B, 0xEF988770), BN_DEF(0x1FA27C16, 0x369509FC), + BN_DEF(0xD9D13C53, 0x03159E7A), BN_DEF(0xF6ADEE9D, 0x3CB41981), + BN_DEF(0xD16043F4, 0xFD4EA5BF), BN_DEF(0x17C1C2EE, 0xA5E5E443), + BN_DEF(0x36751835, 0x9A39FE32), BN_DEF(0x0D11F863, 0x89F5ABD4), + BN_DEF(0x5201BE03, 0x91111702), BN_DEF(0x7E42456C, 0xF1FEDC5F), + BN_DEF(0xF1CEB296, 0x11C78B65), BN_DEF(0x15F8E4BC, 0x1A11DA3A), + BN_DEF(0x2D727AB4, 0x1D55B1CE), BN_DEF(0xB5D21233, 0x92BB7B49), + BN_DEF(0xC57E23F6, 0x3A0FD3DF), BN_DEF(0x46CEE980, 0x1DE4195B), + BN_DEF(0x39DC98DD, 0x6C5F6268), BN_DEF(0x54996FC6, 0x1C3BBE5B), + BN_DEF(0x897F72F2, 0xBA51C937), BN_DEF(0x36DF08AC, 0x734A7C8F), + BN_DEF(0x85BA3A6B, 0x095F96AD), BN_DEF(0x1FA43077, 0x021F47B3), + BN_DEF(0xB71E0234, 0x1C3FF46B), BN_DEF(0x17794B19, 0x6D2B64F6), + BN_DEF(0xD189EAAE, 0x758CE658), BN_DEF(0xC50FDFF8, 0x7AA8551E), + BN_DEF(0xDBE2ED3B, 0x0350EAC5), BN_DEF(0x794DF194, 0x53CB8AF7), + BN_DEF(0x07C01BF0, 0x0A662F69), BN_DEF(0x5FA470EC, 0x6647B6BF), + BN_DEF(0x15A0AA55, 0xA5EA03D9), BN_DEF(0xFFAC2D62, 0x078EA2DB), + BN_DEF(0x1B66445F, 0x91D4BD3F), BN_DEF(0xDF63F479, 0x2CF3E4BF), + BN_DEF(0xC8058E4F, 0x5AD42018), BN_DEF(0xA34C0641, 0x6AAF3817), + BN_DEF(0x373A7F7B, 0xFA416BE7), BN_DEF(0xE8B90E81, 0x7819750A), + BN_DEF(0xE325C976, 0xACC1E500), BN_DEF(0x9BC6695F, 0x37DC7A00), + BN_DEF(0x95EBD7A1, 0x999028A8), BN_DEF(0xF36612A5, 0xEDBF8A23), + BN_DEF(0x676A5D8D, 0xA267365D), BN_DEF(0xE7CD8A76, 0x6D1F6DF5), + BN_DEF(0x432D448C, 0x8BCB93D8), BN_DEF(0xC813EC18, 0x583529F6), + BN_DEF(0xA09800D7, 0x72ED9C17), BN_DEF(0x56CF2987, 0xFC7FCA03), + BN_DEF(0x1EDD1BDE, 0x64BA8F3B), BN_DEF(0x3013236F, 0x60EA6E59), + BN_DEF(0x693E3813, 0x1B61FD5A), BN_DEF(0x9A014249, 0xA6FA1AE4), + BN_DEF(0x48536047, 0xC37FDBEE), BN_DEF(0x46C7EEE0, 0xC9DA754C), + BN_DEF(0xEAD82D54, 0x68034893), BN_DEF(0x10B8240E, 0xDC0DEEBB), + BN_DEF(0x67716BD7, 0x8FB094B8), BN_DEF(0x28ADF3F6, 0x119DD0C3), + BN_DEF(0xD04861D1, 0xCCD94B27), BN_DEF(0xA735E02E, 0x143E2CA3), + BN_DEF(0x0FDF6553, 0x97477E0A), BN_DEF(0x826F477C, 0x6DDDE16D), + BN_DEF(0x156A2674, 0x12C1F4E5), BN_DEF(0x5B0A85ED, 0x0D4A341A), + BN_DEF(0x357A711E, 0x4CE1938C), BN_DEF(0x5EDD2D93, 0xC438CD08), + BN_DEF(0x53C3F36B, 0x8D391E09), BN_DEF(0x54908400, 0x25C16890), + BN_DEF(0x707E8847, 0xA1EDADFE), BN_DEF(0x3A72D598, 0x047127D0), + BN_DEF(0x5D6CA371, 0x3B84C460), BN_DEF(0xBD30AEB6, 0x5DF08BAB), + BN_DEF(0x0BBD9006, 0x290F958C), BN_DEF(0x9F643532, 0x6C3B0139), + BN_DEF(0x6CC50432, 0xF897FD03), BN_DEF(0x0D697735, 0xE771E913), + BN_DEF(0x2512B0CE, 0x8F464A70), BN_DEF(0x6D8499EB, 0xD5FAD746), + BN_DEF(0xD370F263, 0xD9CB87C2), BN_DEF(0xAE83063E, 0x457538AB), + BN_DEF(0x2C6DF785, 0x767DC282), BN_DEF(0xEF8E5D32, 0xD42A90D5), + BN_DEF(0x82283D19, 0xD6998B86), BN_DEF(0x45556216, 0x0AB9472D), + BN_DEF(0x4C7D0288, 0x8AE9130C), BN_DEF(0x754AB572, 0x1CCAA4BE), + BN_DEF(0x4AAC0B8C, 0xEF15E5FB), BN_DEF(0x37A62964, 0xDAE2AEF8), + BN_DEF(0x7603D147, 0xCD93C1D1), BN_DEF(0x0C074301, 0xF1CF3B96), + BN_DEF(0x171B671D, 0x19482F23), BN_DEF(0x650C10BE, 0x78BA3604), + BN_DEF(0x255E4C02, 0xB3861AA7), BN_DEF(0xB84B4B36, 0xCF6A9483), + BN_DEF(0x1042A95D, 0x0E3179AB), BN_DEF(0xEE51D6CB, 0xC1B2AE91), + BN_DEF(0x7E9267AF, 0x348B1FD4), BN_DEF(0x0E2AE9CD, 0xCC6D241B), + BN_DEF(0x50B1DF82, 0xE1003E5C), BN_DEF(0xF6722D9E, 0x24943328), + BN_DEF(0xBE258FF3, 0xD74F9208), BN_DEF(0xAD44CFD2, 0xF71C35FD), + BN_DEF(0x7A035BF6, 0x85FFAE5B), BN_DEF(0xD31BF6B5, 0x7A262174), + BN_DEF(0x312F3F63, 0xF242DABB), BN_DEF(0xB6A8E122, 0xA7F09AB6), + BN_DEF(0xF92F8A1B, 0x98158536), BN_DEF(0xE69D218D, 0xF7CA8CD9), + BN_DEF(0xC71A026E, 0x28A5043C), BN_DEF(0x1D89CD91, 0x0105DF53), + BN_DEF(0x4533E63A, 0x94812704), BN_DEF(0xC06E0E68, 0x62633145), + BN_DEF(0x10B4611A, 0xE487ED51), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; -# elif BN_BITS2 == 32 - +/* DH parameters from RFC5114 */ static const BN_ULONG dh1024_160_p[] = { - 0x2E4A4371, 0xDF1FB2BC, 0x6D4DA708, 0xE68CFDA7, 0x365C1A65, 0x45BF37DF, - 0x0DC8B4BD, 0xA151AF5F, 0xF55BCCC0, 0xFAA31A4F, 0xE5644738, 0x4EFFD6FA, - 0x219A7372, 0x98488E9C, 0x90C4BD70, 0xACCBDD7D, 0xD49B83BF, 0x24975C3C, - 0xA9061123, 0x13ECB4AE, 0x2EE652C0, 0x9838EF1E, 0x75A23D18, 0x6073E286, - 0x52D23B61, 0x9A6A9DCA, 0xFB06A3C6, 0x52C99FBC, 0xAE5D54EC, 0xDE92DE5E, - 0xA080E01D, 0xB10B8F96 + BN_DEF(0x2E4A4371, 0xDF1FB2BC), BN_DEF(0x6D4DA708, 0xE68CFDA7), + BN_DEF(0x365C1A65, 0x45BF37DF), BN_DEF(0x0DC8B4BD, 0xA151AF5F), + BN_DEF(0xF55BCCC0, 0xFAA31A4F), BN_DEF(0xE5644738, 0x4EFFD6FA), + BN_DEF(0x219A7372, 0x98488E9C), BN_DEF(0x90C4BD70, 0xACCBDD7D), + BN_DEF(0xD49B83BF, 0x24975C3C), BN_DEF(0xA9061123, 0x13ECB4AE), + BN_DEF(0x2EE652C0, 0x9838EF1E), BN_DEF(0x75A23D18, 0x6073E286), + BN_DEF(0x52D23B61, 0x9A6A9DCA), BN_DEF(0xFB06A3C6, 0x52C99FBC), + BN_DEF(0xAE5D54EC, 0xDE92DE5E), BN_DEF(0xA080E01D, 0xB10B8F96) }; - -static const BN_ULONG dh1024_160_g[] = { - 0x22B3B2E5, 0x855E6EEB, 0xF97C2A24, 0x858F4DCE, 0x18D08BC8, 0x2D779D59, - 0x8E73AFA3, 0xD662A4D1, 0x69B6A28A, 0x1DBF0A01, 0x7A091F53, 0xA6A24C08, - 0x63F80A76, 0x909D0D22, 0xB9A92EE1, 0xD7FBD7D3, 0x9E2749F4, 0x5E91547F, - 0xB01B886A, 0x160217B4, 0x5504F213, 0x777E690F, 0x5C41564B, 0x266FEA1E, - 0x14266D31, 0xD6406CFF, 0x58AC507F, 0xF8104DD2, 0xEFB99905, 0x6765A442, - 0xC3FD3412, 0xA4D1CBD5 -}; - static const BN_ULONG dh1024_160_q[] = { - 0x49462353, 0x64B7CB9D, 0x8ABA4E7D, 0x81A8DF27, 0xF518AA87 + BN_DEF(0x49462353, 0x64B7CB9D), BN_DEF(0x8ABA4E7D, 0x81A8DF27), + (BN_ULONG)0xF518AA87 }; - -static const BN_ULONG dh2048_224_p[] = { - 0x0C10E64F, 0x0AC4DFFE, 0x4E71B81C, 0xCF9DE538, 0xFFA31F71, 0x7EF363E2, - 0x6B8E75B9, 0xE3FB73C1, 0x4BA80A29, 0xC9B53DCF, 0x16E79763, 0x23F10B0E, - 0x13042E9B, 0xC52172E4, 0xC928B2B9, 0xBE60E69C, 0xB9E587E8, 0x80CD86A1, - 0x98C641A4, 0x315D75E1, 0x44328387, 0xCDF93ACC, 0xDC0A486D, 0x15987D9A, - 0x1FD5A074, 0x7310F712, 0xDE31EFDC, 0x278273C7, 0x415D9330, 0x1602E714, - 0xBC8985DB, 0x81286130, 0x70918836, 0xB3BF8A31, 0xB9C49708, 0x6A00E0A0, - 0x8BBC27BE, 0xC6BA0B2C, 0xED34DBF6, 0xC9F98D11, 0xB6C12207, 0x7AD5B7D0, - 0x55B7394B, 0xD91E8FEF, 0xEFDA4DF8, 0x9037C9ED, 0xAD6AC212, 0x6D3F8152, - 0x1274A0A6, 0x1DE6B85A, 0x309C180E, 0xEB3D688A, 0x7BA1DF15, 0xAF9A3C40, - 0xF95A56DB, 0xE6FA141D, 0xB61D0A75, 0xB54B1597, 0x683B9FD1, 0xA20D64E5, - 0x9559C51F, 0xD660FAA7, 0x9123A9D0, 0xAD107E1E +static const BN_ULONG dh1024_160_g[] = { + BN_DEF(0x22B3B2E5, 0x855E6EEB), BN_DEF(0xF97C2A24, 0x858F4DCE), + BN_DEF(0x18D08BC8, 0x2D779D59), BN_DEF(0x8E73AFA3, 0xD662A4D1), + BN_DEF(0x69B6A28A, 0x1DBF0A01), BN_DEF(0x7A091F53, 0xA6A24C08), + BN_DEF(0x63F80A76, 0x909D0D22), BN_DEF(0xB9A92EE1, 0xD7FBD7D3), + BN_DEF(0x9E2749F4, 0x5E91547F), BN_DEF(0xB01B886A, 0x160217B4), + BN_DEF(0x5504F213, 0x777E690F), BN_DEF(0x5C41564B, 0x266FEA1E), + BN_DEF(0x14266D31, 0xD6406CFF), BN_DEF(0x58AC507F, 0xF8104DD2), + BN_DEF(0xEFB99905, 0x6765A442), BN_DEF(0xC3FD3412, 0xA4D1CBD5) }; -static const BN_ULONG dh2048_224_g[] = { - 0x191F2BFA, 0x84B890D3, 0x2A7065B3, 0x81BC087F, 0xF6EC0179, 0x19C418E1, - 0x71CFFF4C, 0x7B5A0F1C, 0x9B6AA4BD, 0xEDFE72FE, 0x94B30269, 0x81E1BCFE, - 0x8D6C0191, 0x566AFBB4, 0x409D13CD, 0xB539CCE3, 0x5F2FF381, 0x6AA21E7F, - 0x770589EF, 0xD9E263E4, 0xD19963DD, 0x10E183ED, 0x150B8EEB, 0xB70A8137, - 0x28C8F8AC, 0x051AE3D4, 0x0C1AB15B, 0xBB77A86F, 0x16A330EF, 0x6E3025E3, - 0xD6F83456, 0x19529A45, 0x118E98D1, 0xF180EB34, 0x50717CBE, 0xB5F6C6B2, - 0xDA7460CD, 0x09939D54, 0x22EA1ED4, 0xE2471504, 0x521BC98A, 0xB8A762D0, - 0x5AC1348B, 0xF4D02727, 0x1999024A, 0xC1766910, 0xA8D66AD7, 0xBE5E9001, - 0x620A8652, 0xC57DB17C, 0x00C29F52, 0xAB739D77, 0xA70C4AFA, 0xDD921F01, - 0x10B9A6F0, 0xA6824A4E, 0xCFE4FFE3, 0x74866A08, 0x89998CAF, 0x6CDEBE7B, - 0x8FFDAC50, 0x9DF30B5C, 0x4F2D9AE3, 0xAC4032EF +static const BN_ULONG dh2048_224_p[] = { + BN_DEF(0x0C10E64F, 0x0AC4DFFE), BN_DEF(0x4E71B81C, 0xCF9DE538), + BN_DEF(0xFFA31F71, 0x7EF363E2), BN_DEF(0x6B8E75B9, 0xE3FB73C1), + BN_DEF(0x4BA80A29, 0xC9B53DCF), BN_DEF(0x16E79763, 0x23F10B0E), + BN_DEF(0x13042E9B, 0xC52172E4), BN_DEF(0xC928B2B9, 0xBE60E69C), + BN_DEF(0xB9E587E8, 0x80CD86A1), BN_DEF(0x98C641A4, 0x315D75E1), + BN_DEF(0x44328387, 0xCDF93ACC), BN_DEF(0xDC0A486D, 0x15987D9A), + BN_DEF(0x1FD5A074, 0x7310F712), BN_DEF(0xDE31EFDC, 0x278273C7), + BN_DEF(0x415D9330, 0x1602E714), BN_DEF(0xBC8985DB, 0x81286130), + BN_DEF(0x70918836, 0xB3BF8A31), BN_DEF(0xB9C49708, 0x6A00E0A0), + BN_DEF(0x8BBC27BE, 0xC6BA0B2C), BN_DEF(0xED34DBF6, 0xC9F98D11), + BN_DEF(0xB6C12207, 0x7AD5B7D0), BN_DEF(0x55B7394B, 0xD91E8FEF), + BN_DEF(0xEFDA4DF8, 0x9037C9ED), BN_DEF(0xAD6AC212, 0x6D3F8152), + BN_DEF(0x1274A0A6, 0x1DE6B85A), BN_DEF(0x309C180E, 0xEB3D688A), + BN_DEF(0x7BA1DF15, 0xAF9A3C40), BN_DEF(0xF95A56DB, 0xE6FA141D), + BN_DEF(0xB61D0A75, 0xB54B1597), BN_DEF(0x683B9FD1, 0xA20D64E5), + BN_DEF(0x9559C51F, 0xD660FAA7), BN_DEF(0x9123A9D0, 0xAD107E1E) }; - static const BN_ULONG dh2048_224_q[] = { - 0xB36371EB, 0xBF389A99, 0x4738CEBC, 0x1F80535A, 0x99717710, 0xC58D93FE, - 0x801C0D34 + BN_DEF(0xB36371EB, 0xBF389A99), BN_DEF(0x4738CEBC, 0x1F80535A), + BN_DEF(0x99717710, 0xC58D93FE), (BN_ULONG)0x801C0D34 }; - -static const BN_ULONG dh2048_256_p[] = { - 0x1E1A1597, 0xDB094AE9, 0xD7EF09CA, 0x693877FA, 0x6E11715F, 0x6116D227, - 0xC198AF12, 0xA4B54330, 0xD7014103, 0x75F26375, 0x54E710C3, 0xC3A3960A, - 0xBD0BE621, 0xDED4010A, 0x89962856, 0xC0B857F6, 0x71506026, 0xB3CA3F79, - 0xE6B486F6, 0x1CCACB83, 0x14056425, 0x67E144E5, 0xA41825D9, 0xF6A167B5, - 0x96524D8E, 0x3AD83477, 0x51BFA4AB, 0xF13C6D9A, 0x35488A0E, 0x2D525267, - 0xCAA6B790, 0xB63ACAE1, 0x81B23F76, 0x4FDB70C5, 0x12307F5C, 0xBC39A0BF, - 0xB1E59BB8, 0xB941F54E, 0xD45F9088, 0x6C5BFC11, 0x4275BF7B, 0x22E0B1EF, - 0x5B4758C0, 0x91F9E672, 0x6BCF67ED, 0x5A8A9D30, 0x97517ABD, 0x209E0C64, - 0x830E9A7C, 0x3BF4296D, 0x34096FAA, 0x16C3D911, 0x61B2AA30, 0xFAF7DF45, - 0xD61957D4, 0xE00DF8F1, 0x435E3B00, 0x5D2CEED4, 0x660DD0F2, 0x8CEEF608, - 0x65195999, 0xFFBBD19C, 0xB4B6663C, 0x87A8E61D +static const BN_ULONG dh2048_224_g[] = { + BN_DEF(0x191F2BFA, 0x84B890D3), BN_DEF(0x2A7065B3, 0x81BC087F), + BN_DEF(0xF6EC0179, 0x19C418E1), BN_DEF(0x71CFFF4C, 0x7B5A0F1C), + BN_DEF(0x9B6AA4BD, 0xEDFE72FE), BN_DEF(0x94B30269, 0x81E1BCFE), + BN_DEF(0x8D6C0191, 0x566AFBB4), BN_DEF(0x409D13CD, 0xB539CCE3), + BN_DEF(0x5F2FF381, 0x6AA21E7F), BN_DEF(0x770589EF, 0xD9E263E4), + BN_DEF(0xD19963DD, 0x10E183ED), BN_DEF(0x150B8EEB, 0xB70A8137), + BN_DEF(0x28C8F8AC, 0x051AE3D4), BN_DEF(0x0C1AB15B, 0xBB77A86F), + BN_DEF(0x16A330EF, 0x6E3025E3), BN_DEF(0xD6F83456, 0x19529A45), + BN_DEF(0x118E98D1, 0xF180EB34), BN_DEF(0x50717CBE, 0xB5F6C6B2), + BN_DEF(0xDA7460CD, 0x09939D54), BN_DEF(0x22EA1ED4, 0xE2471504), + BN_DEF(0x521BC98A, 0xB8A762D0), BN_DEF(0x5AC1348B, 0xF4D02727), + BN_DEF(0x1999024A, 0xC1766910), BN_DEF(0xA8D66AD7, 0xBE5E9001), + BN_DEF(0x620A8652, 0xC57DB17C), BN_DEF(0x00C29F52, 0xAB739D77), + BN_DEF(0xA70C4AFA, 0xDD921F01), BN_DEF(0x10B9A6F0, 0xA6824A4E), + BN_DEF(0xCFE4FFE3, 0x74866A08), BN_DEF(0x89998CAF, 0x6CDEBE7B), + BN_DEF(0x8FFDAC50, 0x9DF30B5C), BN_DEF(0x4F2D9AE3, 0xAC4032EF) }; -static const BN_ULONG dh2048_256_g[] = { - 0x6CC41659, 0x664B4C0F, 0xEF98C582, 0x5E2327CF, 0xD4795451, 0xD647D148, - 0x90F00EF8, 0x2F630784, 0x1DB246C3, 0x184B523D, 0xCDC67EB6, 0xC7891428, - 0x0DF92B52, 0x7FD02837, 0x64E0EC37, 0xB3353BBB, 0x57CD0915, 0xECD06E15, - 0xDF016199, 0xB7D2BBD2, 0x052588B9, 0xC8484B1E, 0x13D3FE14, 0xDB2A3B73, - 0xD182EA0A, 0xD052B985, 0xE83B9C80, 0xA4BD1BFF, 0xFB3F2E55, 0xDFC967C1, - 0x767164E1, 0xB5045AF2, 0x6F2F9193, 0x1D14348F, 0x428EBC83, 0x64E67982, - 0x82D6ED38, 0x8AC376D2, 0xAAB8A862, 0x777DE62A, 0xE9EC144B, 0xDDF463E5, - 0xC77A57F2, 0x0196F931, 0x41000A65, 0xA55AE313, 0xC28CBB18, 0x901228F8, - 0x7E8C6F62, 0xBC3773BF, 0x0C6B47B1, 0xBE3A6C1B, 0xAC0BB555, 0xFF4FED4A, - 0x77BE463F, 0x10DBC150, 0x1A0BA125, 0x07F4793A, 0x21EF2054, 0x4CA7B18F, - 0x60EDBD48, 0x2E775066, 0x73134D0B, 0x3FB32C9B +static const BN_ULONG dh2048_256_p[] = { + BN_DEF(0x1E1A1597, 0xDB094AE9), BN_DEF(0xD7EF09CA, 0x693877FA), + BN_DEF(0x6E11715F, 0x6116D227), BN_DEF(0xC198AF12, 0xA4B54330), + BN_DEF(0xD7014103, 0x75F26375), BN_DEF(0x54E710C3, 0xC3A3960A), + BN_DEF(0xBD0BE621, 0xDED4010A), BN_DEF(0x89962856, 0xC0B857F6), + BN_DEF(0x71506026, 0xB3CA3F79), BN_DEF(0xE6B486F6, 0x1CCACB83), + BN_DEF(0x14056425, 0x67E144E5), BN_DEF(0xA41825D9, 0xF6A167B5), + BN_DEF(0x96524D8E, 0x3AD83477), BN_DEF(0x51BFA4AB, 0xF13C6D9A), + BN_DEF(0x35488A0E, 0x2D525267), BN_DEF(0xCAA6B790, 0xB63ACAE1), + BN_DEF(0x81B23F76, 0x4FDB70C5), BN_DEF(0x12307F5C, 0xBC39A0BF), + BN_DEF(0xB1E59BB8, 0xB941F54E), BN_DEF(0xD45F9088, 0x6C5BFC11), + BN_DEF(0x4275BF7B, 0x22E0B1EF), BN_DEF(0x5B4758C0, 0x91F9E672), + BN_DEF(0x6BCF67ED, 0x5A8A9D30), BN_DEF(0x97517ABD, 0x209E0C64), + BN_DEF(0x830E9A7C, 0x3BF4296D), BN_DEF(0x34096FAA, 0x16C3D911), + BN_DEF(0x61B2AA30, 0xFAF7DF45), BN_DEF(0xD61957D4, 0xE00DF8F1), + BN_DEF(0x435E3B00, 0x5D2CEED4), BN_DEF(0x660DD0F2, 0x8CEEF608), + BN_DEF(0x65195999, 0xFFBBD19C), BN_DEF(0xB4B6663C, 0x87A8E61D) }; - static const BN_ULONG dh2048_256_q[] = { - 0x64F5FBD3, 0xA308B0FE, 0x1EB3750B, 0x99B1A47D, 0x40129DA2, 0xB4479976, - 0xA709A097, 0x8CF83642 + BN_DEF(0x64F5FBD3, 0xA308B0FE), BN_DEF(0x1EB3750B, 0x99B1A47D), + BN_DEF(0x40129DA2, 0xB4479976), BN_DEF(0xA709A097, 0x8CF83642) +}; +static const BN_ULONG dh2048_256_g[] = { + BN_DEF(0x6CC41659, 0x664B4C0F), BN_DEF(0xEF98C582, 0x5E2327CF), + BN_DEF(0xD4795451, 0xD647D148), BN_DEF(0x90F00EF8, 0x2F630784), + BN_DEF(0x1DB246C3, 0x184B523D), BN_DEF(0xCDC67EB6, 0xC7891428), + BN_DEF(0x0DF92B52, 0x7FD02837), BN_DEF(0x64E0EC37, 0xB3353BBB), + BN_DEF(0x57CD0915, 0xECD06E15), BN_DEF(0xDF016199, 0xB7D2BBD2), + BN_DEF(0x052588B9, 0xC8484B1E), BN_DEF(0x13D3FE14, 0xDB2A3B73), + BN_DEF(0xD182EA0A, 0xD052B985), BN_DEF(0xE83B9C80, 0xA4BD1BFF), + BN_DEF(0xFB3F2E55, 0xDFC967C1), BN_DEF(0x767164E1, 0xB5045AF2), + BN_DEF(0x6F2F9193, 0x1D14348F), BN_DEF(0x428EBC83, 0x64E67982), + BN_DEF(0x82D6ED38, 0x8AC376D2), BN_DEF(0xAAB8A862, 0x777DE62A), + BN_DEF(0xE9EC144B, 0xDDF463E5), BN_DEF(0xC77A57F2, 0x0196F931), + BN_DEF(0x41000A65, 0xA55AE313), BN_DEF(0xC28CBB18, 0x901228F8), + BN_DEF(0x7E8C6F62, 0xBC3773BF), BN_DEF(0x0C6B47B1, 0xBE3A6C1B), + BN_DEF(0xAC0BB555, 0xFF4FED4A), BN_DEF(0x77BE463F, 0x10DBC150), + BN_DEF(0x1A0BA125, 0x07F4793A), BN_DEF(0x21EF2054, 0x4CA7B18F), + BN_DEF(0x60EDBD48, 0x2E775066), BN_DEF(0x73134D0B, 0x3FB32C9B) }; /* Primes from RFC 7919 */ - static const BN_ULONG ffdhe2048_p[] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0x61285C97, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, - 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, - 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, - 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, - 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, - 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, - 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, - 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, - 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, - 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, - 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x61285C97, 0x886B4238), + BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183), + BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B), + BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C), + BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1), + BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7), + BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7), + BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182), + BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1), + BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70), + BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555), + BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5), + BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363), + BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641), + BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620), + BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) +}; +/* q = (p - 1) / 2 */ +static const BN_ULONG ffdhe2048_q[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x30942E4B, 0x4435A11C), + BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1), + BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D), + BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E), + BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70), + BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3), + BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B), + BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1), + BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50), + BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638), + BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA), + BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A), + BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1), + BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20), + BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10), + BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; static const BN_ULONG ffdhe3072_p[] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0x66C62E37, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, - 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, - 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, - 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, - 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, - 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, - 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, - 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, - 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, - 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, - 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, - 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, - 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, - 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, - 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, - 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x66C62E37, 0x25E41D2B), + BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B), + BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197), + BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB), + BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452), + BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309), + BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26), + BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE), + BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238), + BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183), + BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B), + BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C), + BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1), + BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7), + BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7), + BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182), + BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1), + BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70), + BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555), + BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5), + BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363), + BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641), + BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620), + BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) +}; +/* q = (p - 1) / 2 */ +static const BN_ULONG ffdhe3072_q[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xB363171B, 0x12F20E95), + BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835), + BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB), + BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155), + BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229), + BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984), + BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93), + BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F), + BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C), + BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1), + BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D), + BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E), + BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70), + BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3), + BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B), + BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1), + BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50), + BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638), + BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA), + BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A), + BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1), + BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20), + BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10), + BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; static const BN_ULONG ffdhe4096_p[] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0x5E655F6A, 0xC68A007E, 0xF44182E1, 0x4DB5A851, - 0x7F88A46B, 0x8EC9B55A, 0xCEC97DCF, 0x0A8291CD, 0xF98D0ACC, 0x2A4ECEA9, - 0x7140003C, 0x1A1DB93D, 0x33CB8B7A, 0x092999A3, 0x71AD0038, 0x6DC778F9, - 0x918130C4, 0xA907600A, 0x2D9E6832, 0xED6A1E01, 0xEFB4318A, 0x7135C886, - 0x7E31CC7A, 0x87F55BA5, 0x55034004, 0x7763CF1D, 0xD69F6D18, 0xAC7D5F42, - 0xE58857B6, 0x7930E9E4, 0x164DF4FB, 0x6E6F52C3, 0x669E1EF1, 0x25E41D2B, - 0x3FD59D7C, 0x3C1B20EE, 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, - 0x9B0DEADA, 0xABC52197, 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, - 0x71F54BFF, 0x64F2E21E, 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, - 0x85139270, 0xAEFE1309, 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, - 0xD6E6C907, 0x61B46FC9, 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, - 0x611FCFDC, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, - 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, - 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, - 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, - 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, - 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, - 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, - 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, - 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, - 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, - 0xFFFFFFFF, 0xFFFFFFFF + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x5E655F6A, 0xC68A007E), + BN_DEF(0xF44182E1, 0x4DB5A851), BN_DEF(0x7F88A46B, 0x8EC9B55A), + BN_DEF(0xCEC97DCF, 0x0A8291CD), BN_DEF(0xF98D0ACC, 0x2A4ECEA9), + BN_DEF(0x7140003C, 0x1A1DB93D), BN_DEF(0x33CB8B7A, 0x092999A3), + BN_DEF(0x71AD0038, 0x6DC778F9), BN_DEF(0x918130C4, 0xA907600A), + BN_DEF(0x2D9E6832, 0xED6A1E01), BN_DEF(0xEFB4318A, 0x7135C886), + BN_DEF(0x7E31CC7A, 0x87F55BA5), BN_DEF(0x55034004, 0x7763CF1D), + BN_DEF(0xD69F6D18, 0xAC7D5F42), BN_DEF(0xE58857B6, 0x7930E9E4), + BN_DEF(0x164DF4FB, 0x6E6F52C3), BN_DEF(0x669E1EF1, 0x25E41D2B), + BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B), + BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197), + BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB), + BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452), + BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309), + BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26), + BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE), + BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238), + BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183), + BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B), + BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C), + BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1), + BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7), + BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7), + BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182), + BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1), + BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70), + BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555), + BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5), + BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363), + BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641), + BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620), + BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) +}; +/* q = (p - 1) / 2 */ +static const BN_ULONG ffdhe4096_q[] = { + BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0x2F32AFB5, 0xE345003F), + BN_DEF(0xFA20C170, 0xA6DAD428), BN_DEF(0x3FC45235, 0xC764DAAD), + BN_DEF(0xE764BEE7, 0x054148E6), BN_DEF(0xFCC68566, 0x15276754), + BN_DEF(0xB8A0001E, 0x0D0EDC9E), BN_DEF(0x99E5C5BD, 0x0494CCD1), + BN_DEF(0xB8D6801C, 0x36E3BC7C), BN_DEF(0x48C09862, 0x5483B005), + BN_DEF(0x96CF3419, 0x76B50F00), BN_DEF(0x77DA18C5, 0x389AE443), + BN_DEF(0xBF18E63D, 0x43FAADD2), BN_DEF(0xAA81A002, 0x3BB1E78E), + BN_DEF(0x6B4FB68C, 0x563EAFA1), BN_DEF(0x72C42BDB, 0xBC9874F2), + BN_DEF(0x8B26FA7D, 0xB737A961), BN_DEF(0xB34F0F78, 0x12F20E95), + BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835), + BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB), + BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155), + BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229), + BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984), + BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93), + BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F), + BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C), + BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1), + BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D), + BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E), + BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70), + BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3), + BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B), + BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1), + BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50), + BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638), + BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA), + BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A), + BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1), + BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20), + BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10), + BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; static const BN_ULONG ffdhe6144_p[] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0xD0E40E65, 0xA40E329C, 0x7938DAD4, 0xA41D570D, - 0xD43161C1, 0x62A69526, 0x9ADB1E69, 0x3FDD4A8E, 0xDC6B80D6, 0x5B3B71F9, - 0xC6272B04, 0xEC9D1810, 0xCACEF403, 0x8CCF2DD5, 0xC95B9117, 0xE49F5235, - 0xB854338A, 0x505DC82D, 0x1562A846, 0x62292C31, 0x6AE77F5E, 0xD72B0374, - 0x462D538C, 0xF9C9091B, 0x47A67CBE, 0x0AE8DB58, 0x22611682, 0xB3A739C1, - 0x2A281BF6, 0xEEAAC023, 0x77CAF992, 0x94C6651E, 0x94B2BBC1, 0x763E4E4B, - 0x0077D9B4, 0x587E38DA, 0x183023C3, 0x7FB29F8C, 0xF9E3A26E, 0x0ABEC1FF, - 0x350511E3, 0xA00EF092, 0xDB6340D8, 0xB855322E, 0xA9A96910, 0xA52471F7, - 0x4CFDB477, 0x388147FB, 0x4E46041F, 0x9B1F5C3E, 0xFCCFEC71, 0xCDAD0657, - 0x4C701C3A, 0xB38E8C33, 0xB1C0FD4C, 0x917BDD64, 0x9B7624C8, 0x3BB45432, - 0xCAF53EA6, 0x23BA4442, 0x38532A3A, 0x4E677D2C, 0x45036C7A, 0x0BFD64B6, - 0x5E0DD902, 0xC68A007E, 0xF44182E1, 0x4DB5A851, 0x7F88A46B, 0x8EC9B55A, - 0xCEC97DCF, 0x0A8291CD, 0xF98D0ACC, 0x2A4ECEA9, 0x7140003C, 0x1A1DB93D, - 0x33CB8B7A, 0x092999A3, 0x71AD0038, 0x6DC778F9, 0x918130C4, 0xA907600A, - 0x2D9E6832, 0xED6A1E01, 0xEFB4318A, 0x7135C886, 0x7E31CC7A, 0x87F55BA5, - 0x55034004, 0x7763CF1D, 0xD69F6D18, 0xAC7D5F42, 0xE58857B6, 0x7930E9E4, - 0x164DF4FB, 0x6E6F52C3, 0x669E1EF1, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, - 0xFA53DDEF, 0x0ABCD06B, 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, - 0x22363A0D, 0xE86D2BC5, 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, - 0xE2D74DD3, 0xF4FD4452, 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, - 0xC186D91C, 0x598CB0FA, 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, - 0xF99C0238, 0xBC34F4DE, 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, - 0xC1B2EFFA, 0xC6F34A26, 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, - 0x4C6FAD73, 0xC3FE3B1B, 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, - 0x28342F61, 0xC03404CD, 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, - 0x6372BB19, 0xAE56EDE7, 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, - 0xB2C8E3FB, 0xD108A94B, 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, - 0x36ADE735, 0x1DF158A1, 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, - 0x7F57C935, 0xB557135E, 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, - 0xD5FD6561, 0xD3DF1ED5, 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, - 0x249B3EF9, 0xCC939DCE, 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, - 0x273D3CF1, 0xAFDC5620, 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xD0E40E65, 0xA40E329C), + BN_DEF(0x7938DAD4, 0xA41D570D), BN_DEF(0xD43161C1, 0x62A69526), + BN_DEF(0x9ADB1E69, 0x3FDD4A8E), BN_DEF(0xDC6B80D6, 0x5B3B71F9), + BN_DEF(0xC6272B04, 0xEC9D1810), BN_DEF(0xCACEF403, 0x8CCF2DD5), + BN_DEF(0xC95B9117, 0xE49F5235), BN_DEF(0xB854338A, 0x505DC82D), + BN_DEF(0x1562A846, 0x62292C31), BN_DEF(0x6AE77F5E, 0xD72B0374), + BN_DEF(0x462D538C, 0xF9C9091B), BN_DEF(0x47A67CBE, 0x0AE8DB58), + BN_DEF(0x22611682, 0xB3A739C1), BN_DEF(0x2A281BF6, 0xEEAAC023), + BN_DEF(0x77CAF992, 0x94C6651E), BN_DEF(0x94B2BBC1, 0x763E4E4B), + BN_DEF(0x0077D9B4, 0x587E38DA), BN_DEF(0x183023C3, 0x7FB29F8C), + BN_DEF(0xF9E3A26E, 0x0ABEC1FF), BN_DEF(0x350511E3, 0xA00EF092), + BN_DEF(0xDB6340D8, 0xB855322E), BN_DEF(0xA9A96910, 0xA52471F7), + BN_DEF(0x4CFDB477, 0x388147FB), BN_DEF(0x4E46041F, 0x9B1F5C3E), + BN_DEF(0xFCCFEC71, 0xCDAD0657), BN_DEF(0x4C701C3A, 0xB38E8C33), + BN_DEF(0xB1C0FD4C, 0x917BDD64), BN_DEF(0x9B7624C8, 0x3BB45432), + BN_DEF(0xCAF53EA6, 0x23BA4442), BN_DEF(0x38532A3A, 0x4E677D2C), + BN_DEF(0x45036C7A, 0x0BFD64B6), BN_DEF(0x5E0DD902, 0xC68A007E), + BN_DEF(0xF44182E1, 0x4DB5A851), BN_DEF(0x7F88A46B, 0x8EC9B55A), + BN_DEF(0xCEC97DCF, 0x0A8291CD), BN_DEF(0xF98D0ACC, 0x2A4ECEA9), + BN_DEF(0x7140003C, 0x1A1DB93D), BN_DEF(0x33CB8B7A, 0x092999A3), + BN_DEF(0x71AD0038, 0x6DC778F9), BN_DEF(0x918130C4, 0xA907600A), + BN_DEF(0x2D9E6832, 0xED6A1E01), BN_DEF(0xEFB4318A, 0x7135C886), + BN_DEF(0x7E31CC7A, 0x87F55BA5), BN_DEF(0x55034004, 0x7763CF1D), + BN_DEF(0xD69F6D18, 0xAC7D5F42), BN_DEF(0xE58857B6, 0x7930E9E4), + BN_DEF(0x164DF4FB, 0x6E6F52C3), BN_DEF(0x669E1EF1, 0x25E41D2B), + BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B), + BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197), + BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB), + BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452), + BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309), + BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26), + BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE), + BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238), + BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183), + BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B), + BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C), + BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1), + BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7), + BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7), + BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182), + BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1), + BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70), + BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555), + BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5), + BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363), + BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641), + BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620), + BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) +}; +/* q = (p - 1) / 2 */ +static const BN_ULONG ffdhe6144_q[] = { + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0x68720732, 0x5207194E), + BN_DEF(0xBC9C6D6A, 0xD20EAB86), BN_DEF(0x6A18B0E0, 0xB1534A93), + BN_DEF(0x4D6D8F34, 0x1FEEA547), BN_DEF(0xEE35C06B, 0x2D9DB8FC), + BN_DEF(0x63139582, 0xF64E8C08), BN_DEF(0xE5677A01, 0xC66796EA), + BN_DEF(0xE4ADC88B, 0x724FA91A), BN_DEF(0xDC2A19C5, 0x282EE416), + BN_DEF(0x8AB15423, 0x31149618), BN_DEF(0x3573BFAF, 0x6B9581BA), + BN_DEF(0xA316A9C6, 0x7CE4848D), BN_DEF(0x23D33E5F, 0x05746DAC), + BN_DEF(0x91308B41, 0x59D39CE0), BN_DEF(0x95140DFB, 0x77556011), + BN_DEF(0x3BE57CC9, 0xCA63328F), BN_DEF(0xCA595DE0, 0x3B1F2725), + BN_DEF(0x003BECDA, 0xAC3F1C6D), BN_DEF(0x0C1811E1, 0x3FD94FC6), + BN_DEF(0xFCF1D137, 0x855F60FF), BN_DEF(0x1A8288F1, 0x50077849), + BN_DEF(0x6DB1A06C, 0x5C2A9917), BN_DEF(0xD4D4B488, 0xD29238FB), + BN_DEF(0xA67EDA3B, 0x9C40A3FD), BN_DEF(0x2723020F, 0xCD8FAE1F), + BN_DEF(0xFE67F638, 0x66D6832B), BN_DEF(0xA6380E1D, 0x59C74619), + BN_DEF(0x58E07EA6, 0x48BDEEB2), BN_DEF(0x4DBB1264, 0x1DDA2A19), + BN_DEF(0x657A9F53, 0x11DD2221), BN_DEF(0x1C29951D, 0x2733BE96), + BN_DEF(0x2281B63D, 0x05FEB25B), BN_DEF(0x2F06EC81, 0xE345003F), + BN_DEF(0xFA20C170, 0xA6DAD428), BN_DEF(0x3FC45235, 0xC764DAAD), + BN_DEF(0xE764BEE7, 0x054148E6), BN_DEF(0xFCC68566, 0x15276754), + BN_DEF(0xB8A0001E, 0x0D0EDC9E), BN_DEF(0x99E5C5BD, 0x0494CCD1), + BN_DEF(0xB8D6801C, 0x36E3BC7C), BN_DEF(0x48C09862, 0x5483B005), + BN_DEF(0x96CF3419, 0x76B50F00), BN_DEF(0x77DA18C5, 0x389AE443), + BN_DEF(0xBF18E63D, 0x43FAADD2), BN_DEF(0xAA81A002, 0x3BB1E78E), + BN_DEF(0x6B4FB68C, 0x563EAFA1), BN_DEF(0x72C42BDB, 0xBC9874F2), + BN_DEF(0x8B26FA7D, 0xB737A961), BN_DEF(0xB34F0F78, 0x12F20E95), + BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835), + BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB), + BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155), + BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229), + BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984), + BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93), + BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F), + BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C), + BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1), + BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D), + BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E), + BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70), + BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3), + BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B), + BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1), + BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50), + BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638), + BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA), + BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A), + BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1), + BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20), + BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10), + BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; static const BN_ULONG ffdhe8192_p[] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0xC5C6424C, 0xD68C8BB7, 0x838FF88C, 0x011E2A94, - 0xA9F4614E, 0x0822E506, 0xF7A8443D, 0x97D11D49, 0x30677F0D, 0xA6BBFDE5, - 0xC1FE86FE, 0x2F741EF8, 0x5D71A87E, 0xFAFABE1C, 0xFBE58A30, 0xDED2FBAB, - 0x72B0A66E, 0xB6855DFE, 0xBA8A4FE8, 0x1EFC8CE0, 0x3F2FA457, 0x83F81D4A, - 0xA577E231, 0xA1FE3075, 0x88D9C0A0, 0xD5B80194, 0xAD9A95F9, 0x624816CD, - 0x50C1217B, 0x99E9E316, 0x0E423CFC, 0x51AA691E, 0x3826E52C, 0x1C217E6C, - 0x09703FEE, 0x51A8A931, 0x6A460E74, 0xBB709987, 0x9C86B022, 0x541FC68C, - 0x46FD8251, 0x59160CC0, 0x35C35F5C, 0x2846C0BA, 0x8B758282, 0x54504AC7, - 0xD2AF05E4, 0x29388839, 0xC01BD702, 0xCB2C0F1C, 0x7C932665, 0x555B2F74, - 0xA3AB8829, 0x86B63142, 0xF64B10EF, 0x0B8CC3BD, 0xEDD1CC5E, 0x687FEB69, - 0xC9509D43, 0xFDB23FCE, 0xD951AE64, 0x1E425A31, 0xF600C838, 0x36AD004C, - 0xCFF46AAA, 0xA40E329C, 0x7938DAD4, 0xA41D570D, 0xD43161C1, 0x62A69526, - 0x9ADB1E69, 0x3FDD4A8E, 0xDC6B80D6, 0x5B3B71F9, 0xC6272B04, 0xEC9D1810, - 0xCACEF403, 0x8CCF2DD5, 0xC95B9117, 0xE49F5235, 0xB854338A, 0x505DC82D, - 0x1562A846, 0x62292C31, 0x6AE77F5E, 0xD72B0374, 0x462D538C, 0xF9C9091B, - 0x47A67CBE, 0x0AE8DB58, 0x22611682, 0xB3A739C1, 0x2A281BF6, 0xEEAAC023, - 0x77CAF992, 0x94C6651E, 0x94B2BBC1, 0x763E4E4B, 0x0077D9B4, 0x587E38DA, - 0x183023C3, 0x7FB29F8C, 0xF9E3A26E, 0x0ABEC1FF, 0x350511E3, 0xA00EF092, - 0xDB6340D8, 0xB855322E, 0xA9A96910, 0xA52471F7, 0x4CFDB477, 0x388147FB, - 0x4E46041F, 0x9B1F5C3E, 0xFCCFEC71, 0xCDAD0657, 0x4C701C3A, 0xB38E8C33, - 0xB1C0FD4C, 0x917BDD64, 0x9B7624C8, 0x3BB45432, 0xCAF53EA6, 0x23BA4442, - 0x38532A3A, 0x4E677D2C, 0x45036C7A, 0x0BFD64B6, 0x5E0DD902, 0xC68A007E, - 0xF44182E1, 0x4DB5A851, 0x7F88A46B, 0x8EC9B55A, 0xCEC97DCF, 0x0A8291CD, - 0xF98D0ACC, 0x2A4ECEA9, 0x7140003C, 0x1A1DB93D, 0x33CB8B7A, 0x092999A3, - 0x71AD0038, 0x6DC778F9, 0x918130C4, 0xA907600A, 0x2D9E6832, 0xED6A1E01, - 0xEFB4318A, 0x7135C886, 0x7E31CC7A, 0x87F55BA5, 0x55034004, 0x7763CF1D, - 0xD69F6D18, 0xAC7D5F42, 0xE58857B6, 0x7930E9E4, 0x164DF4FB, 0x6E6F52C3, - 0x669E1EF1, 0x25E41D2B, 0x3FD59D7C, 0x3C1B20EE, 0xFA53DDEF, 0x0ABCD06B, - 0xD5C4484E, 0x1DBF9A42, 0x9B0DEADA, 0xABC52197, 0x22363A0D, 0xE86D2BC5, - 0x9C9DF69E, 0x5CAE82AB, 0x71F54BFF, 0x64F2E21E, 0xE2D74DD3, 0xF4FD4452, - 0xBC437944, 0xB4130C93, 0x85139270, 0xAEFE1309, 0xC186D91C, 0x598CB0FA, - 0x91F7F7EE, 0x7AD91D26, 0xD6E6C907, 0x61B46FC9, 0xF99C0238, 0xBC34F4DE, - 0x6519035B, 0xDE355B3B, 0x611FCFDC, 0x886B4238, 0xC1B2EFFA, 0xC6F34A26, - 0x7D1683B2, 0xC58EF183, 0x2EC22005, 0x3BB5FCBC, 0x4C6FAD73, 0xC3FE3B1B, - 0xEEF28183, 0x8E4F1232, 0xE98583FF, 0x9172FE9C, 0x28342F61, 0xC03404CD, - 0xCDF7E2EC, 0x9E02FCE1, 0xEE0A6D70, 0x0B07A7C8, 0x6372BB19, 0xAE56EDE7, - 0xDE394DF4, 0x1D4F42A3, 0x60D7F468, 0xB96ADAB7, 0xB2C8E3FB, 0xD108A94B, - 0xB324FB61, 0xBC0AB182, 0x483A797A, 0x30ACCA4F, 0x36ADE735, 0x1DF158A1, - 0xF3EFE872, 0xE2A689DA, 0xE0E68B77, 0x984F0C70, 0x7F57C935, 0xB557135E, - 0x3DED1AF3, 0x85636555, 0x5F066ED0, 0x2433F51F, 0xD5FD6561, 0xD3DF1ED5, - 0xAEC4617A, 0xF681B202, 0x630C75D8, 0x7D2FE363, 0x249B3EF9, 0xCC939DCE, - 0x146433FB, 0xA9E13641, 0xCE2D3695, 0xD8B9C583, 0x273D3CF1, 0xAFDC5620, - 0xA2BB4A9A, 0xADF85458, 0xFFFFFFFF, 0xFFFFFFFF + BN_DEF(0xFFFFFFFF, 0xFFFFFFFF), BN_DEF(0xC5C6424C, 0xD68C8BB7), + BN_DEF(0x838FF88C, 0x011E2A94), BN_DEF(0xA9F4614E, 0x0822E506), + BN_DEF(0xF7A8443D, 0x97D11D49), BN_DEF(0x30677F0D, 0xA6BBFDE5), + BN_DEF(0xC1FE86FE, 0x2F741EF8), BN_DEF(0x5D71A87E, 0xFAFABE1C), + BN_DEF(0xFBE58A30, 0xDED2FBAB), BN_DEF(0x72B0A66E, 0xB6855DFE), + BN_DEF(0xBA8A4FE8, 0x1EFC8CE0), BN_DEF(0x3F2FA457, 0x83F81D4A), + BN_DEF(0xA577E231, 0xA1FE3075), BN_DEF(0x88D9C0A0, 0xD5B80194), + BN_DEF(0xAD9A95F9, 0x624816CD), BN_DEF(0x50C1217B, 0x99E9E316), + BN_DEF(0x0E423CFC, 0x51AA691E), BN_DEF(0x3826E52C, 0x1C217E6C), + BN_DEF(0x09703FEE, 0x51A8A931), BN_DEF(0x6A460E74, 0xBB709987), + BN_DEF(0x9C86B022, 0x541FC68C), BN_DEF(0x46FD8251, 0x59160CC0), + BN_DEF(0x35C35F5C, 0x2846C0BA), BN_DEF(0x8B758282, 0x54504AC7), + BN_DEF(0xD2AF05E4, 0x29388839), BN_DEF(0xC01BD702, 0xCB2C0F1C), + BN_DEF(0x7C932665, 0x555B2F74), BN_DEF(0xA3AB8829, 0x86B63142), + BN_DEF(0xF64B10EF, 0x0B8CC3BD), BN_DEF(0xEDD1CC5E, 0x687FEB69), + BN_DEF(0xC9509D43, 0xFDB23FCE), BN_DEF(0xD951AE64, 0x1E425A31), + BN_DEF(0xF600C838, 0x36AD004C), BN_DEF(0xCFF46AAA, 0xA40E329C), + BN_DEF(0x7938DAD4, 0xA41D570D), BN_DEF(0xD43161C1, 0x62A69526), + BN_DEF(0x9ADB1E69, 0x3FDD4A8E), BN_DEF(0xDC6B80D6, 0x5B3B71F9), + BN_DEF(0xC6272B04, 0xEC9D1810), BN_DEF(0xCACEF403, 0x8CCF2DD5), + BN_DEF(0xC95B9117, 0xE49F5235), BN_DEF(0xB854338A, 0x505DC82D), + BN_DEF(0x1562A846, 0x62292C31), BN_DEF(0x6AE77F5E, 0xD72B0374), + BN_DEF(0x462D538C, 0xF9C9091B), BN_DEF(0x47A67CBE, 0x0AE8DB58), + BN_DEF(0x22611682, 0xB3A739C1), BN_DEF(0x2A281BF6, 0xEEAAC023), + BN_DEF(0x77CAF992, 0x94C6651E), BN_DEF(0x94B2BBC1, 0x763E4E4B), + BN_DEF(0x0077D9B4, 0x587E38DA), BN_DEF(0x183023C3, 0x7FB29F8C), + BN_DEF(0xF9E3A26E, 0x0ABEC1FF), BN_DEF(0x350511E3, 0xA00EF092), + BN_DEF(0xDB6340D8, 0xB855322E), BN_DEF(0xA9A96910, 0xA52471F7), + BN_DEF(0x4CFDB477, 0x388147FB), BN_DEF(0x4E46041F, 0x9B1F5C3E), + BN_DEF(0xFCCFEC71, 0xCDAD0657), BN_DEF(0x4C701C3A, 0xB38E8C33), + BN_DEF(0xB1C0FD4C, 0x917BDD64), BN_DEF(0x9B7624C8, 0x3BB45432), + BN_DEF(0xCAF53EA6, 0x23BA4442), BN_DEF(0x38532A3A, 0x4E677D2C), + BN_DEF(0x45036C7A, 0x0BFD64B6), BN_DEF(0x5E0DD902, 0xC68A007E), + BN_DEF(0xF44182E1, 0x4DB5A851), BN_DEF(0x7F88A46B, 0x8EC9B55A), + BN_DEF(0xCEC97DCF, 0x0A8291CD), BN_DEF(0xF98D0ACC, 0x2A4ECEA9), + BN_DEF(0x7140003C, 0x1A1DB93D), BN_DEF(0x33CB8B7A, 0x092999A3), + BN_DEF(0x71AD0038, 0x6DC778F9), BN_DEF(0x918130C4, 0xA907600A), + BN_DEF(0x2D9E6832, 0xED6A1E01), BN_DEF(0xEFB4318A, 0x7135C886), + BN_DEF(0x7E31CC7A, 0x87F55BA5), BN_DEF(0x55034004, 0x7763CF1D), + BN_DEF(0xD69F6D18, 0xAC7D5F42), BN_DEF(0xE58857B6, 0x7930E9E4), + BN_DEF(0x164DF4FB, 0x6E6F52C3), BN_DEF(0x669E1EF1, 0x25E41D2B), + BN_DEF(0x3FD59D7C, 0x3C1B20EE), BN_DEF(0xFA53DDEF, 0x0ABCD06B), + BN_DEF(0xD5C4484E, 0x1DBF9A42), BN_DEF(0x9B0DEADA, 0xABC52197), + BN_DEF(0x22363A0D, 0xE86D2BC5), BN_DEF(0x9C9DF69E, 0x5CAE82AB), + BN_DEF(0x71F54BFF, 0x64F2E21E), BN_DEF(0xE2D74DD3, 0xF4FD4452), + BN_DEF(0xBC437944, 0xB4130C93), BN_DEF(0x85139270, 0xAEFE1309), + BN_DEF(0xC186D91C, 0x598CB0FA), BN_DEF(0x91F7F7EE, 0x7AD91D26), + BN_DEF(0xD6E6C907, 0x61B46FC9), BN_DEF(0xF99C0238, 0xBC34F4DE), + BN_DEF(0x6519035B, 0xDE355B3B), BN_DEF(0x611FCFDC, 0x886B4238), + BN_DEF(0xC1B2EFFA, 0xC6F34A26), BN_DEF(0x7D1683B2, 0xC58EF183), + BN_DEF(0x2EC22005, 0x3BB5FCBC), BN_DEF(0x4C6FAD73, 0xC3FE3B1B), + BN_DEF(0xEEF28183, 0x8E4F1232), BN_DEF(0xE98583FF, 0x9172FE9C), + BN_DEF(0x28342F61, 0xC03404CD), BN_DEF(0xCDF7E2EC, 0x9E02FCE1), + BN_DEF(0xEE0A6D70, 0x0B07A7C8), BN_DEF(0x6372BB19, 0xAE56EDE7), + BN_DEF(0xDE394DF4, 0x1D4F42A3), BN_DEF(0x60D7F468, 0xB96ADAB7), + BN_DEF(0xB2C8E3FB, 0xD108A94B), BN_DEF(0xB324FB61, 0xBC0AB182), + BN_DEF(0x483A797A, 0x30ACCA4F), BN_DEF(0x36ADE735, 0x1DF158A1), + BN_DEF(0xF3EFE872, 0xE2A689DA), BN_DEF(0xE0E68B77, 0x984F0C70), + BN_DEF(0x7F57C935, 0xB557135E), BN_DEF(0x3DED1AF3, 0x85636555), + BN_DEF(0x5F066ED0, 0x2433F51F), BN_DEF(0xD5FD6561, 0xD3DF1ED5), + BN_DEF(0xAEC4617A, 0xF681B202), BN_DEF(0x630C75D8, 0x7D2FE363), + BN_DEF(0x249B3EF9, 0xCC939DCE), BN_DEF(0x146433FB, 0xA9E13641), + BN_DEF(0xCE2D3695, 0xD8B9C583), BN_DEF(0x273D3CF1, 0xAFDC5620), + BN_DEF(0xA2BB4A9A, 0xADF85458), BN_DEF(0xFFFFFFFF, 0xFFFFFFFF) +}; +/* q = (p - 1) / 2 */ +static const BN_ULONG ffdhe8192_q[] = { + BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), BN_DEF(0xE2E32126, 0x6B4645DB), + BN_DEF(0x41C7FC46, 0x008F154A), BN_DEF(0x54FA30A7, 0x84117283), + BN_DEF(0xFBD4221E, 0xCBE88EA4), BN_DEF(0x9833BF86, 0x535DFEF2), + BN_DEF(0x60FF437F, 0x17BA0F7C), BN_DEF(0x2EB8D43F, 0x7D7D5F0E), + BN_DEF(0xFDF2C518, 0x6F697DD5), BN_DEF(0x39585337, 0x5B42AEFF), + BN_DEF(0x5D4527F4, 0x8F7E4670), BN_DEF(0x1F97D22B, 0xC1FC0EA5), + BN_DEF(0xD2BBF118, 0x50FF183A), BN_DEF(0x446CE050, 0xEADC00CA), + BN_DEF(0xD6CD4AFC, 0xB1240B66), BN_DEF(0x286090BD, 0x4CF4F18B), + BN_DEF(0x07211E7E, 0x28D5348F), BN_DEF(0x1C137296, 0x0E10BF36), + BN_DEF(0x84B81FF7, 0x28D45498), BN_DEF(0xB523073A, 0x5DB84CC3), + BN_DEF(0x4E435811, 0xAA0FE346), BN_DEF(0x237EC128, 0x2C8B0660), + BN_DEF(0x1AE1AFAE, 0x1423605D), BN_DEF(0xC5BAC141, 0x2A282563), + BN_DEF(0xE95782F2, 0x149C441C), BN_DEF(0x600DEB81, 0xE596078E), + BN_DEF(0x3E499332, 0xAAAD97BA), BN_DEF(0x51D5C414, 0xC35B18A1), + BN_DEF(0xFB258877, 0x05C661DE), BN_DEF(0xF6E8E62F, 0xB43FF5B4), + BN_DEF(0x64A84EA1, 0x7ED91FE7), BN_DEF(0xECA8D732, 0x0F212D18), + BN_DEF(0x7B00641C, 0x1B568026), BN_DEF(0x67FA3555, 0x5207194E), + BN_DEF(0xBC9C6D6A, 0xD20EAB86), BN_DEF(0x6A18B0E0, 0xB1534A93), + BN_DEF(0x4D6D8F34, 0x1FEEA547), BN_DEF(0xEE35C06B, 0x2D9DB8FC), + BN_DEF(0x63139582, 0xF64E8C08), BN_DEF(0xE5677A01, 0xC66796EA), + BN_DEF(0xE4ADC88B, 0x724FA91A), BN_DEF(0xDC2A19C5, 0x282EE416), + BN_DEF(0x8AB15423, 0x31149618), BN_DEF(0x3573BFAF, 0x6B9581BA), + BN_DEF(0xA316A9C6, 0x7CE4848D), BN_DEF(0x23D33E5F, 0x05746DAC), + BN_DEF(0x91308B41, 0x59D39CE0), BN_DEF(0x95140DFB, 0x77556011), + BN_DEF(0x3BE57CC9, 0xCA63328F), BN_DEF(0xCA595DE0, 0x3B1F2725), + BN_DEF(0x003BECDA, 0xAC3F1C6D), BN_DEF(0x0C1811E1, 0x3FD94FC6), + BN_DEF(0xFCF1D137, 0x855F60FF), BN_DEF(0x1A8288F1, 0x50077849), + BN_DEF(0x6DB1A06C, 0x5C2A9917), BN_DEF(0xD4D4B488, 0xD29238FB), + BN_DEF(0xA67EDA3B, 0x9C40A3FD), BN_DEF(0x2723020F, 0xCD8FAE1F), + BN_DEF(0xFE67F638, 0x66D6832B), BN_DEF(0xA6380E1D, 0x59C74619), + BN_DEF(0x58E07EA6, 0x48BDEEB2), BN_DEF(0x4DBB1264, 0x1DDA2A19), + BN_DEF(0x657A9F53, 0x11DD2221), BN_DEF(0x1C29951D, 0x2733BE96), + BN_DEF(0x2281B63D, 0x05FEB25B), BN_DEF(0x2F06EC81, 0xE345003F), + BN_DEF(0xFA20C170, 0xA6DAD428), BN_DEF(0x3FC45235, 0xC764DAAD), + BN_DEF(0xE764BEE7, 0x054148E6), BN_DEF(0xFCC68566, 0x15276754), + BN_DEF(0xB8A0001E, 0x0D0EDC9E), BN_DEF(0x99E5C5BD, 0x0494CCD1), + BN_DEF(0xB8D6801C, 0x36E3BC7C), BN_DEF(0x48C09862, 0x5483B005), + BN_DEF(0x96CF3419, 0x76B50F00), BN_DEF(0x77DA18C5, 0x389AE443), + BN_DEF(0xBF18E63D, 0x43FAADD2), BN_DEF(0xAA81A002, 0x3BB1E78E), + BN_DEF(0x6B4FB68C, 0x563EAFA1), BN_DEF(0x72C42BDB, 0xBC9874F2), + BN_DEF(0x8B26FA7D, 0xB737A961), BN_DEF(0xB34F0F78, 0x12F20E95), + BN_DEF(0x1FEACEBE, 0x9E0D9077), BN_DEF(0xFD29EEF7, 0x055E6835), + BN_DEF(0x6AE22427, 0x0EDFCD21), BN_DEF(0xCD86F56D, 0xD5E290CB), + BN_DEF(0x911B1D06, 0x743695E2), BN_DEF(0xCE4EFB4F, 0xAE574155), + BN_DEF(0x38FAA5FF, 0xB279710F), BN_DEF(0x716BA6E9, 0x7A7EA229), + BN_DEF(0xDE21BCA2, 0x5A098649), BN_DEF(0xC289C938, 0x577F0984), + BN_DEF(0x60C36C8E, 0x2CC6587D), BN_DEF(0x48FBFBF7, 0xBD6C8E93), + BN_DEF(0xEB736483, 0x30DA37E4), BN_DEF(0x7CCE011C, 0xDE1A7A6F), + BN_DEF(0xB28C81AD, 0x6F1AAD9D), BN_DEF(0x308FE7EE, 0x4435A11C), + BN_DEF(0x60D977FD, 0x6379A513), BN_DEF(0xBE8B41D9, 0xE2C778C1), + BN_DEF(0x17611002, 0x9DDAFE5E), BN_DEF(0xA637D6B9, 0xE1FF1D8D), + BN_DEF(0x777940C1, 0xC7278919), BN_DEF(0x74C2C1FF, 0xC8B97F4E), + BN_DEF(0x941A17B0, 0x601A0266), BN_DEF(0xE6FBF176, 0x4F017E70), + BN_DEF(0x770536B8, 0x8583D3E4), BN_DEF(0xB1B95D8C, 0x572B76F3), + BN_DEF(0xEF1CA6FA, 0x0EA7A151), BN_DEF(0xB06BFA34, 0xDCB56D5B), + BN_DEF(0xD96471FD, 0xE88454A5), BN_DEF(0x59927DB0, 0x5E0558C1), + BN_DEF(0xA41D3CBD, 0x98566527), BN_DEF(0x9B56F39A, 0x0EF8AC50), + BN_DEF(0x79F7F439, 0xF15344ED), BN_DEF(0x707345BB, 0xCC278638), + BN_DEF(0x3FABE49A, 0xDAAB89AF), BN_DEF(0x9EF68D79, 0x42B1B2AA), + BN_DEF(0xAF833768, 0x9219FA8F), BN_DEF(0xEAFEB2B0, 0x69EF8F6A), + BN_DEF(0x576230BD, 0x7B40D901), BN_DEF(0xB1863AEC, 0xBE97F1B1), + BN_DEF(0x124D9F7C, 0xE649CEE7), BN_DEF(0x8A3219FD, 0xD4F09B20), + BN_DEF(0xE7169B4A, 0xEC5CE2C1), BN_DEF(0x139E9E78, 0x57EE2B10), + BN_DEF(0x515DA54D, 0xD6FC2A2C), BN_DEF(0xFFFFFFFF, 0x7FFFFFFF), }; - -# else -# error "unsupported BN_BITS2" -# endif /* Macro to make a BIGNUM from static data */ -# define make_dh_bn(x) extern const BIGNUM _bignum_##x; \ - const BIGNUM _bignum_##x = { (BN_ULONG *) x, \ - OSSL_NELEM(x),\ - OSSL_NELEM(x),\ - 0, BN_FLG_STATIC_DATA }; +# define make_dh_bn(x) \ + extern const BIGNUM ossl_bignum_##x; \ + const BIGNUM ossl_bignum_##x = { \ + (BN_ULONG *) x, \ + OSSL_NELEM(x), \ + OSSL_NELEM(x), \ + 0, BN_FLG_STATIC_DATA }; static const BN_ULONG value_2 = 2; -const BIGNUM _bignum_const_2 = - { (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA }; +const BIGNUM ossl_bignum_const_2 = { + (BN_ULONG *)&value_2, 1, 1, 0, BN_FLG_STATIC_DATA +}; make_dh_bn(dh1024_160_p) -make_dh_bn(dh1024_160_g) make_dh_bn(dh1024_160_q) +make_dh_bn(dh1024_160_g) make_dh_bn(dh2048_224_p) -make_dh_bn(dh2048_224_g) make_dh_bn(dh2048_224_q) +make_dh_bn(dh2048_224_g) make_dh_bn(dh2048_256_p) -make_dh_bn(dh2048_256_g) make_dh_bn(dh2048_256_q) +make_dh_bn(dh2048_256_g) make_dh_bn(ffdhe2048_p) +make_dh_bn(ffdhe2048_q) make_dh_bn(ffdhe3072_p) +make_dh_bn(ffdhe3072_q) make_dh_bn(ffdhe4096_p) +make_dh_bn(ffdhe4096_q) make_dh_bn(ffdhe6144_p) +make_dh_bn(ffdhe6144_q) make_dh_bn(ffdhe8192_p) +make_dh_bn(ffdhe8192_q) - -#endif +# ifndef FIPS_MODULE +make_dh_bn(modp_1536_p) +make_dh_bn(modp_1536_q) +# endif +make_dh_bn(modp_2048_p) +make_dh_bn(modp_2048_q) +make_dh_bn(modp_3072_p) +make_dh_bn(modp_3072_q) +make_dh_bn(modp_4096_p) +make_dh_bn(modp_4096_q) +make_dh_bn(modp_6144_p) +make_dh_bn(modp_6144_q) +make_dh_bn(modp_8192_p) +make_dh_bn(modp_8192_q) diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c --- a/crypto/bn/bn_div.c +++ b/crypto/bn/bn_div.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -24,7 +24,7 @@ bn_check_top(m); bn_check_top(d); if (BN_is_zero(d)) { - BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); + ERR_raise(ERR_LIB_BN, BN_R_DIV_BY_ZERO); return 0; } @@ -97,7 +97,7 @@ */ # if BN_BITS2 == 64 && defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 # undef BN_ULLONG -# define BN_ULLONG __uint128_t +# define BN_ULLONG uint128_t # define BN_LLONG # endif @@ -212,7 +212,7 @@ int ret; if (BN_is_zero(divisor)) { - BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); + ERR_raise(ERR_LIB_BN, BN_R_DIV_BY_ZERO); return 0; } @@ -222,7 +222,7 @@ * BN_DEBUG builds) */ if (divisor->d[divisor->top - 1] == 0) { - BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_BN, BN_R_NOT_INITIALIZED); return 0; } diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c --- a/crypto/bn/bn_err.c +++ b/crypto/bn/bn_err.c @@ -1,8 +1,8 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,74 +10,10 @@ #include #include +#include "crypto/bnerr.h" #ifndef OPENSSL_NO_ERR -static const ERR_STRING_DATA BN_str_functs[] = { - {ERR_PACK(ERR_LIB_BN, BN_F_BNRAND, 0), "bnrand"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BNRAND_RANGE, 0), "bnrand_range"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_CONVERT_EX, 0), - "BN_BLINDING_convert_ex"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_CREATE_PARAM, 0), - "BN_BLINDING_create_param"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_INVERT_EX, 0), - "BN_BLINDING_invert_ex"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_NEW, 0), "BN_BLINDING_new"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BLINDING_UPDATE, 0), "BN_BLINDING_update"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BN2DEC, 0), "BN_bn2dec"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_BN2HEX, 0), "BN_bn2hex"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_COMPUTE_WNAF, 0), "bn_compute_wNAF"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_GET, 0), "BN_CTX_get"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_NEW, 0), "BN_CTX_new"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_START, 0), "BN_CTX_start"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_DIV, 0), "BN_div"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_DIV_RECP, 0), "BN_div_recp"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_EXP, 0), "BN_exp"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_EXPAND_INTERNAL, 0), "bn_expand_internal"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENCB_NEW, 0), "BN_GENCB_new"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENERATE_DSA_NONCE, 0), - "BN_generate_dsa_nonce"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GENERATE_PRIME_EX, 0), - "BN_generate_prime_ex"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD, 0), "BN_GF2m_mod"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_EXP, 0), "BN_GF2m_mod_exp"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_MUL, 0), "BN_GF2m_mod_mul"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SOLVE_QUAD, 0), - "BN_GF2m_mod_solve_quad"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, 0), - "BN_GF2m_mod_solve_quad_arr"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SQR, 0), "BN_GF2m_mod_sqr"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_GF2M_MOD_SQRT, 0), "BN_GF2m_mod_sqrt"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_LSHIFT, 0), "BN_lshift"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP2_MONT, 0), "BN_mod_exp2_mont"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT, 0), "BN_mod_exp_mont"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT_CONSTTIME, 0), - "BN_mod_exp_mont_consttime"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_MONT_WORD, 0), - "BN_mod_exp_mont_word"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_RECP, 0), "BN_mod_exp_recp"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_EXP_SIMPLE, 0), "BN_mod_exp_simple"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_INVERSE, 0), "BN_mod_inverse"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_INVERSE_NO_BRANCH, 0), - "BN_mod_inverse_no_branch"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_LSHIFT_QUICK, 0), "BN_mod_lshift_quick"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MOD_SQRT, 0), "BN_mod_sqrt"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MONT_CTX_NEW, 0), "BN_MONT_CTX_new"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_MPI2BN, 0), "BN_mpi2bn"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_NEW, 0), "BN_new"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_POOL_GET, 0), "BN_POOL_get"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_RAND, 0), "BN_rand"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_RAND_RANGE, 0), "BN_rand_range"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_RECP_CTX_NEW, 0), "BN_RECP_CTX_new"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_RSHIFT, 0), "BN_rshift"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_SET_WORDS, 0), "bn_set_words"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_STACK_PUSH, 0), "BN_STACK_push"}, - {ERR_PACK(ERR_LIB_BN, BN_F_BN_USUB, 0), "BN_usub"}, - {ERR_PACK(ERR_LIB_BN, BN_F_OSSL_BN_RSA_DO_UNBLIND, 0), - "ossl_bn_rsa_do_unblind"}, - {0, NULL} -}; - static const ERR_STRING_DATA BN_str_reasons[] = { {ERR_PACK(ERR_LIB_BN, 0, BN_R_ARG2_LT_ARG3), "arg2 lt arg3"}, {ERR_PACK(ERR_LIB_BN, 0, BN_R_BAD_RECIPROCAL), "bad reciprocal"}, @@ -96,7 +32,9 @@ {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "not a square"}, {ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "not initialized"}, {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "no inverse"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_PRIME_CANDIDATE), "no prime candidate"}, {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_SOLUTION), "no solution"}, + {ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_SUITABLE_DIGEST), "no suitable digest"}, {ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE), "private key too large"}, {ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "p is not prime"}, @@ -108,13 +46,11 @@ #endif -int ERR_load_BN_strings(void) +int ossl_err_load_BN_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(BN_str_functs[0].error) == NULL) { - ERR_load_strings_const(BN_str_functs); + if (ERR_reason_error_string(BN_str_reasons[0].error) == NULL) ERR_load_strings_const(BN_str_reasons); - } #endif return 1; } diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -29,8 +29,7 @@ #undef SPARC_T4_MONT #if defined(OPENSSL_BN_ASM_MONT) && (defined(__sparc__) || defined(__sparc)) -# include "sparc_arch.h" -extern unsigned int OPENSSL_sparcv9cap_P[]; +# include "crypto/sparc_arch.h" # define SPARC_T4_MONT #endif @@ -55,7 +54,7 @@ if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 || BN_get_flags(a, BN_FLG_CONSTTIME) != 0) { /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ - BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -181,7 +180,7 @@ || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ - BNerr(BN_F_BN_MOD_EXP_RECP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -262,7 +261,6 @@ * a window to do. To do this we need to scan forward until the last * set bit before the end of the window */ - j = wstart; wvalue = 1; wend = 0; for (i = 1; i < window; i++) { @@ -319,7 +317,7 @@ bn_check_top(m); if (!BN_is_odd(m)) { - BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS); return 0; } @@ -421,7 +419,6 @@ * a window to do. To do this we need to scan forward until the last * set bit before the end of the window */ - j = wstart; wvalue = 1; wend = 0; for (i = 1; i < window; i++) { @@ -623,7 +620,7 @@ bn_check_top(m); if (!BN_is_odd(m)) { - BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS); + ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS); return 0; } @@ -841,7 +838,7 @@ /* * BN_to_montgomery can contaminate words above .top [in - * BN_DEBUG[_DEBUG] build]... + * BN_DEBUG build... */ for (i = am.top; i < top; i++) am.d[i] = 0; @@ -950,7 +947,7 @@ /* * BN_to_montgomery can contaminate words above .top [in - * BN_DEBUG[_DEBUG] build]... + * BN_DEBUG build... */ for (i = am.top; i < top; i++) am.d[i] = 0; @@ -1184,7 +1181,7 @@ if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ - BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -1192,7 +1189,7 @@ bn_check_top(m); if (!BN_is_odd(m)) { - BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS); + ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS); return 0; } if (m->top == 1) @@ -1316,7 +1313,7 @@ || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ - BNerr(BN_F_BN_MOD_EXP_SIMPLE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -1383,7 +1380,6 @@ * a window to do. To do this we need to scan forward until the last * set bit before the end of the window */ - j = wstart; wvalue = 1; wend = 0; for (i = 1; i < window; i++) { @@ -1422,3 +1418,85 @@ bn_check_top(r); return ret; } + +/* + * This is a variant of modular exponentiation optimization that does + * parallel 2-primes exponentiation using 256-bit (AVX512VL) AVX512_IFMA ISA + * in 52-bit binary redundant representation. + * If such instructions are not available, or input data size is not supported, + * it falls back to two BN_mod_exp_mont_consttime() calls. + */ +int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *m1, BN_MONT_CTX *in_mont1, + BIGNUM *rr2, const BIGNUM *a2, const BIGNUM *p2, + const BIGNUM *m2, BN_MONT_CTX *in_mont2, + BN_CTX *ctx) +{ + int ret = 0; + +#ifdef RSAZ_ENABLED + BN_MONT_CTX *mont1 = NULL; + BN_MONT_CTX *mont2 = NULL; + + if (ossl_rsaz_avx512ifma_eligible() && + ((a1->top == 16) && (p1->top == 16) && (BN_num_bits(m1) == 1024) && + (a2->top == 16) && (p2->top == 16) && (BN_num_bits(m2) == 1024))) { + + if (bn_wexpand(rr1, 16) == NULL) + goto err; + if (bn_wexpand(rr2, 16) == NULL) + goto err; + + /* Ensure that montgomery contexts are initialized */ + if (in_mont1 != NULL) { + mont1 = in_mont1; + } else { + if ((mont1 = BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont1, m1, ctx)) + goto err; + } + if (in_mont2 != NULL) { + mont2 = in_mont2; + } else { + if ((mont2 = BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(mont2, m2, ctx)) + goto err; + } + + ret = ossl_rsaz_mod_exp_avx512_x2(rr1->d, a1->d, p1->d, m1->d, + mont1->RR.d, mont1->n0[0], + rr2->d, a2->d, p2->d, m2->d, + mont2->RR.d, mont2->n0[0], + 1024 /* factor bit size */); + + rr1->top = 16; + rr1->neg = 0; + bn_correct_top(rr1); + bn_check_top(rr1); + + rr2->top = 16; + rr2->neg = 0; + bn_correct_top(rr2); + bn_check_top(rr2); + + goto err; + } +#endif + + /* rr1 = a1^p1 mod m1 */ + ret = BN_mod_exp_mont_consttime(rr1, a1, p1, m1, ctx, in_mont1); + /* rr2 = a2^p2 mod m2 */ + ret &= BN_mod_exp_mont_consttime(rr2, a2, p2, m2, ctx, in_mont2); + +#ifdef RSAZ_ENABLED +err: + if (in_mont2 == NULL) + BN_MONT_CTX_free(mont2); + if (in_mont1 == NULL) + BN_MONT_CTX_free(mont1); +#endif + + return ret; +} diff --git a/crypto/bn/bn_exp2.c b/crypto/bn/bn_exp2.c --- a/crypto/bn/bn_exp2.c +++ b/crypto/bn/bn_exp2.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -33,7 +33,7 @@ bn_check_top(m); if (!BN_is_odd(m)) { - BNerr(BN_F_BN_MOD_EXP2_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS); return 0; } bits1 = BN_num_bits(p1); diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c --- a/crypto/bn/bn_gcd.c +++ b/crypto/bn/bn_gcd.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -520,16 +520,16 @@ int noinv = 0; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(NULL); if (ctx == NULL) { - BNerr(BN_F_BN_MOD_INVERSE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } } rv = int_bn_mod_inverse(in, a, n, ctx, &noinv); if (noinv) - BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE); + ERR_raise(ERR_LIB_BN, BN_R_NO_INVERSE); BN_CTX_free(new_ctx); return rv; } diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -1,8 +1,8 @@ /* - * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -297,7 +297,7 @@ bn_check_top(a); - if (!p[0]) { + if (p[0] == 0) { /* reduction mod 1 => return 0 */ BN_zero(r); return 1; @@ -395,7 +395,7 @@ bn_check_top(p); ret = BN_GF2m_poly2arr(p, arr, OSSL_NELEM(arr)); if (!ret || ret > (int)OSSL_NELEM(arr)) { - BNerr(BN_F_BN_GF2M_MOD, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); return 0; } ret = BN_GF2m_mod_arr(r, a, arr); @@ -467,15 +467,20 @@ { int ret = 0; const int max = BN_num_bits(p) + 1; - int *arr = NULL; + int *arr; + bn_check_top(a); bn_check_top(b); bn_check_top(p); - if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) - goto err; + + arr = OPENSSL_malloc(sizeof(*arr) * max); + if (arr == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + return 0; + } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { - BNerr(BN_F_BN_GF2M_MOD_MUL, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); goto err; } ret = BN_GF2m_mod_mul_arr(r, a, b, arr, ctx); @@ -525,15 +530,19 @@ { int ret = 0; const int max = BN_num_bits(p) + 1; - int *arr = NULL; + int *arr; bn_check_top(a); bn_check_top(p); - if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) - goto err; + + arr = OPENSSL_malloc(sizeof(*arr) * max); + if (arr == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + return 0; + } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { - BNerr(BN_F_BN_GF2M_MOD_SQR, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); goto err; } ret = BN_GF2m_mod_sqr_arr(r, a, arr, ctx); @@ -706,8 +715,8 @@ ret = 1; err: -# ifdef BN_DEBUG /* BN_CTX_end would complain about the - * expanded form */ +# ifdef BN_DEBUG + /* BN_CTX_end would complain about the expanded form */ bn_correct_top(c); bn_correct_top(u); bn_correct_top(v); @@ -732,8 +741,8 @@ /* generate blinding value */ do { - if (!BN_priv_rand(b, BN_num_bits(p) - 1, - BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + if (!BN_priv_rand_ex(b, BN_num_bits(p) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) goto err; } while (BN_is_zero(b)); @@ -899,15 +908,20 @@ { int ret = 0; const int max = BN_num_bits(p) + 1; - int *arr = NULL; + int *arr; + bn_check_top(a); bn_check_top(b); bn_check_top(p); - if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) - goto err; + + arr = OPENSSL_malloc(sizeof(*arr) * max); + if (arr == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + return 0; + } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { - BNerr(BN_F_BN_GF2M_MOD_EXP, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); goto err; } ret = BN_GF2m_mod_exp_arr(r, a, b, arr, ctx); @@ -929,7 +943,7 @@ bn_check_top(a); - if (!p[0]) { + if (p[0] == 0) { /* reduction mod 1 => return 0 */ BN_zero(r); return 1; @@ -959,14 +973,19 @@ { int ret = 0; const int max = BN_num_bits(p) + 1; - int *arr = NULL; + int *arr; + bn_check_top(a); bn_check_top(p); - if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) - goto err; + + arr = OPENSSL_malloc(sizeof(*arr) * max); + if (arr == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + return 0; + } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { - BNerr(BN_F_BN_GF2M_MOD_SQRT, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); goto err; } ret = BN_GF2m_mod_sqrt_arr(r, a, arr, ctx); @@ -988,7 +1007,7 @@ bn_check_top(a_); - if (!p[0]) { + if (p[0] == 0) { /* reduction mod 1 => return 0 */ BN_zero(r); return 1; @@ -1031,7 +1050,8 @@ if (tmp == NULL) goto err; do { - if (!BN_priv_rand(rho, p[0], BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + if (!BN_priv_rand_ex(rho, p[0], BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY, + 0, ctx)) goto err; if (!BN_GF2m_mod_arr(rho, rho, p)) goto err; @@ -1053,7 +1073,7 @@ count++; } while (BN_is_zero(w) && (count < MAX_ITERATIONS)); if (BN_is_zero(w)) { - BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_TOO_MANY_ITERATIONS); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS); goto err; } } @@ -1063,7 +1083,7 @@ if (!BN_GF2m_add(w, z, w)) goto err; if (BN_GF2m_cmp(w, a)) { - BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR, BN_R_NO_SOLUTION); + ERR_raise(ERR_LIB_BN, BN_R_NO_SOLUTION); goto err; } @@ -1089,14 +1109,19 @@ { int ret = 0; const int max = BN_num_bits(p) + 1; - int *arr = NULL; + int *arr; + bn_check_top(a); bn_check_top(p); - if ((arr = OPENSSL_malloc(sizeof(*arr) * max)) == NULL) + + arr = OPENSSL_malloc(sizeof(*arr) * max); + if (arr == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); goto err; + } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { - BNerr(BN_F_BN_GF2M_MOD_SOLVE_QUAD, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); goto err; } ret = BN_GF2m_mod_solve_quad_arr(r, a, arr, ctx); diff --git a/crypto/bn/bn_intern.c b/crypto/bn/bn_intern.c --- a/crypto/bn/bn_intern.c +++ b/crypto/bn/bn_intern.c @@ -1,7 +1,7 @@ /* - * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -30,7 +30,7 @@ if (BN_is_zero(scalar)) { r = OPENSSL_malloc(1); if (r == NULL) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); goto err; } r[0] = 0; @@ -40,7 +40,7 @@ if (w <= 0 || w > 7) { /* 'signed char' can represent integers with * absolute values less than 2^7 */ - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR); goto err; } bit = 1 << w; /* at most 128 */ @@ -52,7 +52,7 @@ } if (scalar->d == NULL || scalar->top == 0) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR); goto err; } @@ -63,7 +63,7 @@ * BN_num_bits(scalar) + 1) */ if (r == NULL) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); goto err; } window_val = scalar->d[0] & mask; @@ -98,7 +98,7 @@ } if (digit <= -bit || digit >= bit || !(digit & 1)) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR); goto err; } @@ -110,7 +110,7 @@ */ if (window_val != 0 && window_val != next_bit && window_val != bit) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR); goto err; } } @@ -121,13 +121,13 @@ window_val += bit * BN_is_bit_set(scalar, j + w); if (window_val > next_bit) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR); goto err; } } if (j > len + 1) { - BNerr(BN_F_BN_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR); goto err; } *ret_len = j; @@ -188,7 +188,7 @@ int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words) { if (bn_wexpand(a, num_words) == NULL) { - BNerr(BN_F_BN_SET_WORDS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return 0; } diff --git a/crypto/bn/bn_kron.c b/crypto/bn/bn_kron.c --- a/crypto/bn/bn_kron.c +++ b/crypto/bn/bn_kron.c @@ -1,7 +1,7 @@ /* * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,12 +10,13 @@ #include #include #include "internal/cryptlib.h" +#include "internal/endian.h" #include "bn_local.h" #include #include "internal/constant_time.h" /* This stuff appears to be completely unused, so is deprecated */ -#if OPENSSL_API_COMPAT < 0x00908000L +#ifndef OPENSSL_NO_DEPRECATED_0_9_8 /*- * For a 32 bit machine * 2 - 4 == 128 @@ -244,7 +245,7 @@ BIGNUM *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } ret->flags = BN_FLG_MALLOCED; @@ -267,11 +268,11 @@ BN_ULONG *a = NULL; if (words > (INT_MAX / (4 * BN_BITS2))) { - BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG); + ERR_raise(ERR_LIB_BN, BN_R_BIGNUM_TOO_LONG); return NULL; } if (BN_get_flags(b, BN_FLG_STATIC_DATA)) { - BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + ERR_raise(ERR_LIB_BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); return NULL; } if (BN_get_flags(b, BN_FLG_SECURE)) @@ -279,7 +280,7 @@ else a = OPENSSL_zalloc(words * sizeof(*a)); if (a == NULL) { - BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } @@ -504,7 +505,8 @@ /* Swipe through whole available data and don't give away padded zero. */ atop = a->dmax * BN_BYTES; if (atop == 0) { - OPENSSL_cleanse(to, tolen); + if (tolen != 0) + memset(to, '\0', tolen); return tolen; } @@ -593,6 +595,24 @@ return bn2binpad(a, to, tolen, little); } +BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + DECLARE_IS_ENDIAN; + + if (IS_LITTLE_ENDIAN) + return BN_lebin2bn(s, len, ret); + return BN_bin2bn(s, len, ret); +} + +int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen) +{ + DECLARE_IS_ENDIAN; + + if (IS_LITTLE_ENDIAN) + return BN_bn2lebinpad(a, to, tolen); + return BN_bn2binpad(a, to, tolen); +} + int BN_ucmp(const BIGNUM *a, const BIGNUM *b) { int i; @@ -947,7 +967,7 @@ BN_GENCB *ret; if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { - BNerr(BN_F_BN_GENCB_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h --- a/crypto/bn/bn_local.h +++ b/crypto/bn/bn_local.h @@ -1,7 +1,7 @@ /* * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -22,18 +22,25 @@ # endif # include "crypto/bn.h" +# include "internal/cryptlib.h" +# include "internal/numbers.h" /* * These preprocessor symbols control various aspects of the bignum headers * and library code. They're not defined by any "normal" configuration, as - * they are intended for development and testing purposes. NB: defining all - * three can be useful for debugging application code as well as openssl + * they are intended for development and testing purposes. NB: defining + * them can be useful for debugging application code as well as openssl * itself. BN_DEBUG - turn on various debugging alterations to the bignum - * code BN_DEBUG_RAND - uses random poisoning of unused words to trip up - * mismanagement of bignum internals. You must also define BN_DEBUG. + * code BN_RAND_DEBUG - uses random poisoning of unused words to trip up + * mismanagement of bignum internals. Enable BN_RAND_DEBUG is known to + * break some of the OpenSSL tests. */ -/* #define BN_DEBUG */ -/* #define BN_DEBUG_RAND */ +# if defined(BN_RAND_DEBUG) && !defined(BN_DEBUG) +# define BN_DEBUG +# endif +# if defined(BN_RAND_DEBUG) +# include +# endif /* * This should limit the stack usage due to alloca to about 4K. @@ -145,7 +152,7 @@ * bn_check_top() is as before. * - if BN_DEBUG *is* defined; * - bn_check_top() tries to pollute unused words even if the bignum 'top' is - * consistent. (ed: only if BN_DEBUG_RAND is defined) + * consistent. (ed: only if BN_RAND_DEBUG is defined) * - bn_fix_top() maps to bn_check_top() rather than "fixing" anything. * The idea is to have debug builds flag up inconsistent bignums when they * occur. If that occurs in a bn_fix_top(), we examine the code in question; if @@ -171,7 +178,7 @@ * all operations manipulating the bit in question in non-BN_DEBUG build. */ # define BN_FLG_FIXED_TOP 0x10000 -# ifdef BN_DEBUG_RAND +# ifdef BN_RAND_DEBUG # define bn_pollute(a) \ do { \ const BIGNUM *_bnum1 = (a); \ @@ -182,7 +189,7 @@ * wouldn't be constructed with top!=dmax. */ \ BN_ULONG *_not_const; \ memcpy(&_not_const, &_bnum1->d, sizeof(_not_const)); \ - RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */\ + (void)RAND_bytes(&_tmp_char, 1); /* Debug only - safe to ignore error return */\ memset(_not_const + _bnum1->top, _tmp_char, \ sizeof(*_not_const) * (_bnum1->dmax - _bnum1->top)); \ } \ @@ -408,9 +415,9 @@ */ # if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 && \ (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)) -# define BN_UMULT_HIGH(a,b) (((__uint128_t)(a)*(b))>>64) +# define BN_UMULT_HIGH(a,b) (((uint128_t)(a)*(b))>>64) # define BN_UMULT_LOHI(low,high,a,b) ({ \ - __uint128_t ret=(__uint128_t)(a)*(b); \ + uint128_t ret=(uint128_t)(a)*(b); \ (high)=ret>>64; (low)=ret; }) # elif defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT)) # if defined(__DECC) @@ -483,7 +490,7 @@ # endif /* cpu */ # endif /* OPENSSL_NO_ASM */ -# ifdef BN_DEBUG_RAND +# ifdef BN_RAND_DEBUG # define bn_clear_top2max(a) \ { \ int ind = (a)->dmax - (a)->top; \ @@ -699,4 +706,7 @@ return bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2); } +int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb); + #endif diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c --- a/crypto/bn/bn_mod.c +++ b/crypto/bn/bn_mod.c @@ -1,7 +1,7 @@ /* - * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -56,9 +56,13 @@ if (bn_wexpand(r, mtop) == NULL) return 0; - if (mtop > sizeof(storage) / sizeof(storage[0]) - && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL) - return 0; + if (mtop > sizeof(storage) / sizeof(storage[0])) { + tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG)); + if (tp == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + return 0; + } + } ap = a->d != NULL ? a->d : tp; bp = b->d != NULL ? b->d : tp; @@ -291,7 +295,7 @@ /* max_shift >= 0 */ if (max_shift < 0) { - BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED); + ERR_raise(ERR_LIB_BN, BN_R_INPUT_NOT_REDUCED); return 0; } diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -230,7 +230,7 @@ BN_MONT_CTX *ret; if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { - BNerr(BN_F_BN_MONT_CTX_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } @@ -430,14 +430,15 @@ { BN_MONT_CTX *ret; - CRYPTO_THREAD_read_lock(lock); + if (!CRYPTO_THREAD_read_lock(lock)) + return NULL; ret = *pmont; CRYPTO_THREAD_unlock(lock); if (ret) return ret; /* - * We don't want to serialise globally while doing our lazy-init math in + * We don't want to serialize globally while doing our lazy-init math in * BN_MONT_CTX_set. That punishes threads that are doing independent * things. Instead, punish the case where more than one thread tries to * lazy-init the same 'pmont', by having each do the lazy-init math work @@ -453,7 +454,11 @@ } /* The locked compare-and-set, after the local work is done. */ - CRYPTO_THREAD_write_lock(lock); + if (!CRYPTO_THREAD_write_lock(lock)) { + BN_MONT_CTX_free(ret); + return NULL; + } + if (*pmont) { BN_MONT_CTX_free(ret); ret = *pmont; diff --git a/crypto/bn/bn_mpi.c b/crypto/bn/bn_mpi.c --- a/crypto/bn/bn_mpi.c +++ b/crypto/bn/bn_mpi.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -46,13 +46,13 @@ BIGNUM *a = NULL; if (n < 4 || (d[0] & 0x80) != 0) { - BNerr(BN_F_BN_MPI2BN, BN_R_INVALID_LENGTH); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); return NULL; } len = ((long)d[0] << 24) | ((long)d[1] << 16) | ((int)d[2] << 8) | (int) d[3]; if ((len + 4) != n) { - BNerr(BN_F_BN_MPI2BN, BN_R_ENCODING_ERROR); + ERR_raise(ERR_LIB_BN, BN_R_ENCODING_ERROR); return NULL; } diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c --- a/crypto/bn/bn_mul.c +++ b/crypto/bn/bn_mul.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -1,7 +1,7 @@ /* * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -184,7 +184,7 @@ # error "unsupported BN_BITS2" #endif -static const BIGNUM _bignum_nist_p_192 = { +static const BIGNUM ossl_bignum_nist_p_192 = { (BN_ULONG *)_nist_p_192[0], BN_NIST_192_TOP, BN_NIST_192_TOP, @@ -192,7 +192,7 @@ BN_FLG_STATIC_DATA }; -static const BIGNUM _bignum_nist_p_224 = { +static const BIGNUM ossl_bignum_nist_p_224 = { (BN_ULONG *)_nist_p_224[0], BN_NIST_224_TOP, BN_NIST_224_TOP, @@ -200,7 +200,7 @@ BN_FLG_STATIC_DATA }; -static const BIGNUM _bignum_nist_p_256 = { +static const BIGNUM ossl_bignum_nist_p_256 = { (BN_ULONG *)_nist_p_256[0], BN_NIST_256_TOP, BN_NIST_256_TOP, @@ -208,7 +208,7 @@ BN_FLG_STATIC_DATA }; -static const BIGNUM _bignum_nist_p_384 = { +static const BIGNUM ossl_bignum_nist_p_384 = { (BN_ULONG *)_nist_p_384[0], BN_NIST_384_TOP, BN_NIST_384_TOP, @@ -216,7 +216,7 @@ BN_FLG_STATIC_DATA }; -static const BIGNUM _bignum_nist_p_521 = { +static const BIGNUM ossl_bignum_nist_p_521 = { (BN_ULONG *)_nist_p_521, BN_NIST_521_TOP, BN_NIST_521_TOP, @@ -226,27 +226,27 @@ const BIGNUM *BN_get0_nist_prime_192(void) { - return &_bignum_nist_p_192; + return &ossl_bignum_nist_p_192; } const BIGNUM *BN_get0_nist_prime_224(void) { - return &_bignum_nist_p_224; + return &ossl_bignum_nist_p_224; } const BIGNUM *BN_get0_nist_prime_256(void) { - return &_bignum_nist_p_256; + return &ossl_bignum_nist_p_256; } const BIGNUM *BN_get0_nist_prime_384(void) { - return &_bignum_nist_p_384; + return &ossl_bignum_nist_p_384; } const BIGNUM *BN_get0_nist_prime_521(void) { - return &_bignum_nist_p_521; + return &ossl_bignum_nist_p_521; } /* @@ -339,16 +339,16 @@ } buf; BN_ULONG c_d[BN_NIST_192_TOP], *res; PTR_SIZE_INT mask; - static const BIGNUM _bignum_nist_p_192_sqr = { + static const BIGNUM ossl_bignum_nist_p_192_sqr = { (BN_ULONG *)_nist_p_192_sqr, OSSL_NELEM(_nist_p_192_sqr), OSSL_NELEM(_nist_p_192_sqr), 0, BN_FLG_STATIC_DATA }; - field = &_bignum_nist_p_192; /* just to make sure */ + field = &ossl_bignum_nist_p_192; /* just to make sure */ - if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_192_sqr) >= 0) + if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_192_sqr) >= 0) return BN_nnmod(r, a, field, ctx); i = BN_ucmp(field, a); @@ -484,16 +484,16 @@ bn_addsub_f f; PTR_SIZE_INT p; } u; - static const BIGNUM _bignum_nist_p_224_sqr = { + static const BIGNUM ossl_bignum_nist_p_224_sqr = { (BN_ULONG *)_nist_p_224_sqr, OSSL_NELEM(_nist_p_224_sqr), OSSL_NELEM(_nist_p_224_sqr), 0, BN_FLG_STATIC_DATA }; - field = &_bignum_nist_p_224; /* just to make sure */ + field = &ossl_bignum_nist_p_224; /* just to make sure */ - if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_224_sqr) >= 0) + if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_224_sqr) >= 0) return BN_nnmod(r, a, field, ctx); i = BN_ucmp(field, a); @@ -665,16 +665,16 @@ bn_addsub_f f; PTR_SIZE_INT p; } u; - static const BIGNUM _bignum_nist_p_256_sqr = { + static const BIGNUM ossl_bignum_nist_p_256_sqr = { (BN_ULONG *)_nist_p_256_sqr, OSSL_NELEM(_nist_p_256_sqr), OSSL_NELEM(_nist_p_256_sqr), 0, BN_FLG_STATIC_DATA }; - field = &_bignum_nist_p_256; /* just to make sure */ + field = &ossl_bignum_nist_p_256; /* just to make sure */ - if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_256_sqr) >= 0) + if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_256_sqr) >= 0) return BN_nnmod(r, a, field, ctx); i = BN_ucmp(field, a); @@ -911,16 +911,16 @@ bn_addsub_f f; PTR_SIZE_INT p; } u; - static const BIGNUM _bignum_nist_p_384_sqr = { + static const BIGNUM ossl_bignum_nist_p_384_sqr = { (BN_ULONG *)_nist_p_384_sqr, OSSL_NELEM(_nist_p_384_sqr), OSSL_NELEM(_nist_p_384_sqr), 0, BN_FLG_STATIC_DATA }; - field = &_bignum_nist_p_384; /* just to make sure */ + field = &ossl_bignum_nist_p_384; /* just to make sure */ - if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_384_sqr) >= 0) + if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_384_sqr) >= 0) return BN_nnmod(r, a, field, ctx); i = BN_ucmp(field, a); @@ -1169,16 +1169,16 @@ int top = a->top, i; BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res; PTR_SIZE_INT mask; - static const BIGNUM _bignum_nist_p_521_sqr = { + static const BIGNUM ossl_bignum_nist_p_521_sqr = { (BN_ULONG *)_nist_p_521_sqr, OSSL_NELEM(_nist_p_521_sqr), OSSL_NELEM(_nist_p_521_sqr), 0, BN_FLG_STATIC_DATA }; - field = &_bignum_nist_p_521; /* just to make sure */ + field = &ossl_bignum_nist_p_521; /* just to make sure */ - if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_521_sqr) >= 0) + if (BN_is_negative(a) || BN_ucmp(a, &ossl_bignum_nist_p_521_sqr) >= 0) return BN_nnmod(r, a, field, ctx); i = BN_ucmp(field, a); @@ -1236,15 +1236,15 @@ int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_CTX *ctx) { - if (BN_ucmp(&_bignum_nist_p_192, p) == 0) + if (BN_ucmp(&ossl_bignum_nist_p_192, p) == 0) return BN_nist_mod_192; - if (BN_ucmp(&_bignum_nist_p_224, p) == 0) + if (BN_ucmp(&ossl_bignum_nist_p_224, p) == 0) return BN_nist_mod_224; - if (BN_ucmp(&_bignum_nist_p_256, p) == 0) + if (BN_ucmp(&ossl_bignum_nist_p_256, p) == 0) return BN_nist_mod_256; - if (BN_ucmp(&_bignum_nist_p_384, p) == 0) + if (BN_ucmp(&ossl_bignum_nist_p_384, p) == 0) return BN_nist_mod_384; - if (BN_ucmp(&_bignum_nist_p_521, p) == 0) + if (BN_ucmp(&ossl_bignum_nist_p_521, p) == 0) return BN_nist_mod_521; return 0; } diff --git a/crypto/bn/bn_ppc.c b/crypto/bn/bn_ppc.c new file mode 100644 --- /dev/null +++ b/crypto/bn/bn_ppc.c @@ -0,0 +1,38 @@ +/* + * Copyright 2009-2022 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "crypto/ppc_arch.h" +#include "bn_local.h" + +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num) +{ + int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul4x_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + + if (num < 4) + return 0; + + if ((num & 3) == 0) + return bn_mul4x_mont_int(rp, ap, bp, np, n0, num); + + /* + * There used to be [optional] call to bn_mul_mont_fpu64 here, + * but above subroutine is faster on contemporary processors. + * Formulation means that there might be old processors where + * FPU code path would be faster, POWER6 perhaps, but there was + * no opportunity to figure it out... + */ + + return bn_mul_mont_int(rp, ap, bp, np, n0, num); +} diff --git a/crypto/bn/bn_prime.h b/crypto/bn/bn_prime.h --- a/crypto/bn/bn_prime.h +++ b/crypto/bn/bn_prime.h @@ -2,9 +2,9 @@ * WARNING: do not edit! * Generated by crypto/bn/bn_prime.pl * - * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c --- a/crypto/bn/bn_prime.c +++ b/crypto/bn/bn_prime.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -19,16 +19,85 @@ */ #include "bn_prime.h" -static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, - const BIGNUM *a1_odd, int k, BN_CTX *ctx, - BN_MONT_CTX *mont); -static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods); +static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods, + BN_CTX *ctx); static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods, const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); +static int bn_is_prime_int(const BIGNUM *w, int checks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb); #define square(x) ((BN_ULONG)(x) * (BN_ULONG)(x)) +#if BN_BITS2 == 64 +# define BN_DEF(lo, hi) (BN_ULONG)hi<<32|lo +#else +# define BN_DEF(lo, hi) lo, hi +#endif + +/* + * See SP800 89 5.3.3 (Step f) + * The product of the set of primes ranging from 3 to 751 + * Generated using process in test/bn_internal_test.c test_bn_small_factors(). + * This includes 751 (which is not currently included in SP 800-89). + */ +static const BN_ULONG small_prime_factors[] = { + BN_DEF(0x3ef4e3e1, 0xc4309333), BN_DEF(0xcd2d655f, 0x71161eb6), + BN_DEF(0x0bf94862, 0x95e2238c), BN_DEF(0x24f7912b, 0x3eb233d3), + BN_DEF(0xbf26c483, 0x6b55514b), BN_DEF(0x5a144871, 0x0a84d817), + BN_DEF(0x9b82210a, 0x77d12fee), BN_DEF(0x97f050b3, 0xdb5b93c2), + BN_DEF(0x4d6c026b, 0x4acad6b9), BN_DEF(0x54aec893, 0xeb7751f3), + BN_DEF(0x36bc85c4, 0xdba53368), BN_DEF(0x7f5ec78e, 0xd85a1b28), + BN_DEF(0x6b322244, 0x2eb072d8), BN_DEF(0x5e2b3aea, 0xbba51112), + BN_DEF(0x0e2486bf, 0x36ed1a6c), BN_DEF(0xec0c5727, 0x5f270460), + (BN_ULONG)0x000017b1 +}; + +#define BN_SMALL_PRIME_FACTORS_TOP OSSL_NELEM(small_prime_factors) +static const BIGNUM _bignum_small_prime_factors = { + (BN_ULONG *)small_prime_factors, + BN_SMALL_PRIME_FACTORS_TOP, + BN_SMALL_PRIME_FACTORS_TOP, + 0, + BN_FLG_STATIC_DATA +}; + +const BIGNUM *ossl_bn_get0_small_factors(void) +{ + return &_bignum_small_prime_factors; +} + +/* + * Calculate the number of trial divisions that gives the best speed in + * combination with Miller-Rabin prime test, based on the sized of the prime. + */ +static int calc_trial_divisions(int bits) +{ + if (bits <= 512) + return 64; + else if (bits <= 1024) + return 128; + else if (bits <= 2048) + return 384; + else if (bits <= 4096) + return 1024; + return NUMPRIMES; +} + +/* + * Use a minimum of 64 rounds of Miller-Rabin, which should give a false + * positive rate of 2^-128. If the size of the prime is larger than 2048 + * the user probably wants a higher security level than 128, so switch + * to 128 rounds giving a false positive rate of 2^-256. + * Returns the number of rounds. + */ +static int bn_mr_min_checks(int bits) +{ + if (bits > 2048) + return 128; + return 64; +} + int BN_GENCB_call(BN_GENCB *cb, int a, int b) { /* No callback means continue */ @@ -51,19 +120,19 @@ return 0; } -int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, - const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb) +int BN_generate_prime_ex2(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb, + BN_CTX *ctx) { BIGNUM *t; int found = 0; int i, j, c1 = 0; - BN_CTX *ctx = NULL; prime_t *mods = NULL; - int checks = BN_prime_checks_for_size(bits); + int checks = bn_mr_min_checks(bits); if (bits < 2) { /* There are no prime numbers this small. */ - BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL); + ERR_raise(ERR_LIB_BN, BN_R_BITS_TOO_SMALL); return 0; } else if (add == NULL && safe && bits < 6 && bits != 3) { /* @@ -71,17 +140,16 @@ * But the following two safe primes with less than 6 bits (11, 23) * are unreachable for BN_rand with BN_RAND_TOP_TWO. */ - BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL); + ERR_raise(ERR_LIB_BN, BN_R_BITS_TOO_SMALL); return 0; } mods = OPENSSL_zalloc(sizeof(*mods) * NUMPRIMES); - if (mods == NULL) - goto err; + if (mods == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + return 0; + } - ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; BN_CTX_start(ctx); t = BN_CTX_get(ctx); if (t == NULL) @@ -89,7 +157,7 @@ loop: /* make a random number and set the top and bottom bits */ if (add == NULL) { - if (!probable_prime(ret, bits, safe, mods)) + if (!probable_prime(ret, bits, safe, mods, ctx)) goto err; } else { if (!probable_prime_dh(ret, bits, safe, mods, add, rem, ctx)) @@ -101,7 +169,7 @@ goto err; if (!safe) { - i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb); + i = bn_is_prime_int(ret, checks, ctx, 0, cb); if (i == -1) goto err; if (i == 0) @@ -115,13 +183,13 @@ goto err; for (i = 0; i < checks; i++) { - j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, cb); + j = bn_is_prime_int(ret, 1, ctx, 0, cb); if (j == -1) goto err; if (j == 0) goto loop; - j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, cb); + j = bn_is_prime_int(t, 1, ctx, 0, cb); if (j == -1) goto err; if (j == 0) @@ -137,152 +205,292 @@ err: OPENSSL_free(mods); BN_CTX_end(ctx); - BN_CTX_free(ctx); bn_check_top(ret); return found; } +#ifndef FIPS_MODULE +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb) +{ + BN_CTX *ctx = BN_CTX_new(); + int retval; + + if (ctx == NULL) + return 0; + + retval = BN_generate_prime_ex2(ret, bits, safe, add, rem, cb, ctx); + + BN_CTX_free(ctx); + return retval; +} +#endif + +#ifndef OPENSSL_NO_DEPRECATED_3_0 int BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, BN_GENCB *cb) { - return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb); + return ossl_bn_check_prime(a, checks, ctx_passed, 0, cb); } -int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, +int BN_is_prime_fasttest_ex(const BIGNUM *w, int checks, BN_CTX *ctx, int do_trial_division, BN_GENCB *cb) { - int i, j, ret = -1; - int k; - BN_CTX *ctx = NULL; - BIGNUM *A1, *A1_odd, *A3, *check; /* taken from ctx */ - BN_MONT_CTX *mont = NULL; + return ossl_bn_check_prime(w, checks, ctx, do_trial_division, cb); +} +#endif - /* Take care of the really small primes 2 & 3 */ - if (BN_is_word(a, 2) || BN_is_word(a, 3)) - return 1; +/* Wrapper around bn_is_prime_int that sets the minimum number of checks */ +int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb) +{ + int min_checks = bn_mr_min_checks(BN_num_bits(w)); + + if (checks < min_checks) + checks = min_checks; + + return bn_is_prime_int(w, checks, ctx, do_trial_division, cb); +} + +int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb) +{ + return ossl_bn_check_prime(p, 0, ctx, 1, cb); +} + +/* + * Tests that |w| is probably prime + * See FIPS 186-4 C.3.1 Miller Rabin Probabilistic Primality Test. + * + * Returns 0 when composite, 1 when probable prime, -1 on error. + */ +static int bn_is_prime_int(const BIGNUM *w, int checks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb) +{ + int i, status, ret = -1; +#ifndef FIPS_MODULE + BN_CTX *ctxlocal = NULL; +#else + + if (ctx == NULL) + return -1; +#endif - /* Check odd and bigger than 1 */ - if (!BN_is_odd(a) || BN_cmp(a, BN_value_one()) <= 0) + /* w must be bigger than 1 */ + if (BN_cmp(w, BN_value_one()) <= 0) return 0; - if (checks == BN_prime_checks) - checks = BN_prime_checks_for_size(BN_num_bits(a)); + /* w must be odd */ + if (BN_is_odd(w)) { + /* Take care of the really small prime 3 */ + if (BN_is_word(w, 3)) + return 1; + } else { + /* 2 is the only even prime */ + return BN_is_word(w, 2); + } /* first look for small factors */ if (do_trial_division) { - for (i = 1; i < NUMPRIMES; i++) { - BN_ULONG mod = BN_mod_word(a, primes[i]); + int trial_divisions = calc_trial_divisions(BN_num_bits(w)); + + for (i = 1; i < trial_divisions; i++) { + BN_ULONG mod = BN_mod_word(w, primes[i]); if (mod == (BN_ULONG)-1) - goto err; + return -1; if (mod == 0) - return BN_is_word(a, primes[i]); + return BN_is_word(w, primes[i]); } if (!BN_GENCB_call(cb, 1, -1)) - goto err; + return -1; } - - if (ctx_passed != NULL) - ctx = ctx_passed; - else if ((ctx = BN_CTX_new()) == NULL) +#ifndef FIPS_MODULE + if (ctx == NULL && (ctxlocal = ctx = BN_CTX_new()) == NULL) goto err; - BN_CTX_start(ctx); +#endif - A1 = BN_CTX_get(ctx); - A3 = BN_CTX_get(ctx); - A1_odd = BN_CTX_get(ctx); - check = BN_CTX_get(ctx); - if (check == NULL) + if (!ossl_bn_miller_rabin_is_prime(w, checks, ctx, cb, 0, &status)) { + ret = -1; goto err; + } + ret = (status == BN_PRIMETEST_PROBABLY_PRIME); +err: +#ifndef FIPS_MODULE + BN_CTX_free(ctxlocal); +#endif + return ret; +} - /* compute A1 := a - 1 */ - if (!BN_copy(A1, a) || !BN_sub_word(A1, 1)) +/* + * Refer to FIPS 186-4 C.3.2 Enhanced Miller-Rabin Probabilistic Primality Test. + * OR C.3.1 Miller-Rabin Probabilistic Primality Test (if enhanced is zero). + * The Step numbers listed in the code refer to the enhanced case. + * + * if enhanced is set, then status returns one of the following: + * BN_PRIMETEST_PROBABLY_PRIME + * BN_PRIMETEST_COMPOSITE_WITH_FACTOR + * BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME + * if enhanced is zero, then status returns either + * BN_PRIMETEST_PROBABLY_PRIME or + * BN_PRIMETEST_COMPOSITE + * + * returns 0 if there was an error, otherwise it returns 1. + */ +int ossl_bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx, + BN_GENCB *cb, int enhanced, int *status) +{ + int i, j, a, ret = 0; + BIGNUM *g, *w1, *w3, *x, *m, *z, *b; + BN_MONT_CTX *mont = NULL; + + /* w must be odd */ + if (!BN_is_odd(w)) + return 0; + + BN_CTX_start(ctx); + g = BN_CTX_get(ctx); + w1 = BN_CTX_get(ctx); + w3 = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + m = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + + if (!(b != NULL + /* w1 := w - 1 */ + && BN_copy(w1, w) + && BN_sub_word(w1, 1) + /* w3 := w - 3 */ + && BN_copy(w3, w) + && BN_sub_word(w3, 3))) goto err; - /* compute A3 := a - 3 */ - if (!BN_copy(A3, a) || !BN_sub_word(A3, 3)) + + /* check w is larger than 3, otherwise the random b will be too small */ + if (BN_is_zero(w3) || BN_is_negative(w3)) goto err; - /* write A1 as A1_odd * 2^k */ - k = 1; - while (!BN_is_bit_set(A1, k)) - k++; - if (!BN_rshift(A1_odd, A1, k)) + /* (Step 1) Calculate largest integer 'a' such that 2^a divides w-1 */ + a = 1; + while (!BN_is_bit_set(w1, a)) + a++; + /* (Step 2) m = (w-1) / 2^a */ + if (!BN_rshift(m, w1, a)) goto err; /* Montgomery setup for computations mod a */ mont = BN_MONT_CTX_new(); - if (mont == NULL) - goto err; - if (!BN_MONT_CTX_set(mont, a, ctx)) + if (mont == NULL || !BN_MONT_CTX_set(mont, w, ctx)) goto err; - for (i = 0; i < checks; i++) { - /* 1 < check < a-1 */ - if (!BN_priv_rand_range(check, A3) || !BN_add_word(check, 2)) + if (iterations == 0) + iterations = bn_mr_min_checks(BN_num_bits(w)); + + /* (Step 4) */ + for (i = 0; i < iterations; ++i) { + /* (Step 4.1) obtain a Random string of bits b where 1 < b < w-1 */ + if (!BN_priv_rand_range_ex(b, w3, 0, ctx) + || !BN_add_word(b, 2)) /* 1 < b < w-1 */ goto err; - j = witness(check, a, A1, A1_odd, k, ctx, mont); - if (j == -1) + if (enhanced) { + /* (Step 4.3) */ + if (!BN_gcd(g, b, w, ctx)) + goto err; + /* (Step 4.4) */ + if (!BN_is_one(g)) { + *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR; + ret = 1; + goto err; + } + } + /* (Step 4.5) z = b^m mod w */ + if (!BN_mod_exp_mont(z, b, m, w, ctx, mont)) goto err; - if (j) { - ret = 0; + /* (Step 4.6) if (z = 1 or z = w-1) */ + if (BN_is_one(z) || BN_cmp(z, w1) == 0) + goto outer_loop; + /* (Step 4.7) for j = 1 to a-1 */ + for (j = 1; j < a ; ++j) { + /* (Step 4.7.1 - 4.7.2) x = z. z = x^2 mod w */ + if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) + goto err; + /* (Step 4.7.3) */ + if (BN_cmp(z, w1) == 0) + goto outer_loop; + /* (Step 4.7.4) */ + if (BN_is_one(z)) + goto composite; + } + /* At this point z = b^((w-1)/2) mod w */ + /* (Steps 4.8 - 4.9) x = z, z = x^2 mod w */ + if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) + goto err; + /* (Step 4.10) */ + if (BN_is_one(z)) + goto composite; + /* (Step 4.11) x = b^(w-1) mod w */ + if (!BN_copy(x, z)) goto err; +composite: + if (enhanced) { + /* (Step 4.1.2) g = GCD(x-1, w) */ + if (!BN_sub_word(x, 1) || !BN_gcd(g, x, w, ctx)) + goto err; + /* (Steps 4.1.3 - 4.1.4) */ + if (BN_is_one(g)) + *status = BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME; + else + *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR; + } else { + *status = BN_PRIMETEST_COMPOSITE; } + ret = 1; + goto err; +outer_loop: ; + /* (Step 4.1.5) */ if (!BN_GENCB_call(cb, 1, i)) goto err; } + /* (Step 5) */ + *status = BN_PRIMETEST_PROBABLY_PRIME; ret = 1; - err: - if (ctx != NULL) { - BN_CTX_end(ctx); - if (ctx_passed == NULL) - BN_CTX_free(ctx); - } +err: + BN_clear(g); + BN_clear(w1); + BN_clear(w3); + BN_clear(x); + BN_clear(m); + BN_clear(z); + BN_clear(b); + BN_CTX_end(ctx); BN_MONT_CTX_free(mont); - return ret; } -static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, - const BIGNUM *a1_odd, int k, BN_CTX *ctx, - BN_MONT_CTX *mont) -{ - if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */ - return -1; - if (BN_is_one(w)) - return 0; /* probably prime */ - if (BN_cmp(w, a1) == 0) - return 0; /* w == -1 (mod a), 'a' is probably prime */ - while (--k) { - if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */ - return -1; - if (BN_is_one(w)) - return 1; /* 'a' is composite, otherwise a previous 'w' - * would have been == -1 (mod 'a') */ - if (BN_cmp(w, a1) == 0) - return 0; /* w == -1 (mod a), 'a' is probably prime */ - } - /* - * If we get here, 'w' is the (a-1)/2-th power of the original 'w', and - * it is neither -1 nor +1 -- so 'a' cannot be prime - */ - bn_check_top(w); - return 1; -} - -static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods) +/* + * Generate a random number of |bits| bits that is probably prime by sieving. + * If |safe| != 0, it generates a safe prime. + * |mods| is a preallocated array that gets reused when called again. + * + * The probably prime is saved in |rnd|. + * + * Returns 1 on success and 0 on error. + */ +static int probable_prime(BIGNUM *rnd, int bits, int safe, prime_t *mods, + BN_CTX *ctx) { int i; BN_ULONG delta; - BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; + int trial_divisions = calc_trial_divisions(bits); + BN_ULONG maxdelta = BN_MASK2 - primes[trial_divisions - 1]; again: - /* TODO: Not all primes are private */ - if (!BN_priv_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) + if (!BN_priv_rand_ex(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD, 0, + ctx)) return 0; if (safe && !BN_set_bit(rnd, 1)) return 0; /* we now have a random number 'rnd' to test. */ - for (i = 1; i < NUMPRIMES; i++) { + for (i = 1; i < trial_divisions; i++) { BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); if (mod == (BN_ULONG)-1) return 0; @@ -290,7 +498,7 @@ } delta = 0; loop: - for (i = 1; i < NUMPRIMES; i++) { + for (i = 1; i < trial_divisions; i++) { /* * check that rnd is a prime and also that * gcd(rnd-1,primes) == 1 (except for 2) @@ -317,6 +525,14 @@ return 1; } +/* + * Generate a random number |rnd| of |bits| bits that is probably prime + * and satisfies |rnd| % |add| == |rem| by sieving. + * If |safe| != 0, it generates a safe prime. + * |mods| is a preallocated array that gets reused when called again. + * + * Returns 1 on success and 0 on error. + */ static int probable_prime_dh(BIGNUM *rnd, int bits, int safe, prime_t *mods, const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx) @@ -324,7 +540,8 @@ int i, ret = 0; BIGNUM *t1; BN_ULONG delta; - BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; + int trial_divisions = calc_trial_divisions(bits); + BN_ULONG maxdelta = BN_MASK2 - primes[trial_divisions - 1]; BN_CTX_start(ctx); if ((t1 = BN_CTX_get(ctx)) == NULL) @@ -334,7 +551,7 @@ maxdelta = BN_MASK2 - BN_get_word(add); again: - if (!BN_rand(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) + if (!BN_rand_ex(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD, 0, ctx)) goto err; /* we need ((rnd-rem) % add) == 0 */ @@ -358,7 +575,7 @@ } /* we now have a random number 'rnd' to test. */ - for (i = 1; i < NUMPRIMES; i++) { + for (i = 1; i < trial_divisions; i++) { BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); if (mod == (BN_ULONG)-1) goto err; @@ -366,7 +583,7 @@ } delta = 0; loop: - for (i = 1; i < NUMPRIMES; i++) { + for (i = 1; i < trial_divisions; i++) { /* check that rnd is a prime */ if (bits <= 31 && delta <= 0x7fffffff && square(primes[i]) > BN_get_word(rnd) + delta) diff --git a/crypto/bn/bn_prime.pl b/crypto/bn/bn_prime.pl --- a/crypto/bn/bn_prime.pl +++ b/crypto/bn/bn_prime.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# 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 # https://www.openssl.org/source/license.html @@ -11,6 +11,7 @@ # The year the output file is generated. my $YEAR = OpenSSL::copyright::year_of($0); + print <<"EOF"; /* * WARNING: do not edit! @@ -18,7 +19,7 @@ * * Copyright 1998-$YEAR The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c --- a/crypto/bn/bn_print.c +++ b/crypto/bn/bn_print.c @@ -1,292 +1,19 @@ /* * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ #include -#include "crypto/ctype.h" -#include -#include "internal/cryptlib.h" -#include +#include #include "bn_local.h" static const char Hex[] = "0123456789ABCDEF"; -/* Must 'OPENSSL_free' the returned data */ -char *BN_bn2hex(const BIGNUM *a) -{ - int i, j, v, z = 0; - char *buf; - char *p; - - if (BN_is_zero(a)) - return OPENSSL_strdup("0"); - buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); - if (buf == NULL) { - BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE); - goto err; - } - p = buf; - if (a->neg) - *p++ = '-'; - for (i = a->top - 1; i >= 0; i--) { - for (j = BN_BITS2 - 8; j >= 0; j -= 8) { - /* strip leading zeros */ - v = (int)((a->d[i] >> j) & 0xff); - if (z || v != 0) { - *p++ = Hex[v >> 4]; - *p++ = Hex[v & 0x0f]; - z = 1; - } - } - } - *p = '\0'; - err: - return buf; -} - -/* Must 'OPENSSL_free' the returned data */ -char *BN_bn2dec(const BIGNUM *a) -{ - int i = 0, num, ok = 0, n, tbytes; - char *buf = NULL; - char *p; - BIGNUM *t = NULL; - BN_ULONG *bn_data = NULL, *lp; - int bn_data_num; - - /*- - * get an upper bound for the length of the decimal integer - * num <= (BN_num_bits(a) + 1) * log(2) - * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error) - * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1 - */ - i = BN_num_bits(a) * 3; - num = (i / 10 + i / 1000 + 1) + 1; - tbytes = num + 3; /* negative and terminator and one spare? */ - bn_data_num = num / BN_DEC_NUM + 1; - bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); - buf = OPENSSL_malloc(tbytes); - if (buf == NULL || bn_data == NULL) { - BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE); - goto err; - } - if ((t = BN_dup(a)) == NULL) - goto err; - - p = buf; - lp = bn_data; - if (BN_is_zero(t)) { - *p++ = '0'; - *p++ = '\0'; - } else { - if (BN_is_negative(t)) - *p++ = '-'; - - while (!BN_is_zero(t)) { - if (lp - bn_data >= bn_data_num) - goto err; - *lp = BN_div_word(t, BN_DEC_CONV); - if (*lp == (BN_ULONG)-1) - goto err; - lp++; - } - lp--; - /* - * We now have a series of blocks, BN_DEC_NUM chars in length, where - * the last one needs truncation. The blocks need to be reversed in - * order. - */ - n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp); - if (n < 0) - goto err; - p += n; - while (lp != bn_data) { - lp--; - n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp); - if (n < 0) - goto err; - p += n; - } - } - ok = 1; - err: - OPENSSL_free(bn_data); - BN_free(t); - if (ok) - return buf; - OPENSSL_free(buf); - return NULL; -} - -int BN_hex2bn(BIGNUM **bn, const char *a) -{ - BIGNUM *ret = NULL; - BN_ULONG l = 0; - int neg = 0, h, m, i, j, k, c; - int num; - - if (a == NULL || *a == '\0') - return 0; - - if (*a == '-') { - neg = 1; - a++; - } - - for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++) - continue; - - if (i == 0 || i > INT_MAX / 4) - return 0; - - num = i + neg; - if (bn == NULL) - return num; - - /* a is the start of the hex digits, and it is 'i' long */ - if (*bn == NULL) { - if ((ret = BN_new()) == NULL) - return 0; - } else { - ret = *bn; - BN_zero(ret); - } - - /* i is the number of hex digits */ - if (bn_expand(ret, i * 4) == NULL) - goto err; - - j = i; /* least significant 'hex' */ - m = 0; - h = 0; - while (j > 0) { - m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j; - l = 0; - for (;;) { - c = a[j - m]; - k = OPENSSL_hexchar2int(c); - if (k < 0) - k = 0; /* paranoia */ - l = (l << 4) | k; - - if (--m <= 0) { - ret->d[h++] = l; - break; - } - } - j -= BN_BYTES * 2; - } - ret->top = h; - bn_correct_top(ret); - - *bn = ret; - bn_check_top(ret); - /* Don't set the negative flag if it's zero. */ - if (ret->top != 0) - ret->neg = neg; - return num; - err: - if (*bn == NULL) - BN_free(ret); - return 0; -} - -int BN_dec2bn(BIGNUM **bn, const char *a) -{ - BIGNUM *ret = NULL; - BN_ULONG l = 0; - int neg = 0, i, j; - int num; - - if (a == NULL || *a == '\0') - return 0; - if (*a == '-') { - neg = 1; - a++; - } - - for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++) - continue; - - if (i == 0 || i > INT_MAX / 4) - goto err; - - num = i + neg; - if (bn == NULL) - return num; - - /* - * a is the start of the digits, and it is 'i' long. We chop it into - * BN_DEC_NUM digits at a time - */ - if (*bn == NULL) { - if ((ret = BN_new()) == NULL) - return 0; - } else { - ret = *bn; - BN_zero(ret); - } - - /* i is the number of digits, a bit of an over expand */ - if (bn_expand(ret, i * 4) == NULL) - goto err; - - j = BN_DEC_NUM - i % BN_DEC_NUM; - if (j == BN_DEC_NUM) - j = 0; - l = 0; - while (--i >= 0) { - l *= 10; - l += *a - '0'; - a++; - if (++j == BN_DEC_NUM) { - if (!BN_mul_word(ret, BN_DEC_CONV) - || !BN_add_word(ret, l)) - goto err; - l = 0; - j = 0; - } - } - - bn_correct_top(ret); - *bn = ret; - bn_check_top(ret); - /* Don't set the negative flag if it's zero. */ - if (ret->top != 0) - ret->neg = neg; - return num; - err: - if (*bn == NULL) - BN_free(ret); - return 0; -} - -int BN_asc2bn(BIGNUM **bn, const char *a) -{ - const char *p = a; - - if (*p == '-') - p++; - - if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { - if (!BN_hex2bn(bn, p + 2)) - return 0; - } else { - if (!BN_dec2bn(bn, p)) - return 0; - } - /* Don't set the negative flag if it's zero. */ - if (*a == '-' && (*bn)->top != 0) - (*bn)->neg = 1; - return 1; -} - -# ifndef OPENSSL_NO_STDIO +#ifndef OPENSSL_NO_STDIO int BN_print_fp(FILE *fp, const BIGNUM *a) { BIO *b; @@ -299,7 +26,7 @@ BIO_free(b); return ret; } -# endif +#endif int BN_print(BIO *bp, const BIGNUM *a) { diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c --- a/crypto/bn/bn_rand.c +++ b/crypto/bn/bn_rand.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -10,18 +10,22 @@ #include #include #include "internal/cryptlib.h" +#include "crypto/rand.h" #include "bn_local.h" #include #include +#include typedef enum bnrand_flag_e { NORMAL, TESTING, PRIVATE } BNRAND_FLAG; -static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom) +static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom, + unsigned int strength, BN_CTX *ctx) { unsigned char *buf = NULL; int b, ret = 0, bit, bytes, mask; + OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx); if (bits == 0) { if (top != BN_RAND_TOP_ANY || bottom != BN_RAND_BOTTOM_ANY) @@ -38,12 +42,13 @@ buf = OPENSSL_malloc(bytes); if (buf == NULL) { - BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); goto err; } /* make a random number and set the top and bottom bits */ - b = flag == NORMAL ? RAND_bytes(buf, bytes) : RAND_priv_bytes(buf, bytes); + b = flag == NORMAL ? RAND_bytes_ex(libctx, buf, bytes, strength) + : RAND_priv_bytes_ex(libctx, buf, bytes, strength); if (b <= 0) goto err; @@ -55,7 +60,7 @@ unsigned char c; for (i = 0; i < bytes; i++) { - if (RAND_bytes(&c, 1) <= 0) + if (RAND_bytes_ex(libctx, &c, 1, strength) <= 0) goto err; if (c >= 128 && i > 0) buf[i] = buf[i - 1]; @@ -90,33 +95,54 @@ return ret; toosmall: - BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL); + ERR_raise(ERR_LIB_BN, BN_R_BITS_TOO_SMALL); return 0; } +int BN_rand_ex(BIGNUM *rnd, int bits, int top, int bottom, + unsigned int strength, BN_CTX *ctx) +{ + return bnrand(NORMAL, rnd, bits, top, bottom, strength, ctx); +} +#ifndef FIPS_MODULE int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) { - return bnrand(NORMAL, rnd, bits, top, bottom); + return bnrand(NORMAL, rnd, bits, top, bottom, 0, NULL); } int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom) { - return bnrand(TESTING, rnd, bits, top, bottom); + return bnrand(TESTING, rnd, bits, top, bottom, 0, NULL); +} +#endif + +int BN_priv_rand_ex(BIGNUM *rnd, int bits, int top, int bottom, + unsigned int strength, BN_CTX *ctx) +{ + return bnrand(PRIVATE, rnd, bits, top, bottom, strength, ctx); } +#ifndef FIPS_MODULE int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom) { - return bnrand(PRIVATE, rnd, bits, top, bottom); + return bnrand(PRIVATE, rnd, bits, top, bottom, 0, NULL); } +#endif /* random number r: 0 <= r < range */ -static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range) +static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range, + unsigned int strength, BN_CTX *ctx) { int n; int count = 100; + if (r == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (range->neg || BN_is_zero(range)) { - BNerr(BN_F_BNRAND_RANGE, BN_R_INVALID_RANGE); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_RANGE); return 0; } @@ -132,7 +158,8 @@ * than range */ do { - if (!bnrand(flag, r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + if (!bnrand(flag, r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, + strength, ctx)) return 0; /* @@ -150,7 +177,7 @@ } if (!--count) { - BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS); return 0; } @@ -159,11 +186,12 @@ } else { do { /* range = 11..._2 or range = 101..._2 */ - if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, + ctx)) return 0; if (!--count) { - BNerr(BN_F_BNRAND_RANGE, BN_R_TOO_MANY_ITERATIONS); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS); return 0; } } @@ -174,16 +202,32 @@ return 1; } +int BN_rand_range_ex(BIGNUM *r, const BIGNUM *range, unsigned int strength, + BN_CTX *ctx) +{ + return bnrand_range(NORMAL, r, range, strength, ctx); +} + +#ifndef FIPS_MODULE int BN_rand_range(BIGNUM *r, const BIGNUM *range) { - return bnrand_range(NORMAL, r, range); + return bnrand_range(NORMAL, r, range, 0, NULL); } +#endif +int BN_priv_rand_range_ex(BIGNUM *r, const BIGNUM *range, unsigned int strength, + BN_CTX *ctx) +{ + return bnrand_range(PRIVATE, r, range, strength, ctx); +} + +#ifndef FIPS_MODULE int BN_priv_rand_range(BIGNUM *r, const BIGNUM *range) { - return bnrand_range(PRIVATE, r, range); + return bnrand_range(PRIVATE, r, range, 0, NULL); } +# ifndef OPENSSL_NO_DEPRECATED_3_0 int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) { return BN_rand(rnd, bits, top, bottom); @@ -193,6 +237,8 @@ { return BN_rand_range(r, range); } +# endif +#endif /* * BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike @@ -206,7 +252,7 @@ const BIGNUM *priv, const unsigned char *message, size_t message_len, BN_CTX *ctx) { - SHA512_CTX sha; + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); /* * We use 512 bits of random data per iteration to ensure that we have at * least |range| bits of randomness. @@ -217,8 +263,13 @@ /* We generate |range|+8 bytes of random output. */ const unsigned num_k_bytes = BN_num_bytes(range) + 8; unsigned char private_bytes[96]; - unsigned char *k_bytes; + unsigned char *k_bytes = NULL; int ret = 0; + EVP_MD *md = NULL; + OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx); + + if (mdctx == NULL) + goto err; k_bytes = OPENSSL_malloc(num_k_bytes); if (k_bytes == NULL) @@ -231,19 +282,27 @@ * large and we don't handle this case in order to avoid leaking the * length of the private key. */ - BNerr(BN_F_BN_GENERATE_DSA_NONCE, BN_R_PRIVATE_KEY_TOO_LARGE); + ERR_raise(ERR_LIB_BN, BN_R_PRIVATE_KEY_TOO_LARGE); goto err; } + md = EVP_MD_fetch(libctx, "SHA512", NULL); + if (md == NULL) { + ERR_raise(ERR_LIB_BN, BN_R_NO_SUITABLE_DIGEST); + goto err; + } for (done = 0; done < num_k_bytes;) { - if (RAND_priv_bytes(random_bytes, sizeof(random_bytes)) != 1) + if (RAND_priv_bytes_ex(libctx, random_bytes, sizeof(random_bytes), 0) <= 0) + goto err; + + if (!EVP_DigestInit_ex(mdctx, md, NULL) + || !EVP_DigestUpdate(mdctx, &done, sizeof(done)) + || !EVP_DigestUpdate(mdctx, private_bytes, + sizeof(private_bytes)) + || !EVP_DigestUpdate(mdctx, message, message_len) + || !EVP_DigestUpdate(mdctx, random_bytes, sizeof(random_bytes)) + || !EVP_DigestFinal_ex(mdctx, digest, NULL)) goto err; - SHA512_Init(&sha); - SHA512_Update(&sha, &done, sizeof(done)); - SHA512_Update(&sha, private_bytes, sizeof(private_bytes)); - SHA512_Update(&sha, message, message_len); - SHA512_Update(&sha, random_bytes, sizeof(random_bytes)); - SHA512_Final(digest, &sha); todo = num_k_bytes - done; if (todo > SHA512_DIGEST_LENGTH) @@ -259,7 +318,11 @@ ret = 1; err: - OPENSSL_free(k_bytes); + EVP_MD_CTX_free(mdctx); + EVP_MD_free(md); + OPENSSL_clear_free(k_bytes, num_k_bytes); + OPENSSL_cleanse(digest, sizeof(digest)); + OPENSSL_cleanse(random_bytes, sizeof(random_bytes)); OPENSSL_cleanse(private_bytes, sizeof(private_bytes)); return ret; } diff --git a/crypto/bn/bn_recp.c b/crypto/bn/bn_recp.c --- a/crypto/bn/bn_recp.c +++ b/crypto/bn/bn_recp.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -22,7 +22,7 @@ BN_RECP_CTX *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BNerr(BN_F_BN_RECP_CTX_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); return NULL; } @@ -146,7 +146,7 @@ j = 0; while (BN_ucmp(r, &(recp->N)) >= 0) { if (j++ > 2) { - BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL); + ERR_raise(ERR_LIB_BN, BN_R_BAD_RECIPROCAL); goto err; } if (!BN_usub(r, r, &(recp->N))) diff --git a/crypto/bn/bn_rsa_fips186_4.c b/crypto/bn/bn_rsa_fips186_4.c new file mode 100644 --- /dev/null +++ b/crypto/bn/bn_rsa_fips186_4.c @@ -0,0 +1,367 @@ +/* + * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2018-2019, Oracle and/or its affiliates. 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 + * https://www.openssl.org/source/license.html + */ + +/* + * According to NIST SP800-131A "Transitioning the use of cryptographic + * algorithms and key lengths" Generation of 1024 bit RSA keys are no longer + * allowed for signatures (Table 2) or key transport (Table 5). In the code + * below any attempt to generate 1024 bit RSA keys will result in an error (Note + * that digital signature verification can still use deprecated 1024 bit keys). + * + * FIPS 186-4 relies on the use of the auxiliary primes p1, p2, q1 and q2 that + * must be generated before the module generates the RSA primes p and q. + * Table B.1 in FIPS 186-4 specifies RSA modulus lengths of 2048 and + * 3072 bits only, the min/max total length of the auxiliary primes. + * FIPS 186-5 Table A.1 includes an additional entry for 4096 which has been + * included here. + */ +#include +#include +#include "bn_local.h" +#include "crypto/bn.h" +#include "internal/nelem.h" + +#if BN_BITS2 == 64 +# define BN_DEF(lo, hi) (BN_ULONG)hi<<32|lo +#else +# define BN_DEF(lo, hi) lo, hi +#endif + +/* 1 / sqrt(2) * 2^256, rounded up */ +static const BN_ULONG inv_sqrt_2_val[] = { + BN_DEF(0x83339916UL, 0xED17AC85UL), BN_DEF(0x893BA84CUL, 0x1D6F60BAUL), + BN_DEF(0x754ABE9FUL, 0x597D89B3UL), BN_DEF(0xF9DE6484UL, 0xB504F333UL) +}; + +const BIGNUM ossl_bn_inv_sqrt_2 = { + (BN_ULONG *)inv_sqrt_2_val, + OSSL_NELEM(inv_sqrt_2_val), + OSSL_NELEM(inv_sqrt_2_val), + 0, + BN_FLG_STATIC_DATA +}; + +/* + * FIPS 186-5 Table A.1. "Min length of auxiliary primes p1, p2, q1, q2". + * (FIPS 186-5 has an entry for >= 4096 bits). + * + * Params: + * nbits The key size in bits. + * Returns: + * The minimum size of the auxiliary primes or 0 if nbits is invalid. + */ +static int bn_rsa_fips186_5_aux_prime_min_size(int nbits) +{ + if (nbits >= 4096) + return 201; + if (nbits >= 3072) + return 171; + if (nbits >= 2048) + return 141; + return 0; +} + +/* + * FIPS 186-5 Table A.1 "Max of len(p1) + len(p2) and + * len(q1) + len(q2) for p,q Probable Primes". + * (FIPS 186-5 has an entry for >= 4096 bits). + * Params: + * nbits The key size in bits. + * Returns: + * The maximum length or 0 if nbits is invalid. + */ +static int bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(int nbits) +{ + if (nbits >= 4096) + return 2030; + if (nbits >= 3072) + return 1518; + if (nbits >= 2048) + return 1007; + return 0; +} + +/* + * Find the first odd integer that is a probable prime. + * + * See section FIPS 186-4 B.3.6 (Steps 4.2/5.2). + * + * Params: + * Xp1 The passed in starting point to find a probably prime. + * p1 The returned probable prime (first odd integer >= Xp1) + * ctx A BN_CTX object. + * cb An optional BIGNUM callback. + * Returns: 1 on success otherwise it returns 0. + */ +static int bn_rsa_fips186_4_find_aux_prob_prime(const BIGNUM *Xp1, + BIGNUM *p1, BN_CTX *ctx, + BN_GENCB *cb) +{ + int ret = 0; + int i = 0; + int tmp = 0; + + if (BN_copy(p1, Xp1) == NULL) + return 0; + BN_set_flags(p1, BN_FLG_CONSTTIME); + + /* Find the first odd number >= Xp1 that is probably prime */ + for(;;) { + i++; + BN_GENCB_call(cb, 0, i); + /* MR test with trial division */ + tmp = BN_check_prime(p1, ctx, cb); + if (tmp > 0) + break; + if (tmp < 0) + goto err; + /* Get next odd number */ + if (!BN_add_word(p1, 2)) + goto err; + } + BN_GENCB_call(cb, 2, i); + ret = 1; +err: + return ret; +} + +/* + * Generate a probable prime (p or q). + * + * See FIPS 186-4 B.3.6 (Steps 4 & 5) + * + * Params: + * p The returned probable prime. + * Xpout An optionally returned random number used during generation of p. + * p1, p2 The returned auxiliary primes. If NULL they are not returned. + * Xp An optional passed in value (that is random number used during + * generation of p). + * Xp1, Xp2 Optional passed in values that are normally generated + * internally. Used to find p1, p2. + * nlen The bit length of the modulus (the key size). + * e The public exponent. + * ctx A BN_CTX object. + * cb An optional BIGNUM callback. + * Returns: 1 on success otherwise it returns 0. + */ +int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout, + BIGNUM *p1, BIGNUM *p2, + const BIGNUM *Xp, const BIGNUM *Xp1, + const BIGNUM *Xp2, int nlen, + const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb) +{ + int ret = 0; + BIGNUM *p1i = NULL, *p2i = NULL, *Xp1i = NULL, *Xp2i = NULL; + int bitlen; + + if (p == NULL || Xpout == NULL) + return 0; + + BN_CTX_start(ctx); + + p1i = (p1 != NULL) ? p1 : BN_CTX_get(ctx); + p2i = (p2 != NULL) ? p2 : BN_CTX_get(ctx); + Xp1i = (Xp1 != NULL) ? (BIGNUM *)Xp1 : BN_CTX_get(ctx); + Xp2i = (Xp2 != NULL) ? (BIGNUM *)Xp2 : BN_CTX_get(ctx); + if (p1i == NULL || p2i == NULL || Xp1i == NULL || Xp2i == NULL) + goto err; + + bitlen = bn_rsa_fips186_5_aux_prime_min_size(nlen); + if (bitlen == 0) + goto err; + + /* (Steps 4.1/5.1): Randomly generate Xp1 if it is not passed in */ + if (Xp1 == NULL) { + /* Set the top and bottom bits to make it odd and the correct size */ + if (!BN_priv_rand_ex(Xp1i, bitlen, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD, + 0, ctx)) + goto err; + } + /* (Steps 4.1/5.1): Randomly generate Xp2 if it is not passed in */ + if (Xp2 == NULL) { + /* Set the top and bottom bits to make it odd and the correct size */ + if (!BN_priv_rand_ex(Xp2i, bitlen, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD, + 0, ctx)) + goto err; + } + + /* (Steps 4.2/5.2) - find first auxiliary probable primes */ + if (!bn_rsa_fips186_4_find_aux_prob_prime(Xp1i, p1i, ctx, cb) + || !bn_rsa_fips186_4_find_aux_prob_prime(Xp2i, p2i, ctx, cb)) + goto err; + /* (Table B.1) auxiliary prime Max length check */ + if ((BN_num_bits(p1i) + BN_num_bits(p2i)) >= + bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(nlen)) + goto err; + /* (Steps 4.3/5.3) - generate prime */ + if (!ossl_bn_rsa_fips186_4_derive_prime(p, Xpout, Xp, p1i, p2i, nlen, e, + ctx, cb)) + goto err; + ret = 1; +err: + /* Zeroize any internally generated values that are not returned */ + if (p1 == NULL) + BN_clear(p1i); + if (p2 == NULL) + BN_clear(p2i); + if (Xp1 == NULL) + BN_clear(Xp1i); + if (Xp2 == NULL) + BN_clear(Xp2i); + BN_CTX_end(ctx); + return ret; +} + +/* + * Constructs a probable prime (a candidate for p or q) using 2 auxiliary + * prime numbers and the Chinese Remainder Theorem. + * + * See FIPS 186-4 C.9 "Compute a Probable Prime Factor Based on Auxiliary + * Primes". Used by FIPS 186-4 B.3.6 Section (4.3) for p and Section (5.3) for q. + * + * Params: + * Y The returned prime factor (private_prime_factor) of the modulus n. + * X The returned random number used during generation of the prime factor. + * Xin An optional passed in value for X used for testing purposes. + * r1 An auxiliary prime. + * r2 An auxiliary prime. + * nlen The desired length of n (the RSA modulus). + * e The public exponent. + * ctx A BN_CTX object. + * cb An optional BIGNUM callback object. + * Returns: 1 on success otherwise it returns 0. + * Assumptions: + * Y, X, r1, r2, e are not NULL. + */ +int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin, + const BIGNUM *r1, const BIGNUM *r2, + int nlen, const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb) +{ + int ret = 0; + int i, imax; + int bits = nlen >> 1; + BIGNUM *tmp, *R, *r1r2x2, *y1, *r1x2; + BIGNUM *base, *range; + + BN_CTX_start(ctx); + + base = BN_CTX_get(ctx); + range = BN_CTX_get(ctx); + R = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + r1r2x2 = BN_CTX_get(ctx); + y1 = BN_CTX_get(ctx); + r1x2 = BN_CTX_get(ctx); + if (r1x2 == NULL) + goto err; + + if (Xin != NULL && BN_copy(X, Xin) == NULL) + goto err; + + /* + * We need to generate a random number X in the range + * 1/sqrt(2) * 2^(nlen/2) <= X < 2^(nlen/2). + * We can rewrite that as: + * base = 1/sqrt(2) * 2^(nlen/2) + * range = ((2^(nlen/2))) - (1/sqrt(2) * 2^(nlen/2)) + * X = base + random(range) + * We only have the first 256 bit of 1/sqrt(2) + */ + if (Xin == NULL) { + if (bits < BN_num_bits(&ossl_bn_inv_sqrt_2)) + goto err; + if (!BN_lshift(base, &ossl_bn_inv_sqrt_2, + bits - BN_num_bits(&ossl_bn_inv_sqrt_2)) + || !BN_lshift(range, BN_value_one(), bits) + || !BN_sub(range, range, base)) + goto err; + } + + if (!(BN_lshift1(r1x2, r1) + /* (Step 1) GCD(2r1, r2) = 1 */ + && BN_gcd(tmp, r1x2, r2, ctx) + && BN_is_one(tmp) + /* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */ + && BN_mod_inverse(R, r2, r1x2, ctx) + && BN_mul(R, R, r2, ctx) /* R = (r2^-1 mod 2r1) * r2 */ + && BN_mod_inverse(tmp, r1x2, r2, ctx) + && BN_mul(tmp, tmp, r1x2, ctx) /* tmp = (2r1^-1 mod r2)*2r1 */ + && BN_sub(R, R, tmp) + /* Calculate 2r1r2 */ + && BN_mul(r1r2x2, r1x2, r2, ctx))) + goto err; + /* Make positive by adding the modulus */ + if (BN_is_negative(R) && !BN_add(R, R, r1r2x2)) + goto err; + + /* + * In FIPS 186-4 imax was set to 5 * nlen/2. + * Analysis by Allen Roginsky (See https://csrc.nist.gov/CSRC/media/Publications/fips/186/4/final/documents/comments-received-fips186-4-december-2015.pdf + * page 68) indicates this has a 1 in 2 million chance of failure. + * The number has been updated to 20 * nlen/2 as used in + * FIPS186-5 Appendix B.9 Step 9. + */ + imax = 20 * bits; /* max = 20/2 * nbits */ + for (;;) { + if (Xin == NULL) { + /* + * (Step 3) Choose Random X such that + * sqrt(2) * 2^(nlen/2-1) <= Random X <= (2^(nlen/2)) - 1. + */ + if (!BN_priv_rand_range_ex(X, range, 0, ctx) || !BN_add(X, X, base)) + goto end; + } + /* (Step 4) Y = X + ((R - X) mod 2r1r2) */ + if (!BN_mod_sub(Y, R, X, r1r2x2, ctx) || !BN_add(Y, Y, X)) + goto err; + /* (Step 5) */ + i = 0; + for (;;) { + /* (Step 6) */ + if (BN_num_bits(Y) > bits) { + if (Xin == NULL) + break; /* Randomly Generated X so Go back to Step 3 */ + else + goto err; /* X is not random so it will always fail */ + } + BN_GENCB_call(cb, 0, 2); + + /* (Step 7) If GCD(Y-1) == 1 & Y is probably prime then return Y */ + if (BN_copy(y1, Y) == NULL + || !BN_sub_word(y1, 1) + || !BN_gcd(tmp, y1, e, ctx)) + goto err; + if (BN_is_one(tmp)) { + int rv = BN_check_prime(Y, ctx, cb); + + if (rv > 0) + goto end; + if (rv < 0) + goto err; + } + /* (Step 8-10) */ + if (++i >= imax) { + ERR_raise(ERR_LIB_BN, BN_R_NO_PRIME_CANDIDATE); + goto err; + } + if (!BN_add(Y, Y, r1r2x2)) + goto err; + } + } +end: + ret = 1; + BN_GENCB_call(cb, 3, 0); +err: + BN_clear(y1); + BN_CTX_end(ctx); + return ret; +} diff --git a/crypto/bn/bn_shift.c b/crypto/bn/bn_shift.c --- a/crypto/bn/bn_shift.c +++ b/crypto/bn/bn_shift.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -83,7 +83,7 @@ int ret; if (n < 0) { - BNerr(BN_F_BN_LSHIFT, BN_R_INVALID_SHIFT); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_SHIFT); return 0; } @@ -152,7 +152,7 @@ int ret = 0; if (n < 0) { - BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT); + ERR_raise(ERR_LIB_BN, BN_R_INVALID_SHIFT); return 0; } diff --git a/crypto/bn/bn_sparc.c b/crypto/bn/bn_sparc.c new file mode 100644 --- /dev/null +++ b/crypto/bn/bn_sparc.c @@ -0,0 +1,77 @@ +/* + * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include "internal/cryptlib.h" +#include "crypto/sparc_arch.h" +#include "bn_local.h" /* for definition of bn_mul_mont */ + +int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num) +{ + int bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); + + if (!(num & 1) && num >= 6) { + if ((num & 15) == 0 && num <= 64 && + (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) == + (CFR_MONTMUL | CFR_MONTSQR)) { + typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, + const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0); + static const bn_mul_mont_f funcs[4] = { + bn_mul_mont_t4_8, bn_mul_mont_t4_16, + bn_mul_mont_t4_24, bn_mul_mont_t4_32 + }; + bn_mul_mont_f worker = funcs[num / 16 - 1]; + + if ((*worker) (rp, ap, bp, np, n0)) + return 1; + /* retry once and fall back */ + if ((*worker) (rp, ap, bp, np, n0)) + return 1; + return bn_mul_mont_vis3(rp, ap, bp, np, n0, num); + } + if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3)) + return bn_mul_mont_vis3(rp, ap, bp, np, n0, num); + else if (num >= 8 && + /* + * bn_mul_mont_fpu doesn't use FMADD, we just use the + * flag to detect when FPU path is preferable in cases + * when current heuristics is unreliable. [it works + * out because FMADD-capable processors where FPU + * code path is undesirable are also VIS3-capable and + * VIS3 code path takes precedence.] + */ + ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) || + (OPENSSL_sparcv9cap_P[0] & + (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) == + (SPARCV9_PREFER_FPU | SPARCV9_VIS1) )) + return bn_mul_mont_fpu(rp, ap, bp, np, n0, num); + } + return bn_mul_mont_int(rp, ap, bp, np, n0, num); +} diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c --- a/crypto/bn/bn_sqr.c +++ b/crypto/bn/bn_sqr.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_sqrt.c b/crypto/bn/bn_sqrt.c --- a/crypto/bn/bn_sqrt.c +++ b/crypto/bn/bn_sqrt.c @@ -1,7 +1,7 @@ /* * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -23,6 +23,7 @@ int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; + int used_ctx = 0; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { @@ -39,7 +40,7 @@ return ret; } - BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + ERR_raise(ERR_LIB_BN, BN_R_P_IS_NOT_PRIME); return NULL; } @@ -58,6 +59,7 @@ } BN_CTX_start(ctx); + used_ctx = 1; A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); @@ -181,7 +183,7 @@ if (!BN_set_word(y, i)) goto end; } else { - if (!BN_priv_rand(y, BN_num_bits(p), 0, 0)) + if (!BN_priv_rand_ex(y, BN_num_bits(p), 0, 0, 0, ctx)) goto end; if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub) (y, y, p)) @@ -198,7 +200,7 @@ goto end; if (r == 0) { /* m divides p */ - BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + ERR_raise(ERR_LIB_BN, BN_R_P_IS_NOT_PRIME); goto end; } } @@ -210,7 +212,7 @@ * than just bad luck. Even if p is not prime, we should have found * some y such that r == -1. */ - BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); + ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS); goto end; } @@ -225,7 +227,7 @@ if (!BN_mod_exp(y, y, q, p, ctx)) goto end; if (BN_is_one(y)) { - BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + ERR_raise(ERR_LIB_BN, BN_R_P_IS_NOT_PRIME); goto end; } @@ -317,7 +319,7 @@ } /* If not found, a is not a square or p is not prime. */ if (i >= e) { - BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE); goto end; } @@ -348,7 +350,7 @@ err = 1; if (!err && 0 != BN_cmp(x, A)) { - BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE); err = 1; } } @@ -359,7 +361,8 @@ BN_clear_free(ret); ret = NULL; } - BN_CTX_end(ctx); + if (used_ctx) + BN_CTX_end(ctx); bn_check_top(ret); return ret; } diff --git a/crypto/bn/bn_srp.c b/crypto/bn/bn_srp.c --- a/crypto/bn/bn_srp.c +++ b/crypto/bn/bn_srp.c @@ -1,7 +1,7 @@ /* - * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -48,7 +48,7 @@ bn_pack4(0xEEAF, 0x0AB9, 0xADB3, 0x8DD6) }; -const BIGNUM bn_group_1024 = { +const BIGNUM ossl_bn_group_1024 = { (BN_ULONG *)bn_group_1024_value, OSSL_NELEM(bn_group_1024_value), OSSL_NELEM(bn_group_1024_value), @@ -83,7 +83,7 @@ bn_pack4(0x9DEF, 0x3CAF, 0xB939, 0x277A) }; -const BIGNUM bn_group_1536 = { +const BIGNUM ossl_bn_group_1536 = { (BN_ULONG *)bn_group_1536_value, OSSL_NELEM(bn_group_1536_value), OSSL_NELEM(bn_group_1536_value), @@ -126,7 +126,7 @@ bn_pack4(0xAC6B, 0xDB41, 0x324A, 0x9A9B) }; -const BIGNUM bn_group_2048 = { +const BIGNUM ossl_bn_group_2048 = { (BN_ULONG *)bn_group_2048_value, OSSL_NELEM(bn_group_2048_value), OSSL_NELEM(bn_group_2048_value), @@ -185,7 +185,7 @@ bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) }; -const BIGNUM bn_group_3072 = { +const BIGNUM ossl_bn_group_3072 = { (BN_ULONG *)bn_group_3072_value, OSSL_NELEM(bn_group_3072_value), OSSL_NELEM(bn_group_3072_value), @@ -260,7 +260,7 @@ bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) }; -const BIGNUM bn_group_4096 = { +const BIGNUM ossl_bn_group_4096 = { (BN_ULONG *)bn_group_4096_value, OSSL_NELEM(bn_group_4096_value), OSSL_NELEM(bn_group_4096_value), @@ -367,7 +367,7 @@ bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) }; -const BIGNUM bn_group_6144 = { +const BIGNUM ossl_bn_group_6144 = { (BN_ULONG *)bn_group_6144_value, OSSL_NELEM(bn_group_6144_value), OSSL_NELEM(bn_group_6144_value), @@ -506,7 +506,7 @@ bn_pack4(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF) }; -const BIGNUM bn_group_8192 = { +const BIGNUM ossl_bn_group_8192 = { (BN_ULONG *)bn_group_8192_value, OSSL_NELEM(bn_group_8192_value), OSSL_NELEM(bn_group_8192_value), @@ -516,7 +516,7 @@ static const BN_ULONG bn_generator_19_value[] = { 19 }; -const BIGNUM bn_generator_19 = { +const BIGNUM ossl_bn_generator_19 = { (BN_ULONG *)bn_generator_19_value, 1, 1, @@ -525,7 +525,7 @@ }; static const BN_ULONG bn_generator_5_value[] = { 5 }; -const BIGNUM bn_generator_5 = { +const BIGNUM ossl_bn_generator_5 = { (BN_ULONG *)bn_generator_5_value, 1, 1, @@ -534,7 +534,7 @@ }; static const BN_ULONG bn_generator_2_value[] = { 2 }; -const BIGNUM bn_generator_2 = { +const BIGNUM ossl_bn_generator_2 = { (BN_ULONG *)bn_generator_2_value, 1, 1, diff --git a/crypto/bn/bn_word.c b/crypto/bn/bn_word.c --- a/crypto/bn/bn_word.c +++ b/crypto/bn/bn_word.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/bn_x931p.c b/crypto/bn/bn_x931p.c --- a/crypto/bn/bn_x931p.c +++ b/crypto/bn/bn_x931p.c @@ -1,12 +1,14 @@ /* - * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include "bn_local.h" @@ -30,7 +32,7 @@ i++; BN_GENCB_call(cb, 0, i); /* NB 27 MR is specified in X9.31 */ - is_prime = BN_is_prime_fasttest_ex(pi, 27, ctx, 1, cb); + is_prime = BN_check_prime(pi, ctx, cb); if (is_prime < 0) return 0; if (is_prime) @@ -131,7 +133,7 @@ * offering similar or better guarantees 50 MR is considerably * better. */ - int r = BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb); + int r = BN_check_prime(p, ctx, cb); if (r < 0) goto err; if (r) @@ -173,8 +175,9 @@ * - 1. By setting the top two bits we ensure that the lower bound is * exceeded. */ - if (!BN_priv_rand(Xp, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) - goto err; + if (!BN_priv_rand_ex(Xp, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY, 0, + ctx)) + return 0; BN_CTX_start(ctx); t = BN_CTX_get(ctx); @@ -182,7 +185,8 @@ goto err; for (i = 0; i < 1000; i++) { - if (!BN_priv_rand(Xq, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) + if (!BN_priv_rand_ex(Xq, nbits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY, 0, + ctx)) goto err; /* Check that |Xp - Xq| > 2^(nbits - 100) */ @@ -227,9 +231,9 @@ if (Xp1 == NULL || Xp2 == NULL) goto error; - if (!BN_priv_rand(Xp1, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + if (!BN_priv_rand_ex(Xp1, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY, 0, ctx)) goto error; - if (!BN_priv_rand(Xp2, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + if (!BN_priv_rand_ex(Xp2, 101, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY, 0, ctx)) goto error; if (!BN_X931_derive_prime_ex(p, p1, p2, Xp, Xp1, Xp2, e, ctx, cb)) goto error; diff --git a/crypto/bn/build.info b/crypto/bn/build.info --- a/crypto/bn/build.info +++ b/crypto/bn/build.info @@ -1,67 +1,177 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c bn_mod.c \ - bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \ - bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c \ - {- $target{bn_asm_src} -} \ + +$BNASM=bn_asm.c +IF[{- !$disabled{asm} -}] + # Define source files and macros per asm architecture + # Known macros are: + # + # OPENSSL_BN_ASM_PART_WORDS For any collection with /-586/ file names + # OPENSSL_BN_ASM_MONT For any collection with /-mont/ file names + # OPENSSL_BN_ASM_MONT5 For any collection with /-mont5/ file names + # OPENSSL_BN_ASM_GF2m For any collection with /-gf2m/ file names + # OPENSSL_IA32_SSE2 For any collection with /86/ file names + # when sse2 is enabled + # BN_DIV3W For any collection with /-div3w/ file names + # + # All variables are named in such a way that they can be "indexed" with + # $target{asm_arch} + + $BNASM_x86=bn-586.S co-586.S x86-mont.S x86-gf2m.S + # bn-586 is the only one implementing bn_*_part_words + # => OPENSSL_BN_ASM_PART_WORDS + $BNDEF_x86=OPENSSL_BN_ASM_PART_WORDS OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m + $BNDEF_x86_sse2=OPENSSL_IA32_SSE2 + + $BNASM_x86_64=\ + x86_64-mont.s x86_64-mont5.s x86_64-gf2m.s rsaz_exp.c rsaz-x86_64.s \ + rsaz-avx2.s rsaz_exp_x2.c rsaz-avx512.s + IF[{- $config{target} !~ /^VC/ -}] + $BNASM_x86_64=asm/x86_64-gcc.c $BNASM_x86_64 + ELSE + $BNASM_x86_64=bn_asm.c $BNASM_x86_64 + ENDIF + $BNDEF_x86_64=OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_MONT5 OPENSSL_BN_ASM_GF2m + $BNDEF_x86_64_sse2=OPENSSL_IA32_SSE2 + + IF[{- $config{target} !~ /^VC/ -}] + $BNASM_ia64=bn-ia64.s ia64-mont.s + ELSE + $BNASM_ia64=bn_asm.c ia64-mont.s + ENDIF + + $BNASM_sparcv9=asm/sparcv8plus.S sparcv9-mont.S sparcv9a-mont.S vis3-mont.S \ + sparct4-mont.S bn_sparc.c + $BNDEF_sparcv9=OPENSSL_BN_ASM_MONT + $BNASM_sparcv9_ec2m=sparcv9-gf2m.S + $BNDEF_sparcv9_ec2m=OPENSSL_BN_ASM_GF2m + + $BNASM_sparcv8=asm/sparcv8.S + + $BNASM_alpha=bn_asm.c alpha-mont.S + $BNDEF_alpha=OPENSSL_BN_ASM_MONT + + $BNASM_mips32=bn-mips.S mips-mont.S + $BNDEF_mips32=OPENSSL_BN_ASM_MONT + $BNASM_mips64=$BNASM_mips32 + $BNDEF_mips64=$BNDEF_mips32 + + IF[{- ($target{perlasm_scheme} // '') eq '31' -}] + $BNASM_s390x=bn_asm.c s390x-mont.S + ELSE + $BNASM_s390x=asm/s390x.S s390x-mont.S + ENDIF + $BNDEF_s390x=OPENSSL_BN_ASM_MONT + $BNASM_s390x_ec2m=s390x-gf2m.s + $BNDEF_s390x_ec2m=OPENSSL_BN_ASM_GF2m + + $BNASM_armv4=bn_asm.c armv4-mont.S + $BNDEF_armv4=OPENSSL_BN_ASM_MONT + $BNASM_armv4_ec2m=armv4-gf2m.S + $BNDEF_armv4_ec2m=OPENSSL_BN_ASM_GF2m + + $BNASM_aarch64=bn_asm.c armv8-mont.S + $BNDEF_aarch64=OPENSSL_BN_ASM_MONT + + $BNASM_parisc11=bn_asm.c parisc-mont.s + $BNDEF_parisc11=OPENSSL_BN_ASM_MONT + $BNASM_parisc20_64=$BNASM_parisc11 + $BNDEF_parisc20_64=$BNDEF_parisc11 + + $BNASM_ppc32=bn_ppc.c bn-ppc.s ppc-mont.s + $BNDEF_ppc32=OPENSSL_BN_ASM_MONT + $BNASM_ppc64=$BNASM_ppc32 + $BNDEF_ppc64=$BNDEF_ppc32 + + $BNASM_c64xplus=asm/bn-c64xplus.asm + $BNASM_c64xplus_ec2m=c64xplus-gf2m.s + $BNDEF_c64xplus_ec2m=OPENSSL_BN_ASM_GF2m + + # Now that we have defined all the arch specific variables, use the + # appropriate ones, and define the appropriate macros + IF[$BNASM_{- $target{asm_arch} -}] + $BNASM=$BNASM_{- $target{asm_arch} -} + $BNDEF=$BNDEF_{- $target{asm_arch} -} + IF[{- !$disabled{ec2m} -}] + $BNASM=$BNASM $BNASM_{- $target{asm_arch} -}_ec2m + $BNDEF=$BNDEF $BNDEF_{- $target{asm_arch} -}_ec2m + ENDIF + IF[{- !$disabled{sse2} -}] + $BNDEF=$BNDEF $BNDEF_{- $target{asm_arch} -}_sse2 + ENDIF + ENDIF +ENDIF + +$COMMON=bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c \ + bn_mod.c bn_conv.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \ + bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_sqr.c \ bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \ - bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c \ - rsa_sup_mul.c + bn_intern.c bn_dh.c bn_rsa_fips186_4.c bn_const.c rsa_sup_mul.c +SOURCE[../../libcrypto]=$COMMON $BNASM bn_print.c bn_err.c bn_srp.c +DEFINE[../../libcrypto]=$BNDEF +IF[{- !$disabled{'deprecated-0.9.8'} -}] + SOURCE[../../libcrypto]=bn_depr.c +ENDIF +IF[{- !$disabled{'deprecated-3.0'} -}] + SOURCE[../../libcrypto]=bn_x931p.c +ENDIF +SOURCE[../../providers/libfips.a]=$COMMON $BNASM +DEFINE[../../providers/libfips.a]=$BNDEF +# Implementations are now spread across several libraries, so the defines +# need to be applied to all affected libraries and modules. +DEFINE[../../providers/libcommon.a]=$BNDEF INCLUDE[bn_exp.o]=.. -GENERATE[bn-586.s]=asm/bn-586.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[bn-586.s]=../perlasm/x86asm.pl -GENERATE[co-586.s]=asm/co-586.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[co-586.s]=../perlasm/x86asm.pl -GENERATE[x86-mont.s]=asm/x86-mont.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[x86-mont.s]=../perlasm/x86asm.pl -GENERATE[x86-gf2m.s]=asm/x86-gf2m.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) -DEPEND[x86-gf2m.s]=../perlasm/x86asm.pl - -GENERATE[sparcv9a-mont.S]=asm/sparcv9a-mont.pl $(PERLASM_SCHEME) +GENERATE[bn-586.S]=asm/bn-586.pl +DEPEND[bn-586.S]=../perlasm/x86asm.pl +GENERATE[co-586.S]=asm/co-586.pl +DEPEND[co-586.S]=../perlasm/x86asm.pl +GENERATE[x86-mont.S]=asm/x86-mont.pl +DEPEND[x86-mont.S]=../perlasm/x86asm.pl +GENERATE[x86-gf2m.S]=asm/x86-gf2m.pl +DEPEND[x86-gf2m.S]=../perlasm/x86asm.pl + +GENERATE[sparcv9a-mont.S]=asm/sparcv9a-mont.pl INCLUDE[sparcv9a-mont.o]=.. -GENERATE[sparcv9-mont.S]=asm/sparcv9-mont.pl $(PERLASM_SCHEME) +GENERATE[sparcv9-mont.S]=asm/sparcv9-mont.pl INCLUDE[sparcv9-mont.o]=.. -GENERATE[vis3-mont.S]=asm/vis3-mont.pl $(PERLASM_SCHEME) +GENERATE[vis3-mont.S]=asm/vis3-mont.pl INCLUDE[vis3-mont.o]=.. -GENERATE[sparct4-mont.S]=asm/sparct4-mont.pl $(PERLASM_SCHEME) +GENERATE[sparct4-mont.S]=asm/sparct4-mont.pl INCLUDE[sparct4-mont.o]=.. -GENERATE[sparcv9-gf2m.S]=asm/sparcv9-gf2m.pl $(PERLASM_SCHEME) +GENERATE[sparcv9-gf2m.S]=asm/sparcv9-gf2m.pl INCLUDE[sparcv9-gf2m.o]=.. -GENERATE[bn-mips.S]=asm/mips.pl $(PERLASM_SCHEME) +GENERATE[bn-mips.S]=asm/mips.pl INCLUDE[bn-mips.o]=.. -GENERATE[mips-mont.S]=asm/mips-mont.pl $(PERLASM_SCHEME) +GENERATE[mips-mont.S]=asm/mips-mont.pl INCLUDE[mips-mont.o]=.. -GENERATE[s390x-mont.S]=asm/s390x-mont.pl $(PERLASM_SCHEME) -GENERATE[s390x-gf2m.s]=asm/s390x-gf2m.pl $(PERLASM_SCHEME) +GENERATE[s390x-mont.S]=asm/s390x-mont.pl +GENERATE[s390x-gf2m.s]=asm/s390x-gf2m.pl -GENERATE[x86_64-mont.s]=asm/x86_64-mont.pl $(PERLASM_SCHEME) -GENERATE[x86_64-mont5.s]=asm/x86_64-mont5.pl $(PERLASM_SCHEME) -GENERATE[x86_64-gf2m.s]=asm/x86_64-gf2m.pl $(PERLASM_SCHEME) -GENERATE[rsaz-x86_64.s]=asm/rsaz-x86_64.pl $(PERLASM_SCHEME) -GENERATE[rsaz-avx2.s]=asm/rsaz-avx2.pl $(PERLASM_SCHEME) +GENERATE[x86_64-mont.s]=asm/x86_64-mont.pl +GENERATE[x86_64-mont5.s]=asm/x86_64-mont5.pl +GENERATE[x86_64-gf2m.s]=asm/x86_64-gf2m.pl +GENERATE[rsaz-x86_64.s]=asm/rsaz-x86_64.pl +GENERATE[rsaz-avx2.s]=asm/rsaz-avx2.pl +GENERATE[rsaz-avx512.s]=asm/rsaz-avx512.pl GENERATE[bn-ia64.s]=asm/ia64.S -GENERATE[ia64-mont.s]=asm/ia64-mont.pl $(LIB_CFLAGS) $(LIB_CPPFLAGS) +GENERATE[ia64-mont.s]=asm/ia64-mont.pl -GENERATE[parisc-mont.s]=asm/parisc-mont.pl $(PERLASM_SCHEME) +GENERATE[parisc-mont.s]=asm/parisc-mont.pl # ppc - AIX, Linux, MacOS X... -GENERATE[bn-ppc.s]=asm/ppc.pl $(PERLASM_SCHEME) -GENERATE[ppc-mont.s]=asm/ppc-mont.pl $(PERLASM_SCHEME) -GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl $(PERLASM_SCHEME) +GENERATE[bn-ppc.s]=asm/ppc.pl +GENERATE[ppc-mont.s]=asm/ppc-mont.pl +GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl -GENERATE[alpha-mont.S]=asm/alpha-mont.pl $(PERLASM_SCHEME) +GENERATE[alpha-mont.S]=asm/alpha-mont.pl -GENERATE[armv4-mont.S]=asm/armv4-mont.pl $(PERLASM_SCHEME) +GENERATE[armv4-mont.S]=asm/armv4-mont.pl INCLUDE[armv4-mont.o]=.. -GENERATE[armv4-gf2m.S]=asm/armv4-gf2m.pl $(PERLASM_SCHEME) +GENERATE[armv4-gf2m.S]=asm/armv4-gf2m.pl INCLUDE[armv4-gf2m.o]=.. -GENERATE[armv8-mont.S]=asm/armv8-mont.pl $(PERLASM_SCHEME) +GENERATE[armv8-mont.S]=asm/armv8-mont.pl +INCLUDE[armv8-mont.o]=.. diff --git a/crypto/bn/rsa_sup_mul.c b/crypto/bn/rsa_sup_mul.c --- a/crypto/bn/rsa_sup_mul.c +++ b/crypto/bn/rsa_sup_mul.c @@ -5,6 +5,7 @@ #include #include #include +#include "internal/endian.h" #include "internal/numbers.h" #include "internal/constant_time.h" #include "bn_local.h" @@ -12,8 +13,7 @@ # if BN_BYTES == 8 typedef uint64_t limb_t; # if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16 -/* nonstandard; implemented by gcc on 64-bit platforms */ -typedef __uint128_t limb2_t; +typedef uint128_t limb2_t; # define HAVE_LIMB2_T # endif # define LIMB_BIT_SIZE 64 @@ -439,7 +439,7 @@ /* add multiples of the modulus to the value until R divides it cleanly */ for (i = modnum; i > 0; i--, rp--) { - v = _mul_add_limb(rp, mod, modnum, rp[modnum - 1] * ni0, tmp2); + v = _mul_add_limb(rp, mod, modnum, rp[modnum-1] * ni0, tmp2); v = v + carry + rp[-1]; carry |= (v != rp[-1]); carry &= (v <= rp[-1]); @@ -467,48 +467,38 @@ #if LIMB_BYTE_SIZE == 8 static ossl_inline uint64_t be64(uint64_t host) { - const union { - long one; - char little; - } is_endian = { 1 }; - - if (is_endian.little) { - uint64_t big = 0; - - big |= (host & 0xff00000000000000) >> 56; - big |= (host & 0x00ff000000000000) >> 40; - big |= (host & 0x0000ff0000000000) >> 24; - big |= (host & 0x000000ff00000000) >> 8; - big |= (host & 0x00000000ff000000) << 8; - big |= (host & 0x0000000000ff0000) << 24; - big |= (host & 0x000000000000ff00) << 40; - big |= (host & 0x00000000000000ff) << 56; - return big; - } else { + uint64_t big = 0; + DECLARE_IS_ENDIAN; + + if (!IS_LITTLE_ENDIAN) return host; - } + + big |= (host & 0xff00000000000000) >> 56; + big |= (host & 0x00ff000000000000) >> 40; + big |= (host & 0x0000ff0000000000) >> 24; + big |= (host & 0x000000ff00000000) >> 8; + big |= (host & 0x00000000ff000000) << 8; + big |= (host & 0x0000000000ff0000) << 24; + big |= (host & 0x000000000000ff00) << 40; + big |= (host & 0x00000000000000ff) << 56; + return big; } #else /* Not all platforms have htobe32(). */ static ossl_inline uint32_t be32(uint32_t host) { - const union { - long one; - char little; - } is_endian = { 1 }; - - if (is_endian.little) { - uint32_t big = 0; - - big |= (host & 0xff000000) >> 24; - big |= (host & 0x00ff0000) >> 8; - big |= (host & 0x0000ff00) << 8; - big |= (host & 0x000000ff) << 24; - return big; - } else { + uint32_t big = 0; + DECLARE_IS_ENDIAN; + + if (!IS_LITTLE_ENDIAN) return host; - } + + big |= (host & 0xff000000) >> 24; + big |= (host & 0x00ff0000) >> 8; + big |= (host & 0x0000ff00) << 8; + big |= (host & 0x000000ff) << 24; + return big; } #endif @@ -579,7 +569,7 @@ /* modulus size in bytes can be equal to num but after limbs conversion it becomes bigger */ if (num < BN_num_bytes(to_mod)) { - BNerr(BN_F_OSSL_BN_RSA_DO_UNBLIND, ERR_R_PASSED_INVALID_ARGUMENT); + ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT); goto err; } diff --git a/crypto/bn/rsaz_exp.h b/crypto/bn/rsaz_exp.h --- a/crypto/bn/rsaz_exp.h +++ b/crypto/bn/rsaz_exp.h @@ -1,8 +1,8 @@ /* * Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2012, Intel Corporation. All Rights Reserved. + * Copyright (c) 2020, Intel Corporation. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html @@ -37,6 +37,23 @@ const BN_ULONG m_norm[8], BN_ULONG k0, const BN_ULONG RR[8]); + +int ossl_rsaz_avx512ifma_eligible(void); + +int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, + const BN_ULONG *base1, + const BN_ULONG *exponent1, + const BN_ULONG *m1, + const BN_ULONG *RR1, + BN_ULONG k0_1, + BN_ULONG *res2, + const BN_ULONG *base2, + const BN_ULONG *exponent2, + const BN_ULONG *m2, + const BN_ULONG *RR2, + BN_ULONG k0_2, + int factor_size); + static ossl_inline void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a, const BN_ULONG *b, size_t num) diff --git a/crypto/bn/rsaz_exp.c b/crypto/bn/rsaz_exp.c --- a/crypto/bn/rsaz_exp.c +++ b/crypto/bn/rsaz_exp.c @@ -2,7 +2,7 @@ * Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2012, Intel Corporation. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * https://www.openssl.org/source/license.html diff --git a/crypto/bn/rsaz_exp_x2.c b/crypto/bn/rsaz_exp_x2.c new file mode 100644 --- /dev/null +++ b/crypto/bn/rsaz_exp_x2.c @@ -0,0 +1,575 @@ +/* + * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2020, Intel Corporation. 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 + * https://www.openssl.org/source/license.html + * + * + * Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov + * Intel Corporation + * + */ + +#include +#include +#include "rsaz_exp.h" + +#ifndef RSAZ_ENABLED +NON_EMPTY_TRANSLATION_UNIT +#else +# include +# include + +# if defined(__GNUC__) +# define ALIGN64 __attribute__((aligned(64))) +# elif defined(_MSC_VER) +# define ALIGN64 __declspec(align(64)) +# else +# define ALIGN64 +# endif + +# define ALIGN_OF(ptr, boundary) \ + ((unsigned char *)(ptr) + (boundary - (((size_t)(ptr)) & (boundary - 1)))) + +/* Internal radix */ +# define DIGIT_SIZE (52) +/* 52-bit mask */ +# define DIGIT_MASK ((uint64_t)0xFFFFFFFFFFFFF) + +# define BITS2WORD8_SIZE(x) (((x) + 7) >> 3) +# define BITS2WORD64_SIZE(x) (((x) + 63) >> 6) + +static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len); +static ossl_inline void put_digit52(uint8_t *out, int out_len, uint64_t digit); +static void to_words52(BN_ULONG *out, int out_len, const BN_ULONG *in, + int in_bitsize); +static void from_words52(BN_ULONG *bn_out, int out_bitsize, const BN_ULONG *in); +static ossl_inline void set_bit(BN_ULONG *a, int idx); + +/* Number of |digit_size|-bit digits in |bitsize|-bit value */ +static ossl_inline int number_of_digits(int bitsize, int digit_size) +{ + return (bitsize + digit_size - 1) / digit_size; +} + +typedef void (*AMM52)(BN_ULONG *res, const BN_ULONG *base, + const BN_ULONG *exp, const BN_ULONG *m, BN_ULONG k0); +typedef void (*EXP52_x2)(BN_ULONG *res, const BN_ULONG *base, + const BN_ULONG *exp[2], const BN_ULONG *m, + const BN_ULONG *rr, const BN_ULONG k0[2]); + +/* + * For details of the methods declared below please refer to + * crypto/bn/asm/rsaz-avx512.pl + * + * Naming notes: + * amm = Almost Montgomery Multiplication + * ams = Almost Montgomery Squaring + * 52x20 - data represented as array of 20 digits in 52-bit radix + * _x1_/_x2_ - 1 or 2 independent inputs/outputs + * _256 suffix - uses 256-bit (AVX512VL) registers + */ + +/*AMM = Almost Montgomery Multiplication. */ +void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res, const BN_ULONG *base, + const BN_ULONG *exp, const BN_ULONG *m, + BN_ULONG k0); +static void RSAZ_exp52x20_x2_256(BN_ULONG *res, const BN_ULONG *base, + const BN_ULONG *exp[2], const BN_ULONG *m, + const BN_ULONG *rr, const BN_ULONG k0[2]); +void ossl_rsaz_amm52x20_x2_256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); +void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y, + const BN_ULONG *red_table, + int red_table_idx, int tbl_idx); + +/* + * Dual Montgomery modular exponentiation using prime moduli of the + * same bit size, optimized with AVX512 ISA. + * + * Input and output parameters for each exponentiation are independent and + * denoted here by index |i|, i = 1..2. + * + * Input and output are all in regular 2^64 radix. + * + * Each moduli shall be |factor_size| bit size. + * + * NOTE: currently only 2x1024 case is supported. + * + * [out] res|i| - result of modular exponentiation: array of qword values + * in regular (2^64) radix. Size of array shall be enough + * to hold |factor_size| bits. + * [in] base|i| - base + * [in] exp|i| - exponent + * [in] m|i| - moduli + * [in] rr|i| - Montgomery parameter RR = R^2 mod m|i| + * [in] k0_|i| - Montgomery parameter k0 = -1/m|i| mod 2^64 + * [in] factor_size - moduli bit size + * + * \return 0 in case of failure, + * 1 in case of success. + */ +int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, + const BN_ULONG *base1, + const BN_ULONG *exp1, + const BN_ULONG *m1, + const BN_ULONG *rr1, + BN_ULONG k0_1, + BN_ULONG *res2, + const BN_ULONG *base2, + const BN_ULONG *exp2, + const BN_ULONG *m2, + const BN_ULONG *rr2, + BN_ULONG k0_2, + int factor_size) +{ + int ret = 0; + + /* + * Number of word-size (BN_ULONG) digits to store exponent in redundant + * representation. + */ + int exp_digits = number_of_digits(factor_size + 2, DIGIT_SIZE); + int coeff_pow = 4 * (DIGIT_SIZE * exp_digits - factor_size); + BN_ULONG *base1_red, *m1_red, *rr1_red; + BN_ULONG *base2_red, *m2_red, *rr2_red; + BN_ULONG *coeff_red; + BN_ULONG *storage = NULL; + BN_ULONG *storage_aligned = NULL; + BN_ULONG storage_len_bytes = 7 * exp_digits * sizeof(BN_ULONG); + + /* AMM = Almost Montgomery Multiplication */ + AMM52 amm = NULL; + /* Dual (2-exps in parallel) exponentiation */ + EXP52_x2 exp_x2 = NULL; + + const BN_ULONG *exp[2] = {0}; + BN_ULONG k0[2] = {0}; + + /* Only 1024-bit factor size is supported now */ + switch (factor_size) { + case 1024: + amm = ossl_rsaz_amm52x20_x1_256; + exp_x2 = RSAZ_exp52x20_x2_256; + break; + default: + goto err; + } + + storage = (BN_ULONG *)OPENSSL_malloc(storage_len_bytes + 64); + if (storage == NULL) + goto err; + storage_aligned = (BN_ULONG *)ALIGN_OF(storage, 64); + + /* Memory layout for red(undant) representations */ + base1_red = storage_aligned; + base2_red = storage_aligned + 1 * exp_digits; + m1_red = storage_aligned + 2 * exp_digits; + m2_red = storage_aligned + 3 * exp_digits; + rr1_red = storage_aligned + 4 * exp_digits; + rr2_red = storage_aligned + 5 * exp_digits; + coeff_red = storage_aligned + 6 * exp_digits; + + /* Convert base_i, m_i, rr_i, from regular to 52-bit radix */ + to_words52(base1_red, exp_digits, base1, factor_size); + to_words52(base2_red, exp_digits, base2, factor_size); + to_words52(m1_red, exp_digits, m1, factor_size); + to_words52(m2_red, exp_digits, m2, factor_size); + to_words52(rr1_red, exp_digits, rr1, factor_size); + to_words52(rr2_red, exp_digits, rr2, factor_size); + + /* + * Compute target domain Montgomery converters RR' for each modulus + * based on precomputed original domain's RR. + * + * RR -> RR' transformation steps: + * (1) coeff = 2^k + *